PageRenderTime 64ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/forum/site_media/js/wym/wymeditor/jquery.wymeditor.js

http://djforum.googlecode.com/
JavaScript | 4606 lines | 3655 code | 347 blank | 604 comment | 245 complexity | df0c1374d0b1ce0c425d4d0e2eb4f41e MD5 | raw file
Possible License(s): GPL-2.0, GPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * WYMeditor : what you see is What You Mean web-based editor
  3. * Copyright (c) 2008 Jean-Francois Hovinne, http://www.wymeditor.org/
  4. * Dual licensed under the MIT (MIT-license.txt)
  5. * and GPL (GPL-license.txt) licenses.
  6. *
  7. * For further information visit:
  8. * http://www.wymeditor.org/
  9. *
  10. * File: jquery.wymeditor.js
  11. *
  12. * Main JS file with core classes and functions.
  13. * See the documentation for more info.
  14. *
  15. * About: authors
  16. *
  17. * Jean-Francois Hovinne (jf.hovinne a-t wymeditor dotorg)
  18. * Volker Mische (vmx a-t gmx dotde)
  19. * Scott Lewis (lewiscot a-t gmail dotcom)
  20. * Bermi Ferrer (wymeditor a-t bermi dotorg)
  21. * Daniel Reszka (d.reszka a-t wymeditor dotorg)
  22. * Jonatan Lundin (jonatan.lundin _at_ gmail.com)
  23. */
  24. /*
  25. Namespace: WYMeditor
  26. Global WYMeditor namespace.
  27. */
  28. if(!WYMeditor) var WYMeditor = {};
  29. jQuery.extend(WYMeditor, {
  30. /*
  31. Constants: Global WYMeditor constants.
  32. VERSION - Defines WYMeditor version.
  33. INSTANCES - An array of loaded WYMeditor.editor instances.
  34. STRINGS - An array of loaded WYMeditor language pairs/values.
  35. SKINS - An array of loaded WYMeditor skins.
  36. NAME - The "name" attribute.
  37. INDEX - A string replaced by the instance index.
  38. WYM_INDEX - A string used to get/set the instance index.
  39. BASE_PATH - A string replaced by WYMeditor's base path.
  40. SKIN_PATH - A string replaced by WYMeditor's skin path.
  41. WYM_PATH - A string replaced by WYMeditor's main JS file path.
  42. SKINS_DEFAULT_PATH - The skins default base path.
  43. SKINS_DEFAULT_CSS - The skins default CSS file.
  44. LANG_DEFAULT_PATH - The language files default path.
  45. IFRAME_BASE_PATH - A string replaced by the designmode iframe's base path.
  46. IFRAME_DEFAULT - The iframe's default base path.
  47. JQUERY_PATH - A string replaced by the computed jQuery path.
  48. DIRECTION - A string replaced by the text direction (rtl or ltr).
  49. LOGO - A string replaced by WYMeditor logo.
  50. TOOLS - A string replaced by the toolbar's HTML.
  51. TOOLS_ITEMS - A string replaced by the toolbar items.
  52. TOOL_NAME - A string replaced by a toolbar item's name.
  53. TOOL_TITLE - A string replaced by a toolbar item's title.
  54. TOOL_CLASS - A string replaced by a toolbar item's class.
  55. CLASSES - A string replaced by the classes panel's HTML.
  56. CLASSES_ITEMS - A string replaced by the classes items.
  57. CLASS_NAME - A string replaced by a class item's name.
  58. CLASS_TITLE - A string replaced by a class item's title.
  59. CONTAINERS - A string replaced by the containers panel's HTML.
  60. CONTAINERS_ITEMS - A string replaced by the containers items.
  61. CONTAINER_NAME - A string replaced by a container item's name.
  62. CONTAINER_TITLE - A string replaced by a container item's title.
  63. CONTAINER_CLASS - A string replaced by a container item's class.
  64. HTML - A string replaced by the HTML view panel's HTML.
  65. IFRAME - A string replaced by the designmode iframe.
  66. STATUS - A string replaced by the status panel's HTML.
  67. DIALOG_TITLE - A string replaced by a dialog's title.
  68. DIALOG_BODY - A string replaced by a dialog's HTML body.
  69. BODY - The BODY element.
  70. STRING - The "string" type.
  71. BODY,DIV,P,
  72. H1,H2,H3,H4,H5,H6,
  73. PRE,BLOCKQUOTE,
  74. A,BR,IMG,
  75. TABLE,TD,TH,
  76. UL,OL,LI - HTML elements string representation.
  77. CLASS,HREF,SRC,
  78. TITLE,ALT - HTML attributes string representation.
  79. DIALOG_LINK - A link dialog type.
  80. DIALOG_IMAGE - An image dialog type.
  81. DIALOG_TABLE - A table dialog type.
  82. DIALOG_PASTE - A 'Paste from Word' dialog type.
  83. BOLD - Command: (un)set selection to <strong>.
  84. ITALIC - Command: (un)set selection to <em>.
  85. CREATE_LINK - Command: open the link dialog or (un)set link.
  86. INSERT_IMAGE - Command: open the image dialog or insert an image.
  87. INSERT_TABLE - Command: open the table dialog.
  88. PASTE - Command: open the paste dialog.
  89. INDENT - Command: nest a list item.
  90. OUTDENT - Command: unnest a list item.
  91. TOGGLE_HTML - Command: display/hide the HTML view.
  92. FORMAT_BLOCK - Command: set a block element to another type.
  93. PREVIEW - Command: open the preview dialog.
  94. UNLINK - Command: unset a link.
  95. INSERT_UNORDEREDLIST- Command: insert an unordered list.
  96. INSERT_ORDEREDLIST - Command: insert an ordered list.
  97. MAIN_CONTAINERS - An array of the main HTML containers used in WYMeditor.
  98. BLOCKS - An array of the HTML block elements.
  99. KEY - Standard key codes.
  100. NODE - Node types.
  101. */
  102. VERSION : "0.5-a2",
  103. INSTANCES : [],
  104. STRINGS : [],
  105. SKINS : [],
  106. NAME : "name",
  107. INDEX : "{Wym_Index}",
  108. WYM_INDEX : "wym_index",
  109. BASE_PATH : "{Wym_Base_Path}",
  110. CSS_PATH : "{Wym_Css_Path}",
  111. WYM_PATH : "{Wym_Wym_Path}",
  112. SKINS_DEFAULT_PATH : "skins/",
  113. SKINS_DEFAULT_CSS : "skin.css",
  114. SKINS_DEFAULT_JS : "skin.js",
  115. LANG_DEFAULT_PATH : "lang/",
  116. IFRAME_BASE_PATH : "{Wym_Iframe_Base_Path}",
  117. IFRAME_DEFAULT : "iframe/default/",
  118. JQUERY_PATH : "{Wym_Jquery_Path}",
  119. DIRECTION : "{Wym_Direction}",
  120. LOGO : "{Wym_Logo}",
  121. TOOLS : "{Wym_Tools}",
  122. TOOLS_ITEMS : "{Wym_Tools_Items}",
  123. TOOL_NAME : "{Wym_Tool_Name}",
  124. TOOL_TITLE : "{Wym_Tool_Title}",
  125. TOOL_CLASS : "{Wym_Tool_Class}",
  126. CLASSES : "{Wym_Classes}",
  127. CLASSES_ITEMS : "{Wym_Classes_Items}",
  128. CLASS_NAME : "{Wym_Class_Name}",
  129. CLASS_TITLE : "{Wym_Class_Title}",
  130. CONTAINERS : "{Wym_Containers}",
  131. CONTAINERS_ITEMS : "{Wym_Containers_Items}",
  132. CONTAINER_NAME : "{Wym_Container_Name}",
  133. CONTAINER_TITLE : "{Wym_Containers_Title}",
  134. CONTAINER_CLASS : "{Wym_Container_Class}",
  135. HTML : "{Wym_Html}",
  136. IFRAME : "{Wym_Iframe}",
  137. STATUS : "{Wym_Status}",
  138. DIALOG_TITLE : "{Wym_Dialog_Title}",
  139. DIALOG_BODY : "{Wym_Dialog_Body}",
  140. STRING : "string",
  141. BODY : "body",
  142. DIV : "div",
  143. P : "p",
  144. H1 : "h1",
  145. H2 : "h2",
  146. H3 : "h3",
  147. H4 : "h4",
  148. H5 : "h5",
  149. H6 : "h6",
  150. PRE : "pre",
  151. BLOCKQUOTE : "blockquote",
  152. A : "a",
  153. BR : "br",
  154. IMG : "img",
  155. TABLE : "table",
  156. TD : "td",
  157. TH : "th",
  158. UL : "ul",
  159. OL : "ol",
  160. LI : "li",
  161. CLASS : "class",
  162. HREF : "href",
  163. SRC : "src",
  164. TITLE : "title",
  165. ALT : "alt",
  166. DIALOG_LINK : "Link",
  167. DIALOG_IMAGE : "Image",
  168. DIALOG_TABLE : "Table",
  169. DIALOG_PASTE : "Paste_From_Word",
  170. BOLD : "Bold",
  171. ITALIC : "Italic",
  172. CREATE_LINK : "CreateLink",
  173. INSERT_IMAGE : "InsertImage",
  174. INSERT_TABLE : "InsertTable",
  175. INSERT_HTML : "InsertHTML",
  176. PASTE : "Paste",
  177. INDENT : "Indent",
  178. OUTDENT : "Outdent",
  179. TOGGLE_HTML : "ToggleHtml",
  180. FORMAT_BLOCK : "FormatBlock",
  181. PREVIEW : "Preview",
  182. UNLINK : "Unlink",
  183. INSERT_UNORDEREDLIST : "InsertUnorderedList",
  184. INSERT_ORDEREDLIST : "InsertOrderedList",
  185. MAIN_CONTAINERS : new Array("p","h1","h2","h3","h4","h5","h6","pre","blockquote"),
  186. BLOCKS : new Array("address", "blockquote", "div", "dl",
  187. "fieldset", "form", "h1", "h2", "h3", "h4", "h5", "h6", "hr",
  188. "noscript", "ol", "p", "pre", "table", "ul", "dd", "dt",
  189. "li", "tbody", "td", "tfoot", "th", "thead", "tr"),
  190. KEY : {
  191. BACKSPACE: 8,
  192. ENTER: 13,
  193. END: 35,
  194. HOME: 36,
  195. LEFT: 37,
  196. UP: 38,
  197. RIGHT: 39,
  198. DOWN: 40,
  199. CURSOR: new Array(37, 38, 39, 40),
  200. DELETE: 46
  201. },
  202. NODE : {
  203. ELEMENT: 1,
  204. ATTRIBUTE: 2,
  205. TEXT: 3
  206. },
  207. /*
  208. Class: WYMeditor.editor
  209. WYMeditor editor main class, instanciated for each editor occurrence.
  210. */
  211. editor : function(elem, options) {
  212. /*
  213. Constructor: WYMeditor.editor
  214. Initializes main values (index, elements, paths, ...)
  215. and call WYMeditor.editor.init which initializes the editor.
  216. Parameters:
  217. elem - The HTML element to be replaced by the editor.
  218. options - The hash of options.
  219. Returns:
  220. Nothing.
  221. See Also:
  222. <WYMeditor.editor.init>
  223. */
  224. //store the instance in the INSTANCES array and store the index
  225. this._index = WYMeditor.INSTANCES.push(this) - 1;
  226. //store the element replaced by the editor
  227. this._element = elem;
  228. //store the options
  229. this._options = options;
  230. //store the element's inner value
  231. this._html = jQuery(elem).val();
  232. //store the HTML option, if any
  233. if(this._options.html) this._html = this._options.html;
  234. //get or compute the base path (where the main JS file is located)
  235. this._options.basePath = this._options.basePath
  236. || this.computeBasePath();
  237. //get or set the skin path (where the skin files are located)
  238. this._options.skinPath = this._options.skinPath
  239. || this._options.basePath + WYMeditor.SKINS_DEFAULT_PATH
  240. + this._options.skin + '/';
  241. //get or compute the main JS file location
  242. this._options.wymPath = this._options.wymPath
  243. || this.computeWymPath();
  244. //get or set the language files path
  245. this._options.langPath = this._options.langPath
  246. || this._options.basePath + WYMeditor.LANG_DEFAULT_PATH;
  247. //get or set the designmode iframe's base path
  248. this._options.iframeBasePath = this._options.iframeBasePath
  249. || this._options.basePath + WYMeditor.IFRAME_DEFAULT;
  250. //get or compute the jQuery JS file location
  251. this._options.jQueryPath = this._options.jQueryPath
  252. || this.computeJqueryPath();
  253. //initialize the editor instance
  254. this.init();
  255. }
  256. });
  257. /********** JQUERY **********/
  258. /**
  259. * Replace an HTML element by WYMeditor
  260. *
  261. * @example jQuery(".wymeditor").wymeditor(
  262. * {
  263. *
  264. * }
  265. * );
  266. * @desc Example description here
  267. *
  268. * @name WYMeditor
  269. * @description WYMeditor is a web-based WYSIWYM XHTML editor
  270. * @param Hash hash A hash of parameters
  271. * @option Integer iExample Description here
  272. * @option String sExample Description here
  273. *
  274. * @type jQuery
  275. * @cat Plugins/WYMeditor
  276. * @author Jean-Francois Hovinne
  277. */
  278. jQuery.fn.wymeditor = function(options) {
  279. options = jQuery.extend({
  280. html: "",
  281. basePath: false,
  282. skinPath: false,
  283. wymPath: false,
  284. iframeBasePath: false,
  285. jQueryPath: false,
  286. styles: false,
  287. stylesheet: false,
  288. skin: "default",
  289. initSkin: true,
  290. loadSkin: true,
  291. lang: "en",
  292. direction: "ltr",
  293. boxHtml: "<div class='wym_box'>"
  294. + "<div class='wym_area_top'>"
  295. + WYMeditor.TOOLS
  296. + "</div>"
  297. + "<div class='wym_area_left'></div>"
  298. + "<div class='wym_area_right'>"
  299. + WYMeditor.CONTAINERS
  300. + WYMeditor.CLASSES
  301. + "</div>"
  302. + "<div class='wym_area_main'>"
  303. + WYMeditor.HTML
  304. + WYMeditor.IFRAME
  305. + WYMeditor.STATUS
  306. + "</div>"
  307. + "<div class='wym_area_bottom'>"
  308. + WYMeditor.LOGO
  309. + "</div>"
  310. + "</div>",
  311. logoHtml: "<a class='wym_wymeditor_link' "
  312. + "href='http://www.wymeditor.org/'>WYMeditor</a>",
  313. iframeHtml:"<div class='wym_iframe wym_section'>"
  314. + "<iframe "
  315. + "src='"
  316. + WYMeditor.IFRAME_BASE_PATH
  317. + "wymiframe.html' "
  318. + "onload='this.contentWindow.parent.WYMeditor.INSTANCES["
  319. + WYMeditor.INDEX + "].initIframe(this)'"
  320. + "></iframe>"
  321. + "</div>",
  322. editorStyles: [],
  323. toolsHtml: "<div class='wym_tools wym_section'>"
  324. + "<h2>{Tools}</h2>"
  325. + "<ul>"
  326. + WYMeditor.TOOLS_ITEMS
  327. + "</ul>"
  328. + "</div>",
  329. toolsItemHtml: "<li class='"
  330. + WYMeditor.TOOL_CLASS
  331. + "'><a href='#' name='"
  332. + WYMeditor.TOOL_NAME
  333. + "' title='"
  334. + WYMeditor.TOOL_TITLE
  335. + "'>"
  336. + WYMeditor.TOOL_TITLE
  337. + "</a></li>",
  338. toolsItems: [
  339. {'name': 'Bold', 'title': 'Strong', 'css': 'wym_tools_strong'},
  340. {'name': 'Italic', 'title': 'Emphasis', 'css': 'wym_tools_emphasis'},
  341. {'name': 'Superscript', 'title': 'Superscript',
  342. 'css': 'wym_tools_superscript'},
  343. {'name': 'Subscript', 'title': 'Subscript',
  344. 'css': 'wym_tools_subscript'},
  345. {'name': 'InsertOrderedList', 'title': 'Ordered_List',
  346. 'css': 'wym_tools_ordered_list'},
  347. {'name': 'InsertUnorderedList', 'title': 'Unordered_List',
  348. 'css': 'wym_tools_unordered_list'},
  349. {'name': 'Indent', 'title': 'Indent', 'css': 'wym_tools_indent'},
  350. {'name': 'Outdent', 'title': 'Outdent', 'css': 'wym_tools_outdent'},
  351. {'name': 'Undo', 'title': 'Undo', 'css': 'wym_tools_undo'},
  352. {'name': 'Redo', 'title': 'Redo', 'css': 'wym_tools_redo'},
  353. {'name': 'CreateLink', 'title': 'Link', 'css': 'wym_tools_link'},
  354. {'name': 'Unlink', 'title': 'Unlink', 'css': 'wym_tools_unlink'},
  355. {'name': 'InsertImage', 'title': 'Image', 'css': 'wym_tools_image'},
  356. {'name': 'InsertTable', 'title': 'Table', 'css': 'wym_tools_table'},
  357. {'name': 'Paste', 'title': 'Paste_From_Word',
  358. 'css': 'wym_tools_paste'},
  359. {'name': 'ToggleHtml', 'title': 'HTML', 'css': 'wym_tools_html'},
  360. {'name': 'Preview', 'title': 'Preview', 'css': 'wym_tools_preview'}
  361. ],
  362. containersHtml: "<div class='wym_containers wym_section'>"
  363. + "<h2>{Containers}</h2>"
  364. + "<ul>"
  365. + WYMeditor.CONTAINERS_ITEMS
  366. + "</ul>"
  367. + "</div>",
  368. containersItemHtml:"<li class='"
  369. + WYMeditor.CONTAINER_CLASS
  370. + "'>"
  371. + "<a href='#' name='"
  372. + WYMeditor.CONTAINER_NAME
  373. + "'>"
  374. + WYMeditor.CONTAINER_TITLE
  375. + "</a></li>",
  376. containersItems: [
  377. {'name': 'P', 'title': 'Paragraph', 'css': 'wym_containers_p'},
  378. {'name': 'H1', 'title': 'Heading_1', 'css': 'wym_containers_h1'},
  379. {'name': 'H2', 'title': 'Heading_2', 'css': 'wym_containers_h2'},
  380. {'name': 'H3', 'title': 'Heading_3', 'css': 'wym_containers_h3'},
  381. {'name': 'H4', 'title': 'Heading_4', 'css': 'wym_containers_h4'},
  382. {'name': 'H5', 'title': 'Heading_5', 'css': 'wym_containers_h5'},
  383. {'name': 'H6', 'title': 'Heading_6', 'css': 'wym_containers_h6'},
  384. {'name': 'PRE', 'title': 'Preformatted', 'css': 'wym_containers_pre'},
  385. {'name': 'BLOCKQUOTE', 'title': 'Blockquote',
  386. 'css': 'wym_containers_blockquote'},
  387. {'name': 'TH', 'title': 'Table_Header', 'css': 'wym_containers_th'}
  388. ],
  389. classesHtml: "<div class='wym_classes wym_section'>"
  390. + "<h2>{Classes}</h2><ul>"
  391. + WYMeditor.CLASSES_ITEMS
  392. + "</ul></div>",
  393. classesItemHtml: "<li><a href='#' name='"
  394. + WYMeditor.CLASS_NAME
  395. + "'>"
  396. + WYMeditor.CLASS_TITLE
  397. + "</a></li>",
  398. classesItems: [],
  399. statusHtml: "<div class='wym_status wym_section'>"
  400. + "<h2>{Status}</h2>"
  401. + "</div>",
  402. htmlHtml: "<div class='wym_html wym_section'>"
  403. + "<h2>{Source_Code}</h2>"
  404. + "<textarea class='wym_html_val'></textarea>"
  405. + "</div>",
  406. boxSelector: ".wym_box",
  407. toolsSelector: ".wym_tools",
  408. toolsListSelector: " ul",
  409. containersSelector:".wym_containers",
  410. classesSelector: ".wym_classes",
  411. htmlSelector: ".wym_html",
  412. iframeSelector: ".wym_iframe iframe",
  413. iframeBodySelector:".wym_iframe",
  414. statusSelector: ".wym_status",
  415. toolSelector: ".wym_tools a",
  416. containerSelector: ".wym_containers a",
  417. classSelector: ".wym_classes a",
  418. htmlValSelector: ".wym_html_val",
  419. hrefSelector: ".wym_href",
  420. srcSelector: ".wym_src",
  421. titleSelector: ".wym_title",
  422. altSelector: ".wym_alt",
  423. textSelector: ".wym_text",
  424. rowsSelector: ".wym_rows",
  425. colsSelector: ".wym_cols",
  426. captionSelector: ".wym_caption",
  427. summarySelector: ".wym_summary",
  428. submitSelector: ".wym_submit",
  429. cancelSelector: ".wym_cancel",
  430. previewSelector: "",
  431. dialogTypeSelector: ".wym_dialog_type",
  432. dialogLinkSelector: ".wym_dialog_link",
  433. dialogImageSelector: ".wym_dialog_image",
  434. dialogTableSelector: ".wym_dialog_table",
  435. dialogPasteSelector: ".wym_dialog_paste",
  436. dialogPreviewSelector: ".wym_dialog_preview",
  437. updateSelector: ".wymupdate",
  438. updateEvent: "click",
  439. dialogFeatures: "menubar=no,titlebar=no,toolbar=no,resizable=no"
  440. + ",width=560,height=300,top=0,left=0",
  441. dialogHtml: "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'"
  442. + " 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>"
  443. + "<html dir='"
  444. + WYMeditor.DIRECTION
  445. + "'><head>"
  446. + "<link rel='stylesheet' type='text/css' media='screen'"
  447. + " href='"
  448. + WYMeditor.CSS_PATH
  449. + "' />"
  450. + "<title>"
  451. + WYMeditor.DIALOG_TITLE
  452. + "</title>"
  453. + "<script type='text/javascript'"
  454. + " src='"
  455. + WYMeditor.JQUERY_PATH
  456. + "'></script>"
  457. + "<script type='text/javascript'"
  458. + " src='"
  459. + WYMeditor.WYM_PATH
  460. + "'></script>"
  461. + "</head>"
  462. + WYMeditor.DIALOG_BODY
  463. + "</html>",
  464. dialogLinkHtml: "<body class='wym_dialog wym_dialog_link'"
  465. + " onload='WYMeditor.INIT_DIALOG(" + WYMeditor.INDEX + ")'"
  466. + ">"
  467. + "<form>"
  468. + "<fieldset>"
  469. + "<input type='hidden' class='wym_dialog_type' value='"
  470. + WYMeditor.DIALOG_LINK
  471. + "' />"
  472. + "<legend>{Link}</legend>"
  473. + "<div class='row'>"
  474. + "<label>{URL}</label>"
  475. + "<input type='text' class='wym_href' value='' size='40' />"
  476. + "</div>"
  477. + "<div class='row'>"
  478. + "<label>{Title}</label>"
  479. + "<input type='text' class='wym_title' value='' size='40' />"
  480. + "</div>"
  481. + "<div class='row row-indent'>"
  482. + "<input class='wym_submit' type='button'"
  483. + " value='{Submit}' />"
  484. + "<input class='wym_cancel' type='button'"
  485. + "value='{Cancel}' />"
  486. + "</div>"
  487. + "</fieldset>"
  488. + "</form>"
  489. + "</body>",
  490. dialogImageHtml: "<body class='wym_dialog wym_dialog_image'"
  491. + " onload='WYMeditor.INIT_DIALOG(" + WYMeditor.INDEX + ")'"
  492. + ">"
  493. + "<form>"
  494. + "<fieldset>"
  495. + "<input type='hidden' class='wym_dialog_type' value='"
  496. + WYMeditor.DIALOG_IMAGE
  497. + "' />"
  498. + "<legend>{Image}</legend>"
  499. + "<div class='row'>"
  500. + "<label>{URL}</label>"
  501. + "<input type='text' class='wym_src' value='' size='40' />"
  502. + "</div>"
  503. + "<div class='row'>"
  504. + "<label>{Alternative_Text}</label>"
  505. + "<input type='text' class='wym_alt' value='' size='40' />"
  506. + "</div>"
  507. + "<div class='row'>"
  508. + "<label>{Title}</label>"
  509. + "<input type='text' class='wym_title' value='' size='40' />"
  510. + "</div>"
  511. + "<div class='row row-indent'>"
  512. + "<input class='wym_submit' type='button'"
  513. + " value='{Submit}' />"
  514. + "<input class='wym_cancel' type='button'"
  515. + "value='{Cancel}' />"
  516. + "</div>"
  517. + "</fieldset>"
  518. + "</form>"
  519. + "</body>",
  520. dialogTableHtml: "<body class='wym_dialog wym_dialog_table'"
  521. + " onload='WYMeditor.INIT_DIALOG(" + WYMeditor.INDEX + ")'"
  522. + ">"
  523. + "<form>"
  524. + "<fieldset>"
  525. + "<input type='hidden' class='wym_dialog_type' value='"
  526. + WYMeditor.DIALOG_TABLE
  527. + "' />"
  528. + "<legend>{Table}</legend>"
  529. + "<div class='row'>"
  530. + "<label>{Caption}</label>"
  531. + "<input type='text' class='wym_caption' value='' size='40' />"
  532. + "</div>"
  533. + "<div class='row'>"
  534. + "<label>{Summary}</label>"
  535. + "<input type='text' class='wym_summary' value='' size='40' />"
  536. + "</div>"
  537. + "<div class='row'>"
  538. + "<label>{Number_Of_Rows}</label>"
  539. + "<input type='text' class='wym_rows' value='3' size='3' />"
  540. + "</div>"
  541. + "<div class='row'>"
  542. + "<label>{Number_Of_Cols}</label>"
  543. + "<input type='text' class='wym_cols' value='2' size='3' />"
  544. + "</div>"
  545. + "<div class='row row-indent'>"
  546. + "<input class='wym_submit' type='button'"
  547. + " value='{Submit}' />"
  548. + "<input class='wym_cancel' type='button'"
  549. + "value='{Cancel}' />"
  550. + "</div>"
  551. + "</fieldset>"
  552. + "</form>"
  553. + "</body>",
  554. dialogPasteHtml: "<body class='wym_dialog wym_dialog_paste'"
  555. + " onload='WYMeditor.INIT_DIALOG(" + WYMeditor.INDEX + ")'"
  556. + ">"
  557. + "<form>"
  558. + "<input type='hidden' class='wym_dialog_type' value='"
  559. + WYMeditor.DIALOG_PASTE
  560. + "' />"
  561. + "<fieldset>"
  562. + "<legend>{Paste_From_Word}</legend>"
  563. + "<div class='row'>"
  564. + "<textarea class='wym_text' rows='10' cols='50'></textarea>"
  565. + "</div>"
  566. + "<div class='row'>"
  567. + "<input class='wym_submit' type='button'"
  568. + " value='{Submit}' />"
  569. + "<input class='wym_cancel' type='button'"
  570. + "value='{Cancel}' />"
  571. + "</div>"
  572. + "</fieldset>"
  573. + "</form>"
  574. + "</body>",
  575. dialogPreviewHtml: "<body class='wym_dialog wym_dialog_preview'"
  576. + " onload='WYMeditor.INIT_DIALOG(" + WYMeditor.INDEX + ")'"
  577. + "></body>",
  578. dialogStyles: [],
  579. stringDelimiterLeft: "{",
  580. stringDelimiterRight:"}",
  581. preInit: null,
  582. preBind: null,
  583. postInit: null,
  584. preInitDialog: null,
  585. postInitDialog: null
  586. }, options);
  587. return this.each(function() {
  588. new WYMeditor.editor(jQuery(this),options);
  589. });
  590. };
  591. /* @name extend
  592. * @description Returns the WYMeditor instance based on its index
  593. */
  594. jQuery.extend({
  595. wymeditors: function(i) {
  596. return (WYMeditor.INSTANCES[i]);
  597. }
  598. });
  599. /********** WYMeditor **********/
  600. /* @name Wymeditor
  601. * @description WYMeditor class
  602. */
  603. /* @name init
  604. * @description Initializes a WYMeditor instance
  605. */
  606. WYMeditor.editor.prototype.init = function() {
  607. //load subclass - browser specific
  608. //unsupported browsers: do nothing
  609. if (jQuery.browser.msie) {
  610. var WymClass = new WYMeditor.WymClassExplorer(this);
  611. }
  612. else if (jQuery.browser.mozilla) {
  613. var WymClass = new WYMeditor.WymClassMozilla(this);
  614. }
  615. else if (jQuery.browser.opera) {
  616. var WymClass = new WYMeditor.WymClassOpera(this);
  617. }
  618. else if (jQuery.browser.safari) {
  619. var WymClass = new WYMeditor.WymClassSafari(this);
  620. }
  621. if(WymClass) {
  622. if(jQuery.isFunction(this._options.preInit)) this._options.preInit(this);
  623. var SaxListener = new WYMeditor.XhtmlSaxListener();
  624. jQuery.extend(SaxListener, WymClass);
  625. this.parser = new WYMeditor.XhtmlParser(SaxListener);
  626. if(this._options.styles || this._options.stylesheet){
  627. this.configureEditorUsingRawCss();
  628. }
  629. this.helper = new WYMeditor.XmlHelper();
  630. //extend the Wymeditor object
  631. //don't use jQuery.extend since 1.1.4
  632. //jQuery.extend(this, WymClass);
  633. for (var prop in WymClass) { this[prop] = WymClass[prop]; }
  634. //load wymbox
  635. this._box = jQuery(this._element).hide().after(this._options.boxHtml).next();
  636. //store the instance index in the wymbox element
  637. jQuery(this._box).data(WYMeditor.WYM_INDEX, this._index);
  638. var h = WYMeditor.Helper;
  639. //construct the iframe
  640. var iframeHtml = this._options.iframeHtml;
  641. iframeHtml = h.replaceAll(iframeHtml, WYMeditor.INDEX, this._index);
  642. iframeHtml = h.replaceAll(iframeHtml, WYMeditor.IFRAME_BASE_PATH, this._options.iframeBasePath);
  643. //construct wymbox
  644. var boxHtml = jQuery(this._box).html();
  645. boxHtml = h.replaceAll(boxHtml, WYMeditor.LOGO, this._options.logoHtml);
  646. boxHtml = h.replaceAll(boxHtml, WYMeditor.TOOLS, this._options.toolsHtml);
  647. boxHtml = h.replaceAll(boxHtml, WYMeditor.CONTAINERS,this._options.containersHtml);
  648. boxHtml = h.replaceAll(boxHtml, WYMeditor.CLASSES, this._options.classesHtml);
  649. boxHtml = h.replaceAll(boxHtml, WYMeditor.HTML, this._options.htmlHtml);
  650. boxHtml = h.replaceAll(boxHtml, WYMeditor.IFRAME, iframeHtml);
  651. boxHtml = h.replaceAll(boxHtml, WYMeditor.STATUS, this._options.statusHtml);
  652. //construct tools list
  653. var aTools = eval(this._options.toolsItems);
  654. var sTools = "";
  655. for(var i = 0; i < aTools.length; i++) {
  656. var oTool = aTools[i];
  657. if(oTool.name && oTool.title)
  658. var sTool = this._options.toolsItemHtml;
  659. var sTool = h.replaceAll(sTool, WYMeditor.TOOL_NAME, oTool.name);
  660. sTool = h.replaceAll(sTool, WYMeditor.TOOL_TITLE, this._options.stringDelimiterLeft
  661. + oTool.title
  662. + this._options.stringDelimiterRight);
  663. sTool = h.replaceAll(sTool, WYMeditor.TOOL_CLASS, oTool.css);
  664. sTools += sTool;
  665. }
  666. boxHtml = h.replaceAll(boxHtml, WYMeditor.TOOLS_ITEMS, sTools);
  667. //construct classes list
  668. var aClasses = eval(this._options.classesItems);
  669. var sClasses = "";
  670. for(var i = 0; i < aClasses.length; i++) {
  671. var oClass = aClasses[i];
  672. if(oClass.name && oClass.title)
  673. var sClass = this._options.classesItemHtml;
  674. sClass = h.replaceAll(sClass, WYMeditor.CLASS_NAME, oClass.name);
  675. sClass = h.replaceAll(sClass, WYMeditor.CLASS_TITLE, oClass.title);
  676. sClasses += sClass;
  677. }
  678. boxHtml = h.replaceAll(boxHtml, WYMeditor.CLASSES_ITEMS, sClasses);
  679. //construct containers list
  680. var aContainers = eval(this._options.containersItems);
  681. var sContainers = "";
  682. for(var i = 0; i < aContainers.length; i++) {
  683. var oContainer = aContainers[i];
  684. if(oContainer.name && oContainer.title)
  685. var sContainer = this._options.containersItemHtml;
  686. sContainer = h.replaceAll(sContainer, WYMeditor.CONTAINER_NAME, oContainer.name);
  687. sContainer = h.replaceAll(sContainer, WYMeditor.CONTAINER_TITLE,
  688. this._options.stringDelimiterLeft
  689. + oContainer.title
  690. + this._options.stringDelimiterRight);
  691. sContainer = h.replaceAll(sContainer, WYMeditor.CONTAINER_CLASS, oContainer.css);
  692. sContainers += sContainer;
  693. }
  694. boxHtml = h.replaceAll(boxHtml, WYMeditor.CONTAINERS_ITEMS, sContainers);
  695. //l10n
  696. boxHtml = this.replaceStrings(boxHtml);
  697. //load html in wymbox
  698. jQuery(this._box).html(boxHtml);
  699. //hide the html value
  700. jQuery(this._box).find(this._options.htmlSelector).hide();
  701. //enable the skin
  702. this.loadSkin();
  703. }
  704. };
  705. WYMeditor.editor.prototype.bindEvents = function() {
  706. //copy the instance
  707. var wym = this;
  708. //handle click event on tools buttons
  709. jQuery(this._box).find(this._options.toolSelector).click(function() {
  710. wym.exec(jQuery(this).attr(WYMeditor.NAME));
  711. return(false);
  712. });
  713. //handle click event on containers buttons
  714. jQuery(this._box).find(this._options.containerSelector).click(function() {
  715. wym.container(jQuery(this).attr(WYMeditor.NAME));
  716. return(false);
  717. });
  718. //handle keyup event on html value: set the editor value
  719. jQuery(this._box).find(this._options.htmlValSelector).keyup(function() {
  720. jQuery(wym._doc.body).html(jQuery(this).val());
  721. });
  722. //handle click event on classes buttons
  723. jQuery(this._box).find(this._options.classSelector).click(function() {
  724. var aClasses = eval(wym._options.classesItems);
  725. var sName = jQuery(this).attr(WYMeditor.NAME);
  726. var oClass = WYMeditor.Helper.findByName(aClasses, sName);
  727. if(oClass) {
  728. var jqexpr = oClass.expr;
  729. wym.toggleClass(sName, jqexpr);
  730. }
  731. return(false);
  732. });
  733. //handle event on update element
  734. jQuery(this._options.updateSelector)
  735. .bind(this._options.updateEvent, function() {
  736. wym.update();
  737. });
  738. };
  739. WYMeditor.editor.prototype.ready = function() {
  740. return(this._doc != null);
  741. };
  742. /********** METHODS **********/
  743. /* @name box
  744. * @description Returns the WYMeditor container
  745. */
  746. WYMeditor.editor.prototype.box = function() {
  747. return(this._box);
  748. };
  749. /* @name html
  750. * @description Get/Set the html value
  751. */
  752. WYMeditor.editor.prototype.html = function(html) {
  753. if(typeof html === 'string') jQuery(this._doc.body).html(html);
  754. else return(jQuery(this._doc.body).html());
  755. };
  756. /* @name xhtml
  757. * @description Cleans up the HTML
  758. */
  759. WYMeditor.editor.prototype.xhtml = function() {
  760. return this.parser.parse(this.html());
  761. };
  762. /* @name exec
  763. * @description Executes a button command
  764. */
  765. WYMeditor.editor.prototype.exec = function(cmd) {
  766. //base function for execCommand
  767. //open a dialog or exec
  768. switch(cmd) {
  769. case WYMeditor.CREATE_LINK:
  770. var container = this.container();
  771. if(container || this._selected_image) this.dialog(WYMeditor.DIALOG_LINK);
  772. break;
  773. case WYMeditor.INSERT_IMAGE:
  774. this.dialog(WYMeditor.DIALOG_IMAGE);
  775. break;
  776. case WYMeditor.INSERT_TABLE:
  777. this.dialog(WYMeditor.DIALOG_TABLE);
  778. break;
  779. case WYMeditor.PASTE:
  780. this.dialog(WYMeditor.DIALOG_PASTE);
  781. break;
  782. case WYMeditor.TOGGLE_HTML:
  783. this.update();
  784. this.toggleHtml();
  785. break;
  786. case WYMeditor.PREVIEW:
  787. this.dialog(WYMeditor.PREVIEW);
  788. break;
  789. default:
  790. this._exec(cmd);
  791. break;
  792. }
  793. };
  794. /* @name container
  795. * @description Get/Set the selected container
  796. */
  797. WYMeditor.editor.prototype.container = function(sType) {
  798. if(sType) {
  799. var container = null;
  800. if(sType.toLowerCase() == WYMeditor.TH) {
  801. container = this.container();
  802. //find the TD or TH container
  803. switch(container.tagName.toLowerCase()) {
  804. case WYMeditor.TD: case WYMeditor.TH:
  805. break;
  806. default:
  807. var aTypes = new Array(WYMeditor.TD,WYMeditor.TH);
  808. container = this.findUp(this.container(), aTypes);
  809. break;
  810. }
  811. //if it exists, switch
  812. if(container!=null) {
  813. sType = (container.tagName.toLowerCase() == WYMeditor.TD)? WYMeditor.TH: WYMeditor.TD;
  814. this.switchTo(container,sType);
  815. this.update();
  816. }
  817. } else {
  818. //set the container type
  819. var aTypes=new Array(WYMeditor.P,WYMeditor.H1,WYMeditor.H2,WYMeditor.H3,WYMeditor.H4,WYMeditor.H5,
  820. WYMeditor.H6,WYMeditor.PRE,WYMeditor.BLOCKQUOTE);
  821. container = this.findUp(this.container(), aTypes);
  822. if(container) {
  823. var newNode = null;
  824. //blockquotes must contain a block level element
  825. if(sType.toLowerCase() == WYMeditor.BLOCKQUOTE) {
  826. var blockquote = this.findUp(this.container(), WYMeditor.BLOCKQUOTE);
  827. if(blockquote == null) {
  828. newNode = this._doc.createElement(sType);
  829. container.parentNode.insertBefore(newNode,container);
  830. newNode.appendChild(container);
  831. this.setFocusToNode(newNode.firstChild);
  832. } else {
  833. var nodes = blockquote.childNodes;
  834. var lgt = nodes.length;
  835. var firstNode = null;
  836. if(lgt > 0) firstNode = nodes.item(0);
  837. for(var x=0; x<lgt; x++) {
  838. blockquote.parentNode.insertBefore(nodes.item(0),blockquote);
  839. }
  840. blockquote.parentNode.removeChild(blockquote);
  841. if(firstNode) this.setFocusToNode(firstNode);
  842. }
  843. }
  844. else this.switchTo(container,sType);
  845. this.update();
  846. }
  847. }
  848. }
  849. else return(this.selected());
  850. };
  851. /* @name toggleClass
  852. * @description Toggles class on selected element, or one of its parents
  853. */
  854. WYMeditor.editor.prototype.toggleClass = function(sClass, jqexpr) {
  855. var container = (this._selected_image
  856. ? this._selected_image
  857. : jQuery(this.selected()));
  858. container = jQuery(container).parentsOrSelf(jqexpr);
  859. jQuery(container).toggleClass(sClass);
  860. if(!jQuery(container).attr(WYMeditor.CLASS)) jQuery(container).removeAttr(this._class);
  861. };
  862. /* @name findUp
  863. * @description Returns the first parent or self container, based on its type
  864. */
  865. WYMeditor.editor.prototype.findUp = function(node, filter) {
  866. //filter is a string or an array of strings
  867. if(node) {
  868. var tagname = node.tagName.toLowerCase();
  869. if(typeof(filter) == WYMeditor.STRING) {
  870. while(tagname != filter && tagname != WYMeditor.BODY) {
  871. node = node.parentNode;
  872. tagname = node.tagName.toLowerCase();
  873. }
  874. } else {
  875. var bFound = false;
  876. while(!bFound && tagname != WYMeditor.BODY) {
  877. for(var i = 0; i < filter.length; i++) {
  878. if(tagname == filter[i]) {
  879. bFound = true;
  880. break;
  881. }
  882. }
  883. if(!bFound) {
  884. node = node.parentNode;
  885. tagname = node.tagName.toLowerCase();
  886. }
  887. }
  888. }
  889. if(tagname != WYMeditor.BODY) return(node);
  890. else return(null);
  891. } else return(null);
  892. };
  893. /* @name switchTo
  894. * @description Switch the node's type
  895. */
  896. WYMeditor.editor.prototype.switchTo = function(node,sType) {
  897. var newNode = this._doc.createElement(sType);
  898. var html = jQuery(node).html();
  899. node.parentNode.replaceChild(newNode,node);
  900. jQuery(newNode).html(html);
  901. this.setFocusToNode(newNode);
  902. };
  903. WYMeditor.editor.prototype.replaceStrings = function(sVal) {
  904. //check if the language file has already been loaded
  905. //if not, get it via a synchronous ajax call
  906. if(!WYMeditor.STRINGS[this._options.lang])
  907. eval(jQuery.ajax({url:this._options.langPath
  908. + this._options.lang + '.js', async:false}).responseText);
  909. //replace all the strings in sVal and return it
  910. for (var key in WYMeditor.STRINGS[this._options.lang]) {
  911. sVal = WYMeditor.Helper.replaceAll(sVal, this._options.stringDelimiterLeft + key
  912. + this._options.stringDelimiterRight,
  913. WYMeditor.STRINGS[this._options.lang][key]);
  914. };
  915. return(sVal);
  916. };
  917. WYMeditor.editor.prototype.encloseString = function(sVal) {
  918. return(this._options.stringDelimiterLeft
  919. + sVal
  920. + this._options.stringDelimiterRight);
  921. };
  922. /* @name status
  923. * @description Prints a status message
  924. */
  925. WYMeditor.editor.prototype.status = function(sMessage) {
  926. //print status message
  927. jQuery(this._box).find(this._options.statusSelector).html(sMessage);
  928. };
  929. /* @name update
  930. * @description Updates the element and textarea values
  931. */
  932. WYMeditor.editor.prototype.update = function() {
  933. var html = this.xhtml();
  934. jQuery(this._element).val(html);
  935. jQuery(this._box).find(this._options.htmlValSelector).val(html);
  936. };
  937. /* @name dialog
  938. * @description Opens a dialog box
  939. */
  940. WYMeditor.editor.prototype.dialog = function(sType) {
  941. var wDialog = window.open(
  942. '',
  943. 'dialog',
  944. this._wym._options.dialogFeatures);
  945. if(wDialog) {
  946. var sBodyHtml = "";
  947. switch(sType) {
  948. case(WYMeditor.DIALOG_LINK):
  949. sBodyHtml = this._options.dialogLinkHtml;
  950. break;
  951. case(WYMeditor.DIALOG_IMAGE):
  952. sBodyHtml = this._options.dialogImageHtml;
  953. break;
  954. case(WYMeditor.DIALOG_TABLE):
  955. sBodyHtml = this._options.dialogTableHtml;
  956. break;
  957. case(WYMeditor.DIALOG_PASTE):
  958. sBodyHtml = this._options.dialogPasteHtml;
  959. break;
  960. case(WYMeditor.PREVIEW):
  961. sBodyHtml = this._options.dialogPreviewHtml;
  962. break;
  963. }
  964. var h = WYMeditor.Helper;
  965. //construct the dialog
  966. var dialogHtml = this._options.dialogHtml;
  967. dialogHtml = h.replaceAll(dialogHtml, WYMeditor.BASE_PATH, this._options.basePath);
  968. dialogHtml = h.replaceAll(dialogHtml, WYMeditor.DIRECTION, this._options.direction);
  969. dialogHtml = h.replaceAll(dialogHtml, WYMeditor.CSS_PATH, this._options.skinPath + WYMeditor.SKINS_DEFAULT_CSS);
  970. dialogHtml = h.replaceAll(dialogHtml, WYMeditor.WYM_PATH, this._options.wymPath);
  971. dialogHtml = h.replaceAll(dialogHtml, WYMeditor.JQUERY_PATH, this._options.jQueryPath);
  972. dialogHtml = h.replaceAll(dialogHtml, WYMeditor.DIALOG_TITLE, this.encloseString(sType));
  973. dialogHtml = h.replaceAll(dialogHtml, WYMeditor.DIALOG_BODY, sBodyHtml);
  974. dialogHtml = h.replaceAll(dialogHtml, WYMeditor.INDEX, this._index);
  975. dialogHtml = this.replaceStrings(dialogHtml);
  976. var doc = wDialog.document;
  977. doc.write(dialogHtml);
  978. doc.close();
  979. }
  980. };
  981. /* @name toggleHtml
  982. * @description Shows/Hides the HTML
  983. */
  984. WYMeditor.editor.prototype.toggleHtml = function() {
  985. jQuery(this._box).find(this._options.htmlSelector).toggle();
  986. };
  987. WYMeditor.editor.prototype.uniqueStamp = function() {
  988. var now = new Date();
  989. return("wym-" + now.getTime());
  990. };
  991. WYMeditor.editor.prototype.paste = function(sData) {
  992. var sTmp;
  993. var container = this.selected();
  994. //split the data, using double newlines as the separator
  995. var aP = sData.split(this._newLine + this._newLine);
  996. var rExp = new RegExp(this._newLine, "g");
  997. //add a P for each item
  998. if(container && container.tagName.toLowerCase() != WYMeditor.BODY) {
  999. for(x = aP.length - 1; x >= 0; x--) {
  1000. sTmp = aP[x];
  1001. //simple newlines are replaced by a break
  1002. sTmp = sTmp.replace(rExp, "<br />");
  1003. jQuery(container).after("<p>" + sTmp + "</p>");
  1004. }
  1005. } else {
  1006. for(x = 0; x < aP.length; x++) {
  1007. sTmp = aP[x];
  1008. //simple newlines are replaced by a break
  1009. sTmp = sTmp.replace(rExp, "<br />");
  1010. jQuery(this._doc.body).append("<p>" + sTmp + "</p>");
  1011. }
  1012. }
  1013. };
  1014. WYMeditor.editor.prototype.insert = function(html) {
  1015. // Do we have a selection?
  1016. if (this._iframe.contentWindow.getSelection().focusNode != null) {
  1017. // Overwrite selection with provided html
  1018. this._exec( WYMeditor.INSERT_HTML, html);
  1019. } else {
  1020. // Fall back to the internal paste function if there's no selection
  1021. this.paste(html)
  1022. }
  1023. };
  1024. WYMeditor.editor.prototype.addCssRules = function(doc, aCss) {
  1025. var styles = doc.styleSheets[0];
  1026. if(styles) {
  1027. for(var i = 0; i < aCss.length; i++) {
  1028. var oCss = aCss[i];
  1029. if(oCss.name && oCss.css) this.addCssRule(styles, oCss);
  1030. }
  1031. }
  1032. };
  1033. /********** CONFIGURATION **********/
  1034. WYMeditor.editor.prototype.computeBasePath = function() {
  1035. return jQuery(jQuery.grep(jQuery('script'), function(s){
  1036. return (s.src && s.src.match(/jquery\.wymeditor(\.pack){0,1}\.js(\?.*)?$/ ))
  1037. })).attr('src').replace(/jquery\.wymeditor(\.pack){0,1}\.js(\?.*)?$/, '');
  1038. };
  1039. WYMeditor.editor.prototype.computeWymPath = function() {
  1040. return jQuery(jQuery.grep(jQuery('script'), function(s){
  1041. return (s.src && s.src.match(/jquery\.wymeditor(\.pack){0,1}\.js(\?.*)?$/ ))
  1042. })).attr('src');
  1043. };
  1044. WYMeditor.editor.prototype.computeJqueryPath = function() {
  1045. return jQuery(jQuery.grep(jQuery('script'), function(s){
  1046. return (s.src && s.src.match(/jquery(-(.*)){0,1}(\.pack){0,1}\.js(\?.*)?$/ ))
  1047. })).attr('src');
  1048. };
  1049. WYMeditor.editor.prototype.computeCssPath = function() {
  1050. return jQuery(jQuery.grep(jQuery('link'), function(s){
  1051. return (s.href && s.href.match(/wymeditor\/skins\/(.*)screen\.css(\?.*)?$/ ))
  1052. })).attr('href');
  1053. };
  1054. WYMeditor.editor.prototype.configureEditorUsingRawCss = function() {
  1055. var CssParser = new WYMeditor.WymCssParser();
  1056. if(this._options.stylesheet){
  1057. CssParser.parse(jQuery.ajax({url: this._options.stylesheet,async:false}).responseText);
  1058. }else{
  1059. CssParser.parse(this._options.styles, false);
  1060. }
  1061. if(this._options.classesItems.length == 0) {
  1062. this._options.classesItems = CssParser.css_settings.classesItems;
  1063. }
  1064. if(this._options.editorStyles.length == 0) {
  1065. this._options.editorStyles = CssParser.css_settings.editorStyles;
  1066. }
  1067. if(this._options.dialogStyles.length == 0) {
  1068. this._options.dialogStyles = CssParser.css_settings.dialogStyles;
  1069. }
  1070. };
  1071. /********** EVENTS **********/
  1072. WYMeditor.editor.prototype.listen = function() {
  1073. //don't use jQuery.find() on the iframe body
  1074. //because of MSIE + jQuery + expando issue (#JQ1143)
  1075. //jQuery(this._doc.body).find("*").bind("mouseup", this.mouseup);
  1076. jQuery(this._doc.body).bind("mousedown", this.mousedown);
  1077. var images = this._doc.body.getElementsByTagName("img");
  1078. for(var i=0; i < images.length; i++) {
  1079. jQuery(images[i]).bind("mousedown", this.mousedown);
  1080. }
  1081. };
  1082. WYMeditor.editor.prototype.mousedown = function(evt) {
  1083. var wym = WYMeditor.INSTANCES[this.ownerDocument.title];
  1084. wym._selected_image = (this.tagName.toLowerCase() == WYMeditor.IMG) ? this : null;
  1085. evt.stopPropagation();
  1086. };
  1087. /********** SKINS **********/
  1088. /*
  1089. * Function: WYMeditor.loadCss
  1090. * Loads a stylesheet in the document.
  1091. *
  1092. * Parameters:
  1093. * href - The CSS path.
  1094. */
  1095. WYMeditor.loadCss = function(href) {
  1096. var link = document.createElement('link');
  1097. link.rel = 'stylesheet';
  1098. link.href = href;
  1099. var head = jQuery('head').get(0);
  1100. head.appendChild(link);
  1101. };
  1102. /*
  1103. * Function: WYMeditor.editor.loadSkin
  1104. * Loads the skin CSS and initialization script (if needed).
  1105. */
  1106. WYMeditor.editor.prototype.loadSkin = function() {
  1107. //does the user want to automatically load the CSS (default: yes)?
  1108. //we also test if it hasn't been already loaded by another instance
  1109. //see below for a better (second) test
  1110. if(this._options.loadSkin && !WYMeditor.SKINS[this._options.skin]) {
  1111. //check if it hasn't been already loaded
  1112. //so we don't load it more than once
  1113. //(we check the existing <link> elements)
  1114. var found = false;
  1115. var rExp = new RegExp(this._options.skin
  1116. + '\/' + WYMeditor.SKINS_DEFAULT_CSS + '$');
  1117. jQuery('link').each( function() {
  1118. if(this.href.match(rExp)) found = true;
  1119. });
  1120. //load it, using the skin path
  1121. if(!found) WYMeditor.loadCss( this._options.skinPath
  1122. + WYMeditor.SKINS_DEFAULT_CSS );
  1123. }
  1124. //put the classname (ex. wym_skin_default) on wym_box
  1125. jQuery(this._box).addClass( "wym_skin_" + this._options.skin );
  1126. //does the user want to use some JS to initialize the skin (default: yes)?
  1127. //also check if it hasn't already been loaded by another instance
  1128. if(this._options.initSkin && !WYMeditor.SKINS[this._options.skin]) {
  1129. eval(jQuery.ajax({url:this._options.skinPath
  1130. + WYMeditor.SKINS_DEFAULT_JS, async:false}).responseText);
  1131. }
  1132. //init the skin, if needed
  1133. if(WYMeditor.SKINS[this._options.skin]
  1134. && WYMeditor.SKINS[this._options.skin].init)
  1135. WYMeditor.SKINS[this._options.skin].init(this);
  1136. };
  1137. /********** DIALOGS **********/
  1138. WYMeditor.INIT_DIALOG = function(index) {
  1139. var wym = window.opener.WYMeditor.INSTANCES[index];
  1140. var doc = window.document;
  1141. var selected = wym.selected();
  1142. var dialogType = jQuery(wym._options.dialogTypeSelector).val();
  1143. var sStamp = wym.uniqueStamp();
  1144. switch(dialogType) {
  1145. case WYMeditor.DIALOG_LINK:
  1146. //ensure that we select the link to populate the fields
  1147. if(selected && selected.tagName && selected.tagName.toLowerCase != WYMeditor.A)
  1148. selected = jQuery(selected).parentsOrSelf(WYMeditor.A);
  1149. //fix MSIE selection if link image has been clicked
  1150. if(!selected && wym._selected_image)
  1151. selected = jQuery(wym._selected_image).parentsOrSelf(WYMeditor.A);
  1152. break;
  1153. }
  1154. //pre-init functions
  1155. if(jQuery.isFunction(wym._options.preInitDialog))
  1156. wym._options.preInitDialog(wym,window);
  1157. //add css rules from options
  1158. var styles = doc.styleSheets[0];
  1159. var aCss = eval(wym._options.dialogStyles);
  1160. wym.addCssRules(doc, aCss);
  1161. //auto populate fields if selected container (e.g. A)
  1162. if(selected) {
  1163. jQuery(wym._options.hrefSelector).val(jQuery(selected).attr(WYMeditor.HREF));
  1164. jQuery(wym._options.srcSelector).val(jQuery(selected).attr(WYMeditor.SRC));
  1165. jQuery(wym._options.titleSelector).val(jQuery(selected).attr(WYMeditor.TITLE));
  1166. jQuery(wym._options.altSelector).val(jQuery(selected).attr(WYMeditor.ALT));
  1167. }
  1168. //auto populate image fields if selected image
  1169. if(wym._selected_image) {
  1170. jQuery(wym._options.dialogImageSelector + " " + wym._options.srcSelector)
  1171. .val(jQuery(wym._selected_image).attr(WYMeditor.SRC));
  1172. jQuery(wym._options.dialogImageSelector + " " + wym._options.titleSelector)
  1173. .val(jQuery(wym._selected_image).attr(WYMeditor.TITLE));
  1174. jQuery(wym._options.dialogImageSelector + " " + wym._options.altSelector)
  1175. .val(jQuery(wym._selected_image).attr(WYMeditor.ALT));
  1176. }
  1177. jQuery(wym._options.dialogLinkSelector + " "
  1178. + wym._options.submitSelector).click(function() {
  1179. var sUrl = jQuery(wym._options.hrefSelector).val();
  1180. if(sUrl.length > 0) {
  1181. wym._exec(WYMeditor.CREATE_LINK, sStamp);
  1182. jQuery("a[@href=" + sStamp + "]", wym._doc.body)
  1183. .attr(WYMeditor.HREF, sUrl)
  1184. .attr(WYMeditor.TITLE, jQuery(wym._options.titleSelector).val());
  1185. }
  1186. window.close();
  1187. });
  1188. jQuery(wym._options.dialogImageSelector + " "
  1189. + wym._options.submitSelector).click(function() {
  1190. var sUrl = jQuery(wym._options.srcSelector).val();
  1191. if(sUrl.length > 0) {
  1192. wym._exec(WYMeditor.INSERT_IMAGE, sStamp);
  1193. jQuery("img[@src=" + sStamp + "]", wym._doc.body)
  1194. .attr(WYMeditor.SRC, sUrl)
  1195. .attr(WYMeditor.TITLE, jQuery(wym._options.titleSelector).val())
  1196. .attr(WYMeditor.ALT, jQuery(wym._options.altSelector).val());
  1197. }
  1198. window.close();
  1199. });
  1200. jQuery(wym._options.dialogTableSelector + " "
  1201. + wym._options.submitSelector).click(function() {
  1202. var iRows = jQuery(wym._options.rowsSelector).val();
  1203. var iCols = jQuery(wym._options.colsSelector).val();
  1204. if(iRows > 0 && iCols > 0) {
  1205. var table = wym._doc.createElement(WYMeditor.TABLE);
  1206. var newRow = null;
  1207. var newCol = null;
  1208. var sCaption = jQuery(wym._options.captionSelector).val();
  1209. //we create the caption
  1210. var newCaption = table.createCaption();
  1211. newCaption.innerHTML = sCaption;
  1212. //we create the rows and cells
  1213. for(x=0; x<iRows; x++) {
  1214. newRow = table.insertRow(x);
  1215. for(y=0; y<iCols; y++) {newRow.insertCell(y);}
  1216. }
  1217. //set t…

Large files files are truncated, but you can click here to view the full file