instructor-assist.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. console.info("assist");
  2. // 用于记录那个录音图标正在播放
  3. var audioId = null;
  4. var btnMargin = 16;
  5. var instructor_assist = instructor_assist || function (maxHeight, btns, buttons) {
  6. //初始化按钮(编辑器宽度)
  7. var that = this;
  8. this.mainEditor = document.getElementById("outCont"); // .getElementById("displayArea")。Lin
  9. var $me = $(this.mainEditor);
  10. var before = this.mainEditor;
  11. this.editors = {};
  12. $me.parent().find('.button').each(function () {
  13. var $b = $(this),
  14. btnid = $b.attr("id"),
  15. editorid = $b.attr("editor");
  16. if ($("#" + editorid).length > 0) {
  17. that.editors[editorid] = that.editors[editorid] || {
  18. id: editorid,
  19. btns: []
  20. };
  21. that.editors[editorid].btns.push($b.attr("id"));
  22. if ($b.attr("default-show") != "false") {
  23. $b.show();
  24. $me.show();
  25. var width = $me.width() - $b.width() - 31 + "px";
  26. $me.css({
  27. width: width
  28. });
  29. $me.parent().find(".editor").each(function () {
  30. $(this).css({
  31. width: width
  32. })
  33. });
  34. $me.hide()
  35. }
  36. } else {
  37. $b.remove();
  38. }
  39. });
  40. //初始化编辑器的groeHeight
  41. for (var key in that.editors) {
  42. var ed = that.editors[key],
  43. $e = $("#" + ed.id),
  44. e = $e[0];
  45. $e.show();
  46. var _editor = getGrowHeight(ed.id, maxHeight, buttons, parseInt(e.getAttribute("editorType")),true);
  47. _editor.setOnInput(function () {
  48. $("#outCont").html(this.val()); // $("#displayArea").。Lin
  49. });
  50. $e.parent().hide();
  51. for (var i = 0; i < ed.btns.length; i++) {
  52. var btnId = ed.btns[i];
  53. switch (btnId) {
  54. case 'cmnWord': // 'cyy':。Lin
  55. this.initCyy(btnId, key);
  56. break;
  57. case 'spkByHtml': // 'yy':。Lin
  58. this.initRecorder(btnId, key);
  59. break;
  60. case 'wrByHtml': // 'ss':。Lin
  61. ed.editor = this.initWriter(btnId, key);
  62. break;
  63. case 'delByHtml': // 'ss-del':。Lin
  64. this.initWriterDel(btnId, key);
  65. break;
  66. default:
  67. break;
  68. }
  69. }
  70. cursorManager.setCursorListener(_editor.container);
  71. }
  72. var checkFirstEditor = this.checkFirstEditor = function () {
  73. for (var key in that.editors) {
  74. that.switchEditor(key);
  75. break;
  76. }
  77. }
  78. var checkContent = this.checkContent = function () {
  79. if (!that.currentEdit || that.currentEdit.val() == "") {
  80. checkFirstEditor();
  81. $(that.mainEditor).parent().find("[type='button'][default-show!='false']").show();
  82. } else if (that.mainEditor.childNodes.length == 1) {
  83. that.switchEditor(that.currentEdit.name);
  84. }
  85. }
  86. this.mainEditor.addEventListener("DOMSubtreeModified", checkContent);
  87. this.checkContent()
  88. };
  89. instructor_assist.prototype = {
  90. currentEdit: null,
  91. buttons: [],
  92. switchEditor: function (name) {
  93. if (growHeightList)
  94. for (var key in this.editors) {
  95. var ed = this.editors[key],
  96. gh = growHeightList[ed.id];
  97. if (gh) {
  98. if (gh.name == name) {
  99. this.currentEdit = gh;
  100. $(gh.wrapper).css({
  101. display: "inline-block"
  102. })
  103. $.each(ed.btns, function () {
  104. $("#" + this).show();
  105. this.reset && this.reset();
  106. });
  107. } else {
  108. ed.editor && ed.editor.reset();
  109. gh.hide();
  110. $(gh.wrapper).hide();
  111. $.each(ed.btns, function () {
  112. $("#" + this).hide();
  113. this.reset && this.reset();
  114. });
  115. }
  116. }
  117. }
  118. },
  119. saveEditor: function () {
  120. var element = this.mainEditor;
  121. /* 改,改为从 <div id="txtEditor" / <div id="htmlEditor" 里取 -- 优先 "htmlEditor"。Lin
  122. * this.mainEditor = <div id="displayArea"
  123. * 原,不能取得手写的 HTML
  124. var html = element.innerHTML;
  125. */
  126. /* 再改回,又能取到了。Lin
  127. * 期间
  128. * 打断点调试时,$("#htmlEditor").html() 能取到。运行时,取不到(= null)。
  129. * 后发现,chgChk.ss.jsp 的 "同意"、"退回" 按钮调用的是 wd.display.reset(,即 <varServ.ss resize="true"
  130. * addChk.ss.jsp 的是 wd.display.changeFormAction(,即 <varServ.ss subm="true"
  131. * chgChk.ss.jsp 的 "同意"、"退回" 按钮改为 <varServ.ss subm="true" 后,element.innerHTML 又能取到手写的 HTML 了
  132. * 进入审核界面,直接录入文本 "aaa",$("#displayArea").html() = "aaa"。同时,$("#htmlEditor").html()、$("#txtEditor").html() 均为 ""
  133. * 点击 "手写" 按钮并手写,$("#displayArea").html() 和 $("#htmlEditor").html() 均为手写的 "<img ..."。同时,$("#txtEditor").html() 为 ""
  134. * 进入手写后,不能录入文本
  135. * 删除所有手写内容,并点击 "手写" 按钮切换回文本录入时,"aaa" 出现在录入框(保存在哪?)
  136. var html = $("#htmlEditor").html();
  137. if (!html)
  138. html = $("#txtEditor").html();
  139. */
  140. /* 再改,又不能取到了。Lin
  141. * 另,$("#txtEditor").html() 一直为空 -- 不知是否 "常用语" 时才会有值???
  142. var html = element.innerHTML;
  143. */
  144. var html = $("#htmlEditor").html();
  145. if (!html)
  146. html = $("#outCont").html();
  147. var id = element.getAttribute('nrid');
  148. var shid = element.getAttribute('shid'); // 增加,解决 "每次进入办理页都会产生一个 CMS 内容(最后一次仍会垃圾)" 的问题。Lin
  149. console.log("saveEditor() shid: "+ shid);
  150. $.ajax({
  151. type: "POST",
  152. url: "/service?ssServ=savePsCont",
  153. data: {
  154. 'id': id,
  155. 'html': html,
  156. 'shid': shid // 增加,解决 "每次进入办理页都会产生一个 CMS 内容(最后一次仍会垃圾)" 的问题。Lin
  157. },
  158. async: false,
  159. dataType: "json",
  160. /// 再增加,增加错误处理 -- 统一 Ajax 返回标准 -- .ssCode、.ssMsg、.ssData。Lin
  161. success: function (data) {
  162. if (data.ssCode != 0) {
  163. alert(data.ssMsg);
  164. return;
  165. }
  166. },
  167. ///
  168. error: function () {}
  169. });
  170. },
  171. createImage: function (src) {
  172. var img = new Image();
  173. $(img).addClass('item');
  174. img.src = src;
  175. return img;
  176. },
  177. addRecorderImage: function (index) {
  178. var img = createImage('/nr/image/py/yinpin.png');
  179. $(img).addClass('audio');
  180. $(img).data('index', index);
  181. // 新增音频内容到服务器中
  182. addToService(index, img, id);
  183. // 为div添加图标
  184. // addToDisplayArea(img);
  185. // 为录音图标添加事件
  186. addAudioEvent('.audio');
  187. },
  188. reloadText: function (nrid) {
  189. /*回显*/
  190. var this_ = this;
  191. $(this_.editor).load("/service?ssServ=getCommonNrDataFile", {
  192. id: nrid
  193. },
  194. function () {
  195. var audios = document.querySelectorAll('.audio');
  196. $(this_.editor).children('.audio').on('click', function (event) {
  197. showRecord(event); //显示
  198. });
  199. // cursorManager.focus($(editor));
  200. });
  201. },
  202. initRecorder: function (button) {
  203. if ($(button).length == 0)
  204. return;
  205. var this_ = this;
  206. $(button)[0].editMode = "record";
  207. $(button)[0].showBtn = function () {
  208. this.style.display = "";
  209. };
  210. $(button)[0].hideBtn = function () {
  211. this.style.display = "none";
  212. };
  213. this.buttons.push($(button)[0]);
  214. },
  215. initWriterDel: function (button, editorid) {
  216. var $button = $("#" + button),
  217. button = $button[0],
  218. $editor = $("#" + editorid),
  219. editor = $editor[0],
  220. that = this;
  221. editor.addEventListener("click", function () {});
  222. this.mainEditor.addEventListener("DOMSubtreeModified", function () {
  223. if (this.children.length > 0) {
  224. $button.show();
  225. } else {
  226. $button.hide();
  227. }
  228. });
  229. $button.mouseenter(function () {
  230. //获取光标位置
  231. });
  232. $button.click(function () {
  233. that.switchEditor(editor.id);
  234. var childrens = editor.children;
  235. if (childrens.length > 0) {
  236. try {
  237. editor.removeChild(childrens[childrens.length - 1]);
  238. } catch (e) {}
  239. }
  240. });
  241. button.reset = function () {
  242. $button.hide()
  243. };
  244. },
  245. initWriter: function (button, editorid) {
  246. button = "#" + button;
  247. editorid = "#" + editorid;
  248. if ($(button).length == 0 || $(editorid).length == 0)
  249. return;
  250. var this_ = this;
  251. $(button)[0].editMode = "handWrite";
  252. // var canvasField = this.createWriter(null, editor);
  253. var editor = document.querySelector(editorid);
  254. var writer = new instructor_writer(editor, $(button)[0]);
  255. editor.GrowHeight.setOnfocus(function () {
  256. if (!writer.isshow)
  257. writer.show();
  258. });
  259. $(button).click(function (e) {
  260. if (!writer.isshow) {
  261. this_.switchEditor($(this).attr("editor"));
  262. writer.show();
  263. } else {
  264. writer.hide();
  265. if (editor.GrowHeight.container.children.length == 0) {
  266. this_.checkContent();
  267. }
  268. }
  269. });
  270. $(button)[0].showBtn = function () {
  271. this.style.display = "";
  272. $(this).show();
  273. };
  274. $(button)[0].hideBtn = function () {
  275. this.style.display = "none";
  276. writer.hide();
  277. $(this).hide();
  278. };
  279. this.buttons.push($(button)[0]);
  280. return {
  281. reset: function () {
  282. writer.hide();
  283. }
  284. }
  285. },
  286. initCyy: function (button, editorid) {
  287. button = "#" + button;
  288. if ($(button).length == 0)
  289. return;
  290. var this_ = this;
  291. var ul;
  292. $(button)[0].editMode = "planText";
  293. $(button).click(function () {
  294. this_.switchEditor(editorid);
  295. var that = this;
  296. if (this.isshow) {
  297. that.isshow = false;
  298. that.ul.parentNode.removeChild(that.ul);
  299. this_.checkContent();
  300. } else {
  301. $.ajax({
  302. url: '/service?ssServ=gryy_cx',
  303. dataType: 'json',
  304. success: function (data) {
  305. ul = that.ul = document.createElement("div");
  306. ul.className = "popup-div";
  307. var cyy_li = that.cyy_li = document.createElement("div");
  308. cyy_li.className = "scrollbar";
  309. cyy_li.style.cssText = "max-height: 150px;max-width: 400px;min-width: 180px;";
  310. that.ul.appendChild(cyy_li);
  311. var add_li = document.createElement("div");
  312. add_li.style.cssText = "text-align: right;padding-right: 6px;height: 40px;line-height: 30px;font-size: 14px;color: #000;margin-right: 4px;";
  313. add_li.innerHTML = '<div class="icon-add button cursor-click" style="float: right;margin-right: 0px;height:36px;margin-top:2px;background-position-y:center;" onclick="addCyy()"></div>';
  314. that.cyy_li.appendChild(add_li);
  315. if (data.length) {
  316. var editor__ = $(this_.currentEdit.container)[0];
  317. for (var i = 0; i < data.length; i++) {
  318. var item = data[i];
  319. var li = (function (item, index) {
  320. var li = document.createElement("div");
  321. li.className = "popupList";
  322. li.style.cssText = "text-align: right;padding-right: 16px;max-width: 100%;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;";
  323. li.innerHTML = item.yy; // 这里的 .yy,是服务 gryy_cx 的返回结果。Lin
  324. li.onclick = function () {
  325. var str = li.innerHTML.trim();
  326. if (editor__.tagName === "TEXTAREA") {
  327. if (document.selection) {
  328. var sel = document.selection.createRange();
  329. sel.text = str;
  330. } else if (typeof editor__.selectionStart === 'number' && typeof editor__.selectionEnd === 'number') {
  331. var startPos = editor__.selectionStart;
  332. var endPos = editor__.selectionEnd;
  333. var cursorPos = startPos;
  334. var tmpStr = editor__.value;
  335. var newCyy = tmpStr.substring(0, startPos) + str + tmpStr.substring(endPos, tmpStr.length);
  336. getGrowHeight(editor__.id)&&getGrowHeight(editor__.id).val(newCyy);
  337. editor__.value = newCyy;
  338. cursorPos += str.length;
  339. editor__.selectionStart = editor__.selectionEnd = cursorPos;
  340. } else {
  341. editor__.value += str;
  342. }
  343. } else {
  344. cursorManager.focus(editor__);
  345. var range = getRange(),
  346. // span = document.createElement("span"),
  347. txt = document.createTextNode(str);
  348. range.deleteContents();
  349. range.insertNode(txt);
  350. // }
  351. range.setStartAfter(txt);
  352. }
  353. cursorManager.focus(editor__);
  354. ul.style.display = "none";
  355. that.isshow = false;
  356. //修改常用语次数
  357. this_.updateCyySycs(item);
  358. }
  359. return li;
  360. })(item, i);
  361. that.cyy_li.appendChild(li);
  362. }
  363. }
  364. $(button).before(that.ul);
  365. document.body.appendChild(ul);
  366. var $area = $(editor__);
  367. var $cyy = $(button);
  368. (function (ofs_) {
  369. var bodyHeight = $(document.body).height();
  370. var startBottom = bodyHeight - ofs_.top - $cyy.height();
  371. do {
  372. cyy_li.scrollTop = cyy_li.scrollHeight;
  373. $(ul).css({
  374. bottom: startBottom += 1,
  375. right: $(document.body).width() - ofs_.left - $cyy.width()
  376. });
  377. } while ($(ul).offset().top + $(ul).height() + 5 > ofs_.top);
  378. }
  379. ($cyy.offset()));
  380. try{
  381. //伪滚动条
  382. loadScorll($(".scrollbar"));
  383. }catch(e){
  384. console.log(e)
  385. }
  386. that.isshow = true;
  387. },
  388. context: that,
  389. });
  390. }
  391. });
  392. $(button)[0].showBtn = function () {
  393. this.style.display = "";
  394. };
  395. $(button)[0].hideBtn = function () {
  396. this.style.display = "none";
  397. ul && ul.parentNode && ul.parentNode.removeChild(ul);
  398. };
  399. this.buttons.push($(button)[0]);
  400. },
  401. //修改常用语次数
  402. updateCyySycs:function(item){
  403. console.log(item);
  404. $.ajax({
  405. url: '/service?ssServ=p_gryy_sycs',
  406. dataType: 'json',
  407. type:"post",
  408. data:{gryyid:item.gryyid},
  409. success: function (data) {
  410. console.log(data);
  411. }
  412. });
  413. },
  414. destroy: function () {
  415. $(this.mainEditor).parent().remove();
  416. }
  417. }
  418. // 获取焦点
  419. function getRange() {
  420. var selection = window.getSelection ? window.getSelection() :
  421. document.selection;
  422. var range = selection.createRange ? selection.createRange() : selection
  423. .getRangeAt(0);
  424. return range;
  425. }
  426. /*打开录音页面*/
  427. function openRecordWindow(id) {
  428. var url = window.location.protocol + '//' + window.location.host + '/main/editor/record.jsp' + '?id=' + id;
  429. window.open(url, "_blank", "toolbar=yes, location=yes, directories=no, status=no, menubar=yes, scrollbars=yes, resizable=no, copyhistory=yes, width=400, height=400");
  430. }
  431. function openWriteWindow(id) {
  432. var url = window.location.protocol + '//' + window.location.host + '/main/editor/handwritten.jsp' + '?id=' + id;
  433. window.open(url, "_blank", "toolbar=yes, location=yes, directories=no, status=no, menubar=yes, scrollbars=yes, resizable=no, copyhistory=yes, width=700, height=600");
  434. }
  435. getAbsPoint = function (e) {
  436. try {
  437. var x = e.offsetLeft;
  438. var y = e.offsetTop;
  439. var w = e.offsetWidth;
  440. var h = e.offsetHeight;
  441. /**
  442. * OffsetParent为从中计算偏移量的元素。 如果某个元素的父级或此元素层次结构中的其他元素使用相对或绝对定位, 则 OffsetParent
  443. * 将成为当前元素嵌套到的第一个相对或绝对定位元素。如果当前元素以上的任何元素都不是绝对 或相对定位的,则 OffsetParent 将是文档的
  444. * BODY 标记。
  445. *
  446. * obj.offsetTop 指 obj 距离上方或上层控件的位置,整型,单位像素。 obj.offsetLeft 指 obj
  447. * 距离左方或上层控件的位置,整型,单位像素。
  448. *
  449. * offsetTop与offsetLeft均为相对偏移量,但是下面不断地拿offsetParent的偏移量来累加,
  450. * 直至拿到offsetParent为body之后,就没有offsetParent了,此时循环才终止。
  451. * 最终计算出来的x,y为e相对body的绝对坐标。
  452. */
  453. while (e = e.offsetParent) { // 只要对象的offsetParent存在,则继续累加XY,
  454. x += e.offsetLeft;
  455. y += e.offsetTop;
  456. }
  457. return {
  458. "x": x,
  459. "y": y,
  460. "w": w,
  461. "h": h
  462. };
  463. } catch (e) {
  464. if (this.debug)
  465. //alert('方法getAbsPoint执行异常:'+e);
  466. console.log('方法getAbsPoint执行异常:' + e);
  467. }
  468. }
  469. var recursionIframe = function (win) {
  470. if (!win) {
  471. win = this.wins;
  472. }
  473. function getTop(e) {
  474. var offset = e.offsetTop;
  475. if (e.offsetParent != null)
  476. offset += getTop(e.offsetParent);
  477. return offset;
  478. }
  479. function getLeft(e) {
  480. var offset = e.offsetLeft;
  481. if (e.offsetParent != null)
  482. offset += getLeft(e.offsetParent);
  483. return offset;
  484. }
  485. if (win.parent == top && win.parent == win) {
  486. // var xy = this.getAbsPoint(win);
  487. return {
  488. "left": 0,
  489. "top": 0
  490. };
  491. }
  492. var winPar = win.parent; // .opener
  493. var iframeArr = winPar.document.getElementsByTagName('IFRAME');
  494. var targetIframe;
  495. for (var i = 0; i < iframeArr.length; i++) {
  496. var iframeElem = iframeArr[i];
  497. if (iframeElem.contentWindow == win) {
  498. targetIframe = iframeElem;
  499. break;
  500. }
  501. }
  502. // alert(targetIframe==null)
  503. // var xy = this.getAbsPoint(targetIframe);
  504. var xy = {
  505. left: getLeft(targetIframe),
  506. top: getTop(targetIframe)
  507. }
  508. if (winPar.parent != winPar) {
  509. var xy2 = this.recursionIframe(winPar);
  510. xy.left += xy2.left;
  511. xy.top += xy2.top;
  512. }
  513. return xy
  514. }