PageRenderTime 28ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/dnn5/DesktopModules/XsltDb/edit_area_0_8_2/edit_area_loader.js

#
JavaScript | 1066 lines | 808 code | 162 blank | 96 comment | 231 complexity | 8ef6f51ab88bdad6d7ceffff8ea185e9 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0, BSD-3-Clause
  1. /******
  2. *
  3. * EditArea
  4. * Developped by Christophe Dolivet
  5. * Released under LGPL, Apache and BSD licenses (use the one you want)
  6. *
  7. ******/
  8. function EditAreaLoader() {
  9. var t = this;
  10. t.version = "0.8.2";
  11. date = new Date();
  12. t.start_time = date.getTime();
  13. t.win = "loading"; // window loading state
  14. t.error = false; // to know if load is interrrupt
  15. t.baseURL = "";
  16. //t.suffix="";
  17. t.template = "";
  18. t.lang = {}; // array of loaded speech language
  19. t.load_syntax = {}; // array of loaded syntax language for highlight mode
  20. t.syntax = {}; // array of initilized syntax language for highlight mode
  21. t.loadedFiles = [];
  22. t.waiting_loading = {}; // files that must be loaded in order to allow the script to really start
  23. // scripts that must be loaded in the iframe
  24. t.scripts_to_load = ["elements_functions", "resize_area", "reg_syntax"];
  25. t.sub_scripts_to_load = ["edit_area", "manage_area", "edit_area_functions", "keyboard", "search_replace", "highlight", "regexp"];
  26. t.syntax_display_name = { /*syntax_display_name_AUTO-FILL-BY-COMPRESSOR*/
  27. };
  28. t.resize = []; // contain resizing datas
  29. t.hidden = {}; // store datas of the hidden textareas
  30. t.default_settings = {
  31. //id: "src" // id of the textarea to transform
  32. debug: false
  33. , smooth_selection: true
  34. , font_size: "10" // not for IE
  35. , font_family: "monospace" // can be "verdana,monospace". Allow non monospace font but Firefox get smaller tabulation with non monospace fonts. IE doesn't change the tabulation width and Opera doesn't take this option into account...
  36. , start_highlight: false // if start with highlight
  37. , toolbar: "search, go_to_line, fullscreen, |, undo, redo, |, select_font,|, change_smooth_selection, highlight, reset_highlight, word_wrap, |, help"
  38. , begin_toolbar: "" // "new_document, save, load, |"
  39. , end_toolbar: "" // or end_toolbar
  40. , is_multi_files: false // enable the multi file mode (the textarea content is ignored)
  41. , allow_resize: "both" // possible values: "no", "both", "x", "y"
  42. , show_line_colors: false // if the highlight is disabled for the line currently beeing edited (if enabled => heavy CPU use)
  43. , min_width: 400
  44. , min_height: 125
  45. , replace_tab_by_spaces: false
  46. , allow_toggle: true // true or false
  47. , language: "en"
  48. , syntax: ""
  49. , syntax_selection_allow: "basic,brainfuck,c,coldfusion,cpp,css,html,java,js,pas,perl,php,python,ruby,robotstxt,sql,tsql,vb,xml"
  50. , display: "onload" // onload or later
  51. , max_undo: 30
  52. , browsers: "known" // all or known
  53. , plugins: "" // comma separated plugin list
  54. , gecko_spellcheck: false // enable/disable by default the gecko_spellcheck
  55. , fullscreen: false
  56. , is_editable: true
  57. , cursor_position: "begin"
  58. , word_wrap: false // define if the text is wrapped of not in the textarea
  59. , autocompletion: false // NOT IMPLEMENTED
  60. , load_callback: "" // click on load button (function name)
  61. , save_callback: "" // click on save button (function name)
  62. , change_callback: "" // textarea onchange trigger (function name)
  63. , submit_callback: "" // form submited (function name)
  64. , EA_init_callback: "" // EditArea initiliazed (function name)
  65. , EA_delete_callback: "" // EditArea deleted (function name)
  66. , EA_load_callback: "" // EditArea fully loaded and displayed (function name)
  67. , EA_unload_callback: "" // EditArea delete while being displayed (function name)
  68. , EA_toggle_on_callback: "" // EditArea toggled on (function name)
  69. , EA_toggle_off_callback: "" // EditArea toggled off (function name)
  70. , EA_file_switch_on_callback: "" // a new tab is selected (called for the newly selected file)
  71. , EA_file_switch_off_callback: "" // a new tab is selected (called for the previously selected file)
  72. , EA_file_close_callback: "" // close a tab
  73. };
  74. t.advanced_buttons = [
  75. // id, button img, command (it will try to find the translation of "id"), is_file_specific
  76. ['new_document', 'newdocument.gif', 'new_document', false],
  77. ['search', 'search.gif', 'show_search', false],
  78. ['go_to_line', 'go_to_line.gif', 'go_to_line', false],
  79. ['undo', 'undo.gif', 'undo', true],
  80. ['redo', 'redo.gif', 'redo', true],
  81. ['change_smooth_selection', 'smooth_selection.gif', 'change_smooth_selection_mode', true],
  82. ['reset_highlight', 'reset_highlight.gif', 'resync_highlight', true],
  83. ['highlight', 'highlight.gif', 'change_highlight', true],
  84. ['help', 'help.gif', 'show_help', false],
  85. ['save', 'save.gif', 'save', false],
  86. ['load', 'load.gif', 'load', false],
  87. ['cancel', 'cancel.gif', 'cancel', false],
  88. ['fullscreen', 'fullscreen.gif', 'toggle_full_screen', false],
  89. ['word_wrap', 'word_wrap.gif', 'toggle_word_wrap', true],
  90. ['autocompletion', 'autocompletion.gif', 'toggle_autocompletion', true]
  91. ];
  92. // navigator identification
  93. t.set_browser_infos(t);
  94. if (t.isIE >= 6 || t.isGecko || (t.isWebKit && !t.isSafari < 3) || t.isOpera >= 9 || t.isCamino)
  95. t.isValidBrowser = true;
  96. else
  97. t.isValidBrowser = false;
  98. t.set_base_url();
  99. for (var i = 0; i < t.scripts_to_load.length; i++) {
  100. setTimeout("editAreaLoader.load_script('" + t.baseURL + t.scripts_to_load[i] + ".js?r=" + mdo_xsltdb_version() + "');", 1); // let the time to Object editAreaLoader to be created before loading additionnal scripts
  101. t.waiting_loading[t.scripts_to_load[i] + ".js"] = false;
  102. }
  103. t.add_event(window, "load", EditAreaLoader.prototype.window_loaded);
  104. };
  105. EditAreaLoader.prototype = {
  106. has_error: function() {
  107. this.error = true;
  108. // set to empty all EditAreaLoader functions
  109. for (var i in EditAreaLoader.prototype) {
  110. EditAreaLoader.prototype[i] = function() { };
  111. }
  112. },
  113. // add browser informations to the object passed in parameter
  114. set_browser_infos: function(o) {
  115. ua = navigator.userAgent;
  116. // general detection
  117. o.isWebKit = /WebKit/.test(ua);
  118. o.isGecko = !o.isWebKit && /Gecko/.test(ua);
  119. o.isMac = /Mac/.test(ua);
  120. o.isIE = (navigator.appName == "Microsoft Internet Explorer");
  121. if (o.isIE) {
  122. o.isIE = ua.replace(/^.*?MSIE\s+([0-9\.]+).*$/, "$1");
  123. if (o.isIE < 6)
  124. o.has_error();
  125. }
  126. if (o.isOpera = (ua.indexOf('Opera') != -1)) {
  127. o.isOpera = ua.replace(/^.*?Opera.*?([0-9\.]+).*$/i, "$1");
  128. if (o.isOpera < 9)
  129. o.has_error();
  130. o.isIE = false;
  131. }
  132. if (o.isFirefox = (ua.indexOf('Firefox') != -1))
  133. o.isFirefox = ua.replace(/^.*?Firefox.*?([0-9\.]+).*$/i, "$1");
  134. // Firefox clones
  135. if (ua.indexOf('Iceweasel') != -1)
  136. o.isFirefox = ua.replace(/^.*?Iceweasel.*?([0-9\.]+).*$/i, "$1");
  137. if (ua.indexOf('GranParadiso') != -1)
  138. o.isFirefox = ua.replace(/^.*?GranParadiso.*?([0-9\.]+).*$/i, "$1");
  139. if (ua.indexOf('BonEcho') != -1)
  140. o.isFirefox = ua.replace(/^.*?BonEcho.*?([0-9\.]+).*$/i, "$1");
  141. if (ua.indexOf('SeaMonkey') != -1)
  142. o.isFirefox = (ua.replace(/^.*?SeaMonkey.*?([0-9\.]+).*$/i, "$1")) + 1;
  143. if (o.isCamino = (ua.indexOf('Camino') != -1))
  144. o.isCamino = ua.replace(/^.*?Camino.*?([0-9\.]+).*$/i, "$1");
  145. if (o.isSafari = (ua.indexOf('Safari') != -1))
  146. o.isSafari = ua.replace(/^.*?Version\/([0-9]+\.[0-9]+).*$/i, "$1");
  147. if (o.isChrome = (ua.indexOf('Chrome') != -1)) {
  148. o.isChrome = ua.replace(/^.*?Chrome.*?([0-9\.]+).*$/i, "$1");
  149. o.isSafari = false;
  150. }
  151. },
  152. window_loaded: function() {
  153. editAreaLoader.win = "loaded";
  154. // add events on forms
  155. if (document.forms) {
  156. for (var i = 0; i < document.forms.length; i++) {
  157. var form = document.forms[i];
  158. form.edit_area_replaced_submit = null;
  159. try {
  160. form.edit_area_replaced_submit = form.onsubmit;
  161. form.onsubmit = "";
  162. } catch (e) {// Do nothing
  163. }
  164. editAreaLoader.add_event(form, "submit", EditAreaLoader.prototype.submit);
  165. editAreaLoader.add_event(form, "reset", EditAreaLoader.prototype.reset);
  166. }
  167. }
  168. editAreaLoader.add_event(window, "unload", function() { for (var i in editAreas) { editAreaLoader.delete_instance(i); } }); // ini callback
  169. },
  170. // init the checkup of the selection of the IE textarea
  171. init_ie_textarea: function(id) {
  172. var a = document.getElementById(id);
  173. try {
  174. if (a && typeof (a.focused) == "undefined") {
  175. a.focus();
  176. a.focused = true;
  177. a.selectionStart = a.selectionEnd = 0;
  178. get_IE_selection(a);
  179. editAreaLoader.add_event(a, "focus", IE_textarea_focus);
  180. editAreaLoader.add_event(a, "blur", IE_textarea_blur);
  181. }
  182. } catch (ex) { }
  183. },
  184. init: function(settings) {
  185. var t = this, s = settings, i;
  186. if (!s["id"])
  187. t.has_error();
  188. if (t.error)
  189. return;
  190. // if an instance of the editor already exists for this textarea => delete the previous one
  191. if (editAreas[s["id"]])
  192. t.delete_instance(s["id"]);
  193. // init settings
  194. for (i in t.default_settings) {
  195. if (typeof (s[i]) == "undefined")
  196. s[i] = t.default_settings[i];
  197. }
  198. if (s["browsers"] == "known" && t.isValidBrowser == false) {
  199. return;
  200. }
  201. if (s["begin_toolbar"].length > 0)
  202. s["toolbar"] = s["begin_toolbar"] + "," + s["toolbar"];
  203. if (s["end_toolbar"].length > 0)
  204. s["toolbar"] = s["toolbar"] + "," + s["end_toolbar"];
  205. s["tab_toolbar"] = s["toolbar"].replace(/ /g, "").split(",");
  206. s["plugins"] = s["plugins"].replace(/ /g, "").split(",");
  207. for (i = 0; i < s["plugins"].length; i++) {
  208. if (s["plugins"][i].length == 0)
  209. s["plugins"].splice(i, 1);
  210. }
  211. // alert(settings["plugins"].length+": "+ settings["plugins"].join(","));
  212. t.get_template();
  213. t.load_script(t.baseURL + "langs/" + s["language"] + ".js");
  214. if (s["syntax"].length > 0) {
  215. s["syntax"] = s["syntax"].toLowerCase();
  216. t.load_script(t.baseURL + "reg_syntax/" + s["syntax"] + ".js");
  217. }
  218. //alert(this.template);
  219. editAreas[s["id"]] = { "settings": s };
  220. editAreas[s["id"]]["displayed"] = false;
  221. editAreas[s["id"]]["hidden"] = false;
  222. //if(settings["display"]=="onload")
  223. t.start(s["id"]);
  224. },
  225. // delete an instance of an EditArea
  226. delete_instance: function(id) {
  227. var d = document, fs = window.frames, span, iframe;
  228. editAreaLoader.execCommand(id, "EA_delete");
  229. if (fs["frame_" + id] && fs["frame_" + id].editArea) {
  230. if (editAreas[id]["displayed"])
  231. editAreaLoader.toggle(id, "off");
  232. fs["frame_" + id].editArea.execCommand("EA_unload");
  233. }
  234. // remove toggle infos and debug textarea
  235. span = d.getElementById("EditAreaArroundInfos_" + id);
  236. if (span)
  237. span.parentNode.removeChild(span);
  238. // remove the iframe
  239. iframe = d.getElementById("frame_" + id);
  240. if (iframe) {
  241. iframe.parentNode.removeChild(iframe);
  242. //delete iframe;
  243. try {
  244. delete fs["frame_" + id];
  245. } catch (e) {// Do nothing
  246. }
  247. }
  248. delete editAreas[id];
  249. },
  250. start: function(id) {
  251. var t = this, d = document, f, span, father, next, html = '', html_toolbar_content = '', template, content, i;
  252. // check that the window is loaded
  253. if (t.win != "loaded") {
  254. setTimeout("editAreaLoader.start('" + id + "');", 50);
  255. return;
  256. }
  257. // check that all needed scripts are loaded
  258. for (i in t.waiting_loading) {
  259. if (t.waiting_loading[i] != "loaded" && typeof (t.waiting_loading[i]) != "function") {
  260. setTimeout("editAreaLoader.start('" + id + "');", 50);
  261. return;
  262. }
  263. }
  264. // wait until language and syntax files are loaded
  265. if (!t.lang[editAreas[id]["settings"]["language"]] || (editAreas[id]["settings"]["syntax"].length > 0 && !t.load_syntax[editAreas[id]["settings"]["syntax"]])) {
  266. setTimeout("editAreaLoader.start('" + id + "');", 50);
  267. return;
  268. }
  269. // init the regexp for syntax highlight
  270. if (editAreas[id]["settings"]["syntax"].length > 0)
  271. t.init_syntax_regexp();
  272. // display toggle option and debug area
  273. if (!d.getElementById("EditAreaArroundInfos_" + id) && (editAreas[id]["settings"]["debug"] || editAreas[id]["settings"]["allow_toggle"])) {
  274. span = d.createElement("span");
  275. span.id = "EditAreaArroundInfos_" + id;
  276. if (editAreas[id]["settings"]["allow_toggle"]) {
  277. checked = (editAreas[id]["settings"]["display"] == "onload") ? "checked='checked'" : "";
  278. html += "<div id='edit_area_toggle_" + i + "'>";
  279. html += "<input id='edit_area_toggle_checkbox_" + id + "' class='toggle_" + id + "' type='checkbox' onclick='editAreaLoader.toggle(\"" + id + "\");' accesskey='e' " + checked + " />";
  280. html += "<label for='edit_area_toggle_checkbox_" + id + "'>{$toggle}</label></div>";
  281. }
  282. if (editAreas[id]["settings"]["debug"])
  283. html += "<textarea id='edit_area_debug_" + id + "' spellcheck='off' style='z-index: 20; width: 100%; height: 120px;overflow: auto; border: solid black 1px;'></textarea><br />";
  284. html = t.translate(html, editAreas[id]["settings"]["language"]);
  285. span.innerHTML = html;
  286. father = d.getElementById(id).parentNode;
  287. next = d.getElementById(id).nextSibling;
  288. if (next == null)
  289. father.appendChild(span);
  290. else
  291. father.insertBefore(span, next);
  292. }
  293. if (!editAreas[id]["initialized"]) {
  294. t.execCommand(id, "EA_init"); // ini callback
  295. if (editAreas[id]["settings"]["display"] == "later") {
  296. editAreas[id]["initialized"] = true;
  297. return;
  298. }
  299. }
  300. if (t.isIE) { // launch IE selection checkup
  301. t.init_ie_textarea(id);
  302. }
  303. // get toolbar content
  304. var area = editAreas[id];
  305. for (i = 0; i < area["settings"]["tab_toolbar"].length; i++) {
  306. // alert(this.tab_toolbar[i]+"\n"+ this.get_control_html(this.tab_toolbar[i]));
  307. html_toolbar_content += t.get_control_html(area["settings"]["tab_toolbar"][i], area["settings"]["language"]);
  308. }
  309. // translate toolbar text here for chrome 2
  310. html_toolbar_content = t.translate(html_toolbar_content, area["settings"]["language"], "template");
  311. // create javascript import rules for the iframe if the javascript has not been already loaded by the compressor
  312. if (!t.iframe_script) {
  313. t.iframe_script = "";
  314. for (i = 0; i < t.sub_scripts_to_load.length; i++)
  315. t.iframe_script += '<script language="javascript" type="text/javascript" src="' + t.baseURL + t.sub_scripts_to_load[i] + '.js?r=' + mdo_xsltdb_version() + '"></script>';
  316. }
  317. // add plugins scripts if not already loaded by the compressor (but need to load language in all the case)
  318. for (i = 0; i < area["settings"]["plugins"].length; i++) {
  319. //if(typeof(area["settings"]["plugins"][i])=="function") continue;
  320. if (!t.all_plugins_loaded)
  321. t.iframe_script += '<script language="javascript" type="text/javascript" src="' + t.baseURL + 'plugins/' + area["settings"]["plugins"][i] + '/' + area["settings"]["plugins"][i] + '.js?r=' + mdo_xsltdb_version() + '"></script>';
  322. t.iframe_script += '<script language="javascript" type="text/javascript" src="' + t.baseURL + 'plugins/' + area["settings"]["plugins"][i] + '/langs/' + area["settings"]["language"] + '.js?r=' + mdo_xsltdb_version() + '"></script>';
  323. }
  324. // create css link for the iframe if the whole css text has not been already loaded by the compressor
  325. if (!t.iframe_css) {
  326. t.iframe_css = "<link href='" + t.baseURL + "edit_area.css?r=" + mdo_xsltdb_version() + "' rel='stylesheet' type='text/css' />";
  327. }
  328. // create template
  329. template = t.template.replace(/\[__BASEURL__\]/g, t.baseURL);
  330. template = template.replace("[__TOOLBAR__]", html_toolbar_content);
  331. // fill template with good language sentences
  332. template = t.translate(template, area["settings"]["language"], "template");
  333. // add css_code
  334. template = template.replace("[__CSSRULES__]", t.iframe_css);
  335. // add js_code
  336. template = template.replace("[__JSCODE__]", t.iframe_script);
  337. // add version_code
  338. template = template.replace("[__EA_VERSION__]", t.version);
  339. //template=template.replace(/\{\$([^\}]+)\}/gm, this.traduc_template);
  340. //editAreas[area["settings"]["id"]]["template"]= template;
  341. area.textarea = d.getElementById(area["settings"]["id"]);
  342. editAreas[area["settings"]["id"]]["textarea"] = area.textarea;
  343. // if removing previous instances from DOM before (fix from Marcin)
  344. if (typeof (window.frames["frame_" + area["settings"]["id"]]) != 'undefined')
  345. delete window.frames["frame_" + area["settings"]["id"]];
  346. // insert template in the document after the textarea
  347. father = area.textarea.parentNode;
  348. /* var container= document.createElement("div");
  349. container.id= "EditArea_frame_container_"+area["settings"]["id"];
  350. */
  351. content = d.createElement("iframe");
  352. content.name = "frame_" + area["settings"]["id"];
  353. content.id = "frame_" + area["settings"]["id"];
  354. content.style.borderWidth = "0px";
  355. setAttribute(content, "frameBorder", "0"); // IE
  356. content.style.overflow = "hidden";
  357. content.style.display = "none";
  358. next = area.textarea.nextSibling;
  359. if (next == null)
  360. father.appendChild(content);
  361. else
  362. father.insertBefore(content, next);
  363. f = window.frames["frame_" + area["settings"]["id"]];
  364. f.document.open();
  365. f.editAreas = editAreas;
  366. f.area_id = area["settings"]["id"];
  367. f.document.area_id = area["settings"]["id"];
  368. f.document.write(template);
  369. f.document.close();
  370. // frame.editAreaLoader=this;
  371. //editAreas[area["settings"]["id"]]["displayed"]=true;
  372. },
  373. toggle: function(id, toggle_to) {
  374. /* if((editAreas[id]["displayed"]==true && toggle_to!="on") || toggle_to=="off"){
  375. this.toggle_off(id);
  376. }else if((editAreas[id]["displayed"]==false && toggle_to!="off") || toggle_to=="on"){
  377. this.toggle_on(id);
  378. }*/
  379. if (!toggle_to)
  380. toggle_to = (editAreas[id]["displayed"] == true) ? "off" : "on";
  381. if (editAreas[id]["displayed"] == true && toggle_to == "off") {
  382. this.toggle_off(id);
  383. } else if (editAreas[id]["displayed"] == false && toggle_to == "on") {
  384. this.toggle_on(id);
  385. }
  386. return false;
  387. },
  388. // static function
  389. toggle_off: function(id) {
  390. var fs = window.frames, f, t, parNod, nxtSib, selStart, selEnd, scrollTop, scrollLeft;
  391. if (fs["frame_" + id]) {
  392. f = fs["frame_" + id];
  393. t = editAreas[id]["textarea"];
  394. if (f.editArea.fullscreen['isFull'])
  395. f.editArea.toggle_full_screen(false);
  396. editAreas[id]["displayed"] = false;
  397. // set wrap to off to keep same display mode (some browser get problem with this, so it need more complex operation
  398. t.wrap = "off"; // for IE
  399. setAttribute(t, "wrap", "off"); // for Firefox
  400. parNod = t.parentNode;
  401. nxtSib = t.nextSibling;
  402. parNod.removeChild(t);
  403. parNod.insertBefore(t, nxtSib);
  404. // restore values
  405. t.value = f.editArea.textarea.value;
  406. selStart = f.editArea.last_selection["selectionStart"];
  407. selEnd = f.editArea.last_selection["selectionEnd"];
  408. scrollTop = f.document.getElementById("result").scrollTop;
  409. scrollLeft = f.document.getElementById("result").scrollLeft;
  410. document.getElementById("frame_" + id).style.display = 'none';
  411. t.style.display = "inline";
  412. try { // IE will give an error when trying to focus an invisible or disabled textarea
  413. t.focus();
  414. } catch (e) { };
  415. if (this.isIE) {
  416. t.selectionStart = selStart;
  417. t.selectionEnd = selEnd;
  418. t.focused = true;
  419. set_IE_selection(t);
  420. } else {
  421. if (this.isOpera && this.isOpera < 9.6) { // Opera bug when moving selection start and selection end
  422. t.setSelectionRange(0, 0);
  423. }
  424. try {
  425. t.setSelectionRange(selStart, selEnd);
  426. } catch (e) { };
  427. }
  428. t.scrollTop = scrollTop;
  429. t.scrollLeft = scrollLeft;
  430. f.editArea.execCommand("toggle_off");
  431. }
  432. },
  433. // static function
  434. toggle_on: function(id) {
  435. var fs = window.frames, f, t, selStart = 0, selEnd = 0, scrollTop = 0, scrollLeft = 0, curPos, elem;
  436. if (fs["frame_" + id]) {
  437. f = fs["frame_" + id];
  438. t = editAreas[id]["textarea"];
  439. area = f.editArea;
  440. area.textarea.value = t.value;
  441. // store display values;
  442. curPos = editAreas[id]["settings"]["cursor_position"];
  443. if (t.use_last == true) {
  444. selStart = t.last_selectionStart;
  445. selEnd = t.last_selectionEnd;
  446. scrollTop = t.last_scrollTop;
  447. scrollLeft = t.last_scrollLeft;
  448. t.use_last = false;
  449. }
  450. else if (curPos == "auto") {
  451. try {
  452. selStart = t.selectionStart;
  453. selEnd = t.selectionEnd;
  454. scrollTop = t.scrollTop;
  455. scrollLeft = t.scrollLeft;
  456. //alert(scrollTop);
  457. } catch (ex) { }
  458. }
  459. // set to good size
  460. this.set_editarea_size_from_textarea(id, document.getElementById("frame_" + id));
  461. t.style.display = "none";
  462. document.getElementById("frame_" + id).style.display = "inline";
  463. area.execCommand("focus"); // without this focus opera doesn't manage well the iframe body height
  464. // restore display values
  465. editAreas[id]["displayed"] = true;
  466. area.execCommand("update_size");
  467. f.document.getElementById("result").scrollTop = scrollTop;
  468. f.document.getElementById("result").scrollLeft = scrollLeft;
  469. area.area_select(selStart, selEnd - selStart);
  470. area.execCommand("toggle_on");
  471. }
  472. else {
  473. /* if(this.isIE)
  474. get_IE_selection(document.getElementById(id)); */
  475. elem = document.getElementById(id);
  476. elem.last_selectionStart = elem.selectionStart;
  477. elem.last_selectionEnd = elem.selectionEnd;
  478. elem.last_scrollTop = elem.scrollTop;
  479. elem.last_scrollLeft = elem.scrollLeft;
  480. elem.use_last = true;
  481. editAreaLoader.start(id);
  482. }
  483. },
  484. set_editarea_size_from_textarea: function(id, frame) {
  485. var elem, width, height;
  486. elem = document.getElementById(id);
  487. width = Math.max(editAreas[id]["settings"]["min_width"], elem.offsetWidth) + "px";
  488. height = Math.max(editAreas[id]["settings"]["min_height"], elem.offsetHeight) + "px";
  489. if (elem.style.width.indexOf("%") != -1)
  490. width = elem.style.width;
  491. if (elem.style.height.indexOf("%") != -1)
  492. height = elem.style.height;
  493. //alert("h: "+height+" w: "+width);
  494. frame.style.width = width;
  495. frame.style.height = height;
  496. },
  497. set_base_url: function() {
  498. var t = this, elems, i, docBasePath;
  499. if (!this.baseURL) {
  500. elems = document.getElementsByTagName('script');
  501. for (i = 0; i < elems.length; i++) {
  502. if (elems[i].src && elems[i].src.match(/edit_area_[^\\\/]*$/i)) {
  503. var src = unescape(elems[i].src); // use unescape for utf-8 encoded urls
  504. src = src.substring(0, src.lastIndexOf('/'));
  505. this.baseURL = src;
  506. this.file_name = elems[i].src.substr(elems[i].src.lastIndexOf("/") + 1);
  507. break;
  508. }
  509. }
  510. }
  511. docBasePath = document.location.href;
  512. if (docBasePath.indexOf('?') != -1)
  513. docBasePath = docBasePath.substring(0, docBasePath.indexOf('?'));
  514. docBasePath = docBasePath.substring(0, docBasePath.lastIndexOf('/'));
  515. // If not HTTP absolute
  516. if (t.baseURL.indexOf('://') == -1 && t.baseURL.charAt(0) != '/') {
  517. // If site absolute
  518. t.baseURL = docBasePath + "/" + t.baseURL;
  519. }
  520. t.baseURL += "/";
  521. },
  522. get_button_html: function(id, img, exec, isFileSpecific, baseURL) {
  523. var cmd, html;
  524. if (!baseURL)
  525. baseURL = this.baseURL;
  526. cmd = 'editArea.execCommand(\'' + exec + '\')';
  527. html = '<a id="a_' + id + '" href="javascript:' + cmd + '" onclick="' + cmd + ';return false;" onmousedown="return false;" target="_self" fileSpecific="' + (isFileSpecific ? 'yes' : 'no') + '">';
  528. html += '<img id="' + id + '" src="' + baseURL + 'images/' + img + '" title="{$' + id + '}" width="20" height="20" class="editAreaButtonNormal" onmouseover="editArea.switchClass(this,\'editAreaButtonOver\');" onmouseout="editArea.restoreClass(this);" onmousedown="editArea.restoreAndSwitchClass(this,\'editAreaButtonDown\');" /></a>';
  529. return html;
  530. },
  531. get_control_html: function(button_name, lang) {
  532. var t = this, i, but, html, si;
  533. for (i = 0; i < t.advanced_buttons.length; i++) {
  534. but = t.advanced_buttons[i];
  535. if (but[0] == button_name) {
  536. return t.get_button_html(but[0], but[1], but[2], but[3]);
  537. }
  538. }
  539. switch (button_name) {
  540. case "*":
  541. case "return":
  542. return "<br />";
  543. case "|":
  544. case "separator":
  545. return '<img src="' + t.baseURL + 'images/spacer.gif" width="1" height="15" class="editAreaSeparatorLine">';
  546. case "select_font":
  547. html = "<select id='area_font_size' onchange='javascript:editArea.execCommand(\"change_font_size\")' fileSpecific='yes'>";
  548. html += "<option value='-1'>{$font_size}</option>";
  549. si = [8, 9, 10, 11, 12, 14];
  550. for (i = 0; i < si.length; i++) {
  551. html += "<option value='" + si[i] + "'>" + si[i] + " pt</option>";
  552. }
  553. html += "</select>";
  554. return html;
  555. case "syntax_selection":
  556. html = "<select id='syntax_selection' onchange='javascript:editArea.execCommand(\"change_syntax\", this.value)' fileSpecific='yes'>";
  557. html += "<option value='-1'>{$syntax_selection}</option>";
  558. html += "</select>";
  559. return html;
  560. }
  561. return "<span id='tmp_tool_" + button_name + "'>[" + button_name + "]</span>";
  562. },
  563. get_template: function() {
  564. if (this.template == "") {
  565. var xhr_object = null;
  566. if (window.XMLHttpRequest) // Firefox
  567. xhr_object = new XMLHttpRequest();
  568. else if (window.ActiveXObject) // Internet Explorer
  569. xhr_object = new ActiveXObject("Microsoft.XMLHTTP");
  570. else { // XMLHttpRequest not supported
  571. alert("XMLHTTPRequest not supported. EditArea not loaded");
  572. return;
  573. }
  574. xhr_object.open("GET", this.baseURL + "template.html", false);
  575. xhr_object.send(null);
  576. if (xhr_object.readyState == 4)
  577. this.template = xhr_object.responseText;
  578. else
  579. this.has_error();
  580. }
  581. },
  582. // translate text
  583. translate: function(text, lang, mode) {
  584. if (mode == "word")
  585. text = editAreaLoader.get_word_translation(text, lang);
  586. else if (mode = "template") {
  587. editAreaLoader.current_language = lang;
  588. text = text.replace(/\{\$([^\}]+)\}/gm, editAreaLoader.translate_template);
  589. }
  590. return text;
  591. },
  592. translate_template: function() {
  593. return editAreaLoader.get_word_translation(EditAreaLoader.prototype.translate_template.arguments[1], editAreaLoader.current_language);
  594. },
  595. get_word_translation: function(val, lang) {
  596. var i;
  597. for (i in editAreaLoader.lang[lang]) {
  598. if (i == val)
  599. return editAreaLoader.lang[lang][i];
  600. }
  601. return "_" + val;
  602. },
  603. load_script: function(url) {
  604. var t = this, d = document, script, head;
  605. if (t.loadedFiles[url])
  606. return;
  607. //alert("load: "+url);
  608. try {
  609. script = d.createElement("script");
  610. script.type = "text/javascript";
  611. script.src = url;
  612. script.charset = "UTF-8";
  613. d.getElementsByTagName("head")[0].appendChild(script);
  614. } catch (e) {
  615. d.write('<sc' + 'ript language="javascript" type="text/javascript" src="' + url + '" charset="UTF-8"></sc' + 'ript>');
  616. }
  617. t.loadedFiles[url] = true;
  618. },
  619. add_event: function(obj, name, handler) {
  620. try {
  621. if (obj.attachEvent) {
  622. obj.attachEvent("on" + name, handler);
  623. } else {
  624. obj.addEventListener(name, handler, false);
  625. }
  626. } catch (e) { }
  627. },
  628. remove_event: function(obj, name, handler) {
  629. try {
  630. if (obj.detachEvent)
  631. obj.detachEvent("on" + name, handler);
  632. else
  633. obj.removeEventListener(name, handler, false);
  634. } catch (e) { }
  635. },
  636. // reset all the editareas in the form that have been reseted
  637. reset: function(e) {
  638. var formObj, is_child, i, x;
  639. formObj = editAreaLoader.isIE ? window.event.srcElement : e.target;
  640. if (formObj.tagName != 'FORM')
  641. formObj = formObj.form;
  642. for (i in editAreas) {
  643. is_child = false;
  644. for (x = 0; x < formObj.elements.length; x++) {
  645. if (formObj.elements[x].id == i)
  646. is_child = true;
  647. }
  648. if (window.frames["frame_" + i] && is_child && editAreas[i]["displayed"] == true) {
  649. var exec = 'window.frames["frame_' + i + '"].editArea.textarea.value= document.getElementById("' + i + '").value;';
  650. exec += 'window.frames["frame_' + i + '"].editArea.execCommand("focus");';
  651. exec += 'window.frames["frame_' + i + '"].editArea.check_line_selection();';
  652. exec += 'window.frames["frame_' + i + '"].editArea.execCommand("reset");';
  653. window.setTimeout(exec, 10);
  654. }
  655. }
  656. return;
  657. },
  658. // prepare all the textarea replaced by an editarea to be submited
  659. submit: function(e) {
  660. var formObj, is_child, fs = window.frames, i, x;
  661. formObj = editAreaLoader.isIE ? window.event.srcElement : e.target;
  662. if (formObj.tagName != 'FORM')
  663. formObj = formObj.form;
  664. for (i in editAreas) {
  665. is_child = false;
  666. for (x = 0; x < formObj.elements.length; x++) {
  667. if (formObj.elements[x].id == i)
  668. is_child = true;
  669. }
  670. if (is_child) {
  671. if (fs["frame_" + i] && editAreas[i]["displayed"] == true)
  672. document.getElementById(i).value = fs["frame_" + i].editArea.textarea.value;
  673. editAreaLoader.execCommand(i, "EA_submit");
  674. }
  675. }
  676. if (typeof (formObj.edit_area_replaced_submit) == "function") {
  677. res = formObj.edit_area_replaced_submit();
  678. if (res == false) {
  679. if (editAreaLoader.isIE)
  680. return false;
  681. else
  682. e.preventDefault();
  683. }
  684. }
  685. return;
  686. },
  687. // allow to get the value of the editarea
  688. getValue: function(id) {
  689. if (window.frames["frame_" + id] && editAreas[id]["displayed"] == true) {
  690. return window.frames["frame_" + id].editArea.textarea.value;
  691. } else if (elem = document.getElementById(id)) {
  692. return elem.value;
  693. }
  694. return false;
  695. },
  696. // allow to set the value of the editarea
  697. setValue: function(id, new_val) {
  698. var fs = window.frames;
  699. if ((f = fs["frame_" + id]) && editAreas[id]["displayed"] == true) {
  700. f.editArea.textarea.value = new_val;
  701. f.editArea.execCommand("focus");
  702. f.editArea.check_line_selection(false);
  703. f.editArea.execCommand("onchange");
  704. } else if (elem = document.getElementById(id)) {
  705. elem.value = new_val;
  706. }
  707. },
  708. // allow to get infos on the selection: array(start, end)
  709. getSelectionRange: function(id) {
  710. var sel, eA, fs = window.frames;
  711. sel = { "start": 0, "end": 0 };
  712. if (fs["frame_" + id] && editAreas[id]["displayed"] == true) {
  713. eA = fs["frame_" + id].editArea;
  714. sel["start"] = eA.textarea.selectionStart;
  715. sel["end"] = eA.textarea.selectionEnd;
  716. } else if (elem = document.getElementById(id)) {
  717. sel = getSelectionRange(elem);
  718. }
  719. return sel;
  720. },
  721. // allow to set the selection with the given start and end positions
  722. setSelectionRange: function(id, new_start, new_end) {
  723. var fs = window.frames;
  724. if (fs["frame_" + id] && editAreas[id]["displayed"] == true) {
  725. fs["frame_" + id].editArea.area_select(new_start, new_end - new_start);
  726. // make an auto-scroll to the selection
  727. if (!this.isIE) {
  728. fs["frame_" + id].editArea.check_line_selection(false);
  729. fs["frame_" + id].editArea.scroll_to_view();
  730. }
  731. } else if (elem = document.getElementById(id)) {
  732. setSelectionRange(elem, new_start, new_end);
  733. }
  734. },
  735. getSelectedText: function(id) {
  736. var sel = this.getSelectionRange(id);
  737. return this.getValue(id).substring(sel["start"], sel["end"]);
  738. },
  739. setSelectedText: function(id, new_val) {
  740. var fs = window.frames, d = document, sel, text, scrollTop, scrollLeft, new_sel_end;
  741. new_val = new_val.replace(/\r/g, "");
  742. sel = this.getSelectionRange(id);
  743. text = this.getValue(id);
  744. if (fs["frame_" + id] && editAreas[id]["displayed"] == true) {
  745. scrollTop = fs["frame_" + id].document.getElementById("result").scrollTop;
  746. scrollLeft = fs["frame_" + id].document.getElementById("result").scrollLeft;
  747. } else {
  748. scrollTop = d.getElementById(id).scrollTop;
  749. scrollLeft = d.getElementById(id).scrollLeft;
  750. }
  751. text = text.substring(0, sel["start"]) + new_val + text.substring(sel["end"]);
  752. this.setValue(id, text);
  753. new_sel_end = sel["start"] + new_val.length;
  754. this.setSelectionRange(id, sel["start"], new_sel_end);
  755. // fix \r problem for selection length count on IE & Opera
  756. if (new_val != this.getSelectedText(id).replace(/\r/g, "")) {
  757. this.setSelectionRange(id, sel["start"], new_sel_end + new_val.split("\n").length - 1);
  758. }
  759. // restore scrolling position
  760. if (fs["frame_" + id] && editAreas[id]["displayed"] == true) {
  761. fs["frame_" + id].document.getElementById("result").scrollTop = scrollTop;
  762. fs["frame_" + id].document.getElementById("result").scrollLeft = scrollLeft;
  763. fs["frame_" + id].editArea.execCommand("onchange");
  764. } else {
  765. d.getElementById(id).scrollTop = scrollTop;
  766. d.getElementById(id).scrollLeft = scrollLeft;
  767. }
  768. },
  769. insertTags: function(id, open_tag, close_tag) {
  770. var old_sel, new_sel;
  771. old_sel = this.getSelectionRange(id);
  772. text = open_tag + this.getSelectedText(id) + close_tag;
  773. editAreaLoader.setSelectedText(id, text);
  774. new_sel = this.getSelectionRange(id);
  775. if (old_sel["end"] > old_sel["start"]) // if text was selected, cursor at the end
  776. this.setSelectionRange(id, new_sel["end"], new_sel["end"]);
  777. else // cursor in the middle
  778. this.setSelectionRange(id, old_sel["start"] + open_tag.length, old_sel["start"] + open_tag.length);
  779. },
  780. // hide both EditArea and normal textarea
  781. hide: function(id) {
  782. var fs = window.frames, d = document, t = this, scrollTop, scrollLeft, span;
  783. if (d.getElementById(id) && !t.hidden[id]) {
  784. t.hidden[id] = {};
  785. t.hidden[id]["selectionRange"] = t.getSelectionRange(id);
  786. if (d.getElementById(id).style.display != "none") {
  787. t.hidden[id]["scrollTop"] = d.getElementById(id).scrollTop;
  788. t.hidden[id]["scrollLeft"] = d.getElementById(id).scrollLeft;
  789. }
  790. if (fs["frame_" + id]) {
  791. t.hidden[id]["toggle"] = editAreas[id]["displayed"];
  792. if (fs["frame_" + id] && editAreas[id]["displayed"] == true) {
  793. scrollTop = fs["frame_" + id].document.getElementById("result").scrollTop;
  794. scrollLeft = fs["frame_" + id].document.getElementById("result").scrollLeft;
  795. } else {
  796. scrollTop = d.getElementById(id).scrollTop;
  797. scrollLeft = d.getElementById(id).scrollLeft;
  798. }
  799. t.hidden[id]["scrollTop"] = scrollTop;
  800. t.hidden[id]["scrollLeft"] = scrollLeft;
  801. if (editAreas[id]["displayed"] == true)
  802. editAreaLoader.toggle_off(id);
  803. }
  804. // hide toggle button and debug box
  805. span = d.getElementById("EditAreaArroundInfos_" + id);
  806. if (span) {
  807. span.style.display = 'none';
  808. }
  809. // hide textarea
  810. d.getElementById(id).style.display = "none";
  811. }
  812. },
  813. // restore hidden EditArea and normal textarea
  814. show: function(id) {
  815. var fs = window.frames, d = document, t = this, span;
  816. if ((elem = d.getElementById(id)) && t.hidden[id]) {
  817. elem.style.display = "inline";
  818. elem.scrollTop = t.hidden[id]["scrollTop"];
  819. elem.scrollLeft = t.hidden[id]["scrollLeft"];
  820. span = d.getElementById("EditAreaArroundInfos_" + id);
  821. if (span) {
  822. span.style.display = 'inline';
  823. }
  824. if (fs["frame_" + id]) {
  825. // restore toggle button and debug box
  826. // restore textarea
  827. elem.style.display = "inline";
  828. // restore EditArea
  829. if (t.hidden[id]["toggle"] == true)
  830. editAreaLoader.toggle_on(id);
  831. scrollTop = t.hidden[id]["scrollTop"];
  832. scrollLeft = t.hidden[id]["scrollLeft"];
  833. if (fs["frame_" + id] && editAreas[id]["displayed"] == true) {
  834. fs["frame_" + id].document.getElementById("result").scrollTop = scrollTop;
  835. fs["frame_" + id].document.getElementById("result").scrollLeft = scrollLeft;
  836. } else {
  837. elem.scrollTop = scrollTop;
  838. elem.scrollLeft = scrollLeft;
  839. }
  840. }
  841. // restore selection
  842. sel = t.hidden[id]["selectionRange"];
  843. t.setSelectionRange(id, sel["start"], sel["end"]);
  844. delete t.hidden[id];
  845. }
  846. },
  847. // get the current file datas (for multi file editing mode)
  848. getCurrentFile: function(id) {
  849. return this.execCommand(id, 'get_file', this.execCommand(id, 'curr_file'));
  850. },
  851. // get the given file datas (for multi file editing mode)
  852. getFile: function(id, file_id) {
  853. return this.execCommand(id, 'get_file', file_id);
  854. },
  855. // get all the openned files datas (for multi file editing mode)
  856. getAllFiles: function(id) {
  857. return this.execCommand(id, 'get_all_files()');
  858. },
  859. // open a file (for multi file editing mode)
  860. openFile: function(id, file_infos) {
  861. return this.execCommand(id, 'open_file', file_infos);
  862. },
  863. // close the given file (for multi file editing mode)
  864. closeFile: function(id, file_id) {
  865. return this.execCommand(id, 'close_file', file_id);
  866. },
  867. // close the given file (for multi file editing mode)
  868. setFileEditedMode: function(id, file_id, to) {
  869. var reg1, reg2;
  870. reg1 = new RegExp('\\\\', 'g');
  871. reg2 = new RegExp('"', 'g');
  872. return this.execCommand(id, 'set_file_edited_mode("' + file_id.replace(reg1, '\\\\').replace(reg2, '\\"') + '", ' + to + ')');
  873. },
  874. // allow to access to editarea functions and datas (for advanced users only)
  875. execCommand: function(id, cmd, fct_param) {
  876. switch (cmd) {
  877. case "EA_init":
  878. if (editAreas[id]['settings']["EA_init_callback"].length > 0)
  879. eval(editAreas[id]['settings']["EA_init_callback"] + "('" + id + "');");
  880. break;
  881. case "EA_delete":
  882. if (editAreas[id]['settings']["EA_delete_callback"].length > 0)
  883. eval(editAreas[id]['settings']["EA_delete_callback"] + "('" + id + "');");
  884. break;
  885. case "EA_submit":
  886. if (editAreas[id]['settings']["submit_callback"].length > 0)
  887. eval(editAreas[id]['settings']["submit_callback"] + "('" + id + "');");
  888. break;
  889. }
  890. if (window.frames["frame_" + id] && window.frames["frame_" + id].editArea) {
  891. if (fct_param != undefined)
  892. return eval('window.frames["frame_' + id + '"].editArea.' + cmd + '(fct_param);');
  893. else
  894. return eval('window.frames["frame_' + id + '"].editArea.' + cmd + ';');
  895. }
  896. return false;
  897. }
  898. };
  899. var editAreaLoader = new EditAreaLoader();
  900. var editAreas = {};