Upgrade TinyMCE to v3.4.5
[citadel.git] / webcit / tiny_mce / themes / advanced / editor_template_src.js
index b3cef0199bd93e9357f6e2edab30d923c8f4dde9..bee26e161025b55d7efa965e4dcf449c300f26f9 100644 (file)
@@ -1,11 +1,14 @@
 /**\r
- * $Id: editor_template_src.js 960 2008-11-12 18:30:32Z spocke $\r
+ * editor_template_src.js\r
  *\r
- * @author Moxiecode\r
- * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.\r
+ * Copyright 2009, Moxiecode Systems AB\r
+ * Released under LGPL License.\r
+ *\r
+ * License: http://tinymce.moxiecode.com/license\r
+ * Contributing: http://tinymce.moxiecode.com/contributing\r
  */\r
 \r
-(function() {\r
+(function(tinymce) {\r
        var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, each = tinymce.each, Cookie = tinymce.util.Cookie, lastExtID, explode = tinymce.explode;\r
 \r
        // Tell it to load theme specific language pack(s)\r
@@ -63,6 +66,9 @@
                        t.url = url;\r
                        t.onResolveName = new tinymce.util.Dispatcher(this);\r
 \r
+                       ed.forcedHighContrastMode = ed.settings.detect_highcontrast && t._isHighContrast();\r
+                       ed.settings.skin = ed.forcedHighContrastMode ? 'highcontrast' : ed.settings.skin;\r
+\r
                        // Default settings\r
                        t.settings = s = extend({\r
                                theme_advanced_path : true,\r
@@ -78,6 +84,8 @@
                                theme_advanced_resize_horizontal : 1,\r
                                theme_advanced_resizing_use_cookie : 1,\r
                                theme_advanced_font_sizes : "1,2,3,4,5,6,7",\r
+                               theme_advanced_font_selector : "span",\r
+                               theme_advanced_show_current_color: 0,\r
                                readonly : ed.settings.readonly\r
                        }, ed.settings);\r
 \r
 \r
                                        if (k == v && v >= 1 && v <= 7) {\r
                                                k = v + ' (' + t.sizes[v - 1] + 'pt)';\r
-\r
-                                               if (ed.settings.convert_fonts_to_spans) {\r
-                                                       cl = s.font_size_classes[v - 1];\r
-                                                       v = s.font_size_style_values[v - 1] || (t.sizes[v - 1] + 'pt');\r
-                                               }\r
+                                               cl = s.font_size_classes[v - 1];\r
+                                               v = s.font_size_style_values[v - 1] || (t.sizes[v - 1] + 'pt');\r
                                        }\r
 \r
-                                       if (/\s*\./.test(v))\r
+                                       if (/^\s*\./.test(v))\r
                                                cl = v.replace(/\./g, '');\r
 \r
                                        o[k] = cl ? {'class' : cl} : {fontSize : v};\r
                        if (s.theme_advanced_statusbar_location == 'none')\r
                                s.theme_advanced_statusbar_location = 0;\r
 \r
+                       if (ed.settings.content_css !== false)\r
+                               ed.contentCSS.push(ed.baseURI.toAbsolute(url + "/skins/" + ed.settings.skin + "/content.css"));\r
+\r
                        // Init editor\r
                        ed.onInit.add(function() {\r
-                               ed.onNodeChange.add(t._nodeChanged, t);\r
-\r
-                               if (ed.settings.content_css !== false)\r
-                                       ed.dom.loadCSS(ed.baseURI.toAbsolute("themes/advanced/skins/" + ed.settings.skin + "/content.css"));\r
+                               if (!ed.settings.readonly) {\r
+                                       ed.onNodeChange.add(t._nodeChanged, t);\r
+                                       ed.onKeyUp.add(t._updateUndoStatus, t);\r
+                                       ed.onMouseUp.add(t._updateUndoStatus, t);\r
+                                       ed.dom.bind(ed.dom.getRoot(), 'dragend', function() {\r
+                                               t._updateUndoStatus(ed);\r
+                                       });\r
+                               }\r
                        });\r
 \r
                        ed.onSetProgressState.add(function(ed, b, ti) {\r
                                DOM.loadCSS(url + "/skins/" + ed.settings.skin + "/ui_" + s.skin_variant + ".css");\r
                },\r
 \r
+               _isHighContrast : function() {\r
+                       var actualColor, div = DOM.add(DOM.getRoot(), 'div', {'style': 'background-color: rgb(171,239,86);'});\r
+\r
+                       actualColor = (DOM.getStyle(div, 'background-color', true) + '').toLowerCase().replace(/ /g, '');\r
+                       DOM.remove(div);\r
+\r
+                       return actualColor != 'rgb(171,239,86)' && actualColor != '#abef56';\r
+               },\r
+\r
                createControl : function(n, cf) {\r
                        var cd, c;\r
 \r
                },\r
 \r
                _importClasses : function(e) {\r
-                       var ed = this.editor, c = ed.controlManager.get('styleselect');\r
+                       var ed = this.editor, ctrl = ed.controlManager.get('styleselect');\r
+\r
+                       if (ctrl.getLength() == 0) {\r
+                               each(ed.dom.getClasses(), function(o, idx) {\r
+                                       var name = 'style_' + idx;\r
+\r
+                                       ed.formatter.register(name, {\r
+                                               inline : 'span',\r
+                                               attributes : {'class' : o['class']},\r
+                                               selector : '*'\r
+                                       });\r
 \r
-                       if (c.getLength() == 0) {\r
-                               each(ed.dom.getClasses(), function(o) {\r
-                                       c.add(o['class'], o['class']);\r
+                                       ctrl.add(o['class'], name);\r
                                });\r
                        }\r
                },\r
 \r
                _createStyleSelect : function(n) {\r
-                       var t = this, ed = t.editor, cf = ed.controlManager, c = cf.createListBox('styleselect', {\r
+                       var t = this, ed = t.editor, ctrlMan = ed.controlManager, ctrl;\r
+\r
+                       // Setup style select box\r
+                       ctrl = ctrlMan.createListBox('styleselect', {\r
                                title : 'advanced.style_select',\r
-                               onselect : function(v) {\r
-                                       if (c.selectedValue === v) {\r
-                                               ed.execCommand('mceSetStyleInfo', 0, {command : 'removeformat'});\r
-                                               c.select();\r
-                                               return false;\r
+                               onselect : function(name) {\r
+                                       var matches, formatNames = [];\r
+\r
+                                       each(ctrl.items, function(item) {\r
+                                               formatNames.push(item.value);\r
+                                       });\r
+\r
+                                       ed.focus();\r
+                                       ed.undoManager.add();\r
+\r
+                                       // Toggle off the current format\r
+                                       matches = ed.formatter.matchAll(formatNames);\r
+                                       if (!name || matches[0] == name) {\r
+                                               if (matches[0]) \r
+                                                       ed.formatter.remove(matches[0]);\r
                                        } else\r
-                                               ed.execCommand('mceSetCSSClass', 0, v);\r
+                                               ed.formatter.apply(name);\r
+\r
+                                       ed.undoManager.add();\r
+                                       ed.nodeChanged();\r
+\r
+                                       return false; // No auto select\r
                                }\r
                        });\r
 \r
-                       if (c) {\r
-                               each(ed.getParam('theme_advanced_styles', '', 'hash'), function(v, k) {\r
-                                       if (v)\r
-                                               c.add(t.editor.translate(k), v);\r
-                               });\r
+                       // Handle specified format\r
+                       ed.onInit.add(function() {\r
+                               var counter = 0, formats = ed.getParam('style_formats');\r
+\r
+                               if (formats) {\r
+                                       each(formats, function(fmt) {\r
+                                               var name, keys = 0;\r
+\r
+                                               each(fmt, function() {keys++;});\r
+\r
+                                               if (keys > 1) {\r
+                                                       name = fmt.name = fmt.name || 'style_' + (counter++);\r
+                                                       ed.formatter.register(name, fmt);\r
+                                                       ctrl.add(fmt.title, name);\r
+                                               } else\r
+                                                       ctrl.add(fmt.title);\r
+                                       });\r
+                               } else {\r
+                                       each(ed.getParam('theme_advanced_styles', '', 'hash'), function(val, key) {\r
+                                               var name;\r
+\r
+                                               if (val) {\r
+                                                       name = 'style_' + (counter++);\r
+\r
+                                                       ed.formatter.register(name, {\r
+                                                               inline : 'span',\r
+                                                               classes : val,\r
+                                                               selector : '*'\r
+                                                       });\r
+\r
+                                                       ctrl.add(t.editor.translate(key), name);\r
+                                               }\r
+                                       });\r
+                               }\r
+                       });\r
 \r
-                               c.onPostRender.add(function(ed, n) {\r
-                                       if (!c.NativeListBox) {\r
+                       // Auto import classes if the ctrl box is empty\r
+                       if (ctrl.getLength() == 0) {\r
+                               ctrl.onPostRender.add(function(ed, n) {\r
+                                       if (!ctrl.NativeListBox) {\r
                                                Event.add(n.id + '_text', 'focus', t._importClasses, t);\r
                                                Event.add(n.id + '_text', 'mousedown', t._importClasses, t);\r
                                                Event.add(n.id + '_open', 'focus', t._importClasses, t);\r
                                });\r
                        }\r
 \r
-                       return c;\r
+                       return ctrl;\r
                },\r
 \r
                _createFontSelect : function() {\r
                        var c, t = this, ed = t.editor;\r
 \r
-                       c = ed.controlManager.createListBox('fontselect', {title : 'advanced.fontdefault', cmd : 'FontName'});\r
+                       c = ed.controlManager.createListBox('fontselect', {\r
+                               title : 'advanced.fontdefault',\r
+                               onselect : function(v) {\r
+                                       var cur = c.items[c.selectedIndex];\r
+\r
+                                       if (!v && cur) {\r
+                                               ed.execCommand('FontName', false, cur.value);\r
+                                               return;\r
+                                       }\r
+\r
+                                       ed.execCommand('FontName', false, v);\r
+\r
+                                       // Fake selection, execCommand will fire a nodeChange and update the selection\r
+                                       c.select(function(sv) {\r
+                                               return v == sv;\r
+                                       });\r
+\r
+                                       if (cur && cur.value == v) {\r
+                                               c.select(null);\r
+                                       }\r
+\r
+                                       return false; // No auto select\r
+                               }\r
+                       });\r
+\r
                        if (c) {\r
                                each(ed.getParam('theme_advanced_fonts', t.settings.theme_advanced_fonts, 'hash'), function(v, k) {\r
                                        c.add(ed.translate(k), v, {style : v.indexOf('dings') == -1 ? 'font-family:' + v : ''});\r
                        var t = this, ed = t.editor, c, i = 0, cl = [];\r
 \r
                        c = ed.controlManager.createListBox('fontsizeselect', {title : 'advanced.font_size', onselect : function(v) {\r
-                               if (v.fontSize)\r
+                               var cur = c.items[c.selectedIndex];\r
+\r
+                               if (!v && cur) {\r
+                                       cur = cur.value;\r
+\r
+                                       if (cur['class']) {\r
+                                               ed.formatter.toggle('fontsize_class', {value : cur['class']});\r
+                                               ed.undoManager.add();\r
+                                               ed.nodeChanged();\r
+                                       } else {\r
+                                               ed.execCommand('FontSize', false, cur.fontSize);\r
+                                       }\r
+\r
+                                       return;\r
+                               }\r
+\r
+                               if (v['class']) {\r
+                                       ed.focus();\r
+                                       ed.undoManager.add();\r
+                                       ed.formatter.toggle('fontsize_class', {value : v['class']});\r
+                                       ed.undoManager.add();\r
+                                       ed.nodeChanged();\r
+                               } else\r
                                        ed.execCommand('FontSize', false, v.fontSize);\r
-                               else {\r
-                                       each(t.settings.theme_advanced_font_sizes, function(v, k) {\r
-                                               if (v['class'])\r
-                                                       cl.push(v['class']);\r
-                                       });\r
 \r
-                                       ed.editorCommands._applyInlineStyle('span', {'class' : v['class']}, {check_classes : cl});\r
+                               // Fake selection, execCommand will fire a nodeChange and update the selection\r
+                               c.select(function(sv) {\r
+                                       return v == sv;\r
+                               });\r
+\r
+                               if (cur && (cur.value.fontSize == v.fontSize || cur.value['class'] == v['class'])) {\r
+                                       c.select(null);\r
                                }\r
+\r
+                               return false; // No auto select\r
                        }});\r
 \r
                        if (c) {\r
                                samp : 'advanced.samp'\r
                        }, t = this;\r
 \r
-                       c = t.editor.controlManager.createListBox('formatselect', {title : 'advanced.block', cmd : 'FormatBlock'});\r
+                       c = t.editor.controlManager.createListBox('formatselect', {title : 'advanced.block', onselect : function(v) {\r
+                               t.editor.execCommand('FormatBlock', false, v);\r
+                               return false;\r
+                       }});\r
+\r
                        if (c) {\r
                                each(t.editor.getParam('theme_advanced_blockformats', t.settings.theme_advanced_blockformats, 'hash'), function(v, k) {\r
                                        c.add(t.editor.translate(k != v ? k : fmts[v]), v, {'class' : 'mce_formatPreview mce_' + v});\r
                renderUI : function(o) {\r
                        var n, ic, tb, t = this, ed = t.editor, s = t.settings, sc, p, nl;\r
 \r
-                       n = p = DOM.create('span', {id : ed.id + '_parent', 'class' : 'mceEditor ' + ed.settings.skin + 'Skin' + (s.skin_variant ? ' ' + ed.settings.skin + 'Skin' + t._ufirst(s.skin_variant) : '')});\r
+                       if (ed.settings) {\r
+                               ed.settings.aria_label = s.aria_label + ed.getLang('advanced.help_shortcut');\r
+                       }\r
+\r
+                       // TODO: ACC Should have an aria-describedby attribute which is user-configurable to describe what this field is actually for.\r
+                       // Maybe actually inherit it from the original textara?\r
+                       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) : '')});\r
+                       DOM.add(n, 'span', {'class': 'mceVoiceLabel', 'style': 'display:none;', id: ed.id + '_voice'}, s.aria_label);\r
 \r
                        if (!DOM.boxModel)\r
                                n = DOM.add(n, 'div', {'class' : 'mceOldBoxModel'});\r
 \r
-                       n = sc = DOM.add(n, 'table', {id : ed.id + '_tbl', 'class' : 'mceLayout', cellSpacing : 0, cellPadding : 0});\r
+                       n = sc = DOM.add(n, 'table', {role : "presentation", id : ed.id + '_tbl', 'class' : 'mceLayout', cellSpacing : 0, cellPadding : 0});\r
                        n = tb = DOM.add(n, 'tbody');\r
 \r
                        switch ((s.theme_advanced_layout_manager || '').toLowerCase()) {\r
                        n = o.targetNode;\r
 \r
                        // Add classes to first and last TRs\r
-                       nl = DOM.stdMode ? sc.getElementsByTagName('tr') : sc.rows; // Quick fix for IE 8\r
+                       nl = sc.rows;\r
                        DOM.addClass(nl[0], 'mceFirst');\r
                        DOM.addClass(nl[nl.length - 1], 'mceLast');\r
 \r
                        }\r
 */\r
 \r
-                       if (!ed.getParam('accessibility_focus') || ed.getParam('tab_focus'))\r
+                       if (!ed.getParam('accessibility_focus'))\r
                                Event.add(DOM.add(p, 'a', {href : '#'}, '<!-- IE -->'), 'focus', function() {tinyMCE.get(ed.id).focus();});\r
 \r
                        if (s.theme_advanced_toolbar_location == 'external')\r
                        t.deltaHeight = o.deltaHeight;\r
                        o.targetNode = null;\r
 \r
+                       ed.onKeyDown.add(function(ed, evt) {\r
+                               var DOM_VK_F10 = 121, DOM_VK_F11 = 122;\r
+\r
+                               if (evt.altKey) {\r
+                                       if (evt.keyCode === DOM_VK_F10) {\r
+                                               window.focus();\r
+                                               t.toolbarGroup.focus();\r
+                                               return Event.cancel(evt);\r
+                                       } else if (evt.keyCode === DOM_VK_F11) {\r
+                                               DOM.get(ed.id + '_path_row').focus();\r
+                                               return Event.cancel(evt);\r
+                                       }\r
+                               }\r
+                       });\r
+\r
+                       // alt+0 is the UK recommended shortcut for accessing the list of access controls.\r
+                       ed.addShortcut('alt+0', '', 'mceShortcuts', t);\r
+\r
                        return {\r
                                iframeContainer : ic,\r
                                editorContainer : ed.id + '_parent',\r
                },\r
 \r
                resizeBy : function(dw, dh) {\r
-                       var e = DOM.get(this.editor.id + '_tbl');\r
+                       var e = DOM.get(this.editor.id + '_ifr');\r
 \r
                        this.resizeTo(e.clientWidth + dw, e.clientHeight + dh);\r
                },\r
 \r
-               resizeTo : function(w, h) {\r
-                       var ed = this.editor, s = ed.settings, e = DOM.get(ed.id + '_tbl'), ifr = DOM.get(ed.id + '_ifr'), dh;\r
+               resizeTo : function(w, h, store) {\r
+                       var ed = this.editor, s = this.settings, e = DOM.get(ed.id + '_tbl'), ifr = DOM.get(ed.id + '_ifr');\r
 \r
                        // Boundery fix box\r
                        w = Math.max(s.theme_advanced_resizing_min_width || 100, w);\r
                        w = Math.min(s.theme_advanced_resizing_max_width || 0xFFFF, w);\r
                        h = Math.min(s.theme_advanced_resizing_max_height || 0xFFFF, h);\r
 \r
-                       // Calc difference between iframe and container\r
-                       dh = e.clientHeight - ifr.clientHeight;\r
-\r
                        // Resize iframe and container\r
-                       DOM.setStyle(ifr, 'height', h - dh);\r
-                       DOM.setStyles(e, {width : w, height : h});\r
+                       DOM.setStyle(e, 'height', '');\r
+                       DOM.setStyle(ifr, 'height', h);\r
+\r
+                       if (s.theme_advanced_resize_horizontal) {\r
+                               DOM.setStyle(e, 'width', '');\r
+                               DOM.setStyle(ifr, 'width', w);\r
+\r
+                               // Make sure that the size is never smaller than the over all ui\r
+                               if (w < e.clientWidth) {\r
+                                       w = e.clientWidth;\r
+                                       DOM.setStyle(ifr, 'width', e.clientWidth);\r
+                               }\r
+                       }\r
+\r
+                       // Store away the size\r
+                       if (store && s.theme_advanced_resizing_use_cookie) {\r
+                               Cookie.setHash("TinyMCE_" + ed.id + "_size", {\r
+                                       cw : w,\r
+                                       ch : h\r
+                               });\r
+                       }\r
                },\r
 \r
                destroy : function() {\r
                        each(explode(s.theme_advanced_containers || ''), function(c, i) {\r
                                var v = s['theme_advanced_container_' + c] || '';\r
 \r
-                               switch (v.toLowerCase()) {\r
+                               switch (c.toLowerCase()) {\r
                                        case 'mceeditor':\r
                                                n = DOM.add(tb, 'tr');\r
                                                n = ic = DOM.add(n, 'td', {'class' : 'mceIframeContainer'});\r
                },\r
 \r
                _addToolbars : function(c, o) {\r
-                       var t = this, i, tb, ed = t.editor, s = t.settings, v, cf = ed.controlManager, di, n, h = [], a;\r
+                       var t = this, i, tb, ed = t.editor, s = t.settings, v, cf = ed.controlManager, di, n, h = [], a, toolbarGroup;\r
 \r
-                       a = s.theme_advanced_toolbar_align.toLowerCase();\r
-                       a = 'mce' + t._ufirst(a);\r
+                       toolbarGroup = cf.createToolbarGroup('toolbargroup', {\r
+                               'name': ed.getLang('advanced.toolbar'),\r
+                               'tab_focus_toolbar':ed.getParam('theme_advanced_tab_focus_toolbar')\r
+                       });\r
 \r
-                       n = DOM.add(DOM.add(c, 'tr'), 'td', {'class' : 'mceToolbar ' + a});\r
+                       t.toolbarGroup = toolbarGroup;\r
 \r
-                       if (!ed.getParam('accessibility_focus') || ed.getParam('tab_focus'))\r
-                               h.push(DOM.createHTML('a', {href : '#', onfocus : 'tinyMCE.get(\'' + ed.id + '\').focus();'}, '<!-- IE -->'));\r
+                       a = s.theme_advanced_toolbar_align.toLowerCase();\r
+                       a = 'mce' + t._ufirst(a);\r
 \r
-                       h.push(DOM.createHTML('a', {href : '#', accesskey : 'q', title : ed.getLang("advanced.toolbar_focus")}, '<!-- IE -->'));\r
+                       n = DOM.add(DOM.add(c, 'tr', {role: 'presentation'}), 'td', {'class' : 'mceToolbar ' + a, "role":"presentation"});\r
 \r
                        // Create toolbar and add the controls\r
                        for (i=1; (v = s['theme_advanced_buttons' + i]); i++) {\r
                                        v = s['theme_advanced_buttons' + i + '_add_before'] + ',' + v;\r
 \r
                                t._addControls(v, tb);\r
-\r
-                               //n.appendChild(n = tb.render());\r
-                               h.push(tb.renderHTML());\r
+                               toolbarGroup.add(tb);\r
 \r
                                o.deltaHeight -= s.theme_advanced_row_height;\r
                        }\r
-\r
+                       h.push(toolbarGroup.renderHTML());\r
                        h.push(DOM.createHTML('a', {href : '#', accesskey : 'z', title : ed.getLang("advanced.toolbar_focus"), onfocus : 'tinyMCE.getInstanceById(\'' + ed.id + '\').focus();'}, '<!-- IE -->'));\r
                        DOM.setHTML(n, h.join(''));\r
                },\r
                        var n, t = this, ed = t.editor, s = t.settings, r, mf, me, td;\r
 \r
                        n = DOM.add(tb, 'tr');\r
-                       n = td = DOM.add(n, 'td', {'class' : 'mceStatusbar'});\r
-                       n = DOM.add(n, 'div', {id : ed.id + '_path_row'}, s.theme_advanced_path ? ed.translate('advanced.path') + ': ' : '&nbsp;');\r
-                       DOM.add(n, 'a', {href : '#', accesskey : 'x'});\r
+                       n = td = DOM.add(n, 'td', {'class' : 'mceStatusbar'}); \r
+                       n = DOM.add(n, 'div', {id : ed.id + '_path_row', 'role': 'group', 'aria-labelledby': ed.id + '_path_voice'});\r
+                       if (s.theme_advanced_path) {\r
+                               DOM.add(n, 'span', {id: ed.id + '_path_voice'}, ed.translate('advanced.path'));\r
+                               DOM.add(n, 'span', {}, ': ');\r
+                       } else {\r
+                               DOM.add(n, 'span', {}, '&#160;');\r
+                       }\r
+                       \r
 \r
-                       if (s.theme_advanced_resizing && !tinymce.isOldWebKit) {\r
-                               DOM.add(td, 'a', {id : ed.id + '_resize', href : 'javascript:;', onclick : "return false;", 'class' : 'mceResize'});\r
+                       if (s.theme_advanced_resizing) {\r
+                               DOM.add(td, 'a', {id : ed.id + '_resize', href : 'javascript:;', onclick : "return false;", 'class' : 'mceResize', tabIndex:"-1"});\r
 \r
                                if (s.theme_advanced_resizing_use_cookie) {\r
                                        ed.onPostRender.add(function() {\r
                                                if (!o)\r
                                                        return;\r
 \r
-                                               if (s.theme_advanced_resize_horizontal)\r
-                                                       c.style.width = Math.max(10, o.cw) + 'px';\r
-\r
-                                               c.style.height = Math.max(10, o.ch) + 'px';\r
-                                               DOM.get(ed.id + '_ifr').style.height = Math.max(10, parseInt(o.ch) + t.deltaHeight) + 'px';\r
+                                               t.resizeTo(o.cw, o.ch);\r
                                        });\r
                                }\r
 \r
                                ed.onPostRender.add(function() {\r
-                                       Event.add(ed.id + '_resize', 'mousedown', function(e) {\r
-                                               var c, p, w, h, n, pa;\r
-\r
-                                               // Measure container\r
-                                               c = DOM.get(ed.id + '_tbl');\r
-                                               w = c.clientWidth;\r
-                                               h = c.clientHeight;\r
-\r
-                                               miw = s.theme_advanced_resizing_min_width || 100;\r
-                                               mih = s.theme_advanced_resizing_min_height || 100;\r
-                                               maw = s.theme_advanced_resizing_max_width || 0xFFFF;\r
-                                               mah = s.theme_advanced_resizing_max_height || 0xFFFF;\r
-\r
-                                               // Setup placeholder\r
-                                               p = DOM.add(DOM.get(ed.id + '_parent'), 'div', {'class' : 'mcePlaceHolder'});\r
-                                               DOM.setStyles(p, {width : w, height : h});\r
-\r
-                                               // Replace with placeholder\r
-                                               DOM.hide(c);\r
-                                               DOM.show(p);\r
-\r
-                                               // Create internal resize obj\r
-                                               r = {\r
-                                                       x : e.screenX,\r
-                                                       y : e.screenY,\r
-                                                       w : w,\r
-                                                       h : h,\r
-                                                       dx : null,\r
-                                                       dy : null\r
-                                               };\r
-\r
-                                               // Start listening\r
-                                               mf = Event.add(DOM.doc, 'mousemove', function(e) {\r
-                                                       var w, h;\r
-\r
-                                                       // Calc delta values\r
-                                                       r.dx = e.screenX - r.x;\r
-                                                       r.dy = e.screenY - r.y;\r
-\r
-                                                       // Boundery fix box\r
-                                                       w = Math.max(miw, r.w + r.dx);\r
-                                                       h = Math.max(mih, r.h + r.dy);\r
-                                                       w = Math.min(maw, w);\r
-                                                       h = Math.min(mah, h);\r
+                                       Event.add(ed.id + '_resize', 'click', function(e) {\r
+                                               e.preventDefault();\r
+                                       });\r
 \r
-                                                       // Resize placeholder\r
-                                                       if (s.theme_advanced_resize_horizontal)\r
-                                                               p.style.width = w + 'px';\r
+                                       Event.add(ed.id + '_resize', 'mousedown', function(e) {\r
+                                               var mouseMoveHandler1, mouseMoveHandler2,\r
+                                                       mouseUpHandler1, mouseUpHandler2,\r
+                                                       startX, startY, startWidth, startHeight, width, height, ifrElm;\r
 \r
-                                                       p.style.height = h + 'px';\r
+                                               function resizeOnMove(e) {\r
+                                                       e.preventDefault();\r
 \r
-                                                       return Event.cancel(e);\r
-                                               });\r
+                                                       width = startWidth + (e.screenX - startX);\r
+                                                       height = startHeight + (e.screenY - startY);\r
 \r
-                                               me = Event.add(DOM.doc, 'mouseup', function(e) {\r
-                                                       var ifr;\r
+                                                       t.resizeTo(width, height);\r
+                                               };\r
 \r
+                                               function endResize(e) {\r
                                                        // Stop listening\r
-                                                       Event.remove(DOM.doc, 'mousemove', mf);\r
-                                                       Event.remove(DOM.doc, 'mouseup', me);\r
-\r
-                                                       c.style.display = '';\r
-                                                       DOM.remove(p);\r
-\r
-                                                       if (r.dx === null)\r
-                                                               return;\r
-\r
-                                                       ifr = DOM.get(ed.id + '_ifr');\r
-\r
-                                                       if (s.theme_advanced_resize_horizontal)\r
-                                                               c.style.width = Math.max(10, r.w + r.dx) + 'px';\r
+                                                       Event.remove(DOM.doc, 'mousemove', mouseMoveHandler1);\r
+                                                       Event.remove(ed.getDoc(), 'mousemove', mouseMoveHandler2);\r
+                                                       Event.remove(DOM.doc, 'mouseup', mouseUpHandler1);\r
+                                                       Event.remove(ed.getDoc(), 'mouseup', mouseUpHandler2);\r
+\r
+                                                       width = startWidth + (e.screenX - startX);\r
+                                                       height = startHeight + (e.screenY - startY);\r
+                                                       t.resizeTo(width, height, true);\r
+                                               };\r
 \r
-                                                       c.style.height = Math.max(10, r.h + r.dy) + 'px';\r
-                                                       ifr.style.height = Math.max(10, ifr.clientHeight + r.dy) + 'px';\r
+                                               e.preventDefault();\r
 \r
-                                                       if (s.theme_advanced_resizing_use_cookie) {\r
-                                                               Cookie.setHash("TinyMCE_" + ed.id + "_size", {\r
-                                                                       cw : r.w + r.dx,\r
-                                                                       ch : r.h + r.dy\r
-                                                               });\r
-                                                       }\r
-                                               });\r
+                                               // Get the current rect size\r
+                                               startX = e.screenX;\r
+                                               startY = e.screenY;\r
+                                               ifrElm = DOM.get(t.editor.id + '_ifr');\r
+                                               startWidth = width = ifrElm.clientWidth;\r
+                                               startHeight = height = ifrElm.clientHeight;\r
 \r
-                                               return Event.cancel(e);\r
+                                               // Register envent handlers\r
+                                               mouseMoveHandler1 = Event.add(DOM.doc, 'mousemove', resizeOnMove);\r
+                                               mouseMoveHandler2 = Event.add(ed.getDoc(), 'mousemove', resizeOnMove);\r
+                                               mouseUpHandler1 = Event.add(DOM.doc, 'mouseup', endResize);\r
+                                               mouseUpHandler2 = Event.add(ed.getDoc(), 'mouseup', endResize);\r
                                        });\r
                                });\r
                        }\r
                        n = tb = null;\r
                },\r
 \r
-               _nodeChanged : function(ed, cm, n, co) {\r
-                       var t = this, p, de = 0, v, c, s = t.settings, cl, fz, fn;\r
+               _updateUndoStatus : function(ed) {\r
+                       var cm = ed.controlManager, um = ed.undoManager;\r
 \r
-                       if (s.readonly)\r
-                               return;\r
+                       cm.setDisabled('undo', !um.hasUndo() && !um.typing);\r
+                       cm.setDisabled('redo', !um.hasRedo());\r
+               },\r
+\r
+               _nodeChanged : function(ed, cm, n, co, ob) {\r
+                       var t = this, p, de = 0, v, c, s = t.settings, cl, fz, fn, fc, bc, formatNames, matches;\r
 \r
                        tinymce.each(t.stateControls, function(c) {\r
                                cm.setActive(c, ed.queryCommandState(t.controls[c][1]));\r
                        });\r
 \r
+                       function getParent(name) {\r
+                               var i, parents = ob.parents, func = name;\r
+\r
+                               if (typeof(name) == 'string') {\r
+                                       func = function(node) {\r
+                                               return node.nodeName == name;\r
+                                       };\r
+                               }\r
+\r
+                               for (i = 0; i < parents.length; i++) {\r
+                                       if (func(parents[i]))\r
+                                               return parents[i];\r
+                               }\r
+                       };\r
+\r
                        cm.setActive('visualaid', ed.hasVisual);\r
-                       cm.setDisabled('undo', !ed.undoManager.hasUndo() && !ed.typing);\r
-                       cm.setDisabled('redo', !ed.undoManager.hasRedo());\r
+                       t._updateUndoStatus(ed);\r
                        cm.setDisabled('outdent', !ed.queryCommandState('Outdent'));\r
 \r
-                       p = DOM.getParent(n, 'A');\r
+                       p = getParent('A');\r
                        if (c = cm.get('link')) {\r
                                if (!p || !p.name) {\r
                                        c.setDisabled(!p && co);\r
                        }\r
 \r
                        if (c = cm.get('anchor')) {\r
-                               c.setActive(!!p && p.name);\r
-\r
-                               if (tinymce.isWebKit) {\r
-                                       p = DOM.getParent(n, 'IMG');\r
-                                       c.setActive(!!p && DOM.getAttrib(p, 'mce_name') == 'a');\r
-                               }\r
+                               c.setActive(!co && !!p && p.name);\r
                        }\r
 \r
-                       p = DOM.getParent(n, 'IMG');\r
+                       p = getParent('IMG');\r
                        if (c = cm.get('image'))\r
-                               c.setActive(!!p && n.className.indexOf('mceItem') == -1);\r
+                               c.setActive(!co && !!p && n.className.indexOf('mceItem') == -1);\r
 \r
                        if (c = cm.get('styleselect')) {\r
-                               if (n.className) {\r
-                                       t._importClasses();\r
-                                       c.select(n.className);\r
-                               } else\r
-                                       c.select();\r
+                               t._importClasses();\r
+\r
+                               formatNames = [];\r
+                               each(c.items, function(item) {\r
+                                       formatNames.push(item.value);\r
+                               });\r
+\r
+                               matches = ed.formatter.matchAll(formatNames);\r
+                               c.select(matches[0]);\r
                        }\r
 \r
                        if (c = cm.get('formatselect')) {\r
-                               p = DOM.getParent(n, DOM.isBlock);\r
+                               p = getParent(DOM.isBlock);\r
 \r
                                if (p)\r
                                        c.select(p.nodeName.toLowerCase());\r
                        }\r
 \r
-                       if (ed.settings.convert_fonts_to_spans) {\r
-                               ed.dom.getParent(n, function(n) {\r
-                                       if (n.nodeName === 'SPAN') {\r
-                                               if (!cl && n.className)\r
-                                                       cl = n.className;\r
+                       // Find out current fontSize, fontFamily and fontClass\r
+                       getParent(function(n) {\r
+                               if (n.nodeName === 'SPAN') {\r
+                                       if (!cl && n.className)\r
+                                               cl = n.className;\r
+                               }\r
 \r
-                                               if (!fz && n.style.fontSize)\r
-                                                       fz = n.style.fontSize;\r
+                               if (ed.dom.is(n, s.theme_advanced_font_selector)) {\r
+                                       if (!fz && n.style.fontSize)\r
+                                               fz = n.style.fontSize;\r
 \r
-                                               if (!fn && n.style.fontFamily)\r
-                                                       fn = n.style.fontFamily.replace(/[\"\']+/g, '').replace(/^([^,]+).*/, '$1').toLowerCase();\r
-                                       }\r
+                                       if (!fn && n.style.fontFamily)\r
+                                               fn = n.style.fontFamily.replace(/[\"\']+/g, '').replace(/^([^,]+).*/, '$1').toLowerCase();\r
+                                       \r
+                                       if (!fc && n.style.color)\r
+                                               fc = n.style.color;\r
 \r
-                                       return false;\r
+                                       if (!bc && n.style.backgroundColor)\r
+                                               bc = n.style.backgroundColor;\r
+                               }\r
+\r
+                               return false;\r
+                       });\r
+\r
+                       if (c = cm.get('fontselect')) {\r
+                               c.select(function(v) {\r
+                                       return v.replace(/^([^,]+).*/, '$1').toLowerCase() == fn;\r
                                });\r
+                       }\r
 \r
-                               if (c = cm.get('fontselect')) {\r
-                                       c.select(function(v) {\r
-                                               return v.replace(/^([^,]+).*/, '$1').toLowerCase() == fn;\r
-                                       });\r
-                               }\r
+                       // Select font size\r
+                       if (c = cm.get('fontsizeselect')) {\r
+                               // Use computed style\r
+                               if (s.theme_advanced_runtime_fontsize && !fz && !cl)\r
+                                       fz = ed.dom.getStyle(n, 'fontSize', true);\r
 \r
-                               if (c = cm.get('fontsizeselect')) {\r
-                                       c.select(function(v) {\r
-                                               if (v.fontSize && v.fontSize === fz)\r
-                                                       return true;\r
+                               c.select(function(v) {\r
+                                       if (v.fontSize && v.fontSize === fz)\r
+                                               return true;\r
 \r
-                                               if (v['class'] && v['class'] === cl)\r
-                                                       return true;\r
-                                       });\r
+                                       if (v['class'] && v['class'] === cl)\r
+                                               return true;\r
+                               });\r
+                       }\r
+                       \r
+                       if (s.theme_advanced_show_current_color) {\r
+                               function updateColor(controlId, color) {\r
+                                       if (c = cm.get(controlId)) {\r
+                                               if (!color)\r
+                                                       color = c.settings.default_color;\r
+                                               if (color !== c.value) {\r
+                                                       c.displayColor(color);\r
+                                               }\r
+                                       }\r
                                }\r
-                       } else {\r
-                               if (c = cm.get('fontselect'))\r
-                                       c.select(ed.queryCommandValue('FontName'));\r
+                               updateColor('forecolor', fc);\r
+                               updateColor('backcolor', bc);\r
+                       }\r
 \r
-                               if (c = cm.get('fontsizeselect')) {\r
-                                       v = ed.queryCommandValue('FontSize');\r
-                                       c.select(function(iv) {\r
-                                               return iv.fontSize == v;\r
-                                       });\r
-                               }\r
+                       if (s.theme_advanced_show_current_color) {\r
+                               function updateColor(controlId, color) {\r
+                                       if (c = cm.get(controlId)) {\r
+                                               if (!color)\r
+                                                       color = c.settings.default_color;\r
+                                               if (color !== c.value) {\r
+                                                       c.displayColor(color);\r
+                                               }\r
+                                       }\r
+                               };\r
+\r
+                               updateColor('forecolor', fc);\r
+                               updateColor('backcolor', bc);\r
                        }\r
 \r
                        if (s.theme_advanced_path && s.theme_advanced_statusbar_location) {\r
                                p = DOM.get(ed.id + '_path') || DOM.add(ed.id + '_path_row', 'span', {id : ed.id + '_path'});\r
+\r
+                               if (t.statusKeyboardNavigation) {\r
+                                       t.statusKeyboardNavigation.destroy();\r
+                                       t.statusKeyboardNavigation = null;\r
+                               }\r
+\r
                                DOM.setHTML(p, '');\r
 \r
-                               ed.dom.getParent(n, function(n) {\r
+                               getParent(function(n) {\r
                                        var na = n.nodeName.toLowerCase(), u, pi, ti = '';\r
 \r
-                                       // Ignore non element and hidden elements\r
-                                       if (n.nodeType != 1 || n.nodeName === 'BR' || (DOM.hasClass(n, 'mceItemHidden') || DOM.hasClass(n, 'mceItemRemoved')))\r
+                                       // Ignore non element and bogus/hidden elements\r
+                                       if (n.nodeType != 1 || na === 'br' || n.getAttribute('data-mce-bogus') || DOM.hasClass(n, 'mceItemHidden') || DOM.hasClass(n, 'mceItemRemoved'))\r
                                                return;\r
 \r
-                                       // Fake name\r
-                                       if (v = DOM.getAttrib(n, 'mce_name'))\r
-                                               na = v;\r
-\r
                                        // Handle prefix\r
                                        if (tinymce.isIE && n.scopeName !== 'HTML')\r
                                                na = n.scopeName + ':' + na;\r
                                                        break;\r
 \r
                                                case 'font':\r
-                                                       if (s.convert_fonts_to_spans)\r
-                                                               na = 'span';\r
-\r
                                                        if (v = DOM.getAttrib(n, 'face'))\r
                                                                ti += 'font: ' + v + ' ';\r
 \r
                                                ti += 'id: ' + v + ' ';\r
 \r
                                        if (v = n.className) {\r
-                                               v = v.replace(/(webkit-[\w\-]+|Apple-[\w\-]+|mceItem\w+|mceVisualAid)/g, '');\r
+                                               v = v.replace(/\b\s*(webkit|mce|Apple-)\w+\s*\b/g, '')\r
 \r
-                                               if (v && v.indexOf('mceItem') == -1) {\r
+                                               if (v) {\r
                                                        ti += 'class: ' + v + ' ';\r
 \r
                                                        if (DOM.isBlock(n) || na == 'img' || na == 'span')\r
                                        na = na.name;\r
 \r
                                        //u = "javascript:tinymce.EditorManager.get('" + ed.id + "').theme._sel('" + (de++) + "');";\r
-                                       pi = DOM.create('a', {'href' : "javascript:;", onmousedown : "return false;", title : ti, 'class' : 'mcePath_' + (de++)}, na);\r
+                                       pi = DOM.create('a', {'href' : "javascript:;", role: 'button', onmousedown : "return false;", title : ti, 'class' : 'mcePath_' + (de++)}, na);\r
 \r
                                        if (p.hasChildNodes()) {\r
-                                               p.insertBefore(DOM.doc.createTextNode(' \u00bb '), p.firstChild);\r
+                                               p.insertBefore(DOM.create('span', {'aria-hidden': 'true'}, '\u00a0\u00bb '), p.firstChild);\r
                                                p.insertBefore(pi, p.firstChild);\r
                                        } else\r
                                                p.appendChild(pi);\r
                                }, ed.getBody());\r
+\r
+                               if (DOM.select('a', p).length > 0) {\r
+                                       t.statusKeyboardNavigation = new tinymce.ui.KeyboardNavigation({\r
+                                               root: ed.id + "_path_row",\r
+                                               items: DOM.select('a', p),\r
+                                               excludeFromTabOrder: true,\r
+                                               onCancel: function() {\r
+                                                       ed.focus();\r
+                                               }\r
+                                       }, DOM);\r
+                               }\r
                        }\r
                },\r
 \r
                        var ed = this.editor;\r
 \r
                        ed.windowManager.open({\r
-                               url : tinymce.baseURL + '/themes/advanced/anchor.htm',\r
+                               url : this.url + '/anchor.htm',\r
                                width : 320 + parseInt(ed.getLang('advanced.anchor_delta_width', 0)),\r
                                height : 90 + parseInt(ed.getLang('advanced.anchor_delta_height', 0)),\r
                                inline : true\r
                        var ed = this.editor;\r
 \r
                        ed.windowManager.open({\r
-                               url : tinymce.baseURL + '/themes/advanced/charmap.htm',\r
+                               url : this.url + '/charmap.htm',\r
                                width : 550 + parseInt(ed.getLang('advanced.charmap_delta_width', 0)),\r
                                height : 250 + parseInt(ed.getLang('advanced.charmap_delta_height', 0)),\r
                                inline : true\r
                        var ed = this.editor;\r
 \r
                        ed.windowManager.open({\r
-                               url : tinymce.baseURL + '/themes/advanced/about.htm',\r
+                               url : this.url + '/about.htm',\r
                                width : 480,\r
                                height : 380,\r
                                inline : true\r
                        });\r
                },\r
 \r
+               _mceShortcuts : function() {\r
+                       var ed = this.editor;\r
+                       ed.windowManager.open({\r
+                               url: this.url + '/shortcuts.htm',\r
+                               width: 480,\r
+                               height: 380,\r
+                               inline: true\r
+                       }, {\r
+                               theme_url: this.url\r
+                       });\r
+               },\r
+\r
                _mceColorPicker : function(u, v) {\r
                        var ed = this.editor;\r
 \r
                        v = v || {};\r
 \r
                        ed.windowManager.open({\r
-                               url : tinymce.baseURL + '/themes/advanced/color_picker.htm',\r
+                               url : this.url + '/color_picker.htm',\r
                                width : 375 + parseInt(ed.getLang('advanced.colorpicker_delta_width', 0)),\r
                                height : 250 + parseInt(ed.getLang('advanced.colorpicker_delta_height', 0)),\r
                                close_previous : false,\r
                        var ed = this.editor;\r
 \r
                        ed.windowManager.open({\r
-                               url : tinymce.baseURL + '/themes/advanced/source_editor.htm',\r
+                               url : this.url + '/source_editor.htm',\r
                                width : parseInt(ed.getParam("theme_advanced_source_editor_width", 720)),\r
                                height : parseInt(ed.getParam("theme_advanced_source_editor_height", 580)),\r
                                inline : true,\r
                                return;\r
 \r
                        ed.windowManager.open({\r
-                               url : tinymce.baseURL + '/themes/advanced/image.htm',\r
+                               url : this.url + '/image.htm',\r
                                width : 355 + parseInt(ed.getLang('advanced.image_delta_width', 0)),\r
                                height : 275 + parseInt(ed.getLang('advanced.image_delta_height', 0)),\r
                                inline : true\r
                        var ed = this.editor;\r
 \r
                        ed.windowManager.open({\r
-                               url : tinymce.baseURL + '/themes/advanced/link.htm',\r
+                               url : this.url + '/link.htm',\r
                                width : 310 + parseInt(ed.getLang('advanced.link_delta_width', 0)),\r
                                height : 200 + parseInt(ed.getLang('advanced.link_delta_height', 0)),\r
                                inline : true\r
        });\r
 \r
        tinymce.ThemeManager.add('advanced', tinymce.themes.AdvancedTheme);\r
-}());
\ No newline at end of file
+}(tinymce));\r