editor_template_src.js 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490
  1. /**
  2. * editor_template_src.js
  3. *
  4. * Copyright 2009, Moxiecode Systems AB
  5. * Released under LGPL License.
  6. *
  7. * License: http://tinymce.moxiecode.com/license
  8. * Contributing: http://tinymce.moxiecode.com/contributing
  9. */
  10. (function(tinymce) {
  11. var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, each = tinymce.each, Cookie = tinymce.util.Cookie, lastExtID, explode = tinymce.explode;
  12. // Generates a preview for a format
  13. function getPreviewCss(ed, fmt) {
  14. var name, previewElm, dom = ed.dom, previewCss = '', parentFontSize, previewStylesName;
  15. previewStyles = ed.settings.preview_styles;
  16. // No preview forced
  17. if (previewStyles === false)
  18. return '';
  19. // Default preview
  20. if (!previewStyles)
  21. previewStyles = 'font-family font-size font-weight text-decoration text-transform color background-color';
  22. // Removes any variables since these can't be previewed
  23. function removeVars(val) {
  24. return val.replace(/%(\w+)/g, '');
  25. };
  26. // Create block/inline element to use for preview
  27. name = fmt.block || fmt.inline || 'span';
  28. previewElm = dom.create(name);
  29. // Add format styles to preview element
  30. each(fmt.styles, function(value, name) {
  31. value = removeVars(value);
  32. if (value)
  33. dom.setStyle(previewElm, name, value);
  34. });
  35. // Add attributes to preview element
  36. each(fmt.attributes, function(value, name) {
  37. value = removeVars(value);
  38. if (value)
  39. dom.setAttrib(previewElm, name, value);
  40. });
  41. // Add classes to preview element
  42. each(fmt.classes, function(value) {
  43. value = removeVars(value);
  44. if (!dom.hasClass(previewElm, value))
  45. dom.addClass(previewElm, value);
  46. });
  47. // Add the previewElm outside the visual area
  48. dom.setStyles(previewElm, {position: 'absolute', left: -0xFFFF});
  49. ed.getBody().appendChild(previewElm);
  50. // Get parent container font size so we can compute px values out of em/% for older IE:s
  51. parentFontSize = dom.getStyle(ed.getBody(), 'fontSize', true);
  52. parentFontSize = /px$/.test(parentFontSize) ? parseInt(parentFontSize, 10) : 0;
  53. each(previewStyles.split(' '), function(name) {
  54. var value = dom.getStyle(previewElm, name, true);
  55. // If background is transparent then check if the body has a background color we can use
  56. if (name == 'background-color' && /transparent|rgba\s*\([^)]+,\s*0\)/.test(value)) {
  57. value = dom.getStyle(ed.getBody(), name, true);
  58. // Ignore white since it's the default color, not the nicest fix
  59. if (dom.toHex(value).toLowerCase() == '#ffffff') {
  60. return;
  61. }
  62. }
  63. // Old IE won't calculate the font size so we need to do that manually
  64. if (name == 'font-size') {
  65. if (/em|%$/.test(value)) {
  66. if (parentFontSize === 0) {
  67. return;
  68. }
  69. // Convert font size from em/% to px
  70. value = parseFloat(value, 10) / (/%$/.test(value) ? 100 : 1);
  71. value = (value * parentFontSize) + 'px';
  72. }
  73. }
  74. previewCss += name + ':' + value + ';';
  75. });
  76. dom.remove(previewElm);
  77. return previewCss;
  78. };
  79. // Tell it to load theme specific language pack(s)
  80. tinymce.ThemeManager.requireLangPack('advanced');
  81. tinymce.create('tinymce.themes.AdvancedTheme', {
  82. sizes : [8, 10, 12, 14, 18, 24, 36],
  83. // Control name lookup, format: title, command
  84. controls : {
  85. bold : ['bold_desc', 'Bold'],
  86. italic : ['italic_desc', 'Italic'],
  87. underline : ['underline_desc', 'Underline'],
  88. strikethrough : ['striketrough_desc', 'Strikethrough'],
  89. justifyleft : ['justifyleft_desc', 'JustifyLeft'],
  90. justifycenter : ['justifycenter_desc', 'JustifyCenter'],
  91. justifyright : ['justifyright_desc', 'JustifyRight'],
  92. justifyfull : ['justifyfull_desc', 'JustifyFull'],
  93. bullist : ['bullist_desc', 'InsertUnorderedList'],
  94. numlist : ['numlist_desc', 'InsertOrderedList'],
  95. outdent : ['outdent_desc', 'Outdent'],
  96. indent : ['indent_desc', 'Indent'],
  97. cut : ['cut_desc', 'Cut'],
  98. copy : ['copy_desc', 'Copy'],
  99. paste : ['paste_desc', 'Paste'],
  100. undo : ['undo_desc', 'Undo'],
  101. redo : ['redo_desc', 'Redo'],
  102. link : ['link_desc', 'mceLink'],
  103. unlink : ['unlink_desc', 'unlink'],
  104. image : ['image_desc', 'mceImage'],
  105. cleanup : ['cleanup_desc', 'mceCleanup'],
  106. help : ['help_desc', 'mceHelp'],
  107. code : ['code_desc', 'mceCodeEditor'],
  108. hr : ['hr_desc', 'InsertHorizontalRule'],
  109. removeformat : ['removeformat_desc', 'RemoveFormat'],
  110. sub : ['sub_desc', 'subscript'],
  111. sup : ['sup_desc', 'superscript'],
  112. forecolor : ['forecolor_desc', 'ForeColor'],
  113. forecolorpicker : ['forecolor_desc', 'mceForeColor'],
  114. backcolor : ['backcolor_desc', 'HiliteColor'],
  115. backcolorpicker : ['backcolor_desc', 'mceBackColor'],
  116. charmap : ['charmap_desc', 'mceCharMap'],
  117. visualaid : ['visualaid_desc', 'mceToggleVisualAid'],
  118. anchor : ['anchor_desc', 'mceInsertAnchor'],
  119. newdocument : ['newdocument_desc', 'mceNewDocument'],
  120. blockquote : ['blockquote_desc', 'mceBlockQuote']
  121. },
  122. stateControls : ['bold', 'italic', 'underline', 'strikethrough', 'bullist', 'numlist', 'justifyleft', 'justifycenter', 'justifyright', 'justifyfull', 'sub', 'sup', 'blockquote'],
  123. init : function(ed, url) {
  124. var t = this, s, v, o;
  125. t.editor = ed;
  126. t.url = url;
  127. t.onResolveName = new tinymce.util.Dispatcher(this);
  128. s = ed.settings;
  129. ed.forcedHighContrastMode = ed.settings.detect_highcontrast && t._isHighContrast();
  130. ed.settings.skin = ed.forcedHighContrastMode ? 'highcontrast' : ed.settings.skin;
  131. // Setup default buttons
  132. if (!s.theme_advanced_buttons1) {
  133. s = extend({
  134. theme_advanced_buttons1 : "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect",
  135. theme_advanced_buttons2 : "bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code",
  136. theme_advanced_buttons3 : "hr,removeformat,visualaid,|,sub,sup,|,charmap"
  137. }, s);
  138. }
  139. // Default settings
  140. t.settings = s = extend({
  141. theme_advanced_path : true,
  142. theme_advanced_toolbar_location : 'top',
  143. theme_advanced_blockformats : "p,address,pre,h1,h2,h3,h4,h5,h6",
  144. theme_advanced_toolbar_align : "left",
  145. theme_advanced_statusbar_location : "bottom",
  146. theme_advanced_fonts : "Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats",
  147. theme_advanced_more_colors : 1,
  148. theme_advanced_row_height : 23,
  149. theme_advanced_resize_horizontal : 1,
  150. theme_advanced_resizing_use_cookie : 1,
  151. theme_advanced_font_sizes : "1,2,3,4,5,6,7",
  152. theme_advanced_font_selector : "span",
  153. theme_advanced_show_current_color: 0,
  154. readonly : ed.settings.readonly
  155. }, s);
  156. // Setup default font_size_style_values
  157. if (!s.font_size_style_values)
  158. s.font_size_style_values = "8pt,10pt,12pt,14pt,18pt,24pt,36pt";
  159. if (tinymce.is(s.theme_advanced_font_sizes, 'string')) {
  160. s.font_size_style_values = tinymce.explode(s.font_size_style_values);
  161. s.font_size_classes = tinymce.explode(s.font_size_classes || '');
  162. // Parse string value
  163. o = {};
  164. ed.settings.theme_advanced_font_sizes = s.theme_advanced_font_sizes;
  165. each(ed.getParam('theme_advanced_font_sizes', '', 'hash'), function(v, k) {
  166. var cl;
  167. if (k == v && v >= 1 && v <= 7) {
  168. k = v + ' (' + t.sizes[v - 1] + 'pt)';
  169. cl = s.font_size_classes[v - 1];
  170. v = s.font_size_style_values[v - 1] || (t.sizes[v - 1] + 'pt');
  171. }
  172. if (/^\s*\./.test(v))
  173. cl = v.replace(/\./g, '');
  174. o[k] = cl ? {'class' : cl} : {fontSize : v};
  175. });
  176. s.theme_advanced_font_sizes = o;
  177. }
  178. if ((v = s.theme_advanced_path_location) && v != 'none')
  179. s.theme_advanced_statusbar_location = s.theme_advanced_path_location;
  180. if (s.theme_advanced_statusbar_location == 'none')
  181. s.theme_advanced_statusbar_location = 0;
  182. if (ed.settings.content_css !== false)
  183. ed.contentCSS.push(ed.baseURI.toAbsolute(url + "/skins/" + ed.settings.skin + "/content.css"));
  184. // Init editor
  185. ed.onInit.add(function() {
  186. if (!ed.settings.readonly) {
  187. ed.onNodeChange.add(t._nodeChanged, t);
  188. ed.onKeyUp.add(t._updateUndoStatus, t);
  189. ed.onMouseUp.add(t._updateUndoStatus, t);
  190. ed.dom.bind(ed.dom.getRoot(), 'dragend', function() {
  191. t._updateUndoStatus(ed);
  192. });
  193. }
  194. });
  195. ed.onSetProgressState.add(function(ed, b, ti) {
  196. var co, id = ed.id, tb;
  197. if (b) {
  198. t.progressTimer = setTimeout(function() {
  199. co = ed.getContainer();
  200. co = co.insertBefore(DOM.create('DIV', {style : 'position:relative'}), co.firstChild);
  201. tb = DOM.get(ed.id + '_tbl');
  202. DOM.add(co, 'div', {id : id + '_blocker', 'class' : 'mceBlocker', style : {width : tb.clientWidth + 2, height : tb.clientHeight + 2}});
  203. DOM.add(co, 'div', {id : id + '_progress', 'class' : 'mceProgress', style : {left : tb.clientWidth / 2, top : tb.clientHeight / 2}});
  204. }, ti || 0);
  205. } else {
  206. DOM.remove(id + '_blocker');
  207. DOM.remove(id + '_progress');
  208. clearTimeout(t.progressTimer);
  209. }
  210. });
  211. DOM.loadCSS(s.editor_css ? ed.documentBaseURI.toAbsolute(s.editor_css) : url + "/skins/" + ed.settings.skin + "/ui.css");
  212. if (s.skin_variant)
  213. DOM.loadCSS(url + "/skins/" + ed.settings.skin + "/ui_" + s.skin_variant + ".css");
  214. },
  215. _isHighContrast : function() {
  216. var actualColor, div = DOM.add(DOM.getRoot(), 'div', {'style': 'background-color: rgb(171,239,86);'});
  217. actualColor = (DOM.getStyle(div, 'background-color', true) + '').toLowerCase().replace(/ /g, '');
  218. DOM.remove(div);
  219. return actualColor != 'rgb(171,239,86)' && actualColor != '#abef56';
  220. },
  221. createControl : function(n, cf) {
  222. var cd, c;
  223. if (c = cf.createControl(n))
  224. return c;
  225. switch (n) {
  226. case "styleselect":
  227. return this._createStyleSelect();
  228. case "formatselect":
  229. return this._createBlockFormats();
  230. case "fontselect":
  231. return this._createFontSelect();
  232. case "fontsizeselect":
  233. return this._createFontSizeSelect();
  234. case "forecolor":
  235. return this._createForeColorMenu();
  236. case "backcolor":
  237. return this._createBackColorMenu();
  238. }
  239. if ((cd = this.controls[n]))
  240. return cf.createButton(n, {title : "advanced." + cd[0], cmd : cd[1], ui : cd[2], value : cd[3]});
  241. },
  242. execCommand : function(cmd, ui, val) {
  243. var f = this['_' + cmd];
  244. if (f) {
  245. f.call(this, ui, val);
  246. return true;
  247. }
  248. return false;
  249. },
  250. _importClasses : function(e) {
  251. var ed = this.editor, ctrl = ed.controlManager.get('styleselect');
  252. if (ctrl.getLength() == 0) {
  253. each(ed.dom.getClasses(), function(o, idx) {
  254. var name = 'style_' + idx, fmt;
  255. fmt = {
  256. inline : 'span',
  257. attributes : {'class' : o['class']},
  258. selector : '*'
  259. };
  260. ed.formatter.register(name, fmt);
  261. ctrl.add(o['class'], name, {
  262. style: function() {
  263. return getPreviewCss(ed, fmt);
  264. }
  265. });
  266. });
  267. }
  268. },
  269. _createStyleSelect : function(n) {
  270. var t = this, ed = t.editor, ctrlMan = ed.controlManager, ctrl;
  271. // Setup style select box
  272. ctrl = ctrlMan.createListBox('styleselect', {
  273. title : 'advanced.style_select',
  274. onselect : function(name) {
  275. var matches, formatNames = [], removedFormat;
  276. each(ctrl.items, function(item) {
  277. formatNames.push(item.value);
  278. });
  279. ed.focus();
  280. ed.undoManager.add();
  281. // Toggle off the current format(s)
  282. matches = ed.formatter.matchAll(formatNames);
  283. tinymce.each(matches, function(match) {
  284. if (!name || match == name) {
  285. if (match)
  286. ed.formatter.remove(match);
  287. removedFormat = true;
  288. }
  289. });
  290. if (!removedFormat)
  291. ed.formatter.apply(name);
  292. ed.undoManager.add();
  293. ed.nodeChanged();
  294. return false; // No auto select
  295. }
  296. });
  297. // Handle specified format
  298. ed.onPreInit.add(function() {
  299. var counter = 0, formats = ed.getParam('style_formats');
  300. if (formats) {
  301. each(formats, function(fmt) {
  302. var name, keys = 0;
  303. each(fmt, function() {keys++;});
  304. if (keys > 1) {
  305. name = fmt.name = fmt.name || 'style_' + (counter++);
  306. ed.formatter.register(name, fmt);
  307. ctrl.add(fmt.title, name, {
  308. style: function() {
  309. return getPreviewCss(ed, fmt);
  310. }
  311. });
  312. } else
  313. ctrl.add(fmt.title);
  314. });
  315. } else {
  316. each(ed.getParam('theme_advanced_styles', '', 'hash'), function(val, key) {
  317. var name, fmt;
  318. if (val) {
  319. name = 'style_' + (counter++);
  320. fmt = {
  321. inline : 'span',
  322. classes : val,
  323. selector : '*'
  324. };
  325. ed.formatter.register(name, fmt);
  326. ctrl.add(t.editor.translate(key), name, {
  327. style: function() {
  328. return getPreviewCss(ed, fmt);
  329. }
  330. });
  331. }
  332. });
  333. }
  334. });
  335. // Auto import classes if the ctrl box is empty
  336. if (ctrl.getLength() == 0) {
  337. ctrl.onPostRender.add(function(ed, n) {
  338. if (!ctrl.NativeListBox) {
  339. Event.add(n.id + '_text', 'focus', t._importClasses, t);
  340. Event.add(n.id + '_text', 'mousedown', t._importClasses, t);
  341. Event.add(n.id + '_open', 'focus', t._importClasses, t);
  342. Event.add(n.id + '_open', 'mousedown', t._importClasses, t);
  343. } else
  344. Event.add(n.id, 'focus', t._importClasses, t);
  345. });
  346. }
  347. return ctrl;
  348. },
  349. _createFontSelect : function() {
  350. var c, t = this, ed = t.editor;
  351. c = ed.controlManager.createListBox('fontselect', {
  352. title : 'advanced.fontdefault',
  353. onselect : function(v) {
  354. var cur = c.items[c.selectedIndex];
  355. if (!v && cur) {
  356. ed.execCommand('FontName', false, cur.value);
  357. return;
  358. }
  359. ed.execCommand('FontName', false, v);
  360. // Fake selection, execCommand will fire a nodeChange and update the selection
  361. c.select(function(sv) {
  362. return v == sv;
  363. });
  364. if (cur && cur.value == v) {
  365. c.select(null);
  366. }
  367. return false; // No auto select
  368. }
  369. });
  370. if (c) {
  371. each(ed.getParam('theme_advanced_fonts', t.settings.theme_advanced_fonts, 'hash'), function(v, k) {
  372. c.add(ed.translate(k), v, {style : v.indexOf('dings') == -1 ? 'font-family:' + v : ''});
  373. });
  374. }
  375. return c;
  376. },
  377. _createFontSizeSelect : function() {
  378. var t = this, ed = t.editor, c, i = 0, cl = [];
  379. c = ed.controlManager.createListBox('fontsizeselect', {title : 'advanced.font_size', onselect : function(v) {
  380. var cur = c.items[c.selectedIndex];
  381. if (!v && cur) {
  382. cur = cur.value;
  383. if (cur['class']) {
  384. ed.formatter.toggle('fontsize_class', {value : cur['class']});
  385. ed.undoManager.add();
  386. ed.nodeChanged();
  387. } else {
  388. ed.execCommand('FontSize', false, cur.fontSize);
  389. }
  390. return;
  391. }
  392. if (v['class']) {
  393. ed.focus();
  394. ed.undoManager.add();
  395. ed.formatter.toggle('fontsize_class', {value : v['class']});
  396. ed.undoManager.add();
  397. ed.nodeChanged();
  398. } else
  399. ed.execCommand('FontSize', false, v.fontSize);
  400. // Fake selection, execCommand will fire a nodeChange and update the selection
  401. c.select(function(sv) {
  402. return v == sv;
  403. });
  404. if (cur && (cur.value.fontSize == v.fontSize || cur.value['class'] && cur.value['class'] == v['class'])) {
  405. c.select(null);
  406. }
  407. return false; // No auto select
  408. }});
  409. if (c) {
  410. each(t.settings.theme_advanced_font_sizes, function(v, k) {
  411. var fz = v.fontSize;
  412. if (fz >= 1 && fz <= 7)
  413. fz = t.sizes[parseInt(fz) - 1] + 'pt';
  414. c.add(k, v, {'style' : 'font-size:' + fz, 'class' : 'mceFontSize' + (i++) + (' ' + (v['class'] || ''))});
  415. });
  416. }
  417. return c;
  418. },
  419. _createBlockFormats : function() {
  420. var c, fmts = {
  421. p : 'advanced.paragraph',
  422. address : 'advanced.address',
  423. pre : 'advanced.pre',
  424. h1 : 'advanced.h1',
  425. h2 : 'advanced.h2',
  426. h3 : 'advanced.h3',
  427. h4 : 'advanced.h4',
  428. h5 : 'advanced.h5',
  429. h6 : 'advanced.h6',
  430. div : 'advanced.div',
  431. blockquote : 'advanced.blockquote',
  432. code : 'advanced.code',
  433. dt : 'advanced.dt',
  434. dd : 'advanced.dd',
  435. samp : 'advanced.samp'
  436. }, t = this;
  437. c = t.editor.controlManager.createListBox('formatselect', {title : 'advanced.block', onselect : function(v) {
  438. t.editor.execCommand('FormatBlock', false, v);
  439. return false;
  440. }});
  441. if (c) {
  442. each(t.editor.getParam('theme_advanced_blockformats', t.settings.theme_advanced_blockformats, 'hash'), function(v, k) {
  443. c.add(t.editor.translate(k != v ? k : fmts[v]), v, {'class' : 'mce_formatPreview mce_' + v, style: function() {
  444. return getPreviewCss(t.editor, {block: v});
  445. }});
  446. });
  447. }
  448. return c;
  449. },
  450. _createForeColorMenu : function() {
  451. var c, t = this, s = t.settings, o = {}, v;
  452. if (s.theme_advanced_more_colors) {
  453. o.more_colors_func = function() {
  454. t._mceColorPicker(0, {
  455. color : c.value,
  456. func : function(co) {
  457. c.setColor(co);
  458. }
  459. });
  460. };
  461. }
  462. if (v = s.theme_advanced_text_colors)
  463. o.colors = v;
  464. if (s.theme_advanced_default_foreground_color)
  465. o.default_color = s.theme_advanced_default_foreground_color;
  466. o.title = 'advanced.forecolor_desc';
  467. o.cmd = 'ForeColor';
  468. o.scope = this;
  469. c = t.editor.controlManager.createColorSplitButton('forecolor', o);
  470. return c;
  471. },
  472. _createBackColorMenu : function() {
  473. var c, t = this, s = t.settings, o = {}, v;
  474. if (s.theme_advanced_more_colors) {
  475. o.more_colors_func = function() {
  476. t._mceColorPicker(0, {
  477. color : c.value,
  478. func : function(co) {
  479. c.setColor(co);
  480. }
  481. });
  482. };
  483. }
  484. if (v = s.theme_advanced_background_colors)
  485. o.colors = v;
  486. if (s.theme_advanced_default_background_color)
  487. o.default_color = s.theme_advanced_default_background_color;
  488. o.title = 'advanced.backcolor_desc';
  489. o.cmd = 'HiliteColor';
  490. o.scope = this;
  491. c = t.editor.controlManager.createColorSplitButton('backcolor', o);
  492. return c;
  493. },
  494. renderUI : function(o) {
  495. var n, ic, tb, t = this, ed = t.editor, s = t.settings, sc, p, nl;
  496. if (ed.settings) {
  497. ed.settings.aria_label = s.aria_label + ed.getLang('advanced.help_shortcut');
  498. }
  499. // TODO: ACC Should have an aria-describedby attribute which is user-configurable to describe what this field is actually for.
  500. // Maybe actually inherit it from the original textara?
  501. n = p = DOM.create('span', {role : 'application', 'aria-labelledby' : ed.id + '_voice', id : ed.id + '_parent', 'class' : 'mceEditor ' + ed.settings.skin + 'Skin' + (s.skin_variant ? ' ' + ed.settings.skin + 'Skin' + t._ufirst(s.skin_variant) : '') + (ed.settings.directionality == "rtl" ? ' mceRtl' : '')});
  502. DOM.add(n, 'span', {'class': 'mceVoiceLabel', 'style': 'display:none;', id: ed.id + '_voice'}, s.aria_label);
  503. if (!DOM.boxModel)
  504. n = DOM.add(n, 'div', {'class' : 'mceOldBoxModel'});
  505. n = sc = DOM.add(n, 'table', {role : "presentation", id : ed.id + '_tbl', 'class' : 'mceLayout', cellSpacing : 0, cellPadding : 0});
  506. n = tb = DOM.add(n, 'tbody');
  507. switch ((s.theme_advanced_layout_manager || '').toLowerCase()) {
  508. case "rowlayout":
  509. ic = t._rowLayout(s, tb, o);
  510. break;
  511. case "customlayout":
  512. ic = ed.execCallback("theme_advanced_custom_layout", s, tb, o, p);
  513. break;
  514. default:
  515. ic = t._simpleLayout(s, tb, o, p);
  516. }
  517. n = o.targetNode;
  518. // Add classes to first and last TRs
  519. nl = sc.rows;
  520. DOM.addClass(nl[0], 'mceFirst');
  521. DOM.addClass(nl[nl.length - 1], 'mceLast');
  522. // Add classes to first and last TDs
  523. each(DOM.select('tr', tb), function(n) {
  524. DOM.addClass(n.firstChild, 'mceFirst');
  525. DOM.addClass(n.childNodes[n.childNodes.length - 1], 'mceLast');
  526. });
  527. if (DOM.get(s.theme_advanced_toolbar_container))
  528. DOM.get(s.theme_advanced_toolbar_container).appendChild(p);
  529. else
  530. DOM.insertAfter(p, n);
  531. Event.add(ed.id + '_path_row', 'click', function(e) {
  532. e = e.target;
  533. if (e.nodeName == 'A') {
  534. t._sel(e.className.replace(/^.*mcePath_([0-9]+).*$/, '$1'));
  535. return false;
  536. }
  537. });
  538. /*
  539. if (DOM.get(ed.id + '_path_row')) {
  540. Event.add(ed.id + '_tbl', 'mouseover', function(e) {
  541. var re;
  542. e = e.target;
  543. if (e.nodeName == 'SPAN' && DOM.hasClass(e.parentNode, 'mceButton')) {
  544. re = DOM.get(ed.id + '_path_row');
  545. t.lastPath = re.innerHTML;
  546. DOM.setHTML(re, e.parentNode.title);
  547. }
  548. });
  549. Event.add(ed.id + '_tbl', 'mouseout', function(e) {
  550. if (t.lastPath) {
  551. DOM.setHTML(ed.id + '_path_row', t.lastPath);
  552. t.lastPath = 0;
  553. }
  554. });
  555. }
  556. */
  557. if (!ed.getParam('accessibility_focus'))
  558. Event.add(DOM.add(p, 'a', {href : '#'}, '<!-- IE -->'), 'focus', function() {tinyMCE.get(ed.id).focus();});
  559. if (s.theme_advanced_toolbar_location == 'external')
  560. o.deltaHeight = 0;
  561. t.deltaHeight = o.deltaHeight;
  562. o.targetNode = null;
  563. ed.onKeyDown.add(function(ed, evt) {
  564. var DOM_VK_F10 = 121, DOM_VK_F11 = 122;
  565. if (evt.altKey) {
  566. if (evt.keyCode === DOM_VK_F10) {
  567. // Make sure focus is given to toolbar in Safari.
  568. // We can't do this in IE as it prevents giving focus to toolbar when editor is in a frame
  569. if (tinymce.isWebKit) {
  570. window.focus();
  571. }
  572. t.toolbarGroup.focus();
  573. return Event.cancel(evt);
  574. } else if (evt.keyCode === DOM_VK_F11) {
  575. DOM.get(ed.id + '_path_row').focus();
  576. return Event.cancel(evt);
  577. }
  578. }
  579. });
  580. // alt+0 is the UK recommended shortcut for accessing the list of access controls.
  581. ed.addShortcut('alt+0', '', 'mceShortcuts', t);
  582. return {
  583. iframeContainer : ic,
  584. editorContainer : ed.id + '_parent',
  585. sizeContainer : sc,
  586. deltaHeight : o.deltaHeight
  587. };
  588. },
  589. getInfo : function() {
  590. return {
  591. longname : 'Advanced theme',
  592. author : 'Moxiecode Systems AB',
  593. authorurl : 'http://tinymce.moxiecode.com',
  594. version : tinymce.majorVersion + "." + tinymce.minorVersion
  595. }
  596. },
  597. resizeBy : function(dw, dh) {
  598. var e = DOM.get(this.editor.id + '_ifr');
  599. this.resizeTo(e.clientWidth + dw, e.clientHeight + dh);
  600. },
  601. resizeTo : function(w, h, store) {
  602. var ed = this.editor, s = this.settings, e = DOM.get(ed.id + '_tbl'), ifr = DOM.get(ed.id + '_ifr');
  603. // Boundery fix box
  604. w = Math.max(s.theme_advanced_resizing_min_width || 100, w);
  605. h = Math.max(s.theme_advanced_resizing_min_height || 100, h);
  606. w = Math.min(s.theme_advanced_resizing_max_width || 0xFFFF, w);
  607. h = Math.min(s.theme_advanced_resizing_max_height || 0xFFFF, h);
  608. // Resize iframe and container
  609. DOM.setStyle(e, 'height', '');
  610. DOM.setStyle(ifr, 'height', h);
  611. if (s.theme_advanced_resize_horizontal) {
  612. DOM.setStyle(e, 'width', '');
  613. DOM.setStyle(ifr, 'width', w);
  614. // Make sure that the size is never smaller than the over all ui
  615. if (w < e.clientWidth) {
  616. w = e.clientWidth;
  617. DOM.setStyle(ifr, 'width', e.clientWidth);
  618. }
  619. }
  620. // Store away the size
  621. if (store && s.theme_advanced_resizing_use_cookie) {
  622. Cookie.setHash("TinyMCE_" + ed.id + "_size", {
  623. cw : w,
  624. ch : h
  625. });
  626. }
  627. },
  628. destroy : function() {
  629. var id = this.editor.id;
  630. Event.clear(id + '_resize');
  631. Event.clear(id + '_path_row');
  632. Event.clear(id + '_external_close');
  633. },
  634. // Internal functions
  635. _simpleLayout : function(s, tb, o, p) {
  636. var t = this, ed = t.editor, lo = s.theme_advanced_toolbar_location, sl = s.theme_advanced_statusbar_location, n, ic, etb, c;
  637. if (s.readonly) {
  638. n = DOM.add(tb, 'tr');
  639. n = ic = DOM.add(n, 'td', {'class' : 'mceIframeContainer'});
  640. return ic;
  641. }
  642. // Create toolbar container at top
  643. if (lo == 'top')
  644. t._addToolbars(tb, o);
  645. // Create external toolbar
  646. if (lo == 'external') {
  647. n = c = DOM.create('div', {style : 'position:relative'});
  648. n = DOM.add(n, 'div', {id : ed.id + '_external', 'class' : 'mceExternalToolbar'});
  649. DOM.add(n, 'a', {id : ed.id + '_external_close', href : 'javascript:;', 'class' : 'mceExternalClose'});
  650. n = DOM.add(n, 'table', {id : ed.id + '_tblext', cellSpacing : 0, cellPadding : 0});
  651. etb = DOM.add(n, 'tbody');
  652. if (p.firstChild.className == 'mceOldBoxModel')
  653. p.firstChild.appendChild(c);
  654. else
  655. p.insertBefore(c, p.firstChild);
  656. t._addToolbars(etb, o);
  657. ed.onMouseUp.add(function() {
  658. var e = DOM.get(ed.id + '_external');
  659. DOM.show(e);
  660. DOM.hide(lastExtID);
  661. var f = Event.add(ed.id + '_external_close', 'click', function() {
  662. DOM.hide(ed.id + '_external');
  663. Event.remove(ed.id + '_external_close', 'click', f);
  664. return false;
  665. });
  666. DOM.show(e);
  667. DOM.setStyle(e, 'top', 0 - DOM.getRect(ed.id + '_tblext').h - 1);
  668. // Fixes IE rendering bug
  669. DOM.hide(e);
  670. DOM.show(e);
  671. e.style.filter = '';
  672. lastExtID = ed.id + '_external';
  673. e = null;
  674. });
  675. }
  676. if (sl == 'top')
  677. t._addStatusBar(tb, o);
  678. // Create iframe container
  679. if (!s.theme_advanced_toolbar_container) {
  680. n = DOM.add(tb, 'tr');
  681. n = ic = DOM.add(n, 'td', {'class' : 'mceIframeContainer'});
  682. }
  683. // Create toolbar container at bottom
  684. if (lo == 'bottom')
  685. t._addToolbars(tb, o);
  686. if (sl == 'bottom')
  687. t._addStatusBar(tb, o);
  688. return ic;
  689. },
  690. _rowLayout : function(s, tb, o) {
  691. var t = this, ed = t.editor, dc, da, cf = ed.controlManager, n, ic, to, a;
  692. dc = s.theme_advanced_containers_default_class || '';
  693. da = s.theme_advanced_containers_default_align || 'center';
  694. each(explode(s.theme_advanced_containers || ''), function(c, i) {
  695. var v = s['theme_advanced_container_' + c] || '';
  696. switch (c.toLowerCase()) {
  697. case 'mceeditor':
  698. n = DOM.add(tb, 'tr');
  699. n = ic = DOM.add(n, 'td', {'class' : 'mceIframeContainer'});
  700. break;
  701. case 'mceelementpath':
  702. t._addStatusBar(tb, o);
  703. break;
  704. default:
  705. a = (s['theme_advanced_container_' + c + '_align'] || da).toLowerCase();
  706. a = 'mce' + t._ufirst(a);
  707. n = DOM.add(DOM.add(tb, 'tr'), 'td', {
  708. 'class' : 'mceToolbar ' + (s['theme_advanced_container_' + c + '_class'] || dc) + ' ' + a || da
  709. });
  710. to = cf.createToolbar("toolbar" + i);
  711. t._addControls(v, to);
  712. DOM.setHTML(n, to.renderHTML());
  713. o.deltaHeight -= s.theme_advanced_row_height;
  714. }
  715. });
  716. return ic;
  717. },
  718. _addControls : function(v, tb) {
  719. var t = this, s = t.settings, di, cf = t.editor.controlManager;
  720. if (s.theme_advanced_disable && !t._disabled) {
  721. di = {};
  722. each(explode(s.theme_advanced_disable), function(v) {
  723. di[v] = 1;
  724. });
  725. t._disabled = di;
  726. } else
  727. di = t._disabled;
  728. each(explode(v), function(n) {
  729. var c;
  730. if (di && di[n])
  731. return;
  732. // Compatiblity with 2.x
  733. if (n == 'tablecontrols') {
  734. each(["table","|","row_props","cell_props","|","row_before","row_after","delete_row","|","col_before","col_after","delete_col","|","split_cells","merge_cells"], function(n) {
  735. n = t.createControl(n, cf);
  736. if (n)
  737. tb.add(n);
  738. });
  739. return;
  740. }
  741. c = t.createControl(n, cf);
  742. if (c)
  743. tb.add(c);
  744. });
  745. },
  746. _addToolbars : function(c, o) {
  747. var t = this, i, tb, ed = t.editor, s = t.settings, v, cf = ed.controlManager, di, n, h = [], a, toolbarGroup, toolbarsExist = false;
  748. toolbarGroup = cf.createToolbarGroup('toolbargroup', {
  749. 'name': ed.getLang('advanced.toolbar'),
  750. 'tab_focus_toolbar':ed.getParam('theme_advanced_tab_focus_toolbar')
  751. });
  752. t.toolbarGroup = toolbarGroup;
  753. a = s.theme_advanced_toolbar_align.toLowerCase();
  754. a = 'mce' + t._ufirst(a);
  755. n = DOM.add(DOM.add(c, 'tr', {role: 'toolbar'}), 'td', {'class' : 'mceToolbar ' + a, "role":"toolbar"});
  756. // Create toolbar and add the controls
  757. for (i=1; (v = s['theme_advanced_buttons' + i]); i++) {
  758. toolbarsExist = true;
  759. tb = cf.createToolbar("toolbar" + i, {'class' : 'mceToolbarRow' + i});
  760. if (s['theme_advanced_buttons' + i + '_add'])
  761. v += ',' + s['theme_advanced_buttons' + i + '_add'];
  762. if (s['theme_advanced_buttons' + i + '_add_before'])
  763. v = s['theme_advanced_buttons' + i + '_add_before'] + ',' + v;
  764. t._addControls(v, tb);
  765. toolbarGroup.add(tb);
  766. o.deltaHeight -= s.theme_advanced_row_height;
  767. }
  768. // Handle case when there are no toolbar buttons and ensure editor height is adjusted accordingly
  769. if (!toolbarsExist)
  770. o.deltaHeight -= s.theme_advanced_row_height;
  771. h.push(toolbarGroup.renderHTML());
  772. h.push(DOM.createHTML('a', {href : '#', accesskey : 'z', title : ed.getLang("advanced.toolbar_focus"), onfocus : 'tinyMCE.getInstanceById(\'' + ed.id + '\').focus();'}, '<!-- IE -->'));
  773. DOM.setHTML(n, h.join(''));
  774. },
  775. _addStatusBar : function(tb, o) {
  776. var n, t = this, ed = t.editor, s = t.settings, r, mf, me, td;
  777. n = DOM.add(tb, 'tr');
  778. n = td = DOM.add(n, 'td', {'class' : 'mceStatusbar'});
  779. n = DOM.add(n, 'div', {id : ed.id + '_path_row', 'role': 'group', 'aria-labelledby': ed.id + '_path_voice'});
  780. if (s.theme_advanced_path) {
  781. DOM.add(n, 'span', {id: ed.id + '_path_voice'}, ed.translate('advanced.path'));
  782. DOM.add(n, 'span', {}, ': ');
  783. } else {
  784. DOM.add(n, 'span', {}, '&#160;');
  785. }
  786. if (s.theme_advanced_resizing) {
  787. DOM.add(td, 'a', {id : ed.id + '_resize', href : 'javascript:;', onclick : "return false;", 'class' : 'mceResize', tabIndex:"-1"});
  788. if (s.theme_advanced_resizing_use_cookie) {
  789. ed.onPostRender.add(function() {
  790. var o = Cookie.getHash("TinyMCE_" + ed.id + "_size"), c = DOM.get(ed.id + '_tbl');
  791. if (!o)
  792. return;
  793. t.resizeTo(o.cw, o.ch);
  794. });
  795. }
  796. ed.onPostRender.add(function() {
  797. Event.add(ed.id + '_resize', 'click', function(e) {
  798. e.preventDefault();
  799. });
  800. Event.add(ed.id + '_resize', 'mousedown', function(e) {
  801. var mouseMoveHandler1, mouseMoveHandler2,
  802. mouseUpHandler1, mouseUpHandler2,
  803. startX, startY, startWidth, startHeight, width, height, ifrElm;
  804. function resizeOnMove(e) {
  805. e.preventDefault();
  806. width = startWidth + (e.screenX - startX);
  807. height = startHeight + (e.screenY - startY);
  808. t.resizeTo(width, height);
  809. };
  810. function endResize(e) {
  811. // Stop listening
  812. Event.remove(DOM.doc, 'mousemove', mouseMoveHandler1);
  813. Event.remove(ed.getDoc(), 'mousemove', mouseMoveHandler2);
  814. Event.remove(DOM.doc, 'mouseup', mouseUpHandler1);
  815. Event.remove(ed.getDoc(), 'mouseup', mouseUpHandler2);
  816. width = startWidth + (e.screenX - startX);
  817. height = startHeight + (e.screenY - startY);
  818. t.resizeTo(width, height, true);
  819. ed.nodeChanged();
  820. };
  821. e.preventDefault();
  822. // Get the current rect size
  823. startX = e.screenX;
  824. startY = e.screenY;
  825. ifrElm = DOM.get(t.editor.id + '_ifr');
  826. startWidth = width = ifrElm.clientWidth;
  827. startHeight = height = ifrElm.clientHeight;
  828. // Register envent handlers
  829. mouseMoveHandler1 = Event.add(DOM.doc, 'mousemove', resizeOnMove);
  830. mouseMoveHandler2 = Event.add(ed.getDoc(), 'mousemove', resizeOnMove);
  831. mouseUpHandler1 = Event.add(DOM.doc, 'mouseup', endResize);
  832. mouseUpHandler2 = Event.add(ed.getDoc(), 'mouseup', endResize);
  833. });
  834. });
  835. }
  836. o.deltaHeight -= 21;
  837. n = tb = null;
  838. },
  839. _updateUndoStatus : function(ed) {
  840. var cm = ed.controlManager, um = ed.undoManager;
  841. cm.setDisabled('undo', !um.hasUndo() && !um.typing);
  842. cm.setDisabled('redo', !um.hasRedo());
  843. },
  844. _nodeChanged : function(ed, cm, n, co, ob) {
  845. var t = this, p, de = 0, v, c, s = t.settings, cl, fz, fn, fc, bc, formatNames, matches;
  846. tinymce.each(t.stateControls, function(c) {
  847. cm.setActive(c, ed.queryCommandState(t.controls[c][1]));
  848. });
  849. function getParent(name) {
  850. var i, parents = ob.parents, func = name;
  851. if (typeof(name) == 'string') {
  852. func = function(node) {
  853. return node.nodeName == name;
  854. };
  855. }
  856. for (i = 0; i < parents.length; i++) {
  857. if (func(parents[i]))
  858. return parents[i];
  859. }
  860. };
  861. cm.setActive('visualaid', ed.hasVisual);
  862. t._updateUndoStatus(ed);
  863. cm.setDisabled('outdent', !ed.queryCommandState('Outdent'));
  864. p = getParent('A');
  865. if (c = cm.get('link')) {
  866. c.setDisabled((!p && co) || (p && !p.href));
  867. c.setActive(!!p && (!p.name && !p.id));
  868. }
  869. if (c = cm.get('unlink')) {
  870. c.setDisabled(!p && co);
  871. c.setActive(!!p && !p.name && !p.id);
  872. }
  873. if (c = cm.get('anchor')) {
  874. c.setActive(!co && !!p && (p.name || (p.id && !p.href)));
  875. }
  876. p = getParent('IMG');
  877. if (c = cm.get('image'))
  878. c.setActive(!co && !!p && n.className.indexOf('mceItem') == -1);
  879. if (c = cm.get('styleselect')) {
  880. t._importClasses();
  881. formatNames = [];
  882. each(c.items, function(item) {
  883. formatNames.push(item.value);
  884. });
  885. matches = ed.formatter.matchAll(formatNames);
  886. c.select(matches[0]);
  887. tinymce.each(matches, function(match, index) {
  888. if (index > 0) {
  889. c.mark(match);
  890. }
  891. });
  892. }
  893. if (c = cm.get('formatselect')) {
  894. p = getParent(ed.dom.isBlock);
  895. if (p)
  896. c.select(p.nodeName.toLowerCase());
  897. }
  898. // Find out current fontSize, fontFamily and fontClass
  899. getParent(function(n) {
  900. if (n.nodeName === 'SPAN') {
  901. if (!cl && n.className)
  902. cl = n.className;
  903. }
  904. if (ed.dom.is(n, s.theme_advanced_font_selector)) {
  905. if (!fz && n.style.fontSize)
  906. fz = n.style.fontSize;
  907. if (!fn && n.style.fontFamily)
  908. fn = n.style.fontFamily.replace(/[\"\']+/g, '').replace(/^([^,]+).*/, '$1').toLowerCase();
  909. if (!fc && n.style.color)
  910. fc = n.style.color;
  911. if (!bc && n.style.backgroundColor)
  912. bc = n.style.backgroundColor;
  913. }
  914. return false;
  915. });
  916. if (c = cm.get('fontselect')) {
  917. c.select(function(v) {
  918. return v.replace(/^([^,]+).*/, '$1').toLowerCase() == fn;
  919. });
  920. }
  921. // Select font size
  922. if (c = cm.get('fontsizeselect')) {
  923. // Use computed style
  924. if (s.theme_advanced_runtime_fontsize && !fz && !cl)
  925. fz = ed.dom.getStyle(n, 'fontSize', true);
  926. c.select(function(v) {
  927. if (v.fontSize && v.fontSize === fz)
  928. return true;
  929. if (v['class'] && v['class'] === cl)
  930. return true;
  931. });
  932. }
  933. if (s.theme_advanced_show_current_color) {
  934. function updateColor(controlId, color) {
  935. if (c = cm.get(controlId)) {
  936. if (!color)
  937. color = c.settings.default_color;
  938. if (color !== c.value) {
  939. c.displayColor(color);
  940. }
  941. }
  942. }
  943. updateColor('forecolor', fc);
  944. updateColor('backcolor', bc);
  945. }
  946. if (s.theme_advanced_show_current_color) {
  947. function updateColor(controlId, color) {
  948. if (c = cm.get(controlId)) {
  949. if (!color)
  950. color = c.settings.default_color;
  951. if (color !== c.value) {
  952. c.displayColor(color);
  953. }
  954. }
  955. };
  956. updateColor('forecolor', fc);
  957. updateColor('backcolor', bc);
  958. }
  959. if (s.theme_advanced_path && s.theme_advanced_statusbar_location) {
  960. p = DOM.get(ed.id + '_path') || DOM.add(ed.id + '_path_row', 'span', {id : ed.id + '_path'});
  961. if (t.statusKeyboardNavigation) {
  962. t.statusKeyboardNavigation.destroy();
  963. t.statusKeyboardNavigation = null;
  964. }
  965. DOM.setHTML(p, '');
  966. getParent(function(n) {
  967. var na = n.nodeName.toLowerCase(), u, pi, ti = '';
  968. // Ignore non element and bogus/hidden elements
  969. if (n.nodeType != 1 || na === 'br' || n.getAttribute('data-mce-bogus') || DOM.hasClass(n, 'mceItemHidden') || DOM.hasClass(n, 'mceItemRemoved'))
  970. return;
  971. // Handle prefix
  972. if (tinymce.isIE && n.scopeName !== 'HTML' && n.scopeName)
  973. na = n.scopeName + ':' + na;
  974. // Remove internal prefix
  975. na = na.replace(/mce\:/g, '');
  976. // Handle node name
  977. switch (na) {
  978. case 'b':
  979. na = 'strong';
  980. break;
  981. case 'i':
  982. na = 'em';
  983. break;
  984. case 'img':
  985. if (v = DOM.getAttrib(n, 'src'))
  986. ti += 'src: ' + v + ' ';
  987. break;
  988. case 'a':
  989. if (v = DOM.getAttrib(n, 'name')) {
  990. ti += 'name: ' + v + ' ';
  991. na += '#' + v;
  992. }
  993. if (v = DOM.getAttrib(n, 'href'))
  994. ti += 'href: ' + v + ' ';
  995. break;
  996. case 'font':
  997. if (v = DOM.getAttrib(n, 'face'))
  998. ti += 'font: ' + v + ' ';
  999. if (v = DOM.getAttrib(n, 'size'))
  1000. ti += 'size: ' + v + ' ';
  1001. if (v = DOM.getAttrib(n, 'color'))
  1002. ti += 'color: ' + v + ' ';
  1003. break;
  1004. case 'span':
  1005. if (v = DOM.getAttrib(n, 'style'))
  1006. ti += 'style: ' + v + ' ';
  1007. break;
  1008. }
  1009. if (v = DOM.getAttrib(n, 'id'))
  1010. ti += 'id: ' + v + ' ';
  1011. if (v = n.className) {
  1012. v = v.replace(/\b\s*(webkit|mce|Apple-)\w+\s*\b/g, '');
  1013. if (v) {
  1014. ti += 'class: ' + v + ' ';
  1015. if (ed.dom.isBlock(n) || na == 'img' || na == 'span')
  1016. na += '.' + v;
  1017. }
  1018. }
  1019. na = na.replace(/(html:)/g, '');
  1020. na = {name : na, node : n, title : ti};
  1021. t.onResolveName.dispatch(t, na);
  1022. ti = na.title;
  1023. na = na.name;
  1024. //u = "javascript:tinymce.EditorManager.get('" + ed.id + "').theme._sel('" + (de++) + "');";
  1025. pi = DOM.create('a', {'href' : "javascript:;", role: 'button', onmousedown : "return false;", title : ti, 'class' : 'mcePath_' + (de++)}, na);
  1026. if (p.hasChildNodes()) {
  1027. p.insertBefore(DOM.create('span', {'aria-hidden': 'true'}, '\u00a0\u00bb '), p.firstChild);
  1028. p.insertBefore(pi, p.firstChild);
  1029. } else
  1030. p.appendChild(pi);
  1031. }, ed.getBody());
  1032. if (DOM.select('a', p).length > 0) {
  1033. t.statusKeyboardNavigation = new tinymce.ui.KeyboardNavigation({
  1034. root: ed.id + "_path_row",
  1035. items: DOM.select('a', p),
  1036. excludeFromTabOrder: true,
  1037. onCancel: function() {
  1038. ed.focus();
  1039. }
  1040. }, DOM);
  1041. }
  1042. }
  1043. },
  1044. // Commands gets called by execCommand
  1045. _sel : function(v) {
  1046. this.editor.execCommand('mceSelectNodeDepth', false, v);
  1047. },
  1048. _mceInsertAnchor : function(ui, v) {
  1049. var ed = this.editor;
  1050. ed.windowManager.open({
  1051. url : this.url + '/anchor.htm',
  1052. width : 320 + parseInt(ed.getLang('advanced.anchor_delta_width', 0)),
  1053. height : 90 + parseInt(ed.getLang('advanced.anchor_delta_height', 0)),
  1054. inline : true
  1055. }, {
  1056. theme_url : this.url
  1057. });
  1058. },
  1059. _mceCharMap : function() {
  1060. var ed = this.editor;
  1061. ed.windowManager.open({
  1062. url : this.url + '/charmap.htm',
  1063. width : 550 + parseInt(ed.getLang('advanced.charmap_delta_width', 0)),
  1064. height : 265 + parseInt(ed.getLang('advanced.charmap_delta_height', 0)),
  1065. inline : true
  1066. }, {
  1067. theme_url : this.url
  1068. });
  1069. },
  1070. _mceHelp : function() {
  1071. var ed = this.editor;
  1072. ed.windowManager.open({
  1073. url : this.url + '/about.htm',
  1074. width : 480,
  1075. height : 380,
  1076. inline : true
  1077. }, {
  1078. theme_url : this.url
  1079. });
  1080. },
  1081. _mceShortcuts : function() {
  1082. var ed = this.editor;
  1083. ed.windowManager.open({
  1084. url: this.url + '/shortcuts.htm',
  1085. width: 480,
  1086. height: 380,
  1087. inline: true
  1088. }, {
  1089. theme_url: this.url
  1090. });
  1091. },
  1092. _mceColorPicker : function(u, v) {
  1093. var ed = this.editor;
  1094. v = v || {};
  1095. ed.windowManager.open({
  1096. url : this.url + '/color_picker.htm',
  1097. width : 375 + parseInt(ed.getLang('advanced.colorpicker_delta_width', 0)),
  1098. height : 250 + parseInt(ed.getLang('advanced.colorpicker_delta_height', 0)),
  1099. close_previous : false,
  1100. inline : true
  1101. }, {
  1102. input_color : v.color,
  1103. func : v.func,
  1104. theme_url : this.url
  1105. });
  1106. },
  1107. _mceCodeEditor : function(ui, val) {
  1108. var ed = this.editor;
  1109. ed.windowManager.open({
  1110. url : this.url + '/source_editor.htm',
  1111. width : parseInt(ed.getParam("theme_advanced_source_editor_width", 720)),
  1112. height : parseInt(ed.getParam("theme_advanced_source_editor_height", 580)),
  1113. inline : true,
  1114. resizable : true,
  1115. maximizable : true
  1116. }, {
  1117. theme_url : this.url
  1118. });
  1119. },
  1120. _mceImage : function(ui, val) {
  1121. var ed = this.editor;
  1122. // Internal image object like a flash placeholder
  1123. if (ed.dom.getAttrib(ed.selection.getNode(), 'class', '').indexOf('mceItem') != -1)
  1124. return;
  1125. ed.windowManager.open({
  1126. url : this.url + '/image.htm',
  1127. width : 355 + parseInt(ed.getLang('advanced.image_delta_width', 0)),
  1128. height : 275 + parseInt(ed.getLang('advanced.image_delta_height', 0)),
  1129. inline : true
  1130. }, {
  1131. theme_url : this.url
  1132. });
  1133. },
  1134. _mceLink : function(ui, val) {
  1135. var ed = this.editor;
  1136. ed.windowManager.open({
  1137. url : this.url + '/link.htm',
  1138. width : 310 + parseInt(ed.getLang('advanced.link_delta_width', 0)),
  1139. height : 200 + parseInt(ed.getLang('advanced.link_delta_height', 0)),
  1140. inline : true
  1141. }, {
  1142. theme_url : this.url
  1143. });
  1144. },
  1145. _mceNewDocument : function() {
  1146. var ed = this.editor;
  1147. ed.windowManager.confirm('advanced.newdocument', function(s) {
  1148. if (s)
  1149. ed.execCommand('mceSetContent', false, '');
  1150. });
  1151. },
  1152. _mceForeColor : function() {
  1153. var t = this;
  1154. this._mceColorPicker(0, {
  1155. color: t.fgColor,
  1156. func : function(co) {
  1157. t.fgColor = co;
  1158. t.editor.execCommand('ForeColor', false, co);
  1159. }
  1160. });
  1161. },
  1162. _mceBackColor : function() {
  1163. var t = this;
  1164. this._mceColorPicker(0, {
  1165. color: t.bgColor,
  1166. func : function(co) {
  1167. t.bgColor = co;
  1168. t.editor.execCommand('HiliteColor', false, co);
  1169. }
  1170. });
  1171. },
  1172. _ufirst : function(s) {
  1173. return s.substring(0, 1).toUpperCase() + s.substring(1);
  1174. }
  1175. });
  1176. tinymce.ThemeManager.add('advanced', tinymce.themes.AdvancedTheme);
  1177. }(tinymce));