Make WordPress Core

Changeset 6632


Ignore:
Timestamp:
01/17/2008 03:44:05 PM (17 years ago)
Author:
ryan
Message:

TinyMCE 3.0 RC1. First cut, eexpect regressions. Props azaozz. see #5674

Location:
trunk/wp-includes
Files:
80 added
42 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/formatting.php

    r6613 r6632  
    6868    $pee = preg_replace('!(</' . $allblocks . '>)!', "$1\n\n", $pee);
    6969    $pee = str_replace(array("\r\n", "\r"), "\n", $pee); // cross-platform newlines
     70    if ( strpos($pee, '<object') !== false ) {
     71        $pee = preg_replace('|\s*<param([^>]*)>\s*|', "<param$1>", $pee); // no pee inside object/embed
     72        $pee = preg_replace('|\s*</embed>\s*|', '</embed>', $pee);
     73    }
    7074    $pee = preg_replace("/\n\n+/", "\n\n", $pee); // take care of duplicates
    7175    $pee = preg_replace('/\n?(.+?)(?:\n\s*\n|\z)/s', "<p>$1</p>\n", $pee); // make paragraphs, including one at the end
  • trunk/wp-includes/general-template.php

    r6609 r6632  
    953953    <script type="text/javascript">
    954954    // <![CDATA[
    955         if ( typeof tinyMCE != "undefined" && tinyMCE.configs.length > 0 )
     955        if ( typeof tinyMCE != "undefined" )
    956956            document.getElementById('editor-toolbar').style.display = 'block';
    957957    // ]]>
     
    968968    <script type="text/javascript">
    969969    // <![CDATA[
    970         if ( typeof tinyMCE != "undefined" && tinyMCE.configs.length > 0 )
     970        if ( typeof tinyMCE != "undefined" )
    971971            document.getElementById("quicktags").style.display="none";
    972972    // ]]>
  • trunk/wp-includes/js/tinymce/langs/en.js

    r4747 r6632  
    1 // UK lang variables
    2 
    3 tinyMCE.addToLang('',{
    4 bold_desc : 'Bold (Ctrl+B)',
    5 italic_desc : 'Italic (Ctrl+I)',
    6 underline_desc : 'Underline (Ctrl+U)',
    7 striketrough_desc : 'Strikethrough',
    8 justifyleft_desc : 'Align left',
    9 justifycenter_desc : 'Align center',
    10 justifyright_desc : 'Align right',
    11 justifyfull_desc : 'Align full',
    12 bullist_desc : 'Unordered list',
    13 numlist_desc : 'Ordered list',
    14 outdent_desc : 'Outdent',
    15 indent_desc : 'Indent',
    16 undo_desc : 'Undo (Ctrl+Z)',
    17 redo_desc : 'Redo (Ctrl+Y)',
    18 link_desc : 'Insert/edit link',
    19 unlink_desc : 'Unlink',
    20 image_desc : 'Insert/edit image',
    21 cleanup_desc : 'Cleanup messy code',
    22 focus_alert : 'A editor instance must be focused before using this command.',
    23 edit_confirm : 'Do you want to use the WYSIWYG mode for this textarea?',
    24 insert_link_title : 'Insert/edit link',
    25 insert : 'Insert',
    26 update : 'Update',
    27 cancel : 'Cancel',
    28 insert_link_url : 'Link URL',
    29 insert_link_target : 'Target',
    30 insert_link_target_same : 'Open link in the same window',
    31 insert_link_target_blank : 'Open link in a new window',
    32 insert_image_title : 'Insert/edit image',
    33 insert_image_src : 'Image URL',
    34 insert_image_alt : 'Image description',
    35 help_desc : 'Help',
    36 bold_img : "bold.gif",
    37 italic_img : "italic.gif",
    38 underline_img : "underline.gif",
    39 clipboard_msg : 'Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?',
    40 popup_blocked : 'Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.'
    41 });
     1tinyMCE.addI18n({en:{
     2common:{
     3edit_confirm:"Do you want to use the WYSIWYG mode for this textarea?",
     4apply:"Apply",
     5insert:"Insert",
     6update:"Update",
     7cancel:"Cancel",
     8close:"Close",
     9browse:"Browse",
     10class_name:"Class",
     11not_set:"-- Not set --",
     12clipboard_msg:"Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?",
     13clipboard_no_support:"Currently not supported by your browser, use keyboard shortcuts instead.",
     14popup_blocked:"Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.",
     15invalid_data:"Error: Invalid values entered, these are marked in red.",
     16more_colors:"More colors"
     17},
     18contextmenu:{
     19align:"Alignment",
     20left:"Left",
     21center:"Center",
     22right:"Right",
     23full:"Full"
     24},
     25insertdatetime:{
     26date_fmt:"%Y-%m-%d",
     27time_fmt:"%H:%M:%S",
     28insertdate_desc:"Insert date",
     29inserttime_desc:"Insert time",
     30months_long:"January,February,March,April,May,June,July,August,September,October,November,December",
     31months_short:"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
     32day_long:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday",
     33day_short:"Sun,Mon,Tue,Wed,Thu,Fri,Sat,Sun"
     34},
     35print:{
     36print_desc:"Print"
     37},
     38preview:{
     39preview_desc:"Preview"
     40},
     41directionality:{
     42ltr_desc:"Direction left to right",
     43rtl_desc:"Direction right to left"
     44},
     45layer:{
     46insertlayer_desc:"Insert new layer",
     47forward_desc:"Move forward",
     48backward_desc:"Move backward",
     49absolute_desc:"Toggle absolute positioning",
     50content:"New layer..."
     51},
     52save:{
     53save_desc:"Save",
     54cancel_desc:"Cancel all changes"
     55},
     56nonbreaking:{
     57nonbreaking_desc:"Insert non-breaking space character"
     58},
     59iespell:{
     60iespell_desc:"Run spell checking",
     61download:"ieSpell not detected. Do you want to install it now?"
     62},
     63advhr:{
     64advhr_desc:"Horizontale rule"
     65},
     66emotions:{
     67emotions_desc:"Emotions"
     68},
     69searchreplace:{
     70search_desc:"Find",
     71replace_desc:"Find/Replace"
     72},
     73advimage:{
     74image_desc:"Insert/edit image"
     75},
     76advlink:{
     77link_desc:"Insert/edit link"
     78},
     79xhtmlxtras:{
     80cite_desc:"Citation",
     81abbr_desc:"Abbreviation",
     82acronym_desc:"Acronym",
     83del_desc:"Deletion",
     84ins_desc:"Insertion",
     85attribs_desc:"Insert/Edit Attributes"
     86},
     87style:{
     88desc:"Edit CSS Style"
     89},
     90paste:{
     91paste_text_desc:"Paste as Plain Text",
     92paste_word_desc:"Paste from Word",
     93selectall_desc:"Select All"
     94},
     95paste_dlg:{
     96text_title:"Use CTRL+V on your keyboard to paste the text into the window.",
     97text_linebreaks:"Keep linebreaks",
     98word_title:"Use CTRL+V on your keyboard to paste the text into the window."
     99},
     100table:{
     101desc:"Inserts a new table",
     102row_before_desc:"Insert row before",
     103row_after_desc:"Insert row after",
     104delete_row_desc:"Delete row",
     105col_before_desc:"Insert column before",
     106col_after_desc:"Insert column after",
     107delete_col_desc:"Remove column",
     108split_cells_desc:"Split merged table cells",
     109merge_cells_desc:"Merge table cells",
     110row_desc:"Table row properties",
     111cell_desc:"Table cell properties",
     112props_desc:"Table properties",
     113paste_row_before_desc:"Paste table row before",
     114paste_row_after_desc:"Paste table row after",
     115cut_row_desc:"Cut table row",
     116copy_row_desc:"Copy table row",
     117del:"Delete table",
     118row:"Row",
     119col:"Column",
     120cell:"Cell"
     121},
     122autosave:{
     123unload_msg:"The changes you made will be lost if you navigate away from this page."
     124},
     125fullscreen:{
     126desc:"Toggle fullscreen mode"
     127},
     128media:{
     129desc:"Insert / edit embedded media",
     130edit:"Edit embedded media"
     131},
     132fullpage:{
     133desc:"Document properties"
     134},
     135template:{
     136desc:"Insert predefined template content"
     137},
     138visualchars:{
     139desc:"Visual control characters on/off."
     140},
     141spellchecker:{
     142desc:"Toggle spellchecker",
     143menu:"Spellchecker settings",
     144ignore_word:"Ignore word",
     145ignore_words:"Ignore all",
     146langs:"Languages",
     147wait:"Please wait...",
     148sug:"Suggestions",
     149no_sug:"No suggestions",
     150no_mpell:"No misspellings found."
     151},
     152pagebreak:{
     153desc:"Insert page break."
     154}}});
  • trunk/wp-includes/js/tinymce/plugins/autosave/editor_plugin.js

    r5256 r6632  
    11/**
    2  * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
     2 * $Id$
    33 *
    44 * @author Moxiecode
    5  * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
     5 * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
    66 */
    77
    8 /* Import plugin specific language pack */
    9 tinyMCE.importPluginLanguagePack('autosave');
     8(function() {
     9    tinymce.create('tinymce.plugins.AutoSavePlugin', {
     10        init : function(ed, url) {
     11            var t = this;
    1012
    11 var TinyMCE_AutoSavePlugin = {
    12     getInfo : function() {
    13         return {
    14             longname : 'Auto save',
    15             author : 'Moxiecode Systems AB',
    16             authorurl : 'http://tinymce.moxiecode.com',
    17             infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autosave',
    18             version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
    19         };
    20     },
     13            t.editor = ed;
    2114
    22     // Private plugin internal methods
     15            window.onbeforeunload = tinymce.plugins.AutoSavePlugin._beforeUnloadHandler;
     16        },
    2317
    24     _beforeUnloadHandler : function() {
    25         var n, inst, anyDirty = false, msg = tinyMCE.getLang("lang_autosave_unload_msg");
     18        getInfo : function() {
     19            return {
     20                longname : 'Auto save',
     21                author : 'Moxiecode Systems AB',
     22                authorurl : 'http://tinymce.moxiecode.com',
     23                infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autosave',
     24                version : tinymce.majorVersion + "." + tinymce.minorVersion
     25            };
     26        },
    2627
    27         if (tinyMCE.getParam("fullscreen_is_enabled"))
    28             return;
     28        // Private plugin internal methods
    2929
    30         for (n in tinyMCE.instances) {
    31             inst = tinyMCE.instances[n];
     30        'static' : {
     31            _beforeUnloadHandler : function() {
     32                var msg;
    3233
    33             if (!tinyMCE.isInstance(inst))
    34                 continue;
     34                tinymce.each(tinyMCE.editors, function(ed) {
     35                    if (ed.getParam("fullscreen_is_enabled"))
     36                        return;
    3537
    36             if (inst.isDirty())
     38                    if (ed.isDirty()) {
     39                        msg = ed.getLang("autosave.unload_msg");
     40                        return false;
     41                    }
     42                });
     43
    3744                return msg;
     45            }
    3846        }
     47    });
    3948
    40         return;
    41     }
    42 };
    43 
    44 window.onbeforeunload = TinyMCE_AutoSavePlugin._beforeUnloadHandler;
    45 
    46 tinyMCE.addPlugin("autosave", TinyMCE_AutoSavePlugin);
     49    // Register plugin
     50    tinymce.PluginManager.add('autosave', tinymce.plugins.AutoSavePlugin);
     51})();
  • trunk/wp-includes/js/tinymce/plugins/directionality/editor_plugin.js

    r5256 r6632  
    11/**
    2  * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
     2 * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $
    33 *
    44 * @author Moxiecode
    5  * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
     5 * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
    66 */
    77
    8 /* Import plugin specific language pack */
    9 tinyMCE.importPluginLanguagePack('directionality');
     8(function() {
     9    tinymce.create('tinymce.plugins.Directionality', {
     10        init : function(ed, url) {
     11            var t = this;
    1012
    11 var TinyMCE_DirectionalityPlugin = {
    12     getInfo : function() {
    13         return {
    14             longname : 'Directionality',
    15             author : 'Moxiecode Systems AB',
    16             authorurl : 'http://tinymce.moxiecode.com',
    17             infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/directionality',
    18             version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
    19         };
    20     },
     13            t.editor = ed;
    2114
    22     getControlHTML : function(cn) {
    23         switch (cn) {
    24             case "ltr":
    25                 return tinyMCE.getButtonHTML(cn, 'lang_directionality_ltr_desc', '{$pluginurl}/images/ltr.gif', 'mceDirectionLTR');
     15            ed.addCommand('mceDirectionLTR', function() {
     16                var e = ed.dom.getParent(ed.selection.getNode(), ed.dom.isBlock);
    2617
    27             case "rtl":
    28                 return tinyMCE.getButtonHTML(cn, 'lang_directionality_rtl_desc', '{$pluginurl}/images/rtl.gif', 'mceDirectionRTL');
     18                if (e) {
     19                    if (ed.dom.getAttrib(e, "dir") != "ltr")
     20                        ed.dom.setAttrib(e, "dir", "ltr");
     21                    else
     22                        ed.dom.setAttrib(e, "dir", "");
     23                }
     24
     25                ed.nodeChanged();
     26            });
     27
     28            ed.addCommand('mceDirectionRTL', function() {
     29                var e = ed.dom.getParent(ed.selection.getNode(), ed.dom.isBlock);
     30
     31                if (e) {
     32                    if (ed.dom.getAttrib(e, "dir") != "rtl")
     33                        ed.dom.setAttrib(e, "dir", "rtl");
     34                    else
     35                        ed.dom.setAttrib(e, "dir", "");
     36                }
     37
     38                ed.nodeChanged();
     39            });
     40
     41            ed.addButton('ltr', {title : 'directionality.ltr_desc', cmd : 'mceDirectionLTR'});
     42            ed.addButton('rtl', {title : 'directionality.rtl_desc', cmd : 'mceDirectionRTL'});
     43
     44            ed.onNodeChange.add(t._nodeChange, t);
     45        },
     46
     47        getInfo : function() {
     48            return {
     49                longname : 'Directionality',
     50                author : 'Moxiecode Systems AB',
     51                authorurl : 'http://tinymce.moxiecode.com',
     52                infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/directionality',
     53                version : tinymce.majorVersion + "." + tinymce.minorVersion
     54            };
     55        },
     56
     57        // Private methods
     58
     59        _nodeChange : function(ed, cm, n) {
     60            var dom = ed.dom, dir;
     61
     62            n = dom.getParent(n, dom.isBlock);
     63            if (!n) {
     64                cm.setDisabled('ltr', 1);
     65                cm.setDisabled('rtl', 1);
     66                return;
     67            }
     68
     69            dir = dom.getAttrib(n, 'dir');
     70            cm.setActive('ltr', dir == "ltr");
     71            cm.setDisabled('ltr', 0);
     72            cm.setActive('rtl', dir == "rtl");
     73            cm.setDisabled('rtl', 0);
    2974        }
     75    });
    3076
    31         return "";
    32     },
    33 
    34     execCommand : function(editor_id, element, command, user_interface, value) {
    35         // Handle commands
    36         switch (command) {
    37             case "mceDirectionLTR":
    38                 var inst = tinyMCE.getInstanceById(editor_id);
    39                 var elm = tinyMCE.getParentElement(inst.getFocusElement(), "p,div,td,h1,h2,h3,h4,h5,h6,pre,address");
    40 
    41                 if (elm)
    42                     elm.setAttribute("dir", "ltr");
    43 
    44                 tinyMCE.triggerNodeChange(false);
    45                 return true;
    46 
    47             case "mceDirectionRTL":
    48                 var inst = tinyMCE.getInstanceById(editor_id);
    49                 var elm = tinyMCE.getParentElement(inst.getFocusElement(), "p,div,td,h1,h2,h3,h4,h5,h6,pre,address");
    50 
    51                 if (elm)
    52                     elm.setAttribute("dir", "rtl");
    53 
    54                 tinyMCE.triggerNodeChange(false);
    55                 return true;
    56         }
    57 
    58         // Pass to next handler in chain
    59         return false;
    60     },
    61 
    62     handleNodeChange : function(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) {
    63         function getAttrib(elm, name) {
    64             return elm.getAttribute(name) ? elm.getAttribute(name) : "";
    65         }
    66 
    67         if (node == null)
    68             return;
    69 
    70         var elm = tinyMCE.getParentElement(node, "p,div,td,h1,h2,h3,h4,h5,h6,pre,address");
    71         if (!elm) {
    72             tinyMCE.switchClass(editor_id + '_ltr', 'mceButtonDisabled');
    73             tinyMCE.switchClass(editor_id + '_rtl', 'mceButtonDisabled');
    74             return true;
    75         }
    76 
    77         tinyMCE.switchClass(editor_id + '_ltr', 'mceButtonNormal');
    78         tinyMCE.switchClass(editor_id + '_rtl', 'mceButtonNormal');
    79 
    80         var dir = getAttrib(elm, "dir");
    81         if (dir == "ltr" || dir == "")
    82             tinyMCE.switchClass(editor_id + '_ltr', 'mceButtonSelected');
    83         else
    84             tinyMCE.switchClass(editor_id + '_rtl', 'mceButtonSelected');
    85 
    86         return true;
    87     }
    88 };
    89 
    90 tinyMCE.addPlugin("directionality", TinyMCE_DirectionalityPlugin);
     77    // Register plugin
     78    tinymce.PluginManager.add('directionality', tinymce.plugins.Directionality);
     79})();
  • trunk/wp-includes/js/tinymce/plugins/inlinepopups/css/inlinepopup.css

    • Property svn:eol-style set to native
  • trunk/wp-includes/js/tinymce/plugins/inlinepopups/editor_plugin.js

    r6568 r6632  
    11/**
    2  * $Id: editor_plugin_src.js 268 2007-04-28 15:52:59Z spocke $
    3  *
    4  * Moxiecode DHTML Windows script.
     2 * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $
    53 *
    64 * @author Moxiecode
    7  * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
     5 * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
    86 */
    97
    10 // Patch openWindow, closeWindow TinyMCE functions
    11 
    12 var TinyMCE_InlinePopupsPlugin = {
    13     getInfo : function() {
    14         return {
    15             longname : 'Inline Popups',
    16             author : 'Moxiecode Systems AB',
    17             authorurl : 'http://tinymce.moxiecode.com',
    18             infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/inlinepopups',
    19             version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
    20         };
    21     }
    22 };
    23 
    24 tinyMCE.addPlugin("inlinepopups", TinyMCE_InlinePopupsPlugin);
    25 
    26 // Patch openWindow, closeWindow TinyMCE functions
    27 
    28 TinyMCE_Engine.prototype.orgOpenWindow = TinyMCE_Engine.prototype.openWindow;
    29 TinyMCE_Engine.prototype.orgCloseWindow = TinyMCE_Engine.prototype.closeWindow;
    30 
    31 TinyMCE_Engine.prototype.openWindow = function(template, args) {
    32     // Does the caller support inline
    33     if (args['inline'] != "yes" || tinyMCE.isOpera || tinyMCE.getParam("plugins").indexOf('inlinepopups') == -1) {
    34         mcWindows.selectedWindow = null;
    35         args['mce_inside_iframe'] = false;
    36         this.orgOpenWindow(template, args);
    37         return;
    38     }
    39 
    40     var url, resizable, scrollbars;
    41 
    42     args['mce_inside_iframe'] = true;
    43     tinyMCE.windowArgs = args;
    44 
    45     if (template['file'].charAt(0) != '/' && template['file'].indexOf('://') == -1)
    46         url = tinyMCE.baseURL + "/themes/" + tinyMCE.getParam("theme") + "/" + template['file'];
    47     else
    48         url = template['file'];
    49 
    50     if (!(width = parseInt(template['width'])))
    51         width = 320;
    52 
    53     if (!(height = parseInt(template['height'])))
    54         height = 200;
    55 
    56     if (!(minWidth = parseInt(template['minWidth'])))
    57         minWidth = 100;
    58 
    59     if (!(minHeight = parseInt(template['minHeight'])))
    60         minHeight = 100;
    61 
    62     resizable = (args && args['resizable']) ? args['resizable'] : "no";
    63     scrollbars = (args && args['scrollbars']) ? args['scrollbars'] : "no";
    64 
    65     height += 18;
    66 
    67     // Replace all args as variables in URL
    68     for (var name in args) {
    69         if (typeof(args[name]) == 'function')
    70             continue;
    71 
    72         url = tinyMCE.replaceVar(url, name, escape(args[name]));
    73     }
    74 
    75     var elm = document.getElementById(this.selectedInstance.editorId + '_parent');
    76 
    77     if (tinyMCE.hasPlugin('fullscreen') && this.selectedInstance.getData('fullscreen').enabled)
    78         pos = { absLeft: 0, absTop: 0 };
    79     else
    80         pos = tinyMCE.getAbsPosition(elm);
    81 
    82     // Center div in editor area
    83     pos.absLeft += Math.round((elm.firstChild.clientWidth / 2) - (width / 2));
    84     pos.absTop += Math.round((elm.firstChild.clientHeight / 2) - (height / 2));
     8(function() {
     9    var DOM = tinymce.DOM, Element = tinymce.dom.Element, Event = tinymce.dom.Event, each = tinymce.each, is = tinymce.is;
     10
     11    tinymce.create('tinymce.plugins.InlinePopups', {
     12        init : function(ed, url) {
     13            // Replace window manager
     14            ed.onBeforeRenderUI.add(function() {
     15                ed.windowManager = new tinymce.InlineWindowManager(ed);
     16                DOM.loadCSS(url + '/skins/' + (ed.settings.inlinepopups_skin || 'clearlooks2') + "/window.css");
     17            });
     18        },
     19
     20        getInfo : function() {
     21            return {
     22                longname : 'InlinePopups',
     23                author : 'Moxiecode Systems AB',
     24                authorurl : 'http://tinymce.moxiecode.com',
     25                infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/inlinepopups',
     26                version : tinymce.majorVersion + "." + tinymce.minorVersion
     27            };
     28        }
     29    });
     30
     31    tinymce.create('tinymce.InlineWindowManager:tinymce.WindowManager', {
     32        InlineWindowManager : function(ed) {
     33            var t = this;
     34
     35            t.parent(ed);
     36            t.zIndex = 1000;
     37        },
     38
     39        open : function(f, p) {
     40            var t = this, id, opt = '', ed = t.editor, dw = 0, dh = 0, vp, po, mdf, clf, we, w;
     41
     42            f = f || {};
     43            p = p || {};
     44
     45            // Run native windows
     46            if (!f.inline)
     47                return t.parent(f, p);
     48
     49            t.bookmark = ed.selection.getBookmark('simple');
     50            id = DOM.uniqueId();
     51            vp = DOM.getViewPort();
     52            f.width = parseInt(f.width || 320);
     53            f.height = parseInt(f.height || 240) + (tinymce.isIE ? 8 : 0);
     54            f.min_width = parseInt(f.min_width || 150);
     55            f.min_height = parseInt(f.min_height || 100);
     56            f.max_width = parseInt(f.max_width || 2000);
     57            f.max_height = parseInt(f.max_height || 2000);
     58            f.left = f.left || Math.round(Math.max(vp.x, vp.x + (vp.w / 2.0) - (f.width / 2.0)));
     59            f.top = f.top || Math.round(Math.max(vp.y, vp.y + (vp.h / 2.0) - (f.height / 2.0)));
     60            f.movable = f.resizable = true;
     61            p.mce_width = f.width;
     62            p.mce_height = f.height;
     63            p.mce_inline = true;
     64            p.mce_window_id = id;
     65
     66            // Transpose
     67//          po = DOM.getPos(ed.getContainer());
     68//          f.left -= po.x;
     69//          f.top -= po.y;
     70
     71            t.features = f;
     72            t.params = p;
     73            t.onOpen.dispatch(t, f, p);
     74
     75            if (f.type) {
     76                opt += ' modal ' + f.type;
     77                f.resizable = false;
     78            }
     79
     80            if (f.statusbar)
     81                opt += ' statusbar';
     82
     83            if (f.resizable)
     84                opt += ' resizable';
     85
     86            if (f.minimizable)
     87                opt += ' minimizable';
     88
     89            if (f.maximizable)
     90                opt += ' maximizable';
     91
     92            if (f.movable)
     93                opt += ' movable';
     94
     95            // Create DOM objects
     96            t._addAll(document.body,
     97                ['div', {id : id, 'class' : ed.settings.inlinepopups_skin || 'clearlooks2', style : 'width:100px;height:100px'},
     98                    ['div', {id : id + '_wrapper', 'class' : 'wrapper' + opt},
     99                        ['div', {id : id + '_top', 'class' : 'top'},
     100                            ['div', {'class' : 'left'}],
     101                            ['div', {'class' : 'center'}],
     102                            ['div', {'class' : 'right'}],
     103                            ['span', {id : id + '_title'}, f.title || '']
     104                        ],
     105
     106                        ['div', {id : id + '_middle', 'class' : 'middle'},
     107                            ['div', {id : id + '_left', 'class' : 'left'}],
     108                            ['span', {id : id + '_content'}],
     109                            ['div', {id : id + '_right', 'class' : 'right'}]
     110                        ],
     111
     112                        ['div', {id : id + '_bottom', 'class' : 'bottom'},
     113                            ['div', {'class' : 'left'}],
     114                            ['div', {'class' : 'center'}],
     115                            ['div', {'class' : 'right'}],
     116                            ['span', {id : id + '_status'}, 'Content']
     117                        ],
     118
     119                        ['a', {'class' : 'move', href : 'javascript:;'}],
     120                        ['a', {'class' : 'min', href : 'javascript:;', onmousedown : 'return false;'}],
     121                        ['a', {'class' : 'max', href : 'javascript:;', onmousedown : 'return false;'}],
     122                        ['a', {'class' : 'med', href : 'javascript:;', onmousedown : 'return false;'}],
     123                        ['a', {'class' : 'close', href : 'javascript:;', onmousedown : 'return false;'}],
     124                        ['a', {id : id + '_resize_n', 'class' : 'resize resize-n', href : 'javascript:;'}],
     125                        ['a', {id : id + '_resize_s', 'class' : 'resize resize-s', href : 'javascript:;'}],
     126                        ['a', {id : id + '_resize_w', 'class' : 'resize resize-w', href : 'javascript:;'}],
     127                        ['a', {id : id + '_resize_e', 'class' : 'resize resize-e', href : 'javascript:;'}],
     128                        ['a', {id : id + '_resize_nw', 'class' : 'resize resize-nw', href : 'javascript:;'}],
     129                        ['a', {id : id + '_resize_ne', 'class' : 'resize resize-ne', href : 'javascript:;'}],
     130                        ['a', {id : id + '_resize_sw', 'class' : 'resize resize-sw', href : 'javascript:;'}],
     131                        ['a', {id : id + '_resize_se', 'class' : 'resize resize-se', href : 'javascript:;'}]
     132                    ]
     133                ]
     134            );
     135
     136            DOM.setStyles(id, {top : -10000, left : -10000});
     137
     138            // Fix gecko rendering bug, where the editors iframe messed with window contents
     139            if (tinymce.isGecko)
     140                DOM.setStyle(id, 'overflow', 'auto');
     141
     142            // Measure borders
     143            if (!f.type) {
     144                dw += DOM.get(id + '_left').clientWidth;
     145                dw += DOM.get(id + '_right').clientWidth;
     146                dh += DOM.get(id + '_top').clientHeight;
     147                dh += DOM.get(id + '_bottom').clientHeight;
     148            }
     149
     150            // Resize window
     151            DOM.setStyles(id, {top : f.top, left : f.left, width : f.width + dw, height : f.height + dh});
     152
     153            if (!f.type) {
     154                DOM.add(id + '_content', 'iframe', {id : id + '_ifr', src : 'javascript:""', frameBorder : 0, style : 'border:0;width:10px;height:10px'});
     155                DOM.setStyles(id + '_ifr', {width : f.width, height : f.height});
     156                DOM.setAttrib(id + '_ifr', 'src', f.url || f.file);
     157            } else {
     158                DOM.add(id + '_wrapper', 'a', {id : id + '_ok', 'class' : 'button ok', href : 'javascript:;', onmousedown : 'return false;'}, 'Ok');
     159
     160                if (f.type == 'confirm')
     161                    DOM.add(id + '_wrapper', 'a', {'class' : 'button cancel', href : 'javascript:;', onmousedown : 'return false;'}, 'Cancel');
     162
     163                DOM.add(id + '_middle', 'div', {'class' : 'icon'});
     164                DOM.setHTML(id + '_content', f.content.replace('\n', '<br />'));
     165            }
     166
     167            // Register events
     168            mdf = Event.add(id, 'mousedown', function(e) {
     169                var n = e.target, w, vp;
     170
     171                w = t.windows[id];
     172                t.focus(id);
     173
     174                if (n.nodeName == 'A' || n.nodeName == 'a') {
     175                    if (n.className == 'max') {
     176                        w.oldPos = w.element.getXY();
     177                        w.oldSize = w.element.getSize();
     178
     179                        vp = DOM.getViewPort();
     180
     181                        // Reduce viewport size to avoid scrollbars
     182                        vp.w -= 2;
     183                        vp.h -= 2;
     184
     185                        w.element.moveTo(vp.x, vp.y);
     186                        w.element.resizeTo(vp.w, vp.h);
     187                        DOM.setStyles(id + '_ifr', {width : vp.w - w.deltaWidth, height : vp.h - w.deltaHeight});
     188                        DOM.addClass(id + '_wrapper', 'maximized');
     189                    } else if (n.className == 'med') {
     190                        // Reset to old size
     191                        w.element.moveTo(w.oldPos.x, w.oldPos.y);
     192                        w.element.resizeTo(w.oldSize.w, w.oldSize.h);
     193                        w.iframeElement.resizeTo(w.oldSize.w - w.deltaWidth, w.oldSize.h - w.deltaHeight);
     194
     195                        DOM.removeClass(id + '_wrapper', 'maximized');
     196                    } else if (n.className == 'move')
     197                        return t._startDrag(id, e, n.className);
     198                    else if (DOM.hasClass(n, 'resize'))
     199                        return t._startDrag(id, e, n.className.substring(7));
     200                }
     201            });
     202
     203            clf = Event.add(id, 'click', function(e) {
     204                var n = e.target;
     205
     206                t.focus(id);
     207
     208                if (n.nodeName == 'A' || n.nodeName == 'a') {
     209                    switch (n.className) {
     210                        case 'close':
     211                            t.close(null, id);
     212                            return Event.cancel(e);
     213
     214                        case 'button ok':
     215                        case 'button cancel':
     216                            f.button_func(n.className == 'button ok');
     217                            return Event.cancel(e);
     218                    }
     219                }
     220            });
     221
     222            // Add window
     223            t.windows = t.windows || {};
     224            w = t.windows[id] = {
     225                id : id,
     226                mousedown_func : mdf,
     227                click_func : clf,
     228                element : new Element(id, {blocker : 1, container : ed.getContainer()}),
     229                iframeElement : new Element(id + '_ifr'),
     230                features : f,
     231                deltaWidth : dw,
     232                deltaHeight : dh
     233            };
     234
     235            w.iframeElement.on('focus', function() {
     236                t.focus(id);
     237            });
     238
     239            t.focus(id);
     240            t._fixIELayout(id, 1);
     241
     242//          if (DOM.get(id + '_ok'))
     243//              DOM.get(id + '_ok').focus();
     244
     245            return w;
     246        },
     247
     248        focus : function(id) {
     249            var t = this, w = t.windows[id];
     250
     251            w.zIndex = this.zIndex++;
     252            w.element.setStyle('zIndex', w.zIndex);
     253            w.element.update();
     254
     255            id = id + '_wrapper';
     256            DOM.removeClass(t.lastId, 'focus');
     257            DOM.addClass(id, 'focus');
     258            t.lastId = id;
     259        },
     260
     261        _addAll : function(te, ne) {
     262            var i, n, t = this, dom = tinymce.DOM;
     263
     264            if (is(ne, 'string'))
     265                te.appendChild(dom.doc.createTextNode(ne));
     266            else if (ne.length) {
     267                te = te.appendChild(dom.create(ne[0], ne[1]));
     268
     269                for (i=2; i<ne.length; i++)
     270                    t._addAll(te, ne[i]);
     271            }
     272        },
     273
     274        _startDrag : function(id, se, ac) {
     275            var t = this, mu, mm, d = document, eb, w = t.windows[id], we = w.element, sp = we.getXY(), p, sz, ph, cp, vp, sx, sy, sex, sey, dx, dy, dw, dh;
     276
     277            // Get positons and sizes
     278//          cp = DOM.getPos(t.editor.getContainer());
     279            cp = {x : 0, y : 0};
     280            vp = DOM.getViewPort();
     281
     282            // Reduce viewport size to avoid scrollbars
     283            vp.w -= 2;
     284            vp.h -= 2;
     285
     286            sex = se.screenX;
     287            sey = se.screenY;
     288            dx = dy = dw = dh = 0;
     289
     290            // Handle mouse up
     291            mu = Event.add(d, 'mouseup', function(e) {
     292                Event.remove(d, 'mouseup', mu);
     293                Event.remove(d, 'mousemove', mm);
     294
     295                if (eb)
     296                    eb.remove();
     297
     298                we.moveBy(dx, dy);
     299                we.resizeBy(dw, dh);
     300                sz = we.getSize();
     301                DOM.setStyles(id + '_ifr', {width : sz.w - w.deltaWidth, height : sz.h - w.deltaHeight});
     302                t._fixIELayout(id, 1);
     303
     304                return Event.cancel(e);
     305            });
     306
     307            if (ac != 'move')
     308                startMove();
     309
     310            function startMove() {
     311                if (eb)
     312                    return;
     313
     314                t._fixIELayout(id, 0);
     315
     316                // Setup event blocker
     317                DOM.add(d.body, 'div', {
     318                    id : 'mceEventBlocker',
     319                    'class' : 'mceEventBlocker ' + (t.editor.settings.inlinepopups_skin || 'clearlooks2'),
     320                    style : {left : vp.x, top : vp.y, width : vp.w - 20, height : vp.h - 20, zIndex : 20001}
     321                });
     322                eb = new Element('mceEventBlocker');
     323                eb.update();
     324
     325                // Setup placeholder
     326                p = we.getXY();
     327                sz = we.getSize();
     328                sx = cp.x + p.x - vp.x;
     329                sy = cp.y + p.y - vp.y;
     330                DOM.add(eb.get(), 'div', {id : 'mcePlaceHolder', 'class' : 'placeholder', style : {left : sx, top : sy, width : sz.w, height : sz.h}});
     331                ph = new Element('mcePlaceHolder');
     332            };
     333
     334            // Handle mouse move/drag
     335            mm = Event.add(d, 'mousemove', function(e) {
     336                var x, y, v;
     337
     338                startMove();
     339
     340                x = e.screenX - sex;
     341                y = e.screenY - sey;
     342
     343                switch (ac) {
     344                    case 'resize-w':
     345                        dx = x;
     346                        dw = 0 - x;
     347                        break;
     348
     349                    case 'resize-e':
     350                        dw = x;
     351                        break;
     352
     353                    case 'resize-n':
     354                    case 'resize-nw':
     355                    case 'resize-ne':
     356                        if (ac == "resize-nw") {
     357                            dx = x;
     358                            dw = 0 - x;
     359                        } else if (ac == "resize-ne")
     360                            dw = x;
     361
     362                        dy = y;
     363                        dh = 0 - y;
     364                        break;
     365
     366                    case 'resize-s':
     367                    case 'resize-sw':
     368                    case 'resize-se':
     369                        if (ac == "resize-sw") {
     370                            dx = x;
     371                            dw = 0 - x;
     372                        } else if (ac == "resize-se")
     373                            dw = x;
     374
     375                        dh = y;
     376                        break;
     377
     378                    case 'move':
     379                        dx = x;
     380                        dy = y;
     381                        break;
     382                }
     383
     384                // Boundary check
     385                if (dw < (v = w.features.min_width - sz.w)) {
     386                    if (dx !== 0)
     387                        dx += dw - v;
     388
     389                    dw = v;
     390                }
    85391   
    86     // WordPress cache buster
    87     url += tinyMCE.settings['imp_version'] ? (url.indexOf('?')==-1?'?':'&') + 'ver=' + tinyMCE.settings['imp_version'] : '';
    88 
    89     mcWindows.open(url, mcWindows.idCounter++, "modal=yes,width=" + width+ ",height=" + height + ",resizable=" + resizable + ",scrollbars=" + scrollbars + ",statusbar=" + resizable + ",left=" + pos.absLeft + ",top=" + pos.absTop + ",minWidth=" + minWidth + ",minHeight=" + minHeight );
    90 };
    91 
    92 TinyMCE_Engine.prototype.closeWindow = function(win) {
    93     var gotit = false, n, w;
    94 
    95     for (n in mcWindows.windows) {
    96         w = mcWindows.windows[n];
    97 
    98         if (typeof(w) == 'function')
    99             continue;
    100 
    101         if (win.name == w.id + '_iframe') {
    102             w.close();
    103             gotit = true;
     392                if (dh < (v = w.features.min_height - sz.h)) {
     393                    if (dy !== 0)
     394                        dy += dh - v;
     395
     396                    dh = v;
     397                }
     398
     399                dw = Math.min(dw, w.features.max_width - sz.w);
     400                dh = Math.min(dh, w.features.max_height - sz.h);
     401                dx = Math.max(dx, vp.x - (sx + vp.x));
     402                dy = Math.max(dy, vp.y - (sy + vp.y));
     403                dx = Math.min(dx, (vp.w + vp.x) - (sx + sz.w + vp.x));
     404                dy = Math.min(dy, (vp.h + vp.y) - (sy + sz.h + vp.y));
     405
     406                // Move if needed
     407                if (dx + dy !== 0) {
     408                    if (sx + dx < 0)
     409                        dx = 0;
     410   
     411                    if (sy + dy < 0)
     412                        dy = 0;
     413
     414                    ph.moveTo(sx + dx, sy + dy);
     415                }
     416
     417                // Resize if needed
     418                if (dw + dh !== 0)
     419                    ph.resizeTo(sz.w + dw, sz.h + dh);
     420
     421                return Event.cancel(e);
     422            });
     423
     424            return Event.cancel(se);
     425        },
     426
     427        resizeBy : function(dw, dh, id) {
     428            var w = this.windows[id];
     429
     430            if (w) {
     431                w.element.resizeBy(dw, dh);
     432                w.iframeElement.resizeBy(dw, dh);
     433            }
     434        },
     435
     436        close : function(win, id) {
     437            var t = this, w, d = document, ix = 0, fw;
     438
     439            // Probably not inline
     440            if (!id && win) {
     441                t.parent(win);
     442                return;
     443            }
     444
     445            if (w = t.windows[id]) {
     446                t.onClose.dispatch(t);
     447                Event.remove(d, 'mousedown', w.mousedownFunc);
     448                Event.remove(d, 'click', w.clickFunc);
     449
     450                DOM.setAttrib(id + '_ifr', 'src', 'javascript:""'); // Prevent leak
     451                w.element.remove();
     452                delete t.windows[id];
     453
     454                // Find front most window and focus that
     455                each (t.windows, function(w) {
     456                    if (w.zIndex > ix) {
     457                        fw = w;
     458                        ix = w.zIndex;
     459                    }
     460                });
     461
     462                if (fw)
     463                    t.focus(fw.id);
     464            }
     465        },
     466
     467        setTitle : function(ti, id) {
     468            DOM.get(id + '_title').innerHTML = DOM.encode(ti);
     469        },
     470
     471        alert : function(txt, cb, s) {
     472            var t = this, w;
     473
     474            w = t.open({
     475                title : t,
     476                type : 'alert',
     477                button_func : function(s) {
     478                    if (cb)
     479                        cb.call(s || t, s);
     480
     481                    t.close(null, w.id);
     482                },
     483                content : DOM.encode(t.editor.getLang(txt, txt)),
     484                inline : 1,
     485                width : 400,
     486                height : 130
     487            });
     488        },
     489
     490        confirm : function(txt, cb, s) {
     491            var t = this, w;
     492
     493            w = t.open({
     494                title : t,
     495                type : 'confirm',
     496                button_func : function(s) {
     497                    if (cb)
     498                        cb.call(s || t, s);
     499
     500                    t.close(null, w.id);
     501                },
     502                content : DOM.encode(t.editor.getLang(txt, txt)),
     503                inline : 1,
     504                width : 400,
     505                height : 130
     506            });
     507        },
     508
     509        // Internal functions
     510
     511        _fixIELayout : function(id, s) {
     512            var w, img;
     513
     514            if (!tinymce.isIE6)
     515                return;
     516
     517            // Fixes the bug where hover flickers and does odd things in IE6
     518            each(['n','s','w','e','nw','ne','sw','se'], function(v) {
     519                var e = DOM.get(id + '_resize_' + v);
     520
     521                DOM.setStyles(e, {
     522                    width : s ? e.clientWidth : '',
     523                    height : s ? e.clientHeight : '',
     524                    cursor : DOM.getStyle(e, 'cursor', 1)
     525                });
     526
     527                DOM.setStyle(id + "_bottom", 'bottom', '-1px');
     528
     529                e = 0;
     530            });
     531
     532            // Fixes graphics glitch
     533            if (w = this.windows[id]) {
     534                // Fixes rendering bug after resize
     535                w.element.hide();
     536                w.element.show();
     537
     538                // Forced a repaint of the window
     539                //DOM.get(id).style.filter = '';
     540
     541                // IE has a bug where images used in CSS won't get loaded
     542                // sometimes when the cache in the browser is disabled
     543                // This fix tries to solve it by loading the images using the image object
     544                each(DOM.select('div,a', id), function(e, i) {
     545                    if (e.currentStyle.backgroundImage != 'none') {
     546                        img = new Image();
     547                        img.src = e.currentStyle.backgroundImage.replace(/url\(\"(.+)\"\)/, '$1');
     548                    }
     549                });
     550
     551                DOM.get(id).style.filter = '';
     552            }
    104553        }
    105     }
    106 
    107     if (!gotit)
    108         this.orgCloseWindow(win);
    109 
    110     tinyMCE.selectedInstance.getWin().focus();
    111 };
    112 
    113 TinyMCE_Engine.prototype.setWindowTitle = function(win_ref, title) {
    114     for (var n in mcWindows.windows) {
    115         var win = mcWindows.windows[n];
    116         if (typeof(win) == 'function')
    117             continue;
    118 
    119         if (win_ref.name == win.id + "_iframe")
    120             window.frames[win.id + "_iframe"].document.getElementById(win.id + '_title').innerHTML = title;
    121     }
    122 };
    123 
    124 // * * * * * TinyMCE_Windows classes below
    125 
    126 // Windows handler
    127 function TinyMCE_Windows() {
    128     this.settings = new Array();
    129     this.windows = new Array();
    130     this.isMSIE = (navigator.appName == "Microsoft Internet Explorer");
    131     this.isGecko = navigator.userAgent.indexOf('Gecko') != -1;
    132     this.isSafari = navigator.userAgent.indexOf('Safari') != -1;
    133     this.isMac = navigator.userAgent.indexOf('Mac') != -1;
    134     this.isMSIE5_0 = this.isMSIE && (navigator.userAgent.indexOf('MSIE 5.0') != -1);
    135     this.action = "none";
    136     this.selectedWindow = null;
    137     this.lastSelectedWindow = null;
    138     this.zindex = 1001;
    139     this.mouseDownScreenX = 0;
    140     this.mouseDownScreenY = 0;
    141     this.mouseDownLayerX = 0;
    142     this.mouseDownLayerY = 0;
    143     this.mouseDownWidth = 0;
    144     this.mouseDownHeight = 0;
    145     this.idCounter = 0;
    146 };
    147 
    148 TinyMCE_Windows.prototype.init = function(settings) {
    149     this.settings = settings;
    150 
    151     if (this.isMSIE)
    152         this.addEvent(document, "mousemove", mcWindows.eventDispatcher);
    153     else
    154         this.addEvent(window, "mousemove", mcWindows.eventDispatcher);
    155 
    156     this.addEvent(document, "mouseup", mcWindows.eventDispatcher);
    157 
    158     this.addEvent(window, "resize", mcWindows.eventDispatcher);
    159     this.addEvent(document, "scroll", mcWindows.eventDispatcher);
    160 
    161     this.doc = document;
    162 };
    163 
    164 TinyMCE_Windows.prototype.getBounds = function() {
    165     if (!this.bounds) {
    166         var vp = tinyMCE.getViewPort(window);
    167         var top, left, bottom, right, docEl = this.doc.documentElement;
    168 
    169         top    = vp.top;
    170         left   = vp.left;
    171         bottom = vp.height + top - 2;
    172         right  = vp.width  + left - 22; // TODO this number is platform dependant
    173         // x1, y1, x2, y2
    174         this.bounds = [left, top, right, bottom];
    175     }
    176     return this.bounds;
    177 };
    178 
    179 TinyMCE_Windows.prototype.clampBoxPosition = function(x, y, w, h, minW, minH) {
    180     var bounds = this.getBounds();
    181 
    182     x = Math.max(bounds[0], Math.min(bounds[2], x + w) - w);
    183     y = Math.max(bounds[1], Math.min(bounds[3], y + h) - h);
    184 
    185     return this.clampBoxSize(x, y, w, h, minW, minH);
    186 };
    187 
    188 TinyMCE_Windows.prototype.clampBoxSize = function(x, y, w, h, minW, minH) {
    189     var bounds = this.getBounds();
    190 
    191     return [
    192         x, y,
    193         Math.max(minW, Math.min(bounds[2], x + w) - x),
    194         Math.max(minH, Math.min(bounds[3], y + h) - y)
    195     ];
    196 };
    197 
    198 TinyMCE_Windows.prototype.getParam = function(name, default_value) {
    199     var value = null;
    200 
    201     value = (typeof(this.settings[name]) == "undefined") ? default_value : this.settings[name];
    202 
    203     // Fix bool values
    204     if (value == "true" || value == "false")
    205         return (value == "true");
    206 
    207     return value;
    208 };
    209 
    210 TinyMCE_Windows.prototype.eventDispatcher = function(e) {
    211     e = typeof(e) == "undefined" ? window.event : e;
    212 
    213     if (mcWindows.selectedWindow == null)
    214         return;
    215 
    216     // Switch focus
    217     if (mcWindows.isGecko && e.type == "mousedown") {
    218         var elm = e.currentTarget;
    219 
    220         for (var n in mcWindows.windows) {
    221             var win = mcWindows.windows[n];
    222 
    223             if (win.headElement == elm || win.resizeElement == elm) {
    224                 win.focus();
    225                 break;
    226             }
    227         }
    228     }
    229 
    230     switch (e.type) {
    231         case "mousemove":
    232             mcWindows.selectedWindow.onMouseMove(e);
    233             break;
    234 
    235         case "mouseup":
    236             mcWindows.selectedWindow.onMouseUp(e);
    237             break;
    238 
    239         case "mousedown":
    240             mcWindows.selectedWindow.onMouseDown(e);
    241             break;
    242 
    243         case "focus":
    244             mcWindows.selectedWindow.onFocus(e);
    245             break;
    246         case "scroll":
    247         case "resize":
    248             if (mcWindows.clampUpdateTimeout)
    249                 clearTimeout(mcWindows.clampUpdateTimeout);
    250             mcWindows.clampEventType = e.type;
    251             mcWindows.clampUpdateTimeout =
    252                 setTimeout(function () {mcWindows.updateClamping()}, 100);
    253             break;
    254     }
    255 };
    256 
    257 TinyMCE_Windows.prototype.updateClamping = function () {
    258     var clamp, oversize, etype = mcWindows.clampEventType;
    259 
    260     this.bounds = null; // Recalc window bounds on resize/scroll
    261     this.clampUpdateTimeout = null;
    262 
    263     for (var n in this.windows) {
    264         win = this.windows[n];
    265         if (typeof(win) == 'function' || ! win.winElement) continue;
    266 
    267         clamp = mcWindows.clampBoxPosition(
    268             win.left, win.top,
    269             win.winElement.scrollWidth,
    270             win.winElement.scrollHeight,
    271             win.features.minWidth,
    272             win.features.minHeight
    273         );
    274         oversize = (
    275             clamp[2] != win.winElement.scrollWidth ||
    276             clamp[3] != win.winElement.scrollHeight
    277         ) ? true : false;
    278 
    279         if (!oversize || win.features.resizable == "yes" || etype != "scroll")
    280             win.moveTo(clamp[0], clamp[1]);
    281         if (oversize && win.features.resizable == "yes")
    282             win.resizeTo(clamp[2], clamp[3]);
    283     }
    284 };
    285 
    286 TinyMCE_Windows.prototype.addEvent = function(obj, name, handler) {
    287     if (this.isMSIE)
    288         obj.attachEvent("on" + name, handler);
    289     else
    290         obj.addEventListener(name, handler, false);
    291 };
    292 
    293 TinyMCE_Windows.prototype.cancelEvent = function(e) {
    294     if (this.isMSIE) {
    295         e.returnValue = false;
    296         e.cancelBubble = true;
    297     } else
    298         e.preventDefault();
    299 };
    300 
    301 TinyMCE_Windows.prototype.parseFeatures = function(opts) {
    302     // Cleanup the options
    303     opts = opts.toLowerCase();
    304     opts = opts.replace(/;/g, ",");
    305     opts = opts.replace(/[^0-9a-z=,]/g, "");
    306 
    307     var optionChunks = opts.split(',');
    308     var options = new Array();
    309 
    310     options['left'] = "10";
    311     options['top'] = "10";
    312     options['width'] = "300";
    313     options['height'] = "300";
    314     options['minwidth'] = "100";
    315     options['minheight'] = "100";
    316     options['resizable'] = "yes";
    317     options['minimizable'] = "yes";
    318     options['maximizable'] = "yes";
    319     options['close'] = "yes";
    320     options['movable'] = "yes";
    321     options['statusbar'] = "yes";
    322     options['scrollbars'] = "auto";
    323     options['modal'] = "no";
    324 
    325     if (opts == "")
    326         return options;
    327 
    328     for (var i=0; i<optionChunks.length; i++) {
    329         var parts = optionChunks[i].split('=');
    330 
    331         if (parts.length == 2)
    332             options[parts[0]] = parts[1];
    333     }
    334 
    335     options['left'] = parseInt(options['left']);
    336     options['top'] = parseInt(options['top']);
    337     options['width'] = parseInt(options['width']);
    338     options['height'] = parseInt(options['height']);
    339     options['minWidth'] = parseInt(options['minwidth']);
    340     options['minHeight'] = parseInt(options['minheight']);
    341 
    342     return options;
    343 };
    344 
    345 TinyMCE_Windows.prototype.open = function(url, name, features) {
    346     this.lastSelectedWindow = this.selectedWindow;
    347 
    348     var win = new TinyMCE_Window();
    349     var winDiv, html = "", id;
    350     var imgPath = this.getParam("images_path");
    351 
    352     features = this.parseFeatures(features);
    353 
    354     // Clamp specified dimensions
    355     var clamp = mcWindows.clampBoxPosition(
    356         features['left'], features['top'],
    357         features['width'], features['height'],
    358         features['minWidth'], features['minHeight']
    359     );
    360 
    361     features['left'] = clamp[0];
    362     features['top'] = clamp[1];
    363 
    364     if (features['resizable'] == "yes") {
    365         features['width'] = clamp[2];
    366         features['height'] = clamp[3];
    367     }
    368 
    369     // Create div
    370     id = "mcWindow_" + name;
    371     win.deltaHeight = 18;
    372 
    373     if (features['statusbar'] == "yes") {
    374         win.deltaHeight += 13;
    375 
    376         if (this.isMSIE)
    377             win.deltaHeight += 1;
    378     }
    379 
    380     width = parseInt(features['width']);
    381     height = parseInt(features['height'])-win.deltaHeight;
    382 
    383     if (this.isMSIE)
    384         width -= 2;
    385 
    386     // Setup first part of window
    387     win.id = id;
    388     win.url = url;
    389     win.name = name;
    390     win.features = features;
    391     this.windows[name] = win;
    392 
    393     iframeWidth = width;
    394     iframeHeight = height;
    395 
    396     // Create inner content
    397     html += '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">';
    398     html += '<html>';
    399     html += '<head>';
    400     html += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">';
    401     html += '<title>Wrapper iframe</title>';
    402    
    403     // WordPress: put the window buttons on the left as in Macs
    404     if (this.isMac) html += '<style type="text/css">.mceWindowTitle{float:none;margin:0;width:100%;text-align:center;}.mceWindowClose{float:none;position:absolute;left:0px;top:0px;}</style>';
    405    
    406     html += '<link href="' + this.getParam("css_file") + '" rel="stylesheet" type="text/css" />';
    407     html += '</head>';
    408     html += '<body onload="parent.mcWindows.onLoad(\'' + name + '\');">';
    409 
    410     html += '<div id="' + id + '_container" class="mceWindow">';
    411     html += '<div id="' + id + '_head" class="mceWindowHead" onmousedown="parent.mcWindows.windows[\'' + name + '\'].focus();">';
    412     html += '  <div id="' + id + '_title" class="mceWindowTitle"';
    413     html += '  onselectstart="return false;" unselectable="on" style="-moz-user-select: none !important;"></div>';
    414     html += '    <div class="mceWindowHeadTools">';
    415     html += '      <a href="javascript:parent.mcWindows.windows[\'' + name + '\'].close();" target="_self" onmousedown="return false;" class="mceWindowClose"><img border="0" src="' + imgPath + '/window_close.gif" /></a>';
    416     if (features['resizable'] == "yes" && features['maximizable'] == "yes")
    417         html += '      <a href="javascript:parent.mcWindows.windows[\'' + name + '\'].maximize();" target="_self" onmousedown="return false;" class="mceWindowMaximize"><img border="0" src="' + imgPath + '/window_maximize.gif" /></a>';
    418     // html += '      <a href="javascript:mcWindows.windows[\'' + name + '\'].minimize();" target="_self" onmousedown="return false;" class="mceWindowMinimize"></a>';
    419     html += '    </div>';
    420     html += '</div><div id="' + id + '_body" class="mceWindowBody" style="width: ' + width + 'px; height: ' + height + 'px;">';
    421     html += '<iframe id="' + id + '_iframe" name="' + id + '_iframe" frameborder="0" width="' + iframeWidth + '" height="' + iframeHeight + '" src="' + url + '" class="mceWindowBodyIframe" scrolling="' + features['scrollbars'] + '"></iframe></div>';
    422 
    423     if (features['statusbar'] == "yes") {
    424         html += '<div id="' + id + '_statusbar" class="mceWindowStatusbar" onmousedown="parent.mcWindows.windows[\'' + name + '\'].focus();">';
    425 
    426         if (features['resizable'] == "yes") {
    427             if (this.isGecko)
    428                 html += '<div id="' + id + '_resize" class="mceWindowResize"><div style="background-image: url(\'' + imgPath + '/window_resize.gif\'); width: 12px; height: 12px;"></div></div>';
    429             else
    430                 html += '<div id="' + id + '_resize" class="mceWindowResize"><img onmousedown="parent.mcWindows.windows[\'' + name + '\'].focus();" border="0" src="' + imgPath + '/window_resize.gif" /></div>';
    431         }
    432 
    433         html += '</div>';
    434     }
    435 
    436     html += '</div>';
    437 
    438     html += '</body>';
    439     html += '</html>';
    440 
    441     // Create iframe
    442     this.createFloatingIFrame(id, features['left'], features['top'], features['width'], features['height'], html);
    443 };
    444 
    445 // Blocks the document events by placing a image over the whole document
    446 TinyMCE_Windows.prototype.setDocumentLock = function(state) {
    447     var elm = document.getElementById('mcWindowEventBlocker');
    448 
    449     if (state) {
    450         if (elm == null) {
    451             elm = document.createElement("div");
    452 
    453             elm.id = "mcWindowEventBlocker";
    454             elm.style.position = "absolute";
    455             elm.style.left = "0";
    456             elm.style.top = "0";
    457 
    458             document.body.appendChild(elm);
    459         }
    460 
    461         elm.style.display = "none";
    462 
    463         var imgPath = this.getParam("images_path");
    464         var width = document.body.clientWidth;
    465         var height = document.body.clientHeight;
    466 
    467         elm.style.width = width;
    468         elm.style.height = height;
    469         elm.innerHTML = '<img src="' + imgPath + '/spacer.gif" width="' + width + '" height="' + height + '" />';
    470 
    471         elm.style.zIndex = mcWindows.zindex-1;
    472         elm.style.display = "block";
    473     } else if (elm != null) {
    474         if (mcWindows.windows.length == 0)
    475             elm.parentNode.removeChild(elm);
    476         else
    477             elm.style.zIndex = mcWindows.zindex-1;
    478     }
    479 };
    480 
    481 // Gets called when wrapper iframe is initialized
    482 TinyMCE_Windows.prototype.onLoad = function(name) {
    483     var win = mcWindows.windows[name];
    484     var id = "mcWindow_" + name;
    485     var wrapperIframe = window.frames[id + "_iframe"].frames[0];
    486     var wrapperDoc = window.frames[id + "_iframe"].document;
    487     var doc = window.frames[id + "_iframe"].document;
    488     var winDiv = document.getElementById("mcWindow_" + name + "_div");
    489     var realIframe = window.frames[id + "_iframe"].frames[0];
    490 
    491     // Set window data
    492     win.id = "mcWindow_" + name;
    493     win.winElement = winDiv;
    494     win.bodyElement = doc.getElementById(id + '_body');
    495     win.iframeElement = doc.getElementById(id + '_iframe');
    496     win.headElement = doc.getElementById(id + '_head');
    497     win.titleElement = doc.getElementById(id + '_title');
    498     win.resizeElement = doc.getElementById(id + '_resize');
    499     win.containerElement = doc.getElementById(id + '_container');
    500     win.left = win.features['left'];
    501     win.top = win.features['top'];
    502     win.frame = window.frames[id + '_iframe'].frames[0];
    503     win.wrapperFrame = window.frames[id + '_iframe'];
    504     win.wrapperIFrameElement = document.getElementById(id + "_iframe");
    505 
    506     // Add event handlers
    507     mcWindows.addEvent(win.headElement, "mousedown", mcWindows.eventDispatcher);
    508 
    509     if (win.resizeElement != null)
    510         mcWindows.addEvent(win.resizeElement, "mousedown", mcWindows.eventDispatcher);
    511 
    512     if (mcWindows.isMSIE) {
    513         mcWindows.addEvent(realIframe.document, "mousemove", mcWindows.eventDispatcher);
    514         mcWindows.addEvent(realIframe.document, "mouseup", mcWindows.eventDispatcher);
    515     } else {
    516         mcWindows.addEvent(realIframe, "mousemove", mcWindows.eventDispatcher);
    517         mcWindows.addEvent(realIframe, "mouseup", mcWindows.eventDispatcher);
    518         mcWindows.addEvent(realIframe, "focus", mcWindows.eventDispatcher);
    519     }
    520 
    521     for (var i=0; i<window.frames.length; i++) {
    522         if (!window.frames[i]._hasMouseHandlers) {
    523             if (mcWindows.isMSIE) {
    524                 mcWindows.addEvent(window.frames[i].document, "mousemove", mcWindows.eventDispatcher);
    525                 mcWindows.addEvent(window.frames[i].document, "mouseup", mcWindows.eventDispatcher);
    526             } else {
    527                 mcWindows.addEvent(window.frames[i], "mousemove", mcWindows.eventDispatcher);
    528                 mcWindows.addEvent(window.frames[i], "mouseup", mcWindows.eventDispatcher);
    529             }
    530 
    531             window.frames[i]._hasMouseHandlers = true;
    532         }
    533     }
    534 
    535     if (mcWindows.isMSIE) {
    536         mcWindows.addEvent(win.frame.document, "mousemove", mcWindows.eventDispatcher);
    537         mcWindows.addEvent(win.frame.document, "mouseup", mcWindows.eventDispatcher);
    538     } else {
    539         mcWindows.addEvent(win.frame, "mousemove", mcWindows.eventDispatcher);
    540         mcWindows.addEvent(win.frame, "mouseup", mcWindows.eventDispatcher);
    541         mcWindows.addEvent(win.frame, "focus", mcWindows.eventDispatcher);
    542     }
    543 
    544     // Dispatch open window event
    545     var func = this.getParam("on_open_window", "");
    546     if (func != "")
    547         eval(func + "(win);");
    548 
    549     win.focus();
    550 
    551     if (win.features['modal'] == "yes")
    552         mcWindows.setDocumentLock(true);
    553 };
    554 
    555 TinyMCE_Windows.prototype.createFloatingIFrame = function(id_prefix, left, top, width, height, html) {
    556     var iframe = document.createElement("iframe");
    557     var div = document.createElement("div"), doc;
    558 
    559     width = parseInt(width);
    560     height = parseInt(height)+1;
    561 
    562     // Create wrapper div
    563     div.setAttribute("id", id_prefix + "_div");
    564     div.setAttribute("width", width);
    565     div.setAttribute("height", (height));
    566     div.style.position = "absolute";
    567 
    568     div.style.left = left + "px";
    569     div.style.top = top + "px";
    570     div.style.width = width + "px";
    571     div.style.height = (height) + "px";
    572     div.style.backgroundColor = "white";
    573     div.style.display = "none";
    574 
    575     if (this.isGecko) {
    576         iframeWidth = width + 2;
    577         iframeHeight = height + 2;
    578     } else {
    579         iframeWidth = width;
    580         iframeHeight = height + 1;
    581     }
    582 
    583     // Create iframe
    584     iframe.setAttribute("id", id_prefix + "_iframe");
    585     iframe.setAttribute("name", id_prefix + "_iframe");
    586     iframe.setAttribute("border", "0");
    587     iframe.setAttribute("frameBorder", "0");
    588     iframe.setAttribute("marginWidth", "0");
    589     iframe.setAttribute("marginHeight", "0");
    590     iframe.setAttribute("leftMargin", "0");
    591     iframe.setAttribute("topMargin", "0");
    592     iframe.setAttribute("width", iframeWidth);
    593     iframe.setAttribute("height", iframeHeight);
    594     // iframe.setAttribute("src", "../jscripts/tiny_mce/blank.htm");
    595     // iframe.setAttribute("allowtransparency", "false");
    596     iframe.setAttribute("scrolling", "no");
    597     iframe.style.width = iframeWidth + "px";
    598     iframe.style.height = iframeHeight + "px";
    599     iframe.style.backgroundColor = "white";
    600     div.appendChild(iframe);
    601 
    602     document.body.appendChild(div);
    603 
    604     // Fixed MSIE 5.0 issue
    605     div.innerHTML = div.innerHTML;
    606 
    607     if (this.isSafari) {
    608         // Give Safari some time to setup
    609         window.setTimeout(function() {
    610             var doc = window.frames[id_prefix + '_iframe'].document;
    611             doc.open();
    612             doc.write(html);
    613             doc.close();
    614         }, 10);
    615     } else {
    616         doc = window.frames[id_prefix + '_iframe'].window.document;
    617         doc.open();
    618         doc.write(html);
    619         doc.close();
    620     }
    621 
    622     div.style.display = "block";
    623 
    624     return div;
    625 };
    626 
    627 // Window instance
    628 function TinyMCE_Window() {
    629 };
    630 
    631 TinyMCE_Window.prototype.focus = function() {
    632     if (this != mcWindows.selectedWindow) {
    633         this.winElement.style.zIndex = ++mcWindows.zindex;
    634         mcWindows.lastSelectedWindow = mcWindows.selectedWindow;
    635         mcWindows.selectedWindow = this;
    636     }
    637 };
    638 
    639 TinyMCE_Window.prototype.minimize = function() {
    640 };
    641 
    642 TinyMCE_Window.prototype.maximize = function() {
    643     if (this.restoreSize) {
    644         this.moveTo(this.restoreSize[0], this.restoreSize[1]);
    645         this.resizeTo(this.restoreSize[2], this.restoreSize[3]);
    646         this.updateClamping();
    647         this.restoreSize = null;
    648     } else {
    649         var bounds = mcWindows.getBounds();
    650         this.restoreSize = [
    651             this.left, this.top,
    652             this.winElement.scrollWidth,
    653             this.winElement.scrollHeight
    654         ];
    655         this.moveTo(bounds[0], bounds[1]);
    656         this.resizeTo(
    657             bounds[2] - bounds[0],
    658             bounds[3] - bounds[1]
    659         );
    660     }
    661 };
    662 
    663 TinyMCE_Window.prototype.startResize = function() {
    664     mcWindows.action = "resize";
    665 };
    666 
    667 TinyMCE_Window.prototype.startMove = function(e) {
    668     mcWindows.action = "move";
    669 };
    670 
    671 TinyMCE_Window.prototype.close = function() {
    672     if (this.frame && this.frame['tinyMCEPopup'])
    673         this.frame['tinyMCEPopup'].restoreSelection();
    674 
    675     if (mcWindows.lastSelectedWindow != null)
    676         mcWindows.lastSelectedWindow.focus();
    677 
    678     var mcWindowsNew = new Array();
    679     for (var n in mcWindows.windows) {
    680         var win = mcWindows.windows[n];
    681         if (typeof(win) == 'function')
    682             continue;
    683 
    684         if (win.name != this.name)
    685             mcWindowsNew[n] = win;
    686     }
    687 
    688     mcWindows.windows = mcWindowsNew;
    689 
    690     // alert(mcWindows.doc.getElementById(this.id + "_iframe"));
    691 
    692     var e = mcWindows.doc.getElementById(this.id + "_iframe");
    693     e.parentNode.removeChild(e);
    694 
    695     var e = mcWindows.doc.getElementById(this.id + "_div");
    696     e.parentNode.removeChild(e);
    697 
    698     mcWindows.setDocumentLock(false);
    699 };
    700 
    701 TinyMCE_Window.prototype.onMouseMove = function(e) {
    702     var clamp;
    703     // Calculate real X, Y
    704     var dx = e.screenX - mcWindows.mouseDownScreenX;
    705     var dy = e.screenY - mcWindows.mouseDownScreenY;
    706 
    707     switch (mcWindows.action) {
    708         case "resize":
    709             clamp = mcWindows.clampBoxSize(
    710                 this.left, this.top,
    711                 mcWindows.mouseDownWidth + (e.screenX - mcWindows.mouseDownScreenX),
    712                 mcWindows.mouseDownHeight + (e.screenY - mcWindows.mouseDownScreenY),
    713                 this.features.minWidth, this.features.minHeight
    714             );
    715 
    716             this.resizeTo(clamp[2], clamp[3]);
    717 
    718             mcWindows.cancelEvent(e);
    719             break;
    720 
    721         case "move":
    722             this.left = mcWindows.mouseDownLayerX + (e.screenX - mcWindows.mouseDownScreenX);
    723             this.top = mcWindows.mouseDownLayerY + (e.screenY - mcWindows.mouseDownScreenY);
    724             this.updateClamping();
    725 
    726             mcWindows.cancelEvent(e);
    727             break;
    728     }
    729 };
    730 
    731 TinyMCE_Window.prototype.moveTo = function (x, y) {
    732     this.left = x;
    733     this.top = y;
    734 
    735     this.winElement.style.left = this.left + "px";
    736     this.winElement.style.top = this.top + "px";
    737 };
    738 
    739 TinyMCE_Window.prototype.resizeTo = function (width, height) {
    740     this.wrapperIFrameElement.style.width = (width+2) + 'px';
    741     this.wrapperIFrameElement.style.height = (height+2) + 'px';
    742     this.wrapperIFrameElement.width = width+2;
    743     this.wrapperIFrameElement.height = height+2;
    744     this.winElement.style.width = width + 'px';
    745     this.winElement.style.height = height + 'px';
    746 
    747     height = height - this.deltaHeight;
    748 
    749     this.containerElement.style.width = width + 'px';
    750     this.iframeElement.style.width = width + 'px';
    751     this.iframeElement.style.height = height + 'px';
    752     this.bodyElement.style.width = width + 'px';
    753     this.bodyElement.style.height = height + 'px';
    754     this.headElement.style.width = width + 'px';
    755     //this.statusElement.style.width = width + 'px';
    756 };
    757 
    758 TinyMCE_Window.prototype.updateClamping = function () {
    759     var clamp, oversize;
    760 
    761     clamp = mcWindows.clampBoxPosition(
    762         this.left, this.top,
    763         this.winElement.scrollWidth,
    764         this.winElement.scrollHeight,
    765         this.features.minWidth, this.features.minHeight
    766     );
    767     oversize = (
    768         clamp[2] != this.winElement.scrollWidth ||
    769         clamp[3] != this.winElement.scrollHeight
    770     ) ? true : false;
    771 
    772     this.moveTo(clamp[0], clamp[1]);
    773     if (this.features.resizable == "yes" && oversize)
    774         this.resizeTo(clamp[2], clamp[3]);
    775 };
    776 
    777 function debug(msg) {
    778     document.getElementById('debug').value += msg + "\n";
    779 }
    780 
    781 TinyMCE_Window.prototype.onMouseUp = function(e) {
    782     mcWindows.action = "none";
    783 };
    784 
    785 TinyMCE_Window.prototype.onFocus = function(e) {
    786     // Gecko only handler
    787     var winRef = e.currentTarget;
    788 
    789     for (var n in mcWindows.windows) {
    790         var win = mcWindows.windows[n];
    791         if (typeof(win) == 'function')
    792             continue;
    793 
    794         if (winRef.name == win.id + "_iframe") {
    795             win.focus();
    796             return;
    797         }
    798     }
    799 };
    800 
    801 TinyMCE_Window.prototype.onMouseDown = function(e) {
    802     var elm = mcWindows.isMSIE ? this.wrapperFrame.event.srcElement : e.target;
    803 
    804     mcWindows.mouseDownScreenX = e.screenX;
    805     mcWindows.mouseDownScreenY = e.screenY;
    806     mcWindows.mouseDownLayerX = this.left;
    807     mcWindows.mouseDownLayerY = this.top;
    808     mcWindows.mouseDownWidth = parseInt(this.winElement.style.width);
    809     mcWindows.mouseDownHeight = parseInt(this.winElement.style.height);
    810 
    811     if (this.resizeElement != null && elm == this.resizeElement.firstChild)
    812         this.startResize(e);
    813     else
    814         this.startMove(e);
    815 
    816     mcWindows.cancelEvent(e);
    817 };
    818 
    819 // Global instance
    820 var mcWindows = new TinyMCE_Windows();
    821 
    822 // Initialize windows
    823 mcWindows.init({
    824     images_path : tinyMCE.baseURL + "/plugins/inlinepopups/images",
    825     css_file : tinyMCE.baseURL + "/plugins/inlinepopups/css/inlinepopup.css"
    826 });
     554    });
     555
     556    // Register plugin
     557    tinymce.PluginManager.add('inlinepopups', tinymce.plugins.InlinePopups);
     558})();
     559
  • trunk/wp-includes/js/tinymce/plugins/paste/blank.htm

    • Property svn:eol-style set to native
    r6568 r6632  
    11<html xmlns="http://www.w3.org/1999/xhtml">
    22<head>
    3     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    4     <title>blank_page</title>
    5     <script language="javascript">
    6         function init() {
    7             document.body.contentEditable = true;
    8             document.designMode = 'on';
    9             parent.initIframe(document);
    10             window.focus();
    11         }
    12     </script>
    13     <link href="css/blank.css" rel="stylesheet" type="text/css" />
    14     <base target="_self" />
     3<title>blank_page</title>
     4<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
     5<link href="css/blank.css" rel="stylesheet" type="text/css" />
     6<base target="_self" />
     7<script type="text/javascript">
     8function init() {
     9    if (parent.tinymce.isIE)
     10        document.body.contentEditable = true;
     11    else
     12        document.designMode = 'on';
     13
     14    parent.initIframe(document);
     15    window.focus();
     16}
     17</script>
    1518</head>
    1619<body onload="init();">
  • trunk/wp-includes/js/tinymce/plugins/paste/css/blank.css

    • Property svn:eol-style set to native
    r3664 r6632  
     1html, body {height:98%}
    12body {
    2     background-color: #FFFFFF;
    3     font-family: Verdana, Arial, Helvetica, sans-serif;
    4     font-size: 10px;
    5     scrollbar-3dlight-color: #F0F0EE;
    6     scrollbar-arrow-color: #676662;
    7     scrollbar-base-color: #F0F0EE;
    8     scrollbar-darkshadow-color: #DDDDDD;
    9     scrollbar-face-color: #E0E0DD;
    10     scrollbar-highlight-color: #F0F0EE;
    11     scrollbar-shadow-color: #F0F0EE;
    12     scrollbar-track-color: #F5F5F5;
     3background-color: #FFFFFF;
     4font-family: Verdana, Arial, Helvetica, sans-serif;
     5font-size: 10px;
     6scrollbar-3dlight-color: #F0F0EE;
     7scrollbar-arrow-color: #676662;
     8scrollbar-base-color: #F0F0EE;
     9scrollbar-darkshadow-color: #DDDDDD;
     10scrollbar-face-color: #E0E0DD;
     11scrollbar-highlight-color: #F0F0EE;
     12scrollbar-shadow-color: #F0F0EE;
     13scrollbar-track-color: #F5F5F5;
    1314}
  • trunk/wp-includes/js/tinymce/plugins/paste/css/pasteword.css

    • Property svn:eol-style set to native
  • trunk/wp-includes/js/tinymce/plugins/paste/editor_plugin.js

    r5256 r6632  
    11/**
    2  * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
     2 * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $
    33 *
    44 * @author Moxiecode
    5  * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
     5 * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
    66 */
    77
    8 /* Import plugin specific language pack */
    9 tinyMCE.importPluginLanguagePack('paste');
    10 
    11 var TinyMCE_PastePlugin = {
    12     getInfo : function() {
    13         return {
    14             longname : 'Paste text/word',
    15             author : 'Moxiecode Systems AB',
    16             authorurl : 'http://tinymce.moxiecode.com',
    17             infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste',
    18             version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
    19         };
    20     },
    21 
    22     initInstance : function(inst) {
    23         if (tinyMCE.isMSIE && tinyMCE.getParam("paste_auto_cleanup_on_paste", false))
    24             tinyMCE.addEvent(inst.getBody(), "paste", TinyMCE_PastePlugin._handlePasteEvent);
    25     },
    26 
    27     handleEvent : function(e) {
    28         // Force paste dialog if non IE browser
    29         if (!tinyMCE.isRealIE && tinyMCE.getParam("paste_auto_cleanup_on_paste", false) && e.ctrlKey && e.keyCode == 86 && e.type == "keydown") {
    30             window.setTimeout('tinyMCE.selectedInstance.execCommand("mcePasteText",true)', 1);
    31             return tinyMCE.cancelEvent(e);
     8(function() {
     9    var Event = tinymce.dom.Event;
     10
     11    tinymce.create('tinymce.plugins.PastePlugin', {
     12        init : function(ed, url) {
     13            var t = this;
     14
     15            t.editor = ed;
     16
     17            // Register commands
     18            ed.addCommand('mcePasteText', function(ui, v) {
     19                if (ui) {
     20                    ed.windowManager.open({
     21                        file : url + '/pastetext.htm',
     22                        width : 450,
     23                        height : 400,
     24                        inline : 1
     25                    }, {
     26                        plugin_url : url
     27                    });
     28                } else
     29                    t._insertText(v.html, v.linebreaks);
     30            });
     31
     32            ed.addCommand('mcePasteWord', function(ui, v) {
     33                if (ui) {
     34                    ed.windowManager.open({
     35                        file : url + '/pasteword.htm',
     36                        width : 450,
     37                        height : 400,
     38                        inline : 1
     39                    }, {
     40                        plugin_url : url
     41                    });
     42                } else
     43                    t._insertWordContent(v);
     44            });
     45
     46            ed.addCommand('mceSelectAll', function() {
     47                ed.execCommand('selectall');
     48            });
     49
     50            // Register buttons
     51            ed.addButton('pastetext', {title : 'paste.paste_text_desc', cmd : 'mcePasteText', ui : true});
     52            ed.addButton('pasteword', {title : 'paste.paste_word_desc', cmd : 'mcePasteWord', ui : true});
     53            ed.addButton('selectall', {title : 'paste.selectall_desc', cmd : 'mceSelectAll'});
     54
     55            if (ed.getParam("paste_auto_cleanup_on_paste", false)) {
     56                ed.onPaste.add(function(ed, e) {
     57                    return t._handlePasteEvent(e)
     58                });
     59            }
     60
     61            if (!tinymce.isIE && ed.getParam("paste_auto_cleanup_on_paste", false)) {
     62                // Force paste dialog if non IE browser
     63                ed.onKeyDown.add(function(ed, e) {
     64                    if (e.ctrlKey && e.keyCode == 86) {
     65                        window.setTimeout(function() {
     66                            ed.execCommand("mcePasteText", true);
     67                        }, 1);
     68
     69                        Event.cancel(e);
     70                    }
     71                });
     72            }
     73        },
     74
     75        getInfo : function() {
     76            return {
     77                longname : 'Paste text/word',
     78                author : 'Moxiecode Systems AB',
     79                authorurl : 'http://tinymce.moxiecode.com',
     80                infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste',
     81                version : tinymce.majorVersion + "." + tinymce.minorVersion
     82            };
     83        },
     84
     85        // Private methods
     86
     87        _handlePasteEvent : function(e) {
     88            var html = this._clipboardHTML(), ed = this.editor, sel = ed.selection, r;
     89
     90            // Removes italic, strong etc, the if was needed due to bug #1437114
     91            if (ed && (r = sel.getRng()) && r.text.length > 0)
     92                ed.execCommand('delete');
     93
     94            if (html && html.length > 0)
     95                ed.execCommand('mcePasteWord', false, html);
     96
     97            return Event.cancel(e);
     98        },
     99
     100        _insertText : function(content, bLinebreaks) {
     101            if (content && content.length > 0) {
     102                if (bLinebreaks) {
     103                    // Special paragraph treatment
     104                    if (this.editor.getParam("paste_create_paragraphs", true)) {
     105                        var rl = this.editor.getParam("paste_replace_list", '\u2122,<sup>TM</sup>,\u2026,...,\u201c|\u201d,",\u2019,\',\u2013|\u2014|\u2015|\u2212,-').split(',');
     106                        for (var i=0; i<rl.length; i+=2)
     107                            content = content.replace(new RegExp(rl[i], 'gi'), rl[i+1]);
     108
     109                        content = content.replace(/\r\n\r\n/g, '</p><p>');
     110                        content = content.replace(/\r\r/g, '</p><p>');
     111                        content = content.replace(/\n\n/g, '</p><p>');
     112
     113                        // Has paragraphs
     114                        if ((pos = content.indexOf('</p><p>')) != -1) {
     115                            this.editor.execCommand("Delete");
     116
     117                            var node = this.editor.selection.getNode();
     118
     119                            // Get list of elements to break
     120                            var breakElms = [];
     121
     122                            do {
     123                                if (node.nodeType == 1) {
     124                                    // Don't break tables and break at body
     125                                    if (node.nodeName == "TD" || node.nodeName == "BODY")
     126                                        break;
     127           
     128                                    breakElms[breakElms.length] = node;
     129                                }
     130                            } while(node = node.parentNode);
     131
     132                            var before = "", after = "</p>";
     133                            before += content.substring(0, pos);
     134
     135                            for (var i=0; i<breakElms.length; i++) {
     136                                before += "</" + breakElms[i].nodeName + ">";
     137                                after += "<" + breakElms[(breakElms.length-1)-i].nodeName + ">";
     138                            }
     139
     140                            before += "<p>";
     141                            content = before + content.substring(pos+7) + after;
     142                        }
     143                    }
     144
     145                    if (this.editor.getParam("paste_create_linebreaks", true)) {
     146                        content = content.replace(/\r\n/g, '<br />');
     147                        content = content.replace(/\r/g, '<br />');
     148                        content = content.replace(/\n/g, '<br />');
     149                    }
     150                }
     151           
     152                this.editor.execCommand("mceInsertRawHTML", false, content);
     153            }
     154        },
     155
     156        _insertWordContent : function(content) {
     157            var t = this, ed = t.editor;
     158
     159            if (content && content.length > 0) {
     160                // Cleanup Word content
     161                var bull = String.fromCharCode(8226);
     162                var middot = String.fromCharCode(183);
     163                var cb;
     164
     165                if ((cb = this.editor.getParam("paste_insert_word_content_callback", "")) != "")
     166                    content = eval(cb + "('before', content)");
     167
     168                var rl = this.editor.getParam("paste_replace_list", '\u2122,<sup>TM</sup>,\u2026,...,\u201c|\u201d,",\u2019,\',\u2013|\u2014|\u2015|\u2212,-').split(',');
     169                for (var i=0; i<rl.length; i+=2)
     170                    content = content.replace(new RegExp(rl[i], 'gi'), rl[i+1]);
     171
     172                if (this.editor.getParam("paste_convert_headers_to_strong", false)) {
     173                    content = content.replace(new RegExp('<p class=MsoHeading.*?>(.*?)<\/p>', 'gi'), '<p><b>$1</b></p>');
     174                }
     175
     176                content = content.replace(new RegExp('tab-stops: list [0-9]+.0pt">', 'gi'), '">' + "--list--");
     177                content = content.replace(new RegExp(bull + "(.*?)<BR>", "gi"), "<p>" + middot + "$1</p>");
     178                content = content.replace(new RegExp('<SPAN style="mso-list: Ignore">', 'gi'), "<span>" + bull); // Covert to bull list
     179                content = content.replace(/<o:p><\/o:p>/gi, "");
     180                content = content.replace(new RegExp('<br style="page-break-before: always;.*>', 'gi'), '-- page break --'); // Replace pagebreaks
     181                content = content.replace(new RegExp('<(!--)([^>]*)(--)>', 'g'), "");  // Word comments
     182
     183                if (this.editor.getParam("paste_remove_spans", true))
     184                    content = content.replace(/<\/?span[^>]*>/gi, "");
     185
     186                if (this.editor.getParam("paste_remove_styles", true))
     187                    content = content.replace(new RegExp('<(\\w[^>]*) style="([^"]*)"([^>]*)', 'gi'), "<$1$3");
     188
     189                content = content.replace(/<\/?font[^>]*>/gi, "");
     190
     191                // Strips class attributes.
     192                switch (this.editor.getParam("paste_strip_class_attributes", "all")) {
     193                    case "all":
     194                        content = content.replace(/<(\w[^>]*) class=([^ |>]*)([^>]*)/gi, "<$1$3");
     195                        break;
     196
     197                    case "mso":
     198                        content = content.replace(new RegExp('<(\\w[^>]*) class="?mso([^ |>]*)([^>]*)', 'gi'), "<$1$3");
     199                        break;
     200                }
     201
     202                content = content.replace(new RegExp('href="?' + this._reEscape("" + document.location) + '', 'gi'), 'href="' + this.editor.documentBaseURI.getURI());
     203                content = content.replace(/<(\w[^>]*) lang=([^ |>]*)([^>]*)/gi, "<$1$3");
     204                content = content.replace(/<\\?\?xml[^>]*>/gi, "");
     205                content = content.replace(/<\/?\w+:[^>]*>/gi, "");
     206                content = content.replace(/-- page break --\s*<p>&nbsp;<\/p>/gi, ""); // Remove pagebreaks
     207                content = content.replace(/-- page break --/gi, ""); // Remove pagebreaks
     208
     209        //      content = content.replace(/\/?&nbsp;*/gi, ""); &nbsp;
     210        //      content = content.replace(/<p>&nbsp;<\/p>/gi, '');
     211
     212                if (!this.editor.getParam('force_p_newlines')) {
     213                    content = content.replace('', '' ,'gi');
     214                    content = content.replace('</p>', '<br /><br />' ,'gi');
     215                }
     216
     217                if (!tinymce.isIE && !this.editor.getParam('force_p_newlines')) {
     218                    content = content.replace(/<\/?p[^>]*>/gi, "");
     219                }
     220
     221                content = content.replace(/<\/?div[^>]*>/gi, "");
     222
     223                // Convert all middlot lists to UL lists
     224                if (this.editor.getParam("paste_convert_middot_lists", true)) {
     225                    var div = ed.dom.create("div", null, content);
     226
     227                    // Convert all middot paragraphs to li elements
     228                    var className = this.editor.getParam("paste_unindented_list_class", "unIndentedList");
     229
     230                    while (this._convertMiddots(div, "--list--")) ; // bull
     231                    while (this._convertMiddots(div, middot, className)) ; // Middot
     232                    while (this._convertMiddots(div, bull)) ; // bull
     233
     234                    content = div.innerHTML;
     235                }
     236
     237                // Replace all headers with strong and fix some other issues
     238                if (this.editor.getParam("paste_convert_headers_to_strong", false)) {
     239                    content = content.replace(/<h[1-6]>&nbsp;<\/h[1-6]>/gi, '<p>&nbsp;&nbsp;</p>');
     240                    content = content.replace(/<h[1-6]>/gi, '<p><b>');
     241                    content = content.replace(/<\/h[1-6]>/gi, '</b></p>');
     242                    content = content.replace(/<b>&nbsp;<\/b>/gi, '<b>&nbsp;&nbsp;</b>');
     243                    content = content.replace(/^(&nbsp;)*/gi, '');
     244                }
     245
     246                content = content.replace(/--list--/gi, ""); // Remove --list--
     247
     248                if ((cb = this.editor.getParam("paste_insert_word_content_callback", "")) != "")
     249                    content = eval(cb + "('after', content)");
     250
     251                // Insert cleaned content
     252                this.editor.execCommand("mceInsertContent", false, content);
     253
     254                if (this.editor.getParam('paste_force_cleanup_wordpaste', true)) {
     255                    var ed = this.editor;
     256
     257                    window.setTimeout(function() {
     258                        ed.execCommand("mceCleanup");
     259                    }, 1); // Do normal cleanup detached from this thread
     260                }
     261            }
     262        },
     263
     264        _reEscape : function(s) {
     265            var l = "?.\\*[](){}+^$:";
     266            var o = "";
     267
     268            for (var i=0; i<s.length; i++) {
     269                var c = s.charAt(i);
     270
     271                if (l.indexOf(c) != -1)
     272                    o += '\\' + c;
     273                else
     274                    o += c;
     275            }
     276
     277            return o;
     278        },
     279
     280        _convertMiddots : function(div, search, class_name) {
     281            var mdot = String.fromCharCode(183);
     282            var bull = String.fromCharCode(8226);
     283
     284            var nodes = div.getElementsByTagName("p");
     285            var prevul;
     286            for (var i=0; i<nodes.length; i++) {
     287                var p = nodes[i];
     288
     289                // Is middot
     290                if (p.innerHTML.indexOf(search) == 0) {
     291                    var ul = document.createElement("ul");
     292
     293                    if (class_name)
     294                        ul.className = class_name;
     295
     296                    // Add the first one
     297                    var li = document.createElement("li");
     298                    li.innerHTML = p.innerHTML.replace(new RegExp('' + mdot + '|' + bull + '|--list--|&nbsp;', "gi"), '');
     299                    ul.appendChild(li);
     300
     301                    // Add the rest
     302                    var np = p.nextSibling;
     303                    while (np) {
     304                        // If the node is whitespace, then
     305                        // ignore it and continue on.
     306                        if (np.nodeType == 3 && new RegExp('^\\s$', 'm').test(np.nodeValue)) {
     307                                np = np.nextSibling;
     308                                continue;
     309                        }
     310
     311                        if (search == mdot) {
     312                                if (np.nodeType == 1 && new RegExp('^o(\\s+|&nbsp;)').test(np.innerHTML)) {
     313                                        // Second level of nesting
     314                                        if (!prevul) {
     315                                                prevul = ul;
     316                                                ul = document.createElement("ul");
     317                                                prevul.appendChild(ul);
     318                                        }
     319                                        np.innerHTML = np.innerHTML.replace(/^o/, '');
     320                                } else {
     321                                        // Pop the stack if we're going back up to the first level
     322                                        if (prevul) {
     323                                                ul = prevul;
     324                                                prevul = null;
     325                                        }
     326                                        // Not element or middot paragraph
     327                                        if (np.nodeType != 1 || np.innerHTML.indexOf(search) != 0)
     328                                                break;
     329                                }
     330                        } else {
     331                                // Not element or middot paragraph
     332                                if (np.nodeType != 1 || np.innerHTML.indexOf(search) != 0)
     333                                        break;
     334                            }
     335
     336                        var cp = np.nextSibling;
     337                        var li = document.createElement("li");
     338                        li.innerHTML = np.innerHTML.replace(new RegExp('' + mdot + '|' + bull + '|--list--|&nbsp;', "gi"), '');
     339                        np.parentNode.removeChild(np);
     340                        ul.appendChild(li);
     341                        np = cp;
     342                    }
     343
     344                    p.parentNode.replaceChild(ul, p);
     345
     346                    return true;
     347                }
     348            }
     349
     350            return false;
     351        },
     352
     353        _clipboardHTML : function() {
     354            var div = document.getElementById('_TinyMCE_clipboardHTML');
     355
     356            if (!div) {
     357                var div = document.createElement('DIV');
     358                div.id = '_TinyMCE_clipboardHTML';
     359
     360                with (div.style) {
     361                    visibility = 'hidden';
     362                    overflow = 'hidden';
     363                    position = 'absolute';
     364                    width = 1;
     365                    height = 1;
     366                }
     367
     368                document.body.appendChild(div);
     369            }
     370
     371            div.innerHTML = '';
     372            var rng = document.body.createTextRange();
     373            rng.moveToElementText(div);
     374            rng.execCommand('Paste');
     375            var html = div.innerHTML;
     376            div.innerHTML = '';
     377            return html;
    32378        }
    33 
    34         return true;
    35     },
    36 
    37     getControlHTML : function(cn) {
    38         switch (cn) {
    39             case "pastetext":
    40                 return tinyMCE.getButtonHTML(cn, 'lang_paste_text_desc', '{$pluginurl}/images/pastetext.gif', 'mcePasteText', true);
    41 
    42             case "pasteword":
    43                 return tinyMCE.getButtonHTML(cn, 'lang_paste_word_desc', '{$pluginurl}/images/pasteword.gif', 'mcePasteWord', true);
    44 
    45             case "selectall":
    46                 return tinyMCE.getButtonHTML(cn, 'lang_selectall_desc', '{$pluginurl}/images/selectall.gif', 'mceSelectAll', true);
    47         }
    48 
    49         return '';
    50     },
    51 
    52     execCommand : function(editor_id, element, command, user_interface, value) {
    53         switch (command) {
    54             case "mcePasteText":
    55                 if (user_interface) {
    56                     if ((tinyMCE.isMSIE && !tinyMCE.isOpera) && !tinyMCE.getParam('paste_use_dialog', false))
    57                         TinyMCE_PastePlugin._insertText(clipboardData.getData("Text"), true);
    58                     else {
    59                         var template = new Array();
    60                         template['file']    = '../../plugins/paste/pastetext.htm'; // Relative to theme
    61                         template['width']  = 450;
    62                         template['height'] = 400;
    63                         var plain_text = "";
    64                         tinyMCE.openWindow(template, {editor_id : editor_id, plain_text: plain_text, resizable : "yes", scrollbars : "no", inline : "yes", mceDo : 'insert'});
    65                     }
    66                 } else
    67                     TinyMCE_PastePlugin._insertText(value['html'], value['linebreaks']);
    68 
    69                 return true;
    70 
    71             case "mcePasteWord":
    72                 if (user_interface) {
    73                     if ((tinyMCE.isMSIE && !tinyMCE.isOpera) && !tinyMCE.getParam('paste_use_dialog', false)) {
    74                         TinyMCE_PastePlugin._insertWordContent(TinyMCE_PastePlugin._clipboardHTML());
    75                     } else {
    76                         var template = new Array();
    77                         template['file']    = '../../plugins/paste/pasteword.htm'; // Relative to theme
    78                         template['width']  = 450;
    79                         template['height'] = 400;
    80                         var plain_text = "";
    81                         tinyMCE.openWindow(template, {editor_id : editor_id, plain_text: plain_text, resizable : "yes", scrollbars : "no", inline : "yes", mceDo : 'insert'});
    82                     }
    83                 } else
    84                     TinyMCE_PastePlugin._insertWordContent(value);
    85 
    86                 return true;
    87 
    88             case "mceSelectAll":
    89                 tinyMCE.execInstanceCommand(editor_id, 'selectall');
    90                 return true;
    91 
    92         }
    93 
    94         // Pass to next handler in chain
    95         return false;
    96     },
    97 
    98     // Private plugin internal methods
    99 
    100     _handlePasteEvent : function(e) {
    101         switch (e.type) {
    102             case "paste":
    103                 var html = TinyMCE_PastePlugin._clipboardHTML();
    104                 var r, inst = tinyMCE.selectedInstance;
    105 
    106                 // Removes italic, strong etc, the if was needed due to bug #1437114
    107                 if (inst && (r = inst.getRng()) && r.text.length > 0)
    108                     tinyMCE.execCommand('delete');
    109 
    110                 if (html && html.length > 0)
    111                     tinyMCE.execCommand('mcePasteWord', false, html);
    112 
    113                 tinyMCE.cancelEvent(e);
    114                 return false;
    115         }
    116 
    117         return true;
    118     },
    119 
    120     _insertText : function(content, bLinebreaks) {
    121         if (content && content.length > 0) {
    122             if (bLinebreaks) {
    123                 // Special paragraph treatment
    124                 if (tinyMCE.getParam("paste_create_paragraphs", true)) {
    125                     var rl = tinyMCE.getParam("paste_replace_list", '\u2122,<sup>TM</sup>,\u2026,...,\u201c|\u201d,",\u2019,\',\u2013|\u2014|\u2015|\u2212,-').split(',');
    126                     for (var i=0; i<rl.length; i+=2)
    127                         content = content.replace(new RegExp(rl[i], 'gi'), rl[i+1]);
    128 
    129                     content = tinyMCE.regexpReplace(content, "\r\n\r\n", "</p><p>", "gi");
    130                     content = tinyMCE.regexpReplace(content, "\r\r", "</p><p>", "gi");
    131                     content = tinyMCE.regexpReplace(content, "\n\n", "</p><p>", "gi");
    132 
    133                     // Has paragraphs
    134                     if ((pos = content.indexOf('</p><p>')) != -1) {
    135                         tinyMCE.execCommand("Delete");
    136 
    137                         var node = tinyMCE.selectedInstance.getFocusElement();
    138 
    139                         // Get list of elements to break
    140                         var breakElms = new Array();
    141 
    142                         do {
    143                             if (node.nodeType == 1) {
    144                                 // Don't break tables and break at body
    145                                 if (node.nodeName == "TD" || node.nodeName == "BODY")
    146                                     break;
    147        
    148                                 breakElms[breakElms.length] = node;
    149                             }
    150                         } while(node = node.parentNode);
    151 
    152                         var before = "", after = "</p>";
    153                         before += content.substring(0, pos);
    154 
    155                         for (var i=0; i<breakElms.length; i++) {
    156                             before += "</" + breakElms[i].nodeName + ">";
    157                             after += "<" + breakElms[(breakElms.length-1)-i].nodeName + ">";
    158                         }
    159 
    160                         before += "<p>";
    161                         content = before + content.substring(pos+7) + after;
    162                     }
    163                 }
    164 
    165                 if (tinyMCE.getParam("paste_create_linebreaks", true)) {
    166                     content = tinyMCE.regexpReplace(content, "\r\n", "<br />", "gi");
    167                     content = tinyMCE.regexpReplace(content, "\r", "<br />", "gi");
    168                     content = tinyMCE.regexpReplace(content, "\n", "<br />", "gi");
    169                 }
    170             }
    171        
    172             tinyMCE.execCommand("mceInsertRawHTML", false, content);
    173         }
    174     },
    175 
    176     _insertWordContent : function(content) {
    177         if (content && content.length > 0) {
    178             // Cleanup Word content
    179             var bull = String.fromCharCode(8226);
    180             var middot = String.fromCharCode(183);
    181             var cb;
    182 
    183             if ((cb = tinyMCE.getParam("paste_insert_word_content_callback", "")) != "")
    184                 content = eval(cb + "('before', content)");
    185 
    186             var rl = tinyMCE.getParam("paste_replace_list", '\u2122,<sup>TM</sup>,\u2026,...,\u201c|\u201d,",\u2019,\',\u2013|\u2014|\u2015|\u2212,-').split(',');
    187             for (var i=0; i<rl.length; i+=2)
    188                 content = content.replace(new RegExp(rl[i], 'gi'), rl[i+1]);
    189 
    190             if (tinyMCE.getParam("paste_convert_headers_to_strong", false)) {
    191                 content = content.replace(new RegExp('<p class=MsoHeading.*?>(.*?)<\/p>', 'gi'), '<p><b>$1</b></p>');
    192             }
    193 
    194             content = content.replace(new RegExp('tab-stops: list [0-9]+.0pt">', 'gi'), '">' + "--list--");
    195             content = content.replace(new RegExp(bull + "(.*?)<BR>", "gi"), "<p>" + middot + "$1</p>");
    196             content = content.replace(new RegExp('<SPAN style="mso-list: Ignore">', 'gi'), "<span>" + bull); // Covert to bull list
    197             content = content.replace(/<o:p><\/o:p>/gi, "");
    198             content = content.replace(new RegExp('<br style="page-break-before: always;.*>', 'gi'), '-- page break --'); // Replace pagebreaks
    199             content = content.replace(new RegExp('<(!--)([^>]*)(--)>', 'g'), "");  // Word comments
    200 
    201             if (tinyMCE.getParam("paste_remove_spans", true))
    202                 content = content.replace(/<\/?span[^>]*>/gi, "");
    203 
    204             if (tinyMCE.getParam("paste_remove_styles", true))
    205                 content = content.replace(new RegExp('<(\\w[^>]*) style="([^"]*)"([^>]*)', 'gi'), "<$1$3");
    206 
    207             content = content.replace(/<\/?font[^>]*>/gi, "");
    208 
    209             // Strips class attributes.
    210             switch (tinyMCE.getParam("paste_strip_class_attributes", "all")) {
    211                 case "all":
    212                     content = content.replace(/<(\w[^>]*) class=([^ |>]*)([^>]*)/gi, "<$1$3");
    213                     break;
    214 
    215                 case "mso":
    216                     content = content.replace(new RegExp('<(\\w[^>]*) class="?mso([^ |>]*)([^>]*)', 'gi'), "<$1$3");
    217                     break;
    218             }
    219 
    220             content = content.replace(new RegExp('href="?' + TinyMCE_PastePlugin._reEscape("" + document.location) + '', 'gi'), 'href="' + tinyMCE.settings['document_base_url']);
    221             content = content.replace(/<(\w[^>]*) lang=([^ |>]*)([^>]*)/gi, "<$1$3");
    222             content = content.replace(/<\\?\?xml[^>]*>/gi, "");
    223             content = content.replace(/<\/?\w+:[^>]*>/gi, "");
    224             content = content.replace(/-- page break --\s*<p>&nbsp;<\/p>/gi, ""); // Remove pagebreaks
    225             content = content.replace(/-- page break --/gi, ""); // Remove pagebreaks
    226 
    227     //      content = content.replace(/\/?&nbsp;*/gi, ""); &nbsp;
    228     //      content = content.replace(/<p>&nbsp;<\/p>/gi, '');
    229 
    230             if (!tinyMCE.settings['force_p_newlines']) {
    231                 content = content.replace('', '' ,'gi');
    232                 content = content.replace('</p>', '<br /><br />' ,'gi');
    233             }
    234 
    235             if (!tinyMCE.isMSIE && !tinyMCE.settings['force_p_newlines']) {
    236                 content = content.replace(/<\/?p[^>]*>/gi, "");
    237             }
    238 
    239             content = content.replace(/<\/?div[^>]*>/gi, "");
    240 
    241             // Convert all middlot lists to UL lists
    242             if (tinyMCE.getParam("paste_convert_middot_lists", true)) {
    243                 var div = document.createElement("div");
    244                 div.innerHTML = content;
    245 
    246                 // Convert all middot paragraphs to li elements
    247                 var className = tinyMCE.getParam("paste_unindented_list_class", "unIndentedList");
    248 
    249                 while (TinyMCE_PastePlugin._convertMiddots(div, "--list--")) ; // bull
    250                 while (TinyMCE_PastePlugin._convertMiddots(div, middot, className)) ; // Middot
    251                 while (TinyMCE_PastePlugin._convertMiddots(div, bull)) ; // bull
    252 
    253                 content = div.innerHTML;
    254             }
    255 
    256             // Replace all headers with strong and fix some other issues
    257             if (tinyMCE.getParam("paste_convert_headers_to_strong", false)) {
    258                 content = content.replace(/<h[1-6]>&nbsp;<\/h[1-6]>/gi, '<p>&nbsp;&nbsp;</p>');
    259                 content = content.replace(/<h[1-6]>/gi, '<p><b>');
    260                 content = content.replace(/<\/h[1-6]>/gi, '</b></p>');
    261                 content = content.replace(/<b>&nbsp;<\/b>/gi, '<b>&nbsp;&nbsp;</b>');
    262                 content = content.replace(/^(&nbsp;)*/gi, '');
    263             }
    264 
    265             content = content.replace(/--list--/gi, ""); // Remove --list--
    266 
    267             if ((cb = tinyMCE.getParam("paste_insert_word_content_callback", "")) != "")
    268                 content = eval(cb + "('after', content)");
    269 
    270             // Insert cleaned content
    271             tinyMCE.execCommand("mceInsertContent", false, content);
    272 
    273             if (tinyMCE.getParam('paste_force_cleanup_wordpaste', true))
    274                 window.setTimeout('tinyMCE.execCommand("mceCleanup");', 1); // Do normal cleanup detached from this thread
    275         }
    276     },
    277 
    278     _reEscape : function(s) {
    279         var l = "?.\\*[](){}+^$:";
    280         var o = "";
    281 
    282         for (var i=0; i<s.length; i++) {
    283             var c = s.charAt(i);
    284 
    285             if (l.indexOf(c) != -1)
    286                 o += '\\' + c;
    287             else
    288                 o += c;
    289         }
    290 
    291         return o;
    292     },
    293 
    294     _convertMiddots : function(div, search, class_name) {
    295         var mdot = String.fromCharCode(183);
    296         var bull = String.fromCharCode(8226);
    297 
    298         var nodes = div.getElementsByTagName("p");
    299         var prevul;
    300         for (var i=0; i<nodes.length; i++) {
    301             var p = nodes[i];
    302 
    303             // Is middot
    304             if (p.innerHTML.indexOf(search) == 0) {
    305                 var ul = document.createElement("ul");
    306 
    307                 if (class_name)
    308                     ul.className = class_name;
    309 
    310                 // Add the first one
    311                 var li = document.createElement("li");
    312                 li.innerHTML = p.innerHTML.replace(new RegExp('' + mdot + '|' + bull + '|--list--|&nbsp;', "gi"), '');
    313                 ul.appendChild(li);
    314 
    315                 // Add the rest
    316                 var np = p.nextSibling;
    317                 while (np) {
    318                     // If the node is whitespace, then
    319                     // ignore it and continue on.
    320                     if (np.nodeType == 3 && new RegExp('^\\s$', 'm').test(np.nodeValue)) {
    321                             np = np.nextSibling;
    322                             continue;
    323                     }
    324 
    325                     if (search == mdot) {
    326                             if (np.nodeType == 1 && new RegExp('^o(\\s+|&nbsp;)').test(np.innerHTML)) {
    327                                     // Second level of nesting
    328                                     if (!prevul) {
    329                                             prevul = ul;
    330                                             ul = document.createElement("ul");
    331                                             prevul.appendChild(ul);
    332                                     }
    333                                     np.innerHTML = np.innerHTML.replace(/^o/, '');
    334                             } else {
    335                                     // Pop the stack if we're going back up to the first level
    336                                     if (prevul) {
    337                                             ul = prevul;
    338                                             prevul = null;
    339                                     }
    340                                     // Not element or middot paragraph
    341                                     if (np.nodeType != 1 || np.innerHTML.indexOf(search) != 0)
    342                                             break;
    343                             }
    344                     } else {
    345                             // Not element or middot paragraph
    346                             if (np.nodeType != 1 || np.innerHTML.indexOf(search) != 0)
    347                                     break;
    348                         }
    349 
    350                     var cp = np.nextSibling;
    351                     var li = document.createElement("li");
    352                     li.innerHTML = np.innerHTML.replace(new RegExp('' + mdot + '|' + bull + '|--list--|&nbsp;', "gi"), '');
    353                     np.parentNode.removeChild(np);
    354                     ul.appendChild(li);
    355                     np = cp;
    356                 }
    357 
    358                 p.parentNode.replaceChild(ul, p);
    359 
    360                 return true;
    361             }
    362         }
    363 
    364         return false;
    365     },
    366 
    367     _clipboardHTML : function() {
    368         var div = document.getElementById('_TinyMCE_clipboardHTML');
    369 
    370         if (!div) {
    371             var div = document.createElement('DIV');
    372             div.id = '_TinyMCE_clipboardHTML';
    373 
    374             with (div.style) {
    375                 visibility = 'hidden';
    376                 overflow = 'hidden';
    377                 position = 'absolute';
    378                 width = 1;
    379                 height = 1;
    380             }
    381 
    382             document.body.appendChild(div);
    383         }
    384 
    385         div.innerHTML = '';
    386         var rng = document.body.createTextRange();
    387         rng.moveToElementText(div);
    388         rng.execCommand('Paste');
    389         var html = div.innerHTML;
    390         div.innerHTML = '';
    391         return html;
    392     }
    393 };
    394 
    395 tinyMCE.addPlugin("paste", TinyMCE_PastePlugin);
     379    });
     380
     381    // Register plugin
     382    tinymce.PluginManager.add('paste', tinymce.plugins.PastePlugin);
     383})();
  • trunk/wp-includes/js/tinymce/plugins/paste/pastetext.htm

    • Property svn:eol-style set to native
    r3664 r6632  
    11<html xmlns="http://www.w3.org/1999/xhtml">
    22<head>
    3     <title>{$lang_paste_text_desc}</title>
     3    <title>{#paste.paste_text_desc}</title>
    44    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    5     <script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
    6     <script language="javascript" type="text/javascript" src="jscripts/pastetext.js"></script>
     5    <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
     6    <script type="text/javascript" src="js/pastetext.js"></script>
    77    <base target="_self" />
    88</head>
    9 <body onload="tinyMCEPopup.executeOnLoad('onLoadInit();');" onresize="resizeInputs();" style="display: none">
     9<body onresize="resizeInputs();" style="display:none; overflow:hidden;">
    1010<form name="source" onsubmit="saveContent();">
    11     <div style="float: left" class="title">{$lang_paste_text_desc}</div>
     11    <div style="float: left" class="title">{#paste.paste_text_desc}</div>
    1212
    1313    <div style="float: right">
    14         <input type="checkbox" name="linebreaks" id="linebreaks" class="wordWrapCode" checked="checked" /><label for="linebreaks">{$lang_paste_text_linebreaks}</label>
     14        <input type="checkbox" name="linebreaks" id="linebreaks" class="wordWrapCode" checked="checked" /><label for="linebreaks">{#paste_dlg.text_linebreaks}</label>
    1515    </div>
    1616
    1717    <br style="clear: both" />
    1818
    19     <div>{$lang_paste_text_title}</div>
     19    <div>{#paste_dlg.text_title}</div>
    2020
    2121    <textarea name="htmlSource" id="htmlSource" rows="15" cols="100" style="width: 100%; height: 100%; font-family: 'Courier New',Courier,mono; font-size: 12px;" dir="ltr" wrap="soft"></textarea>
     
    2323    <div class="mceActionPanel">
    2424        <div style="float: left">
    25             <input type="button" name="insert" value="{$lang_insert}" onclick="saveContent();" id="insert" />
     25            <input type="button" name="insert" value="{#insert}" onclick="saveContent();" id="insert" />
    2626        </div>
    2727
    2828        <div style="float: right">
    29             <input type="button" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" id="cancel" />
     29            <input type="button" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" id="cancel" />
    3030        </div>
    3131    </div>
  • trunk/wp-includes/js/tinymce/plugins/paste/pasteword.htm

    • Property svn:eol-style set to native
    r3664 r6632  
    22<head>
    33    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    4     <title>{$lang_paste_word_desc}</title>
    5     <script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
    6     <script language="javascript" type="text/javascript" src="jscripts/pasteword.js"></script>
     4    <title>{#paste.paste_word_desc}</title>
     5    <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
     6    <script type="text/javascript" src="js/pasteword.js"></script>
    77    <link href="css/pasteword.css" rel="stylesheet" type="text/css" />
    88    <base target="_self" />
    99</head>
    10 <body onload="tinyMCEPopup.executeOnLoad('onLoadInit();');" onresize="resizeInputs();" style="display: none">
     10<body onresize="resizeInputs();" style="display:none; overflow:hidden;">
    1111    <form name="source" onsubmit="saveContent();" action="#">
    12         <div class="title">{$lang_paste_word_desc}</div>
     12        <div class="title">{#paste.paste_word_desc}</div>
    1313
    14         <div>{$lang_paste_word_title}</div>
     14        <div>{#paste_dlg.word_title}</div>
    1515
    1616        <div id="iframecontainer"></div>
     
    1818        <div class="mceActionPanel">
    1919            <div style="float: left">
    20                 <input type="button" id="insert" name="insert" value="{$lang_insert}" onclick="saveContent();" />
     20                <input type="button" id="insert" name="insert" value="{#insert}" onclick="saveContent();" />
    2121            </div>
    2222
    2323            <div style="float: right">
    24                 <input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
     24                <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
    2525            </div>
    2626        </div>
  • trunk/wp-includes/js/tinymce/plugins/spellchecker/config.php

    r6360 r6632  
    11<?php
    2     $spellCheckerConfig = array();
     2    // General settings
     3    $config['general.engine'] = 'GoogleSpell';
     4    //$config['general.engine'] = 'PSpell';
     5    //$config['general.engine'] = 'PSpellShell';
    36
    4     // Spellchecker class use
    5     // require_once("classes/TinyPspellShell.class.php"); // Command line pspell
    6     require_once("classes/TinyGoogleSpell.class.php"); // Google web service
    7     // require_once("classes/TinyPspell.class.php"); // Internal PHP version
     7    // PSpell settings
     8    $config['PSpell.mode'] = PSPELL_FAST;
     9    $config['PSpell.spelling'] = "";
     10    $config['PSpell.jargon'] = "";
     11    $config['PSpell.encoding'] = "";
    812
    9     // General settings
    10     $spellCheckerConfig['enabled'] = true;
     13    // PSpellShell settings
     14    $config['PSpellShell.mode'] = PSPELL_FAST;
     15    $config['PSpellShell.aspell'] = '/usr/bin/aspell';
     16    $config['PSpellShell.tmp'] = '/tmp';
    1117
    12     // Default settings
    13     $spellCheckerConfig['default.language'] = 'en';
    14     $spellCheckerConfig['default.mode'] = PSPELL_FAST;
    15 
    16     // Normaly not required to configure
    17     $spellCheckerConfig['default.spelling'] = "";
    18     $spellCheckerConfig['default.jargon'] = "";
    19     $spellCheckerConfig['default.encoding'] = "";
    20 
    21     // Pspell shell specific settings
    22     $spellCheckerConfig['tinypspellshell.aspell'] = '/usr/bin/aspell';
    23     $spellCheckerConfig['tinypspellshell.tmp'] = '/tmp';
     18    // Windows PSpellShell settings
     19    //$config['PSpellShell.aspell'] = '"c:\Program Files\Aspell\bin\aspell.exe"';
     20    //$config['PSpellShell.tmp'] = 'c:/temp';
    2421?>
  • trunk/wp-includes/js/tinymce/plugins/spellchecker/css/content.css

    • Property svn:eol-style set to native
    r6360 r6632  
    1 .mceItemHiddenSpellWord {
    2     background: url('../images/wline.gif') repeat-x bottom left;
    3     cursor: default;
    4 }
     1.mceItemHiddenSpellWord {background:url(../img/wline.gif) repeat-x bottom left; cursor:default;}
  • trunk/wp-includes/js/tinymce/plugins/spellchecker/css/spellchecker.css

    • Property svn:eol-style set to native
  • trunk/wp-includes/js/tinymce/plugins/spellchecker/editor_plugin.js

    r6360 r6632  
    11/**
    2  * $Id: editor_plugin_src.js 289 2007-05-28 09:12:16Z spocke $
     2 * $Id: editor_plugin_src.js 425 2007-11-21 15:17:39Z spocke $
    33 *
    44 * @author Moxiecode
    5  * @copyright Copyright © 2004-2006, Moxiecode Systems AB, All rights reserved.
     5 * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
    66 */
    77
    8 tinyMCE.importPluginLanguagePack('spellchecker', 'en,fr,sv,nn,nb');
    9 
    10 // Plucin static class
    11 var TinyMCE_SpellCheckerPlugin = {
    12     _contextMenu : new TinyMCE_Menu(),
    13     _menu : new TinyMCE_Menu(),
    14     _counter : 0,
    15     _ajaxPage : '/tinyspell.php',
    16 
    17     getInfo : function() {
    18         return {
    19             longname : 'Spellchecker PHP',
    20             author : 'Moxiecode Systems AB',
    21             authorurl : 'http://tinymce.moxiecode.com',
    22             infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/spellchecker',
    23             version : "1.0.5"
    24         };
    25     },
    26 
    27     handleEvent : function(e) {
    28         var elm = tinyMCE.isMSIE ? e.srcElement : e.target;
    29         var inst = tinyMCE.selectedInstance, args = '';
    30         var self = TinyMCE_SpellCheckerPlugin;
    31         var cm = self._contextMenu;
    32         var p, p2, x, y, sx, sy, h, elm;
    33 
    34         // Handle click on word
    35         if ((e.type == "click" || e.type == "contextmenu") && elm) {
    36             do {
    37                 if (tinyMCE.getAttrib(elm, 'class') == "mceItemHiddenSpellWord") {
    38                     inst.spellCheckerElm = elm;
    39 
    40                     // Setup arguments
    41                     args += 'id=' + inst.editorId + "|" + (++self._counter);
    42                     args += '&cmd=suggest&check=' + encodeURIComponent(elm.innerHTML);
    43                     args += '&lang=' + escape(inst.spellCheckerLang);
    44 
    45                     elm = inst.spellCheckerElm;
    46                     p = tinyMCE.getAbsPosition(inst.iframeElement);
    47                     p2 = tinyMCE.getAbsPosition(elm);
    48                     h = parseInt(elm.offsetHeight);
    49                     sx = inst.getBody().scrollLeft;
    50                     sy = inst.getBody().scrollTop;
    51                     x = p.absLeft + p2.absLeft - sx;
    52                     y = p.absTop + p2.absTop - sy + h;
    53 
    54                     cm.clear();
    55                     cm.addTitle(tinyMCE.getLang('lang_spellchecker_wait', '', true));
    56                     cm.show();
    57                     cm.moveTo(x, y);
    58 
    59                     inst.selection.selectNode(elm, false, false);
    60 
    61                     self._sendAjax(self.baseURL + self._ajaxPage, self._ajaxResponse, 'post', args);
    62 
    63                     tinyMCE.cancelEvent(e);
    64                     return false;
    65                 }
    66             } while ((elm = elm.parentNode));
    67         }
    68 
    69         return true;
    70     },
    71 
    72     initInstance : function(inst) {
    73         var self = TinyMCE_SpellCheckerPlugin, m = self._menu, cm = self._contextMenu, e;
    74 
    75         tinyMCE.importCSS(inst.getDoc(), tinyMCE.baseURL + "/plugins/spellchecker/css/content.css");
    76 
    77         if (!tinyMCE.hasMenu('spellcheckercontextmenu')) {
    78             tinyMCE.importCSS(document, tinyMCE.baseURL + "/plugins/spellchecker/css/spellchecker.css");
    79 
    80             cm.init({drop_menu : false});
    81             tinyMCE.addMenu('spellcheckercontextmenu', cm);
    82         }
    83 
    84         if (!tinyMCE.hasMenu('spellcheckermenu')) {
    85             m.init({});
    86             tinyMCE.addMenu('spellcheckermenu', m);
    87         }
    88 
    89         inst.spellCheckerLang = 'en';
    90         self._buildSettingsMenu(inst, null);
    91 
    92         e = self._getBlockBoxLayer(inst).create('div', 'mceBlockBox', document.getElementById(inst.editorId + '_parent'));
    93         self._getMsgBoxLayer(inst).create('div', 'mceMsgBox', document.getElementById(inst.editorId + '_parent'));
    94     },
    95 
    96     _getMsgBoxLayer : function(inst) {
    97         if (!inst.spellCheckerMsgBoxL)
    98             inst.spellCheckerMsgBoxL = new TinyMCE_Layer(inst.editorId + '_spellcheckerMsgBox', false);
    99 
    100         return inst.spellCheckerMsgBoxL;
    101     },
    102 
    103     _getBlockBoxLayer : function(inst) {
    104         if (!inst.spellCheckerBoxL)
    105             inst.spellCheckerBoxL = new TinyMCE_Layer(inst.editorId + '_spellcheckerBlockBox', false);
    106 
    107         return inst.spellCheckerBoxL;
    108     },
    109 
    110     _buildSettingsMenu : function(inst, lang) {
    111         var i, ar = tinyMCE.getParam('spellchecker_languages', '+English=en').split(','), p;
    112         var self = TinyMCE_SpellCheckerPlugin, m = self._menu, c;
    113 
    114         m.clear();
    115         m.addTitle(tinyMCE.getLang('lang_spellchecker_langs', '', true));
    116 
    117         for (i=0; i<ar.length; i++) {
    118             if (ar[i] != '') {
    119                 p = ar[i].split('=');
    120                 c = 'mceMenuCheckItem';
    121 
    122                 if (p[0].charAt(0) == '+') {
    123                     p[0] = p[0].substring(1);
    124 
    125                     if (lang == null) {
    126                         c = 'mceMenuSelectedItem';
    127                         inst.spellCheckerLang = p[1];
    128                     }
    129                 }
    130 
    131                 if (lang == p[1])
    132                     c = 'mceMenuSelectedItem';
    133 
    134                 m.add({text : p[0], js : "tinyMCE.execInstanceCommand('" + inst.editorId + "','mceSpellCheckerSetLang',false,'" + p[1] + "');", class_name : c});
     8(function() {
     9    var JSONRequest = tinymce.util.JSONRequest, each = tinymce.each, DOM = tinymce.DOM;
     10
     11    tinymce.create('tinymce.plugins.SpellcheckerPlugin', {
     12        getInfo : function() {
     13            return {
     14                longname : 'Spellchecker',
     15                author : 'Moxiecode Systems AB',
     16                authorurl : 'http://tinymce.moxiecode.com',
     17                infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/spellchecker',
     18                version : "2.0b2"
     19            };
     20        },
     21
     22        init : function(ed, url) {
     23            var t = this, cm;
     24
     25            t.url = url;
     26            t.editor = ed;
     27
     28            // Register commands
     29            ed.addCommand('mceSpellCheck', function() {
     30                if (!t.active) {
     31                    ed.setProgressState(1);
     32                    t._sendRPC('checkWords', [t.selectedLang, t._getWords()], function(r) {
     33                        if (r.length > 0) {
     34                            t.active = 1;
     35                            t._markWords(r);
     36                            ed.setProgressState(0);
     37                            ed.nodeChanged();
     38                        } else {
     39                            ed.setProgressState(0);
     40                            ed.windowManager.alert('spellchecker.no_mpell');
     41                        }
     42                    });
     43                } else
     44                    t._done();
     45            });
     46
     47            ed.onInit.add(function() {
     48                ed.dom.loadCSS(url + '/css/content.css');
     49            });
     50
     51            ed.onClick.add(t._showMenu, t);
     52            ed.onContextMenu.add(t._showMenu, t);
     53            ed.onBeforeGetContent.add(function() {
     54                if (t.active)
     55                    t._removeWords();
     56            });
     57
     58            ed.onNodeChange.add(function(ed, cm) {
     59                cm.setActive('spellchecker', t.active);
     60            });
     61
     62            ed.onSetContent.add(function() {
     63                t._done();
     64            });
     65
     66            ed.onBeforeGetContent.add(function() {
     67                t._done();
     68            });
     69
     70            ed.onBeforeExecCommand.add(function(ed, cmd) {
     71                if (cmd == 'mceFullScreen')
     72                    t._done();
     73            });
     74
     75            // Find selected language
     76            t.languages = {};
     77            each(ed.getParam('spellchecker_languages', '+English=en,Danish=da,Dutch=nl,Finnish=fi,French=fr,German=de,Italian=it,Polish=pl,Portuguese=pt,Spanish=es,Swedish=sv').split(','), function(v) {
     78                v = v.split('=');
     79
     80                if (v[0].indexOf('+') === 0) {
     81                    v[0] = v[0].substring(1);
     82                    t.selectedLang = v[1];
     83                }
     84
     85                t.languages[v[0]] = v[1];
     86            });
     87        },
     88
     89        createControl : function(n, cm) {
     90            var t = this, c, ed = t.editor;
     91
     92            if (n == 'spellchecker') {
     93                c = cm.createSplitButton(n, {title : 'spellchecker.desc', cmd : 'mceSpellCheck', scope : t});
     94
     95                c.onRenderMenu.add(function(c, m) {
     96                    m.add({title : 'spellchecker.langs', 'class' : 'mceMenuItemTitle'}).setDisabled(1);
     97                    each(t.languages, function(v, k) {
     98                        var o = {icon : 1}, mi;
     99
     100                        o.onclick = function() {
     101                            mi.setSelected(1);
     102                            t.selectedItem.setSelected(0);
     103                            t.selectedItem = mi;
     104                            t.selectedLang = v;
     105                        };
     106
     107                        o.title = k;
     108                        mi = m.add(o);
     109                        mi.setSelected(v == t.selectedLang);
     110
     111                        if (v == t.selectedLang)
     112                            t.selectedItem = mi;
     113                    })
     114                });
     115
     116                return c;
    135117            }
    136         }
    137     },
    138 
    139     setupContent : function(editor_id, body, doc) {
    140         TinyMCE_SpellCheckerPlugin._removeWords(doc, null, true);
    141     },
    142 
    143     getControlHTML : function(cn) {
    144         switch (cn) {
    145             case "spellchecker":
    146                 return TinyMCE_SpellCheckerPlugin._getMenuButtonHTML(cn, 'lang_spellchecker_desc', '{$pluginurl}/images/spellchecker.gif', 'lang_spellchecker_desc', 'mceSpellCheckerMenu', 'mceSpellCheck');
    147         }
    148 
    149         return "";
    150     },
    151 
    152     /**
    153      * Returns the HTML code for a normal button control.
    154      *
    155      * @param {string} id Button control id, this will be the suffix for the element id, the prefix is the editor id.
    156      * @param {string} lang Language variable key name to insert as the title/alt of the button image.
    157      * @param {string} img Image URL to insert, {$themeurl} and {$pluginurl} will be replaced.
    158      * @param {string} mlang Language variable key name to insert as the title/alt of the menu button image.
    159      * @param {string} mid Menu by id to display when the menu button is pressed.
    160      * @param {string} cmd Command to execute when the user clicks the button.
    161      * @param {string} ui Optional user interface boolean for command.
    162      * @param {string} val Optional value for command.
    163      * @return HTML code for a normal button based in input information.
    164      * @type string
    165      */
    166     _getMenuButtonHTML : function(id, lang, img, mlang, mid, cmd, ui, val) {
    167         var h = '', m, x;
    168 
    169         cmd = 'tinyMCE.hideMenus();tinyMCE.execInstanceCommand(\'{$editor_id}\',\'' + cmd + '\'';
    170 
    171         if (typeof(ui) != "undefined" && ui != null)
    172             cmd += ',' + ui;
    173 
    174         if (typeof(val) != "undefined" && val != null)
    175             cmd += ",'" + val + "'";
    176 
    177         cmd += ');';
    178 
    179         // Use tilemaps when enabled and found and never in MSIE since it loads the tile each time from cache if cahce is disabled
    180         if (tinyMCE.getParam('button_tile_map') && (!tinyMCE.isMSIE || tinyMCE.isOpera) && (m = tinyMCE.buttonMap[id]) != null && (tinyMCE.getParam("language") == "en" || img.indexOf('$lang') == -1)) {
    181             // Tiled button
    182             x = 0 - (m * 20) == 0 ? '0' : 0 - (m * 20);
    183             h += '<a id="{$editor_id}_' + id + '" href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" class="mceTiledButton mceButtonNormal" target="_self">';
    184             h += '<img src="{$themeurl}/images/spacer.gif" style="background-position: ' + x + 'px 0" title="{$' + lang + '}" />';
    185             h += '<img src="{$themeurl}/images/button_menu.gif" title="{$' + lang + '}" class="mceMenuButton" onclick="' + mcmd + 'return false;" />';
    186             h += '</a>';
    187         } else {
    188             if (tinyMCE.isMSIE && !tinyMCE.isOpera)
    189                 h += '<span id="{$editor_id}_' + id + '" class="mceMenuButton" onmouseover="tinyMCE.plugins.spellchecker._menuButtonEvent(\'over\',this);" onmouseout="tinyMCE.plugins.spellchecker._menuButtonEvent(\'out\',this);">';
    190             else
    191                 h += '<span id="{$editor_id}_' + id + '" class="mceMenuButton">';
    192 
    193             h += '<a href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" class="mceMenuButtonNormal" target="_self">';
    194             h += '<img src="' + img + '" title="{$' + lang + '}" /></a>';
    195             h += '<a href="#" onclick="tinyMCE.plugins.spellchecker._toggleMenu(\'{$editor_id}\',\'' + mid + '\');return false;" onmousedown="return false;"><img src="{$themeurl}/images/button_menu.gif" title="{$' + lang + '}" class="mceMenuButton" />';
    196             h += '</a></span>';
    197         }
    198 
    199         return h;
    200     },
    201 
    202     _menuButtonEvent : function(e, o) {
    203         var t = this;
    204 
    205         // Give IE some time since it's buggy!! :(
    206         window.setTimeout(function() {
    207             t._menuButtonEvent2(e, o);
    208         }, 1);
    209     },
    210 
    211     _menuButtonEvent2 : function(e, o) {
    212         if (o.className == 'mceMenuButtonFocus')
    213             return;
    214 
    215         if (e == 'over')
    216             o.className = o.className + ' mceMenuHover';
    217         else
    218             o.className = o.className.replace(/\s.*$/, '');
    219     },
    220 
    221     _toggleMenu : function(editor_id, id) {
    222         var self = TinyMCE_SpellCheckerPlugin;
    223         var e = document.getElementById(editor_id + '_spellchecker');
    224         var inst = tinyMCE.getInstanceById(editor_id);
    225 
    226         if (self._menu.isVisible()) {
    227             tinyMCE.hideMenus();
    228             return;
    229         }
    230 
    231         tinyMCE.lastMenuBtnClass = e.className.replace(/\s.*$/, '');
    232         tinyMCE.switchClass(editor_id + '_spellchecker', 'mceMenuButtonFocus');
    233 
    234         self._menu.moveRelativeTo(e, 'bl');
    235         self._menu.moveBy(tinyMCE.isMSIE && !tinyMCE.isOpera ? 0 : 1, -1);
    236 
    237         if (tinyMCE.isOpera)
    238             self._menu.moveBy(0, -2);
    239 
    240         self._onMenuEvent(inst, self._menu, 'show');
    241 
    242         self._menu.show();
    243 
    244         tinyMCE.lastSelectedMenuBtn = editor_id + '_spellchecker';
    245     },
    246 
    247     _onMenuEvent : function(inst, m, n) {
    248         TinyMCE_SpellCheckerPlugin._buildSettingsMenu(inst, inst.spellCheckerLang);
    249     },
    250 
    251     execCommand : function(editor_id, element, command, user_interface, value) {
    252         var inst = tinyMCE.getInstanceById(editor_id), self = TinyMCE_SpellCheckerPlugin, args = '', co, bb, mb, nl, i, e, mbs;
    253 
    254         // Handle commands
    255         switch (command) {
    256             case "mceSpellCheck":
    257                 if (!inst.spellcheckerOn) {
    258                     inst.spellCheckerBookmark = inst.selection.getBookmark();
    259 
    260                     // Fix for IE bug: #1610184
    261                     if (tinyMCE.isRealIE)
    262                         tinyMCE.setInnerHTML(inst.getBody(), inst.getBody().innerHTML);
    263 
    264                     // Setup arguments
    265                     args += 'id=' + inst.editorId + "|" + (++self._counter);
    266                     args += '&cmd=spell&check=' + encodeURIComponent(self._getWordList(inst.getBody())).replace(/\'/g, '%27');
    267                     args += '&lang=' + escape(inst.spellCheckerLang);
    268 
    269                     co = document.getElementById(inst.editorId + '_parent').firstChild;
    270                     bb = self._getBlockBoxLayer(inst);
    271                     bb.moveRelativeTo(co, 'tl');
    272                     bb.resizeTo(co.offsetWidth, co.offsetHeight);
    273                     bb.show();
    274 
    275                     // Setup message box
    276                     mb = self._getMsgBoxLayer(inst);
    277                     e = mb.getElement();
    278 
    279                     if (e.childNodes[0])
    280                         e.removeChild(e.childNodes[0]);
    281 
    282                     mbs = document.createElement("span");
    283                     mbs.innerHTML = '<span>' + tinyMCE.getLang('lang_spellchecker_swait', '', true) + '</span>';
    284                     e.appendChild(mbs);
    285 
    286                     mb.show();
    287                     mb.moveRelativeTo(co, 'cc');
    288 
    289                     if (tinyMCE.isMSIE && !tinyMCE.isOpera) {
    290                         nl = co.getElementsByTagName('select');
    291                         for (i=0; i<nl.length; i++)
    292                             nl[i].disabled = true;
    293                     }
    294 
    295                     inst.spellcheckerOn = true;
    296                     tinyMCE.switchClass(editor_id + '_spellchecker', 'mceMenuButtonSelected');
    297 
    298                     self._sendAjax(self.baseURL + self._ajaxPage, self._ajaxResponse, 'post', args);
    299                 } else {
    300                     self._removeWords(inst.getDoc());
    301                     inst.spellcheckerOn = false;
    302                     tinyMCE.switchClass(editor_id + '_spellchecker', 'mceMenuButton');
    303                 }
    304 
    305                 return true;
    306 
    307             case "mceSpellCheckReplace":
    308                 if (inst.spellCheckerElm)
    309                     tinyMCE.setOuterHTML(inst.spellCheckerElm, value);
    310 
    311                 self._checkDone(inst);
    312                 self._contextMenu.hide();
    313                 self._menu.hide();
    314 
    315                 return true;
    316 
    317             case "mceSpellCheckIgnore":
    318                 if (inst.spellCheckerElm)
    319                     self._removeWord(inst.spellCheckerElm);
    320 
    321                 self._checkDone(inst);
    322                 self._contextMenu.hide();
    323                 self._menu.hide();
    324                 return true;
    325 
    326             case "mceSpellCheckIgnoreAll":
    327                 if (inst.spellCheckerElm)
    328                     self._removeWords(inst.getDoc(), inst.spellCheckerElm.innerHTML);
    329 
    330                 self._checkDone(inst);
    331                 self._contextMenu.hide();
    332                 self._menu.hide();
    333                 return true;
    334 
    335             case "mceSpellCheckerSetLang":
    336                 tinyMCE.hideMenus();
    337                 inst.spellCheckerLang = value;
    338                 self._removeWords(inst.getDoc());
    339                 inst.spellcheckerOn = false;
    340                 tinyMCE.switchClass(editor_id + '_spellchecker', 'mceMenuButton');
    341                 return true;
    342         }
    343 
    344         // Pass to next handler in chain
    345         return false;
    346     },
    347 
    348     cleanup : function(type, content, inst) {
    349         switch (type) {
    350             case "get_from_editor_dom":
    351                 TinyMCE_SpellCheckerPlugin._removeWords(content, null, true);
    352                 inst.spellcheckerOn = false;
    353                 break;
    354         }
    355 
    356         return content;
    357     },
    358 
    359     // Private plugin specific methods
    360 
    361     _displayUI : function(inst) {
    362         var self = TinyMCE_SpellCheckerPlugin;
    363         var bb = self._getBlockBoxLayer(inst);
    364         var mb = self._getMsgBoxLayer(inst);
    365         var nl, i;
    366         var co = document.getElementById(inst.editorId + '_parent').firstChild;
    367 
    368         if (tinyMCE.isMSIE && !tinyMCE.isOpera) {
    369             nl = co.getElementsByTagName('select');
    370             for (i=0; i<nl.length; i++)
    371                 nl[i].disabled = false;
    372         }
    373 
    374         bb.hide();
    375 
    376         // Boom, crash in FF if focus isn't else were
    377         // el.style.display='none' on a opacity element seems to crash it
    378         mb.hide();
    379     },
    380 
    381     _ajaxResponse : function(xml, text) {
    382         var el = xml ? xml.documentElement : null;
    383         var inst = tinyMCE.selectedInstance, self = TinyMCE_SpellCheckerPlugin;
    384         var cmd = el ? el.getAttribute("cmd") : null, err, id = el ? el.getAttribute("id") : null;
    385 
    386         if (id)
    387             inst = tinyMCE.getInstanceById(id.substring(0, id.indexOf('|')));
    388 
    389         // Workaround for crash in Gecko
    390         if (tinyMCE.isGecko)
    391             window.focus();
    392 
    393         self._displayUI(inst);
    394 
    395         // Restore the selection again
    396         if (tinyMCE.isGecko) {
    397             inst.getWin().focus();
    398             inst.selection.moveToBookmark(inst.spellCheckerBookmark);
    399         }
    400 
    401         // Ignore suggestions for other ajax responses
    402         if (cmd == "suggest" && id != inst.editorId + "|" + self._counter)
    403             return;
    404 
    405         if (!el) {
    406             text = '' + text;
    407 
    408             if (text.length > 500)
    409                 text = text.substring(500);
    410 
    411             inst.spellcheckerOn = false;
    412             tinyMCE.switchClass(inst.editorId + '_spellchecker', 'mceMenuButton');
    413             alert("Could not execute AJAX call, server didn't return valid a XML.\nResponse: " + text);
    414             return;
    415         }
    416 
    417         err = el.getAttribute("error");
    418 
    419         if (err == "true") {
    420             inst.spellcheckerOn = false;
    421             tinyMCE.switchClass(inst.editorId + '_spellchecker', 'mceMenuButton');
    422             alert(el.getAttribute("msg"));
    423             return;
    424         }
    425 
    426         switch (cmd) {
    427             case "spell":
    428                 if (xml.documentElement.firstChild) {
    429                     self._markWords(inst.getDoc(), inst.getBody(), decodeURIComponent(el.firstChild.nodeValue).split('+'));
    430                     inst.selection.moveToBookmark(inst.spellCheckerBookmark);
    431 
    432                     if(tinyMCE.getParam('spellchecker_report_misspellings', false))
    433                         alert(tinyMCE.getLang('lang_spellchecker_mpell_found', '', true, {words : self._countWords(inst)}));
    434                 } else
    435                     alert(tinyMCE.getLang('lang_spellchecker_no_mpell', '', true));
    436 
    437                 self._checkDone(inst);
    438 
    439                 // Odd stuff FF removed useCSS, disable state for it
    440                 inst.useCSS = false;
    441 
    442                 break;
    443 
    444             case "suggest":
    445                 self._buildMenu(el.firstChild ? decodeURIComponent(el.firstChild.nodeValue).split('+') : null, 10);
    446                 self._contextMenu.show();
    447                 break;
    448         }
    449     },
    450 
    451     _getWordSeparators : function() {
    452         var i, re = '', ch = tinyMCE.getParam('spellchecker_word_separator_chars', '\\s!"#$%&()*+,-./:;<=>?@[\]^_{|}§©«®±¶·¸»¼½¾¿×÷¤\u201d\u201c');
    453 
    454         for (i=0; i<ch.length; i++)
    455             re += '\\' + ch.charAt(i);
    456 
    457         return re;
    458     },
    459 
    460     _getWordList : function(n) {
    461         var i, x, s, nv = '', nl = tinyMCE.getNodeTree(n, [], 3), wl = [];
    462         var re = TinyMCE_SpellCheckerPlugin._getWordSeparators();
    463 
    464         for (i=0; i<nl.length; i++) {
    465             if (!new RegExp('/SCRIPT|STYLE/').test(nl[i].parentNode.nodeName))
    466                 nv += nl[i].nodeValue + " ";
    467         }
    468 
    469         nv = nv.replace(new RegExp('([0-9]|[' + re + '])', 'g'), ' ');
    470         nv = tinyMCE.trim(nv.replace(/(\s+)/g, ' '));
    471 
    472         nl = nv.split(/\s+/);
    473         for (i=0; i<nl.length; i++) {
    474             s = false;
    475             for (x=0; x<wl.length; x++) {
    476                 if (wl[x] == nl[i]) {
    477                     s = true;
    478                     break;
    479                 }
    480             }
    481 
    482             if (!s && nl[i].length > 0)
    483                 wl[wl.length] = nl[i];
    484         }
    485 
    486         return wl.join(' ');
    487     },
    488 
    489     _removeWords : function(doc, word, cleanup) {
    490         var i, c, nl = doc.getElementsByTagName("span");
    491         var self = TinyMCE_SpellCheckerPlugin;
    492         var inst = tinyMCE.selectedInstance, b = inst ? inst.selection.getBookmark() : null;
    493 
    494         word = typeof(word) == 'undefined' ? null : word;
    495 
    496         for (i=nl.length-1; i>=0; i--) {
    497             c = tinyMCE.getAttrib(nl[i], 'class');
    498 
    499             if ((c == 'mceItemHiddenSpellWord' || c == 'mceItemHidden') && (word == null || nl[i].innerHTML == word))
    500                 self._removeWord(nl[i]);
    501         }
    502 
    503         if (b && !cleanup)
    504             inst.selection.moveToBookmark(b);
    505     },
    506 
    507     _checkDone : function(inst) {
    508         var self = TinyMCE_SpellCheckerPlugin;
    509         var w = self._countWords(inst);
    510 
    511         if (w == 0) {
    512             self._removeWords(inst.getDoc());
    513             inst.spellcheckerOn = false;
    514             tinyMCE.switchClass(inst.editorId + '_spellchecker', 'mceMenuButton');
    515         }
    516     },
    517 
    518     _countWords : function(inst) {
    519         var i, w = 0, nl = inst.getDoc().getElementsByTagName("span"), c;
    520         var self = TinyMCE_SpellCheckerPlugin;
    521 
    522         for (i=nl.length-1; i>=0; i--) {
    523             c = tinyMCE.getAttrib(nl[i], 'class');
    524 
    525             if (c == 'mceItemHiddenSpellWord')
    526                 w++;
    527         }
    528 
    529         return w;
    530     },
    531 
    532     _removeWord : function(e) {
    533         if (e != null)
    534             tinyMCE.setOuterHTML(e, e.innerHTML);
    535     },
    536 
    537     _markWords : function(doc, n, wl) {
    538         var i, nv, nn, nl = tinyMCE.getNodeTree(n, new Array(), 3);
    539         var r1, r2, r3, r4, r5, w = '';
    540         var re = TinyMCE_SpellCheckerPlugin._getWordSeparators();
    541 
    542         for (i=0; i<wl.length; i++) {
    543             if (wl[i].length > 0)
    544                 w += wl[i] + ((i == wl.length-1) ? '' : '|');
    545         }
    546 
    547         for (i=0; i<nl.length; i++) {
    548             nv = nl[i].nodeValue;
     118        },
     119
     120        // Internal functions
     121
     122        _walk : function(n, f) {
     123            var d = this.editor.getDoc(), w;
     124
     125            if (d.createTreeWalker) {
     126                w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);
     127
     128                while ((n = w.nextNode()) != null)
     129                    f.call(this, n);
     130            } else
     131                tinymce.walk(n, f, 'childNodes');
     132        },
     133
     134        _getSeparators : function() {
     135            var re = '', i, str = this.editor.getParam('spellchecker_word_separator_chars', '\\s!"#$%&()*+,-./:;<=>?@[\]^_{|}§©«®±¶·¸»¼½¾¿×÷¤\u201d\u201c');
     136
     137            // Build word separator regexp
     138            for (i=0; i<str.length; i++)
     139                re += '\\' + str.charAt(i);
     140
     141            return re;
     142        },
     143
     144        _getWords : function() {
     145            var ed = this.editor, wl = [], tx = '', lo = {};
     146
     147            // Get area text
     148            this._walk(ed.getBody(), function(n) {
     149                if (n.nodeType == 3)
     150                    tx += n.nodeValue + ' ';
     151            });
     152
     153            // Split words by separator
     154            tx = tx.replace(new RegExp('([0-9]|[' + this._getSeparators() + '])', 'g'), ' ');
     155            tx = tinymce.trim(tx.replace(/(\s+)/g, ' '));
     156
     157            // Build word array and remove duplicates
     158            each(tx.split(' '), function(v) {
     159                if (!lo[v]) {
     160                    wl.push(v);
     161                    lo[v] = 1;
     162                }
     163            });
     164
     165            return wl;
     166        },
     167
     168        _removeWords : function(w) {
     169            var ed = this.editor, dom = ed.dom, se = ed.selection, b = se.getBookmark();
     170
     171            each(dom.select('span').reverse(), function(n) {
     172                if (n && (dom.hasClass(n, 'mceItemHiddenSpellWord') || dom.hasClass(n, 'mceItemHidden'))) {
     173                    if (!w || dom.decode(n.innerHTML) == w)
     174                        dom.remove(n, 1);
     175                }
     176            });
     177
     178            se.moveToBookmark(b);
     179        },
     180
     181        _markWords : function(wl) {
     182            var r1, r2, r3, r4, r5, w = '', ed = this.editor, re = this._getSeparators(), dom = ed.dom, nl = [];
     183            var se = ed.selection, b = se.getBookmark();
     184
     185            each(wl, function(v) {
     186                w += (w ? '|' : '') + v;
     187            });
    549188
    550189            r1 = new RegExp('([' + re + '])(' + w + ')([' + re + '])', 'g');
     
    554193            r5 = new RegExp('(' + w + ')([' + re + '])', 'g');
    555194
    556             if (r1.test(nv) || r2.test(nv) || r3.test(nv) || r4.test(nv)) {
    557                 nv = tinyMCE.xmlEncode(nv).replace('&#39;', "'");
    558                 nv = nv.replace(r5, '<span class="mceItemHiddenSpellWord">$1</span>$2');
    559                 nv = nv.replace(r3, '<span class="mceItemHiddenSpellWord">$1</span>$2');
    560 
    561                 nn = doc.createElement('span');
    562                 nn.className = "mceItemHidden";
    563                 nn.innerHTML = nv;
    564 
    565                 // Remove old text node
    566                 nl[i].parentNode.replaceChild(nn, nl[i]);
     195            // Collect all text nodes
     196            this._walk(this.editor.getBody(), function(n) {
     197                if (n.nodeType == 3) {
     198                    nl.push(n);
     199                }
     200            });
     201
     202            // Wrap incorrect words in spans
     203            each(nl, function(n) {
     204                var v;
     205
     206                if (n.nodeType == 3) {
     207                    v = n.nodeValue;
     208
     209                    if (r1.test(v) || r2.test(v) || r3.test(v) || r4.test(v)) {
     210                        v = dom.encode(v);
     211                        v = v.replace(r5, '<span class="mceItemHiddenSpellWord">$1</span>$2');
     212                        v = v.replace(r3, '<span class="mceItemHiddenSpellWord">$1</span>$2');
     213
     214                        dom.replace(dom.create('span', {'class' : 'mceItemHidden'}, v), n);
     215                    }
     216                }
     217            });
     218
     219            se.moveToBookmark(b);
     220        },
     221
     222        _showMenu : function(ed, e) {
     223            var t = this, ed = t.editor, m = t._menu, p1, dom = ed.dom, vp = dom.getViewPort(ed.getWin());
     224
     225            if (!m) {
     226                p1 = DOM.getPos(ed.getContentAreaContainer());
     227                //p2 = DOM.getPos(ed.getContainer());
     228
     229                m = ed.controlManager.createDropMenu('spellcheckermenu', {
     230                    offset_x : p1.x,
     231                    offset_y : p1.y,
     232                    'class' : 'noIcons'
     233                });
     234
     235                t._menu = m;
    567236            }
     237
     238            if (dom.hasClass(e.target, 'mceItemHiddenSpellWord')) {
     239                m.removeAll();
     240                m.add({title : 'spellchecker.wait', 'class' : 'mceMenuItemTitle'}).setDisabled(1);
     241
     242                t._sendRPC('getSuggestions', [t.selectedLang, dom.decode(e.target.innerHTML)], function(r) {
     243                    m.removeAll();
     244
     245                    if (r.length > 0) {
     246                        m.add({title : 'spellchecker.sug', 'class' : 'mceMenuItemTitle'}).setDisabled(1);
     247                        each(r, function(v) {
     248                            m.add({title : v, onclick : function() {
     249                                dom.replace(ed.getDoc().createTextNode(v), e.target);
     250                                t._checkDone();
     251                            }});
     252                        });
     253
     254                        m.addSeparator();
     255                    } else
     256                        m.add({title : 'spellchecker.no_sug', 'class' : 'mceMenuItemTitle'}).setDisabled(1);
     257
     258                    m.add({
     259                        title : 'spellchecker.ignore_word',
     260                        onclick : function() {
     261                            dom.remove(e.target, 1);
     262                            t._checkDone();
     263                        }
     264                    });
     265
     266                    m.add({
     267                        title : 'spellchecker.ignore_words',
     268                        onclick : function() {
     269                            t._removeWords(dom.decode(e.target.innerHTML));
     270                            t._checkDone();
     271                        }
     272                    });
     273
     274                    m.update();
     275                });
     276
     277                ed.selection.select(e.target);
     278                p1 = dom.getPos(e.target);
     279                m.showMenu(p1.x, p1.y + e.target.offsetHeight - vp.y);
     280
     281                return tinymce.dom.Event.cancel(e);
     282            } else
     283                m.hideMenu();
     284        },
     285
     286        _checkDone : function() {
     287            var t = this, ed = t.editor, dom = ed.dom, o;
     288
     289            each(dom.select('span'), function(n) {
     290                if (n && dom.hasClass(n, 'mceItemHiddenSpellWord')) {
     291                    o = true;
     292                    return false;
     293                }
     294            });
     295
     296            if (!o)
     297                t._done();
     298        },
     299
     300        _done : function() {
     301            var t = this, la = t.active;
     302
     303            t.active = 0;
     304            t._removeWords();
     305
     306            if (t._menu)
     307                t._menu.hideMenu();
     308
     309            if (la)
     310                t.editor.nodeChanged();
     311        },
     312
     313        _sendRPC : function(m, p, cb) {
     314            var t = this, url = t.editor.getParam("spellchecker_rpc_url", this.url+'/rpc.php');
     315
     316            if (url == '{backend}') {
     317                alert('Please specify: spellchecker_rpc_url');
     318                return;
     319            }
     320
     321            JSONRequest.sendRPC({
     322                url : url,
     323                method : m,
     324                params : p,
     325                success : cb,
     326                error : function(e, x) {
     327                    t.editor.setProgressState(0);
     328                    t.editor.windowManager.alert(e.errstr || ('Error response: ' + x.responseText));
     329                }
     330            });
    568331        }
    569     },
    570 
    571     _buildMenu : function(sg, max) {
    572         var i, self = TinyMCE_SpellCheckerPlugin, cm = self._contextMenu;
    573 
    574         cm.clear();
    575 
    576         if (sg != null) {
    577             cm.addTitle(tinyMCE.getLang('lang_spellchecker_sug', '', true));
    578 
    579             for (i=0; i<sg.length && i<max; i++)
    580                 cm.addItem(sg[i], 'tinyMCE.execCommand("mceSpellCheckReplace",false,"' + sg[i] + '");');
    581 
    582             cm.addSeparator();
    583         } else
    584             cm.addTitle(tinyMCE.getLang('lang_spellchecker_no_sug', '', true));
    585 
    586         cm.addItem(tinyMCE.getLang('lang_spellchecker_ignore_word', '', true), 'tinyMCE.execCommand(\'mceSpellCheckIgnore\');');
    587         cm.addItem(tinyMCE.getLang('lang_spellchecker_ignore_words', '', true), 'tinyMCE.execCommand(\'mceSpellCheckIgnoreAll\');');
    588 
    589         cm.update();
    590     },
    591 
    592     _getAjaxHTTP : function() {
    593         try {
    594             return new ActiveXObject('Msxml2.XMLHTTP')
    595         } catch (e) {
    596             try {
    597                 return new ActiveXObject('Microsoft.XMLHTTP')
    598             } catch (e) {
    599                 return new XMLHttpRequest();
    600             }
    601         }
    602     },
    603 
    604     /**
    605      * Perform AJAX call.
    606      *
    607      * @param {string} u URL of AJAX service.
    608      * @param {function} f Function to call when response arrives.
    609      * @param {string} m Request method post or get.
    610      * @param {Array} a Array with arguments to send.
    611      */
    612     _sendAjax : function(u, f, m, a) {
    613         var x = TinyMCE_SpellCheckerPlugin._getAjaxHTTP();
    614 
    615         x.open(m, u, true);
    616 
    617         x.onreadystatechange = function() {
    618             if (x.readyState == 4)
    619                 f(x.responseXML, x.responseText);
    620         };
    621 
    622         if (m == 'post')
    623             x.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    624 
    625         x.send(a);
    626     }
    627 };
    628 
    629 // Register plugin
    630 tinyMCE.addPlugin('spellchecker', TinyMCE_SpellCheckerPlugin);
     332    });
     333
     334    // Register plugin
     335    tinymce.PluginManager.add('spellchecker', tinymce.plugins.SpellcheckerPlugin);
     336})();
  • trunk/wp-includes/js/tinymce/plugins/wordpress/editor_plugin.js

    r6567 r6632  
    11/* Import plugin specific language pack */
    2 tinyMCE.importPluginLanguagePack('wordpress', 'en');
     2//tinyMCE.importPluginLanguagePack('wordpress', 'en');
    33
    44var TinyMCE_wordpressPlugin = {
     
    288288        // We have a TON of cleanup to do.
    289289
     290        if ( tinyMCE.activeEditor.isHidden() ) {
     291    //        return content;           
     292        }
     293   
    290294        // Mark </p> if it has any attributes.
    291295        content = content.replace(new RegExp('(<p[^>]+>.*?)</p>', 'mg'), '$1</p#>');
     
    295299
    296300        // Get it ready for wpautop.
    297         content = content.replace(new RegExp('\\s*<p>', 'mgi'), '');
     301        content = content.replace(new RegExp('\\s*<p>', 'mgi'), '');
    298302        content = content.replace(new RegExp('\\s*</p>\\s*', 'mgi'), '\n\n');
    299303        content = content.replace(new RegExp('\\n\\s*\\n', 'mgi'), '\n\n');
     
    305309        content = content.replace(new RegExp('\\s*</('+blocklist+')>\\s*', 'mg'), '</$1>\n');
    306310        content = content.replace(new RegExp('<li>', 'g'), '\t<li>');
    307 
     311       
     312        if ( content.indexOf('<object') != -1 ) {
     313            content = content.replace(new RegExp('\\s*<param([^>]*)>\\s*', 'g'), "<param$1>"); // no pee inside object/embed
     314            content = content.replace(new RegExp('\\s*</embed>\\s*', 'g'), '</embed>');
     315        }
     316       
    308317        // Unmark special paragraph closing tags
    309318        content = content.replace(new RegExp('</p#>', 'g'), '</p>\n');
     
    366375};
    367376
    368 tinyMCE.addPlugin("wordpress", TinyMCE_wordpressPlugin);
     377//tinyMCE.addPlugin("wordpress", TinyMCE_wordpressPlugin);
    369378
    370379/* This little hack protects our More and Page placeholders from the removeformat command */
     
    477486    var pdr = ta.parentNode;
    478487
    479     if ( inst ) {
     488    if ( ! inst.isHidden(id) ) {
    480489        edToggle(H, P);
    481490
     
    493502        var y1 = table.offsetTop + table.offsetHeight;
    494503
    495         if ( TinyMCE_AdvancedTheme._getCookie("TinyMCE_" + inst.editorId + "_height") == null ) {
     504        if ( tinymce.util.Cookie.get("TinyMCE_" + inst.editorId + "_height") == null ) {
    496505            var expires = new Date();
    497506            expires.setTime(expires.getTime() + 3600000 * 24 * 30);
    498507            var offset = tinyMCE.isMSIE ? 1 : 2;
    499             TinyMCE_AdvancedTheme._setCookie("TinyMCE_" + inst.editorId + "_height", "" + (table.offsetHeight - offset), expires);
     508            tinymce.util.Cookie.set("TinyMCE_" + inst.editorId + "_height", "" + (table.offsetHeight - offset), expires);
    500509        }
    501510
    502511        // Unload the rich editor
    503         inst.triggerSave(false, false);
    504         htm = inst.formElement.value;
    505         tinyMCE.removeMCEControl(id);
    506         document.getElementById(id).value = htm;
    507         --tinyMCE.idCounter;
     512        // inst.triggerSave(false, false);
     513        // inst.formElement.value;
     514        inst.hide(); // tinyMCE.removeMCEControl(id);
     515        // document.getElementById(id).value = htm;
     516        // --tinyMCE.idCounter;
    508517
    509518        // Reveal Quicktags and textarea
     
    544553
    545554        // Load the rich editor with formatted html
    546         if ( tinyMCE.isMSIE ) {
     555        //if ( tinyMCE.isMSIE ) {
     556        //  ta.value = wpautop(ta.value);
     557        //  tinyMCE.addMCEControl(ta, id);
     558        //} else {
    547559            ta.value = wpautop(ta.value);
    548             tinyMCE.addMCEControl(ta, id);
    549         } else {
    550             htm = wpautop(ta.value);
    551             tinyMCE.addMCEControl(ta, id);
    552             tinyMCE.getInstanceById(id).execCommand('mceSetContent', null, htm);
    553         }
     560            inst.show() // tinyMCE.addMCEControl(ta, id);
     561            //tinyMCE.getInstanceById(id).execCommand('mceSetContent', null, htm);
     562        //}
    554563
    555564        if ( tinyMCE.isMSIE && !tinyMCE.isOpera ) {
  • trunk/wp-includes/js/tinymce/plugins/wordpress/popups.css

    • Property svn:eol-style set to native
  • trunk/wp-includes/js/tinymce/plugins/wordpress/wordpress.css

    • Property svn:eol-style set to native
  • trunk/wp-includes/js/tinymce/themes/advanced/about.htm

    r4799 r6632  
     1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    12<html xmlns="http://www.w3.org/1999/xhtml">
    23<head>
    3     <title>{$lang_about_title}</title>
    4     <script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
    5     <script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
    6     <script language="javascript" type="text/javascript" src="jscripts/about.js"></script>
    7     <base target="_self" />
     4    <title>{#advanced_dlg.about_title}</title>
     5    <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
     6    <script type="text/javascript" src="../../utils/mctabs.js"></script>
     7    <script type="text/javascript" src="js/about.js"></script>
    88</head>
    9 <body id="about" onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
     9<body id="about" style="display: none">
    1010        <div class="tabs">
    1111            <ul>
    12                 <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{$lang_about}</a></span></li>
    13                 <li id="help_tab"><span><a href="javascript:mcTabs.displayTab('help_tab','help_panel');" onmousedown="return false;">{$lang_help}</a></span></li>
    14                 <li id="plugins_tab"><span><a href="javascript:mcTabs.displayTab('plugins_tab','plugins_panel');" onmousedown="return false;">{$lang_plugins}</a></span></li>
     12                <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advanced_dlg.about_general}</a></span></li>
     13                <li id="help_tab" style="display:none"><span><a href="javascript:mcTabs.displayTab('help_tab','help_panel');" onmousedown="return false;">{#advanced_dlg.about_help}</a></span></li>
     14                <li id="plugins_tab"><span><a href="javascript:mcTabs.displayTab('plugins_tab','plugins_panel');" onmousedown="return false;">{#advanced_dlg.about_plugins}</a></span></li>
    1515            </ul>
    1616        </div>
     
    1818        <div class="panel_wrapper">
    1919            <div id="general_panel" class="panel current">
    20                 <h3>{$lang_about_title}</h3>
    21                 <p>Version: {$tinymce_version} ({$tinymce_releasedate})</p>
     20                <h3>{#advanced_dlg.about_title}</h3>
     21                <p>Version: <span id="version"></span> (<span id="date"></span>)</p>
    2222                <p>TinyMCE is a platform independent web based Javascript HTML WYSIWYG editor control released as Open Source under <a href="../../license.txt" target="_blank">LGPL</a>
    2323                by Moxiecode Systems AB. It has the ability to convert HTML TEXTAREA fields or other HTML elements to editor instances.</p>
     
    2525                <p>For more information about this software visit the <a href="http://tinymce.moxiecode.com" target="_blank">TinyMCE website</a>.</p>
    2626
    27                 <div id="buttoncontainer"></div>
     27                <div id="buttoncontainer">
     28                    <a href="http://www.moxiecode.com" target="_blank"><img src="http://tinymce.moxiecode.com/images/gotmoxie.png" alt="Got Moxie?" border="0" /></a>
     29                    <a href="http://sourceforge.net/projects/tinymce/" target="_blank"><img src="http://sourceforge.net/sflogo.php?group_id=103281" alt="Hosted By Sourceforge" border="0" /></a>
     30                    <a href="http://www.freshmeat.net/projects/tinymce" target="_blank"><img src="http://tinymce.moxiecode.com/images/fm.gif" alt="Also on freshmeat" border="0" /></a>
     31                </div>
    2832            </div>
    2933
    3034            <div id="plugins_panel" class="panel">
    3135                <div id="pluginscontainer">
    32                     <h3>{$lang_loaded_plugins}</h3>
     36                    <h3>{#advanced_dlg.about_loaded}</h3>
    3337
    3438                    <div id="plugintablecontainer">
     
    4650        <div class="mceActionPanel">
    4751            <div style="float: right">
    48                 <input type="button" id="cancel" name="cancel" value="{$lang_close}" onclick="tinyMCEPopup.close();" />
     52                <input type="button" id="cancel" name="cancel" value="{#close}" onclick="tinyMCEPopup.close();" />
    4953            </div>
    5054        </div>
  • trunk/wp-includes/js/tinymce/themes/advanced/anchor.htm

    r3664 r6632  
     1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    12<html xmlns="http://www.w3.org/1999/xhtml">
    23<head>
    3     <title>{$lang_insert_anchor_title}</title>
    4     <script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
    5     <script language="javascript" type="text/javascript" src="jscripts/anchor.js"></script>
     4    <title>{#advanced_dlg.anchor_title}</title>
     5    <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
     6    <script type="text/javascript" src="js/anchor.js"></script>
    67    <base target="_self" />
    78</head>
    8 <body onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
    9 <form onsubmit="insertAnchor();return false;" action="#">
    10 
     9<body style="display: none">
     10<form onsubmit="AnchorDialog.update();return false;" action="#">
    1111    <table border="0" cellpadding="4" cellspacing="0">
    1212        <tr>
    13             <td colspan="2" class="title">{$lang_insert_anchor_title}</td>
     13            <td colspan="2" class="title">{#advanced_dlg.anchor_title}</td>
    1414        </tr>
    1515        <tr>
    16             <td nowrap="nowrap">{$lang_insert_anchor_name}:</td>
     16            <td nowrap="nowrap">{#advanced_dlg.anchor_name}:</td>
    1717            <td><input name="anchorName" type="text" id="anchorName" value="" style="width: 200px" /></td>
    1818        </tr>
     
    2121    <div class="mceActionPanel">
    2222        <div style="float: left">
    23             <input type="button" id="insert" name="insert" value="{$lang_update}" onclick="insertAnchor();" />
     23            <input type="button" id="insert" name="insert" value="{#update}" onclick="AnchorDialog.update();" />
    2424        </div>
    2525
    2626        <div style="float: right">
    27             <input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
     27            <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
    2828        </div>
    2929    </div>
    30 
    3130</form>
    3231</body>
  • trunk/wp-includes/js/tinymce/themes/advanced/charmap.htm

    r4506 r6632  
    11<html xmlns="http://www.w3.org/1999/xhtml">
    22<head>
    3     <title>{$lang_theme_charmap_title}</title>
     3    <title>{#advanced_dlg.charmap_title}</title>
    44    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
    5     <script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
    6     <script language="javascript" type="text/javascript" src="jscripts/charmap.js"></script>
     5    <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
     6    <script type="text/javascript" src="js/charmap.js"></script>
    77    <base target="_self" />
    88</head>
    9 <body onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
     9<body style="display: none">
    1010<table align="center" border="0" cellspacing="0" cellpadding="2">
    1111    <tr>
    12         <td colspan="2" class="title">{$lang_theme_charmap_title}</td>
     12        <td colspan="2" class="title">{#advanced_dlg.charmap_title}</td>
    1313    </tr>
    1414    <tr>
    15         <td rowspan="2" align="left" valign="top">
    16             <script language="javascript" type="text/javascript">renderCharMapHTML();</script>
     15        <td id="charmap" rowspan="2" align="left" valign="top">
     16            <!-- Chars will be rendered here -->
    1717        </td>
    1818        <td width="100" align="center" valign="top">
  • trunk/wp-includes/js/tinymce/themes/advanced/color_picker.htm

    r5487 r6632  
     1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    12<html xmlns="http://www.w3.org/1999/xhtml">
    23<head>
    3     <title>{$lang_theme_colorpicker_title}</title>
    4     <script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
    5     <script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
    6     <script language="javascript" type="text/javascript" src="jscripts/color_picker.js"></script>
    7     <link href="css/colorpicker.css" rel="stylesheet" type="text/css" />
     4    <title>{#advanced_dlg.colorpicker_title}</title>
     5    <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
     6    <script type="text/javascript" src="../../utils/mctabs.js"></script>
     7    <script type="text/javascript" src="js/color_picker.js"></script>
    88    <base target="_self" />
    99</head>
    10 <body onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
     10<body id="colorpicker" style="display: none">
    1111    <div class="tabs">
    1212        <ul>
    13             <li id="picker_tab" class="current"><span><a href="javascript:mcTabs.displayTab('picker_tab','picker_panel');" onmousedown="return false;">{$lang_color_picker_tab}</a></span></li>
    14             <li id="rgb_tab"><span><a href="#" onclick="generateWebColors();mcTabs.displayTab('rgb_tab','rgb_panel');" onmousedown="return false;">{$lang_web_colors_tab}</a></span></li>
    15             <li id="named_tab"><span><a  href="#" onclick="generateNamedColors();javascript:mcTabs.displayTab('named_tab','named_panel');" onmousedown="return false;">{$lang_named_colors_tab}</a></span></li>
     13            <li id="picker_tab" class="current"><span><a href="javascript:mcTabs.displayTab('picker_tab','picker_panel');" onmousedown="return false;">{#advanced_dlg.colorpicker_picker_tab}</a></span></li>
     14            <li id="rgb_tab"><span><a href="javascript:;" onclick="generateWebColors();mcTabs.displayTab('rgb_tab','rgb_panel');" onmousedown="return false;">{#advanced_dlg.colorpicker_palette_tab}</a></span></li>
     15            <li id="named_tab"><span><a  href="javascript:;" onclick="generateNamedColors();javascript:mcTabs.displayTab('named_tab','named_panel');" onmousedown="return false;">{#advanced_dlg.colorpicker_named_tab}</a></span></li>
    1616        </ul>
    1717    </div>
     
    2020        <div id="picker_panel" class="panel current">
    2121            <fieldset>
    22                 <legend>{$lang_color_picker}</legend>
     22                <legend>{#advanced_dlg.colorpicker_picker_title}</legend>
    2323                <div id="picker">
    24                     <img id="colorpicker" src="images/colors.jpg" onclick="computeColor(event)" onmousedown="isMouseDown = true;return false;" onmouseup="isMouseDown = false;" onmousemove="if (isMouseDown && isMouseOver) computeColor(event); return false;" onmouseover="isMouseOver=true;" onmouseout="isMouseOver=false;" />
     24                    <img id="colors" src="img/colorpicker.jpg" onclick="computeColor(event)" onmousedown="isMouseDown = true;return false;" onmouseup="isMouseDown = false;" onmousemove="if (isMouseDown && isMouseOver) computeColor(event); return false;" onmouseover="isMouseOver=true;" onmouseout="isMouseOver=false;" />
    2525
    2626                    <div id="light">
     
    3535        <div id="rgb_panel" class="panel">
    3636            <fieldset>
    37                 <legend>{$lang_web_colors}</legend>
     37                <legend>{#advanced_dlg.colorpicker_palette_title}</legend>
    3838                <div id="webcolors">
    3939                    <!-- Gets filled with web safe colors-->
     
    4646        <div id="named_panel" class="panel">
    4747            <fieldset>
    48                 <legend>{$lang_named_colors}</legend>
     48                <legend>{#advanced_dlg.colorpicker_named_title}</legend>
    4949                <div id="namedcolors">
    5050                    <!-- Gets filled with named colors-->
     
    5454
    5555                <div id="colornamecontainer">
    56                     {$lang_color_name} <span id="colorname"></span>
     56                    {#advanced_dlg.colorpicker_name} <span id="colorname"></span>
    5757                </div>
    5858            </fieldset>
     
    6262    <div class="mceActionPanel">
    6363        <div style="float: left">
    64             <input type="button" id="insert" name="insert" value="{$lang_theme_colorpicker_apply}" onclick="insertAction();" />
     64            <input type="button" id="insert" name="insert" value="{#apply}" onclick="insertAction();" />
    6565        </div>
    6666
     
    6868
    6969        <div id="previewblock">
    70             <label for="color">{$lang_color}</label> <input id="color" type="text" size="8" maxlength="8" class="text" />
     70            <label for="color">{#advanced_dlg.colorpicker_color}</label> <input id="color" type="text" size="8" maxlength="8" class="text" />
    7171        </div>
    7272    </div>
  • trunk/wp-includes/js/tinymce/themes/advanced/css/colorpicker.css

    • Property svn:eol-style set to native
  • trunk/wp-includes/js/tinymce/themes/advanced/css/editor_content.css

    • Property svn:eol-style set to native
  • trunk/wp-includes/js/tinymce/themes/advanced/css/editor_popup.css

    • Property svn:eol-style set to native
  • trunk/wp-includes/js/tinymce/themes/advanced/css/editor_ui.css

    • Property svn:eol-style set to native
  • trunk/wp-includes/js/tinymce/themes/advanced/editor_template.js

    r5577 r6632  
    11/**
    2  * $Id: editor_template_src.js 256 2007-04-24 09:03:20Z spocke $
     2 * $Id: editor_template_src.js 520 2008-01-07 16:30:32Z spocke $
    33 *
    44 * @author Moxiecode
    5  * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
     5 * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
    66 */
    77
    8 /* Import theme specific language pack */
    9 tinyMCE.importThemeLanguagePack('advanced');
    10 
    11 var TinyMCE_AdvancedTheme = {
    12     // Private theme fields
    13     _defColors : "000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF",
    14     _autoImportCSSClasses : true,
    15     _resizer : {},
    16     _buttons : [
    17         // Control id, button img, button title, command, user_interface, value
    18         ['bold', '{$lang_bold_img}', 'lang_bold_desc', 'Bold'],
    19         ['italic', '{$lang_italic_img}', 'lang_italic_desc', 'Italic'],
    20         ['underline', '{$lang_underline_img}', 'lang_underline_desc', 'Underline'],
    21         ['strikethrough', 'strikethrough.gif', 'lang_striketrough_desc', 'Strikethrough'],
    22         ['justifyleft', 'justifyleft.gif', 'lang_justifyleft_desc', 'JustifyLeft'],
    23         ['justifycenter', 'justifycenter.gif', 'lang_justifycenter_desc', 'JustifyCenter'],
    24         ['justifyright', 'justifyright.gif', 'lang_justifyright_desc', 'JustifyRight'],
    25         ['justifyfull', 'justifyfull.gif', 'lang_justifyfull_desc', 'JustifyFull'],
    26         ['bullist', 'bullist.gif', 'lang_bullist_desc', 'InsertUnorderedList'],
    27         ['numlist', 'numlist.gif', 'lang_numlist_desc', 'InsertOrderedList'],
    28         ['outdent', 'outdent.gif', 'lang_outdent_desc', 'Outdent'],
    29         ['indent', 'indent.gif', 'lang_indent_desc', 'Indent'],
    30         ['cut', 'cut.gif', 'lang_cut_desc', 'Cut'],
    31         ['copy', 'copy.gif', 'lang_copy_desc', 'Copy'],
    32         ['paste', 'paste.gif', 'lang_paste_desc', 'Paste'],
    33         ['undo', 'undo.gif', 'lang_undo_desc', 'Undo'],
    34         ['redo', 'redo.gif', 'lang_redo_desc', 'Redo'],
    35         ['link', 'link.gif', 'lang_link_desc', 'mceLink', true],
    36         ['unlink', 'unlink.gif', 'lang_unlink_desc', 'unlink'],
    37         ['image', 'image.gif', 'lang_image_desc', 'mceImage', true],
    38         ['cleanup', 'cleanup.gif', 'lang_cleanup_desc', 'mceCleanup'],
    39         ['help', 'help.gif', 'lang_help_desc', 'mceHelp'],
    40         ['code', 'code.gif', 'lang_theme_code_desc', 'mceCodeEditor'],
    41         ['hr', 'hr.gif', 'lang_theme_hr_desc', 'inserthorizontalrule'],
    42         ['removeformat', 'removeformat.gif', 'lang_theme_removeformat_desc', 'removeformat'],
    43         ['sub', 'sub.gif', 'lang_theme_sub_desc', 'subscript'],
    44         ['sup', 'sup.gif', 'lang_theme_sup_desc', 'superscript'],
    45         ['forecolor', 'forecolor.gif', 'lang_theme_forecolor_desc', 'forecolor', true],
    46         ['forecolorpicker', 'forecolor.gif', 'lang_theme_forecolor_desc', 'forecolorpicker', true],
    47         ['backcolor', 'backcolor.gif', 'lang_theme_backcolor_desc', 'HiliteColor', true],
    48         ['backcolorpicker', 'backcolor.gif', 'lang_theme_backcolor_desc', 'backcolorpicker', true],
    49         ['charmap', 'charmap.gif', 'lang_theme_charmap_desc', 'mceCharMap'],
    50         ['visualaid', 'visualaid.gif', 'lang_theme_visualaid_desc', 'mceToggleVisualAid'],
    51         ['anchor', 'anchor.gif', 'lang_theme_anchor_desc', 'mceInsertAnchor'],
    52         ['newdocument', 'newdocument.gif', 'lang_newdocument_desc', 'mceNewDocument']
    53     ],
    54 
    55     _buttonMap : 'anchor,backcolor,bold,bullist,charmap,cleanup,code,copy,cut,forecolor,help,hr,image,indent,italic,justifycenter,justifyfull,justifyleft,justifyright,link,newdocument,numlist,outdent,paste,redo,removeformat,strikethrough,sub,sup,underline,undo,unlink,visualaid,advhr,ltr,rtl,emotions,flash,fullpage,fullscreen,iespell,insertdate,inserttime,pastetext,pasteword,selectall,preview,print,save,replace,search,table,cell_props,delete_col,delete_row,col_after,col_before,row_after,row_before,merge_cells,row_props,split_cells,delete_table',
    56 
    57     /**
    58      * Returns HTML code for the specificed control.
    59      */
    60     getControlHTML : function(button_name) {
    61         var i, x, but;
    62 
    63         // Lookup button in button list
    64         for (i=0; i<TinyMCE_AdvancedTheme._buttons.length; i++) {
    65             but = TinyMCE_AdvancedTheme._buttons[i];
    66 
    67             if (but[0] == button_name && (button_name == "forecolor" || button_name == "backcolor"))
    68                 return tinyMCE.getMenuButtonHTML(but[0], but[2], '{$themeurl}/images/' + but[1], but[3] + "Menu", but[3], (but.length > 4 ? but[4] : false), (but.length > 5 ? but[5] : null));
    69 
    70             if (but[0] == button_name)
    71                 return tinyMCE.getButtonHTML(but[0], but[2], '{$themeurl}/images/' + but[1], but[3], (but.length > 4 ? but[4] : false), (but.length > 5 ? but[5] : null));
    72         }
    73 
    74         // Custom controlls other than buttons
    75         switch (button_name) {
    76             case "formatselect":
    77                 var html = '<select id="{$editor_id}_formatSelect" name="{$editor_id}_formatSelect" onfocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="tinyMCE.execInstanceCommand(\'{$editor_id}\',\'FormatBlock\',false,this.options[this.selectedIndex].value);" class="mceSelectList">';
    78                 var formats = tinyMCE.getParam("theme_advanced_blockformats", "p,address,pre,h1,h2,h3,h4,h5,h6", true).split(',');
    79                 var lookup = [
    80                     ['p', '{$lang_theme_paragraph}'],
    81                     ['address', '{$lang_theme_address}'],
    82                     ['pre', '{$lang_theme_pre}'],
    83                     ['h1', '{$lang_theme_h1}'],
    84                     ['h2', '{$lang_theme_h2}'],
    85                     ['h3', '{$lang_theme_h3}'],
    86                     ['h4', '{$lang_theme_h4}'],
    87                     ['h5', '{$lang_theme_h5}'],
    88                     ['h6', '{$lang_theme_h6}'],
    89                     ['div', '{$lang_theme_div}'],
    90                     ['blockquote', '{$lang_theme_blockquote}'],
    91                     ['code', '{$lang_theme_code}'],
    92                     ['dt', '{$lang_theme_dt}'],
    93                     ['dd', '{$lang_theme_dd}'],
    94                     ['samp', '{$lang_theme_samp}']
    95                 ];
    96 
    97                 html += '<option value="">{$lang_theme_block}</option>';
    98 
    99                 // Build format select
    100                 for (var i=0; i<formats.length; i++) {
    101                     for (var x=0; x<lookup.length; x++) {
    102                         if (formats[i] == lookup[x][0])
    103                             html += '<option value="&lt;' + lookup[x][0] + '&gt;">' + lookup[x][1] + '</option>';
     8(function() {
     9    var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, each = tinymce.each, Cookie = tinymce.util.Cookie, lastExtID;
     10
     11    // Tell it to load theme specific language pack(s)
     12    tinymce.ThemeManager.requireLangPack('advanced');
     13
     14    tinymce.create('tinymce.themes.AdvancedTheme', {
     15        // Control name lookup, format: title, command
     16        controls : {
     17            bold : ['bold_desc', 'Bold'],
     18            italic : ['italic_desc', 'Italic'],
     19            underline : ['underline_desc', 'Underline'],
     20            strikethrough : ['striketrough_desc', 'Strikethrough'],
     21            justifyleft : ['justifyleft_desc', 'JustifyLeft'],
     22            justifycenter : ['justifycenter_desc', 'JustifyCenter'],
     23            justifyright : ['justifyright_desc', 'JustifyRight'],
     24            justifyfull : ['justifyfull_desc', 'JustifyFull'],
     25            bullist : ['bullist_desc', 'InsertUnorderedList'],
     26            numlist : ['numlist_desc', 'InsertOrderedList'],
     27            outdent : ['outdent_desc', 'Outdent'],
     28            indent : ['indent_desc', 'Indent'],
     29            cut : ['cut_desc', 'Cut'],
     30            copy : ['copy_desc', 'Copy'],
     31            paste : ['paste_desc', 'Paste'],
     32            undo : ['undo_desc', 'Undo'],
     33            redo : ['redo_desc', 'Redo'],
     34            link : ['link_desc', 'mceLink'],
     35            unlink : ['unlink_desc', 'unlink'],
     36            image : ['image_desc', 'mceImage'],
     37            cleanup : ['cleanup_desc', 'mceCleanup'],
     38            help : ['help_desc', 'mceHelp'],
     39            code : ['code_desc', 'mceCodeEditor'],
     40            hr : ['hr_desc', 'InsertHorizontalRule'],
     41            removeformat : ['removeformat_desc', 'RemoveFormat'],
     42            sub : ['sub_desc', 'subscript'],
     43            sup : ['sup_desc', 'superscript'],
     44            forecolor : ['forecolor_desc', 'ForeColor'],
     45            forecolorpicker : ['forecolor_desc', 'mceForeColor'],
     46            backcolor : ['backcolor_desc', 'HiliteColor'],
     47            backcolorpicker : ['backcolor_desc', 'mceBackColor'],
     48            charmap : ['charmap_desc', 'mceCharMap'],
     49            visualaid : ['visualaid_desc', 'mceToggleVisualAid'],
     50            anchor : ['anchor_desc', 'mceInsertAnchor'],
     51            newdocument : ['newdocument_desc', 'mceNewDocument'],
     52            blockquote : ['blockquote_desc', 'mceBlockQuote']
     53        },
     54
     55        stateControls : ['bold', 'italic', 'underline', 'strikethrough', 'bullist', 'numlist', 'justifyleft', 'justifycenter', 'justifyright', 'justifyfull', 'sub', 'sup', 'blockquote'],
     56
     57        init : function(ed, url) {
     58            var t = this, s;
     59
     60            t.editor = ed;
     61            t.url = url;
     62            t.onResolveName = new tinymce.util.Dispatcher(this);
     63
     64            // Default settings
     65            t.settings = s = extend({
     66                theme_advanced_path : true,
     67                theme_advanced_toolbar_location : 'bottom',
     68                theme_advanced_buttons1 : "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect",
     69                theme_advanced_buttons2 : "bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code",
     70                theme_advanced_buttons3 : "hr,removeformat,visualaid,|,sub,sup,|,charmap",
     71                theme_advanced_blockformats : "p,address,pre,h1,h2,h3,h4,h5,h6",
     72                theme_advanced_toolbar_align : "center",
     73                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",
     74                theme_advanced_font_sizes : "1,2,3,4,5,6,7",
     75                theme_advanced_more_colors : 1,
     76                theme_advanced_row_height : 23,
     77                theme_advanced_resize_horizontal : 1,
     78                theme_advanced_resizing_use_cookie : 1
     79            }, ed.settings);
     80
     81            if (s.theme_advanced_statusbar_location == 'none')
     82                s.theme_advanced_statusbar_location = 0;
     83
     84            // Init editor
     85            ed.onInit.add(function() {
     86                ed.onNodeChange.add(t._nodeChanged, t);
     87                ed.dom.loadCSS(ed.baseURI.toAbsolute("themes/advanced/skins/" + ed.settings.skin + "/content.css"));
     88            });
     89
     90            ed.onSetProgressState.add(function(ed, b, ti) {
     91                var co, id = ed.id, tb;
     92
     93                if (b) {
     94                    t.progressTimer = setTimeout(function() {
     95                        co = ed.getContainer();
     96                        co = co.insertBefore(DOM.create('DIV', {style : 'position:relative'}), co.firstChild);
     97                        tb = DOM.get(ed.id + '_tbl');
     98
     99                        DOM.add(co, 'div', {id : id + '_blocker', 'class' : 'mceBlocker', style : {width : tb.clientWidth + 2, height : tb.clientHeight + 2}});
     100                        DOM.add(co, 'div', {id : id + '_progress', 'class' : 'mceProgress', style : {left : tb.clientWidth / 2, top : tb.clientHeight / 2}});
     101                    }, ti || 0);
     102                } else {
     103                    DOM.remove(id + '_blocker');
     104                    DOM.remove(id + '_progress');
     105                    clearTimeout(t.progressTimer);
     106                }
     107            });
     108
     109            DOM.loadCSS(ed.baseURI.toAbsolute(s.editor_css || "themes/advanced/skins/" + ed.settings.skin + "/ui.css"));
     110        },
     111
     112        createControl : function(n, cf) {
     113            var cd, c;
     114
     115            if (c = cf.createControl(n))
     116                return c;
     117
     118            switch (n) {
     119                case "styleselect":
     120                    return this._createStyleSelect();
     121
     122                case "formatselect":
     123                    return this._createBlockFormats();
     124
     125                case "fontselect":
     126                    return this._createFontSelect();
     127
     128                case "fontsizeselect":
     129                    return this._createFontSizeSelect();
     130
     131                case "forecolor":
     132                    return this._createForeColorMenu();
     133
     134                case "backcolor":
     135                    return this._createBackColorMenu();
     136            }
     137
     138            if ((cd = this.controls[n]))
     139                return cf.createButton(n, {title : "advanced." + cd[0], cmd : cd[1], ui : cd[2], value : cd[3]});
     140        },
     141
     142        execCommand : function(cmd, ui, val) {
     143            var f = this['_' + cmd];
     144
     145            if (f) {
     146                f.call(this, ui, val);
     147                return true;
     148            }
     149
     150            return false;
     151        },
     152
     153        _importClasses : function() {
     154            var ed = this.editor, c = ed.controlManager.get('styleselect');
     155
     156            if (c.getLength() == 0) {
     157                each(ed.dom.getClasses(), function(o) {
     158                    c.add(o['class'], o['class']);
     159                });
     160            }
     161        },
     162
     163        _createStyleSelect : function(n) {
     164            var t = this, ed = t.editor, cf = ed.controlManager, c = cf.createListBox('styleselect', {
     165                title : 'advanced.style_select',
     166                onselect : function(v) {
     167                    if (c.selectedValue === v) {
     168                        ed.execCommand('mceSetStyleInfo', 0, {command : 'removeformat'});
     169                        c.select();
     170                        return false;
     171                    } else
     172                        ed.execCommand('mceSetCSSClass', 0, v);
     173                }
     174            });
     175
     176            each((t.settings.theme_advanced_styles || '').split(';'), function(v) {
     177                var p = v.split('=');
     178
     179                if (v)
     180                    c.add(t.editor.translate(p[0]), p[1]);
     181            });
     182
     183            c.onPostRender.add(function(ed, n) {
     184                Event.add(n, 'focus', t._importClasses, t);
     185                Event.add(n, 'mousedown', t._importClasses, t);
     186            });
     187
     188            return c;
     189        },
     190
     191        _createFontSelect : function() {
     192            var c, t = this;
     193
     194            c = t.editor.controlManager.createListBox('fontselect', {title : 'advanced.fontdefault', cmd : 'FontName'});
     195
     196            each(t.settings.theme_advanced_fonts.split(';'), function(v) {
     197                var p = v.split('='), st;
     198
     199                if (p[1].indexOf('dings') == -1)
     200                    st = 'font-family:' + p[1];
     201
     202                c.add(t.editor.translate(p[0]), p[1], {style : st});
     203            });
     204
     205            return c;
     206        },
     207
     208        _createFontSizeSelect : function() {
     209            var c, t = this, lo = [
     210                "1 (8 pt)",
     211                "2 (10 pt)",
     212                "3 (12 pt)",
     213                "4 (14 pt)",
     214                "5 (18 pt)",
     215                "6 (24 pt)",
     216                "7 (36 pt)"
     217            ], fz = [8, 10, 12, 14, 18, 24, 36];
     218
     219            c = t.editor.controlManager.createListBox('fontsizeselect', {title : 'advanced.font_size', cmd : 'FontSize'});
     220
     221            each(t.settings.theme_advanced_font_sizes.split(','), function(v) {
     222                c.add(lo[parseInt(v) - 1], v, {'style' : 'font-size:' + fz[v - 1] + 'pt', 'class' : 'fontSize' + v});
     223            });
     224
     225            return c;
     226        },
     227
     228        _createBlockFormats : function() {
     229            var c, fmts = {
     230                p : 'advanced.paragraph',
     231                address : 'advanced.address',
     232                pre : 'advanced.pre',
     233                h1 : 'advanced.h1',
     234                h2 : 'advanced.h2',
     235                h3 : 'advanced.h3',
     236                h4 : 'advanced.h4',
     237                h5 : 'advanced.h5',
     238                h6 : 'advanced.h6',
     239                div : 'advanced.div',
     240                blockquote : 'advanced.blockquote',
     241                code : 'advanced.code',
     242                dt : 'advanced.dt',
     243                dd : 'advanced.dd',
     244                samp : 'advanced.samp'
     245            }, t = this;
     246
     247            c = t.editor.controlManager.createListBox('formatselect', {title : 'advanced.block', cmd : 'FormatBlock'});
     248
     249            each(t.settings.theme_advanced_blockformats.split(','), function(v) {
     250                c.add(t.editor.translate(fmts[v]), v, {element : v, 'class' : v.indexOf('h') == 0 ? '' : 'preview'});
     251            });
     252
     253            return c;
     254        },
     255
     256        _createForeColorMenu : function() {
     257            var c, t = this, s = t.settings, o = {}, v;
     258
     259            if (s.theme_advanced_more_colors) {
     260                o.more_colors_func = function() {
     261                    t._mceColorPicker(0, {
     262                        color : c.value,
     263                        func : function(co) {
     264                            c.setColor(co);
     265                        }
     266                    });
     267                };
     268            }
     269
     270            if (v = s.theme_advanced_text_colors)
     271                o.colors = v;
     272
     273            o.title = 'advanced.forecolor_desc';
     274            o.cmd = 'ForeColor';
     275            o.scope = this;
     276
     277            c = t.editor.controlManager.createColorSplitButton('forecolor', o);
     278
     279            return c;
     280        },
     281
     282        _createBackColorMenu : function() {
     283            var c, t = this, s = t.settings, o = {}, v;
     284
     285            if (s.theme_advanced_more_colors) {
     286                o.more_colors_func = function() {
     287                    t._mceColorPicker(0, {
     288                        color : c.value,
     289                        func : function(co) {
     290                            c.setColor(co);
     291                        }
     292                    });
     293                };
     294            }
     295
     296            if (v = s.theme_advanced_background_colors)
     297                o.colors = v;
     298
     299            o.title = 'advanced.backcolor_desc';
     300            o.cmd = 'HiliteColor';
     301            o.scope = this;
     302
     303            c = t.editor.controlManager.createColorSplitButton('backcolor', o);
     304
     305            return c;
     306        },
     307
     308        renderUI : function(o) {
     309            var n, ic, tb, t = this, ed = t.editor, s = t.settings, sc, p, nl;
     310
     311            n = p = DOM.create('div', {id : ed.id + '_parent', 'class' : 'mceEditor ' + ed.settings.skin + 'Skin'});
     312
     313            if (!DOM.boxModel)
     314                n = DOM.add(n, 'div', {'class' : 'mceOldBoxModel'});
     315
     316            n = sc = DOM.add(n, 'table', {id : ed.id + '_tbl', 'class' : 'mceLayout', cellSpacing : 0, cellPadding : 0});
     317            n = tb = DOM.add(n, 'tbody');
     318
     319            switch ((s.theme_advanced_layout_manager || '').toLowerCase()) {
     320                case "rowlayout":
     321                    ic = t._rowLayout(s, tb, o);
     322                    break;
     323
     324                case "customlayout":
     325                    ic = ed.execCallback("theme_advanced_custom_layout", s, tb, o, p);
     326                    break;
     327
     328                default:
     329                    ic = t._simpleLayout(s, tb, o, p);
     330            }
     331
     332            n = o.targetNode;
     333
     334            // Add classes to first and last TRs
     335            nl = sc.rows;
     336            DOM.addClass(nl[0], 'first');
     337            DOM.addClass(nl[nl.length - 1], 'last');
     338
     339            // Add classes to first and last TDs
     340            each(DOM.select('tr', tb), function(n) {
     341                DOM.addClass(n.firstChild, 'first');
     342                DOM.addClass(n.childNodes[n.childNodes.length - 1], 'last');
     343            });
     344
     345            if (DOM.get(s.theme_advanced_toolbar_container))
     346                DOM.get(s.theme_advanced_toolbar_container).appendChild(p);
     347            else
     348                DOM.insertAfter(p, n);
     349
     350            Event.add(ed.id + '_path_row', 'click', function(e) {
     351                e = e.target;
     352
     353                if (e.nodeName == 'A') {
     354                    t._sel(e.href.replace(/^[^#]*#/, ''));
     355
     356                    return Event.cancel(e);
     357                }
     358            });
     359/*
     360            if (DOM.get(ed.id + '_path_row')) {
     361                Event.add(ed.id + '_tbl', 'mouseover', function(e) {
     362                    var re;
     363   
     364                    e = e.target;
     365
     366                    if (e.nodeName == 'SPAN' && DOM.hasClass(e.parentNode, 'mceButton')) {
     367                        re = DOM.get(ed.id + '_path_row');
     368                        t.lastPath = re.innerHTML;
     369                        DOM.setHTML(re, e.parentNode.title);
    104370                    }
     371                });
     372
     373                Event.add(ed.id + '_tbl', 'mouseout', function(e) {
     374                    if (t.lastPath) {
     375                        DOM.setHTML(ed.id + '_path_row', t.lastPath);
     376                        t.lastPath = 0;
     377                    }
     378                });
     379            }
     380*/
     381            if (s.theme_advanced_toolbar_location == 'external')
     382                o.deltaHeight = 0;
     383
     384            t.deltaHeight = o.deltaHeight;
     385            o.targetNode = null;
     386
     387            return {
     388                iframeContainer : ic,
     389                editorContainer : ed.id + '_parent',
     390                sizeContainer : sc,
     391                deltaHeight : o.deltaHeight
     392            };
     393        },
     394
     395        getInfo : function() {
     396            return {
     397                longname : 'Simple theme',
     398                author : 'Moxiecode Systems AB',
     399                authorurl : 'http://tinymce.moxiecode.com',
     400                version : tinymce.majorVersion + "." + tinymce.minorVersion
     401            }
     402        },
     403
     404        _simpleLayout : function(s, tb, o, p) {
     405            var t = this, ed = t.editor, lo = s.theme_advanced_toolbar_location, sl = s.theme_advanced_statusbar_location, n, ic, etb, c;
     406
     407            // Create toolbar container at top
     408            if (lo == 'top')
     409                t._addToolbars(tb, o);
     410
     411            // Create external toolbar
     412            if (lo == 'external') {
     413                n = c = DOM.create('div', {style : 'position:relative'});
     414                n = DOM.add(n, 'div', {id : ed.id + '_external', 'class' : 'mceExternalToolbar'});
     415                DOM.add(n, 'a', {id : ed.id + '_external_close', href : 'javascript:;', 'class' : 'mceExternalClose'});
     416                n = DOM.add(n, 'table', {id : ed.id + '_tblext', cellSpacing : 0, cellPadding : 0});
     417                etb = DOM.add(n, 'tbody');
     418
     419                if (p.firstChild.className == 'mceOldBoxModel')
     420                    p.firstChild.appendChild(c);
     421                else
     422                    p.insertBefore(c, p.firstChild);
     423
     424                t._addToolbars(etb, o);
     425
     426                ed.onMouseUp.add(function() {
     427                    var e = DOM.get(ed.id + '_external');
     428                    DOM.show(e);
     429
     430                    DOM.hide(lastExtID);
     431
     432                    var f = Event.add(ed.id + '_external_close', 'click', function() {
     433                        DOM.hide(ed.id + '_external');
     434                        Event.remove(ed.id + '_external_close', 'click', f);
     435                    });
     436
     437                    DOM.show(e);
     438                    DOM.setStyle(e, 'top', 0 - DOM.getRect(ed.id + '_tblext').h - 1);
     439
     440                    // Fixes IE rendering bug
     441                    DOM.hide(e);
     442                    DOM.show(e);
     443                    e.style.filter = '';
     444
     445                    lastExtID = ed.id + '_external';
     446
     447                    e = null;
     448                });
     449            }
     450
     451            if (sl == 'top')
     452                t._addStatusBar(tb, o);
     453
     454            // Create iframe container
     455            if (!s.theme_advanced_toolbar_container) {
     456                n = DOM.add(tb, 'tr');
     457                n = ic = DOM.add(n, 'td', {'class' : 'mceIframeContainer'});
     458            }
     459
     460            // Create toolbar container at bottom
     461            if (lo == 'bottom')
     462                t._addToolbars(tb, o);
     463
     464            if (sl == 'bottom')
     465                t._addStatusBar(tb, o);
     466
     467            return ic;
     468        },
     469
     470        _rowLayout : function(s, tb, o) {
     471            var t = this, ed = t.editor, dc, da, cf = ed.controlManager, n, ic, to;
     472
     473            dc = s.theme_advanced_containers_default_class || '';
     474            da = s.theme_advanced_containers_default_align || 'center';
     475
     476            each((s.theme_advanced_containers || '').split(','), function(c, i) {
     477                var v = s['theme_advanced_container_' + c].toLowerCase();
     478
     479                switch (v) {
     480                    case 'mceeditor':
     481                        n = DOM.add(tb, 'tr');
     482                        n = ic = DOM.add(n, 'td', {'class' : 'mceIframeContainer'});
     483                        break;
     484
     485                    case 'mceelementpath':
     486                        t._addStatusBar(tb, o);
     487                        break;
     488
     489                    default:
     490                        n = DOM.add(DOM.add(tb, 'tr'), 'td', {
     491                            'class' : 'mceToolbar ' + (s['theme_advanced_container_' + c + '_class'] || dc),
     492                            align : s['theme_advanced_container_' + c + '_align'] || da
     493                        });
     494
     495                        to = cf.createToolbar("toolbar" + i);
     496                        t._addControls(v, to);
     497                        DOM.setHTML(n, to.renderHTML());
     498                        o.deltaHeight -= s.theme_advanced_row_height;
    105499                }
    106 
    107                 html += '</select>';
    108 
    109                 return html;
    110 
    111             case "styleselect":
    112                 return '<select id="{$editor_id}_styleSelect" onmousedown="tinyMCE.themes.advanced._setupCSSClasses(\'{$editor_id}\');" name="{$editor_id}_styleSelect" onfocus="tinyMCE.addSelectAccessibility(event,this,window);" onchange="tinyMCE.execInstanceCommand(\'{$editor_id}\',\'mceSetCSSClass\',false,this.options[this.selectedIndex].value);" class="mceSelectList">{$style_select_options}</select>';
    113 
    114             case "fontselect":
    115                 var fontHTML = '<select id="{$editor_id}_fontNameSelect" name="{$editor_id}_fontNameSelect" onfocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="tinyMCE.execInstanceCommand(\'{$editor_id}\',\'FontName\',false,this.options[this.selectedIndex].value);" class="mceSelectList"><option value="">{$lang_theme_fontdefault}</option>';
    116                 var iFonts = 'Arial=arial,helvetica,sans-serif;Courier New=courier new,courier,monospace;Georgia=georgia,times new roman,times,serif;Tahoma=tahoma,arial,helvetica,sans-serif;Times New Roman=times new roman,times,serif;Verdana=verdana,arial,helvetica,sans-serif;Impact=impact;WingDings=wingdings';
    117                 var nFonts = '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,sand;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';
    118                 var fonts = tinyMCE.getParam("theme_advanced_fonts", nFonts).split(';');
    119                 for (i=0; i<fonts.length; i++) {
    120                     if (fonts[i] != '') {
    121                         var parts = fonts[i].split('=');
    122                         fontHTML += '<option value="' + parts[1] + '">' + parts[0] + '</option>';
     500            });
     501
     502            return ic;
     503        },
     504
     505        _addControls : function(v, tb) {
     506            var t = this, s = t.settings, di, cf = t.editor.controlManager;
     507
     508            if (s.theme_advanced_disable && !t._disabled) {
     509                di = {};
     510
     511                each(s.theme_advanced_disable.split(','), function(v) {
     512                    di[v] = 1;
     513                });
     514
     515                t._disabled = di;
     516            } else
     517                di = t._disabled;
     518
     519            each(v.split(','), function(n) {
     520                var c;
     521
     522                if (di && di[n])
     523                    return;
     524
     525                // Compatiblity with 2.x
     526                if (n == 'tablecontrols') {
     527                    each(["table","|","row_props","cell_props","|","row_before","row_after","delete_row","|","col_before","col_after","delete_col","|","split_cells","merge_cells"], function(n) {
     528                        n = t.createControl(n, cf);
     529
     530                        if (n)
     531                            tb.add(n);
     532                    });
     533
     534                    return;
     535                }
     536
     537                c = t.createControl(n, cf);
     538
     539                if (c)
     540                    tb.add(c);
     541            });
     542        },
     543
     544        _addToolbars : function(c, o) {
     545            var t = this, i, tb, ed = t.editor, s = t.settings, v, cf = ed.controlManager, di, n, h = [];
     546
     547            n = DOM.add(DOM.add(c, 'tr'), 'td', {'class' : 'mceToolbar', align : s.theme_advanced_toolbar_align});
     548
     549            if (!ed.getParam('accessibility_focus') || ed.getParam('tab_focus'))
     550                h.push(DOM.createHTML('a', {href : '#', onfocus : 'tinyMCE.get(\'' + ed.id + '\').focus();'}, '<!-- IE -->'));
     551
     552            h.push(DOM.createHTML('a', {href : '#', accesskey : 'q', title : ed.getLang("advanced.toolbar_focus")}, '<!-- IE -->'));
     553
     554            // Create toolbar and add the controls
     555            for (i=1; (v = s['theme_advanced_buttons' + i]); i++) {
     556                tb = cf.createToolbar("toolbar" + i, {'class' : 'mceToolbarRow' + i});
     557
     558                if (s['theme_advanced_buttons' + i + '_add'])
     559                    v += ',' + s['theme_advanced_buttons' + i + '_add'];
     560
     561                if (s['theme_advanced_buttons' + i + '_add_before'])
     562                    v = s['theme_advanced_buttons' + i + '_add_before'] + ',' + v;
     563
     564                t._addControls(v, tb, di);
     565
     566                //n.appendChild(n = tb.render());
     567                h.push(tb.renderHTML());
     568
     569                o.deltaHeight -= s.theme_advanced_row_height;
     570            }
     571
     572            h.push(DOM.createHTML('a', {href : '#', accesskey : 'z', title : ed.getLang("advanced.toolbar_focus"), onfocus : 'tinyMCE.getInstanceById(\'' + ed.id + '\').focus();'}, '<!-- IE -->'));
     573            DOM.setHTML(n, h.join(''));
     574        },
     575
     576        _addStatusBar : function(tb, o) {
     577            var n, t = this, ed = t.editor, s = t.settings, r, mf, me, td;
     578
     579            n = DOM.add(tb, 'tr');
     580            n = td = DOM.add(n, 'td', {'class' : 'mceStatusbar'});
     581            n = DOM.add(n, 'div', {id : ed.id + '_path_row'}, s.theme_advanced_path ? ed.translate('advanced.path') + ': ' : '&nbsp;');
     582            DOM.add(n, 'a', {href : '#', accesskey : 'x'});
     583
     584            if (s.theme_advanced_resizing && !tinymce.isOldWebKit) {
     585                DOM.add(td, 'a', {id : ed.id + '_resize', href : 'javascript:;', onclick : "return false;", 'class' : 'resize'});
     586
     587                if (s.theme_advanced_resizing_use_cookie) {
     588                    ed.onPostRender.add(function() {
     589                        var o = Cookie.getHash("TinyMCE_" + ed.id + "_size"), c = DOM.get(ed.id + '_tbl');
     590
     591                        if (!o)
     592                            return;
     593
     594                        if (s.theme_advanced_resize_horizontal)
     595                            c.style.width = o.cw + 'px';
     596
     597                        c.style.height = o.ch + 'px';
     598                        DOM.get(ed.id + '_ifr').style.height = (parseInt(o.ch) + t.deltaHeight) + 'px';
     599                    });
     600                }
     601
     602                ed.onPostRender.add(function() {
     603                    Event.add(ed.id + '_resize', 'mousedown', function(e) {
     604                        var c, p, w, h, n, pa;
     605
     606                        // Measure container
     607                        c = DOM.get(ed.id + '_tbl');
     608                        w = c.clientWidth;
     609                        h = c.clientHeight;
     610
     611                        miw = s.theme_advanced_resizing_min_width || 100;
     612                        mih = s.theme_advanced_resizing_min_height || 100;
     613                        maw = s.theme_advanced_resizing_max_width || 0xFFFF;
     614                        mah = s.theme_advanced_resizing_max_height || 0xFFFF;
     615
     616                        // Setup placeholder
     617                        p = DOM.add(DOM.get(ed.id + '_parent'), 'div', {'class' : 'mcePlaceHolder'});
     618                        DOM.setStyles(p, {width : w, height : h});
     619
     620                        // Replace with placeholder
     621                        DOM.hide(c);
     622                        DOM.show(p);
     623
     624                        // Create internal resize obj
     625                        r = {
     626                            x : e.screenX,
     627                            y : e.screenY,
     628                            w : w,
     629                            h : h,
     630                            dx : null,
     631                            dy : null
     632                        };
     633
     634                        // Start listening
     635                        mf = Event.add(document, 'mousemove', function(e) {
     636                            var w, h;
     637
     638                            // Calc delta values
     639                            r.dx = e.screenX - r.x;
     640                            r.dy = e.screenY - r.y;
     641
     642                            // Boundery fix box
     643                            w = Math.max(miw, r.w + r.dx);
     644                            h = Math.max(mih, r.h + r.dy);
     645                            w = Math.min(maw, w);
     646                            h = Math.min(mah, h);
     647
     648                            // Resize placeholder
     649                            if (s.theme_advanced_resize_horizontal)
     650                                p.style.width = w + 'px';
     651
     652                            p.style.height = h + 'px';
     653
     654                            return Event.cancel(e);
     655                        });
     656
     657                        me = Event.add(document, 'mouseup', function(e) {
     658                            var ifr;
     659
     660                            // Stop listening
     661                            Event.remove(document, 'mousemove', mf);
     662                            Event.remove(document, 'mouseup', me);
     663
     664                            c.style.display = '';
     665                            DOM.remove(p);
     666
     667                            if (r.dx === null)
     668                                return;
     669
     670                            ifr = DOM.get(ed.id + '_ifr');
     671
     672                            if (s.theme_advanced_resize_horizontal)
     673                                c.style.width = (r.w + r.dx) + 'px';
     674
     675                            c.style.height = (r.h + r.dy) + 'px';
     676                            ifr.style.height = (ifr.clientHeight + r.dy) + 'px';
     677
     678                            if (s.theme_advanced_resizing_use_cookie) {
     679                                Cookie.setHash("TinyMCE_" + ed.id + "_size", {
     680                                    cw : r.w + r.dx,
     681                                    ch : r.h + r.dy
     682                                });
     683                            }
     684                        });
     685
     686                        return Event.cancel(e);
     687                    });
     688                });
     689            }
     690
     691            o.deltaHeight -= 21;
     692            n = tb = null;
     693        },
     694
     695        _nodeChanged : function(ed, cm, n, co) {
     696            var t = this, p, de = 0, v, c, s = t.settings;
     697
     698            tinymce.each(t.stateControls, function(c) {
     699                cm.setActive(c, ed.queryCommandState(t.controls[c][1]));
     700            });
     701
     702            cm.setActive('visualaid', ed.hasVisual);
     703            cm.setDisabled('undo', !ed.undoManager.hasUndo() && !ed.typing);
     704            cm.setDisabled('redo', !ed.undoManager.hasRedo());
     705            cm.setDisabled('outdent', !ed.queryCommandState('Outdent'));
     706
     707            p = DOM.getParent(n, 'A');
     708            if (c = cm.get('link')) {
     709                if (!p || !p.name) {
     710                    c.setDisabled(!p && co);
     711                    c.setActive(!!p);
     712                }
     713            }
     714
     715            if (c = cm.get('unlink')) {
     716                c.setDisabled(!p && co);
     717                c.setActive(!!p && !p.name);
     718            }
     719
     720            if (c = cm.get('anchor')) {
     721                c.setActive(!!p && p.name);
     722
     723                if (tinymce.isWebKit) {
     724                    p = DOM.getParent(n, 'IMG');
     725                    c.setActive(!!p && DOM.getAttrib(p, 'mce_name') == 'a');
     726                }
     727            }
     728
     729            p = DOM.getParent(n, 'IMG');
     730            if (c = cm.get('image'))
     731                c.setActive(!!p && n.className.indexOf('mceItem') == -1);
     732
     733            if (c = cm.get('styleselect')) {
     734                if (n.className) {
     735                    t._importClasses();
     736                    c.select(n.className);
     737                } else
     738                    c.select();
     739            }
     740
     741            if (c = cm.get('formatselect')) {
     742                p = DOM.getParent(n, DOM.isBlock);
     743
     744                if (p)
     745                    c.select(p.nodeName.toLowerCase());
     746            }
     747
     748            if (c = cm.get('fontselect'))
     749                c.select(ed.queryCommandValue('FontName'));
     750
     751            if (c = cm.get('fontsizeselect'))
     752                c.select(ed.queryCommandValue('FontSize'));
     753
     754            if (s.theme_advanced_path && s.theme_advanced_statusbar_location) {
     755                p = DOM.get(ed.id + '_path') || DOM.add(ed.id + '_path_row', 'span', {id : ed.id + '_path'});
     756                DOM.setHTML(p, '');
     757
     758                ed.dom.getParent(n, function(n) {
     759                    var na = n.nodeName.toLowerCase(), u, pi, ti = '';
     760
     761                    // Ignore non element and hidden elements
     762                    if (n.nodeType != 1 || (DOM.hasClass(n, 'mceItemHidden') || DOM.hasClass(n, 'mceItemRemoved')))
     763                        return;
     764
     765                    // Fake name
     766                    if (v = DOM.getAttrib(n, 'mce_name'))
     767                        na = v;
     768   
     769                    // Handle prefix
     770                    if (tinymce.isIE && n.scopeName !== 'HTML')
     771                        na = n.scopeName + ':' + na;
     772
     773                    // Remove internal prefix
     774                    na = na.replace(/mce\:/g, '');
     775
     776                    // Handle node name
     777                    switch (na) {
     778                        case 'b':
     779                            na = 'strong';
     780                            break;
     781
     782                        case 'i':
     783                            na = 'em';
     784                            break;
     785
     786                        case 'img':
     787                            if (v = DOM.getAttrib(n, 'src'))
     788                                ti += 'src: ' + v + ' ';
     789
     790                            break;
     791
     792                        case 'a':
     793                            if (v = DOM.getAttrib(n, 'name')) {
     794                                ti += 'name: ' + v + ' ';
     795                                na += '#' + v;
     796                            }
     797
     798                            if (v = DOM.getAttrib(n, 'href'))
     799                                ti += 'href: ' + v + ' ';
     800
     801                            break;
     802
     803                        case 'font':
     804                            if (s.convert_fonts_to_spans)
     805                                na = 'span';
     806
     807                            if (v = DOM.getAttrib(n, 'face'))
     808                                ti += 'font: ' + v + ' ';
     809
     810                            if (v = DOM.getAttrib(n, 'size'))
     811                                ti += 'size: ' + v + ' ';
     812
     813                            if (v = DOM.getAttrib(n, 'color'))
     814                                ti += 'color: ' + v + ' ';
     815
     816                            break;
     817
     818                        case 'span':
     819                            if (v = DOM.getAttrib(n, 'style'))
     820                                ti += 'style: ' + v + ' ';
     821
     822                            break;
    123823                    }
    124                 }
    125 
    126                 fontHTML += '</select>';
    127                 return fontHTML;
    128 
    129             case "fontsizeselect":
    130                 return '<select id="{$editor_id}_fontSizeSelect" name="{$editor_id}_fontSizeSelect" onfocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="tinyMCE.execInstanceCommand(\'{$editor_id}\',\'FontSize\',false,this.options[this.selectedIndex].value);" class="mceSelectList">'+
    131                         '<option value="0">{$lang_theme_font_size}</option>'+
    132                         '<option value="1">1 (8 pt)</option>'+
    133                         '<option value="2">2 (10 pt)</option>'+
    134                         '<option value="3">3 (12 pt)</option>'+
    135                         '<option value="4">4 (14 pt)</option>'+
    136                         '<option value="5">5 (18 pt)</option>'+
    137                         '<option value="6">6 (24 pt)</option>'+
    138                         '<option value="7">7 (36 pt)</option>'+
    139                         '</select>';
    140 
    141             case "|":
    142             case "separator":
    143                 return '<img src="{$themeurl}/images/separator.gif" width="2" height="20" class="mceSeparatorLine" alt="" />';
    144 
    145             case "spacer":
    146                 return '<img src="{$themeurl}/images/separator.gif" width="2" height="15" border="0" class="mceSeparatorLine" style="vertical-align: middle" alt="" />';
    147 
    148             case "rowseparator":
    149                 return '<br />';
    150         }
    151 
    152         return "";
    153     },
    154 
    155     /**
    156      * Theme specific execcommand handling.
    157      */
    158     execCommand : function(editor_id, element, command, user_interface, value) {
    159         switch (command) {
    160             case 'mceHelp':
    161                 tinyMCE.openWindow({
    162                     file : 'about.htm',
    163                     width : 480,
    164                     height : 380
    165                 }, {
    166                     tinymce_version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion,
    167                     tinymce_releasedate : tinyMCE.releaseDate,
    168                     inline : "yes"
    169                 });
    170             return true;
    171 
    172             case "mceLink":
    173                 var inst = tinyMCE.getInstanceById(editor_id);
    174                 var doc = inst.getDoc();
    175                 var selectedText = "";
    176 
    177                 if (tinyMCE.isMSIE) {
    178                     var rng = doc.selection.createRange();
    179                     selectedText = rng.text;
    180                 } else
    181                     selectedText = inst.getSel().toString();
    182 
    183                 if (!tinyMCE.linkElement) {
    184                     if ((tinyMCE.selectedElement.nodeName.toLowerCase() != "img") && (selectedText.length <= 0))
    185                         return true;
    186                 }
    187 
    188                 var href = "", target = "", title = "", onclick = "", action = "insert", style_class = "";
    189 
    190                 if (tinyMCE.selectedElement.nodeName.toLowerCase() == "a")
    191                     tinyMCE.linkElement = tinyMCE.selectedElement;
    192 
    193                 // Is anchor not a link
    194                 if (tinyMCE.linkElement != null && tinyMCE.getAttrib(tinyMCE.linkElement, 'href') == "")
    195                     tinyMCE.linkElement = null;
    196 
    197                 if (tinyMCE.linkElement) {
    198                     href = tinyMCE.getAttrib(tinyMCE.linkElement, 'href');
    199                     target = tinyMCE.getAttrib(tinyMCE.linkElement, 'target');
    200                     title = tinyMCE.getAttrib(tinyMCE.linkElement, 'title');
    201                     onclick = tinyMCE.getAttrib(tinyMCE.linkElement, 'onclick');
    202                     style_class = tinyMCE.getAttrib(tinyMCE.linkElement, 'class');
    203 
    204                     // Try old onclick to if copy/pasted content
    205                     if (onclick == "")
    206                         onclick = tinyMCE.getAttrib(tinyMCE.linkElement, 'onclick');
    207 
    208                     onclick = tinyMCE.cleanupEventStr(onclick);
    209 
    210                     href = eval(tinyMCE.settings['urlconverter_callback'] + "(href, tinyMCE.linkElement, true);");
    211 
    212                     // Use mce_href if defined
    213                     mceRealHref = tinyMCE.getAttrib(tinyMCE.linkElement, 'mce_href');
    214                     if (mceRealHref != "") {
    215                         href = mceRealHref;
    216 
    217                         if (tinyMCE.getParam('convert_urls'))
    218                             href = eval(tinyMCE.settings['urlconverter_callback'] + "(href, tinyMCE.linkElement, true);");
    219                     }
    220 
    221                     action = "update";
    222                 }
    223 
    224                 var template = new Array();
    225 
    226                 template['file'] = 'link.htm';
    227                 template['width'] = 310;
    228                 template['height'] = 200;
    229 
    230                 // Language specific width and height addons
    231                 template['width'] += tinyMCE.getLang('lang_insert_link_delta_width', 0);
    232                 template['height'] += tinyMCE.getLang('lang_insert_link_delta_height', 0);
    233 
    234                 if (inst.settings['insertlink_callback']) {
    235                     var returnVal = eval(inst.settings['insertlink_callback'] + "(href, target, title, onclick, action, style_class);");
    236                     if (returnVal && returnVal['href'])
    237                         TinyMCE_AdvancedTheme._insertLink(returnVal['href'], returnVal['target'], returnVal['title'], returnVal['onclick'], returnVal['style_class']);
    238                 } else {
    239                     tinyMCE.openWindow(template, {href : href, target : target, title : title, onclick : onclick, action : action, className : style_class, inline : "yes"});
    240                 }
    241 
    242                 return true;
    243 
    244             case "mceImage":
    245                 var src = "", alt = "", border = "", hspace = "", vspace = "", width = "", height = "", align = "";
    246                 var title = "", onmouseover = "", onmouseout = "", action = "insert";
    247                 var img = tinyMCE.imgElement;
    248                 var inst = tinyMCE.getInstanceById(editor_id);
    249 
    250                 if (tinyMCE.selectedElement != null && tinyMCE.selectedElement.nodeName.toLowerCase() == "img") {
    251                     img = tinyMCE.selectedElement;
    252                     tinyMCE.imgElement = img;
    253                 }
    254 
    255                 if (img) {
    256                     // Is it a internal MCE visual aid image, then skip this one.
    257                     if (tinyMCE.getAttrib(img, 'name').indexOf('mce_') == 0)
    258                         return true;
    259 
    260                     src = tinyMCE.getAttrib(img, 'src');
    261                     alt = tinyMCE.getAttrib(img, 'alt');
    262 
    263                     // Try polling out the title
    264                     if (alt == "")
    265                         alt = tinyMCE.getAttrib(img, 'title');
    266 
    267                     // Fix width/height attributes if the styles is specified
    268                     if (tinyMCE.isGecko) {
    269                         var w = img.style.width;
    270                         if (w != null && w != "")
    271                             img.setAttribute("width", w);
    272 
    273                         var h = img.style.height;
    274                         if (h != null && h != "")
    275                             img.setAttribute("height", h);
    276                     }
    277 
    278                     border = tinyMCE.getAttrib(img, 'border');
    279                     hspace = tinyMCE.getAttrib(img, 'hspace');
    280                     vspace = tinyMCE.getAttrib(img, 'vspace');
    281                     width = tinyMCE.getAttrib(img, 'width');
    282                     height = tinyMCE.getAttrib(img, 'height');
    283                     align = tinyMCE.getAttrib(img, 'align');
    284                     onmouseover = tinyMCE.getAttrib(img, 'onmouseover');
    285                     onmouseout = tinyMCE.getAttrib(img, 'onmouseout');
    286                     title = tinyMCE.getAttrib(img, 'title');
    287 
    288                     // Is realy specified?
    289                     if (tinyMCE.isMSIE) {
    290                         width = img.attributes['width'].specified ? width : "";
    291                         height = img.attributes['height'].specified ? height : "";
    292                     }
    293 
    294                     //onmouseover = tinyMCE.getImageSrc(tinyMCE.cleanupEventStr(onmouseover));
    295                     //onmouseout = tinyMCE.getImageSrc(tinyMCE.cleanupEventStr(onmouseout));
    296 
    297                     src = eval(tinyMCE.settings['urlconverter_callback'] + "(src, img, true);");
    298 
    299                     // Use mce_src if defined
    300                     mceRealSrc = tinyMCE.getAttrib(img, 'mce_src');
    301                     if (mceRealSrc != "") {
    302                         src = mceRealSrc;
    303 
    304                         if (tinyMCE.getParam('convert_urls'))
    305                             src = eval(tinyMCE.settings['urlconverter_callback'] + "(src, img, true);");
    306                     }
    307 
    308                     //if (onmouseover != "")
    309                     //  onmouseover = eval(tinyMCE.settings['urlconverter_callback'] + "(onmouseover, img, true);");
    310 
    311                     //if (onmouseout != "")
    312                     //  onmouseout = eval(tinyMCE.settings['urlconverter_callback'] + "(onmouseout, img, true);");
    313 
    314                     action = "update";
    315                 }
    316 
    317                 var template = new Array();
    318 
    319                 template['file'] = 'image.htm?src={$src}';
    320                 template['width'] = 355;
    321                 template['height'] = 265 + (tinyMCE.isMSIE ? 25 : 0);
    322 
    323                 // Language specific width and height addons
    324                 template['width'] += tinyMCE.getLang('lang_insert_image_delta_width', 0);
    325                 template['height'] += tinyMCE.getLang('lang_insert_image_delta_height', 0);
    326 
    327                 if (inst.settings['insertimage_callback']) {
    328                     var returnVal = eval(inst.settings['insertimage_callback'] + "(src, alt, border, hspace, vspace, width, height, align, title, onmouseover, onmouseout, action);");
    329                     if (returnVal && returnVal['src'])
    330                         TinyMCE_AdvancedTheme._insertImage(returnVal['src'], returnVal['alt'], returnVal['border'], returnVal['hspace'], returnVal['vspace'], returnVal['width'], returnVal['height'], returnVal['align'], returnVal['title'], returnVal['onmouseover'], returnVal['onmouseout']);
    331                 } else
    332                     tinyMCE.openWindow(template, {src : src, alt : alt, border : border, hspace : hspace, vspace : vspace, width : width, height : height, align : align, title : title, onmouseover : onmouseover, onmouseout : onmouseout, action : action, inline : "yes"});
    333 
    334                 return true;
    335 
    336             case "forecolor":
    337                 var fcp = new TinyMCE_Layer(editor_id + '_fcPreview', false), p, img, elm;
    338 
    339                 TinyMCE_AdvancedTheme._hideMenus(editor_id);
    340 
    341                 if (!fcp.exists()) {
    342                     fcp.create('div', 'mceColorPreview', document.getElementById(editor_id + '_toolbar'));
    343                     elm = fcp.getElement();
    344                     elm._editor_id = editor_id;
    345                     elm._command = "forecolor";
    346                     elm._switchId = editor_id + "_forecolor";
    347                     tinyMCE.addEvent(elm, 'click', TinyMCE_AdvancedTheme._handleMenuEvent);
    348                     tinyMCE.addEvent(elm, 'mouseover', TinyMCE_AdvancedTheme._handleMenuEvent);
    349                     tinyMCE.addEvent(elm, 'mouseout', TinyMCE_AdvancedTheme._handleMenuEvent);
    350                 }
    351 
    352                 img = tinyMCE.selectNodes(document.getElementById(editor_id + "_forecolor"), function(n) {return n.nodeName == "IMG";})[0];
    353                 p = tinyMCE.getAbsPosition(img, document.getElementById(editor_id + '_toolbar'));
    354 
    355                 fcp.moveTo(p.absLeft, p.absTop);
    356                 fcp.getElement().style.backgroundColor = value != null ? value : tinyMCE.getInstanceById(editor_id).foreColor;
    357                 fcp.show();
    358 
    359                 return false;
    360 
    361             case "forecolorpicker":
    362                 this._pickColor(editor_id, 'forecolor');
    363                 return true;
    364 
    365             case "forecolorMenu":
    366                 TinyMCE_AdvancedTheme._hideMenus(editor_id);
    367 
    368                 // Create color layer
    369                 var ml = new TinyMCE_Layer(editor_id + '_fcMenu');
    370 
    371                 if (!ml.exists())
    372                     ml.create('div', 'mceMenu', document.body, TinyMCE_AdvancedTheme._getColorHTML(editor_id, 'theme_advanced_text_colors', 'forecolor'));
    373 
    374                 tinyMCE.switchClass(editor_id + '_forecolor', 'mceMenuButtonFocus');
    375                 ml.moveRelativeTo(document.getElementById(editor_id + "_forecolor"), 'bl');
    376 
    377                 ml.moveBy(tinyMCE.isMSIE && !tinyMCE.isOpera ? -1 : 1, -1);
    378 
    379                 if (tinyMCE.isOpera)
    380                     ml.moveBy(0, -2);
    381 
    382                 ml.show();
    383             return true;
    384 
    385             case "HiliteColor":
    386                 var bcp = new TinyMCE_Layer(editor_id + '_bcPreview', false), p, img;
    387 
    388                 TinyMCE_AdvancedTheme._hideMenus(editor_id);
    389 
    390                 if (!bcp.exists()) {
    391                     bcp.create('div', 'mceColorPreview', document.getElementById(editor_id + '_toolbar'));
    392                     elm = bcp.getElement();
    393                     elm._editor_id = editor_id;
    394                     elm._command = "HiliteColor";
    395                     elm._switchId = editor_id + "_backcolor";
    396                     tinyMCE.addEvent(elm, 'click', TinyMCE_AdvancedTheme._handleMenuEvent);
    397                     tinyMCE.addEvent(elm, 'mouseover', TinyMCE_AdvancedTheme._handleMenuEvent);
    398                     tinyMCE.addEvent(elm, 'mouseout', TinyMCE_AdvancedTheme._handleMenuEvent);
    399                 }
    400 
    401                 img = tinyMCE.selectNodes(document.getElementById(editor_id + "_backcolor"), function(n) {return n.nodeName == "IMG";})[0];
    402                 p = tinyMCE.getAbsPosition(img, document.getElementById(editor_id + '_toolbar'));
    403 
    404                 bcp.moveTo(p.absLeft, p.absTop);
    405                 bcp.getElement().style.backgroundColor = value != null ? value : tinyMCE.getInstanceById(editor_id).backColor;
    406                 bcp.show();
    407 
    408                 return false;
    409 
    410             case "HiliteColorMenu":
    411                 TinyMCE_AdvancedTheme._hideMenus(editor_id);
    412 
    413                 // Create color layer
    414                 var ml = new TinyMCE_Layer(editor_id + '_bcMenu');
    415 
    416                 if (!ml.exists())
    417                     ml.create('div', 'mceMenu', document.body, TinyMCE_AdvancedTheme._getColorHTML(editor_id, 'theme_advanced_background_colors', 'HiliteColor'));
    418 
    419                 tinyMCE.switchClass(editor_id + '_backcolor', 'mceMenuButtonFocus');
    420                 ml.moveRelativeTo(document.getElementById(editor_id + "_backcolor"), 'bl');
    421 
    422                 ml.moveBy(tinyMCE.isMSIE && !tinyMCE.isOpera ? -1 : 1, -1);
    423 
    424                 if (tinyMCE.isOpera)
    425                     ml.moveBy(0, -2);
    426 
    427                 ml.show();
    428             return true;
    429    
    430             case "backcolorpicker":
    431                 this._pickColor(editor_id, 'HiliteColor');
    432                 return true;
    433 
    434             case "mceColorPicker":
    435                 if (user_interface) {
    436                     var template = [];
    437    
    438                     if (!value['callback'] && !value['color'])
    439                         value['color'] = value['document'].getElementById(value['element_id']).value;
    440 
    441                     template['file'] = 'color_picker.htm';
    442                     template['width'] = 380;
    443                     template['height'] = 250;
    444                     template['close_previous'] = "no";
    445 
    446                     template['width'] += tinyMCE.getLang('lang_theme_advanced_colorpicker_delta_width', 0);
    447                     template['height'] += tinyMCE.getLang('lang_theme_advanced_colorpicker_delta_height', 0);
    448 
    449                     if (typeof(value['store_selection']) == "undefined")
    450                         value['store_selection'] = true;
    451 
    452                     tinyMCE.lastColorPickerValue = value;
    453                     tinyMCE.openWindow(template, {editor_id : editor_id, mce_store_selection : value['store_selection'], inline : "yes", command : "mceColorPicker", input_color : value['color']});
    454                 } else {
    455                     var savedVal = tinyMCE.lastColorPickerValue, elm;
    456 
    457                     if (savedVal['callback']) {
    458                         savedVal['callback'](value);
    459                         return true;
    460                     }
    461 
    462                     elm = savedVal['document'].getElementById(savedVal['element_id']);
    463                     elm.value = value;
    464 
    465                     if (elm.onchange != null && elm.onchange != '')
    466                         eval('elm.onchange();');
    467                 }
    468             return true;
    469 
    470             case "mceCodeEditor":
    471                 var template = new Array();
    472 
    473                 template['file'] = 'source_editor.htm';
    474                 template['width'] = parseInt(tinyMCE.getParam("theme_advanced_source_editor_width", 720));
    475                 template['height'] = parseInt(tinyMCE.getParam("theme_advanced_source_editor_height", 580));
    476 
    477                 tinyMCE.openWindow(template, {editor_id : editor_id, resizable : "yes", scrollbars : "no", inline : "yes"});
    478                 return true;
    479 
    480             case "mceCharMap":
    481                 var template = new Array();
    482 
    483                 template['file'] = 'charmap.htm';
    484                 template['width'] = 550 + (tinyMCE.isOpera ? 40 : 0);
    485                 template['height'] = 250;
    486 
    487                 template['width'] += tinyMCE.getLang('lang_theme_advanced_charmap_delta_width', 0);
    488                 template['height'] += tinyMCE.getLang('lang_theme_advanced_charmap_delta_height', 0);
    489 
    490                 tinyMCE.openWindow(template, {editor_id : editor_id, inline : "yes"});
    491                 return true;
    492 
    493             case "mceInsertAnchor":
    494                 var template = new Array();
    495 
    496                 template['file'] = 'anchor.htm';
    497                 template['width'] = 320;
    498                 template['height'] = 90 + (tinyMCE.isNS7 ? 30 : 0);
    499 
    500                 template['width'] += tinyMCE.getLang('lang_theme_advanced_anchor_delta_width', 0);
    501                 template['height'] += tinyMCE.getLang('lang_theme_advanced_anchor_delta_height', 0);
    502 
    503                 tinyMCE.openWindow(template, {editor_id : editor_id, inline : "yes"});
    504                 return true;
    505 
    506             case "mceNewDocument":
    507                 if (confirm(tinyMCE.getLang('lang_newdocument')))
    508                     tinyMCE.execInstanceCommand(editor_id, 'mceSetContent', false, ' ');
    509 
    510                 return true;
    511         }
    512 
    513         return false;
    514     },
    515 
    516     /**
    517      * Editor instance template function.
    518      */
    519     getEditorTemplate : function(settings, editorId) {
    520         function removeFromArray(in_array, remove_array) {
    521             var outArray = new Array(), skip;
    522            
    523             for (var i=0; i<in_array.length; i++) {
    524                 skip = false;
    525 
    526                 for (var j=0; j<remove_array.length; j++) {
    527                     if (in_array[i] == remove_array[j]) {
    528                         skip = true;
    529                     }
    530                 }
    531 
    532                 if (!skip) {
    533                     outArray[outArray.length] = in_array[i];
    534                 }
    535             }
    536 
    537             return outArray;
    538         }
    539 
    540         function addToArray(in_array, add_array) {
    541             for (var i=0; i<add_array.length; i++) {
    542                 in_array[in_array.length] = add_array[i];
    543             }
    544 
    545             return in_array;
    546         }
    547 
    548         var template = new Array();
    549         var deltaHeight = 0;
    550         var resizing = tinyMCE.getParam("theme_advanced_resizing", false);
    551         var path = tinyMCE.getParam("theme_advanced_path", true);
    552         var statusbarHTML = '<div id="{$editor_id}_path" class="mceStatusbarPathText" style="display: ' + (path ? "block" : "none") + '">&#160;</div><div id="{$editor_id}_resize" class="mceStatusbarResize" style="display: ' + (resizing ? "block" : "none") + '" onmousedown="tinyMCE.themes.advanced._setResizing(event,\'{$editor_id}\',true);"></div><br style="clear: both" />';
    553         var layoutManager = tinyMCE.getParam("theme_advanced_layout_manager", "SimpleLayout");
    554 
    555         // Setup style select options -- MOVED UP FOR EXTERNAL TOOLBAR COMPATABILITY!
    556         var styleSelectHTML = '<option value="">{$lang_theme_style_select}</option>';
    557         if (settings['theme_advanced_styles']) {
    558             var stylesAr = settings['theme_advanced_styles'].split(';');
    559            
    560             for (var i=0; i<stylesAr.length; i++) {
    561                 var key, value;
    562 
    563                 key = stylesAr[i].split('=')[0];
    564                 value = stylesAr[i].split('=')[1];
    565 
    566                 styleSelectHTML += '<option value="' + value + '">' + key + '</option>';
    567             }
    568 
    569             TinyMCE_AdvancedTheme._autoImportCSSClasses = false;
    570         }
    571 
    572         switch(layoutManager) {
    573             case "SimpleLayout" : //the default TinyMCE Layout (for backwards compatibility)...
    574                 var toolbarHTML = "";
    575                 var toolbarLocation = tinyMCE.getParam("theme_advanced_toolbar_location", "bottom");
    576                 var toolbarAlign = tinyMCE.getParam("theme_advanced_toolbar_align", "center");
    577                 var pathLocation = tinyMCE.getParam("theme_advanced_path_location", "none"); // Compatiblity
    578                 var statusbarLocation = tinyMCE.getParam("theme_advanced_statusbar_location", pathLocation);
    579                 var defVals = {
    580                     theme_advanced_buttons1 : "bold,italic,underline,strikethrough,separator,justifyleft,justifycenter,justifyright,justifyfull,separator,styleselect,formatselect",
    581                     theme_advanced_buttons2 : "bullist,numlist,separator,outdent,indent,separator,undo,redo,separator,link,unlink,anchor,image,cleanup,help,code",
    582                     theme_advanced_buttons3 : "hr,removeformat,visualaid,separator,sub,sup,separator,charmap"
    583                 };
    584 
    585                 // Add accessibility control
    586                 toolbarHTML += '<a href="#" accesskey="q" title="' + tinyMCE.getLang("lang_toolbar_focus") + '"';
    587 
    588                 if (!tinyMCE.getParam("accessibility_focus"))
    589                     toolbarHTML += ' onfocus="tinyMCE.getInstanceById(\'' + editorId + '\').getWin().focus();"';
    590 
    591                 toolbarHTML += '></a>';
    592 
    593                 // Render rows
    594                 for (var i=1; i<100; i++) {
    595                     var def = defVals["theme_advanced_buttons" + i];
    596 
    597                     var buttons = tinyMCE.getParam("theme_advanced_buttons" + i, def == null ? '' : def, true, ',');
    598                     if (buttons.length == 0)
    599                         break;
    600 
    601                     buttons = removeFromArray(buttons, tinyMCE.getParam("theme_advanced_disable", "", true, ','));
    602                     buttons = addToArray(buttons, tinyMCE.getParam("theme_advanced_buttons" + i + "_add", "", true, ','));
    603                     buttons = addToArray(tinyMCE.getParam("theme_advanced_buttons" + i + "_add_before", "", true, ','), buttons);
    604 
    605                     for (var b=0; b<buttons.length; b++)
    606                         toolbarHTML += tinyMCE.getControlHTML(buttons[b]);
    607 
    608                     if (buttons.length > 0) {
    609                         toolbarHTML += "<br />";
    610                         deltaHeight -= 23;
    611                     }
    612                 }
    613 
    614                 // Add accessibility control
    615                 toolbarHTML += '<a href="#" accesskey="z" onfocus="tinyMCE.getInstanceById(\'' + editorId + '\').getWin().focus();"></a>';
    616 
    617                 // Setup template html
    618                 template['html'] = '<table class="mceEditor" border="0" cellpadding="0" cellspacing="0" width="{$width}" height="{$height}" style="width:{$width_style};height:{$height_style}"><tbody>';
    619 
    620                 if (toolbarLocation == "top")
    621                     template['html'] += '<tr><td dir="ltr" class="mceToolbarTop" align="' + toolbarAlign + '" height="1" nowrap="nowrap"><span id="' + editorId + '_toolbar" class="mceToolbarContainer">' + toolbarHTML + '</span></td></tr>';
    622 
    623                 if (statusbarLocation == "top") {
    624                     template['html'] += '<tr><td class="mceStatusbarTop" height="1">' + statusbarHTML + '</td></tr>';
    625                     deltaHeight -= 23;
    626                 }
    627 
    628                 template['html'] += '<tr><td align="center"><span id="{$editor_id}"></span></td></tr>';
    629 
    630                 if (toolbarLocation == "bottom")
    631                     template['html'] += '<tr><td dir="ltr" class="mceToolbarBottom" align="' + toolbarAlign + '" height="1"><span id="' + editorId + '_toolbar" class="mceToolbarContainer">' + toolbarHTML + '</span></td></tr>';
    632 
    633                 // External toolbar changes
    634                 if (toolbarLocation == "external") {
    635                     var bod = document.body;
    636                     var elm = document.createElement ("div");
    637 
    638                     toolbarHTML = tinyMCE.replaceVar(toolbarHTML, 'style_select_options', styleSelectHTML);
    639                     toolbarHTML = tinyMCE.applyTemplate(toolbarHTML, {editor_id : editorId});
    640 
    641                     elm.className = "mceToolbarExternal";
    642                     elm.id = editorId+"_toolbar";
    643                     elm.innerHTML = '<table width="100%" border="0" align="center"><tr><td align="center">'+toolbarHTML+'</td></tr></table>';
    644                     bod.appendChild (elm);
    645                     // bod.style.marginTop = elm.offsetHeight + "px";
    646 
    647                     deltaHeight = 0;
    648                     tinyMCE.getInstanceById(editorId).toolbarElement = elm;
    649 
    650                     //template['html'] = '<div id="mceExternalToolbar" align="center" class="mceToolbarExternal"><table width="100%" border="0" align="center"><tr><td align="center">'+toolbarHTML+'</td></tr></table></div>' + template["html"];
    651                 } else {
    652                     tinyMCE.getInstanceById(editorId).toolbarElement = null;
    653                 }
    654 
    655                 if (statusbarLocation == "bottom") {
    656                     template['html'] += '<tr><td class="mceStatusbarBottom" height="1">' + statusbarHTML + '</td></tr>';
    657                     deltaHeight -= 23;
    658                 }
    659 
    660                 template['html'] += '</tbody></table>';
    661                 //"SimpleLayout"
    662             break;
    663 
    664             case "RowLayout" : //Container Layout - containers defined in "theme_advanced_containers" are rendered from top to bottom.
    665                 template['html'] = '<table class="mceEditor" border="0" cellpadding="0" cellspacing="0" width="{$width}" height="{$height}" style="width:{$width}px;height:{$height}px"><tbody>';
    666 
    667                 var containers = tinyMCE.getParam("theme_advanced_containers", "", true, ",");
    668                 var defaultContainerCSS = tinyMCE.getParam("theme_advanced_containers_default_class", "container");
    669                 var defaultContainerAlign = tinyMCE.getParam("theme_advanced_containers_default_align", "center");
    670 
    671                 //Render Containers:
    672                 for (var i = 0; i < containers.length; i++)
    673                 {
    674                     if (containers[i] == "mceEditor") //Exceptions for mceEditor and ...
    675                         template['html'] += '<tr><td align="center" class="mceEditor_border"><span id="{$editor_id}"></span></td></tr>';
    676                     else if (containers[i] == "mceElementpath" || containers[i] == "mceStatusbar") // ... mceElementpath:
    677                     {
    678                         var pathClass = "mceStatusbar";
    679 
    680                         if (i == containers.length-1)
    681                         {
    682                             pathClass = "mceStatusbarBottom";
    683                         }
    684                         else if (i == 0)
    685                         {
    686                             pathClass = "mceStatusbar";
    687                         }
    688                         else
    689                         {
    690                             deltaHeight-=2;
    691                         }
    692 
    693                         template['html'] += '<tr><td class="' + pathClass + '" height="1">' + statusbarHTML + '</td></tr>';
    694                         deltaHeight -= 22;
    695                     } else { // Render normal Container
    696                         var curContainer = tinyMCE.getParam("theme_advanced_container_"+containers[i], "", true, ',');
    697                         var curContainerHTML = "";
    698                         var curAlign = tinyMCE.getParam("theme_advanced_container_"+containers[i]+"_align", defaultContainerAlign);
    699                         var curCSS = tinyMCE.getParam("theme_advanced_container_"+containers[i]+"_class", defaultContainerCSS);
    700 
    701                         curContainer = removeFromArray(curContainer, tinyMCE.getParam("theme_advanced_disable", "", true, ','));
    702 
    703                         for (var j=0; j<curContainer.length; j++)
    704                             curContainerHTML += tinyMCE.getControlHTML(curContainer[j]);
    705 
    706                         if (curContainer.length > 0) {
    707                             curContainerHTML += "<br />";
    708                             deltaHeight -= 23;
    709                         }
    710 
    711                         template['html'] += '<tr><td class="' + curCSS + '" align="' + curAlign + '" height="1">' + curContainerHTML + '</td></tr>';
    712                     }
    713                 }
    714 
    715                 template['html'] += '</tbody></table>';
    716                 //RowLayout
    717             break;
    718 
    719             case "CustomLayout" : //User defined layout callback...
    720                 var customLayout = tinyMCE.getParam("theme_advanced_custom_layout","");
    721 
    722                 if (customLayout != "" && eval("typeof(" + customLayout + ")") != "undefined") {
    723                     template = eval(customLayout + "(template);");
    724                 }
    725             break;
    726         }
    727 
    728         if (resizing)
    729             template['html'] += '<span id="{$editor_id}_resize_box" class="mceResizeBox"></span>';
    730 
    731         template['html'] = tinyMCE.replaceVar(template['html'], 'style_select_options', styleSelectHTML);
    732 
    733         // Set to default values
    734         if (!template['delta_width'])
    735             template['delta_width'] = 0;
    736 
    737         if (!template['delta_height'])
    738             template['delta_height'] = deltaHeight;
    739 
    740         return template;
    741     },
    742 
    743     initInstance : function(inst) {
    744         if (tinyMCE.getParam("theme_advanced_resizing", false)) {
    745             if (tinyMCE.getParam("theme_advanced_resizing_use_cookie", true)) {
    746                 var w = TinyMCE_AdvancedTheme._getCookie("TinyMCE_" + inst.editorId + "_width");
    747                 var h = TinyMCE_AdvancedTheme._getCookie("TinyMCE_" + inst.editorId + "_height");
    748 
    749                 TinyMCE_AdvancedTheme._resizeTo(inst, w, h, tinyMCE.getParam("theme_advanced_resize_horizontal", true));
    750             }
    751         }
    752 
    753         inst.addShortcut('ctrl', 'k', 'lang_link_desc', 'mceLink');
    754     },
    755 
    756     removeInstance : function(inst) {
    757         new TinyMCE_Layer(inst.editorId + '_fcMenu').remove();
    758         new TinyMCE_Layer(inst.editorId + '_bcMenu').remove();
    759     },
    760 
    761     hideInstance : function(inst) {
    762         TinyMCE_AdvancedTheme._hideMenus(inst.editorId);
    763     },
    764 
    765     _handleMenuEvent : function(e) {
    766         var te = tinyMCE.isMSIE ? window.event.srcElement : e.target;
    767         tinyMCE._menuButtonEvent(e.type == "mouseover" ? "over" : "out", document.getElementById(te._switchId));
    768 
    769         if (e.type == "click")
    770             tinyMCE.execInstanceCommand(te._editor_id, te._command);
    771     },
    772 
    773     _hideMenus : function(id) {
    774         var fcml = new TinyMCE_Layer(id + '_fcMenu'), bcml = new TinyMCE_Layer(id + '_bcMenu');
    775 
    776         if (fcml.exists() && fcml.isVisible()) {
    777             tinyMCE.switchClass(id + '_forecolor', 'mceMenuButton');
    778             fcml.hide();
    779         }
    780 
    781         if (bcml.exists() && bcml.isVisible()) {
    782             tinyMCE.switchClass(id + '_backcolor', 'mceMenuButton');
    783             bcml.hide();
    784         }
    785     },
    786 
    787     /**
    788      * Node change handler.
    789      */
    790     handleNodeChange : function(editor_id, node, undo_index, undo_levels, visual_aid, any_selection, setup_content) {
    791         var alignNode, breakOut, classNode;
    792 
    793         function selectByValue(select_elm, value, first_index) {
    794             first_index = typeof(first_index) == "undefined" ? false : true;
    795 
    796             if (select_elm) {
    797                 for (var i=0; i<select_elm.options.length; i++) {
    798                     var ov = "" + select_elm.options[i].value;
    799 
    800                     if (first_index && ov.toLowerCase().indexOf(value.toLowerCase()) == 0) {
    801                         select_elm.selectedIndex = i;
    802                         return true;
    803                     }
    804 
    805                     if (ov == value) {
    806                         select_elm.selectedIndex = i;
    807                         return true;
    808                     }
    809                 }
    810             }
    811 
    812             return false;
    813         };
    814 
    815         // No node provided
    816         if (node == null)
    817             return;
    818 
    819         // Update path
    820         var pathElm = document.getElementById(editor_id + "_path");
    821         var inst = tinyMCE.getInstanceById(editor_id);
    822         var doc = inst.getDoc();
    823         TinyMCE_AdvancedTheme._hideMenus(editor_id);
    824 
    825         if (pathElm) {
    826             // Get node path
    827             var parentNode = node;
    828             var path = new Array();
    829            
    830             while (parentNode != null) {
    831                 if (parentNode.nodeName.toUpperCase() == "BODY") {
    832                     break;
    833                 }
    834 
    835                 // Only append element nodes to path
    836                 if (parentNode.nodeType == 1 && tinyMCE.getAttrib(parentNode, "class").indexOf('mceItemHidden') == -1) {
    837                     path[path.length] = parentNode;
    838                 }
    839 
    840                 parentNode = parentNode.parentNode;
    841             }
    842 
    843             // Setup HTML
    844             var html = "";
    845             for (var i=path.length-1; i>=0; i--) {
    846                 var nodeName = path[i].nodeName.toLowerCase();
    847                 var nodeData = "";
    848 
    849                 if (nodeName.indexOf("html:") == 0)
    850                     nodeName = nodeName.substring(5);
    851 
    852                 if (nodeName == "b") {
    853                     nodeName = "strong";
    854                 }
    855 
    856                 if (nodeName == "i") {
    857                     nodeName = "em";
    858                 }
    859 
    860                 if (nodeName == "span") {
    861                     var cn = tinyMCE.getAttrib(path[i], "class");
    862                     if (cn != "" && cn.indexOf('mceItem') == -1)
    863                         nodeData += "class: " + cn + " ";
    864 
    865                     var st = tinyMCE.getAttrib(path[i], "style");
    866                     if (st != "") {
    867                         st = tinyMCE.serializeStyle(tinyMCE.parseStyle(st));
    868                         nodeData += "style: " + tinyMCE.xmlEncode(st) + " ";
    869                     }
    870                 }
    871 
    872                 if (nodeName == "font") {
    873                     if (tinyMCE.getParam("convert_fonts_to_spans"))
    874                         nodeName = "span";
    875 
    876                     var face = tinyMCE.getAttrib(path[i], "face");
    877                     if (face != "")
    878                         nodeData += "font: " + tinyMCE.xmlEncode(face) + " ";
    879 
    880                     var size = tinyMCE.getAttrib(path[i], "size");
    881                     if (size != "")
    882                         nodeData += "size: " + tinyMCE.xmlEncode(size) + " ";
    883 
    884                     var color = tinyMCE.getAttrib(path[i], "color");
    885                     if (color != "")
    886                         nodeData += "color: " + tinyMCE.xmlEncode(color) + " ";
    887                 }
    888 
    889                 if (tinyMCE.getAttrib(path[i], 'id') != "") {
    890                     nodeData += "id: " + path[i].getAttribute('id') + " ";
    891                 }
    892 
    893                 var className = tinyMCE.getVisualAidClass(tinyMCE.getAttrib(path[i], "class"), false);
    894                 if (className != "" && className.indexOf('mceItem') == -1)
    895                     nodeData += "class: " + className + " ";
    896 
    897                 if (tinyMCE.getAttrib(path[i], 'src') != "") {
    898                     var src = tinyMCE.getAttrib(path[i], "mce_src");
    899 
    900                     if (src == "")
    901                          src = tinyMCE.getAttrib(path[i], "src");
    902 
    903                     nodeData += "src: " + tinyMCE.xmlEncode(src) + " ";
    904                 }
    905 
    906                 if (path[i].nodeName == 'A' && tinyMCE.getAttrib(path[i], 'href') != "") {
    907                     var href = tinyMCE.getAttrib(path[i], "mce_href");
    908 
    909                     if (href == "")
    910                          href = tinyMCE.getAttrib(path[i], "href");
    911 
    912                     nodeData += "href: " + tinyMCE.xmlEncode(href) + " ";
    913                 }
    914 
    915                 className = tinyMCE.getAttrib(path[i], "class");
    916                 if ((nodeName == "img" || nodeName == "span") && className.indexOf('mceItem') != -1) {
    917                     nodeName = className.replace(/mceItem([a-z]+)/gi, '$1').toLowerCase();
    918                     nodeData = path[i].getAttribute('title');
    919                 }
    920 
    921                 if (nodeName == "a" && (anchor = tinyMCE.getAttrib(path[i], "name")) != "") {
    922                     nodeName = "a";
    923                     nodeName += "#" + tinyMCE.xmlEncode(anchor);
    924                     nodeData = "";
    925                 }
    926 
    927                 if (tinyMCE.getAttrib(path[i], 'name').indexOf("mce_") != 0) {
    928                     var className = tinyMCE.getVisualAidClass(tinyMCE.getAttrib(path[i], "class"), false);
    929                     if (className != "" && className.indexOf('mceItem') == -1) {
    930                         nodeName += "." + className;
    931                     }
    932                 }
    933 
    934                 var cmd = 'tinyMCE.execInstanceCommand(\'' + editor_id + '\',\'mceSelectNodeDepth\',false,\'' + i + '\');';
    935                 html += '<a title="' + nodeData + '" href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" target="_self" class="mcePathItem">' + nodeName + '</a>';
    936 
    937                 if (i > 0) {
    938                     html += " &raquo; ";
    939                 }
    940             }
    941 
    942             pathElm.innerHTML = '<a href="#" accesskey="x"></a>' + tinyMCE.getLang('lang_theme_path') + ": " + html + '&#160;';
    943         }
    944 
    945         // Reset old states
    946         tinyMCE.switchClass(editor_id + '_justifyleft', 'mceButtonNormal');
    947         tinyMCE.switchClass(editor_id + '_justifyright', 'mceButtonNormal');
    948         tinyMCE.switchClass(editor_id + '_justifycenter', 'mceButtonNormal');
    949         tinyMCE.switchClass(editor_id + '_justifyfull', 'mceButtonNormal');
    950         tinyMCE.switchClass(editor_id + '_bold', 'mceButtonNormal');
    951         tinyMCE.switchClass(editor_id + '_italic', 'mceButtonNormal');
    952         tinyMCE.switchClass(editor_id + '_underline', 'mceButtonNormal');
    953         tinyMCE.switchClass(editor_id + '_strikethrough', 'mceButtonNormal');
    954         tinyMCE.switchClass(editor_id + '_bullist', 'mceButtonNormal');
    955         tinyMCE.switchClass(editor_id + '_numlist', 'mceButtonNormal');
    956         tinyMCE.switchClass(editor_id + '_sub', 'mceButtonNormal');
    957         tinyMCE.switchClass(editor_id + '_sup', 'mceButtonNormal');
    958         tinyMCE.switchClass(editor_id + '_anchor', 'mceButtonNormal');
    959         tinyMCE.switchClass(editor_id + '_link', 'mceButtonDisabled');
    960         tinyMCE.switchClass(editor_id + '_unlink', 'mceButtonDisabled');
    961         tinyMCE.switchClass(editor_id + '_outdent', 'mceButtonDisabled');
    962         tinyMCE.switchClass(editor_id + '_image', 'mceButtonNormal');
    963         tinyMCE.switchClass(editor_id + '_hr', 'mceButtonNormal');
    964 
    965         if (node.nodeName == "A" && tinyMCE.getAttrib(node, "class").indexOf('mceItemAnchor') != -1)
    966             tinyMCE.switchClass(editor_id + '_anchor', 'mceButtonSelected');
    967 
    968         // Get link
    969         var anchorLink = tinyMCE.getParentElement(node, "a", "href");
    970 
    971         if (anchorLink || any_selection) {
    972             tinyMCE.switchClass(editor_id + '_link', anchorLink ? 'mceButtonSelected' : 'mceButtonNormal');
    973             tinyMCE.switchClass(editor_id + '_unlink', anchorLink ? 'mceButtonSelected' : 'mceButtonNormal');
    974         }
    975 
    976         // Handle visual aid
    977         tinyMCE.switchClass(editor_id + '_visualaid', visual_aid ? 'mceButtonSelected' : 'mceButtonNormal');
    978 
    979         if (undo_levels != -1) {
    980             tinyMCE.switchClass(editor_id + '_undo', 'mceButtonDisabled');
    981             tinyMCE.switchClass(editor_id + '_redo', 'mceButtonDisabled');
    982         }
    983 
    984         // Within li, blockquote
    985         if (tinyMCE.getParentElement(node, "li,blockquote"))
    986             tinyMCE.switchClass(editor_id + '_outdent', 'mceButtonNormal');
    987 
    988         // Has redo levels
    989         if (undo_index != -1 && (undo_index < undo_levels-1 && undo_levels > 0))
    990             tinyMCE.switchClass(editor_id + '_redo', 'mceButtonNormal');
    991 
    992         // Has undo levels
    993         if (undo_index != -1 && (undo_index > 0 && undo_levels > 0))
    994             tinyMCE.switchClass(editor_id + '_undo', 'mceButtonNormal');
    995 
    996         // Select class in select box
    997         var selectElm = document.getElementById(editor_id + "_styleSelect");
    998        
    999         if (selectElm) {
    1000             TinyMCE_AdvancedTheme._setupCSSClasses(editor_id);
    1001 
    1002             classNode = node;
    1003             breakOut = false;
    1004             var index = 0;
    1005 
    1006             do {
    1007                 if (classNode && classNode.className) {
    1008                     for (var i=0; i<selectElm.options.length; i++) {
    1009                         if (selectElm.options[i].value == classNode.className) {
    1010                             index = i;
    1011                             breakOut = true;
    1012                             break;
     824
     825                    if (v = DOM.getAttrib(n, 'id'))
     826                        ti += 'id: ' + v + ' ';
     827
     828                    if (v = n.className) {
     829                        v = v.replace(/(webkit-[\w\-]+|Apple-[\w\-]+|mceItem\w+|mceVisualAid)/g, '');
     830
     831                        if (v && v.indexOf('mceItem') == -1) {
     832                            ti += 'class: ' + v + ' ';
     833
     834                            if (DOM.isBlock(n) || na == 'img' || na == 'span')
     835                                na += '.' + v;
    1013836                        }
    1014837                    }
     838
     839                    na = na.replace(/(html:)/g, '');
     840                    na = {name : na, node : n, title : ti};
     841                    t.onResolveName.dispatch(t, na);
     842                    ti = na.title;
     843                    na = na.name;
     844
     845                    //u = "javascript:tinymce.EditorManager.get('" + ed.id + "').theme._sel('" + (de++) + "');";
     846                    pi = DOM.create('a', {'href' : "#" + (de++) + "", onmousedown : "return false;", title : ti}, na);
     847
     848                    if (p.hasChildNodes()) {
     849                        p.insertBefore(document.createTextNode(' \u00bb '), p.firstChild);
     850                        p.insertBefore(pi, p.firstChild);
     851                    } else
     852                        p.appendChild(pi);
     853                }, ed.getBody());
     854            }
     855        },
     856
     857        // Commands gets called by execCommand
     858
     859        _sel : function(v) {
     860            this.editor.execCommand('mceSelectNodeDepth', false, v);
     861        },
     862
     863        _mceInsertAnchor : function(ui, v) {
     864            var ed = this.editor;
     865
     866            ed.windowManager.open({
     867                url : tinymce.baseURL + '/themes/advanced/anchor.htm',
     868                width : 320 + parseInt(ed.getLang('advanced.anchor_delta_width', 0)),
     869                height : 90 + parseInt(ed.getLang('advanced.anchor_delta_height', 0)),
     870                inline : true
     871            }, {
     872                theme_url : this.url
     873            });
     874        },
     875
     876        _mceCharMap : function() {
     877            var ed = this.editor;
     878
     879            ed.windowManager.open({
     880                url : tinymce.baseURL + '/themes/advanced/charmap.htm',
     881                width : 550 + parseInt(ed.getLang('advanced.charmap_delta_width', 0)),
     882                height : 250 + parseInt(ed.getLang('advanced.charmap_delta_height', 0)),
     883                inline : true
     884            }, {
     885                theme_url : this.url
     886            });
     887        },
     888
     889        _mceHelp : function() {
     890            var ed = this.editor;
     891
     892            ed.windowManager.open({
     893                url : tinymce.baseURL + '/themes/advanced/about.htm',
     894                width : 480,
     895                height : 380,
     896                inline : true
     897            }, {
     898                theme_url : this.url
     899            });
     900        },
     901
     902        _mceColorPicker : function(u, v) {
     903            var ed = this.editor;
     904
     905            v = v || {};
     906
     907            ed.windowManager.open({
     908                url : tinymce.baseURL + '/themes/advanced/color_picker.htm',
     909                width : 375 + parseInt(ed.getLang('advanced.colorpicker_delta_width', 0)),
     910                height : 250 + parseInt(ed.getLang('advanced.colorpicker_delta_height', 0)),
     911                close_previous : false,
     912                inline : true
     913            }, {
     914                input_color : v.color,
     915                func : v.func,
     916                theme_url : this.url
     917            });
     918        },
     919
     920        _mceCodeEditor : function(ui, val) {
     921            var ed = this.editor;
     922
     923            ed.windowManager.open({
     924                url : tinymce.baseURL + '/themes/advanced/source_editor.htm',
     925                width : parseInt(ed.getParam("theme_advanced_source_editor_width", 720)),
     926                height : parseInt(ed.getParam("theme_advanced_source_editor_height", 580)),
     927                inline : true,
     928                resizable : true,
     929                maximizable : true
     930            }, {
     931                theme_url : this.url
     932            });
     933        },
     934
     935        _mceImage : function(ui, val) {
     936            var ed = this.editor;
     937
     938            ed.windowManager.open({
     939                url : tinymce.baseURL + '/themes/advanced/image.htm',
     940                width : 355 + parseInt(ed.getLang('advanced.image_delta_width', 0)),
     941                height : 275 + parseInt(ed.getLang('advanced.image_delta_height', 0)),
     942                inline : true
     943            }, {
     944                theme_url : this.url
     945            });
     946        },
     947
     948        _mceLink : function(ui, val) {
     949            var ed = this.editor;
     950
     951            ed.windowManager.open({
     952                url : tinymce.baseURL + '/themes/advanced/link.htm',
     953                width : 310 + parseInt(ed.getLang('advanced.link_delta_width', 0)),
     954                height : 200 + parseInt(ed.getLang('advanced.link_delta_height', 0)),
     955                inline : true
     956            }, {
     957                theme_url : this.url
     958            });
     959        },
     960
     961        _mceNewDocument : function() {
     962            var ed = this.editor;
     963
     964            ed.windowManager.confirm('advanced.newdocument', function(s) {
     965                if (s)
     966                    ed.execCommand('mceSetContent', false, '');
     967            });
     968        },
     969
     970        _mceForeColor : function() {
     971            var t = this;
     972
     973            this._mceColorPicker(0, {
     974                func : function(co) {
     975                    t.editor.execCommand('ForeColor', false, co);
    1015976                }
    1016             } while (!breakOut && classNode != null && (classNode = classNode.parentNode) != null);
    1017 
    1018             selectElm.selectedIndex = index;
     977            });
     978        },
     979
     980        _mceBackColor : function() {
     981            var t = this;
     982
     983            this._mceColorPicker(0, {
     984                func : function(co) {
     985                    t.editor.execCommand('HiliteColor', false, co);
     986                }
     987            });
    1019988        }
    1020 
    1021         // Select formatblock
    1022         var selectElm = document.getElementById(editor_id + "_formatSelect");
    1023         if (selectElm) {
    1024             var elm = tinyMCE.getParentElement(node, "p,div,h1,h2,h3,h4,h5,h6,pre,address");
    1025 
    1026             if (elm)
    1027                 selectByValue(selectElm, "<" + elm.nodeName.toLowerCase() + ">");
    1028             else
    1029                 selectByValue(selectElm, "");
    1030         }
    1031 
    1032         // Select fontselect
    1033         var selectElm = document.getElementById(editor_id + "_fontNameSelect");
    1034         if (selectElm) {
    1035             if (!tinyMCE.isSafari && !(tinyMCE.isMSIE && !tinyMCE.isOpera)) {
    1036                 var face = inst.queryCommandValue('FontName');
    1037 
    1038                 face = face == null || face == "" ? "" : face;
    1039 
    1040                 selectByValue(selectElm, face, face != "");
    1041             } else {
    1042                 var elm = tinyMCE.getParentElement(node, "font", "face");
    1043 
    1044                 if (elm) {
    1045                     var family = tinyMCE.getAttrib(elm, "face");
    1046 
    1047                     if (family == '')
    1048                         family = '' + elm.style.fontFamily;
    1049 
    1050                     if (!selectByValue(selectElm, family, family != ""))
    1051                         selectByValue(selectElm, "");
    1052                 } else
    1053                     selectByValue(selectElm, "");
    1054             }
    1055         }
    1056 
    1057         // Select fontsize
    1058         var selectElm = document.getElementById(editor_id + "_fontSizeSelect");
    1059         if (selectElm) {
    1060             if (!tinyMCE.isSafari && !tinyMCE.isOpera) {
    1061                 var size = inst.queryCommandValue('FontSize');
    1062                 selectByValue(selectElm, size == null || size == "" ? "0" : size);
    1063             } else {
    1064                 var elm = tinyMCE.getParentElement(node, "font", "size");
    1065                 if (elm) {
    1066                     var size = tinyMCE.getAttrib(elm, "size");
    1067 
    1068                     if (size == '') {
    1069                         var sizes = new Array('', '8px', '10px', '12px', '14px', '18px', '24px', '36px');
    1070 
    1071                         size = '' + elm.style.fontSize;
    1072 
    1073                         for (var i=0; i<sizes.length; i++) {
    1074                             if (('' + sizes[i]) == size) {
    1075                                 size = i;
    1076                                 break;
    1077                             }
    1078                         }
    1079                     }
    1080 
    1081                     if (!selectByValue(selectElm, size))
    1082                         selectByValue(selectElm, "");
    1083                 } else
    1084                     selectByValue(selectElm, "0");
    1085             }
    1086         }
    1087 
    1088         // Handle align attributes
    1089         alignNode = node;
    1090         breakOut = false;
    1091         do {
    1092             if (!alignNode.getAttribute || !alignNode.getAttribute('align'))
    1093                 continue;
    1094 
    1095             switch (alignNode.getAttribute('align').toLowerCase()) {
    1096                 case "left":
    1097                     tinyMCE.switchClass(editor_id + '_justifyleft', 'mceButtonSelected');
    1098                     breakOut = true;
    1099                 break;
    1100 
    1101                 case "right":
    1102                     tinyMCE.switchClass(editor_id + '_justifyright', 'mceButtonSelected');
    1103                     breakOut = true;
    1104                 break;
    1105 
    1106                 case "middle":
    1107                 case "center":
    1108                     tinyMCE.switchClass(editor_id + '_justifycenter', 'mceButtonSelected');
    1109                     breakOut = true;
    1110                 break;
    1111 
    1112                 case "justify":
    1113                     tinyMCE.switchClass(editor_id + '_justifyfull', 'mceButtonSelected');
    1114                     breakOut = true;
    1115                 break;
    1116             }
    1117         } while (!breakOut && (alignNode = alignNode.parentNode) != null);
    1118 
    1119         // Div justification
    1120         var div = tinyMCE.getParentElement(node, "div");
    1121         if (div && div.style.textAlign == "center")
    1122             tinyMCE.switchClass(editor_id + '_justifycenter', 'mceButtonSelected');
    1123 
    1124         // Do special text
    1125         if (!setup_content) {
    1126             // , "JustifyLeft", "_justifyleft", "JustifyCenter", "justifycenter", "JustifyRight", "justifyright", "JustifyFull", "justifyfull", "InsertUnorderedList", "bullist", "InsertOrderedList", "numlist", "InsertUnorderedList", "bullist", "Outdent", "outdent", "Indent", "indent", "subscript", "sub"
    1127             var ar = new Array("Bold", "_bold", "Italic", "_italic", "Strikethrough", "_strikethrough", "superscript", "_sup", "subscript", "_sub");
    1128             for (var i=0; i<ar.length; i+=2) {
    1129                 if (inst.queryCommandState(ar[i]))
    1130                     tinyMCE.switchClass(editor_id + ar[i+1], 'mceButtonSelected');
    1131             }
    1132 
    1133             if (inst.queryCommandState("Underline") && (node.parentNode == null || node.parentNode.nodeName != "A"))
    1134                 tinyMCE.switchClass(editor_id + '_underline', 'mceButtonSelected');
    1135         }
    1136 
    1137         // Handle elements
    1138         do {
    1139             switch (node.nodeName) {
    1140                 case "UL":
    1141                     tinyMCE.switchClass(editor_id + '_bullist', 'mceButtonSelected');
    1142                 break;
    1143 
    1144                 case "OL":
    1145                     tinyMCE.switchClass(editor_id + '_numlist', 'mceButtonSelected');
    1146                 break;
    1147 
    1148                 case "HR":
    1149                      tinyMCE.switchClass(editor_id + '_hr', 'mceButtonSelected');
    1150                 break;
    1151 
    1152                 case "IMG":
    1153                 if (tinyMCE.getAttrib(node, 'name').indexOf('mce_') != 0 && tinyMCE.getAttrib(node, 'class').indexOf('mceItem') == -1) {
    1154                     tinyMCE.switchClass(editor_id + '_image', 'mceButtonSelected');
    1155                 }
    1156                 break;
    1157             }
    1158         } while ((node = node.parentNode) != null);
    1159     },
    1160 
    1161     // Private theme internal functions
    1162 
    1163     // This function auto imports CSS classes into the class selection droplist
    1164     _setupCSSClasses : function(editor_id) {
    1165         var i, selectElm;
    1166 
    1167         if (!TinyMCE_AdvancedTheme._autoImportCSSClasses)
    1168             return;
    1169 
    1170         selectElm = document.getElementById(editor_id + '_styleSelect');
    1171 
    1172         if (selectElm && selectElm.getAttribute('cssImported') != 'true') {
    1173             var csses = tinyMCE.getCSSClasses(editor_id);
    1174             if (csses && selectElm) {
    1175                 for (i=0; i<csses.length; i++)
    1176                     selectElm.options[selectElm.options.length] = new Option(csses[i], csses[i]);
    1177             }
    1178 
    1179             // Only do this once
    1180             if (csses != null && csses.length > 0)
    1181                 selectElm.setAttribute('cssImported', 'true');
    1182         }
    1183     },
    1184 
    1185     _setCookie : function(name, value, expires, path, domain, secure) {
    1186         var curCookie = name + "=" + escape(value) +
    1187             ((expires) ? "; expires=" + expires.toGMTString() : "") +
    1188             ((path) ? "; path=" + escape(path) : "") +
    1189             ((domain) ? "; domain=" + domain : "") +
    1190             ((secure) ? "; secure" : "");
    1191 
    1192         document.cookie = curCookie;
    1193     },
    1194 
    1195     _getCookie : function(name) {
    1196         var dc = document.cookie;
    1197         var prefix = name + "=";
    1198         var begin = dc.indexOf("; " + prefix);
    1199 
    1200         if (begin == -1) {
    1201             begin = dc.indexOf(prefix);
    1202 
    1203             if (begin != 0)
    1204                 return null;
    1205         } else
    1206             begin += 2;
    1207 
    1208         var end = document.cookie.indexOf(";", begin);
    1209 
    1210         if (end == -1)
    1211             end = dc.length;
    1212 
    1213         return unescape(dc.substring(begin + prefix.length, end));
    1214     },
    1215 
    1216     _resizeTo : function(inst, w, h, set_w) {
    1217         var editorContainer = document.getElementById(inst.editorId + '_parent');
    1218         var tableElm = editorContainer.firstChild;
    1219         var iframe = inst.iframeElement;
    1220 
    1221         if (w == null || w == "null") {
    1222             set_w = false;
    1223             w = 0;
    1224         }
    1225 
    1226         if (h == null || h == "null")
    1227             return;
    1228 
    1229         w = parseInt(w);
    1230         h = parseInt(h);
    1231 
    1232         if (tinyMCE.isGecko) {
    1233             w += 2;
    1234             h += 2;
    1235         }
    1236 
    1237         var dx = w - tableElm.clientWidth;
    1238         var dy = h - tableElm.clientHeight;
    1239 
    1240         w = w < 1 ? 30 : w;
    1241         h = h < 1 ? 30 : h;
    1242 
    1243         if (set_w)
    1244             tableElm.style.width = w + "px";
    1245        
    1246         if ( !tinyMCE.isMSIE || tinyMCE.isMSIE7 || tinyMCE.isOpera ) // WordPress: do this later to avoid creeping toolbar bug in MSIE6
    1247         tableElm.style.height = h + "px";
    1248 
    1249         iw = iframe.clientWidth + dx;
    1250         ih = iframe.clientHeight + dy;
    1251 
    1252         iw = iw < 1 ? 30 : iw;
    1253         ih = ih < 1 ? 30 : ih;
    1254 /*      WordPress: found that this led to a shrinking editor with every resize.
    1255             (Gray background creeps in 1px at a time.)
    1256         if (tinyMCE.isGecko) {
    1257             iw -= 2;
    1258             ih -= 2;
    1259         }
    1260 */
    1261 
    1262         if (set_w)
    1263             iframe.style.width = iw + "px";
    1264 
    1265         iframe.style.height = ih + "px";
    1266 
    1267         // Is it to small, make it bigger again
    1268         if (set_w) {
    1269             var tableBodyElm = tableElm.firstChild;
    1270             var minIframeWidth = tableBodyElm.scrollWidth;
    1271             if (inst.iframeElement.clientWidth < minIframeWidth) {
    1272                 dx = minIframeWidth - inst.iframeElement.clientWidth;
    1273 
    1274                 inst.iframeElement.style.width = (iw + dx) + "px";
    1275             }
    1276         }
    1277        
    1278         tableElm.style.height = h + "px"; // WordPress: see above
    1279 
    1280         // Remove pesky table controls
    1281         inst.useCSS = false;
    1282     },
    1283 
    1284     /**
    1285      * Handles resizing events.
    1286      */
    1287     _resizeEventHandler : function(e) {
    1288         var resizer = TinyMCE_AdvancedTheme._resizer;
    1289 
    1290         // Do nothing
    1291         if (!resizer.resizing)
    1292             return;
    1293 
    1294         e = typeof(e) == "undefined" ? window.event : e;
    1295 
    1296         var dx = e.screenX - resizer.downX;
    1297         var dy = e.screenY - resizer.downY;
    1298         var resizeBox = resizer.resizeBox;
    1299         var editorId = resizer.editorId;
    1300 
    1301         switch (e.type) {
    1302             case "mousemove":
    1303                 var w, h;
    1304 
    1305                 w = resizer.width + dx;
    1306                 h = resizer.height + dy;
    1307 
    1308                 w = w < 1 ? 1 : w;
    1309                 h = h < 1 ? 1 : h;
    1310 
    1311                 if (resizer.horizontal)
    1312                     resizeBox.style.width = w + "px";
    1313 
    1314                 resizeBox.style.height = h + "px";
    1315                 break;
    1316 
    1317             case "mouseup":
    1318                 TinyMCE_AdvancedTheme._setResizing(e, editorId, false);
    1319                 TinyMCE_AdvancedTheme._resizeTo(tinyMCE.getInstanceById(editorId), resizer.width + dx, resizer.height + dy, resizer.horizontal);
    1320 
    1321                 // Expire in a month
    1322                 if (tinyMCE.getParam("theme_advanced_resizing_use_cookie", true)) {
    1323                     var expires = new Date();
    1324                     expires.setTime(expires.getTime() + 3600000 * 24 * 30);
    1325 
    1326                     // Set the cookies
    1327                     TinyMCE_AdvancedTheme._setCookie("TinyMCE_" + editorId + "_width", "" + (resizer.horizontal ? resizer.width + dx : ""), expires);
    1328                     TinyMCE_AdvancedTheme._setCookie("TinyMCE_" + editorId + "_height", "" + (resizer.height + dy), expires);
    1329                 }
    1330                 break;
    1331         }
    1332     },
    1333 
    1334     /**
    1335      * Starts/stops the editor resizing.
    1336      */
    1337     _setResizing : function(e, editor_id, state) {
    1338         e = typeof(e) == "undefined" ? window.event : e;
    1339 
    1340         var resizer = TinyMCE_AdvancedTheme._resizer;
    1341         var editorContainer = document.getElementById(editor_id + '_parent');
    1342         var editorArea = document.getElementById(editor_id + '_parent').firstChild;
    1343         var resizeBox = document.getElementById(editor_id + '_resize_box');
    1344         var inst = tinyMCE.getInstanceById(editor_id);
    1345 
    1346         if (state) {
    1347             // Place box over editor area
    1348             var width = editorArea.clientWidth;
    1349             var height = editorArea.clientHeight;
    1350 
    1351             resizeBox.style.width = width + "px";
    1352             resizeBox.style.height = height + "px";
    1353 
    1354             resizer.iframeWidth = inst.iframeElement.clientWidth;
    1355             resizer.iframeHeight = inst.iframeElement.clientHeight;
    1356 
    1357             // Hide editor and show resize box
    1358             editorArea.style.display = "none";
    1359             resizeBox.style.display = "block";
    1360 
    1361             // Add event handlers, only once
    1362             if (!resizer.eventHandlers) {
    1363                 if (tinyMCE.isMSIE)
    1364                     tinyMCE.addEvent(document, "mousemove", TinyMCE_AdvancedTheme._resizeEventHandler);
    1365                 else
    1366                     tinyMCE.addEvent(window, "mousemove", TinyMCE_AdvancedTheme._resizeEventHandler);
    1367 
    1368                 tinyMCE.addEvent(document, "mouseup", TinyMCE_AdvancedTheme._resizeEventHandler);
    1369 
    1370                 resizer.eventHandlers = true;
    1371             }
    1372 
    1373             resizer.resizing = true;
    1374             resizer.downX = e.screenX;
    1375             resizer.downY = e.screenY;
    1376             resizer.width = parseInt(resizeBox.style.width);
    1377             resizer.height = parseInt(resizeBox.style.height);
    1378             resizer.editorId = editor_id;
    1379             resizer.resizeBox = resizeBox;
    1380             resizer.horizontal = tinyMCE.getParam("theme_advanced_resize_horizontal", true);
    1381         } else {
    1382             resizer.resizing = false;
    1383             resizeBox.style.display = "none";
    1384             editorArea.style.display = tinyMCE.isMSIE && !tinyMCE.isOpera ? "block" : "table";
    1385             tinyMCE.execCommand('mceResetDesignMode');
    1386         }
    1387     },
    1388 
    1389     _getColorHTML : function(id, n, cm) {
    1390         var i, h, cl;
    1391 
    1392         h = '<span class="mceMenuLine"></span>';
    1393         cl = tinyMCE.getParam(n, TinyMCE_AdvancedTheme._defColors).split(',');
    1394 
    1395         h += '<table class="mceColors"><tr>';
    1396         for (i=0; i<cl.length; i++) {
    1397             c = 'tinyMCE.execInstanceCommand(\'' + id + '\', \'' + cm + '\', false, \'#' + cl[i] + '\');';
    1398             h += '<td><a href="javascript:' + c + '" style="background-color: #' + cl[i] + '" onclick="' + c + ';return false;"></a></td>';
    1399 
    1400             if ((i+1) % 8 == 0)
    1401                 h += '</tr><tr>';
    1402         }
    1403 
    1404         h += '</tr></table>';
    1405 
    1406         if (tinyMCE.getParam("theme_advanced_more_colors", true))
    1407             h += '<a href="javascript:void(0);" onclick="TinyMCE_AdvancedTheme._pickColor(\'' + id + '\',\'' + cm + '\');" class="mceMoreColors">' + tinyMCE.getLang('lang_more_colors') + '</a>';
    1408 
    1409         return h;
    1410     },
    1411 
    1412     _pickColor : function(id, cm) {
    1413         var inputColor, inst = tinyMCE.selectedInstance;
    1414 
    1415         if (cm == 'forecolor' && inst)
    1416             inputColor = inst.foreColor;
    1417 
    1418         if ((cm == 'backcolor' || cm == 'HiliteColor') && inst)
    1419             inputColor = inst.backColor;
    1420 
    1421         tinyMCE.execCommand('mceColorPicker', true, {color : inputColor, callback : function(c) {
    1422             tinyMCE.execInstanceCommand(id, cm, false, c);
    1423         }});
    1424     },
    1425 
    1426     _insertImage : function(src, alt, border, hspace, vspace, width, height, align, title, onmouseover, onmouseout) {
    1427         tinyMCE.execCommand("mceInsertContent", false, tinyMCE.createTagHTML('img', {
    1428             src : tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], src), // Force absolute
    1429             mce_src : src,
    1430             alt : alt,
    1431             border : border,
    1432             hspace : hspace,
    1433             vspace : vspace,
    1434             width : width,
    1435             height : height,
    1436             align : align,
    1437             title : title,
    1438             onmouseover : onmouseover,
    1439             onmouseout : onmouseout
    1440         }));
    1441     },
    1442 
    1443     _insertLink : function(href, target, title, onclick, style_class) {
    1444         tinyMCE.execCommand('mceBeginUndoLevel');
    1445 
    1446         if (tinyMCE.selectedInstance && tinyMCE.selectedElement && tinyMCE.selectedElement.nodeName.toLowerCase() == "img") {
    1447             var doc = tinyMCE.selectedInstance.getDoc();
    1448             var linkElement = tinyMCE.getParentElement(tinyMCE.selectedElement, "a");
    1449             var newLink = false;
    1450 
    1451             if (!linkElement) {
    1452                 linkElement = doc.createElement("a");
    1453                 newLink = true;
    1454             }
    1455 
    1456             var mhref = href;
    1457             var thref = eval(tinyMCE.settings['urlconverter_callback'] + "(href, linkElement);");
    1458             mhref = tinyMCE.getParam('convert_urls') ? href : mhref;
    1459 
    1460             tinyMCE.setAttrib(linkElement, 'href', thref);
    1461             tinyMCE.setAttrib(linkElement, 'mce_href', mhref);
    1462             tinyMCE.setAttrib(linkElement, 'target', target);
    1463             tinyMCE.setAttrib(linkElement, 'title', title);
    1464             tinyMCE.setAttrib(linkElement, 'onclick', onclick);
    1465             tinyMCE.setAttrib(linkElement, 'class', style_class);
    1466 
    1467             if (newLink) {
    1468                 linkElement.appendChild(tinyMCE.selectedElement.cloneNode(true));
    1469                 tinyMCE.selectedElement.parentNode.replaceChild(linkElement, tinyMCE.selectedElement);
    1470             }
    1471 
    1472             return;
    1473         }
    1474 
    1475         if (!tinyMCE.linkElement && tinyMCE.selectedInstance) {
    1476             if (tinyMCE.isSafari) {
    1477                 tinyMCE.execCommand("mceInsertContent", false, '<a href="' + tinyMCE.uniqueURL + '">' + tinyMCE.selectedInstance.selection.getSelectedHTML() + '</a>');
    1478             } else
    1479                 tinyMCE.selectedInstance.contentDocument.execCommand("createlink", false, tinyMCE.uniqueURL);
    1480 
    1481             tinyMCE.linkElement = tinyMCE.getElementByAttributeValue(tinyMCE.selectedInstance.contentDocument.body, "a", "href", tinyMCE.uniqueURL);
    1482 
    1483             var elementArray = tinyMCE.getElementsByAttributeValue(tinyMCE.selectedInstance.contentDocument.body, "a", "href", tinyMCE.uniqueURL);
    1484 
    1485             for (var i=0; i<elementArray.length; i++) {
    1486                 var mhref = href;
    1487                 var thref = eval(tinyMCE.settings['urlconverter_callback'] + "(href, elementArray[i]);");
    1488                 mhref = tinyMCE.getParam('convert_urls') ? href : mhref;
    1489 
    1490                 tinyMCE.setAttrib(elementArray[i], 'href', thref);
    1491                 tinyMCE.setAttrib(elementArray[i], 'mce_href', mhref);
    1492                 tinyMCE.setAttrib(elementArray[i], 'target', target);
    1493                 tinyMCE.setAttrib(elementArray[i], 'title', title);
    1494                 tinyMCE.setAttrib(elementArray[i], 'onclick', onclick);
    1495                 tinyMCE.setAttrib(elementArray[i], 'class', style_class);
    1496             }
    1497 
    1498             tinyMCE.linkElement = elementArray[0];
    1499         }
    1500 
    1501         if (tinyMCE.linkElement) {
    1502             var mhref = href;
    1503             href = eval(tinyMCE.settings['urlconverter_callback'] + "(href, tinyMCE.linkElement);");
    1504             mhref = tinyMCE.getParam('convert_urls') ? href : mhref;
    1505 
    1506             tinyMCE.setAttrib(tinyMCE.linkElement, 'href', href);
    1507             tinyMCE.setAttrib(tinyMCE.linkElement, 'mce_href', mhref);
    1508             tinyMCE.setAttrib(tinyMCE.linkElement, 'target', target);
    1509             tinyMCE.setAttrib(tinyMCE.linkElement, 'title', title);
    1510             tinyMCE.setAttrib(tinyMCE.linkElement, 'onclick', onclick);
    1511             tinyMCE.setAttrib(tinyMCE.linkElement, 'class', style_class);
    1512         }
    1513 
    1514         tinyMCE.execCommand('mceEndUndoLevel');
    1515     }
    1516 };
    1517 
    1518 tinyMCE.addTheme("advanced", TinyMCE_AdvancedTheme);
    1519 
    1520 // Add default buttons maps for advanced theme and all internal plugins
    1521 tinyMCE.addButtonMap(TinyMCE_AdvancedTheme._buttonMap);
     989    });
     990
     991    tinymce.ThemeManager.add('advanced', tinymce.themes.AdvancedTheme);
     992}());
  • trunk/wp-includes/js/tinymce/themes/advanced/image.htm

    r5577 r6632  
     1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    12<html xmlns="http://www.w3.org/1999/xhtml">
    23<head>
    3     <title>{$lang_insert_image_title}</title>
    4     <script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
    5     <script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
    6     <script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script>
    7     <script language="javascript" type="text/javascript" src="jscripts/image.js"></script>
     4    <title>{#advanced_dlg.image_title}</title>
     5    <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
     6    <script type="text/javascript" src="../../utils/mctabs.js"></script>
     7    <script type="text/javascript" src="../../utils/form_utils.js"></script>
     8    <script type="text/javascript" src="js/image.js"></script>
    89    <base target="_self" />
    910</head>
    10 <!-- WordPress: extra onload stuff is WP -->
    11 <body id="image" onload="tinyMCEPopup.executeOnLoad('init();');document.body.style.display='';document.getElementById('src').focus();" style="display: none">
    12 <form onsubmit="insertImage();return false;" action="#">
     11<body id="image" style="display: none">
     12<form onsubmit="ImageDialog.update();return false;" action="#">
    1313    <div class="tabs">
    1414        <ul>
    15             <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{$lang_insert_image_title}</a></span></li>
     15            <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advanced_dlg.image_title}</a></span></li>
    1616        </ul>
    1717    </div>
     
    2121     <table border="0" cellpadding="4" cellspacing="0">
    2222          <tr>
    23             <td nowrap="nowrap"><label for="src">{$lang_insert_image_src}</label></td>
     23            <td nowrap="nowrap"><label for="src">{#advanced_dlg.image_src}</label></td>
    2424            <td><table border="0" cellspacing="0" cellpadding="0">
    2525                <tr>
    26                   <td><input id="src" name="src" type="text" value="" style="width: 200px" onchange="getImageData();" /></td>
     26                  <td><input id="src" name="src" type="text" value="" style="width: 200px" onchange="ImageDialog.getImageData();" /></td>
    2727                  <td id="srcbrowsercontainer">&nbsp;</td>
    2828                </tr>
    2929              </table></td>
    3030          </tr>
    31           <!-- Image list -->
    32           <script language="javascript">
    33             if (typeof(tinyMCEImageList) != "undefined" && tinyMCEImageList.length > 0) {
    34                 var html = "";
    35 
    36                 html += '<tr><td><label for="image_list">{$lang_image_list}</label></td>';
    37                 html += '<td><select id="image_list" name="image_list" style="width: 200px" onchange="this.form.src.value=this.options[this.selectedIndex].value;resetImageData();getImageData();">';
    38                 html += '<option value="">---</option>';
    39 
    40                 for (var i=0; i<tinyMCEImageList.length; i++)
    41                     html += '<option value="' + tinyMCEImageList[i][1] + '">' + tinyMCEImageList[i][0] + '</option>';
    42 
    43                 html += '</select></td></tr>';
    44 
    45                 document.write(html);
    46             }
    47           </script>
    48           <!-- /Image list -->
     31          <tr>
     32            <td><label for="image_list">{#advanced_dlg.image_list}</label></td>
     33            <td><select id="image_list" name="image_list" onchange="document.getElementById('src').value=this.options[this.selectedIndex].value;document.getElementById('alt').value=this.options[this.selectedIndex].text;"></select></td>
     34          </tr>
    4935          <tr>
    50             <td nowrap="nowrap"><label for="alt">{$lang_insert_image_alt}</label></td>
     36            <td nowrap="nowrap"><label for="alt">{#advanced_dlg.image_alt}</label></td>
    5137            <td><input id="alt" name="alt" type="text" value="" style="width: 200px" /></td>
    5238          </tr>
    5339          <tr>
    54             <td nowrap="nowrap"><label for="align">{$lang_insert_image_align}</label></td>
    55             <td><select id="align" name="align">
    56                 <option value="">{$lang_insert_image_align_default}</option>
    57                 <option value="baseline">{$lang_insert_image_align_baseline}</option>
    58                 <option value="top">{$lang_insert_image_align_top}</option>
    59                 <option value="middle">{$lang_insert_image_align_middle}</option>
    60                 <option value="bottom">{$lang_insert_image_align_bottom}</option>
    61                 <option value="texttop">{$lang_insert_image_align_texttop}</option>
    62                 <option value="absmiddle">{$lang_insert_image_align_absmiddle}</option>
    63                 <option value="absbottom">{$lang_insert_image_align_absbottom}</option>
    64                 <option value="left">{$lang_insert_image_align_left}</option>
    65                 <option value="right">{$lang_insert_image_align_right}</option>
     40            <td nowrap="nowrap"><label for="align">{#advanced_dlg.image_align}</label></td>
     41            <td><select id="align" name="align" onchange="ImageDialog.updateStyle();">
     42                <option value="">{#not_set}</option>
     43                <option value="baseline">{#advanced_dlg.image_align_baseline}</option>
     44                <option value="top">{#advanced_dlg.image_align_top}</option>
     45                <option value="middle">{#advanced_dlg.image_align_middle}</option>
     46                <option value="bottom">{#advanced_dlg.image_align_bottom}</option>
     47                <option value="text-top">{#advanced_dlg.image_align_texttop}</option>
     48                <option value="text-bottom">{#advanced_dlg.image_align_textbottom}</option>
     49                <option value="left">{#advanced_dlg.image_align_left}</option>
     50                <option value="right">{#advanced_dlg.image_align_right}</option>
    6651              </select></td>
    6752          </tr>
    6853          <tr>
    69             <td nowrap="nowrap"><label for="width">{$lang_insert_image_dimensions}</label></td>
     54            <td nowrap="nowrap"><label for="width">{#advanced_dlg.image_dimensions}</label></td>
    7055            <td><input id="width" name="width" type="text" value="" size="3" maxlength="5" />
    7156              x
     
    7358          </tr>
    7459          <tr>
    75             <td nowrap="nowrap"><label for="border">{$lang_insert_image_border}</label></td>
    76             <td><input id="border" name="border" type="text" value="" size="3" maxlength="3" /></td>
     60            <td nowrap="nowrap"><label for="border">{#advanced_dlg.image_border}</label></td>
     61            <td><input id="border" name="border" type="text" value="" size="3" maxlength="3" onchange="ImageDialog.updateStyle();" /></td>
    7762          </tr>
    7863          <tr>
    79             <td nowrap="nowrap"><label for="vspace">{$lang_insert_image_vspace}</label></td>
    80             <td><input id="vspace" name="vspace" type="text" value="" size="3" maxlength="3" /></td>
     64            <td nowrap="nowrap"><label for="vspace">{#advanced_dlg.image_vspace}</label></td>
     65            <td><input id="vspace" name="vspace" type="text" value="" size="3" maxlength="3" onchange="ImageDialog.updateStyle();" /></td>
    8166          </tr>
    8267          <tr>
    83             <td nowrap="nowrap"><label for="hspace">{$lang_insert_image_hspace}</label></td>
    84             <td><input id="hspace" name="hspace" type="text" value="" size="3" maxlength="3" /></td>
     68            <td nowrap="nowrap"><label for="hspace">{#advanced_dlg.image_hspace}</label></td>
     69            <td><input id="hspace" name="hspace" type="text" value="" size="3" maxlength="3" onchange="ImageDialog.updateStyle();" /></td>
    8570          </tr>
    8671        </table>
     
    8974
    9075    <div class="mceActionPanel">
    91         <!-- WordPress: buttons reversed! -->
    9276        <div style="float: left">
    93             <input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
     77            <input type="button" id="insert" name="insert" value="{#insert}" onclick="ImageDialog.update();" />
    9478        </div>
    9579
    9680        <div style="float: right">
    97             <input type="submit" id="insert" name="insert" value="{$lang_insert}" onclick="insertImage();" />
     81            <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
    9882        </div>
    9983    </div>
  • trunk/wp-includes/js/tinymce/themes/advanced/langs/en.js

    r5577 r6632  
    1 // UK lang variables
    2 
    3 tinyMCE.addToLang('',{
    4 theme_style_select : '-- Styles --',
    5 theme_code_desc : 'Edit HTML Source',
    6 theme_code_title : 'HTML Source Editor',
    7 theme_code_wordwrap : 'Word wrap',
    8 theme_sub_desc : 'Subscript',
    9 theme_sup_desc : 'Superscript',
    10 theme_hr_desc : 'Insert horizontal ruler',
    11 theme_removeformat_desc : 'Remove formatting',
    12 theme_custom1_desc : 'Your custom description here',
    13 insert_image_border : 'Border',
    14 insert_image_dimensions : 'Dimensions',
    15 insert_image_vspace : 'Vertical space',
    16 insert_image_hspace : 'Horizontal space',
    17 insert_image_align : 'Alignment',
    18 insert_image_align_default : '-- Not set --',
    19 insert_image_align_baseline : 'Baseline',
    20 insert_image_align_top : 'Top',
    21 insert_image_align_middle : 'Middle',
    22 insert_image_align_bottom : 'Bottom',
    23 insert_image_align_texttop : 'TextTop',
    24 insert_image_align_absmiddle : 'Absolute Middle',
    25 insert_image_align_absbottom : 'Absolute Bottom',
    26 insert_image_align_left : 'Left',
    27 insert_image_align_right : 'Right',
    28 theme_font_size : '-- Font size --',
    29 theme_fontdefault : '-- Font family --',
    30 theme_block : '-- Format --',
    31 theme_paragraph : 'Paragraph',
    32 theme_div : 'Div',
    33 theme_address : 'Address',
    34 theme_pre : 'Preformatted',
    35 theme_h1 : 'Heading 1',
    36 theme_h2 : 'Heading 2',
    37 theme_h3 : 'Heading 3',
    38 theme_h4 : 'Heading 4',
    39 theme_h5 : 'Heading 5',
    40 theme_h6 : 'Heading 6',
    41 theme_blockquote : 'Blockquote',
    42 theme_code : 'Code',
    43 theme_samp : 'Code sample',
    44 theme_dt : 'Definition term ',
    45 theme_dd : 'Definition description',
    46 theme_colorpicker_title : 'Select a color',
    47 theme_colorpicker_apply : 'Apply',
    48 theme_forecolor_desc : 'Select text color',
    49 theme_backcolor_desc : 'Select background color',
    50 theme_charmap_title : 'Select custom character',
    51 theme_charmap_desc : 'Insert custom character',
    52 theme_visualaid_desc : 'Toggle guidelines/invisible elements',
    53 insert_anchor_title : 'Insert/edit anchor',
    54 insert_anchor_name : 'Anchor name',
    55 theme_anchor_desc : 'Insert/edit anchor',
    56 theme_insert_link_titlefield : 'Title',
    57 theme_clipboard_msg : 'Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?',
    58 theme_path : 'Path',
    59 cut_desc : 'Cut',
    60 copy_desc : 'Copy',
    61 paste_desc : 'Paste',
    62 link_list : 'Link list',
    63 image_list : 'Image list',
    64 browse : 'Browse',
    65 image_props_desc : 'Image properties',
    66 newdocument_desc : 'New document',
    67 class_name : 'Class',
    68 newdocument : 'Are you sure you want clear all contents?',
    69 about_title : 'About TinyMCE',
    70 about : 'About',
    71 license : 'License',
    72 plugins : 'Plugins',
    73 plugin : 'Plugin',
    74 author : 'Author',
    75 version : 'Version',
    76 loaded_plugins : 'Loaded plugins',
    77 help : 'Help',
    78 not_set : '-- Not set --',
    79 close : 'Close',
    80 toolbar_focus : 'Jump to tool buttons - Alt+Q, Jump to editor - Alt-Z, Jump to element path - Alt-X',
    81 invalid_data : 'Error: Invalid values entered, these are marked in red.',
    82 more_colors : 'More colors',
    83 color_picker_tab : 'Picker',
    84 color_picker : 'Color picker',
    85 web_colors_tab : 'Palette',
    86 web_colors : 'Palette colors',
    87 named_colors_tab : 'Named',
    88 named_colors : 'Named colors',
    89 color : 'Color:',
    90 color_name : 'Name:',
    91 is_email : 'The URL you entered seems to be an email address, do you want to add the required mailto: prefix?',
    92 is_external : 'The URL you entered seems to external link, do you want to add the required http:// prefix?'
     1tinyMCE.addI18n('en.advanced',{
     2style_select:"Styles",
     3font_size:"Font size",
     4fontdefault:"Font family",
     5block:"Format",
     6paragraph:"Paragraph",
     7div:"Div",
     8address:"Address",
     9pre:"Preformatted",
     10h1:"Heading 1",
     11h2:"Heading 2",
     12h3:"Heading 3",
     13h4:"Heading 4",
     14h5:"Heading 5",
     15h6:"Heading 6",
     16blockquote:"Blockquote",
     17code:"Code",
     18samp:"Code sample",
     19dt:"Definition term ",
     20dd:"Definition description",
     21bold_desc:"Bold (Ctrl+B)",
     22italic_desc:"Italic (Ctrl+I)",
     23underline_desc:"Underline (Ctrl+U)",
     24striketrough_desc:"Strikethrough",
     25justifyleft_desc:"Align left",
     26justifycenter_desc:"Align center",
     27justifyright_desc:"Align right",
     28justifyfull_desc:"Align full",
     29bullist_desc:"Unordered list",
     30numlist_desc:"Ordered list",
     31outdent_desc:"Outdent",
     32indent_desc:"Indent",
     33undo_desc:"Undo (Ctrl+Z)",
     34redo_desc:"Redo (Ctrl+Y)",
     35link_desc:"Insert/edit link",
     36unlink_desc:"Unlink",
     37image_desc:"Insert/edit image",
     38cleanup_desc:"Cleanup messy code",
     39code_desc:"Edit HTML Source",
     40sub_desc:"Subscript",
     41sup_desc:"Superscript",
     42hr_desc:"Insert horizontal ruler",
     43removeformat_desc:"Remove formatting",
     44custom1_desc:"Your custom description here",
     45forecolor_desc:"Select text color",
     46backcolor_desc:"Select background color",
     47charmap_desc:"Insert custom character",
     48visualaid_desc:"Toggle guidelines/invisible elements",
     49anchor_desc:"Insert/edit anchor",
     50cut_desc:"Cut",
     51copy_desc:"Copy",
     52paste_desc:"Paste",
     53image_props_desc:"Image properties",
     54newdocument_desc:"New document",
     55help_desc:"Help",
     56blockquote_desc:"Blockquote",
     57clipboard_msg:"Copy/Cut/Paste is not available in Mozilla and Firefox.\r\nDo you want more information about this issue?",
     58path:"Path",
     59newdocument:"Are you sure you want clear all contents?",
     60toolbar_focus:"Jump to tool buttons - Alt+Q, Jump to editor - Alt-Z, Jump to element path - Alt-X",
     61more_colors:"More colors"
    9362});
  • trunk/wp-includes/js/tinymce/themes/advanced/link.htm

    r5577 r6632  
     1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    12<html xmlns="http://www.w3.org/1999/xhtml">
    23<head>
    3     <title>{$lang_insert_link_title}</title>
    4     <script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
    5     <script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
    6     <script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script>
    7     <script language="javascript" type="text/javascript" src="../../utils/validate.js"></script>
    8     <script language="javascript" type="text/javascript" src="jscripts/link.js"></script>
     4    <title>{#advanced_dlg.link_title}</title>
     5    <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
     6    <script type="text/javascript" src="../../utils/mctabs.js"></script>
     7    <script type="text/javascript" src="../../utils/form_utils.js"></script>
     8    <script type="text/javascript" src="../../utils/validate.js"></script>
     9    <script type="text/javascript" src="js/link.js"></script>
    910    <base target="_self" />
    1011</head>
    11 <!-- WordPress: onload after the init();'); -->
    12 <body id="link" onload="tinyMCEPopup.executeOnLoad('init();');document.body.style.display='';document.getElementById('href').focus();" style="display: none">
    13 <form onsubmit="insertLink();return false;" action="#">
     12<body id="link" style="display: none">
     13<form onsubmit="LinkDialog.update();return false;" action="#">
    1414    <div class="tabs">
    1515        <ul>
    16             <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{$lang_insert_link_title}</a></span></li>
     16            <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advanced_dlg.link_title}</a></span></li>
    1717        </ul>
    1818    </div>
     
    2323        <table border="0" cellpadding="4" cellspacing="0">
    2424          <tr>
    25             <td nowrap="nowrap"><label for="href">{$lang_insert_link_url}</label></td>
     25            <td nowrap="nowrap"><label for="href">{#advanced_dlg.link_url}</label></td>
    2626            <td><table border="0" cellspacing="0" cellpadding="0">
    2727                  <tr>
    28                     <td><input id="href" name="href" type="text" value="" style="width: 200px" onchange="checkPrefix(this);" /></td>
     28                    <td><input id="href" name="href" type="text" value="" style="width: 200px" onchange="LinkDialog.checkPrefix(this);" /></td>
    2929                    <td id="hrefbrowsercontainer">&nbsp;</td>
    3030                  </tr>
    3131                </table></td>
    3232          </tr>
    33           <!-- Link list -->
    34           <script language="javascript">
    35             if (typeof(tinyMCELinkList) != "undefined" && tinyMCELinkList.length > 0) {
    36                 var html = "";
    37 
    38                 html += '<tr><td><label for="link_list">{$lang_link_list}</label></td>';
    39                 html += '<td><select id="link_list" name="link_list" style="width: 200px" onchange="this.form.href.value=this.options[this.selectedIndex].value;">';
    40                 html += '<option value="">---</option>';
    41 
    42                 for (var i=0; i<tinyMCELinkList.length; i++)
    43                     html += '<option value="' + tinyMCELinkList[i][1] + '">' + tinyMCELinkList[i][0] + '</option>';
    44 
    45                 html += '</select></td></tr>';
    46 
    47                 document.write(html);
    48             }
    49           </script>
    50           <!-- /Link list -->
     33          <tr>
     34            <td><label for="link_list">{#advanced_dlg.link_list}</label></td>
     35            <td><select id="link_list" name="link_list" onchange="document.getElementById('href').value=this.options[this.selectedIndex].value;"></select></td>
     36          </tr>
     37        <tr>
     38            <td><label id="targetlistlabel" for="targetlist">{#advanced_dlg.link_target}</label></td>
     39            <td><select id="target_list" name="target_list"></select></td>
     40        </tr>
    5141          <tr>
    52             <td nowrap="nowrap"><label for="target">{$lang_insert_link_target}</label></td>
    53             <td><select id="target" name="target" style="width: 200px">
    54                 <option value="_self">{$lang_insert_link_target_same}</option>
    55                 <option value="_blank">{$lang_insert_link_target_blank}</option>
    56                 <script language="javascript">
    57                     var html = "";
    58                     var targets = tinyMCE.getParam('theme_advanced_link_targets', '').split(';');
    59 
    60                     for (var i=0; i<targets.length; i++) {
    61                         var key, value;
    62 
    63                         if (targets[i] == "")
    64                             continue;
    65 
    66                         key = targets[i].split('=')[0];
    67                         value = targets[i].split('=')[1];
    68 
    69                         html += '<option value="' + value + '">' + key + '</option>';
    70                     }
    71 
    72                     document.write(html);
    73                 </script>
    74             </select></td>
     42            <td nowrap="nowrap"><label for="linktitle">{#advanced_dlg.link_titlefield}</label></td>
     43            <td><input id="linktitle" name="linktitle" type="text" value="" style="width: 200px" /></td>
    7544          </tr>
    76           <tr>
    77             <td nowrap="nowrap"><label for="linktitle">{$lang_theme_insert_link_titlefield}</label></td>
    78             <td><input id="linktitle" name="linktitle" type="text" value="" style="width: 200px"></td>
    79           </tr>
    80           <tr id="styleSelectRow">
    81             <td><label for="styleSelect">{$lang_class_name}</label></td>
    82             <td>
    83              <select id="styleSelect" name="styleSelect">
    84                 <option value="" selected>{$lang_theme_style_select}</option>
    85              </select></td>
    86           </tr>
     45            <tr>
     46                <td><label for="class_list">{#class_name}</label></td>
     47                <td><select id="class_list" name="class_list"></select></td>
     48            </tr>
    8749        </table>
    8850        </div>
     
    9052
    9153    <div class="mceActionPanel">
    92         <!-- WordPress: Buttons are reversed! -->
    9354        <div style="float: left">
    94             <input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
     55            <input type="button" id="insert" name="insert" value="{#insert}" onclick="LinkDialog.update();" />
    9556        </div>
    9657
    9758        <div style="float: right">
    98             <input type="submit" id="insert" name="insert" value="{$lang_insert}" onclick="insertLink();" />
     59            <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
    9960        </div>
    10061    </div>
  • trunk/wp-includes/js/tinymce/themes/advanced/source_editor.htm

    r5577 r6632  
    22<head>
    33    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    4     <title>{$lang_theme_code_title}</title>
    5     <script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
    6     <script language="javascript" type="text/javascript" src="jscripts/source_editor.js"></script>
     4    <title>{#advanced_dlg.code_title}</title>
     5    <script type="text/javascript" src="../../tiny_mce_popup.js"></script>
     6    <script type="text/javascript" src="js/source_editor.js"></script>
    77    <base target="_self" />
    88</head>
    9 <!-- WordPress: extra onload stuff is WP! -->
    10 <body onload="tinyMCEPopup.executeOnLoad('onLoadInit();');document.body.style.display='';document.getElementById('htmlSource').focus();" onresize="resizeInputs();" style="display: none">
     9<body onresize="resizeInputs();" style="display:none; overflow:hidden;">
    1110    <form name="source" onsubmit="saveContent();" action="#">
    12         <div style="float: left" class="title">{$lang_theme_code_title}</div>
     11        <div style="float: left" class="title">{#advanced_dlg.code_title}</div>
    1312
    1413        <div id="wrapline" style="float: right">
    15             <input type="checkbox" name="wraped" id="wraped" onclick="toggleWordWrap(this);" class="wordWrapCode" /><label for="wraped">{$lang_theme_code_wordwrap}</label>
     14            <input type="checkbox" name="wraped" id="wraped" onclick="toggleWordWrap(this);" class="wordWrapCode" /><label for="wraped">{#advanced_dlg.code_wordwrap}</label>
    1615        </div>
    1716
    1817        <br style="clear: both" />
    1918
    20         <textarea name="htmlSource" id="htmlSource" rows="15" cols="100" style="width: 100%; height: 100%; font-family: 'Courier New',Courier,monospace; font-size: 12px" dir="ltr" wrap="off"></textarea>
     19        <textarea name="htmlSource" id="htmlSource" rows="15" cols="100" style="width: 100%; height: 100%; font-family: 'Courier New',Courier,monospace; font-size: 12px;" dir="ltr" wrap="off"></textarea>
    2120
    2221        <div class="mceActionPanel">
    23             <!-- WordPress: reversed buttons! -->
    2422            <div style="float: left">
    25                 <input type="button" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" id="cancel" />
     23                <input type="button" name="insert" value="{#update}" onclick="saveContent();" id="insert" />
    2624            </div>
    2725
    2826            <div style="float: right">
    29                 <input type="submit" name="insert" value="{$lang_update}" onclick="saveContent();" id="insert" />
     27                <input type="button" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" id="cancel" />
    3028            </div>
    3129        </div>
  • trunk/wp-includes/js/tinymce/tiny_mce.js

    r6568 r6632  
    11
    2 /* file:jscripts/tiny_mce/classes/TinyMCE_Engine.class.js */
    3 
    4 function TinyMCE_Engine() {
    5     var ua;
    6 
    7     this.majorVersion = "2";
    8     this.minorVersion = "1.1.1";
    9     this.releaseDate = "2007-05-14";
    10 
    11     this.instances = [];
    12     this.switchClassCache = [];
    13     this.windowArgs = [];
    14     this.loadedFiles = [];
    15     this.pendingFiles = [];
    16     this.loadingIndex = 0;
    17     this.configs = [];
    18     this.currentConfig = 0;
    19     this.eventHandlers = [];
    20     this.log = [];
    21     this.undoLevels = [];
    22     this.undoIndex = 0;
    23     this.typingUndoIndex = -1;
    24     this.settings = [];
    25 
    26     // Browser check
    27     ua = navigator.userAgent;
    28     this.isMSIE = (navigator.appName == "Microsoft Internet Explorer");
    29     this.isMSIE5 = this.isMSIE && (ua.indexOf('MSIE 5') != -1);
    30     this.isMSIE5_0 = this.isMSIE && (ua.indexOf('MSIE 5.0') != -1);
    31     this.isMSIE7 = this.isMSIE && (ua.indexOf('MSIE 7') != -1);
    32     this.isGecko = ua.indexOf('Gecko') != -1; // Will also be true on Safari
    33     this.isSafari = ua.indexOf('Safari') != -1;
    34     this.isOpera = window['opera'] && opera.buildNumber ? true : false;
    35     this.isMac = ua.indexOf('Mac') != -1;
    36     this.isNS7 = ua.indexOf('Netscape/7') != -1;
    37     this.isNS71 = ua.indexOf('Netscape/7.1') != -1;
    38     this.dialogCounter = 0;
    39     this.plugins = [];
    40     this.themes = [];
    41     this.menus = [];
    42     this.loadedPlugins = [];
    43     this.buttonMap = [];
    44     this.isLoaded = false;
    45 
    46     // Fake MSIE on Opera and if Opera fakes IE, Gecko or Safari cancel those
    47     if (this.isOpera) {
    48         this.isMSIE = true;
    49         this.isGecko = false;
    50         this.isSafari =  false;
    51     }
    52 
    53     this.isIE = this.isMSIE;
    54     this.isRealIE = this.isMSIE && !this.isOpera;
    55 
    56     // TinyMCE editor id instance counter
    57     this.idCounter = 0;
    58 };
    59 
    60 TinyMCE_Engine.prototype = {
    61     init : function(settings) {
    62         var theme, nl, baseHREF = "", i, cssPath, entities, h, p, src, elements = [], head;
    63 
    64         // IE 5.0x is no longer supported since 5.5, 6.0 and 7.0 now exists. We can't support old browsers forever, sorry.
    65         if (this.isMSIE5_0)
     2/* file:jscripts/tiny_mce/classes/tinymce.js */
     3
     4var tinymce = {
     5    majorVersion : '3',
     6    minorVersion : '0rc2',
     7    releaseDate : '2008-01-xx',
     8
     9    _init : function() {
     10        var t = this, ua = navigator.userAgent, i, nl, n, base;
     11
     12        // Browser checks
     13        t.isOpera = window.opera && opera.buildNumber;
     14        t.isWebKit = /WebKit/.test(ua);
     15        t.isOldWebKit = t.isWebKit && !window.getSelection().getRangeAt;
     16        t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(navigator.appName);
     17        t.isIE6 = t.isIE && /MSIE [56]/.test(ua);
     18        t.isGecko = !t.isWebKit && /Gecko/.test(ua);
     19//      t.isGecko3 = t.isGecko && /(Firefox|Minefield)\/[3-9]/.test(ua);
     20        t.isMac = ua.indexOf('Mac') != -1;
     21
     22        // TinyMCE .NET webcontrol might be setting the values for TinyMCE
     23        if (window.tinyMCEPreInit) {
     24            t.suffix = tinyMCEPreInit.suffix;
     25            t.baseURL = tinyMCEPreInit.base;
    6626            return;
    67 
    68         this.settings = settings;
    69 
    70         // Check if valid browser has execcommand support
    71         if (typeof(document.execCommand) == 'undefined')
     27        }
     28
     29        // Get suffix and base
     30        t.suffix = '';
     31
     32        // If base element found, add that infront of baseURL
     33        nl = document.getElementsByTagName('base');
     34        for (i=0; i<nl.length; i++) {
     35            if (nl[i].href)
     36                base = nl[i].href;
     37        }
     38
     39        function getBase(n) {
     40            if (n.src && /tiny_mce(|_dev|_src|_gzip|_jquery|_prototype).js/.test(n.src)) {
     41                if (/_(src|dev)\.js/g.test(n.src))
     42                    t.suffix = '_src';
     43
     44                t.baseURL = n.src.substring(0, n.src.lastIndexOf('/'));
     45
     46                // If path to script is relative and a base href was found add that one infront
     47                if (base && t.baseURL.indexOf('://') == -1)
     48                    t.baseURL = base + t.baseURL;
     49
     50                return t.baseURL;
     51            }
     52
     53            return null;
     54        };
     55
     56        // Check document
     57        nl = document.getElementsByTagName('script');
     58        for (i=0; i<nl.length; i++) {
     59            if (getBase(nl[i]))
     60                return;
     61        }
     62
     63        // Check head
     64        n = document.getElementsByTagName('head')[0];
     65        if (n) {
     66            nl = n.getElementsByTagName('script');
     67            for (i=0; i<nl.length; i++) {
     68                if (getBase(nl[i]))
     69                    return;
     70            }
     71        }
     72
     73        return;
     74    },
     75
     76    is : function(o, t) {
     77        var n = typeof(o);
     78
     79        if (!t)
     80            return n != 'undefined';
     81
     82        if (t == 'array' && (o instanceof Array))
     83            return true;
     84
     85        return n == t;
     86    },
     87
     88    // #if !jquery
     89
     90    each : function(o, cb, s) {
     91        var n, l;
     92
     93        if (!o)
     94            return 0;
     95
     96        s = s || o;
     97
     98        if (typeof(o.length) != 'undefined') {
     99            // Indexed arrays, needed for Safari
     100            for (n=0, l = o.length; n<l; n++) {
     101                if (cb.call(s, o[n], n, o) === false)
     102                    return 0;
     103            }
     104        } else {
     105            // Hashtables
     106            for (n in o) {
     107                if (o.hasOwnProperty(n)) {
     108                    if (cb.call(s, o[n], n, o) === false)
     109                        return 0;
     110                }
     111            }
     112        }
     113
     114        return 1;
     115    },
     116
     117    map : function(a, f) {
     118        var o = [];
     119
     120        tinymce.each(a, function(v) {
     121            o.push(f(v));
     122        });
     123
     124        return o;
     125    },
     126
     127    grep : function(a, f) {
     128        var o = [];
     129
     130        tinymce.each(a, function(v) {
     131            if (!f || f(v))
     132                o.push(v);
     133        });
     134
     135        return o;
     136    },
     137
     138    inArray : function(a, v) {
     139        var i, l;
     140
     141        if (a) {
     142            for (i = 0, l = a.length; i < l; i++) {
     143                if (a[i] === v)
     144                    return i;
     145            }
     146        }
     147
     148        return -1;
     149    },
     150
     151    extend : function(o, e) {
     152        var i, a = arguments;
     153
     154        for (i=1; i<a.length; i++) {
     155            e = a[i];
     156
     157            tinymce.each(e, function(v, n) {
     158                if (typeof(v) !== 'undefined')
     159                    o[n] = v;
     160            });
     161        }
     162
     163        return o;
     164    },
     165
     166    trim : function(s) {
     167        return (s ? '' + s : '').replace(/^\s*|\s*$/g, '');
     168    },
     169
     170    // #endif
     171
     172    create : function(s, p) {
     173        var t = this, sp, ns, cn, scn, c, de = 0;
     174
     175        // Parse : <prefix> <class>:<super class>
     176        s = /^((static) )?([\w.]+)(:([\w.]+))?/.exec(s);
     177        cn = s[3].match(/(^|\.)(\w+)$/i)[2]; // Class name
     178
     179        // Create namespace for new class
     180        ns = t.createNS(s[3].replace(/\.\w+$/, ''));
     181
     182        // Class already exists
     183        if (ns[cn])
    72184            return;
    73185
    74         // Get script base path
    75         if (!tinyMCE.baseURL) {
    76             // Search through head
    77             head = document.getElementsByTagName('head')[0];
    78 
    79             if (head) {
    80                 for (i=0, nl = head.getElementsByTagName('script'); i<nl.length; i++)
    81                     elements.push(nl[i]);
    82             }
    83 
    84             // Search through rest of document
    85             for (i=0, nl = document.getElementsByTagName('script'); i<nl.length; i++)
    86                 elements.push(nl[i]);
    87 
    88             // If base element found, add that infront of baseURL
    89             nl = document.getElementsByTagName('base');
    90             for (i=0; i<nl.length; i++) {
    91                 if (nl[i].href)
    92                     baseHREF = nl[i].href;
    93             }
    94 
    95             for (i=0; i<elements.length; i++) {
    96                 if (elements[i].src && (elements[i].src.indexOf("tiny_mce.js") != -1 || elements[i].src.indexOf("tiny_mce_dev.js") != -1 || elements[i].src.indexOf("tiny_mce_src.js") != -1 || elements[i].src.indexOf("tiny_mce_gzip") != -1)) {
    97                     src = elements[i].src;
    98 
    99                     tinyMCE.srcMode = (src.indexOf('_src') != -1 || src.indexOf('_dev') != -1) ? '_src' : '';
    100                     tinyMCE.gzipMode = src.indexOf('_gzip') != -1;
    101                     src = src.substring(0, src.lastIndexOf('/'));
    102 
    103                     if (settings.exec_mode == "src" || settings.exec_mode == "normal")
    104                         tinyMCE.srcMode = settings.exec_mode == "src" ? '_src' : '';
    105 
    106                     // Force it absolute if page has a base href
    107                     if (baseHREF !== '' && src.indexOf('://') == -1)
    108                         tinyMCE.baseURL = baseHREF + src;
    109                     else
    110                         tinyMCE.baseURL = src;
    111 
    112                     break;
    113                 }
    114             }
     186        // Make pure static class
     187        if (s[2] == 'static') {
     188            ns[cn] = p;
     189
     190            if (this.onCreate)
     191                this.onCreate(s[2], s[3], ns[cn]);
     192
     193            return;
    115194        }
    116195
    117         // Get document base path
    118         this.documentBasePath = document.location.href;
    119         if (this.documentBasePath.indexOf('?') != -1)
    120             this.documentBasePath = this.documentBasePath.substring(0, this.documentBasePath.indexOf('?'));
    121         this.documentURL = this.documentBasePath;
    122         this.documentBasePath = this.documentBasePath.substring(0, this.documentBasePath.lastIndexOf('/'));
    123 
    124         // If not HTTP absolute
    125         if (tinyMCE.baseURL.indexOf('://') == -1 && tinyMCE.baseURL.charAt(0) != '/') {
    126             // If site absolute
    127             tinyMCE.baseURL = this.documentBasePath + "/" + tinyMCE.baseURL;
     196        // Create default constructor
     197        if (!p[cn]) {
     198            p[cn] = function() {};
     199            de = 1;
    128200        }
    129201
    130         // Set default values on settings
    131         this._def("mode", "none");
    132         this._def("theme", "advanced");
    133         this._def("plugins", "", true);
    134         this._def("language", "en");
    135         this._def("docs_language", this.settings.language);
    136         this._def("elements", "");
    137         this._def("textarea_trigger", "mce_editable");
    138         this._def("editor_selector", "");
    139         this._def("editor_deselector", "mceNoEditor");
    140         this._def("valid_elements", "+a[id|style|rel|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],-strong/-b[class|style],-em/-i[class|style],-strike[class|style],-u[class|style],#p[id|style|dir|class|align],-ol[class|style],-ul[class|style],-li[class|style],br,img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|alt=|title|hspace|vspace|width|height|align],-sub[style|class],-sup[style|class],-blockquote[dir|style],-table[border=0|cellspacing|cellpadding|width|height|class|align|summary|style|dir|id|lang|bgcolor|background|bordercolor],-tr[id|lang|dir|class|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor],tbody[id|class],thead[id|class],tfoot[id|class],#td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],-span[style|class|align],-pre[class|align|style],address[class|align|style],-h1[id|style|dir|class|align],-h2[id|style|dir|class|align],-h3[id|style|dir|class|align],-h4[id|style|dir|class|align],-h5[id|style|dir|class|align],-h6[id|style|dir|class|align],hr[class|style],-font[face|size|style|id|class|dir|color],dd[id|class|title|style|dir|lang],dl[id|class|title|style|dir|lang],dt[id|class|title|style|dir|lang],cite[title|id|class|style|dir|lang],abbr[title|id|class|style|dir|lang],acronym[title|id|class|style|dir|lang],del[title|id|class|style|dir|lang|datetime|cite],ins[title|id|class|style|dir|lang|datetime|cite]");
    141         this._def("extended_valid_elements", "");
    142         this._def("invalid_elements", "");
    143         this._def("encoding", "");
    144         this._def("urlconverter_callback", tinyMCE.getParam("urlconvertor_callback", "TinyMCE_Engine.prototype.convertURL"));
    145         this._def("save_callback", "");
    146         this._def("force_br_newlines", false);
    147         this._def("force_p_newlines", true);
    148         this._def("add_form_submit_trigger", true);
    149         this._def("relative_urls", true);
    150         this._def("remove_script_host", true);
    151         this._def("focus_alert", true);
    152         this._def("document_base_url", this.documentURL);
    153         this._def("visual", true);
    154         this._def("visual_table_class", "mceVisualAid");
    155         this._def("setupcontent_callback", "");
    156         this._def("fix_content_duplication", true);
    157         this._def("custom_undo_redo", true);
    158         this._def("custom_undo_redo_levels", -1);
    159         this._def("custom_undo_redo_keyboard_shortcuts", true);
    160         this._def("custom_undo_redo_restore_selection", true);
    161         this._def("custom_undo_redo_global", false);
    162         this._def("verify_html", true);
    163         this._def("apply_source_formatting", false);
    164         this._def("directionality", "ltr");
    165         this._def("cleanup_on_startup", false);
    166         this._def("inline_styles", false);
    167         this._def("convert_newlines_to_brs", false);
    168         this._def("auto_reset_designmode", true);
    169         this._def("entities", "39,#39,160,nbsp,161,iexcl,162,cent,163,pound,164,curren,165,yen,166,brvbar,167,sect,168,uml,169,copy,170,ordf,171,laquo,172,not,173,shy,174,reg,175,macr,176,deg,177,plusmn,178,sup2,179,sup3,180,acute,181,micro,182,para,183,middot,184,cedil,185,sup1,186,ordm,187,raquo,188,frac14,189,frac12,190,frac34,191,iquest,192,Agrave,193,Aacute,194,Acirc,195,Atilde,196,Auml,197,Aring,198,AElig,199,Ccedil,200,Egrave,201,Eacute,202,Ecirc,203,Euml,204,Igrave,205,Iacute,206,Icirc,207,Iuml,208,ETH,209,Ntilde,210,Ograve,211,Oacute,212,Ocirc,213,Otilde,214,Ouml,215,times,216,Oslash,217,Ugrave,218,Uacute,219,Ucirc,220,Uuml,221,Yacute,222,THORN,223,szlig,224,agrave,225,aacute,226,acirc,227,atilde,228,auml,229,aring,230,aelig,231,ccedil,232,egrave,233,eacute,234,ecirc,235,euml,236,igrave,237,iacute,238,icirc,239,iuml,240,eth,241,ntilde,242,ograve,243,oacute,244,ocirc,245,otilde,246,ouml,247,divide,248,oslash,249,ugrave,250,uacute,251,ucirc,252,uuml,253,yacute,254,thorn,255,yuml,402,fnof,913,Alpha,914,Beta,915,Gamma,916,Delta,917,Epsilon,918,Zeta,919,Eta,920,Theta,921,Iota,922,Kappa,923,Lambda,924,Mu,925,Nu,926,Xi,927,Omicron,928,Pi,929,Rho,931,Sigma,932,Tau,933,Upsilon,934,Phi,935,Chi,936,Psi,937,Omega,945,alpha,946,beta,947,gamma,948,delta,949,epsilon,950,zeta,951,eta,952,theta,953,iota,954,kappa,955,lambda,956,mu,957,nu,958,xi,959,omicron,960,pi,961,rho,962,sigmaf,963,sigma,964,tau,965,upsilon,966,phi,967,chi,968,psi,969,omega,977,thetasym,978,upsih,982,piv,8226,bull,8230,hellip,8242,prime,8243,Prime,8254,oline,8260,frasl,8472,weierp,8465,image,8476,real,8482,trade,8501,alefsym,8592,larr,8593,uarr,8594,rarr,8595,darr,8596,harr,8629,crarr,8656,lArr,8657,uArr,8658,rArr,8659,dArr,8660,hArr,8704,forall,8706,part,8707,exist,8709,empty,8711,nabla,8712,isin,8713,notin,8715,ni,8719,prod,8721,sum,8722,minus,8727,lowast,8730,radic,8733,prop,8734,infin,8736,ang,8743,and,8744,or,8745,cap,8746,cup,8747,int,8756,there4,8764,sim,8773,cong,8776,asymp,8800,ne,8801,equiv,8804,le,8805,ge,8834,sub,8835,sup,8836,nsub,8838,sube,8839,supe,8853,oplus,8855,otimes,8869,perp,8901,sdot,8968,lceil,8969,rceil,8970,lfloor,8971,rfloor,9001,lang,9002,rang,9674,loz,9824,spades,9827,clubs,9829,hearts,9830,diams,34,quot,38,amp,60,lt,62,gt,338,OElig,339,oelig,352,Scaron,353,scaron,376,Yuml,710,circ,732,tilde,8194,ensp,8195,emsp,8201,thinsp,8204,zwnj,8205,zwj,8206,lrm,8207,rlm,8211,ndash,8212,mdash,8216,lsquo,8217,rsquo,8218,sbquo,8220,ldquo,8221,rdquo,8222,bdquo,8224,dagger,8225,Dagger,8240,permil,8249,lsaquo,8250,rsaquo,8364,euro", true);
    170         this._def("entity_encoding", "named");
    171         this._def("cleanup_callback", "");
    172         this._def("add_unload_trigger", true);
    173         this._def("ask", false);
    174         this._def("nowrap", false);
    175         this._def("auto_resize", false);
    176         this._def("auto_focus", false);
    177         this._def("cleanup", true);
    178         this._def("remove_linebreaks", true);
    179         this._def("button_tile_map", false);
    180         this._def("submit_patch", true);
    181         this._def("browsers", "msie,safari,gecko,opera", true);
    182         this._def("dialog_type", "window");
    183         this._def("accessibility_warnings", true);
    184         this._def("accessibility_focus", true);
    185         this._def("merge_styles_invalid_parents", "");
    186         this._def("force_hex_style_colors", true);
    187         this._def("trim_span_elements", true);
    188         this._def("convert_fonts_to_spans", false);
    189         this._def("doctype", '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">');
    190         this._def("font_size_classes", '');
    191         this._def("font_size_style_values", 'xx-small,x-small,small,medium,large,x-large,xx-large', true);
    192         this._def("event_elements", 'a,img', true);
    193         this._def("convert_urls", true);
    194         this._def("table_inline_editing", false);
    195         this._def("object_resizing", true);
    196         this._def("custom_shortcuts", true);
    197         this._def("convert_on_click", false);
    198         this._def("content_css", '');
    199         this._def("fix_list_elements", true);
    200         this._def("fix_table_elements", false);
    201         this._def("strict_loading_mode", document.contentType == 'application/xhtml+xml');
    202         this._def("hidden_tab_class", '');
    203         this._def("display_tab_class", '');
    204         this._def("gecko_spellcheck", false);
    205         this._def("hide_selects_on_submit", true);
    206         this._def("forced_root_block", false);
    207         this._def("remove_trailing_nbsp", false);
    208 
    209         // Force strict loading mode to false on non Gecko browsers
    210         if (this.isMSIE && !this.isOpera)
    211             this.settings.strict_loading_mode = false;
    212 
    213         // Browser check IE
    214         if (this.isMSIE && this.settings.browsers.indexOf('msie') == -1)
    215             return;
    216 
    217         // Browser check Gecko
    218         if (this.isGecko && this.settings.browsers.indexOf('gecko') == -1)
    219             return;
    220 
    221         // Browser check Safari
    222         if (this.isSafari && this.settings.browsers.indexOf('safari') == -1)
    223             return;
    224 
    225         // Browser check Opera
    226         if (this.isOpera && this.settings.browsers.indexOf('opera') == -1)
    227             return;
    228 
    229         // If not super absolute make it so
    230         baseHREF = tinyMCE.settings.document_base_url;
    231         h = document.location.href;
    232         p = h.indexOf('://');
    233         if (p > 0 && document.location.protocol != "file:") {
    234             p = h.indexOf('/', p + 3);
    235             h = h.substring(0, p);
    236 
    237             if (baseHREF.indexOf('://') == -1)
    238                 baseHREF = h + baseHREF;
    239 
    240             tinyMCE.settings.document_base_url = baseHREF;
    241             tinyMCE.settings.document_base_prefix = h;
     202        // Add constructor and methods
     203        ns[cn] = p[cn];
     204        t.extend(ns[cn].prototype, p);
     205
     206        // Extend
     207        if (s[5]) {
     208            sp = t.resolve(s[5]).prototype;
     209            scn = s[5].match(/\.(\w+)$/i)[1]; // Class name
     210
     211            // Extend constructor
     212            c = ns[cn];
     213            if (de) {
     214                // Add passthrough constructor
     215                ns[cn] = function() {
     216                    return sp[scn].apply(this, arguments);
     217                };
     218            } else {
     219                // Add inherit constructor
     220                ns[cn] = function() {
     221                    this.parent = sp[scn];
     222                    return c.apply(this, arguments);
     223                };
     224            }
     225            ns[cn].prototype[cn] = ns[cn];
     226
     227            // Add super methods
     228            t.each(sp, function(f, n) {
     229                if (n != scn)
     230                    ns[cn].prototype[n] = sp[n];
     231            });
     232
     233            // Add overridden methods
     234            t.each(p, function(f, n) {
     235                // Extend methods if needed
     236                if (sp[n]) {
     237                    ns[cn].prototype[n] = function() {
     238                        this.parent = sp[n];
     239                        return f.apply(this, arguments);
     240                    };
     241                } else {
     242                    if (n != cn)
     243                        ns[cn].prototype[n] = f;
     244                }
     245            });
    242246        }
    243247
    244         // Trim away query part
    245         if (baseHREF.indexOf('?') != -1)
    246             baseHREF = baseHREF.substring(0, baseHREF.indexOf('?'));
    247 
    248         this.settings.base_href = baseHREF.substring(0, baseHREF.lastIndexOf('/')) + "/";
    249 
    250         theme = this.settings.theme;
    251         this.inlineStrict = 'A|BR|SPAN|BDO|MAP|OBJECT|IMG|TT|I|B|BIG|SMALL|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|#text|#comment';
    252         this.inlineTransitional = 'A|BR|SPAN|BDO|OBJECT|APPLET|IMG|MAP|IFRAME|TT|I|B|U|S|STRIKE|BIG|SMALL|FONT|BASEFONT|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|INPUT|SELECT|TEXTAREA|LABEL|BUTTON|#text|#comment';
    253         this.blockElms = 'H[1-6]|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|FORM|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP';
    254         this.blockRegExp = new RegExp("^(" + this.blockElms + ")$", "i");
    255         this.posKeyCodes = [13,45,36,35,33,34,37,38,39,40];
    256         this.uniqueURL = 'javascript:void(091039730);'; // Make unique URL non real URL
    257         this.uniqueTag = '<div id="mceTMPElement" style="display: none">TMP</div>';
    258         this.callbacks = ['onInit', 'getInfo', 'getEditorTemplate', 'setupContent', 'onChange', 'onPageLoad', 'handleNodeChange', 'initInstance', 'execCommand', 'getControlHTML', 'handleEvent', 'cleanup', 'removeInstance'];
    259 
    260         // Theme url
    261         this.settings.theme_href = tinyMCE.baseURL + "/themes/" + theme;
    262 
    263         if (!tinyMCE.isIE || tinyMCE.isOpera)
    264             this.settings.force_br_newlines = false;
    265 
    266         if (tinyMCE.getParam("popups_css", false)) {
    267             cssPath = tinyMCE.getParam("popups_css", "");
    268 
    269             // Is relative
    270             if (cssPath.indexOf('://') == -1 && cssPath.charAt(0) != '/')
    271                 this.settings.popups_css = this.documentBasePath + "/" + cssPath;
    272             else
    273                 this.settings.popups_css = cssPath;
    274         } else
    275             this.settings.popups_css = tinyMCE.baseURL + "/themes/" + theme + "/css/editor_popup.css";
    276 
    277         if (tinyMCE.getParam("editor_css", false)) {
    278             cssPath = tinyMCE.getParam("editor_css", "");
    279 
    280             // Is relative
    281             if (cssPath.indexOf('://') == -1 && cssPath.charAt(0) != '/')
    282                 this.settings.editor_css = this.documentBasePath + "/" + cssPath;
    283             else
    284                 this.settings.editor_css = cssPath;
    285         } else {
    286             if (this.settings.editor_css !== '')
    287                 this.settings.editor_css = tinyMCE.baseURL + "/themes/" + theme + "/css/editor_ui.css";
    288         }
    289 
    290         // Only do this once
    291         if (this.configs.length == 0) {
    292             if (typeof(TinyMCECompressed) == "undefined") {
    293                 tinyMCE.addEvent(window, "DOMContentLoaded", TinyMCE_Engine.prototype.onLoad);
    294 
    295                 if (tinyMCE.isRealIE) {
    296                     if (document.body)
    297                         tinyMCE.addEvent(document.body, "readystatechange", TinyMCE_Engine.prototype.onLoad);
    298                     else
    299                         tinyMCE.addEvent(document, "readystatechange", TinyMCE_Engine.prototype.onLoad);
    300                 }
    301 
    302                 tinyMCE.addEvent(window, "load", TinyMCE_Engine.prototype.onLoad);
    303                 tinyMCE._addUnloadEvents();
    304             }
    305         }
    306 
    307         this.loadScript(tinyMCE.baseURL + '/themes/' + this.settings.theme + '/editor_template' + tinyMCE.srcMode + '.js');
    308         this.loadScript(tinyMCE.baseURL + '/langs/' + this.settings.language +  '.js');
    309         this.loadCSS(this.settings.editor_css);
    310 
    311         // Add plugins
    312         p = tinyMCE.getParam('plugins', '', true, ',');
    313         if (p.length > 0) {
    314             for (i=0; i<p.length; i++) {
    315                 if (p[i].charAt(0) != '-')
    316                     this.loadScript(tinyMCE.baseURL + '/plugins/' + p[i] + '/editor_plugin' + tinyMCE.srcMode + '.js');
    317             }
    318         }
    319 
    320         // Setup entities
    321         if (tinyMCE.getParam('entity_encoding') == 'named') {
    322             settings.cleanup_entities = [];
    323             entities = tinyMCE.getParam('entities', '', true, ',');
    324             for (i=0; i<entities.length; i+=2)
    325                 settings.cleanup_entities['c' + entities[i]] = entities[i+1];
    326         }
    327 
    328         // Save away this config
    329         settings.index = this.configs.length;
    330         this.configs[this.configs.length] = settings;
    331 
    332         // Start loading first one in chain
    333         this.loadNextScript();
    334 
    335         // Force flicker free CSS backgrounds in IE
    336         if (this.isIE && !this.isOpera) {
    337             try {
    338                 document.execCommand('BackgroundImageCache', false, true);
    339             } catch (e) {
    340                 // Ignore
    341             }
    342         }
    343 
    344         // Setup XML encoding regexps
    345         this.xmlEncodeRe = new RegExp('[<>&"]', 'g');
     248        // Add static methods
     249        t.each(p['static'], function(f, n) {
     250            ns[cn][n] = f;
     251        });
     252
     253        if (this.onCreate)
     254            this.onCreate(s[2], s[3], ns[cn].prototype);
    346255    },
    347256
    348     _addUnloadEvents : function() {
    349         var st = tinyMCE.settings.add_unload_trigger;
    350 
    351         if (tinyMCE.isIE) {
    352             if (st) {
    353                 tinyMCE.addEvent(window, "unload", TinyMCE_Engine.prototype.unloadHandler);
    354                 tinyMCE.addEvent(window.document, "beforeunload", TinyMCE_Engine.prototype.unloadHandler);
    355             }
    356         } else {
    357             if (st)
    358                 tinyMCE.addEvent(window, "unload", function () {tinyMCE.triggerSave(true, true);});
     257    walk : function(o, f, n, s) {
     258        s = s || this;
     259
     260        if (o) {
     261            if (n)
     262                o = o[n];
     263
     264            tinymce.each(o, function(o, i) {
     265                if (f.call(s, o, i, n) === false)
     266                    return false;
     267
     268                tinymce.walk(o, f, n, s);
     269            });
    359270        }
    360271    },
    361272
    362     _def : function(key, def_val, t) {
    363         var v = tinyMCE.getParam(key, def_val);
    364 
    365         v = t ? v.replace(/\s+/g, "") : v;
    366 
    367         this.settings[key] = v;
     273    createNS : function(n, o) {
     274        var i, v;
     275
     276        o = o || window;
     277
     278        n = n.split('.');
     279        for (i=0; i<n.length; i++) {
     280            v = n[i];
     281
     282            if (!o[v])
     283                o[v] = {};
     284
     285            o = o[v];
     286        }
     287
     288        return o;
    368289    },
    369290
    370     hasPlugin : function(n) {
    371         return typeof(this.plugins[n]) != "undefined" && this.plugins[n] != null;
     291    resolve : function(n, o) {
     292        var i, l;
     293
     294        o = o || window;
     295
     296        n = n.split('.');
     297        for (i=0, l = n.length; i<l; i++) {
     298            o = o[n[i]];
     299
     300            if (!o)
     301                break;
     302        }
     303
     304        return o;
    372305    },
    373306
    374     addPlugin : function(n, p) {
    375         var op = this.plugins[n];
    376 
    377         // Use the previous plugin object base URL used when loading external plugins
    378         p.baseURL = op ? op.baseURL : tinyMCE.baseURL + "/plugins/" + n;
    379         this.plugins[n] = p;
    380 
    381         this.loadNextScript();
     307    addUnload : function(f, s) {
     308        var t = this, w = window, unload;
     309
     310        f = {func : f, scope : s || this};
     311
     312        if (!t.unloads) {
     313            unload = function() {
     314                var li = t.unloads, o, n;
     315
     316                // Call unload handlers
     317                for (n in li) {
     318                    o = li[n];
     319
     320                    if (o && o.func)
     321                        o.func.call(o.scope);
     322                }
     323
     324                // Detach unload function
     325                if (w.detachEvent)
     326                    w.detachEvent('onunload', unload);
     327                else if (w.removeEventListener)
     328                    w.removeEventListener('unload', unload, false);
     329
     330                // Destroy references
     331                o = li = w = unload = null;
     332
     333                // Run garbarge collector on IE
     334                if (window.CollectGarbage)
     335                    window.CollectGarbage();
     336            };
     337
     338            // Attach unload handler
     339            if (w.attachEvent)
     340                w.attachEvent('onunload', unload);
     341            else if (w.addEventListener)
     342                w.addEventListener('unload', unload, false);
     343
     344            // Setup initial unload handler array
     345            t.unloads = [f];
     346        } else
     347            t.unloads.push(f);
     348
     349        return f;
    382350    },
    383351
    384     setPluginBaseURL : function(n, u) {
    385         var op = this.plugins[n];
    386 
    387         if (op)
    388             op.baseURL = u;
    389         else
    390             this.plugins[n] = {baseURL : u};
     352    removeUnload : function(f) {
     353        var u = this.unloads, r = null;
     354
     355        tinymce.each(u, function(o, i) {
     356            if (o && o.func == f) {
     357                u.splice(i, 1);
     358                r = f;
     359                return false;
     360            }
     361        });
     362
     363        return r;
     364    }
     365
     366    };
     367
     368// Required for GZip AJAX loading
     369window.tinymce = tinymce;
     370
     371// Initialize the API
     372tinymce._init();
     373
     374/* file:jscripts/tiny_mce/classes/adapter/jquery/adapter.js */
     375
     376
     377/* file:jscripts/tiny_mce/classes/adapter/prototype/adapter.js */
     378
     379
     380/* file:jscripts/tiny_mce/classes/util/Dispatcher.js */
     381
     382tinymce.create('tinymce.util.Dispatcher', {
     383    scope : null,
     384    listeners : null,
     385
     386    Dispatcher : function(s) {
     387        this.scope = s || this;
     388        this.listeners = [];
    391389    },
    392390
    393     loadPlugin : function(n, u) {
    394         u = u.indexOf('.js') != -1 ? u.substring(0, u.lastIndexOf('/')) : u;
    395         u = u.charAt(u.length-1) == '/' ? u.substring(0, u.length-1) : u;
    396         this.plugins[n] = {baseURL : u};
    397         this.loadScript(u + "/editor_plugin" + (tinyMCE.srcMode ? '_src' : '') + ".js");
     391    add : function(cb, s) {
     392        this.listeners.push({cb : cb, scope : s || this.scope});
     393
     394        return cb;
    398395    },
    399396
    400     hasTheme : function(n) {
    401         return typeof(this.themes[n]) != "undefined" && this.themes[n] != null;
     397    addToTop : function(cb, s) {
     398        this.listeners.unshift({cb : cb, scope : s || this.scope});
     399
     400        return cb;
    402401    },
    403402
    404     addTheme : function(n, t) {
    405         this.themes[n] = t;
    406 
    407         this.loadNextScript();
     403    remove : function(cb) {
     404        var l = this.listeners, o = null;
     405
     406        tinymce.each(l, function(c, i) {
     407            if (cb == c.cb) {
     408                o = cb;
     409                l.splice(i, 1);
     410                return false;
     411            }
     412        });
     413
     414        return o;
    408415    },
    409416
    410     addMenu : function(n, m) {
    411         this.menus[n] = m;
    412     },
    413 
    414     hasMenu : function(n) {
    415         return typeof(this.plugins[n]) != "undefined" && this.plugins[n] != null;
    416     },
    417 
    418     loadScript : function(url) {
    419         var i;
    420 
    421         for (i=0; i<this.loadedFiles.length; i++) {
    422             if (this.loadedFiles[i] == url)
     417    dispatch : function() {
     418        var s, a = arguments;
     419
     420        tinymce.each(this.listeners, function(c) {
     421            return s = c.cb.apply(c.scope, a);
     422        });
     423
     424        return s;
     425    }
     426
     427    });
     428
     429/* file:jscripts/tiny_mce/classes/util/URI.js */
     430
     431(function() {
     432    var each = tinymce.each;
     433
     434    tinymce.create('tinymce.util.URI', {
     435        URI : function(u, s) {
     436            var t = this, o, a, b;
     437
     438            // Default settings
     439            s = t.settings = s || {};
     440
     441            // Strange app protocol or local anchor
     442            if (/^(mailto|news|javascript|about):/i.test(u) || /^\s*#/.test(u)) {
     443                t.source = u;
    423444                return;
    424         }
    425 
    426         if (tinyMCE.settings.strict_loading_mode)
    427             this.pendingFiles[this.pendingFiles.length] = url;
    428         else
    429             document.write('<sc'+'ript language="javascript" type="text/javascript" src="' + url + '"></script>');
    430 
    431         this.loadedFiles[this.loadedFiles.length] = url;
    432     },
    433 
    434     loadNextScript : function() {
    435         var d = document, se;
    436 
    437         if (!tinyMCE.settings.strict_loading_mode)
    438             return;
    439 
    440         if (this.loadingIndex < this.pendingFiles.length) {
    441             se = d.createElementNS('http://www.w3.org/1999/xhtml', 'script');
    442             se.setAttribute('language', 'javascript');
    443             se.setAttribute('type', 'text/javascript');
    444             se.setAttribute('src', this.pendingFiles[this.loadingIndex++]);
    445 
    446             d.getElementsByTagName("head")[0].appendChild(se);
    447         } else
    448             this.loadingIndex = -1; // Done with loading
    449     },
    450 
    451     loadCSS : function(url) {
    452         var ar = url.replace(/\s+/, '').split(',');
    453         var lflen = 0, csslen = 0, skip = false;
    454         var x = 0, i = 0, nl, le;
    455 
    456         for (x = 0,csslen = ar.length; x<csslen; x++) {
    457             if (ar[x] != null && ar[x] != 'null' && ar[x].length > 0) {
    458                 /* Make sure it doesn't exist. */
    459                 for (i=0, lflen=this.loadedFiles.length; i<lflen; i++) {
    460                     if (this.loadedFiles[i] == ar[x]) {
    461                         skip = true;
     445            }
     446
     447            // Absolute path with no host, fake host and protocol
     448            if (u.indexOf('/') === 0 && u.indexOf('//') !== 0)
     449                u = (s.base_uri ? s.base_uri.protocol || 'http' : 'http') + '://mce_host' + u;
     450
     451            // Relative path
     452            if (u.indexOf('://') === -1 && u.indexOf('//') !== 0)
     453                u = (s.base_uri.protocol || 'http') + '://mce_host' + t.toAbsPath(s.base_uri.path, u);
     454
     455            // Parse URL (Credits goes to Steave, http://blog.stevenlevithan.com/archives/parseuri)
     456            u = u.replace(/@@/g, '(mce_at)'); // Zope 3 workaround, they use @@something
     457            u = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(u);
     458            each(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], function(v, i) {
     459                var s = u[i];
     460
     461                // Zope 3 workaround, they use @@something
     462                if (s)
     463                    s = s.replace(/\(mce_at\)/g, '@@');
     464
     465                t[v] = s;
     466            });
     467
     468            if (b = s.base_uri) {
     469                if (!t.protocol)
     470                    t.protocol = b.protocol;
     471
     472                if (!t.userInfo)
     473                    t.userInfo = b.userInfo;
     474
     475                if (!t.port && t.host == 'mce_host')
     476                    t.port = b.port;
     477
     478                if (!t.host || t.host == 'mce_host')
     479                    t.host = b.host;
     480
     481                t.source = '';
     482            }
     483
     484            //t.path = t.path || '/';
     485        },
     486
     487        setPath : function(p) {
     488            var t = this;
     489
     490            p = /^(.*?)\/?(\w+)?$/.exec(p);
     491
     492            // Update path parts
     493            t.path = p[0];
     494            t.directory = p[1];
     495            t.file = p[2];
     496
     497            // Rebuild source
     498            t.source = '';
     499            t.getURI();
     500        },
     501
     502        toRelative : function(u) {
     503            var t = this, o;
     504
     505            u = new tinymce.util.URI(u, {base_uri : t});
     506
     507            // Not on same domain/port or protocol
     508            if ((u.host != 'mce_host' && t.host != u.host && u.host) || t.port != u.port || t.protocol != u.protocol)
     509                return u.getURI();
     510
     511            o = t.toRelPath(t.path, u.path);
     512
     513            // Add query
     514            if (u.query)
     515                o += '?' + u.query;
     516
     517            // Add anchor
     518            if (u.anchor)
     519                o += '#' + u.anchor;
     520
     521            return o;
     522        },
     523   
     524        toAbsolute : function(u, nh) {
     525            var u = new tinymce.util.URI(u, {base_uri : this});
     526
     527            return u.getURI(this.host == u.host ? nh : 0);
     528        },
     529
     530        toRelPath : function(base, path) {
     531            var items, bp = 0, out = '', i;
     532
     533            // Split the paths
     534            base = base.substring(0, base.lastIndexOf('/'));
     535            base = base.split('/');
     536            items = path.split('/');
     537
     538            if (base.length >= items.length) {
     539                for (i = 0; i < base.length; i++) {
     540                    if (i >= items.length || base[i] != items[i]) {
     541                        bp = i + 1;
    462542                        break;
    463543                    }
    464544                }
    465 
    466                 if (!skip) {
    467                     if (tinyMCE.settings.strict_loading_mode) {
    468                         nl = document.getElementsByTagName("head");
    469 
    470                         le = document.createElement('link');
    471                         le.setAttribute('href', ar[x]);
    472                         le.setAttribute('rel', 'stylesheet');
    473                         le.setAttribute('type', 'text/css');
    474 
    475                         nl[0].appendChild(le);         
    476                     } else
    477                         document.write('<link href="' + ar[x] + '" rel="stylesheet" type="text/css" />');
    478 
    479                     this.loadedFiles[this.loadedFiles.length] = ar[x];
    480                 }
    481             }
    482         }
    483     },
    484 
    485     importCSS : function(doc, css) {
    486         var css_ary = css.replace(/\s+/, '').split(',');
    487         var csslen, elm, headArr, x, css_file;
    488 
    489         for (x = 0, csslen = css_ary.length; x<csslen; x++) {
    490             css_file = css_ary[x];
    491 
    492             if (css_file != null && css_file != 'null' && css_file.length > 0) {
    493                 // Is relative, make absolute
    494                 if (css_file.indexOf('://') == -1 && css_file.charAt(0) != '/')
    495                     css_file = this.documentBasePath + "/" + css_file;
    496 
    497                 if (typeof(doc.createStyleSheet) == "undefined") {
    498                     elm = doc.createElement("link");
    499 
    500                     elm.rel = "stylesheet";
    501                     elm.href = css_file;
    502 
    503                     if ((headArr = doc.getElementsByTagName("head")) != null && headArr.length > 0)
    504                         headArr[0].appendChild(elm);
    505                 } else
    506                     doc.createStyleSheet(css_file);
    507             }
    508         }
    509     },
    510 
    511     confirmAdd : function(e, settings) {
    512         var elm = tinyMCE.isIE ? event.srcElement : e.target;
    513         var elementId = elm.name ? elm.name : elm.id;
    514 
    515         tinyMCE.settings = settings;
    516 
    517         if (tinyMCE.settings.convert_on_click || (!elm.getAttribute('mce_noask') && confirm(tinyMCELang.lang_edit_confirm)))
    518             tinyMCE.addMCEControl(elm, elementId);
    519 
    520         elm.setAttribute('mce_noask', 'true');
    521     },
    522 
    523     updateContent : function(form_element_name) {
    524         var formElement, n, inst, doc;
    525 
    526         // Find MCE instance linked to given form element and copy it's value
    527         formElement = document.getElementById(form_element_name);
    528         for (n in tinyMCE.instances) {
    529             inst = tinyMCE.instances[n];
    530 
    531             if (!tinyMCE.isInstance(inst))
    532                 continue;
    533 
    534             inst.switchSettings();
    535 
    536             if (inst.formElement == formElement) {
    537                 doc = inst.getDoc();
    538 
    539                 tinyMCE._setHTML(doc, inst.formElement.value);
    540 
    541                 if (!tinyMCE.isIE)
    542                     doc.body.innerHTML = tinyMCE._cleanupHTML(inst, doc, this.settings, doc.body, inst.visualAid);
    543             }
    544         }
    545     },
    546 
    547     addMCEControl : function(replace_element, form_element_name, target_document) {
    548         var id = "mce_editor_" + tinyMCE.idCounter++;
    549         var inst = new TinyMCE_Control(tinyMCE.settings);
    550 
    551         inst.editorId = id;
    552         this.instances[id] = inst;
    553 
    554         inst._onAdd(replace_element, form_element_name, target_document);
    555     },
    556 
    557     removeInstance : function(ti) {
    558         var t = [], n, i;
    559 
    560         // Remove from instances
    561         for (n in tinyMCE.instances) {
    562             i = tinyMCE.instances[n];
    563 
    564             if (tinyMCE.isInstance(i) && ti != i)
    565                     t[n] = i;
    566         }
    567 
    568         tinyMCE.instances = t;
    569 
    570         // Remove from global undo/redo
    571         n = [];
    572         t = tinyMCE.undoLevels;
    573 
    574         for (i=0; i<t.length; i++) {
    575             if (t[i] != ti)
    576                 n.push(t[i]);
    577         }
    578 
    579         tinyMCE.undoLevels = n;
    580         tinyMCE.undoIndex = n.length;
    581 
    582         // Dispatch remove instance call
    583         tinyMCE.dispatchCallback(ti, 'remove_instance_callback', 'removeInstance', ti);
    584 
    585         return ti;
    586     },
    587 
    588     removeMCEControl : function(editor_id) {
    589         var inst = tinyMCE.getInstanceById(editor_id), h, re, ot, tn;
    590 
    591         if (inst) {
    592             inst.switchSettings();
    593 
    594             editor_id = inst.editorId;
    595             h = tinyMCE.getContent(editor_id);
    596 
    597             this.removeInstance(inst);
    598 
    599             tinyMCE.selectedElement = null;
    600             tinyMCE.selectedInstance = null;
    601 
    602             // Remove element
    603             re = document.getElementById(editor_id + "_parent");
    604             ot = inst.oldTargetElement;
    605             tn = ot.nodeName.toLowerCase();
    606 
    607             if (tn == "textarea" || tn == "input") {
    608                 re.parentNode.removeChild(re);
    609                 ot.style.display = "inline";
    610                 ot.value = h;
    611             } else {
    612                 ot.innerHTML = h;
    613                 ot.style.display = 'block';
    614                 re.parentNode.insertBefore(ot, re);
    615                 re.parentNode.removeChild(re);
    616             }
    617         }
    618     },
    619 
    620     triggerSave : function(skip_cleanup, skip_callback) {
    621         var inst, n;
    622 
    623         // Default to false
    624         if (typeof(skip_cleanup) == "undefined")
    625             skip_cleanup = false;
    626 
    627         // Default to false
    628         if (typeof(skip_callback) == "undefined")
    629             skip_callback = false;
    630 
    631         // Cleanup and set all form fields
    632         for (n in tinyMCE.instances) {
    633             inst = tinyMCE.instances[n];
    634 
    635             if (!tinyMCE.isInstance(inst))
    636                 continue;
    637 
    638             inst.triggerSave(skip_cleanup, skip_callback);
    639         }
    640     },
    641 
    642     resetForm : function(form_index) {
    643         var i, inst, n, formObj = document.forms[form_index];
    644 
    645         for (n in tinyMCE.instances) {
    646             inst = tinyMCE.instances[n];
    647 
    648             if (!tinyMCE.isInstance(inst))
    649                 continue;
    650 
    651             inst.switchSettings();
    652 
    653             for (i=0; i<formObj.elements.length; i++) {
    654                 if (inst.formTargetElementId == formObj.elements[i].name)
    655                     inst.getBody().innerHTML = inst.startContent;
    656             }
    657         }
    658     },
    659 
    660     execInstanceCommand : function(editor_id, command, user_interface, value, focus) {
    661         var inst = tinyMCE.getInstanceById(editor_id), r;
    662 
    663         if (inst) {
    664             r = inst.selection.getRng();
    665 
    666             if (typeof(focus) == "undefined")
    667                 focus = true;
    668 
    669             // IE bug lost focus on images in absolute divs Bug #1534575
    670             if (focus && (!r || !r.item))
    671                 inst.contentWindow.focus();
    672 
    673             // Reset design mode if lost
    674             inst.autoResetDesignMode();
    675 
    676             this.selectedElement = inst.getFocusElement();
    677             inst.select();
    678             tinyMCE.execCommand(command, user_interface, value);
    679 
    680             // Cancel event so it doesn't call onbeforeonunlaod
    681             if (tinyMCE.isIE && window.event != null)
    682                 tinyMCE.cancelEvent(window.event);
    683         }
    684     },
    685 
    686     execCommand : function(command, user_interface, value) {
    687         var inst = tinyMCE.selectedInstance, n, pe, te;
    688 
    689         // Default input
    690         user_interface = user_interface ? user_interface : false;
    691         value = value ? value : null;
    692 
    693         if (inst)
    694             inst.switchSettings();
    695 
    696         switch (command) {
    697             case "Undo":
    698                 if (this.getParam('custom_undo_redo_global')) {
    699                     if (this.undoIndex > 0) {
    700                         tinyMCE.nextUndoRedoAction = 'Undo';
    701                         inst = this.undoLevels[--this.undoIndex];
    702                         inst.select();
    703 
    704                         if (!tinyMCE.nextUndoRedoInstanceId)
    705                             inst.execCommand('Undo');
    706                     }
    707                 } else
    708                     inst.execCommand('Undo');
    709                 return true;
    710 
    711             case "Redo":
    712                 if (this.getParam('custom_undo_redo_global')) {
    713                     if (this.undoIndex <= this.undoLevels.length - 1) {
    714                         tinyMCE.nextUndoRedoAction = 'Redo';
    715                         inst = this.undoLevels[this.undoIndex++];
    716                         inst.select();
    717 
    718                         if (!tinyMCE.nextUndoRedoInstanceId)
    719                             inst.execCommand('Redo');
    720                     }
    721                 } else
    722                     inst.execCommand('Redo');
    723 
    724                 return true;
    725 
    726             case 'mceFocus':
    727                 inst = tinyMCE.getInstanceById(value);
    728 
    729                 if (inst)
    730                     inst.getWin().focus();
    731             return;
    732 
    733             case "mceAddControl":
    734             case "mceAddEditor":
    735                 tinyMCE.addMCEControl(tinyMCE._getElementById(value), value);
    736                 return;
    737 
    738             case "mceAddFrameControl":
    739                 tinyMCE.addMCEControl(tinyMCE._getElementById(value.element, value.document), value.element, value.document);
    740                 return;
    741 
    742             case "mceRemoveControl":
    743             case "mceRemoveEditor":
    744                 tinyMCE.removeMCEControl(value);
    745                 return;
    746 
    747             case "mceToggleEditor":
    748                 inst = tinyMCE.getInstanceById(value);
    749 
    750                 if (inst) {
    751                     pe = document.getElementById(inst.editorId + '_parent');
    752                     te = inst.oldTargetElement;
    753 
    754                     if (typeof(inst.enabled) == 'undefined')
    755                         inst.enabled = true;
    756 
    757                     inst.enabled = !inst.enabled;
    758 
    759                     if (!inst.enabled) {
    760                         pe.style.display = 'none';
    761 
    762                         if (te.nodeName == 'TEXTAREA' || te.nodeName == 'INPUT')
    763                             te.value = inst.getHTML();
    764                         else
    765                             te.innerHTML = inst.getHTML();
    766 
    767                         te.style.display = inst.oldTargetDisplay;
    768                         tinyMCE.dispatchCallback(inst, 'hide_instance_callback', 'hideInstance', inst);
    769                     } else {
    770                         pe.style.display = 'block';
    771                         te.style.display = 'none';
    772 
    773                         if (te.nodeName == 'TEXTAREA' || te.nodeName == 'INPUT')
    774                             inst.setHTML(te.value);
    775                         else
    776                             inst.setHTML(te.innerHTML);
    777 
    778                         inst.useCSS = false;
    779                         tinyMCE.dispatchCallback(inst, 'show_instance_callback', 'showInstance', inst);
    780                     }
    781                 } else
    782                     tinyMCE.addMCEControl(tinyMCE._getElementById(value), value);
    783 
    784                 return;
    785 
    786             case "mceResetDesignMode":
    787                 // Resets the designmode state of the editors in Gecko
    788                 if (tinyMCE.isGecko) {
    789                     for (n in tinyMCE.instances) {
    790                         if (!tinyMCE.isInstance(tinyMCE.instances[n]))
    791                             continue;
    792 
    793                         try {
    794                             tinyMCE.instances[n].getDoc().designMode = "off";
    795                             tinyMCE.instances[n].getDoc().designMode = "on";
    796                             tinyMCE.instances[n].useCSS = false;
    797                         } catch (e) {
    798                             // Ignore any errors
    799                         }
    800                     }
    801                 }
    802 
    803                 return;
    804         }
    805 
    806         if (inst) {
    807             inst.execCommand(command, user_interface, value);
    808         } else if (tinyMCE.settings.focus_alert)
    809             alert(tinyMCELang.lang_focus_alert);
    810     },
    811 
    812     _createIFrame : function(replace_element, doc, win) {
    813         var iframe, id = replace_element.getAttribute("id");
    814         var aw, ah;
    815 
    816         if (typeof(doc) == "undefined")
    817             doc = document;
    818 
    819         if (typeof(win) == "undefined")
    820             win = window;
    821 
    822         iframe = doc.createElement("iframe");
    823 
    824         aw = "" + tinyMCE.settings.area_width;
    825         ah = "" + tinyMCE.settings.area_height;
    826 
    827         if (aw.indexOf('%') == -1) {
    828             aw = parseInt(aw);
    829             aw = (isNaN(aw) || aw < 0) ? 300 : aw;
    830             aw = aw + "px";
    831         }
    832 
    833         if (ah.indexOf('%') == -1) {
    834             ah = parseInt(ah);
    835             ah = (isNaN(ah) || ah < 0) ? 240 : ah;
    836             ah = ah + "px";
    837         }
    838 
    839         iframe.setAttribute("id", id);
    840         iframe.setAttribute("name", id);
    841         iframe.setAttribute("class", "mceEditorIframe");
    842         iframe.setAttribute("border", "0");
    843         iframe.setAttribute("frameBorder", "0");
    844         iframe.setAttribute("marginWidth", "0");
    845         iframe.setAttribute("marginHeight", "0");
    846         iframe.setAttribute("leftMargin", "0");
    847         iframe.setAttribute("topMargin", "0");
    848         iframe.setAttribute("width", aw);
    849         iframe.setAttribute("height", ah);
    850         iframe.setAttribute("allowtransparency", "true");
    851         iframe.className = 'mceEditorIframe';
    852 
    853         if (tinyMCE.settings.auto_resize)
    854             iframe.setAttribute("scrolling", "no");
    855 
    856         // Must have a src element in MSIE HTTPs breaks aswell as absoute URLs
    857         if (tinyMCE.isRealIE)
    858             iframe.setAttribute("src", this.settings.default_document);
    859 
    860         iframe.style.width = aw;
    861         iframe.style.height = ah;
    862 
    863         // Ugly hack for Gecko problem in strict mode
    864         if (tinyMCE.settings.strict_loading_mode)
    865             iframe.style.marginBottom = '-5px';
    866 
    867         // MSIE 5.0 issue
    868         if (tinyMCE.isRealIE)
    869             replace_element.outerHTML = iframe.outerHTML;
    870         else
    871             replace_element.parentNode.replaceChild(iframe, replace_element);
    872 
    873         if (tinyMCE.isRealIE)
    874             return win.frames[id];
    875         else
    876             return iframe;
    877     },
    878 
    879     setupContent : function(editor_id) {
    880         var inst = tinyMCE.instances[editor_id], i, doc = inst.getDoc(), head = doc.getElementsByTagName('head').item(0);
    881         var content = inst.startContent, contentElement, body;
    882 
    883         // HTML values get XML encoded in strict mode
    884         if (tinyMCE.settings.strict_loading_mode) {
    885             content = content.replace(/&lt;/g, '<');
    886             content = content.replace(/&gt;/g, '>');
    887             content = content.replace(/&quot;/g, '"');
    888             content = content.replace(/&amp;/g, '&');
    889         }
    890 
    891         tinyMCE.selectedInstance = inst;
    892         inst.switchSettings();
    893 
    894         // Not loaded correctly hit it again, Mozilla bug #997860
    895         if (!tinyMCE.isIE && tinyMCE.getParam("setupcontent_reload", false) && doc.title != "blank_page") {
    896             // This part will remove the designMode status
    897             // Failes first time in Firefox 1.5b2 on Mac
    898             try {doc.location.href = tinyMCE.baseURL + "/blank.htm";} catch (ex) {}
    899             window.setTimeout("tinyMCE.setupContent('" + editor_id + "');", 1000);
    900             return;
    901         }
    902 
    903         // Wait for it to load
    904         if (!head || !doc.body) {
    905             window.setTimeout("tinyMCE.setupContent('" + editor_id + "');", 10);
    906             return;
    907         }
    908 
    909         // Import theme specific content CSS the user specific
    910         tinyMCE.importCSS(inst.getDoc(), tinyMCE.baseURL + "/themes/" + inst.settings.theme + "/css/editor_content.css");
    911         tinyMCE.importCSS(inst.getDoc(), inst.settings.content_css);
    912         tinyMCE.dispatchCallback(inst, 'init_instance_callback', 'initInstance', inst);
    913 
    914         // Setup keyboard shortcuts
    915         if (tinyMCE.getParam('custom_undo_redo_keyboard_shortcuts')) {
    916             inst.addShortcut('ctrl', 'z', 'lang_undo_desc', 'Undo');
    917             inst.addShortcut('ctrl', 'y', 'lang_redo_desc', 'Redo');
    918         }
    919 
    920         // BlockFormat shortcuts keys
    921         for (i=1; i<=6; i++)
    922             inst.addShortcut('ctrl', '' + i, '', 'FormatBlock', false, '<h' + i + '>');
    923 
    924         inst.addShortcut('ctrl', '7', '', 'FormatBlock', false, '<p>');
    925         inst.addShortcut('ctrl', '8', '', 'FormatBlock', false, '<div>');
    926         inst.addShortcut('ctrl', '9', '', 'FormatBlock', false, '<address>');
    927 
    928         // Add default shortcuts for gecko
    929         if (tinyMCE.isGecko) {
    930             inst.addShortcut('ctrl', 'b', 'lang_bold_desc', 'Bold');
    931             inst.addShortcut('ctrl', 'i', 'lang_italic_desc', 'Italic');
    932             inst.addShortcut('ctrl', 'u', 'lang_underline_desc', 'Underline');
    933         }
    934 
    935         // Setup span styles
    936         if (tinyMCE.getParam("convert_fonts_to_spans"))
    937             inst.getBody().setAttribute('id', 'mceSpanFonts');
    938 
    939         if (tinyMCE.settings.nowrap)
    940             doc.body.style.whiteSpace = "nowrap";
    941 
    942         doc.body.dir = this.settings.directionality;
    943         doc.editorId = editor_id;
    944 
    945         // Add on document element in Mozilla
    946         if (!tinyMCE.isIE)
    947             doc.documentElement.editorId = editor_id;
    948 
    949         inst.setBaseHREF(tinyMCE.settings.base_href);
    950 
    951         // Replace new line characters to BRs
    952         if (tinyMCE.settings.convert_newlines_to_brs) {
    953             content = tinyMCE.regexpReplace(content, "\r\n", "<br />", "gi");
    954             content = tinyMCE.regexpReplace(content, "\r", "<br />", "gi");
    955             content = tinyMCE.regexpReplace(content, "\n", "<br />", "gi");
    956         }
    957 
    958         // Open closed anchors
    959     //  content = content.replace(new RegExp('<a(.*?)/>', 'gi'), '<a$1></a>');
    960 
    961         // Call custom cleanup code
    962         content = tinyMCE.storeAwayURLs(content);
    963         content = tinyMCE._customCleanup(inst, "insert_to_editor", content);
    964 
    965         if (tinyMCE.isIE) {
    966             // Ugly!!!
    967             window.setInterval('try{tinyMCE.getCSSClasses(tinyMCE.instances["' + editor_id + '"].getDoc(), "' + editor_id + '");}catch(e){}', 500);
    968 
    969             if (tinyMCE.settings.force_br_newlines)
    970                 doc.styleSheets[0].addRule("p", "margin: 0;");
    971 
    972             body = inst.getBody();
    973             body.editorId = editor_id;
    974         }
    975 
    976         content = tinyMCE.cleanupHTMLCode(content);
    977 
    978         // Fix for bug #958637
    979         if (!tinyMCE.isIE) {
    980             contentElement = inst.getDoc().createElement("body");
    981             doc = inst.getDoc();
    982 
    983             contentElement.innerHTML = content;
    984 
    985             if (tinyMCE.settings.cleanup_on_startup)
    986                 tinyMCE.setInnerHTML(inst.getBody(), tinyMCE._cleanupHTML(inst, doc, this.settings, contentElement));
    987             else
    988                 tinyMCE.setInnerHTML(inst.getBody(), content);
    989 
    990             tinyMCE.convertAllRelativeURLs(inst.getBody());
    991         } else {
    992             if (tinyMCE.settings.cleanup_on_startup) {
    993                 tinyMCE._setHTML(inst.getDoc(), content);
    994 
    995                 // Produces permission denied error in MSIE 5.5
    996                 try {
    997                     tinyMCE.setInnerHTML(inst.getBody(), tinyMCE._cleanupHTML(inst, inst.contentDocument, this.settings, inst.getBody()));
    998                 } catch(e) {
    999                     // Ignore
    1000                 }
    1001             } else
    1002                 tinyMCE._setHTML(inst.getDoc(), content);
    1003         }
    1004 
    1005         // Fix for bug #957681
    1006         //inst.getDoc().designMode = inst.getDoc().designMode;
    1007 
    1008         tinyMCE.handleVisualAid(inst.getBody(), true, tinyMCE.settings.visual, inst);
    1009         tinyMCE.dispatchCallback(inst, 'setupcontent_callback', 'setupContent', editor_id, inst.getBody(), inst.getDoc());
    1010 
    1011         // Re-add design mode on mozilla
    1012         if (!tinyMCE.isIE)
    1013             tinyMCE.addEventHandlers(inst);
    1014 
    1015         // Add blur handler
    1016         if (tinyMCE.isIE) {
    1017             tinyMCE.addEvent(inst.getBody(), "blur", TinyMCE_Engine.prototype._eventPatch);
    1018             tinyMCE.addEvent(inst.getBody(), "beforedeactivate", TinyMCE_Engine.prototype._eventPatch); // Bug #1439953
    1019 
    1020             // Workaround for drag drop/copy paste base href bug
    1021             if (!tinyMCE.isOpera) {
    1022                 tinyMCE.addEvent(doc.body, "mousemove", TinyMCE_Engine.prototype.onMouseMove);
    1023                 tinyMCE.addEvent(doc.body, "beforepaste", TinyMCE_Engine.prototype._eventPatch);
    1024                 tinyMCE.addEvent(doc.body, "drop", TinyMCE_Engine.prototype._eventPatch);
    1025             }
    1026         }
    1027 
    1028         // Trigger node change, this call locks buttons for tables and so forth
    1029         inst.select();
    1030         tinyMCE.selectedElement = inst.contentWindow.document.body;
    1031 
    1032         // Call custom DOM cleanup
    1033         tinyMCE._customCleanup(inst, "insert_to_editor_dom", inst.getBody());
    1034         tinyMCE._customCleanup(inst, "setup_content_dom", inst.getBody());
    1035         tinyMCE._setEventsEnabled(inst.getBody(), false);
    1036         tinyMCE.cleanupAnchors(inst.getDoc());
    1037 
    1038         if (tinyMCE.getParam("convert_fonts_to_spans"))
    1039             tinyMCE.convertSpansToFonts(inst.getDoc());
    1040 
    1041         inst.startContent = tinyMCE.trim(inst.getBody().innerHTML);
    1042         inst.undoRedo.add({ content : inst.startContent });
    1043 
    1044         // Cleanup any mess left from storyAwayURLs
    1045         if (tinyMCE.isGecko) {
    1046             // Remove mce_src from textnodes and comments
    1047             tinyMCE.selectNodes(inst.getBody(), function(n) {
    1048                 if (n.nodeType == 3 || n.nodeType == 8)
    1049                     n.nodeValue = n.nodeValue.replace(new RegExp('\\s(mce_src|mce_href)=\"[^\"]*\"', 'gi'), "");
    1050 
    1051                 return false;
    1052             });
    1053         }
    1054 
    1055         // Remove Gecko spellchecking
    1056         if (tinyMCE.isGecko)
    1057             inst.getBody().spellcheck = tinyMCE.getParam("gecko_spellcheck");
    1058 
    1059         // Cleanup any mess left from storyAwayURLs
    1060         tinyMCE._removeInternal(inst.getBody());
    1061 
    1062         inst.select();
    1063         tinyMCE.triggerNodeChange(false, true);
    1064     },
    1065 
    1066     storeAwayURLs : function(s) {
    1067         // Remove all mce_src, mce_href and replace them with new ones
    1068         // s = s.replace(new RegExp('mce_src\\s*=\\s*\"[^ >\"]*\"', 'gi'), '');
    1069         // s = s.replace(new RegExp('mce_href\\s*=\\s*\"[^ >\"]*\"', 'gi'), '');
    1070 
    1071         if (!s.match(/(mce_src|mce_href)/gi, s)) {
    1072             s = s.replace(new RegExp('src\\s*=\\s*\"([^ >\"]*)\"', 'gi'), 'src="$1" mce_src="$1"');
    1073             s = s.replace(new RegExp('href\\s*=\\s*\"([^ >\"]*)\"', 'gi'), 'href="$1" mce_href="$1"');
    1074         }
    1075 
    1076         return s;
    1077     },
    1078 
    1079     _removeInternal : function(n) {
    1080         if (tinyMCE.isGecko) {
    1081             // Remove mce_src from textnodes and comments
    1082             tinyMCE.selectNodes(n, function(n) {
    1083                 if (n.nodeType == 3 || n.nodeType == 8)
    1084                     n.nodeValue = n.nodeValue.replace(new RegExp('\\s(mce_src|mce_href)=\"[^\"]*\"', 'gi'), "");
    1085 
    1086                 return false;
    1087             });
    1088         }
    1089     },
    1090 
    1091     removeTinyMCEFormElements : function(form_obj) {
    1092         var i, elementId;
    1093 
    1094         // Skip form element removal
    1095         if (!tinyMCE.getParam('hide_selects_on_submit'))
    1096             return;
    1097 
    1098         // Check if form is valid
    1099         if (typeof(form_obj) == "undefined" || form_obj == null)
    1100             return;
    1101 
    1102         // If not a form, find the form
    1103         if (form_obj.nodeName != "FORM") {
    1104             if (form_obj.form)
    1105                 form_obj = form_obj.form;
    1106             else
    1107                 form_obj = tinyMCE.getParentElement(form_obj, "form");
    1108         }
    1109 
    1110         // Still nothing
    1111         if (form_obj == null)
    1112             return;
    1113 
    1114         // Disable all UI form elements that TinyMCE created
    1115         for (i=0; i<form_obj.elements.length; i++) {
    1116             elementId = form_obj.elements[i].name ? form_obj.elements[i].name : form_obj.elements[i].id;
    1117 
    1118             if (elementId.indexOf('mce_editor_') == 0)
    1119                 form_obj.elements[i].disabled = true;
    1120         }
    1121     },
    1122 
    1123     handleEvent : function(e) {
    1124         var inst = tinyMCE.selectedInstance, i, elm, keys;
    1125 
    1126         // Remove odd, error
    1127         if (typeof(tinyMCE) == "undefined")
    1128             return true;
    1129 
    1130         //tinyMCE.debug(e.type + " " + e.target.nodeName + " " + (e.relatedTarget ? e.relatedTarget.nodeName : ""));
    1131 
    1132         if (tinyMCE.executeCallback(tinyMCE.selectedInstance, 'handle_event_callback', 'handleEvent', e))
    1133             return false;
    1134 
    1135         switch (e.type) {
    1136             case "beforedeactivate": // Was added due to bug #1439953
    1137             case "blur":
    1138                 if (tinyMCE.selectedInstance)
    1139                     tinyMCE.selectedInstance.execCommand('mceEndTyping');
    1140 
    1141                 tinyMCE.hideMenus();
    1142 
    1143                 return;
    1144 
    1145             // Workaround for drag drop/copy paste base href bug
    1146             case "drop":
    1147             case "beforepaste":
    1148                 if (tinyMCE.selectedInstance)
    1149                     tinyMCE.selectedInstance.setBaseHREF(null);
    1150 
    1151                 // Fixes odd MSIE bug where drag/droping elements in a iframe with height 100% breaks
    1152                 // This logic forces the width/height to be in pixels while the user is drag/dropping
    1153                 if (tinyMCE.isRealIE) {
    1154                     var ife = tinyMCE.selectedInstance.iframeElement;
    1155 
    1156                     /*if (ife.style.width.indexOf('%') != -1) {
    1157                         ife._oldWidth = ife.width.height;
    1158                         ife.style.width = ife.clientWidth;
    1159                     }*/
    1160 
    1161                     if (ife.style.height.indexOf('%') != -1) {
    1162                         ife._oldHeight = ife.style.height;
    1163                         ife.style.height = ife.clientHeight;
    1164                     }
    1165                 }
    1166 
    1167                 window.setTimeout("tinyMCE.selectedInstance.setBaseHREF(tinyMCE.settings.base_href);tinyMCE._resetIframeHeight();", 1);
    1168                 return;
    1169 
    1170             case "submit":
    1171                 tinyMCE.formSubmit(tinyMCE.isMSIE ? window.event.srcElement : e.target);
    1172                 return;
    1173 
    1174             case "reset":
    1175                 var formObj = tinyMCE.isIE ? window.event.srcElement : e.target;
    1176 
    1177                 for (i=0; i<document.forms.length; i++) {
    1178                     if (document.forms[i] == formObj)
    1179                         window.setTimeout('tinyMCE.resetForm(' + i + ');', 10);
    1180                 }
    1181 
    1182                 return;
    1183 
    1184             case "keypress":
    1185                 if (inst && inst.handleShortcut(e))
    1186                     return false;
    1187 
    1188                 if (e.target.editorId) {
    1189                     tinyMCE.instances[e.target.editorId].select();
    1190                 } else {
    1191                     if (e.target.ownerDocument.editorId)
    1192                         tinyMCE.instances[e.target.ownerDocument.editorId].select();
    1193                 }
    1194 
    1195                 if (tinyMCE.selectedInstance)
    1196                     tinyMCE.selectedInstance.switchSettings();
    1197 
    1198                 // Insert P element
    1199                 if ((tinyMCE.isGecko || tinyMCE.isOpera || tinyMCE.isSafari) && tinyMCE.settings.force_p_newlines && e.keyCode == 13 && !e.shiftKey) {
    1200                     // Insert P element instead of BR
    1201                     if (TinyMCE_ForceParagraphs._insertPara(tinyMCE.selectedInstance, e)) {
    1202                         // Cancel event
    1203                         tinyMCE.execCommand("mceAddUndoLevel");
    1204                         return tinyMCE.cancelEvent(e);
    1205                     }
    1206                 }
    1207 
    1208                 // Handle backspace
    1209                 if ((tinyMCE.isGecko && !tinyMCE.isSafari) && tinyMCE.settings.force_p_newlines && (e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey) {
    1210                     // Insert P element instead of BR
    1211                     if (TinyMCE_ForceParagraphs._handleBackSpace(tinyMCE.selectedInstance, e.type)) {
    1212                         // Cancel event
    1213                         tinyMCE.execCommand("mceAddUndoLevel");
    1214                         return tinyMCE.cancelEvent(e);
    1215                     }
    1216                 }
    1217 
    1218                 // Return key pressed
    1219                 if (tinyMCE.isIE && tinyMCE.settings.force_br_newlines && e.keyCode == 13) {
    1220                     if (e.target.editorId)
    1221                         tinyMCE.instances[e.target.editorId].select();
    1222 
    1223                     if (tinyMCE.selectedInstance) {
    1224                         var sel = tinyMCE.selectedInstance.getDoc().selection;
    1225                         var rng = sel.createRange();
    1226 
    1227                         if (tinyMCE.getParentElement(rng.parentElement(), "li") != null)
    1228                             return false;
    1229 
    1230                         // Cancel event
    1231                         e.returnValue = false;
    1232                         e.cancelBubble = true;
    1233 
    1234                         // Insert BR element
    1235                         rng.pasteHTML("<br />");
    1236                         rng.collapse(false);
    1237                         rng.select();
    1238 
    1239                         tinyMCE.execCommand("mceAddUndoLevel");
    1240                         tinyMCE.triggerNodeChange(false);
    1241                         return false;
    1242                     }
    1243                 }
    1244 
    1245                 // Backspace or delete
    1246                 if (e.keyCode == 8 || e.keyCode == 46) {
    1247                     tinyMCE.selectedElement = e.target;
    1248                     tinyMCE.linkElement = tinyMCE.getParentElement(e.target, "a");
    1249                     tinyMCE.imgElement = tinyMCE.getParentElement(e.target, "img");
    1250                     tinyMCE.triggerNodeChange(false);
    1251                 }
    1252 
    1253                 return false;
    1254 
    1255             case "keyup":
    1256             case "keydown":
    1257                 tinyMCE.hideMenus();
    1258                 tinyMCE.hasMouseMoved = false;
    1259 
    1260                 if (inst && inst.handleShortcut(e))
    1261                     return false;
    1262 
    1263                 inst._fixRootBlocks();
    1264 
    1265                 if (inst.settings.remove_trailing_nbsp)
    1266                     inst._fixTrailingNbsp();
    1267 
    1268                 if (e.target.editorId)
    1269                     tinyMCE.instances[e.target.editorId].select();
    1270 
    1271                 if (tinyMCE.selectedInstance)
    1272                     tinyMCE.selectedInstance.switchSettings();
    1273 
    1274                 inst = tinyMCE.selectedInstance;
    1275 
    1276                 // Handle backspace
    1277                 if (tinyMCE.isGecko && tinyMCE.settings.force_p_newlines && (e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey) {
    1278                     // Insert P element instead of BR
    1279                     if (TinyMCE_ForceParagraphs._handleBackSpace(tinyMCE.selectedInstance, e.type)) {
    1280                         // Cancel event
    1281                         tinyMCE.execCommand("mceAddUndoLevel");
    1282                         e.preventDefault();
    1283                         return false;
    1284                     }
    1285                 }
    1286 
    1287                 tinyMCE.selectedElement = null;
    1288                 tinyMCE.selectedNode = null;
    1289                 elm = tinyMCE.selectedInstance.getFocusElement();
    1290                 tinyMCE.linkElement = tinyMCE.getParentElement(elm, "a");
    1291                 tinyMCE.imgElement = tinyMCE.getParentElement(elm, "img");
    1292                 tinyMCE.selectedElement = elm;
    1293 
    1294                 // Update visualaids on tabs
    1295                 if (tinyMCE.isGecko && e.type == "keyup" && e.keyCode == 9)
    1296                     tinyMCE.handleVisualAid(tinyMCE.selectedInstance.getBody(), true, tinyMCE.settings.visual, tinyMCE.selectedInstance);
    1297 
    1298                 // Fix empty elements on return/enter, check where enter occured
    1299                 if (tinyMCE.isIE && e.type == "keydown" && e.keyCode == 13)
    1300                     tinyMCE.enterKeyElement = tinyMCE.selectedInstance.getFocusElement();
    1301 
    1302                 // Fix empty elements on return/enter
    1303                 if (tinyMCE.isIE && e.type == "keyup" && e.keyCode == 13) {
    1304                     elm = tinyMCE.enterKeyElement;
    1305                     if (elm) {
    1306                         var re = new RegExp('^HR|IMG|BR$','g'); // Skip these
    1307                         var dre = new RegExp('^H[1-6]$','g'); // Add double on these
    1308 
    1309                         if (!elm.hasChildNodes() && !re.test(elm.nodeName)) {
    1310                             if (dre.test(elm.nodeName))
    1311                                 elm.innerHTML = "&nbsp;&nbsp;";
    1312                             else
    1313                                 elm.innerHTML = "&nbsp;";
    1314                         }
    1315                     }
    1316                 }
    1317 
    1318                 // Check if it's a position key
    1319                 keys = tinyMCE.posKeyCodes;
    1320                 var posKey = false;
    1321                 for (i=0; i<keys.length; i++) {
    1322                     if (keys[i] == e.keyCode) {
    1323                         posKey = true;
     545            }
     546
     547            if (base.length < items.length) {
     548                for (i = 0; i < items.length; i++) {
     549                    if (i >= base.length || base[i] != items[i]) {
     550                        bp = i + 1;
    1324551                        break;
    1325552                    }
    1326553                }
    1327 
    1328                 // MSIE custom key handling
    1329                 if (tinyMCE.isIE && tinyMCE.settings.custom_undo_redo) {
    1330                     keys = [8, 46]; // Backspace,Delete
    1331 
    1332                     for (i=0; i<keys.length; i++) {
    1333                         if (keys[i] == e.keyCode) {
    1334                             if (e.type == "keyup")
    1335                                 tinyMCE.triggerNodeChange(false);
    1336                         }
    1337                     }
    1338                 }
    1339 
    1340                 // If Ctrl key
    1341                 if (e.keyCode == 17)
    1342                     return true;
    1343 
    1344                 // Handle Undo/Redo when typing content
    1345 
    1346                 if (tinyMCE.isGecko) {
    1347                     // Start typing (not a position key or ctrl key, but ctrl+x and ctrl+p is ok)
    1348                     if (!posKey && e.type == "keyup" && !e.ctrlKey || (e.ctrlKey && (e.keyCode == 86 || e.keyCode == 88)))
    1349                         tinyMCE.execCommand("mceStartTyping");
    1350                 } else {
    1351                     // IE seems to be working better with this setting
    1352                     if (!posKey && e.type == "keyup")
    1353                         tinyMCE.execCommand("mceStartTyping");
    1354                 }
    1355 
    1356                 // Store undo bookmark
    1357                 if (e.type == "keydown" && (posKey || e.ctrlKey) && inst)
    1358                     inst.undoBookmark = inst.selection.getBookmark();
    1359 
    1360                 // End typing (position key) or some Ctrl event
    1361                 if (e.type == "keyup" && (posKey || e.ctrlKey))
    1362                     tinyMCE.execCommand("mceEndTyping");
    1363 
    1364                 if (posKey && e.type == "keyup")
    1365                     tinyMCE.triggerNodeChange(false);
    1366 
    1367                 if (tinyMCE.isIE && e.ctrlKey)
    1368                     window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);
    1369             break;
    1370 
    1371             case "mousedown":
    1372             case "mouseup":
    1373             case "click":
    1374             case "dblclick":
    1375             case "focus":
    1376                 tinyMCE.hideMenus();
    1377 
    1378                 if (tinyMCE.selectedInstance) {
    1379                     tinyMCE.selectedInstance.switchSettings();
    1380                     tinyMCE.selectedInstance.isFocused = true;
    1381                 }
    1382 
    1383                 // Check instance event trigged on
    1384                 var targetBody = tinyMCE.getParentElement(e.target, "html");
    1385                 for (var instanceName in tinyMCE.instances) {
    1386                     if (!tinyMCE.isInstance(tinyMCE.instances[instanceName]))
    1387                         continue;
    1388 
    1389                     inst = tinyMCE.instances[instanceName];
    1390 
    1391                     // Reset design mode if lost (on everything just in case)
    1392                     inst.autoResetDesignMode();
    1393 
    1394                     // Use HTML element since users might click outside of body element
    1395                     if (inst.getBody().parentNode == targetBody) {
    1396                         inst.select();
    1397                         tinyMCE.selectedElement = e.target;
    1398                         tinyMCE.linkElement = tinyMCE.getParentElement(tinyMCE.selectedElement, "a");
    1399                         tinyMCE.imgElement = tinyMCE.getParentElement(tinyMCE.selectedElement, "img");
    1400                         break;
    1401                     }
    1402                 }
    1403 
    1404                 // Add first bookmark location
    1405                 if (!tinyMCE.selectedInstance.undoRedo.undoLevels[0].bookmark && (e.type == "mouseup" || e.type == "dblclick"))
    1406                     tinyMCE.selectedInstance.undoRedo.undoLevels[0].bookmark = tinyMCE.selectedInstance.selection.getBookmark();
    1407 
    1408                 // Reset selected node
    1409                 if (e.type != "focus")
    1410                     tinyMCE.selectedNode = null;
    1411 
    1412                 tinyMCE.triggerNodeChange(false);
    1413                 tinyMCE.execCommand("mceEndTyping");
    1414 
    1415                 if (e.type == "mouseup")
    1416                     tinyMCE.execCommand("mceAddUndoLevel");
    1417 
    1418                 // Just in case
    1419                 if (!tinyMCE.selectedInstance && e.target.editorId)
    1420                     tinyMCE.instances[e.target.editorId].select();
    1421 
    1422                 return false;
     554            }
     555
     556            if (bp == 1)
     557                return path;
     558
     559            for (i = 0; i < base.length - (bp - 1); i++)
     560                out += "../";
     561
     562            for (i = bp - 1; i < items.length; i++) {
     563                if (i != bp - 1)
     564                    out += "/" + items[i];
     565                else
     566                    out += items[i];
     567            }
     568
     569            return out;
     570        },
     571
     572        toAbsPath : function(base, path) {
     573            var i, nb = 0, o = [];
     574
     575            // Split paths
     576            base = base.split('/');
     577            path = path.split('/');
     578
     579            // Remove empty chunks
     580            each(base, function(k) {
     581                if (k)
     582                    o.push(k);
     583            });
     584
     585            base = o;
     586
     587            // Merge relURLParts chunks
     588            for (i = path.length - 1, o = []; i >= 0; i--) {
     589                // Ignore empty or .
     590                if (path[i].length == 0 || path[i] == ".")
     591                    continue;
     592
     593                // Is parent
     594                if (path[i] == '..') {
     595                    nb++;
     596                    continue;
     597                }
     598
     599                // Move up
     600                if (nb > 0) {
     601                    nb--;
     602                    continue;
     603                }
     604
     605                o.push(path[i]);
     606            }
     607
     608            i = base.length - nb;
     609
     610            // If /a/b/c or /
     611            if (i <= 0)
     612                return '/' + o.reverse().join('/');
     613
     614            return '/' + base.slice(0, i).join('/') + '/' + o.reverse().join('/');
     615        },
     616
     617        getURI : function(nh) {
     618            var s, t = this;
     619
     620            // Rebuild source
     621            if (!t.source || nh) {
     622                s = '';
     623
     624                if (!nh) {
     625                    if (t.protocol)
     626                        s += t.protocol + '://';
     627
     628                    if (t.userInfo)
     629                        s += t.userInfo + '@';
     630
     631                    if (t.host)
     632                        s += t.host;
     633
     634                    if (t.port)
     635                        s += ':' + t.port;
     636                }
     637
     638                if (t.path)
     639                    s += t.path;
     640
     641                if (t.query)
     642                    s += '?' + t.query;
     643
     644                if (t.anchor)
     645                    s += '#' + t.anchor;
     646
     647                t.source = s;
     648            }
     649
     650            return t.source;
    1423651        }
     652
     653        });
     654})();
     655
     656/* file:jscripts/tiny_mce/classes/util/Cookie.js */
     657
     658(function() {
     659    var each = tinymce.each;
     660
     661    tinymce.create('static tinymce.util.Cookie', {
     662        getHash : function(n) {
     663            var v = this.get(n), h;
     664
     665            if (v) {
     666                each(v.split('&'), function(v) {
     667                    v = v.split('=');
     668                    h = h || {};
     669                    h[unescape(v[0])] = unescape(v[1]);
     670                });
     671            }
     672
     673            return h;
     674        },
     675
     676        setHash : function(n, v, e, p, d, s) {
     677            var o = '';
     678
     679            each(v, function(v, k) {
     680                o += (!o ? '' : '&') + escape(k) + '=' + escape(v);
     681            });
     682
     683            this.set(n, o, e, p, d, s);
     684        },
     685
     686        get : function(n) {
     687            var c = document.cookie, e, p = n + "=", b;
     688
     689            // Strict mode
     690            if (!c)
     691                return;
     692
     693            b = c.indexOf("; " + p);
     694
     695            if (b == -1) {
     696                b = c.indexOf(p);
     697
     698                if (b != 0)
     699                    return null;
     700            } else
     701                b += 2;
     702
     703            e = c.indexOf(";", b);
     704
     705            if (e == -1)
     706                e = c.length;
     707
     708            return unescape(c.substring(b + p.length, e));
     709        },
     710
     711        set : function(n, v, e, p, d, s) {
     712            document.cookie = n + "=" + escape(v) +
     713                ((e) ? "; expires=" + e.toGMTString() : "") +
     714                ((p) ? "; path=" + escape(p) : "") +
     715                ((d) ? "; domain=" + d : "") +
     716                ((s) ? "; secure" : "");
     717        },
     718
     719        remove : function(n, p) {
     720            var d = new Date();
     721
     722            d.setTime(d.getTime() - 1000);
     723
     724            this.set(n, '', d, p, d);
     725        }
     726
     727        });
     728})();
     729
     730/* file:jscripts/tiny_mce/classes/util/JSON.js */
     731
     732tinymce.create('static tinymce.util.JSON', {
     733    serialize : function(o) {
     734        var i, v, s = tinymce.util.JSON.serialize, t;
     735
     736        if (o == null)
     737            return 'null';
     738
     739        t = typeof o;
     740
     741        if (t == 'string') {
     742            v = '\bb\tt\nn\ff\rr\""\'\'\\\\';
     743
     744            return '"' + o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'])/g, function(a, b) {
     745                i = v.indexOf(b);
     746
     747                if (i + 1)
     748                    return '\\' + v.charAt(i + 1);
     749
     750                a = b.charCodeAt().toString(16);
     751
     752                return '\\u' + '0000'.substring(a.length) + a;
     753            }) + '"';
     754        }
     755
     756        if (t == 'object') {
     757            if (o instanceof Array) {
     758                    for (i=0, v = '['; i<o.length; i++)
     759                        v += (i > 0 ? ',' : '') + s(o[i]);
     760
     761                    return v + ']';
     762                }
     763
     764                v = '{';
     765
     766                for (i in o)
     767                    v += typeof o[i] != 'function' ? (v.length > 1 ? ',"' : '"') + i + '":' + s(o[i]) : '';
     768
     769                return v + '}';
     770        }
     771
     772        return '' + o;
    1424773    },
    1425774
    1426     getButtonHTML : function(id, lang, img, cmd, ui, val) {
    1427         var h = '', m, x, io = '';
    1428 
    1429         cmd = 'tinyMCE.execInstanceCommand(\'{$editor_id}\',\'' + cmd + '\'';
    1430 
    1431         if (typeof(ui) != "undefined" && ui != null)
    1432             cmd += ',' + ui;
    1433 
    1434         if (typeof(val) != "undefined" && val != null)
    1435             cmd += ",'" + val + "'";
    1436 
    1437         cmd += ');';
    1438 
    1439         // Patch for IE7 bug with hover out not restoring correctly
    1440         if (tinyMCE.isRealIE)
    1441             io = 'onmouseover="tinyMCE.lastHover = this;"';
    1442 
    1443         // Use tilemaps when enabled and found and never in MSIE since it loads the tile each time from cache if cahce is disabled
    1444         if (tinyMCE.getParam('button_tile_map') && (!tinyMCE.isIE || tinyMCE.isOpera) && (m = this.buttonMap[id]) != null && (tinyMCE.getParam("language") == "en" || img.indexOf('$lang') == -1)) {
    1445             // Tiled button
    1446             x = 0 - (m * 20) == 0 ? '0' : 0 - (m * 20);
    1447             h += '<a id="{$editor_id}_' + id + '" href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" ' + io + ' class="mceTiledButton mceButtonNormal" target="_self">';
    1448             h += '<img src="{$themeurl}/images/spacer.gif" style="background-position: ' + x + 'px 0" alt="{$'+lang+'}" title="{$' + lang + '}" />';
    1449             h += '</a>';
    1450         } else {
    1451             // Normal button
    1452             h += '<a id="{$editor_id}_' + id + '" href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" ' + io + ' class="mceButtonNormal" target="_self">';
    1453             h += '<img src="' + img + '" alt="{$'+lang+'}" title="{$' + lang + '}" />';
    1454             h += '</a>';
    1455         }
    1456 
    1457         return h;
    1458     },
    1459 
    1460     getMenuButtonHTML : function(id, lang, img, mcmd, cmd, ui, val) {
    1461         var h = '', m, x;
    1462 
    1463         mcmd = 'tinyMCE.execInstanceCommand(\'{$editor_id}\',\'' + mcmd + '\');';
    1464         cmd = 'tinyMCE.execInstanceCommand(\'{$editor_id}\',\'' + cmd + '\'';
    1465 
    1466         if (typeof(ui) != "undefined" && ui != null)
    1467             cmd += ',' + ui;
    1468 
    1469         if (typeof(val) != "undefined" && val != null)
    1470             cmd += ",'" + val + "'";
    1471 
    1472         cmd += ');';
    1473 
    1474         // Use tilemaps when enabled and found and never in MSIE since it loads the tile each time from cache if cahce is disabled
    1475         if (tinyMCE.getParam('button_tile_map') && (!tinyMCE.isIE || tinyMCE.isOpera) && (m = tinyMCE.buttonMap[id]) != null && (tinyMCE.getParam("language") == "en" || img.indexOf('$lang') == -1)) {
    1476             x = 0 - (m * 20) == 0 ? '0' : 0 - (m * 20);
    1477 
    1478             if (tinyMCE.isRealIE)
    1479                 h += '<span id="{$editor_id}_' + id + '" class="mceMenuButton" onmouseover="tinyMCE._menuButtonEvent(\'over\',this);tinyMCE.lastHover = this;" onmouseout="tinyMCE._menuButtonEvent(\'out\',this);">';
    1480             else
    1481                 h += '<span id="{$editor_id}_' + id + '" class="mceMenuButton">';
    1482 
    1483             h += '<a href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" class="mceTiledButton mceMenuButtonNormal" target="_self">';
    1484             h += '<img src="{$themeurl}/images/spacer.gif" style="width: 20px; height: 20px; background-position: ' + x + 'px 0" title="{$' + lang + '}" /></a>';
    1485             h += '<a href="javascript:' + mcmd + '" onclick="' + mcmd + 'return false;" onmousedown="return false;"><img src="{$themeurl}/images/button_menu.gif" title="{$' + lang + '}" class="mceMenuButton" />';
    1486             h += '</a></span>';
    1487         } else {
    1488             if (tinyMCE.isRealIE)
    1489                 h += '<span id="{$editor_id}_' + id + '" dir="ltr" class="mceMenuButton" onmouseover="tinyMCE._menuButtonEvent(\'over\',this);tinyMCE.lastHover = this;" onmouseout="tinyMCE._menuButtonEvent(\'out\',this);">';
    1490             else
    1491                 h += '<span id="{$editor_id}_' + id + '" dir="ltr" class="mceMenuButton">';
    1492 
    1493             h += '<a href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" class="mceMenuButtonNormal" target="_self">';
    1494             h += '<img src="' + img + '" title="{$' + lang + '}" /></a>';
    1495             h += '<a href="javascript:' + mcmd + '" onclick="' + mcmd + 'return false;" onmousedown="return false;"><img src="{$themeurl}/images/button_menu.gif" title="{$' + lang + '}" class="mceMenuButton" />';
    1496             h += '</a></span>';
    1497         }
    1498 
    1499         return h;
    1500     },
    1501 
    1502     _menuButtonEvent : function(e, o) {
    1503         if (o.className == 'mceMenuButtonFocus')
    1504             return;
    1505 
    1506         if (e == 'over')
    1507             o.className = o.className + ' mceMenuHover';
    1508         else
    1509             o.className = o.className.replace(/\s.*$/, '');
    1510     },
    1511 
    1512     addButtonMap : function(m) {
    1513         var i, a = m.replace(/\s+/, '').split(',');
    1514 
    1515         for (i=0; i<a.length; i++)
    1516             this.buttonMap[a[i]] = i;
    1517     },
    1518 
    1519     formSubmit : function(f, p) {
    1520         var n, inst, found = false;
    1521 
    1522         if (f.form)
    1523             f = f.form;
    1524 
    1525         // Is it a form that has a TinyMCE instance
    1526         for (n in tinyMCE.instances) {
    1527             inst = tinyMCE.instances[n];
    1528 
    1529             if (!tinyMCE.isInstance(inst))
    1530                 continue;
    1531 
    1532             if (inst.formElement) {
    1533                 if (f == inst.formElement.form) {
    1534                     found = true;
    1535                     inst.isNotDirty = true;
    1536                 }
    1537             }
    1538         }
    1539 
    1540         // Is valid
    1541         if (found) {
    1542             tinyMCE.removeTinyMCEFormElements(f);
    1543             tinyMCE.triggerSave();
    1544         }
    1545 
    1546         // Is it patched
    1547         if (f.mceOldSubmit && p)
    1548             f.mceOldSubmit();
    1549     },
    1550 
    1551     submitPatch : function() {
    1552         tinyMCE.formSubmit(this, true);
    1553     },
    1554 
    1555     onLoad : function() {
    1556         var r, i, c, mode, trigger, elements, element, settings, elementId, elm;
    1557         var selector, deselector, elementRefAr, form;
    1558 
    1559         // Wait for everything to be loaded first
    1560         if (tinyMCE.settings.strict_loading_mode && this.loadingIndex != -1) {
    1561             window.setTimeout('tinyMCE.onLoad();', 1);
    1562             return;
    1563         }
    1564 
    1565         if (tinyMCE.isRealIE && window.event.type == "readystatechange" && document.readyState != "complete")
    1566             return true;
    1567 
    1568         if (tinyMCE.isLoaded)
    1569             return true;
    1570 
    1571         tinyMCE.isLoaded = true;
    1572 
    1573         // IE produces JS error if TinyMCE is placed in a frame
    1574         // It seems to have something to do with the selection not beeing
    1575         // correctly initialized in IE so this hack solves the problem
    1576         if (tinyMCE.isRealIE && document.body && window.location.href != window.top.location.href) {
    1577             r = document.body.createTextRange();
    1578             r.collapse(true);
    1579             r.select();
    1580         }
    1581 
    1582         tinyMCE.dispatchCallback(null, 'onpageload', 'onPageLoad');
    1583 
    1584         for (c=0; c<tinyMCE.configs.length; c++) {
    1585             tinyMCE.settings = tinyMCE.configs[c];
    1586 
    1587             selector = tinyMCE.getParam("editor_selector");
    1588             deselector = tinyMCE.getParam("editor_deselector");
    1589             elementRefAr = [];
    1590 
    1591             // Add submit triggers
    1592             if (document.forms && tinyMCE.settings.add_form_submit_trigger && !tinyMCE.submitTriggers) {
    1593                 for (i=0; i<document.forms.length; i++) {
    1594                     form = document.forms[i];
    1595 
    1596                     tinyMCE.addEvent(form, "submit", TinyMCE_Engine.prototype.handleEvent);
    1597                     tinyMCE.addEvent(form, "reset", TinyMCE_Engine.prototype.handleEvent);
    1598                     tinyMCE.submitTriggers = true; // Do it only once
    1599 
    1600                     // Patch the form.submit function
    1601                     if (tinyMCE.settings.submit_patch) {
    1602                         try {
    1603                             form.mceOldSubmit = form.submit;
    1604                             form.submit = TinyMCE_Engine.prototype.submitPatch;
    1605                         } catch (e) {
    1606                             // Do nothing
    1607                         }
    1608                     }
    1609                 }
    1610             }
    1611 
    1612             // Add editor instances based on mode
    1613             mode = tinyMCE.settings.mode;
    1614             switch (mode) {
    1615                 case "exact":
    1616                     elements = tinyMCE.getParam('elements', '', true, ',');
    1617 
    1618                     for (i=0; i<elements.length; i++) {
    1619                         element = tinyMCE._getElementById(elements[i]);
    1620                         trigger = element ? element.getAttribute(tinyMCE.settings.textarea_trigger) : "";
    1621 
    1622                         if (new RegExp('\\b' + deselector + '\\b').test(tinyMCE.getAttrib(element, "class")))
    1623                             continue;
    1624 
    1625                         if (trigger == "false")
    1626                             continue;
    1627 
    1628                         if ((tinyMCE.settings.ask || tinyMCE.settings.convert_on_click) && element) {
    1629                             elementRefAr[elementRefAr.length] = element;
    1630                             continue;
    1631                         }
    1632 
    1633                         if (element)
    1634                             tinyMCE.addMCEControl(element, elements[i]);
    1635                     }
    1636                 break;
    1637 
    1638                 case "specific_textareas":
    1639                 case "textareas":
    1640                     elements = document.getElementsByTagName("textarea");
    1641 
    1642                     for (i=0; i<elements.length; i++) {
    1643                         elm = elements.item(i);
    1644                         trigger = elm.getAttribute(tinyMCE.settings.textarea_trigger);
    1645 
    1646                         if (selector !== '' && !new RegExp('\\b' + selector + '\\b').test(tinyMCE.getAttrib(elm, "class")))
    1647                             continue;
    1648 
    1649                         if (selector !== '')
    1650                             trigger = selector !== '' ? "true" : "";
    1651 
    1652                         if (new RegExp('\\b' + deselector + '\\b').test(tinyMCE.getAttrib(elm, "class")))
    1653                             continue;
    1654 
    1655                         if ((mode == "specific_textareas" && trigger == "true") || (mode == "textareas" && trigger != "false"))
    1656                             elementRefAr[elementRefAr.length] = elm;
    1657                     }
    1658                 break;
    1659             }
    1660 
    1661             for (i=0; i<elementRefAr.length; i++) {
    1662                 element = elementRefAr[i];
    1663                 elementId = element.name ? element.name : element.id;
    1664 
    1665                 if (tinyMCE.settings.ask || tinyMCE.settings.convert_on_click) {
    1666                     // Focus breaks in Mozilla
    1667                     if (tinyMCE.isGecko) {
    1668                         settings = tinyMCE.settings;
    1669 
    1670                         tinyMCE.addEvent(element, "focus", function (e) {window.setTimeout(function() {TinyMCE_Engine.prototype.confirmAdd(e, settings);}, 10);});
    1671 
    1672                         if (element.nodeName != "TEXTAREA" && element.nodeName != "INPUT")
    1673                             tinyMCE.addEvent(element, "click", function (e) {window.setTimeout(function() {TinyMCE_Engine.prototype.confirmAdd(e, settings);}, 10);});
    1674                         // tinyMCE.addEvent(element, "mouseover", function (e) {window.setTimeout(function() {TinyMCE_Engine.prototype.confirmAdd(e, settings);}, 10);});
    1675                     } else {
    1676                         settings = tinyMCE.settings;
    1677 
    1678                         tinyMCE.addEvent(element, "focus", function () { TinyMCE_Engine.prototype.confirmAdd(null, settings); });
    1679                         tinyMCE.addEvent(element, "click", function () { TinyMCE_Engine.prototype.confirmAdd(null, settings); });
    1680                         // tinyMCE.addEvent(element, "mouseenter", function () { TinyMCE_Engine.prototype.confirmAdd(null, settings); });
    1681                     }
    1682                 } else
    1683                     tinyMCE.addMCEControl(element, elementId);
    1684             }
    1685 
    1686             // Handle auto focus
    1687             if (tinyMCE.settings.auto_focus) {
    1688                 window.setTimeout(function () {
    1689                     var inst = tinyMCE.getInstanceById(tinyMCE.settings.auto_focus);
    1690                     inst.selection.selectNode(inst.getBody(), true, true);
    1691                     inst.contentWindow.focus();
    1692                 }, 100);
    1693             }
    1694 
    1695             tinyMCE.dispatchCallback(null, 'oninit', 'onInit');
    1696         }
    1697     },
    1698 
    1699     isInstance : function(o) {
    1700         return o != null && typeof(o) == "object" && o.isTinyMCE_Control;
    1701     },
    1702 
    1703     getParam : function(name, default_value, strip_whitespace, split_chr) {
    1704         var i, outArray, value = (typeof(this.settings[name]) == "undefined") ? default_value : this.settings[name];
    1705 
    1706         // Fix bool values
    1707         if (value == "true" || value == "false")
    1708             return (value == "true");
    1709 
    1710         if (strip_whitespace)
    1711             value = tinyMCE.regexpReplace(value, "[ \t\r\n]", "");
    1712 
    1713         if (typeof(split_chr) != "undefined" && split_chr != null) {
    1714             value = value.split(split_chr);
    1715             outArray = [];
    1716 
    1717             for (i=0; i<value.length; i++) {
    1718                 if (value[i] && value[i] !== '')
    1719                     outArray[outArray.length] = value[i];
    1720             }
    1721 
    1722             value = outArray;
    1723         }
    1724 
    1725         return value;
    1726     },
    1727 
    1728     getLang : function(name, default_value, parse_entities, va) {
    1729         var v = (typeof(tinyMCELang[name]) == "undefined") ? default_value : tinyMCELang[name], n;
    1730 
    1731         if (parse_entities)
    1732             v = tinyMCE.entityDecode(v);
    1733 
    1734         if (va) {
    1735             for (n in va)
    1736                 v = this.replaceVar(v, n, va[n]);
    1737         }
    1738 
    1739         return v;
    1740     },
    1741 
    1742     entityDecode : function(s) {
    1743         var e = document.createElement("div");
    1744 
    1745         e.innerHTML = s;
    1746 
    1747         return !e.firstChild ? s : e.firstChild.nodeValue;
    1748     },
    1749 
    1750     addToLang : function(prefix, ar) {
    1751         var k;
    1752 
    1753         for (k in ar) {
    1754             if (typeof(ar[k]) == 'function')
    1755                 continue;
    1756 
    1757             tinyMCELang[(k.indexOf('lang_') == -1 ? 'lang_' : '') + (prefix !== '' ? (prefix + "_") : '') + k] = ar[k];
    1758         }
    1759 
    1760         this.loadNextScript();
    1761     },
    1762 
    1763     triggerNodeChange : function(focus, setup_content) {
    1764         var elm, inst, editorId, undoIndex = -1, undoLevels = -1, doc, anySelection = false, st;
    1765 
    1766         if (tinyMCE.selectedInstance) {
    1767             inst = tinyMCE.selectedInstance;
    1768             elm = (typeof(setup_content) != "undefined" && setup_content) ? tinyMCE.selectedElement : inst.getFocusElement();
    1769 
    1770 /*          if (elm == inst.lastTriggerEl)
    1771                 return;
    1772 
    1773             inst.lastTriggerEl = elm;*/
    1774 
    1775             editorId = inst.editorId;
    1776             st = inst.selection.getSelectedText();
    1777 
    1778             if (tinyMCE.settings.auto_resize)
    1779                 inst.resizeToContent();
    1780 
    1781             if (setup_content && tinyMCE.isGecko && inst.isHidden())
    1782                 elm = inst.getBody();
    1783 
    1784             inst.switchSettings();
    1785 
    1786             if (tinyMCE.selectedElement)
    1787                 anySelection = (tinyMCE.selectedElement.nodeName.toLowerCase() == "img") || (st && st.length > 0);
    1788 
    1789             if (tinyMCE.settings.custom_undo_redo) {
    1790                 undoIndex = inst.undoRedo.undoIndex;
    1791                 undoLevels = inst.undoRedo.undoLevels.length;
    1792             }
    1793 
    1794             tinyMCE.dispatchCallback(inst, 'handle_node_change_callback', 'handleNodeChange', editorId, elm, undoIndex, undoLevels, inst.visualAid, anySelection, setup_content);
    1795         }
    1796 
    1797         if (this.selectedInstance && (typeof(focus) == "undefined" || focus))
    1798             this.selectedInstance.contentWindow.focus();
    1799     },
    1800 
    1801     _customCleanup : function(inst, type, content) {
    1802         var pl, po, i, customCleanup;
    1803 
    1804         // Call custom cleanup
    1805         customCleanup = tinyMCE.settings.cleanup_callback;
    1806         if (customCleanup != '')
    1807             content = tinyMCE.resolveDots(tinyMCE.settings.cleanup_callback, window)(type, content, inst);
    1808 
    1809         // Trigger theme cleanup
    1810         po = tinyMCE.themes[tinyMCE.settings.theme];
    1811         if (po && po.cleanup)
    1812             content = po.cleanup(type, content, inst);
    1813 
    1814         // Trigger plugin cleanups
    1815         pl = inst.plugins;
    1816         for (i=0; i<pl.length; i++) {
    1817             po = tinyMCE.plugins[pl[i]];
    1818 
    1819             if (po && po.cleanup)
    1820                 content = po.cleanup(type, content, inst);
    1821         }
    1822 
    1823         return content;
    1824     },
    1825 
    1826     setContent : function(h) {
    1827         if (tinyMCE.selectedInstance) {
    1828             tinyMCE.selectedInstance.execCommand('mceSetContent', false, h);
    1829             tinyMCE.selectedInstance.repaint();
    1830         }
    1831     },
    1832 
    1833     importThemeLanguagePack : function(name) {
    1834         if (typeof(name) == "undefined")
    1835             name = tinyMCE.settings.theme;
    1836 
    1837         tinyMCE.loadScript(tinyMCE.baseURL + '/themes/' + name + '/langs/' + tinyMCE.settings.language + '.js');
    1838     },
    1839 
    1840     importPluginLanguagePack : function(name) {
    1841         var b = tinyMCE.baseURL + '/plugins/' + name;
    1842 
    1843         if (this.plugins[name])
    1844             b = this.plugins[name].baseURL;
    1845 
    1846         tinyMCE.loadScript(b + '/langs/' + tinyMCE.settings.language +  '.js');
    1847     },
    1848 
    1849     applyTemplate : function(h, ag) {
    1850         return h.replace(new RegExp('\\{\\$([a-z0-9_]+)\\}', 'gi'), function(m, s) {
    1851             if (s.indexOf('lang_') == 0 && tinyMCELang[s])
    1852                 return tinyMCELang[s];
    1853 
    1854             if (ag && ag[s])
    1855                 return ag[s];
    1856 
    1857             if (tinyMCE.settings[s])
    1858                 return tinyMCE.settings[s];
    1859 
    1860             if (m == 'themeurl')
    1861                 return tinyMCE.themeURL;
    1862 
    1863             return m;
    1864         });
    1865     },
    1866 
    1867     replaceVar : function(h, r, v) {
    1868         return h.replace(new RegExp('{\\\$' + r + '}', 'g'), v);
    1869     },
    1870 
    1871     openWindow : function(template, args) {
    1872         var html, width, height, x, y, resizable, scrollbars, url, name, win, modal, features;
    1873 
    1874         args = !args ? {} : args;
    1875 
    1876         args.mce_template_file = template.file;
    1877         args.mce_width = template.width;
    1878         args.mce_height = template.height;
    1879         tinyMCE.windowArgs = args;
    1880 
    1881         html = template.html;
    1882         if (!(width = parseInt(template.width)))
    1883             width = 320;
    1884 
    1885         if (!(height = parseInt(template.height)))
    1886             height = 200;
    1887 
    1888         // Add to height in M$ due to SP2 WHY DON'T YOU GUYS IMPLEMENT innerWidth of windows!!
    1889         if (tinyMCE.isIE)
    1890             height += 40;
    1891         else
    1892             height += 20;
    1893 
    1894         x = parseInt(screen.width / 2.0) - (width / 2.0);
    1895         y = parseInt(screen.height / 2.0) - (height / 2.0);
    1896 
    1897         resizable = (args && args.resizable) ? args.resizable : "no";
    1898         scrollbars = (args && args.scrollbars) ? args.scrollbars : "no";
    1899 
    1900         if (template.file.charAt(0) != '/' && template.file.indexOf('://') == -1)
    1901             url = tinyMCE.baseURL + "/themes/" + tinyMCE.getParam("theme") + "/" + template.file;
    1902         else
    1903             url = template.file;
    1904 
    1905         // Replace all args as variables in URL
    1906         for (name in args) {
    1907             if (typeof(args[name]) == 'function')
    1908                 continue;
    1909 
    1910             url = tinyMCE.replaceVar(url, name, escape(args[name]));
    1911         }
    1912 
    1913         if (html) {
    1914             html = tinyMCE.replaceVar(html, "css", this.settings.popups_css);
    1915             html = tinyMCE.applyTemplate(html, args);
    1916 
    1917             win = window.open("", "mcePopup" + new Date().getTime(), "top=" + y + ",left=" + x + ",scrollbars=" + scrollbars + ",dialog=yes,minimizable=" + resizable + ",modal=yes,width=" + width + ",height=" + height + ",resizable=" + resizable);
    1918             if (win == null) {
    1919                 alert(tinyMCELang.lang_popup_blocked);
    1920                 return;
    1921             }
    1922 
    1923             win.document.write(html);
    1924             win.document.close();
    1925             win.resizeTo(width, height);
    1926             win.focus();
    1927         } else {
    1928             if ((tinyMCE.isRealIE) && resizable != 'yes' && tinyMCE.settings.dialog_type == "modal") {
    1929                 height += 10;
    1930 
    1931                 features = "resizable:" + resizable + ";scroll:" + scrollbars + ";status:yes;center:yes;help:no;dialogWidth:" + width + "px;dialogHeight:" + height + "px;";
    1932 
    1933                 window.showModalDialog(url, window, features);
    1934             } else {
    1935                 modal = (resizable == "yes") ? "no" : "yes";
    1936 
    1937                 if (tinyMCE.isGecko && tinyMCE.isMac)
    1938                     modal = "no";
    1939 
    1940                 if (template.close_previous != "no")
    1941                     try {tinyMCE.lastWindow.close();} catch (ex) {}
    1942 
    1943                 win = window.open(url, "mcePopup" + new Date().getTime(), "top=" + y + ",left=" + x + ",scrollbars=" + scrollbars + ",dialog=" + modal + ",minimizable=" + resizable + ",modal=" + modal + ",width=" + width + ",height=" + height + ",resizable=" + resizable);
    1944                 if (win == null) {
    1945                     alert(tinyMCELang.lang_popup_blocked);
    1946                     return;
    1947                 }
    1948 
    1949                 if (template.close_previous != "no")
    1950                     tinyMCE.lastWindow = win;
    1951 
    1952                 try {
    1953                     win.resizeTo(width, height);
    1954                 } catch(e) {
    1955                     // Ignore
    1956                 }
    1957 
    1958                 // Make it bigger if statusbar is forced
    1959                 if (tinyMCE.isGecko) {
    1960                     if (win.document.defaultView.statusbar.visible)
    1961                         win.resizeBy(0, tinyMCE.isMac ? 10 : 24);
    1962                 }
    1963 
    1964                 win.focus();
    1965             }
    1966         }
    1967     },
    1968 
    1969     closeWindow : function(win) {
    1970         win.close();
    1971     },
    1972 
    1973     getVisualAidClass : function(class_name, state) {
    1974         var i, classNames, ar, className, aidClass = tinyMCE.settings.visual_table_class;
    1975 
    1976         if (typeof(state) == "undefined")
    1977             state = tinyMCE.settings.visual;
    1978 
    1979         // Split
    1980         classNames = [];
    1981         ar = class_name.split(' ');
    1982         for (i=0; i<ar.length; i++) {
    1983             if (ar[i] == aidClass)
    1984                 ar[i] = "";
    1985 
    1986             if (ar[i] !== '')
    1987                 classNames[classNames.length] = ar[i];
    1988         }
    1989 
    1990         if (state)
    1991             classNames[classNames.length] = aidClass;
    1992 
    1993         // Glue
    1994         className = "";
    1995         for (i=0; i<classNames.length; i++) {
    1996             if (i > 0)
    1997                 className += " ";
    1998 
    1999             className += classNames[i];
    2000         }
    2001 
    2002         return className;
    2003     },
    2004 
    2005     handleVisualAid : function(el, deep, state, inst, skip_dispatch) {
    2006         var i, x, y, tableElement, anchorName, oldW, oldH, bo, cn;
    2007 
    2008         if (!el)
    2009             return;
    2010 
    2011         if (!skip_dispatch)
    2012             tinyMCE.dispatchCallback(inst, 'handle_visual_aid_callback', 'handleVisualAid', el, deep, state, inst);
    2013 
    2014         tableElement = null;
    2015 
    2016         switch (el.nodeName) {
    2017             case "TABLE":
    2018                 oldW = el.style.width;
    2019                 oldH = el.style.height;
    2020                 bo = tinyMCE.getAttrib(el, "border");
    2021 
    2022                 bo = bo == '' || bo == "0" ? true : false;
    2023 
    2024                 tinyMCE.setAttrib(el, "class", tinyMCE.getVisualAidClass(tinyMCE.getAttrib(el, "class"), state && bo));
    2025 
    2026                 el.style.width = oldW;
    2027                 el.style.height = oldH;
    2028 
    2029                 for (y=0; y<el.rows.length; y++) {
    2030                     for (x=0; x<el.rows[y].cells.length; x++) {
    2031                         cn = tinyMCE.getVisualAidClass(tinyMCE.getAttrib(el.rows[y].cells[x], "class"), state && bo);
    2032                         tinyMCE.setAttrib(el.rows[y].cells[x], "class", cn);
    2033                     }
    2034                 }
    2035 
    2036                 break;
    2037 
    2038             case "A":
    2039                 anchorName = tinyMCE.getAttrib(el, "name");
    2040 
    2041                 if (anchorName !== '' && state) {
    2042                     el.title = anchorName;
    2043                     tinyMCE.addCSSClass(el, 'mceItemAnchor');
    2044                 } else if (anchorName !== '' && !state)
    2045                     el.className = '';
    2046 
    2047                 break;
    2048         }
    2049 
    2050         if (deep && el.hasChildNodes()) {
    2051             for (i=0; i<el.childNodes.length; i++)
    2052                 tinyMCE.handleVisualAid(el.childNodes[i], deep, state, inst, true);
    2053         }
    2054     },
    2055 
    2056     fixGeckoBaseHREFBug : function(m, e, h) {
    2057         var xsrc, xhref;
    2058 
    2059         if (tinyMCE.isGecko) {
    2060             if (m == 1) {
    2061                 h = h.replace(/\ssrc=/gi, " mce_tsrc=");
    2062                 h = h.replace(/\shref=/gi, " mce_thref=");
    2063 
    2064                 return h;
    2065             } else {
    2066                 // Why bother if there is no src or href broken
    2067                 if (!new RegExp('(src|href)=', 'g').test(h))
    2068                     return h;
    2069 
    2070                 // Restore src and href that gets messed up by Gecko
    2071                 tinyMCE.selectElements(e, 'A,IMG,SELECT,AREA,IFRAME,BASE,INPUT,SCRIPT,EMBED,OBJECT,LINK', function (n) {
    2072                     xsrc = tinyMCE.getAttrib(n, "mce_tsrc");
    2073                     xhref = tinyMCE.getAttrib(n, "mce_thref");
    2074 
    2075                     if (xsrc !== '') {
    2076                         try {
    2077                             n.src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, xsrc);
    2078                         } catch (e) {
    2079                             // Ignore, Firefox cast exception if local file wasn't found
    2080                         }
    2081 
    2082                         n.removeAttribute("mce_tsrc");
    2083                     }
    2084 
    2085                     if (xhref !== '') {
    2086                         try {
    2087                             n.href = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, xhref);
    2088                         } catch (e) {
    2089                             // Ignore, Firefox cast exception if local file wasn't found
    2090                         }
    2091 
    2092                         n.removeAttribute("mce_thref");
    2093                     }
    2094 
    2095                     return false;
    2096                 });
    2097 
    2098                 // Restore text/comment nodes
    2099                 tinyMCE.selectNodes(e, function(n) {
    2100                     if (n.nodeType == 3 || n.nodeType == 8) {
    2101                         n.nodeValue = n.nodeValue.replace(/\smce_tsrc=/gi, " src=");
    2102                         n.nodeValue = n.nodeValue.replace(/\smce_thref=/gi, " href=");
    2103                     }
    2104 
    2105                     return false;
    2106                 });
    2107             }
    2108         }
    2109 
    2110         return h;
    2111     },
    2112 
    2113     _setHTML : function(doc, html_content) {
    2114         var i, html, paras, node;
    2115 
    2116         // Force closed anchors open
    2117         //html_content = html_content.replace(new RegExp('<a(.*?)/>', 'gi'), '<a$1></a>');
    2118 
    2119         html_content = tinyMCE.cleanupHTMLCode(html_content);
    2120 
    2121         // Try innerHTML if it fails use pasteHTML in MSIE
     775    parse : function(s) {
    2122776        try {
    2123             tinyMCE.setInnerHTML(doc.body, html_content);
    2124         } catch (e) {
    2125             if (this.isMSIE)
    2126                 doc.body.createTextRange().pasteHTML(html_content);
    2127         }
    2128 
    2129         // Content duplication bug fix
    2130         if (tinyMCE.isIE && tinyMCE.settings.fix_content_duplication) {
    2131             // Remove P elements in P elements
    2132             paras = doc.getElementsByTagName("P");
    2133             for (i=0; i<paras.length; i++) {
    2134                 node = paras[i];
    2135 
    2136                 while ((node = node.parentNode) != null) {
    2137                     if (node.nodeName == "P")
    2138                         node.outerHTML = node.innerHTML;
    2139                 }
    2140             }
    2141 
    2142             // Content duplication bug fix (Seems to be word crap)
    2143             html = doc.body.innerHTML;
    2144 
    2145             // Always set the htmlText output
    2146             tinyMCE.setInnerHTML(doc.body, html);
    2147         }
    2148 
    2149         tinyMCE.cleanupAnchors(doc);
    2150 
    2151         if (tinyMCE.getParam("convert_fonts_to_spans"))
    2152             tinyMCE.convertSpansToFonts(doc);
    2153     },
    2154 
    2155     getEditorId : function(form_element) {
    2156         var inst = this.getInstanceById(form_element);
    2157 
    2158         if (!inst)
    2159             return null;
    2160 
    2161         return inst.editorId;
    2162     },
    2163 
    2164     getInstanceById : function(editor_id) {
    2165         var inst = this.instances[editor_id], n;
    2166 
    2167         if (!inst) {
    2168             for (n in tinyMCE.instances) {
    2169                 inst = tinyMCE.instances[n];
    2170 
    2171                 if (!tinyMCE.isInstance(inst))
    2172                     continue;
    2173 
    2174                 if (inst.formTargetElementId == editor_id)
    2175                     return inst;
    2176             }
    2177         } else
    2178             return inst;
    2179 
    2180         return null;
    2181     },
    2182 
    2183     queryInstanceCommandValue : function(editor_id, command) {
    2184         var inst = tinyMCE.getInstanceById(editor_id);
    2185 
    2186         if (inst)
    2187             return inst.queryCommandValue(command);
    2188 
    2189         return false;
    2190     },
    2191 
    2192     queryInstanceCommandState : function(editor_id, command) {
    2193         var inst = tinyMCE.getInstanceById(editor_id);
    2194 
    2195         if (inst)
    2196             return inst.queryCommandState(command);
    2197 
    2198         return null;
    2199     },
    2200 
    2201     setWindowArg : function(n, v) {
    2202         this.windowArgs[n] = v;
    2203     },
    2204 
    2205     getWindowArg : function(n, d) {
    2206         return (typeof(this.windowArgs[n]) == "undefined") ? d : this.windowArgs[n];
    2207     },
    2208 
    2209     getCSSClasses : function(editor_id, doc) {
    2210         var i, c, x, rule, styles, rules, csses, selectorText, inst = tinyMCE.getInstanceById(editor_id);
    2211         var cssClass, addClass, p;
    2212 
    2213         if (!inst)
    2214             inst = tinyMCE.selectedInstance;
    2215 
    2216         if (!inst)
    2217             return [];
    2218 
    2219         if (!doc)
    2220             doc = inst.getDoc();
    2221 
    2222         // Is cached, use that
    2223         if (inst && inst.cssClasses.length > 0)
    2224             return inst.cssClasses;
    2225 
    2226         if (!doc)
    2227             return;
    2228 
    2229         styles = doc.styleSheets;
    2230 
    2231         if (styles && styles.length > 0) {
    2232             for (x=0; x<styles.length; x++) {
    2233                 csses = null;
    2234 
    2235                 try {
    2236                     csses = tinyMCE.isIE ? doc.styleSheets(x).rules : styles[x].cssRules;
    2237                 } catch(e) {
    2238                     // Just ignore any errors I know this is ugly!!
    2239                 }
    2240    
    2241                 if (!csses)
    2242                     return [];
    2243 
    2244                 for (i=0; i<csses.length; i++) {
    2245                     selectorText = csses[i].selectorText;
    2246 
    2247                     // Can be multiple rules per selector
    2248                     if (selectorText) {
    2249                         rules = selectorText.split(',');
    2250                         for (c=0; c<rules.length; c++) {
    2251                             rule = rules[c];
    2252 
    2253                             // Strip spaces between selectors
    2254                             while (rule.indexOf(' ') == 0)
    2255                                 rule = rule.substring(1);
    2256 
    2257                             // Invalid rule
    2258                             if (rule.indexOf(' ') != -1 || rule.indexOf(':') != -1 || rule.indexOf('mceItem') != -1)
    2259                                 continue;
    2260 
    2261                             if (rule.indexOf(tinyMCE.settings.visual_table_class) != -1 || rule.indexOf('mceEditable') != -1 || rule.indexOf('mceNonEditable') != -1)
    2262                                 continue;
    2263 
    2264                             // Is class rule
    2265                             if (rule.indexOf('.') != -1) {
    2266                                 cssClass = rule.substring(rule.indexOf('.') + 1);
    2267                                 addClass = true;
    2268 
    2269                                 for (p=0; p<inst.cssClasses.length && addClass; p++) {
    2270                                     if (inst.cssClasses[p] == cssClass)
    2271                                         addClass = false;
    2272                                 }
    2273 
    2274                                 if (addClass)
    2275                                     inst.cssClasses[inst.cssClasses.length] = cssClass;
    2276                             }
    2277                         }
    2278                     }
    2279                 }
    2280             }
    2281         }
    2282 
    2283         return inst.cssClasses;
    2284     },
    2285 
    2286     regexpReplace : function(in_str, reg_exp, replace_str, opts) {
    2287         var re;
    2288 
    2289         if (in_str == null)
    2290             return in_str;
    2291 
    2292         if (typeof(opts) == "undefined")
    2293             opts = 'g';
    2294 
    2295         re = new RegExp(reg_exp, opts);
    2296 
    2297         return in_str.replace(re, replace_str);
    2298     },
    2299 
    2300     trim : function(s) {
    2301         return s.replace(/^\s*|\s*$/g, "");
    2302     },
    2303 
    2304     cleanupEventStr : function(s) {
    2305         s = "" + s;
    2306         s = s.replace('function anonymous()\n{\n', '');
    2307         s = s.replace('\n}', '');
    2308         s = s.replace(/^return true;/gi, ''); // Remove event blocker
    2309 
    2310         return s;
    2311     },
    2312 
    2313     getControlHTML : function(c) {
    2314         var i, l, n, o, v, rtl = tinyMCE.getLang('lang_dir') == 'rtl';
    2315 
    2316         l = tinyMCE.plugins;
    2317         for (n in l) {
    2318             o = l[n];
    2319 
    2320             if (o.getControlHTML && (v = o.getControlHTML(c)) !== '') {
    2321                 if (rtl)
    2322                     return '<span dir="rtl">' + tinyMCE.replaceVar(v, "pluginurl", o.baseURL) + '</span>';
    2323 
    2324                 return tinyMCE.replaceVar(v, "pluginurl", o.baseURL);
    2325             }
    2326         }
    2327 
    2328         o = tinyMCE.themes[tinyMCE.settings.theme];
    2329         if (o.getControlHTML && (v = o.getControlHTML(c)) !== '') {
    2330             if (rtl)
    2331                 return '<span dir="rtl">' + v + '</span>';
    2332 
    2333             return v;
    2334         }
    2335 
    2336         return '';
    2337     },
    2338 
    2339     evalFunc : function(f, idx, a, o) {
    2340         o = !o ? window : o;
    2341         f = typeof(f) == 'function' ? f : o[f];
    2342 
    2343         return f.apply(o, Array.prototype.slice.call(a, idx));
    2344     },
    2345 
    2346     dispatchCallback : function(i, p, n) {
    2347         return this.callFunc(i, p, n, 0, this.dispatchCallback.arguments);
    2348     },
    2349 
    2350     executeCallback : function(i, p, n) {
    2351         return this.callFunc(i, p, n, 1, this.executeCallback.arguments);
    2352     },
    2353 
    2354     execCommandCallback : function(i, p, n) {
    2355         return this.callFunc(i, p, n, 2, this.execCommandCallback.arguments);
    2356     },
    2357 
    2358     callFunc : function(ins, p, n, m, a) {
    2359         var l, i, on, o, s, v;
    2360 
    2361         s = m == 2;
    2362 
    2363         l = tinyMCE.getParam(p, '');
    2364 
    2365         if (l !== '' && (v = tinyMCE.evalFunc(l, 3, a)) == s && m > 0)
    2366             return true;
    2367 
    2368         if (ins != null) {
    2369             for (i=0, l = ins.plugins; i<l.length; i++) {
    2370                 o = tinyMCE.plugins[l[i]];
    2371 
    2372                 if (o[n] && (v = tinyMCE.evalFunc(n, 3, a, o)) == s && m > 0)
    2373                     return true;
    2374             }
    2375         }
    2376 
    2377         l = tinyMCE.themes;
    2378         for (on in l) {
    2379             o = l[on];
    2380 
    2381             if (o[n] && (v = tinyMCE.evalFunc(n, 3, a, o)) == s && m > 0)
    2382                 return true;
    2383         }
    2384 
    2385         return false;
    2386     },
    2387 
    2388     resolveDots : function(s, o) {
    2389         var i;
    2390 
    2391         if (typeof(s) == 'string') {
    2392             for (i=0, s=s.split('.'); i<s.length; i++)
    2393                 o = o[s[i]];
    2394         } else
    2395             o = s;
    2396 
    2397         return o;
    2398     },
    2399 
    2400     xmlEncode : function(s) {
    2401         return s ? ('' + s).replace(this.xmlEncodeRe, function (c, b) {
    2402             switch (c) {
    2403                 case '&':
    2404                     return '&amp;';
    2405 
    2406                 case '"':
    2407                     return '&quot;';
    2408 
    2409                 case '<':
    2410                     return '&lt;';
    2411 
    2412                 case '>':
    2413                     return '&gt;';
    2414             }
    2415 
    2416             return c;
    2417         }) : s;
    2418     },
    2419 
    2420     add : function(c, m) {
    2421         var n;
    2422 
    2423         for (n in m)
    2424             c.prototype[n] = m[n];
    2425     },
    2426 
    2427     extend : function(p, np) {
    2428         var o = {}, n;
    2429 
    2430         o.parent = p;
    2431 
    2432         for (n in p)
    2433             o[n] = p[n];
    2434 
    2435         for (n in np)
    2436             o[n] = np[n];
    2437 
    2438         return o;
    2439     },
    2440 
    2441     hideMenus : function() {
    2442         var e = tinyMCE.lastSelectedMenuBtn;
    2443 
    2444         if (tinyMCE.lastMenu) {
    2445             tinyMCE.lastMenu.hide();
    2446             tinyMCE.lastMenu = null;
    2447         }
    2448 
    2449         if (e) {
    2450             tinyMCE.switchClass(e, tinyMCE.lastMenuBtnClass);
    2451             tinyMCE.lastSelectedMenuBtn = null;
    2452         }
    2453     }
    2454 
    2455     };
    2456 
    2457 // Global instances
    2458 var TinyMCE = TinyMCE_Engine; // Compatiblity with gzip compressors
    2459 var tinyMCE = new TinyMCE_Engine();
    2460 var tinyMCELang = {};
    2461 
    2462 /* file:jscripts/tiny_mce/classes/TinyMCE_Control.class.js */
    2463 
    2464 function TinyMCE_Control(settings) {
    2465     var t, i, tos, fu, p, x, fn, fu, pn, s = settings;
    2466 
    2467     this.undoRedoLevel = true;
    2468     this.isTinyMCE_Control = true;
    2469 
    2470     // Default settings
    2471     this.enabled = true;
    2472     this.settings = s;
    2473     this.settings.theme = tinyMCE.getParam("theme", "default");
    2474     this.settings.width = tinyMCE.getParam("width", -1);
    2475     this.settings.height = tinyMCE.getParam("height", -1);
    2476     this.selection = new TinyMCE_Selection(this);
    2477     this.undoRedo = new TinyMCE_UndoRedo(this);
    2478     this.cleanup = new TinyMCE_Cleanup();
    2479     this.shortcuts = [];
    2480     this.hasMouseMoved = false;
    2481     this.foreColor = this.backColor = "#999999";
    2482     this.data = {};
    2483     this.cssClasses = [];
    2484 
    2485     this.cleanup.init({
    2486         valid_elements : s.valid_elements,
    2487         extended_valid_elements : s.extended_valid_elements,
    2488         valid_child_elements : s.valid_child_elements,
    2489         entities : s.entities,
    2490         entity_encoding : s.entity_encoding,
    2491         debug : s.cleanup_debug,
    2492         indent : s.apply_source_formatting,
    2493         invalid_elements : s.invalid_elements,
    2494         verify_html : s.verify_html,
    2495         fix_content_duplication : s.fix_content_duplication,
    2496         convert_fonts_to_spans : s.convert_fonts_to_spans
    2497     });
    2498 
    2499     // Wrap old theme
    2500     t = this.settings.theme;
    2501     if (!tinyMCE.hasTheme(t)) {
    2502         fn = tinyMCE.callbacks;
    2503         tos = {};
    2504 
    2505         for (i=0; i<fn.length; i++) {
    2506             if ((fu = window['TinyMCE_' + t + "_" + fn[i]]))
    2507                 tos[fn[i]] = fu;
    2508         }
    2509 
    2510         tinyMCE.addTheme(t, tos);
    2511     }
    2512 
    2513     // Wrap old plugins
    2514     this.plugins = [];
    2515     p = tinyMCE.getParam('plugins', '', true, ',');
    2516     if (p.length > 0) {
    2517         for (i=0; i<p.length; i++) {
    2518             pn = p[i];
    2519 
    2520             if (pn.charAt(0) == '-')
    2521                 pn = pn.substring(1);
    2522 
    2523             if (!tinyMCE.hasPlugin(pn)) {
    2524                 fn = tinyMCE.callbacks;
    2525                 tos = {};
    2526 
    2527                 for (x=0; x<fn.length; x++) {
    2528                     if ((fu = window['TinyMCE_' + pn + "_" + fn[x]]))
    2529                         tos[fn[x]] = fu;
    2530                 }
    2531 
    2532                 tinyMCE.addPlugin(pn, tos);
    2533             }
    2534 
    2535             this.plugins[this.plugins.length] = pn;
    2536         }
    2537     }
    2538 };
    2539 
    2540 TinyMCE_Control.prototype = {
    2541     selection : null,
    2542 
    2543     settings : null,
    2544 
    2545     cleanup : null,
    2546 
    2547     getData : function(na) {
    2548         var o = this.data[na];
    2549 
    2550         if (!o)
    2551             o = this.data[na] = {};
    2552 
    2553         return o;
    2554     },
    2555 
    2556     hasPlugin : function(n) {
    2557         var i;
    2558 
    2559         for (i=0; i<this.plugins.length; i++) {
    2560             if (this.plugins[i] == n)
    2561                 return true;
    2562         }
    2563 
    2564         return false;
    2565     },
    2566 
    2567     addPlugin : function(n, p) {
    2568         if (!this.hasPlugin(n)) {
    2569             tinyMCE.addPlugin(n, p);
    2570             this.plugins[this.plugins.length] = n;
    2571         }
    2572     },
    2573 
    2574     repaint : function() {
    2575         var s, b, ex;
    2576 
    2577         if (tinyMCE.isRealIE)
    2578             return;
    2579 
    2580         try {
    2581             s = this.selection;
    2582             b = s.getBookmark(true);
    2583             this.getBody().style.display = 'none';
    2584             this.getDoc().execCommand('selectall', false, null);
    2585             this.getSel().collapseToStart();
    2586             this.getBody().style.display = 'block';
    2587             s.moveToBookmark(b);
     777            return eval('(' + s + ')');
    2588778        } catch (ex) {
    2589779            // Ignore
    2590780        }
    2591     },
    2592 
    2593     switchSettings : function() {
    2594         if (tinyMCE.configs.length > 1 && tinyMCE.currentConfig != this.settings.index) {
    2595             tinyMCE.settings = this.settings;
    2596             tinyMCE.currentConfig = this.settings.index;
     781    }
     782
     783    });
     784
     785/* file:jscripts/tiny_mce/classes/util/XHR.js */
     786
     787tinymce.create('static tinymce.util.XHR', {
     788    send : function(o) {
     789        var x, t, w = window, c = 0;
     790
     791        // Default settings
     792        o.scope = o.scope || this;
     793        o.success_scope = o.success_scope || o.scope;
     794        o.error_scope = o.error_scope || o.scope;
     795        o.async = o.async === false ? false : true;
     796        o.data = o.data || '';
     797
     798        function get(s) {
     799            x = 0;
     800
     801            try {
     802                x = new ActiveXObject(s);
     803            } catch (ex) {
     804            }
     805
     806            return x;
     807        };
     808
     809        x = w.XMLHttpRequest ? new XMLHttpRequest() : get('Microsoft.XMLHTTP') || get('Msxml2.XMLHTTP');
     810
     811        if (x) {
     812            if (x.overrideMimeType)
     813                x.overrideMimeType(o.content_type);
     814
     815            x.open(o.type || (o.data ? 'POST' : 'GET'), o.url, o.async);
     816
     817            if (o.content_type)
     818                x.setRequestHeader('Content-Type', o.content_type);
     819
     820            x.send(o.data);
     821
     822            // Wait for response, onReadyStateChange can not be used since it leaks memory in IE
     823            t = w.setInterval(function() {
     824                if (x.readyState == 4 || c++ > 10000) {
     825                    w.clearInterval(t);
     826
     827                    if (o.success && c < 10000 && x.status == 200)
     828                        o.success.call(o.success_scope, '' + x.responseText, x, o);
     829                    else if (o.error)
     830                        o.error.call(o.error_scope, c > 10000 ? 'TIMED_OUT' : 'GENERAL', x, o);
     831
     832                    x = null;
     833                }
     834            }, 10);
    2597835        }
    2598     },
    2599 
    2600     select : function() {
    2601         var oldInst = tinyMCE.selectedInstance;
    2602 
    2603         if (oldInst != this) {
    2604             if (oldInst)
    2605                 oldInst.execCommand('mceEndTyping');
    2606 
    2607             tinyMCE.dispatchCallback(this, 'select_instance_callback', 'selectInstance', this, oldInst);
    2608             tinyMCE.selectedInstance = this;
     836
    2609837        }
    2610     },
    2611 
    2612     getBody : function() {
    2613         return this.contentBody ? this.contentBody : this.getDoc().body;
    2614     },
    2615 
    2616     getDoc : function() {
    2617 //      return this.contentDocument ? this.contentDocument : this.contentWindow.document; // Removed due to IE 5.5 ?
    2618         return this.contentWindow.document;
    2619     },
    2620 
    2621     getWin : function() {
    2622         return this.contentWindow;
    2623     },
    2624 
    2625     getContainerWin : function() {
    2626         return this.containerWindow ? this.containerWindow : window;
    2627     },
    2628 
    2629     getViewPort : function() {
    2630         return tinyMCE.getViewPort(this.getWin());
    2631     },
    2632 
    2633     getParentNode : function(n, f) {
    2634         return tinyMCE.getParentNode(n, f, this.getBody());
    2635     },
    2636 
    2637     getParentElement : function(n, na, f) {
    2638         return tinyMCE.getParentElement(n, na, f, this.getBody());
    2639     },
    2640 
    2641     getParentBlockElement : function(n) {
    2642         return tinyMCE.getParentBlockElement(n, this.getBody());
    2643     },
    2644 
    2645     resizeToContent : function() {
    2646         var d = this.getDoc(), b = d.body, de = d.documentElement;
    2647 
    2648         this.iframeElement.style.height = (tinyMCE.isRealIE) ? b.scrollHeight : de.offsetHeight + 'px';
    2649     },
    2650 
    2651     addShortcut : function(m, k, d, cmd, ui, va) {
    2652         var n = typeof(k) == "number", ie = tinyMCE.isIE, c, sc, i, scl = this.shortcuts;
    2653 
    2654         if (!tinyMCE.getParam('custom_shortcuts'))
    2655             return false;
    2656 
    2657         m = m.toLowerCase();
    2658         k = ie && !n ? k.toUpperCase() : k;
    2659         c = n ? null : k.charCodeAt(0);
    2660         d = d && d.indexOf('lang_') == 0 ? tinyMCE.getLang(d) : d;
    2661 
    2662         sc = {
    2663             alt : m.indexOf('alt') != -1,
    2664             ctrl : m.indexOf('ctrl') != -1,
    2665             shift : m.indexOf('shift') != -1,
    2666             charCode : c,
    2667             keyCode : n ? k : (ie ? c : null),
    2668             desc : d,
    2669             cmd : cmd,
    2670             ui : ui,
    2671             val : va
    2672         };
    2673 
    2674         for (i=0; i<scl.length; i++) {
    2675             if (sc.alt == scl[i].alt && sc.ctrl == scl[i].ctrl && sc.shift == scl[i].shift
    2676                 && sc.charCode == scl[i].charCode && sc.keyCode == scl[i].keyCode) {
    2677                 return false;
     838});
     839
     840/* file:jscripts/tiny_mce/classes/util/JSONRequest.js */
     841
     842(function() {
     843    var extend = tinymce.extend, JSON = tinymce.util.JSON, XHR = tinymce.util.XHR;
     844
     845    tinymce.create('tinymce.util.JSONRequest', {
     846        JSONRequest : function(s) {
     847            this.settings = extend({
     848            }, s);
     849            this.count = 0;
     850        },
     851
     852        send : function(o) {
     853            var ecb = o.error, scb = o.success;
     854
     855            o = extend(this.settings, o);
     856
     857            o.success = function(c, x) {
     858                c = JSON.parse(c);
     859
     860                if (typeof(c) == 'undefined') {
     861                    c = {
     862                        error : 'JSON Parse error.'
     863                    };
     864                }
     865
     866                if (c.error)
     867                    ecb.call(o.error_scope || o.scope, c.error, x);
     868                else
     869                    scb.call(o.success_scope || o.scope, c.result);
     870            };
     871
     872            o.error = function(ty, x) {
     873                ecb.call(o.error_scope || o.scope, ty, x);
     874            };
     875
     876            o.data = JSON.serialize({
     877                id : o.id || 'c' + (this.count++),
     878                method : o.method,
     879                params : o.params
     880            });
     881
     882            XHR.send(o);
     883        },
     884
     885        'static' : {
     886            sendRPC : function(o) {
     887                return new tinymce.util.JSONRequest().send(o);
    2678888            }
    2679889        }
    2680890
    2681         scl[scl.length] = sc;
    2682 
    2683         return true;
    2684     },
    2685 
    2686     handleShortcut : function(e) {
    2687         var i, s, o;
    2688 
    2689         // Normal key press, then ignore it
    2690         if (!e.altKey && !e.ctrlKey)
    2691             return false;
    2692 
    2693         s = this.shortcuts;
    2694 
    2695         for (i=0; i<s.length; i++) {
    2696             o = s[i];
    2697 
    2698             if (o.alt == e.altKey && o.ctrl == e.ctrlKey && (o.keyCode == e.keyCode || o.charCode == e.charCode)) {
    2699                 if (o.cmd && (e.type == "keydown" || (e.type == "keypress" && !tinyMCE.isOpera)))
    2700                     tinyMCE.execCommand(o.cmd, o.ui, o.val);
    2701 
    2702                 tinyMCE.cancelEvent(e);
    2703                 return true;
    2704             }
    2705         }
    2706 
    2707         return false;
    2708     },
    2709 
    2710     autoResetDesignMode : function() {
    2711         // Add fix for tab/style.display none/block problems in Gecko
    2712         if (!tinyMCE.isIE && this.isHidden() && tinyMCE.getParam('auto_reset_designmode'))
    2713             eval('try { this.getDoc().designMode = "On"; this.useCSS = false; } catch(e) {}');
    2714     },
    2715 
    2716     isHidden : function() {
    2717         var s;
    2718 
    2719         if (tinyMCE.isIE)
    2720             return false;
    2721 
    2722         s = this.getSel();
    2723 
    2724         // Weird, wheres that cursor selection?
    2725         return (!s || !s.rangeCount || s.rangeCount == 0);
    2726     },
    2727 
    2728     isDirty : function() {
    2729         // Is content modified and not in a submit procedure
    2730         return tinyMCE.trim(this.startContent) != tinyMCE.trim(this.getBody().innerHTML) && !this.isNotDirty;
    2731     },
    2732 
    2733     _mergeElements : function(scmd, pa, ch, override) {
    2734         var st, stc, className, n;
    2735 
    2736         if (scmd == "removeformat") {
    2737             pa.className = "";
    2738             pa.style.cssText = "";
    2739             ch.className = "";
    2740             ch.style.cssText = "";
    2741             return;
    2742         }
    2743 
    2744         st = tinyMCE.parseStyle(tinyMCE.getAttrib(pa, "style"));
    2745         stc = tinyMCE.parseStyle(tinyMCE.getAttrib(ch, "style"));
    2746         className = tinyMCE.getAttrib(pa, "class");
    2747 
    2748         // Removed class adding due to bug #1478272
    2749         className = tinyMCE.getAttrib(ch, "class");
    2750 
    2751         if (override) {
    2752             for (n in st) {
    2753                 if (typeof(st[n]) == 'function')
    2754                     continue;
    2755 
    2756                 stc[n] = st[n];
    2757             }
    2758         } else {
    2759             for (n in stc) {
    2760                 if (typeof(stc[n]) == 'function')
    2761                     continue;
    2762 
    2763                 st[n] = stc[n];
    2764             }
    2765         }
    2766 
    2767         tinyMCE.setAttrib(pa, "style", tinyMCE.serializeStyle(st));
    2768         tinyMCE.setAttrib(pa, "class", tinyMCE.trim(className));
    2769         ch.className = "";
    2770         ch.style.cssText = "";
    2771         ch.removeAttribute("class");
    2772         ch.removeAttribute("style");
    2773     },
    2774 
    2775     _fixRootBlocks : function() {
    2776         var rb, b, ne, be, nx, bm;
    2777 
    2778         rb = tinyMCE.getParam('forced_root_block');
    2779         if (!rb)
    2780             return;
    2781 
    2782         b = this.getBody();
    2783         ne = b.firstChild;
    2784 
    2785         while (ne) {
    2786             nx = ne.nextSibling;
    2787 
    2788             // If text node or inline element wrap it in a block element
    2789             if (ne.nodeType == 3 || !tinyMCE.blockRegExp.test(ne.nodeName)) {
    2790                 if (!bm)
    2791                     bm = this.selection.getBookmark();
    2792 
    2793                 if (!be) {
    2794                     be = this.getDoc().createElement(rb);
    2795                     be.appendChild(ne.cloneNode(true));
    2796                     b.replaceChild(be, ne);
    2797                 } else {
    2798                     be.appendChild(ne.cloneNode(true));
    2799                     b.removeChild(ne);
    2800                 }
    2801             } else
    2802                 be = null;
    2803 
    2804             ne = nx;
    2805         }
    2806 
    2807         if (bm)
    2808             this.selection.moveToBookmark(bm);
    2809     },
    2810 
    2811     _fixTrailingNbsp : function() {
    2812         var s = this.selection, e = s.getFocusElement(), bm, v;
    2813 
    2814         if (e && tinyMCE.blockRegExp.test(e.nodeName) && e.firstChild) {
    2815             v = e.firstChild.nodeValue;
    2816 
    2817             if (v && v.length > 1 && /(^\u00a0|\u00a0$)/.test(v)) {
    2818                 e.firstChild.nodeValue = v.replace(/(^\u00a0|\u00a0$)/, '');
    2819                 s.selectNode(e.firstChild, true, false, false); // Select and collapse
    2820             }
    2821         }
    2822     },
    2823 
    2824     _setUseCSS : function(b) {
    2825         var d = this.getDoc();
    2826 
    2827         try {d.execCommand("useCSS", false, !b);} catch (ex) {}
    2828         try {d.execCommand("styleWithCSS", false, b);} catch (ex) {}
    2829 
    2830         if (!tinyMCE.getParam("table_inline_editing"))
    2831             try {d.execCommand('enableInlineTableEditing', false, "false");} catch (ex) {}
    2832 
    2833         if (!tinyMCE.getParam("object_resizing"))
    2834             try {d.execCommand('enableObjectResizing', false, "false");} catch (ex) {}
    2835     },
    2836 
    2837     execCommand : function(command, user_interface, value) {
    2838         var i, x, z, align, img, div, doc = this.getDoc(), win = this.getWin(), focusElm = this.getFocusElement();
    2839 
    2840         // Is not a undo specific command
    2841         if (!new RegExp('mceStartTyping|mceEndTyping|mceBeginUndoLevel|mceEndUndoLevel|mceAddUndoLevel', 'gi').test(command))
    2842             this.undoBookmark = null;
    2843 
    2844         // Mozilla issue
    2845         if (!tinyMCE.isIE && !this.useCSS) {
    2846             this._setUseCSS(false);
    2847             this.useCSS = true;
    2848         }
    2849 
    2850         //debug("command: " + command + ", user_interface: " + user_interface + ", value: " + value);
    2851         this.contentDocument = doc; // <-- Strange, unless this is applied Mozilla 1.3 breaks
    2852 
    2853         // Don't dispatch key commands
    2854         if (!/mceStartTyping|mceEndTyping/.test(command)) {
    2855             if (tinyMCE.execCommandCallback(this, 'execcommand_callback', 'execCommand', this.editorId, this.getBody(), command, user_interface, value))
    2856                 return;
    2857         }
    2858 
    2859         // Fix align on images
    2860         if (focusElm && focusElm.nodeName == "IMG") {
    2861             align = focusElm.getAttribute('align');
    2862             img = command == "JustifyCenter" ? focusElm.cloneNode(false) : focusElm;
    2863 
    2864             switch (command) {
    2865                 case "JustifyLeft":
    2866                     if (align == 'left')
    2867                         img.removeAttribute('align');
    2868                     else
    2869                         img.setAttribute('align', 'left');
    2870 
    2871                     // Remove the div
    2872                     div = focusElm.parentNode;
    2873                     if (div && div.nodeName == "DIV" && div.childNodes.length == 1 && div.parentNode)
    2874                         div.parentNode.replaceChild(img, div);
    2875 
    2876                     this.selection.selectNode(img);
    2877                     this.repaint();
    2878                     tinyMCE.triggerNodeChange();
    2879                     return;
    2880 
    2881                 case "JustifyCenter":
    2882                     img.removeAttribute('align');
    2883 
    2884                     // Is centered
    2885                     div = tinyMCE.getParentElement(focusElm, "div");
    2886                     if (div && div.style.textAlign == "center") {
    2887                         // Remove div
    2888                         if (div.nodeName == "DIV" && div.childNodes.length == 1 && div.parentNode)
    2889                             div.parentNode.replaceChild(img, div);
    2890                     } else {
    2891                         // Add div
    2892                         div = this.getDoc().createElement("div");
    2893                         div.style.textAlign = 'center';
    2894                         div.appendChild(img);
    2895                         focusElm.parentNode.replaceChild(div, focusElm);
     891        });
     892}());
     893/* file:jscripts/tiny_mce/classes/dom/DOMUtils.js */
     894
     895(function() {
     896    // Shorten names
     897    var each = tinymce.each, is = tinymce.is;
     898    var isWebKit = tinymce.isWebKit, isIE = tinymce.isIE;
     899
     900    tinymce.create('tinymce.dom.DOMUtils', {
     901        doc : null,
     902        root : null,
     903        files : null,
     904        listeners : {},
     905        pixelStyles : /^(top|left|bottom|right|width|height|borderWidth)$/,
     906        cache : {},
     907        idPattern : /^#[\w]+$/,
     908        elmPattern : /^[\w_*]+$/,
     909        elmClassPattern : /^([\w_]*)\.([\w_]+)$/,
     910
     911        DOMUtils : function(d, s) {
     912            var t = this;
     913
     914            t.doc = d;
     915            t.files = {};
     916            t.cssFlicker = false;
     917            t.counter = 0;
     918            t.boxModel = !tinymce.isIE || d.compatMode == "CSS1Compat";
     919
     920            this.settings = s = tinymce.extend({
     921                keep_values : false,
     922                hex_colors : 1
     923            }, s);
     924
     925            // Fix IE6SP2 flicker and check it failed for pre SP2
     926            if (tinymce.isIE6) {
     927                try {
     928                    d.execCommand('BackgroundImageCache', false, true);
     929                } catch (e) {
     930                    t.cssFlicker = true;
     931                }
     932            }
     933
     934            tinymce.addUnload(function() {
     935                t.doc = t.root = null;
     936            });
     937        },
     938
     939        getRoot : function() {
     940            var t = this, s = t.settings;
     941
     942            return (s && t.get(s.root_element)) || t.doc.body;
     943        },
     944
     945        getViewPort : function(w) {
     946            var d, b;
     947
     948            w = !w ? window : w;
     949            d = w.document;
     950            b = this.boxModel ? d.documentElement : d.body;
     951
     952            // Returns viewport size excluding scrollbars
     953            return {
     954                x : w.pageXOffset || b.scrollLeft,
     955                y : w.pageYOffset || b.scrollTop,
     956                w : w.innerWidth || b.clientWidth,
     957                h : w.innerHeight || b.clientHeight
     958            };
     959        },
     960
     961        getRect : function(e) {
     962            var p, t = this, w, h;
     963
     964            e = t.get(e);
     965            p = t.getPos(e);
     966            w = t.getStyle(e, 'width');
     967            h = t.getStyle(e, 'height');
     968
     969            // Non pixel value, then force offset/clientWidth
     970            if (w.indexOf('px') === -1)
     971                w = 0;
     972
     973            // Non pixel value, then force offset/clientWidth
     974            if (h.indexOf('px') === -1)
     975                h = 0;
     976
     977            return {
     978                x : p.x,
     979                y : p.y,
     980                w : parseInt(w) || e.offsetWidth || e.clientWidth,
     981                h : parseInt(h) || e.offsetHeight || e.clientHeight
     982            };
     983        },
     984
     985        getParent : function(n, f, r) {
     986            var na, se = this.settings;
     987
     988            n = this.get(n);
     989
     990            if (se.strict_root)
     991                r = r || this.getRoot();
     992
     993            // Wrap node name as func
     994            if (is(f, 'string')) {
     995                na = f.toUpperCase();
     996
     997                f = function(n) {
     998                    var s = false;
     999
     1000                    // Any element
     1001                    if (n.nodeType == 1 && na === '*') {
     1002                        s = true;
     1003                        return false;
    28961004                    }
    28971005
    2898                     this.selection.selectNode(img);
    2899                     this.repaint();
    2900                     tinyMCE.triggerNodeChange();
    2901                     return;
    2902 
    2903                 case "JustifyRight":
    2904                     if (align == 'right')
    2905                         img.removeAttribute('align');
    2906                     else
    2907                         img.setAttribute('align', 'right');
    2908 
    2909                     // Remove the div
    2910                     div = focusElm.parentNode;
    2911                     if (div && div.nodeName == "DIV" && div.childNodes.length == 1 && div.parentNode)
    2912                         div.parentNode.replaceChild(img, div);
    2913 
    2914                     this.selection.selectNode(img);
    2915                     this.repaint();
    2916                     tinyMCE.triggerNodeChange();
    2917                     return;
    2918             }
    2919         }
    2920 
    2921         if (tinyMCE.settings.force_br_newlines) {
    2922             var alignValue = "";
    2923 
    2924             if (doc.selection.type != "Control") {
    2925                 switch (command) {
    2926                         case "JustifyLeft":
    2927                             alignValue = "left";
    2928                             break;
    2929 
    2930                         case "JustifyCenter":
    2931                             alignValue = "center";
    2932                             break;
    2933 
    2934                         case "JustifyFull":
    2935                             alignValue = "justify";
    2936                             break;
    2937 
    2938                         case "JustifyRight":
    2939                             alignValue = "right";
    2940                             break;
    2941                 }
    2942 
    2943                 if (alignValue !== '') {
    2944                     var rng = doc.selection.createRange();
    2945 
    2946                     if ((divElm = tinyMCE.getParentElement(rng.parentElement(), "div")) != null)
    2947                         divElm.setAttribute("align", alignValue);
    2948                     else if (rng.pasteHTML && rng.htmlText.length > 0)
    2949                         rng.pasteHTML('<div align="' + alignValue + '">' + rng.htmlText + "</div>");
    2950 
    2951                     tinyMCE.triggerNodeChange();
    2952                     return;
    2953                 }
    2954             }
    2955         }
    2956 
    2957         switch (command) {
    2958             case "mceRepaint":
    2959                 this.repaint();
    2960                 return true;
    2961 
    2962             case "unlink":
    2963                 // Unlink if caret is inside link
    2964                 if (tinyMCE.isGecko && this.getSel().isCollapsed) {
    2965                     focusElm = tinyMCE.getParentElement(focusElm, 'A');
    2966 
    2967                     if (focusElm)
    2968                         this.selection.selectNode(focusElm, false);
    2969                 }
    2970 
    2971                 this.getDoc().execCommand(command, user_interface, value);
    2972 
    2973                 tinyMCE.isGecko && this.getSel().collapseToEnd();
    2974 
    2975                 tinyMCE.triggerNodeChange();
    2976 
    2977                 return true;
    2978 
    2979             case "InsertUnorderedList":
    2980             case "InsertOrderedList":
    2981                 this.getDoc().execCommand(command, user_interface, value);
    2982                 tinyMCE.triggerNodeChange();
    2983                 break;
    2984 
    2985             case "Strikethrough":
    2986                 this.getDoc().execCommand(command, user_interface, value);
    2987                 tinyMCE.triggerNodeChange();
    2988                 break;
    2989 
    2990             case "mceSelectNode":
    2991                 this.selection.selectNode(value);
    2992                 tinyMCE.triggerNodeChange();
    2993                 tinyMCE.selectedNode = value;
    2994                 break;
    2995 
    2996             case "FormatBlock":
    2997                 if (value == null || value == '') {
    2998                     var elm = tinyMCE.getParentElement(this.getFocusElement(), "p,div,h1,h2,h3,h4,h5,h6,pre,address,blockquote,dt,dl,dd,samp");
    2999 
    3000                     if (elm)
    3001                         this.execCommand("mceRemoveNode", false, elm);
    3002                 } else {
    3003                     if (!this.cleanup.isValid(value))
    3004                         return true;
    3005 
    3006                     if (tinyMCE.isGecko && new RegExp('<(div|blockquote|code|dt|dd|dl|samp)>', 'gi').test(value))
    3007                         value = value.replace(/[^a-z]/gi, '');
    3008 
    3009                     if (tinyMCE.isIE && new RegExp('blockquote|code|samp', 'gi').test(value)) {
    3010                         var b = this.selection.getBookmark();
    3011                         this.getDoc().execCommand("FormatBlock", false, '<p>');
    3012                         tinyMCE.renameElement(tinyMCE.getParentBlockElement(this.getFocusElement()), value);
    3013                         this.selection.moveToBookmark(b);
    3014                     } else
    3015                         this.getDoc().execCommand("FormatBlock", false, value);
    3016                 }
    3017 
    3018                 tinyMCE.triggerNodeChange();
    3019 
    3020                 break;
    3021 
    3022             case "mceRemoveNode":
    3023                 if (!value)
    3024                     value = tinyMCE.getParentElement(this.getFocusElement());
    3025 
    3026                 if (tinyMCE.isIE) {
    3027                     value.outerHTML = value.innerHTML;
    3028                 } else {
    3029                     var rng = value.ownerDocument.createRange();
    3030                     rng.setStartBefore(value);
    3031                     rng.setEndAfter(value);
    3032                     rng.deleteContents();
    3033                     rng.insertNode(rng.createContextualFragment(value.innerHTML));
    3034                 }
    3035 
    3036                 tinyMCE.triggerNodeChange();
    3037 
    3038                 break;
    3039 
    3040             case "mceSelectNodeDepth":
    3041                 var parentNode = this.getFocusElement();
    3042                 for (i=0; parentNode; i++) {
    3043                     if (parentNode.nodeName.toLowerCase() == "body")
    3044                         break;
    3045 
    3046                     if (parentNode.nodeName.toLowerCase() == "#text") {
    3047                         i--;
    3048                         parentNode = parentNode.parentNode;
    3049                         continue;
    3050                     }
    3051 
    3052                     if (i == value) {
    3053                         this.selection.selectNode(parentNode, false);
    3054                         tinyMCE.triggerNodeChange();
    3055                         tinyMCE.selectedNode = parentNode;
    3056                         return;
    3057                     }
    3058 
    3059                     parentNode = parentNode.parentNode;
    3060                 }
    3061 
    3062                 break;
    3063 
    3064             case "mceSetStyleInfo":
    3065             case "SetStyleInfo":
    3066                 var rng = this.getRng();
    3067                 var sel = this.getSel();
    3068                 var scmd = value.command;
    3069                 var sname = value.name;
    3070                 var svalue = value.value == null ? '' : value.value;
    3071                 //var svalue = value['value'] == null ? '' : value['value'];
    3072                 var wrapper = value.wrapper ? value.wrapper : "span";
    3073                 var parentElm = null;
    3074                 var invalidRe = new RegExp("^BODY|HTML$", "g");
    3075                 var invalidParentsRe = tinyMCE.settings.merge_styles_invalid_parents !== '' ? new RegExp(tinyMCE.settings.merge_styles_invalid_parents, "gi") : null;
    3076 
    3077                 // Whole element selected check
    3078                 if (tinyMCE.isIE) {
    3079                     // Control range
    3080                     if (rng.item)
    3081                         parentElm = rng.item(0);
    3082                     else {
    3083                         var pelm = rng.parentElement();
    3084                         var prng = doc.selection.createRange();
    3085                         prng.moveToElementText(pelm);
    3086 
    3087                         if (rng.htmlText == prng.htmlText || rng.boundingWidth == 0) {
    3088                             if (invalidParentsRe == null || !invalidParentsRe.test(pelm.nodeName))
    3089                                 parentElm = pelm;
     1006                    each(na.split(','), function(v) {
     1007                        if (n.nodeType == 1 && ((se.strict && n.nodeName.toUpperCase() == v) || n.nodeName == v)) {
     1008                            s = true;
     1009                            return false; // Break loop
    30901010                        }
    3091                     }
    3092                 } else {
    3093                     var felm = this.getFocusElement();
    3094                     if (sel.isCollapsed || (new RegExp('td|tr|tbody|table|img', 'gi').test(felm.nodeName) && sel.anchorNode == felm.parentNode))
    3095                         parentElm = felm;
    3096                 }
    3097 
    3098                 // Whole element selected
    3099                 if (parentElm && !invalidRe.test(parentElm.nodeName)) {
    3100                     if (scmd == "setstyle")
    3101                         tinyMCE.setStyleAttrib(parentElm, sname, svalue);
    3102 
    3103                     if (scmd == "setattrib")
    3104                         tinyMCE.setAttrib(parentElm, sname, svalue);
    3105 
    3106                     if (scmd == "removeformat") {
    3107                         parentElm.style.cssText = '';
    3108                         tinyMCE.setAttrib(parentElm, 'class', '');
    3109                     }
    3110 
    3111                     // Remove style/attribs from all children
    3112                     var ch = tinyMCE.getNodeTree(parentElm, [], 1);
    3113                     for (z=0; z<ch.length; z++) {
    3114                         if (ch[z] == parentElm)
    3115                             continue;
    3116 
    3117                         if (scmd == "setstyle")
    3118                             tinyMCE.setStyleAttrib(ch[z], sname, '');
    3119 
    3120                         if (scmd == "setattrib")
    3121                             tinyMCE.setAttrib(ch[z], sname, '');
    3122 
    3123                         if (scmd == "removeformat") {
    3124                             ch[z].style.cssText = '';
    3125                             tinyMCE.setAttrib(ch[z], 'class', '');
    3126                         }
    3127                     }
    3128                 } else {
    3129                     this._setUseCSS(false); // Bug in FF when running in fullscreen
    3130                     doc.execCommand("FontName", false, "#mce_temp_font#");
    3131                     var elementArray = tinyMCE.getElementsByAttributeValue(this.getBody(), "font", "face", "#mce_temp_font#");
    3132 
    3133                     // Change them all
    3134                     for (x=0; x<elementArray.length; x++) {
    3135                         elm = elementArray[x];
    3136                         if (elm) {
    3137                             var spanElm = doc.createElement(wrapper);
    3138 
    3139                             if (scmd == "setstyle")
    3140                                 tinyMCE.setStyleAttrib(spanElm, sname, svalue);
    3141 
    3142                             if (scmd == "setattrib")
    3143                                 tinyMCE.setAttrib(spanElm, sname, svalue);
    3144 
    3145                             if (scmd == "removeformat") {
    3146                                 spanElm.style.cssText = '';
    3147                                 tinyMCE.setAttrib(spanElm, 'class', '');
    3148                             }
    3149 
    3150                             if (elm.hasChildNodes()) {
    3151                                 for (i=0; i<elm.childNodes.length; i++)
    3152                                     spanElm.appendChild(elm.childNodes[i].cloneNode(true));
    3153                             }
    3154 
    3155                             spanElm.setAttribute("mce_new", "true");
    3156                             elm.parentNode.replaceChild(spanElm, elm);
    3157 
    3158                             // Remove style/attribs from all children
    3159                             var ch = tinyMCE.getNodeTree(spanElm, [], 1);
    3160                             for (z=0; z<ch.length; z++) {
    3161                                 if (ch[z] == spanElm)
    3162                                     continue;
    3163 
    3164                                 if (scmd == "setstyle")
    3165                                     tinyMCE.setStyleAttrib(ch[z], sname, '');
    3166 
    3167                                 if (scmd == "setattrib")
    3168                                     tinyMCE.setAttrib(ch[z], sname, '');
    3169 
    3170                                 if (scmd == "removeformat") {
    3171                                     ch[z].style.cssText = '';
    3172                                     tinyMCE.setAttrib(ch[z], 'class', '');
    3173                                 }
    3174                             }
    3175                         }
    3176                     }
    3177                 }
    3178 
    3179                 // Cleaup wrappers
    3180                 var nodes = doc.getElementsByTagName(wrapper);
    3181                 for (i=nodes.length-1; i>=0; i--) {
    3182                     var elm = nodes[i];
    3183                     var isNew = tinyMCE.getAttrib(elm, "mce_new") == "true";
    3184 
    3185                     elm.removeAttribute("mce_new");
    3186 
    3187                     // Is only child a element
    3188                     if (elm.childNodes && elm.childNodes.length == 1 && elm.childNodes[0].nodeType == 1) {
    3189                         //tinyMCE.debug("merge1" + isNew);
    3190                         this._mergeElements(scmd, elm, elm.childNodes[0], isNew);
    3191                         continue;
    3192                     }
    3193 
    3194                     // Is I the only child
    3195                     if (elm.parentNode.childNodes.length == 1 && !invalidRe.test(elm.nodeName) && !invalidRe.test(elm.parentNode.nodeName)) {
    3196                         //tinyMCE.debug("merge2" + isNew + "," + elm.nodeName + "," + elm.parentNode.nodeName);
    3197                         if (invalidParentsRe == null || !invalidParentsRe.test(elm.parentNode.nodeName))
    3198                             this._mergeElements(scmd, elm.parentNode, elm, false);
    3199                     }
    3200                 }
    3201 
    3202                 // Remove empty wrappers
    3203                 var nodes = doc.getElementsByTagName(wrapper);
    3204                 for (i=nodes.length-1; i>=0; i--) {
    3205                     var elm = nodes[i], isEmpty = true;
    3206 
    3207                     // Check if it has any attribs
    3208                     var tmp = doc.createElement("body");
    3209                     tmp.appendChild(elm.cloneNode(false));
    3210 
    3211                     // Is empty span, remove it
    3212                     tmp.innerHTML = tmp.innerHTML.replace(new RegExp('style=""|class=""', 'gi'), '');
    3213                     //tinyMCE.debug(tmp.innerHTML);
    3214                     if (new RegExp('<span>', 'gi').test(tmp.innerHTML)) {
    3215                         for (x=0; x<elm.childNodes.length; x++) {
    3216                             if (elm.parentNode != null)
    3217                                 elm.parentNode.insertBefore(elm.childNodes[x].cloneNode(true), elm);
    3218                         }
    3219 
    3220                         elm.parentNode.removeChild(elm);
    3221                     }
    3222                 }
    3223 
    3224                 // Re add the visual aids
    3225                 if (scmd == "removeformat")
    3226                     tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this);
    3227 
    3228                 tinyMCE.triggerNodeChange();
    3229 
    3230                 break;
    3231 
    3232             case "FontName":
    3233                 if (value == null) {
    3234                     var s = this.getSel();
    3235 
    3236                     // Find font and select it
    3237                     if (tinyMCE.isGecko && s.isCollapsed) {
    3238                         var f = tinyMCE.getParentElement(this.getFocusElement(), "font");
    3239 
    3240                         if (f != null)
    3241                             this.selection.selectNode(f, false);
    3242                     }
    3243 
    3244                     // Remove format
    3245                     this.getDoc().execCommand("RemoveFormat", false, null);
    3246 
    3247                     // Collapse range if font was found
    3248                     if (f != null && tinyMCE.isGecko) {
    3249                         var r = this.getRng().cloneRange();
    3250                         r.collapse(true);
    3251                         s.removeAllRanges();
    3252                         s.addRange(r);
    3253                     }
    3254                 } else
    3255                     this.getDoc().execCommand('FontName', false, value);
    3256 
    3257                 if (tinyMCE.isGecko)
    3258                     window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);
    3259 
    3260                 return;
    3261 
    3262             case "FontSize":
    3263                 this.getDoc().execCommand('FontSize', false, value);
    3264 
    3265                 if (tinyMCE.isGecko)
    3266                     window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);
    3267 
    3268                 return;
    3269 
    3270             case "forecolor":
    3271                 value = value == null ? this.foreColor : value;
    3272                 value = tinyMCE.trim(value);
    3273                 value = value.charAt(0) != '#' ? (isNaN('0x' + value) ? value : '#' + value) : value;
    3274 
    3275                 this.foreColor = value;
    3276                 this.getDoc().execCommand('forecolor', false, value);
    3277                 break;
    3278 
    3279             case "HiliteColor":
    3280                 value = value == null ? this.backColor : value;
    3281                 value = tinyMCE.trim(value);
    3282                 value = value.charAt(0) != '#' ? (isNaN('0x' + value) ? value : '#' + value) : value;
    3283                 this.backColor = value;
    3284 
    3285                 if (tinyMCE.isGecko) {
    3286                     this._setUseCSS(true);
    3287                     this.getDoc().execCommand('hilitecolor', false, value);
    3288                     this._setUseCSS(false);
    3289                 } else
    3290                     this.getDoc().execCommand('BackColor', false, value);
    3291                 break;
    3292 
    3293             case "Cut":
    3294             case "Copy":
    3295             case "Paste":
    3296                 var cmdFailed = false;
    3297 
    3298                 // Try executing command
    3299                 eval('try {this.getDoc().execCommand(command, user_interface, value);} catch (e) {cmdFailed = true;}');
    3300 
    3301                 if (tinyMCE.isOpera && cmdFailed)
    3302                     alert('Currently not supported by your browser, use keyboard shortcuts instead.');
    3303 
    3304                 // Alert error in gecko if command failed
    3305                 if (tinyMCE.isGecko && cmdFailed) {
    3306                     // Confirm more info
    3307                     if (confirm(tinyMCE.entityDecode(tinyMCE.getLang('lang_clipboard_msg'))))
    3308                         window.open('http://www.mozilla.org/editor/midasdemo/securityprefs.html', 'mceExternal');
    3309 
    3310                     return;
    3311                 } else
    3312                     tinyMCE.triggerNodeChange();
    3313             break;
    3314 
    3315             case "mceSetContent":
    3316                 if (!value)
    3317                     value = "";
    3318 
    3319                 // Call custom cleanup code
    3320                 value = tinyMCE.storeAwayURLs(value);
    3321                 value = tinyMCE._customCleanup(this, "insert_to_editor", value);
    3322 
    3323                 if (this.getBody().nodeName == 'BODY')
    3324                     tinyMCE._setHTML(doc, value);
    3325                 else
    3326                     this.getBody().innerHTML = value;
    3327 
    3328                 tinyMCE.setInnerHTML(this.getBody(), tinyMCE._cleanupHTML(this, doc, this.settings, this.getBody(), false, false, false, true));
    3329                 tinyMCE.convertAllRelativeURLs(this.getBody());
    3330 
    3331                 // Cleanup any mess left from storyAwayURLs
    3332                 tinyMCE._removeInternal(this.getBody());
    3333 
    3334                 // When editing always use fonts internaly
    3335                 if (tinyMCE.getParam("convert_fonts_to_spans"))
    3336                     tinyMCE.convertSpansToFonts(doc);
    3337 
    3338                 tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this);
    3339                 tinyMCE._setEventsEnabled(this.getBody(), false);
    3340                 this._addBogusBR();
    3341 
    3342                 return true;
    3343 
    3344             case "mceCleanup":
    3345                 var b = this.selection.getBookmark();
    3346                 tinyMCE._setHTML(this.contentDocument, this.getBody().innerHTML);
    3347                 tinyMCE.setInnerHTML(this.getBody(), tinyMCE._cleanupHTML(this, this.contentDocument, this.settings, this.getBody(), this.visualAid));
    3348                 tinyMCE.convertAllRelativeURLs(doc.body);
    3349 
    3350                 // When editing always use fonts internaly
    3351                 if (tinyMCE.getParam("convert_fonts_to_spans"))
    3352                     tinyMCE.convertSpansToFonts(doc);
    3353 
    3354                 tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this);
    3355                 tinyMCE._setEventsEnabled(this.getBody(), false);
    3356                 this._addBogusBR();
    3357                 this.repaint();
    3358                 this.selection.moveToBookmark(b);
    3359                 tinyMCE.triggerNodeChange();
    3360             break;
    3361 
    3362             case "mceReplaceContent":
    3363                 // Force empty string
    3364                 if (!value)
    3365                     value = '';
    3366 
    3367                 this.getWin().focus();
    3368 
    3369                 var selectedText = "";
    3370 
    3371                 if (tinyMCE.isIE) {
    3372                     var rng = doc.selection.createRange();
    3373                     selectedText = rng.text;
    3374                 } else
    3375                     selectedText = this.getSel().toString();
    3376 
    3377                 if (selectedText.length > 0) {
    3378                     value = tinyMCE.replaceVar(value, "selection", selectedText);
    3379                     tinyMCE.execCommand('mceInsertContent', false, value);
    3380                 }
    3381 
    3382                 this._addBogusBR();
    3383                 tinyMCE.triggerNodeChange();
    3384             break;
    3385 
    3386             case "mceSetAttribute":
    3387                 if (typeof(value) == 'object') {
    3388                     var targetElms = (typeof(value.targets) == "undefined") ? "p,img,span,div,td,h1,h2,h3,h4,h5,h6,pre,address" : value.targets;
    3389                     var targetNode = tinyMCE.getParentElement(this.getFocusElement(), targetElms);
    3390 
    3391                     if (targetNode) {
    3392                         targetNode.setAttribute(value.name, value.value);
    3393                         tinyMCE.triggerNodeChange();
    3394                     }
    3395                 }
    3396             break;
    3397 
    3398             case "mceSetCSSClass":
    3399                 this.execCommand("mceSetStyleInfo", false, {command : "setattrib", name : "class", value : value});
    3400             break;
    3401 
    3402             case "mceInsertRawHTML":
    3403                 var key = 'tiny_mce_marker';
    3404 
    3405                 this.execCommand('mceBeginUndoLevel');
    3406 
    3407                 // Insert marker key
    3408                 this.execCommand('mceInsertContent', false, key);
    3409 
    3410                 // Store away scroll pos
    3411                 var scrollX = this.getBody().scrollLeft + this.getDoc().documentElement.scrollLeft;
    3412                 var scrollY = this.getBody().scrollTop + this.getDoc().documentElement.scrollTop;
    3413 
    3414                 // Find marker and replace with RAW HTML
    3415                 var html = this.getBody().innerHTML;
    3416                 if ((pos = html.indexOf(key)) != -1)
    3417                     tinyMCE.setInnerHTML(this.getBody(), html.substring(0, pos) + value + html.substring(pos + key.length));
    3418 
    3419                 // Restore scoll pos
    3420                 this.contentWindow.scrollTo(scrollX, scrollY);
    3421 
    3422                 this.execCommand('mceEndUndoLevel');
    3423 
    3424                 break;
    3425 
    3426             case "mceInsertContent":
    3427                 // Force empty string
    3428                 if (!value)
    3429                     value = '';
    3430 
    3431                 var insertHTMLFailed = false;
    3432 
    3433                 // Removed since it produced problems in IE
    3434                 // this.getWin().focus();
    3435 
    3436                 if (tinyMCE.isGecko || tinyMCE.isOpera) {
    3437                     try {
    3438                         // Is plain text or HTML, &amp;, &nbsp; etc will be encoded wrong in FF
    3439                         if (value.indexOf('<') == -1 && !value.match(/(&#38;|&#160;|&#60;|&#62;)/g)) {
    3440                             var r = this.getRng();
    3441                             var n = this.getDoc().createTextNode(tinyMCE.entityDecode(value));
    3442                             var s = this.getSel();
    3443                             var r2 = r.cloneRange();
    3444 
    3445                             // Insert text at cursor position
    3446                             s.removeAllRanges();
    3447                             r.deleteContents();
    3448                             r.insertNode(n);
    3449 
    3450                             // Move the cursor to the end of text
    3451                             r2.selectNode(n);
    3452                             r2.collapse(false);
    3453                             s.removeAllRanges();
    3454                             s.addRange(r2);
    3455                         } else {
    3456                             value = tinyMCE.fixGeckoBaseHREFBug(1, this.getDoc(), value);
    3457                             this.getDoc().execCommand('inserthtml', false, value);
    3458                             tinyMCE.fixGeckoBaseHREFBug(2, this.getDoc(), value);
    3459                         }
    3460                     } catch (ex) {
    3461                         insertHTMLFailed = true;
    3462                     }
    3463 
    3464                     if (!insertHTMLFailed) {
    3465                         tinyMCE.triggerNodeChange();
    3466                         return;
    3467                     }
    3468                 }
    3469 
    3470                 if (!tinyMCE.isIE) {
    3471                     var isHTML = value.indexOf('<') != -1;
    3472                     var sel = this.getSel();
    3473                     var rng = this.getRng();
    3474 
    3475                     if (isHTML) {
    3476                         if (tinyMCE.isSafari) {
    3477                             var tmpRng = this.getDoc().createRange();
    3478 
    3479                             tmpRng.setStart(this.getBody(), 0);
    3480                             tmpRng.setEnd(this.getBody(), 0);
    3481 
    3482                             value = tmpRng.createContextualFragment(value);
    3483                         } else
    3484                             value = rng.createContextualFragment(value);
    3485                     } else {
    3486                         // Setup text node
    3487                         value = doc.createTextNode(tinyMCE.entityDecode(value));
    3488                     }
    3489 
    3490                     // Insert plain text in Safari
    3491                     if (tinyMCE.isSafari && !isHTML) {
    3492                         this.execCommand('InsertText', false, value.nodeValue);
    3493                         tinyMCE.triggerNodeChange();
    3494                         return true;
    3495                     } else if (tinyMCE.isSafari && isHTML) {
    3496                         rng.deleteContents();
    3497                         rng.insertNode(value);
    3498                         tinyMCE.triggerNodeChange();
    3499                         return true;
    3500                     }
    3501 
    3502                     rng.deleteContents();
    3503 
    3504                     // If target node is text do special treatment, (Mozilla 1.3 fix)
    3505                     if (rng.startContainer.nodeType == 3) {
    3506                         var node = rng.startContainer.splitText(rng.startOffset);
    3507                         node.parentNode.insertBefore(value, node);
    3508                     } else
    3509                         rng.insertNode(value);
    3510 
    3511                     if (!isHTML) {
    3512                         // Removes weird selection trails
    3513                         sel.selectAllChildren(doc.body);
    3514                         sel.removeAllRanges();
    3515 
    3516                         // Move cursor to end of content
    3517                         var rng = doc.createRange();
    3518 
    3519                         rng.selectNode(value);
    3520                         rng.collapse(false);
    3521 
    3522                         sel.addRange(rng);
    3523                     } else
    3524                         rng.collapse(false);
    3525 
    3526                     tinyMCE.fixGeckoBaseHREFBug(2, this.getDoc(), value);
    3527                 } else {
    3528                     var rng = doc.selection.createRange(), tmpRng = null;
    3529                     var c = value.indexOf('<!--') != -1;
    3530 
    3531                     // Fix comment bug, add tag before comments
    3532                     if (c)
    3533                         value = tinyMCE.uniqueTag + value;
    3534 
    3535                     //  tmpRng = rng.duplicate(); // Store away range (Fixes Undo bookmark bug in IE)
    3536 
    3537                     if (rng.item)
    3538                         rng.item(0).outerHTML = value;
    3539                     else
    3540                         rng.pasteHTML(value);
    3541 
    3542                     //if (tmpRng)
    3543                     //  tmpRng.select(); // Restore range  (Fixes Undo bookmark bug in IE)
    3544 
    3545                     // Remove unique tag
    3546                     if (c) {
    3547                         var e = this.getDoc().getElementById('mceTMPElement');
    3548                         e.parentNode.removeChild(e);
    3549                     }
    3550                 }
    3551 
    3552                 tinyMCE.execCommand("mceAddUndoLevel");
    3553                 tinyMCE.triggerNodeChange();
    3554             break;
    3555 
    3556             case "mceStartTyping":
    3557                 if (tinyMCE.settings.custom_undo_redo && this.undoRedo.typingUndoIndex == -1) {
    3558                     this.undoRedo.typingUndoIndex = this.undoRedo.undoIndex;
    3559                     tinyMCE.typingUndoIndex = tinyMCE.undoIndex;
    3560                     this.execCommand('mceAddUndoLevel');
    3561                 }
    3562                 break;
    3563 
    3564             case "mceEndTyping":
    3565                 if (tinyMCE.settings.custom_undo_redo && this.undoRedo.typingUndoIndex != -1) {
    3566                     this.execCommand('mceAddUndoLevel');
    3567                     this.undoRedo.typingUndoIndex = -1;
    3568                 }
    3569 
    3570                 tinyMCE.typingUndoIndex = -1;
    3571                 break;
    3572 
    3573             case "mceBeginUndoLevel":
    3574                 this.undoRedoLevel = false;
    3575                 break;
    3576 
    3577             case "mceEndUndoLevel":
    3578                 this.undoRedoLevel = true;
    3579                 this.execCommand('mceAddUndoLevel');
    3580                 break;
    3581 
    3582             case "mceAddUndoLevel":
    3583                 if (tinyMCE.settings.custom_undo_redo && this.undoRedoLevel) {
    3584                     if (this.undoRedo.add())
    3585                         tinyMCE.triggerNodeChange(false);
    3586                 }
    3587                 break;
    3588 
    3589             case "Undo":
    3590                 if (tinyMCE.settings.custom_undo_redo) {
    3591                     tinyMCE.execCommand("mceEndTyping");
    3592                     this.undoRedo.undo();
    3593                     tinyMCE.triggerNodeChange();
    3594                 } else
    3595                     this.getDoc().execCommand(command, user_interface, value);
    3596                 break;
    3597 
    3598             case "Redo":
    3599                 if (tinyMCE.settings.custom_undo_redo) {
    3600                     tinyMCE.execCommand("mceEndTyping");
    3601                     this.undoRedo.redo();
    3602                     tinyMCE.triggerNodeChange();
    3603                 } else
    3604                     this.getDoc().execCommand(command, user_interface, value);
    3605                 break;
    3606 
    3607             case "mceToggleVisualAid":
    3608                 this.visualAid = !this.visualAid;
    3609                 tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this);
    3610                 tinyMCE.triggerNodeChange();
    3611                 break;
    3612 
    3613             case "Indent":
    3614                 this.getDoc().execCommand(command, user_interface, value);
    3615                 tinyMCE.triggerNodeChange();
    3616 
    3617                 if (tinyMCE.isIE) {
    3618                     var n = tinyMCE.getParentElement(this.getFocusElement(), "blockquote");
    3619                     do {
    3620                         if (n && n.nodeName == "BLOCKQUOTE") {
    3621                             n.removeAttribute("dir");
    3622                             n.removeAttribute("style");
    3623                         }
    3624                     } while (n != null && (n = n.parentNode) != null);
    3625                 }
    3626                 break;
    3627 
    3628             case "RemoveFormat":
    3629             case "removeformat":
    3630                 var text = this.selection.getSelectedText();
    3631 
    3632                 if (tinyMCE.isOpera) {
    3633                     this.getDoc().execCommand("RemoveFormat", false, null);
    3634                     return;
    3635                 }
    3636 
    3637                 if (tinyMCE.isIE) {
    3638                     try {
    3639                         var rng = doc.selection.createRange();
    3640                         rng.execCommand("RemoveFormat", false, null);
    3641                     } catch (e) {
    3642                         // Do nothing
    3643                     }
    3644 
    3645                     this.execCommand("mceSetStyleInfo", false, {command : "removeformat"});
    3646                 } else {
    3647                     this.getDoc().execCommand(command, user_interface, value);
    3648 
    3649                     this.execCommand("mceSetStyleInfo", false, {command : "removeformat"});
    3650                 }
    3651 
    3652                 // Remove class
    3653                 if (text.length == 0)
    3654                     this.execCommand("mceSetCSSClass", false, "");
    3655 
    3656                 tinyMCE.triggerNodeChange();
    3657                 break;
    3658 
    3659             default:
    3660                 this.getDoc().execCommand(command, user_interface, value);
    3661 
    3662                 if (tinyMCE.isGecko)
    3663                     window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);
    3664                 else
    3665                     tinyMCE.triggerNodeChange();
    3666         }
    3667 
    3668         // Add undo level after modification
    3669         if (command != "mceAddUndoLevel" && command != "Undo" && command != "Redo" && command != "mceStartTyping" && command != "mceEndTyping")
    3670             tinyMCE.execCommand("mceAddUndoLevel");
    3671     },
    3672 
    3673     queryCommandValue : function(c) {
    3674         try {
    3675             return this.getDoc().queryCommandValue(c);
    3676         } catch (e) {
     1011                    });
     1012
     1013                    return s;
     1014                };
     1015            }
     1016
     1017            while (n) {
     1018                if (n == r)
     1019                    return null;
     1020
     1021                if (f(n))
     1022                    return n;
     1023
     1024                n = n.parentNode;
     1025            }
     1026
    36771027            return null;
    3678         }
    3679     },
    3680 
    3681     queryCommandState : function(c) {
    3682         return this.getDoc().queryCommandState(c);
    3683     },
    3684 
    3685     _addBogusBR : function() {
    3686         var b = this.getBody();
    3687 
    3688         if (tinyMCE.isGecko && !b.hasChildNodes())
    3689             b.innerHTML = '<br _moz_editor_bogus_node="TRUE" />';
    3690     },
    3691 
    3692     _onAdd : function(replace_element, form_element_name, target_document) {
    3693         var hc, th, tos, editorTemplate, targetDoc, deltaWidth, deltaHeight, html, rng, fragment;
    3694         var dynamicIFrame, tElm, doc, parentElm;
    3695 
    3696         th = this.settings.theme;
    3697         tos = tinyMCE.themes[th];
    3698 
    3699         targetDoc = target_document ? target_document : document;
    3700 
    3701         this.targetDoc = targetDoc;
    3702 
    3703         tinyMCE.themeURL = tinyMCE.baseURL + "/themes/" + this.settings.theme;
    3704         this.settings.themeurl = tinyMCE.themeURL;
    3705 
    3706         if (!replace_element) {
    3707             alert("Error: Could not find the target element.");
    3708             return false;
    3709         }
    3710 
    3711         if (tos.getEditorTemplate)
    3712             editorTemplate = tos.getEditorTemplate(this.settings, this.editorId);
    3713 
    3714         deltaWidth = editorTemplate.delta_width ? editorTemplate.delta_width : 0;
    3715         deltaHeight = editorTemplate.delta_height ? editorTemplate.delta_height : 0;
    3716         html = '<span id="' + this.editorId + '_parent" class="mceEditorContainer">' + editorTemplate.html;
    3717 
    3718         html = tinyMCE.replaceVar(html, "editor_id", this.editorId);
    3719 
    3720         if (!this.settings.default_document)
    3721             this.settings.default_document = tinyMCE.baseURL + "/blank.htm";
    3722 
    3723         this.settings.old_width = this.settings.width;
    3724         this.settings.old_height = this.settings.height;
    3725 
    3726         // Set default width, height
    3727         if (this.settings.width == -1)
    3728             this.settings.width = replace_element.offsetWidth;
    3729 
    3730         if (this.settings.height == -1)
    3731             this.settings.height = replace_element.offsetHeight;
    3732 
    3733         // Try the style width
    3734         if (this.settings.width == 0)
    3735             this.settings.width = replace_element.style.width;
    3736 
    3737         // Try the style height
    3738         if (this.settings.height == 0)
    3739             this.settings.height = replace_element.style.height;
    3740 
    3741         // If no width/height then default to 320x240, better than nothing
    3742         if (this.settings.width == 0)
    3743             this.settings.width = 320;
    3744 
    3745         if (this.settings.height == 0)
    3746             this.settings.height = 240;
    3747 
    3748         this.settings.area_width = parseInt(this.settings.width);
    3749         this.settings.area_height = parseInt(this.settings.height);
    3750         this.settings.area_width += deltaWidth;
    3751         this.settings.area_height += deltaHeight;
    3752         this.settings.width_style = "" + this.settings.width;
    3753         this.settings.height_style = "" + this.settings.height;
    3754 
    3755         // Special % handling
    3756         if (("" + this.settings.width).indexOf('%') != -1)
    3757             this.settings.area_width = "100%";
    3758         else
    3759             this.settings.width_style += 'px';
    3760 
    3761         if (("" + this.settings.height).indexOf('%') != -1)
    3762             this.settings.area_height = "100%";
    3763         else
    3764             this.settings.height_style += 'px';
    3765 
    3766         if (("" + replace_element.style.width).indexOf('%') != -1) {
    3767             this.settings.width = replace_element.style.width;
    3768             this.settings.area_width = "100%";
    3769             this.settings.width_style = "100%";
    3770         }
    3771 
    3772         if (("" + replace_element.style.height).indexOf('%') != -1) {
    3773             this.settings.height = replace_element.style.height;
    3774             this.settings.area_height = "100%";
    3775             this.settings.height_style = "100%";
    3776         }
    3777 
    3778         html = tinyMCE.applyTemplate(html);
    3779 
    3780         this.settings.width = this.settings.old_width;
    3781         this.settings.height = this.settings.old_height;
    3782 
    3783         this.visualAid = this.settings.visual;
    3784         this.formTargetElementId = form_element_name;
    3785 
    3786         // Get replace_element contents
    3787         if (replace_element.nodeName == "TEXTAREA" || replace_element.nodeName == "INPUT")
    3788             this.startContent = replace_element.value;
    3789         else
    3790             this.startContent = replace_element.innerHTML;
    3791 
    3792         // If not text area or input
    3793         if (replace_element.nodeName != "TEXTAREA" && replace_element.nodeName != "INPUT") {
    3794             this.oldTargetElement = replace_element;
    3795 
    3796             // Debug mode
    3797             hc = '<input type="hidden" id="' + form_element_name + '" name="' + form_element_name + '" />';
    3798             this.oldTargetDisplay = tinyMCE.getStyle(this.oldTargetElement, 'display', 'inline');
    3799             this.oldTargetElement.style.display = "none";
    3800 
    3801             html += '</span>';
    3802 
    3803             if (tinyMCE.isGecko)
    3804                 html = hc + html;
    3805             else
    3806                 html += hc;
    3807 
    3808             // Output HTML and set editable
    3809             if (tinyMCE.isGecko) {
    3810                 rng = replace_element.ownerDocument.createRange();
    3811                 rng.setStartBefore(replace_element);
    3812 
    3813                 fragment = rng.createContextualFragment(html);
    3814                 tinyMCE.insertAfter(fragment, replace_element);
    3815             } else
    3816                 replace_element.insertAdjacentHTML("beforeBegin", html);
    3817         } else {
    3818             html += '</span>';
    3819 
    3820             // Just hide the textarea element
    3821             this.oldTargetElement = replace_element;
    3822 
    3823             this.oldTargetDisplay = tinyMCE.getStyle(this.oldTargetElement, 'display', 'inline');
    3824             this.oldTargetElement.style.display = "none";
    3825 
    3826             // Output HTML and set editable
    3827             if (tinyMCE.isGecko) {
    3828                 rng = replace_element.ownerDocument.createRange();
    3829                 rng.setStartBefore(replace_element);
    3830 
    3831                 fragment = rng.createContextualFragment(html);
    3832                 tinyMCE.insertAfter(fragment, replace_element);
    3833             } else
    3834                 replace_element.insertAdjacentHTML("beforeBegin", html);
    3835         }
    3836 
    3837         // Setup iframe
    3838         dynamicIFrame = false;
    3839         tElm = targetDoc.getElementById(this.editorId);
    3840 
    3841         if (!tinyMCE.isIE) {
    3842             // Node case is preserved in XML strict mode
    3843             if (tElm && (tElm.nodeName == "SPAN" || tElm.nodeName == "span")) {
    3844                 tElm = tinyMCE._createIFrame(tElm, targetDoc);
    3845                 dynamicIFrame = true;
    3846             }
    3847 
    3848             this.targetElement = tElm;
    3849             this.iframeElement = tElm;
    3850             this.contentDocument = tElm.contentDocument;
    3851             this.contentWindow = tElm.contentWindow;
    3852 
    3853             //this.getDoc().designMode = "on";
    3854         } else {
    3855             if (tElm && tElm.nodeName == "SPAN")
    3856                 tElm = tinyMCE._createIFrame(tElm, targetDoc, targetDoc.parentWindow);
    3857             else
    3858                 tElm = targetDoc.frames[this.editorId];
    3859 
    3860             this.targetElement = tElm;
    3861             this.iframeElement = targetDoc.getElementById(this.editorId);
    3862 
    3863             if (tinyMCE.isOpera) {
    3864                 this.contentDocument = this.iframeElement.contentDocument;
    3865                 this.contentWindow = this.iframeElement.contentWindow;
    3866                 dynamicIFrame = true;
    3867             } else {
    3868                 this.contentDocument = tElm.window.document;
    3869                 this.contentWindow = tElm.window;
    3870             }
    3871 
    3872             this.getDoc().designMode = "on";
    3873         }
    3874 
    3875         // Setup base HTML
    3876         doc = this.contentDocument;
    3877         if (dynamicIFrame) {
    3878             html = tinyMCE.getParam('doctype') + '<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="' + tinyMCE.settings.base_href + '" /><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>blank_page</title></head><body class="mceContentBody"></body></html>';
    3879 
    3880             try {
    3881                 if (!this.isHidden())
    3882                     this.getDoc().designMode = "on";
    3883 
    3884                 doc.open();
    3885                 doc.write(html);
    3886                 doc.close();
    3887             } catch (e) {
    3888                 // Failed Mozilla 1.3
    3889                 this.getDoc().location.href = tinyMCE.baseURL + "/blank.htm";
    3890             }
    3891         }
    3892 
    3893         // This timeout is needed in MSIE 5.5 for some odd reason
    3894         // it seems that the document.frames isn't initialized yet?
    3895         if (tinyMCE.isIE)
    3896             window.setTimeout("tinyMCE.addEventHandlers(tinyMCE.instances[\"" + this.editorId + "\"]);", 1);
    3897 
    3898         // Setup element references
    3899         parentElm = this.targetDoc.getElementById(this.editorId + '_parent');
    3900         this.formElement = tinyMCE.isGecko ? parentElm.previousSibling : parentElm.nextSibling;
    3901 
    3902         tinyMCE.setupContent(this.editorId, true);
    3903 
    3904         return true;
    3905     },
    3906 
    3907     setBaseHREF : function(u) {
    3908         var h, b, d, nl;
    3909 
    3910         d = this.getDoc();
    3911         nl = d.getElementsByTagName("base");
    3912         b = nl.length > 0 ? nl[0] : null;
    3913 
    3914         if (!b) {
    3915             nl = d.getElementsByTagName("head");
    3916             h = nl.length > 0 ? nl[0] : null;
    3917 
    3918             b = d.createElement("base");
    3919             b.setAttribute('href', u);
    3920             h.appendChild(b);
    3921         } else {
    3922             if (u == '' || u == null)
    3923                 b.parentNode.removeChild(b);
    3924             else
    3925                 b.setAttribute('href', u);
    3926         }
    3927     },
    3928 
    3929     getHTML : function(r) {
    3930         var h, d = this.getDoc(), b = this.getBody();
    3931 
    3932         if (r)
    3933             return b.innerHTML;
    3934 
    3935         h = tinyMCE._cleanupHTML(this, d, this.settings, b, false, true, false, true);
    3936 
    3937         if (tinyMCE.getParam("convert_fonts_to_spans"))
    3938             tinyMCE.convertSpansToFonts(d);
    3939 
    3940         return h;
    3941     },
    3942 
    3943     setHTML : function(h) {
    3944         this.execCommand('mceSetContent', false, h);
    3945         this.repaint();
    3946     },
    3947 
    3948     getFocusElement : function() {
    3949         return this.selection.getFocusElement();
    3950     },
    3951 
    3952     getSel : function() {
    3953         return this.selection.getSel();
    3954     },
    3955 
    3956     getRng : function() {
    3957         return this.selection.getRng();
    3958     },
    3959 
    3960     triggerSave : function(skip_cleanup, skip_callback) {
    3961         var e, nl = [], i, s, content, htm;
    3962 
    3963         if (!this.enabled)
    3964             return;
    3965 
    3966         this.switchSettings();
    3967         s = tinyMCE.settings;
    3968 
    3969         // Force hidden tabs visible while serializing
    3970         if (tinyMCE.isRealIE) {
    3971             e = this.iframeElement;
    3972 
    3973             do {
    3974                 if (e.style && e.style.display == 'none') {
    3975                     e.style.display = 'block';
    3976                     nl[nl.length] = {elm : e, type : 'style'};
    3977                 }
    3978 
    3979                 if (e.style && s.hidden_tab_class.length > 0 && e.className.indexOf(s.hidden_tab_class) != -1) {
    3980                     e.className = s.display_tab_class;
    3981                     nl[nl.length] = {elm : e, type : 'class'};
    3982                 }
    3983             } while ((e = e.parentNode) != null)
    3984         }
    3985 
    3986         tinyMCE.settings.preformatted = false;
    3987 
    3988         // Default to false
    3989         if (typeof(skip_cleanup) == "undefined")
    3990             skip_cleanup = false;
    3991 
    3992         // Default to false
    3993         if (typeof(skip_callback) == "undefined")
    3994             skip_callback = false;
    3995 
    3996         tinyMCE._setHTML(this.getDoc(), this.getBody().innerHTML);
    3997 
    3998         // Remove visual aids when cleanup is disabled
    3999         if (this.settings.cleanup == false) {
    4000             tinyMCE.handleVisualAid(this.getBody(), true, false, this);
    4001             tinyMCE._setEventsEnabled(this.getBody(), true);
    4002         }
    4003 
    4004         tinyMCE._customCleanup(this, "submit_content_dom", this.contentWindow.document.body);
    4005         htm = skip_cleanup ? this.getBody().innerHTML : tinyMCE._cleanupHTML(this, this.getDoc(), this.settings, this.getBody(), tinyMCE.visualAid, true, true);
    4006         htm = tinyMCE._customCleanup(this, "submit_content", htm);
    4007 
    4008         if (!skip_callback && tinyMCE.settings.save_callback !== '')
    4009             content = tinyMCE.resolveDots(tinyMCE.settings.save_callback, window)(this.formTargetElementId,htm,this.getBody());
    4010 
    4011         // Use callback content if available
    4012         if ((typeof(content) != "undefined") && content != null)
    4013             htm = content;
    4014 
    4015         // Replace some weird entities (Bug: #1056343)
    4016         htm = tinyMCE.regexpReplace(htm, "&#40;", "(", "gi");
    4017         htm = tinyMCE.regexpReplace(htm, "&#41;", ")", "gi");
    4018         htm = tinyMCE.regexpReplace(htm, "&#59;", ";", "gi");
    4019         htm = tinyMCE.regexpReplace(htm, "&#34;", "&quot;", "gi");
    4020         htm = tinyMCE.regexpReplace(htm, "&#94;", "^", "gi");
    4021 
    4022         if (this.formElement)
    4023             this.formElement.value = htm;
    4024 
    4025         if (tinyMCE.isSafari && this.formElement)
    4026             this.formElement.innerText = htm;
    4027 
    4028         // Hide them again (tabs in MSIE)
    4029         for (i=0; i<nl.length; i++) {
    4030             if (nl[i].type == 'style')
    4031                 nl[i].elm.style.display = 'none';
    4032             else
    4033                 nl[i].elm.className = s.hidden_tab_class;
    4034         }
    4035     }
    4036 
    4037     };
    4038 
    4039 /* file:jscripts/tiny_mce/classes/TinyMCE_Cleanup.class.js */
    4040 
    4041 tinyMCE.add(TinyMCE_Engine, {
    4042     cleanupHTMLCode : function(s) {
    4043         s = s.replace(new RegExp('<p \\/>', 'gi'), '<p>&nbsp;</p>');
    4044         s = s.replace(new RegExp('<p>\\s*<\\/p>', 'gi'), '<p>&nbsp;</p>');
    4045 
    4046         // Fix close BR elements
    4047         s = s.replace(new RegExp('<br>\\s*<\\/br>', 'gi'), '<br />');
    4048 
    4049         // Open closed tags like <b/> to <b></b>
    4050         s = s.replace(new RegExp('<(h[1-6]|p|div|address|pre|form|table|li|ol|ul|td|b|font|em|strong|i|strike|u|span|a|ul|ol|li|blockquote)([a-z]*)([^\\\\|>]*)\\/>', 'gi'), '<$1$2$3></$1$2>');
    4051 
    4052         // Remove trailing space <b > to <b>
    4053         s = s.replace(new RegExp('\\s+></', 'gi'), '></');
    4054 
    4055         // Close tags <img></img> to <img/>
    4056         s = s.replace(new RegExp('<(img|br|hr)([^>]*)><\\/(img|br|hr)>', 'gi'), '<$1$2 />');
    4057 
    4058         // Weird MSIE bug, <p><hr /></p> breaks runtime?
    4059         if (tinyMCE.isIE)
    4060             s = s.replace(new RegExp('<p><hr \\/><\\/p>', 'gi'), "<hr>");
    4061 
    4062         // Weird tags will make IE error #bug: 1538495
    4063         if (tinyMCE.isIE)
    4064             s = s.replace(/<!(\s*)\/>/g, '');
    4065 
    4066         // Convert relative anchors to absolute URLs ex: #something to file.htm#something
    4067         // Removed: Since local document anchors should never be forced absolute example edit.php?id=something
    4068         //if (tinyMCE.getParam('convert_urls'))
    4069         //  s = s.replace(new RegExp('(href=\"{0,1})(\\s*#)', 'gi'), '$1' + tinyMCE.settings.document_base_url + "#");
    4070 
    4071         return s;
    4072     },
    4073 
    4074     parseStyle : function(str) {
    4075         var ar = [], st, i, re, pa;
    4076 
    4077         if (str == null)
    4078             return ar;
    4079 
    4080         st = str.split(';');
    4081 
    4082         tinyMCE.clearArray(ar);
    4083 
    4084         for (i=0; i<st.length; i++) {
    4085             if (st[i] == '')
    4086                 continue;
    4087 
    4088             re = new RegExp('^\\s*([^:]*):\\s*(.*)\\s*$');
    4089             pa = st[i].replace(re, '$1||$2').split('||');
    4090     //tinyMCE.debug(str, pa[0] + "=" + pa[1], st[i].replace(re, '$1||$2'));
    4091             if (pa.length == 2)
    4092                 ar[pa[0].toLowerCase()] = pa[1];
    4093         }
    4094 
    4095         return ar;
    4096     },
    4097 
    4098     compressStyle : function(ar, pr, sf, res) {
    4099         var box = [], i, a;
    4100 
    4101         box[0] = ar[pr + '-top' + sf];
    4102         box[1] = ar[pr + '-left' + sf];
    4103         box[2] = ar[pr + '-right' + sf];
    4104         box[3] = ar[pr + '-bottom' + sf];
    4105 
    4106         for (i=0; i<box.length; i++) {
    4107             if (box[i] == null)
    4108                 return;
    4109 
    4110             for (a=0; a<box.length; a++) {
    4111                 if (box[a] != box[i])
    4112                     return;
    4113             }
    4114         }
    4115 
    4116         // They are all the same
    4117         ar[res] = box[0];
    4118         ar[pr + '-top' + sf] = null;
    4119         ar[pr + '-left' + sf] = null;
    4120         ar[pr + '-right' + sf] = null;
    4121         ar[pr + '-bottom' + sf] = null;
    4122     },
    4123 
    4124     serializeStyle : function(ar) {
    4125         var str = "", key, val, m;
    4126 
    4127         // Compress box
    4128         tinyMCE.compressStyle(ar, "border", "", "border");
    4129         tinyMCE.compressStyle(ar, "border", "-width", "border-width");
    4130         tinyMCE.compressStyle(ar, "border", "-color", "border-color");
    4131         tinyMCE.compressStyle(ar, "border", "-style", "border-style");
    4132         tinyMCE.compressStyle(ar, "padding", "", "padding");
    4133         tinyMCE.compressStyle(ar, "margin", "", "margin");
    4134 
    4135         for (key in ar) {
    4136             val = ar[key];
    4137 
    4138             if (typeof(val) == 'function')
    4139                 continue;
    4140 
    4141             if (key.indexOf('mso-') == 0)
    4142                 continue;
    4143 
    4144             if (val != null && val !== '') {
    4145                 val = '' + val; // Force string
    4146 
    4147                 // Fix style URL
    4148                 val = val.replace(new RegExp("url\\(\\'?([^\\']*)\\'?\\)", 'gi'), "url('$1')");
    4149 
    4150                 // Convert URL
    4151                 if (val.indexOf('url(') != -1 && tinyMCE.getParam('convert_urls')) {
    4152                     m = new RegExp("url\\('(.*?)'\\)").exec(val);
    4153 
    4154                     if (m.length > 1)
    4155                         val = "url('" + eval(tinyMCE.getParam('urlconverter_callback') + "(m[1], null, true);") + "')";
    4156                 }
    4157 
    4158                 // Force HEX colors
    4159                 if (tinyMCE.getParam("force_hex_style_colors"))
    4160                     val = tinyMCE.convertRGBToHex(val, true);
    4161 
    4162                 val = val.replace(/\"/g, '\'');
    4163 
    4164                 if (val != "url('')")
    4165                     str += key.toLowerCase() + ": " + val + "; ";
    4166             }
    4167         }
    4168 
    4169         if (new RegExp('; $').test(str))
    4170             str = str.substring(0, str.length - 2);
    4171 
    4172         return str;
    4173     },
    4174 
    4175     convertRGBToHex : function(s, k) {
    4176         var re, rgb;
    4177 
    4178         if (s.toLowerCase().indexOf('rgb') != -1) {
    4179             re = new RegExp("(.*?)rgb\\s*?\\(\\s*?([0-9]+).*?,\\s*?([0-9]+).*?,\\s*?([0-9]+).*?\\)(.*?)", "gi");
    4180             rgb = s.replace(re, "$1,$2,$3,$4,$5").split(',');
    4181 
    4182             if (rgb.length == 5) {
    4183                 r = parseInt(rgb[1]).toString(16);
    4184                 g = parseInt(rgb[2]).toString(16);
    4185                 b = parseInt(rgb[3]).toString(16);
    4186 
    4187                 r = r.length == 1 ? '0' + r : r;
    4188                 g = g.length == 1 ? '0' + g : g;
    4189                 b = b.length == 1 ? '0' + b : b;
    4190 
    4191                 s = "#" + r + g + b;
    4192 
    4193                 if (k)
    4194                     s = rgb[0] + s + rgb[4];
    4195             }
    4196         }
    4197 
    4198         return s;
    4199     },
    4200 
    4201     convertHexToRGB : function(s) {
    4202         if (s.indexOf('#') != -1) {
    4203             s = s.replace(new RegExp('[^0-9A-F]', 'gi'), '');
    4204             return "rgb(" + parseInt(s.substring(0, 2), 16) + "," + parseInt(s.substring(2, 4), 16) + "," + parseInt(s.substring(4, 6), 16) + ")";
    4205         }
    4206 
    4207         return s;
    4208     },
    4209 
    4210     convertSpansToFonts : function(doc) {
    4211         var s, i, size, fSize, x, fFace, fColor, sizes = tinyMCE.getParam('font_size_style_values').replace(/\s+/, '').split(',');
    4212 
    4213         s = tinyMCE.selectElements(doc, 'span,font');
    4214         for (i=0; i<s.length; i++) {
    4215             size = tinyMCE.trim(s[i].style.fontSize).toLowerCase();
    4216             fSize = 0;
    4217 
    4218             for (x=0; x<sizes.length; x++) {
    4219                 if (sizes[x] == size) {
    4220                     fSize = x + 1;
    4221                     break;
    4222                 }
    4223             }
    4224 
    4225             if (fSize > 0) {
    4226                 tinyMCE.setAttrib(s[i], 'size', fSize);
    4227                 s[i].style.fontSize = '';
    4228             }
    4229 
    4230             fFace = s[i].style.fontFamily;
    4231             if (fFace != null && fFace !== '') {
    4232                 tinyMCE.setAttrib(s[i], 'face', fFace);
    4233                 s[i].style.fontFamily = '';
    4234             }
    4235 
    4236             fColor = s[i].style.color;
    4237             if (fColor != null && fColor !== '') {
    4238                 tinyMCE.setAttrib(s[i], 'color', tinyMCE.convertRGBToHex(fColor));
    4239                 s[i].style.color = '';
    4240             }
    4241         }
    4242     },
    4243 
    4244     convertFontsToSpans : function(doc) {
    4245         var fsClasses, s, i, fSize, fFace, fColor, sizes = tinyMCE.getParam('font_size_style_values').replace(/\s+/, '').split(',');
    4246 
    4247         fsClasses = tinyMCE.getParam('font_size_classes');
    4248         if (fsClasses !== '')
    4249             fsClasses = fsClasses.replace(/\s+/, '').split(',');
    4250         else
    4251             fsClasses = null;
    4252 
    4253         s = tinyMCE.selectElements(doc, 'span,font');
    4254         for (i=0; i<s.length; i++) {
    4255             fSize = tinyMCE.getAttrib(s[i], 'size');
    4256             fFace = tinyMCE.getAttrib(s[i], 'face');
    4257             fColor = tinyMCE.getAttrib(s[i], 'color');
    4258 
    4259             if (fSize !== '') {
    4260                 fSize = parseInt(fSize);
    4261 
    4262                 if (fSize > 0 && fSize < 8) {
    4263                     if (fsClasses != null)
    4264                         tinyMCE.setAttrib(s[i], 'class', fsClasses[fSize-1]);
    4265                     else
    4266                         s[i].style.fontSize = sizes[fSize-1];
    4267                 }
    4268 
    4269                 s[i].removeAttribute('size');
    4270             }
    4271 
    4272             if (fFace !== '') {
    4273                 s[i].style.fontFamily = fFace;
    4274                 s[i].removeAttribute('face');
    4275             }
    4276 
    4277             if (fColor !== '') {
    4278                 s[i].style.color = fColor;
    4279                 s[i].removeAttribute('color');
    4280             }
    4281         }
    4282     },
    4283 
    4284     cleanupAnchors : function(doc) {
    4285         var i, cn, x, an = doc.getElementsByTagName("a");
    4286 
    4287         // Loops backwards due to bug #1467987
    4288         for (i=an.length-1; i>=0; i--) {
    4289             if (tinyMCE.getAttrib(an[i], "name") !== '' && tinyMCE.getAttrib(an[i], "href") == '') {
    4290                 cn = an[i].childNodes;
    4291 
    4292                 for (x=cn.length-1; x>=0; x--)
    4293                     tinyMCE.insertAfter(cn[x], an[i]);
    4294             }
    4295         }
    4296     },
    4297 
    4298     getContent : function(editor_id) {
    4299         if (typeof(editor_id) != "undefined")
    4300              tinyMCE.getInstanceById(editor_id).select();
    4301 
    4302         if (tinyMCE.selectedInstance)
    4303             return tinyMCE.selectedInstance.getHTML();
    4304 
    4305         return null;
    4306     },
    4307 
    4308     _fixListElements : function(d) {
    4309         var nl, x, a = ['ol', 'ul'], i, n, p, r = new RegExp('^(OL|UL)$'), np;
    4310 
    4311         for (x=0; x<a.length; x++) {
    4312             nl = d.getElementsByTagName(a[x]);
    4313 
    4314             for (i=0; i<nl.length; i++) {
    4315                 n = nl[i];
    4316                 p = n.parentNode;
    4317 
    4318                 if (r.test(p.nodeName)) {
    4319                     np = tinyMCE.prevNode(n, 'LI');
    4320 
    4321                     if (!np) {
    4322                         np = d.createElement('li');
    4323                         np.innerHTML = '&nbsp;';
    4324                         np.appendChild(n);
    4325                         p.insertBefore(np, p.firstChild);
    4326                     } else
    4327                         np.appendChild(n);
    4328                 }
    4329             }
    4330         }
    4331     },
    4332 
    4333     _fixTables : function(d) {
    4334         var nl, i, n, p, np, x, t;
    4335 
    4336         nl = d.getElementsByTagName('table');
    4337         for (i=0; i<nl.length; i++) {
    4338             n = nl[i];
    4339 
    4340             if ((p = tinyMCE.getParentElement(n, 'p,h1,h2,h3,h4,h5,h6')) != null) {
    4341                 np = p.cloneNode(false);
    4342                 np.removeAttribute('id');
    4343 
    4344                 t = n;
    4345 
    4346                 while ((n = n.nextSibling))
    4347                     np.appendChild(n);
    4348 
    4349                 tinyMCE.insertAfter(np, p);
    4350                 tinyMCE.insertAfter(t, p);
    4351             }
    4352         }
    4353     },
    4354 
    4355     _cleanupHTML : function(inst, doc, config, elm, visual, on_save, on_submit, inn) {
    4356         var h, d, t1, t2, t3, t4, t5, c, s, nb;
    4357 
    4358         if (!tinyMCE.getParam('cleanup'))
    4359             return elm.innerHTML;
    4360 
    4361         on_save = typeof(on_save) == 'undefined' ? false : on_save;
    4362 
    4363         c = inst.cleanup;
    4364         s = inst.settings;
    4365         d = c.settings.debug;
    4366 
    4367         if (d)
    4368             t1 = new Date().getTime();
    4369 
    4370         inst._fixRootBlocks();
    4371 
    4372         if (tinyMCE.getParam("convert_fonts_to_spans"))
    4373             tinyMCE.convertFontsToSpans(doc);
    4374 
    4375         if (tinyMCE.getParam("fix_list_elements"))
    4376             tinyMCE._fixListElements(doc);
    4377 
    4378         if (tinyMCE.getParam("fix_table_elements"))
    4379             tinyMCE._fixTables(doc);
    4380 
    4381         // Call custom cleanup code
    4382         tinyMCE._customCleanup(inst, on_save ? "get_from_editor_dom" : "insert_to_editor_dom", doc.body);
    4383 
    4384         if (d)
    4385             t2 = new Date().getTime();
    4386 
    4387         c.settings.on_save = on_save;
    4388 
    4389         c.idCount = 0;
    4390         c.serializationId = new Date().getTime().toString(32); // Unique ID needed for the content duplication bug
    4391         c.serializedNodes = [];
    4392         c.sourceIndex = -1;
    4393 
    4394         if (s.cleanup_serializer == "xml")
    4395             h = c.serializeNodeAsXML(elm, inn);
    4396         else
    4397             h = c.serializeNodeAsHTML(elm, inn);
    4398 
    4399         if (d)
    4400             t3 = new Date().getTime();
    4401 
    4402         // Post processing
    4403         nb = tinyMCE.getParam('entity_encoding') == 'numeric' ? '&#160;' : '&nbsp;';
    4404         h = h.replace(/<\/?(body|head|html)[^>]*>/gi, '');
    4405         h = h.replace(new RegExp(' (rowspan="1"|colspan="1")', 'g'), '');
    4406         h = h.replace(/<p><hr \/><\/p>/g, '<hr />');
    4407         h = h.replace(/<p>(&nbsp;|&#160;)<\/p><hr \/><p>(&nbsp;|&#160;)<\/p>/g, '<hr />');
    4408         h = h.replace(/<td>\s*<br \/>\s*<\/td>/g, '<td>' + nb + '</td>');
    4409         h = h.replace(/<p>\s*<br \/>\s*<\/p>/g, '<p>' + nb + '</p>');
    4410         h = h.replace(/<br \/>$/, ''); // Remove last BR for Gecko
    4411         h = h.replace(/<br \/><\/p>/g, '</p>'); // Remove last BR in P tags for Gecko
    4412         h = h.replace(/<p>\s*(&nbsp;|&#160;)\s*<br \/>\s*(&nbsp;|&#160;)\s*<\/p>/g, '<p>' + nb + '</p>');
    4413         h = h.replace(/<p>\s*(&nbsp;|&#160;)\s*<br \/>\s*<\/p>/g, '<p>' + nb + '</p>');
    4414         h = h.replace(/<p>\s*<br \/>\s*&nbsp;\s*<\/p>/g, '<p>' + nb + '</p>');
    4415         h = h.replace(new RegExp('<a>(.*?)<\\/a>', 'g'), '$1');
    4416         h = h.replace(/<p([^>]*)>\s*<\/p>/g, '<p$1>' + nb + '</p>');
    4417 
    4418         // Clean body
    4419         if (/^\s*(<br \/>|<p>&nbsp;<\/p>|<p>&#160;<\/p>|<p><\/p>)\s*$/.test(h))
    4420             h = '';
    4421 
    4422         // If preformatted
    4423         if (s.preformatted) {
    4424             h = h.replace(/^<pre>/, '');
    4425             h = h.replace(/<\/pre>$/, '');
    4426             h = '<pre>' + h + '</pre>';
    4427         }
    4428 
    4429         // Gecko specific processing
    4430         if (tinyMCE.isGecko) {
    4431             // Makes no sence but FF generates it!!
    4432             h = h.replace(/<br \/>\s*<\/li>/g, '</li>');
    4433             h = h.replace(/&nbsp;\s*<\/(dd|dt)>/g, '</$1>');
    4434             h = h.replace(/<o:p _moz-userdefined="" \/>/g, '');
    4435             h = h.replace(/<td([^>]*)>\s*<br \/>\s*<\/td>/g, '<td$1>' + nb + '</td>');
    4436         }
    4437 
    4438         if (s.force_br_newlines)
    4439             h = h.replace(/<p>(&nbsp;|&#160;)<\/p>/g, '<br />');
    4440 
    4441         // Call custom cleanup code
    4442         h = tinyMCE._customCleanup(inst, on_save ? "get_from_editor" : "insert_to_editor", h);
    4443 
    4444         // Remove internal classes
    4445         if (on_save) {
    4446             h = h.replace(new RegExp(' ?(mceItem[a-zA-Z0-9]*|' + s.visual_table_class + ')', 'g'), '');
    4447             h = h.replace(new RegExp(' ?class=""', 'g'), '');
    4448         }
    4449 
    4450         if (s.remove_linebreaks && !c.settings.indent)
    4451             h = h.replace(/\n|\r/g, ' ');
    4452 
    4453         if (d)
    4454             t4 = new Date().getTime();
    4455 
    4456         if (on_save && c.settings.indent)
    4457             h = c.formatHTML(h);
    4458 
    4459         // If encoding (not recommended option)
    4460         if (on_submit && (s.encoding == "xml" || s.encoding == "html"))
    4461             h = c.xmlEncode(h);
    4462 
    4463         if (d)
    4464             t5 = new Date().getTime();
    4465 
    4466         if (c.settings.debug)
    4467             tinyMCE.debug("Cleanup in ms: Pre=" + (t2-t1) + ", Serialize: " + (t3-t2) + ", Post: " + (t4-t3) + ", Format: " + (t5-t4) + ", Sum: " + (t5-t1) + ".");
    4468 
    4469         return h;
    4470     }
    4471 });
    4472 
    4473 function TinyMCE_Cleanup() {
    4474     this.isIE = (navigator.appName == "Microsoft Internet Explorer");
    4475     this.rules = tinyMCE.clearArray([]);
    4476 
    4477     // Default config
    4478     this.settings = {
    4479         indent_elements : 'head,table,tbody,thead,tfoot,form,tr,ul,ol,blockquote,object',
    4480         newline_before_elements : 'h1,h2,h3,h4,h5,h6,pre,address,div,ul,ol,li,meta,option,area,title,link,base,script,td',
    4481         newline_after_elements : 'br,hr,p,pre,address,div,ul,ol,meta,option,area,link,base,script',
    4482         newline_before_after_elements : 'html,head,body,table,thead,tbody,tfoot,tr,form,ul,ol,blockquote,p,object,param,hr,div',
    4483         indent_char : '\t',
    4484         indent_levels : 1,
    4485         entity_encoding : 'raw',
    4486         valid_elements : '*[*]',
    4487         entities : '',
    4488         url_converter : '',
    4489         invalid_elements : '',
    4490         verify_html : false
    4491     };
    4492 
    4493     this.vElements = tinyMCE.clearArray([]);
    4494     this.vElementsRe = '';
    4495     this.closeElementsRe = /^(IMG|BR|HR|LINK|META|BASE|INPUT|AREA)$/;
    4496     this.codeElementsRe = /^(SCRIPT|STYLE)$/;
    4497     this.serializationId = 0;
    4498     this.mceAttribs = {
    4499         href : 'mce_href',
    4500         src : 'mce_src',
    4501         type : 'mce_type'
    4502     };
    4503 }
    4504 
    4505 TinyMCE_Cleanup.prototype = {
    4506     init : function(s) {
    4507         var n, a, i, ir, or, st;
    4508 
    4509         for (n in s)
    4510             this.settings[n] = s[n];
    4511 
    4512         // Setup code formating
    4513         s = this.settings;
    4514 
    4515         // Setup regexps
    4516         this.inRe = this._arrayToRe(s.indent_elements.split(','), '', '^<(', ')[^>]*');
    4517         this.ouRe = this._arrayToRe(s.indent_elements.split(','), '', '^<\\/(', ')[^>]*');
    4518         this.nlBeforeRe = this._arrayToRe(s.newline_before_elements.split(','), 'gi', '<(',  ')([^>]*)>');
    4519         this.nlAfterRe = this._arrayToRe(s.newline_after_elements.split(','), 'gi', '<(',  ')([^>]*)>');
    4520         this.nlBeforeAfterRe = this._arrayToRe(s.newline_before_after_elements.split(','), 'gi', '<(\\/?)(', ')([^>]*)>');
    4521         this.serializedNodes = [];
    4522 
    4523         if (s.invalid_elements !== '')
    4524             this.iveRe = this._arrayToRe(s.invalid_elements.toUpperCase().split(','), 'g', '^(', ')$');
    4525         else
    4526             this.iveRe = null;
    4527 
    4528         // Setup separator
    4529         st = '';
    4530         for (i=0; i<s.indent_levels; i++)
    4531             st += s.indent_char;
    4532 
    4533         this.inStr = st;
    4534 
    4535         // If verify_html if false force *[*]
    4536         if (!s.verify_html) {
    4537             s.valid_elements = '*[*]';
    4538             s.extended_valid_elements = '';
    4539         }
    4540 
    4541         this.fillStr = s.entity_encoding == "named" ? "&nbsp;" : "&#160;";
    4542         this.idCount = 0;
    4543         this.xmlEncodeRe = new RegExp('[\u007F-\uFFFF<>&"]', 'g');
    4544     },
    4545 
    4546     addRuleStr : function(s) {
    4547         var r = this.parseRuleStr(s), n;
    4548 
    4549         for (n in r) {
    4550             if (r[n])
    4551                 this.rules[n] = r[n];
    4552         }
    4553 
    4554         this.vElements = tinyMCE.clearArray([]);
    4555 
    4556         for (n in this.rules) {
    4557             if (this.rules[n])
    4558                 this.vElements[this.vElements.length] = this.rules[n].tag;
    4559         }
    4560 
    4561         this.vElementsRe = this._arrayToRe(this.vElements, '');
    4562     },
    4563 
    4564     isValid : function(n) {
    4565         if (!this.rulesDone)
    4566             this._setupRules(); // Will initialize cleanup rules
    4567 
    4568         // Empty is true since it removes formatting
    4569         if (!n)
    4570             return true;
    4571 
    4572         // Clean the name up a bit
    4573         n = n.replace(/[^a-z0-9]+/gi, '').toUpperCase();
    4574 
    4575         return !tinyMCE.getParam('cleanup') || this.vElementsRe.test(n);
    4576     },
    4577 
    4578     addChildRemoveRuleStr : function(s) {
    4579         var x, y, p, i, t, tn, ta, cl, r;
    4580 
    4581         if (!s)
    4582             return;
    4583 
    4584         ta = s.split(',');
    4585         for (x=0; x<ta.length; x++) {
    4586             s = ta[x];
    4587 
    4588             // Split tag/children
    4589             p = this.split(/\[|\]/, s);
    4590             if (p == null || p.length < 1)
    4591                 t = s.toUpperCase();
    4592             else
    4593                 t = p[0].toUpperCase();
    4594 
    4595             // Handle all tag names
    4596             tn = this.split('/', t);
    4597             for (y=0; y<tn.length; y++) {
    4598                 r = "^(";
    4599 
    4600                 // Build regex
    4601                 cl = this.split(/\|/, p[1]);
    4602                 for (i=0; i<cl.length; i++) {
    4603                     if (cl[i] == '%istrict')
    4604                         r += tinyMCE.inlineStrict;
    4605                     else if (cl[i] == '%itrans')
    4606                         r += tinyMCE.inlineTransitional;
    4607                     else if (cl[i] == '%istrict_na')
    4608                         r += tinyMCE.inlineStrict.substring(2);
    4609                     else if (cl[i] == '%itrans_na')
    4610                         r += tinyMCE.inlineTransitional.substring(2);
    4611                     else if (cl[i] == '%btrans')
    4612                         r += tinyMCE.blockElms;
    4613                     else if (cl[i] == '%strict')
    4614                         r += tinyMCE.blockStrict;
    4615                     else
    4616                         r += (cl[i].charAt(0) != '#' ? cl[i].toUpperCase() : cl[i]);
    4617 
    4618                     r += (i != cl.length - 1 ? '|' : '');
    4619                 }
    4620 
    4621                 r += ')$';
    4622 
    4623                 if (this.childRules == null)
    4624                     this.childRules = tinyMCE.clearArray([]);
    4625 
    4626                 this.childRules[tn[y]] = new RegExp(r);
    4627 
    4628                 if (p.length > 1)
    4629                     this.childRules[tn[y]].wrapTag = p[2];
    4630             }
    4631         }
    4632     },
    4633 
    4634     parseRuleStr : function(s) {
    4635         var ta, p, r, a, i, x, px, t, tn, y, av, or = tinyMCE.clearArray([]), dv;
    4636 
    4637         if (s == null || s.length == 0)
    4638             return or;
    4639 
    4640         ta = s.split(',');
    4641         for (x=0; x<ta.length; x++) {
    4642             s = ta[x];
    4643             if (s.length == 0)
    4644                 continue;
    4645 
    4646             // Split tag/attrs
    4647             p = this.split(/\[|\]/, s);
    4648             if (p == null || p.length < 1)
    4649                 t = s.toUpperCase();
    4650             else
    4651                 t = p[0].toUpperCase();
    4652 
    4653             // Handle all tag names
    4654             tn = this.split('/', t);
    4655             for (y=0; y<tn.length; y++) {
    4656                 r = {};
    4657 
    4658                 r.tag = tn[y];
    4659                 r.forceAttribs = null;
    4660                 r.defaultAttribs = null;
    4661                 r.validAttribValues = null;
    4662 
    4663                 // Handle prefixes
    4664                 px = r.tag.charAt(0);
    4665                 r.forceOpen = px == '+';
    4666                 r.removeEmpty = px == '-';
    4667                 r.fill = px == '#';
    4668                 r.tag = r.tag.replace(/\+|-|#/g, '');
    4669                 r.oTagName = tn[0].replace(/\+|-|#/g, '').toLowerCase();
    4670                 r.isWild = new RegExp('\\*|\\?|\\+', 'g').test(r.tag);
    4671                 r.validRe = new RegExp(this._wildcardToRe('^' + r.tag + '$'));
    4672 
    4673                 // Setup valid attributes
    4674                 if (p.length > 1) {
    4675                     r.vAttribsRe = '^(';
    4676                     a = this.split(/\|/, p[1]);
    4677 
    4678                     for (i=0; i<a.length; i++) {
    4679                         t = a[i];
    4680 
    4681                         if (t.charAt(0) == '!') {
    4682                             a[i] = t = t.substring(1);
    4683 
    4684                             if (!r.reqAttribsRe)
    4685                                 r.reqAttribsRe = '\\s+(' + t;
    4686                             else
    4687                                 r.reqAttribsRe += '|' + t;
    4688                         }
    4689 
    4690                         av = new RegExp('(=|:|<)(.*?)$').exec(t);
    4691                         t = t.replace(new RegExp('(=|:|<).*?$'), '');
    4692                         if (av && av.length > 0) {
    4693                             if (av[0].charAt(0) == ':') {
    4694                                 if (!r.forceAttribs)
    4695                                     r.forceAttribs = tinyMCE.clearArray([]);
    4696 
    4697                                 r.forceAttribs[t.toLowerCase()] = av[0].substring(1);
    4698                             } else if (av[0].charAt(0) == '=') {
    4699                                 if (!r.defaultAttribs)
    4700                                     r.defaultAttribs = tinyMCE.clearArray([]);
    4701 
    4702                                 dv = av[0].substring(1);
    4703 
    4704                                 r.defaultAttribs[t.toLowerCase()] = dv == '' ? "mce_empty" : dv;
    4705                             } else if (av[0].charAt(0) == '<') {
    4706                                 if (!r.validAttribValues)
    4707                                     r.validAttribValues = tinyMCE.clearArray([]);
    4708 
    4709                                 r.validAttribValues[t.toLowerCase()] = this._arrayToRe(this.split('?', av[0].substring(1)), 'i');
    4710                             }
    4711                         }
    4712 
    4713                         r.vAttribsRe += '' + t.toLowerCase() + (i != a.length - 1 ? '|' : '');
    4714 
    4715                         a[i] = t.toLowerCase();
    4716                     }
    4717 
    4718                     if (r.reqAttribsRe)
    4719                         r.reqAttribsRe = new RegExp(r.reqAttribsRe + ')=\"', 'g');
    4720 
    4721                     r.vAttribsRe += ')$';
    4722                     r.vAttribsRe = this._wildcardToRe(r.vAttribsRe);
    4723                     r.vAttribsReIsWild = new RegExp('\\*|\\?|\\+', 'g').test(r.vAttribsRe);
    4724                     r.vAttribsRe = new RegExp(r.vAttribsRe);
    4725                     r.vAttribs = a.reverse();
    4726 
    4727                     //tinyMCE.debug(r.tag, r.oTagName, r.vAttribsRe, r.vAttribsReWC);
    4728                 } else {
    4729                     r.vAttribsRe = '';
    4730                     r.vAttribs = tinyMCE.clearArray([]);
    4731                     r.vAttribsReIsWild = false;
    4732                 }
    4733 
    4734                 or[r.tag] = r;
    4735             }
    4736         }
    4737 
    4738         return or;
    4739     },
    4740 
    4741     serializeNodeAsXML : function(n) {
    4742         var s, b;
    4743 
    4744         if (!this.xmlDoc) {
    4745             if (this.isIE) {
    4746                 try {this.xmlDoc = new ActiveXObject('MSXML2.DOMDocument');} catch (e) {}
    4747 
    4748                 if (!this.xmlDoc)
    4749                     try {this.xmlDoc = new ActiveXObject('Microsoft.XmlDom');} catch (e) {}
    4750             } else
    4751                 this.xmlDoc = document.implementation.createDocument('', '', null);
    4752 
    4753             if (!this.xmlDoc)
    4754                 alert("Error XML Parser could not be found.");
    4755         }
    4756 
    4757         if (this.xmlDoc.firstChild)
    4758             this.xmlDoc.removeChild(this.xmlDoc.firstChild);
    4759 
    4760         b = this.xmlDoc.createElement("html");
    4761         b = this.xmlDoc.appendChild(b);
    4762 
    4763         this._convertToXML(n, b);
    4764 
    4765         if (this.isIE)
    4766             return this.xmlDoc.xml;
    4767         else
    4768             return new XMLSerializer().serializeToString(this.xmlDoc);
    4769     },
    4770 
    4771     _convertToXML : function(n, xn) {
    4772         var xd, el, i, l, cn, at, no, hc = false;
    4773 
    4774         if (tinyMCE.isRealIE && this._isDuplicate(n))
    4775             return;
    4776 
    4777         xd = this.xmlDoc;
    4778 
    4779         switch (n.nodeType) {
    4780             case 1: // Element
    4781                 hc = n.hasChildNodes();
    4782 
    4783                 el = xd.createElement(n.nodeName.toLowerCase());
    4784 
    4785                 at = n.attributes;
    4786                 for (i=at.length-1; i>-1; i--) {
    4787                     no = at[i];
    4788 
    4789                     if (no.specified && no.nodeValue)
    4790                         el.setAttribute(no.nodeName.toLowerCase(), no.nodeValue);
    4791                 }
    4792 
    4793                 if (!hc && !this.closeElementsRe.test(n.nodeName))
    4794                     el.appendChild(xd.createTextNode(""));
    4795 
    4796                 xn = xn.appendChild(el);
    4797                 break;
    4798 
    4799             case 3: // Text
    4800                 xn.appendChild(xd.createTextNode(n.nodeValue));
    4801                 return;
    4802 
    4803             case 8: // Comment
    4804                 xn.appendChild(xd.createComment(n.nodeValue));
    4805                 return;
    4806         }
    4807 
    4808         if (hc) {
    4809             cn = n.childNodes;
    4810 
    4811             for (i=0, l=cn.length; i<l; i++)
    4812                 this._convertToXML(cn[i], xn);
    4813         }
    4814     },
    4815 
    4816     serializeNodeAsHTML : function(n, inn) {
    4817         var en, no, h = '', i, l, t, st, r, cn, va = false, f = false, at, hc, cr, nn;
    4818 
    4819         if (!this.rulesDone)
    4820             this._setupRules(); // Will initialize cleanup rules
    4821 
    4822         if (tinyMCE.isRealIE && this._isDuplicate(n))
    4823             return '';
    4824 
    4825         // Skip non valid child elements
    4826         if (n.parentNode && this.childRules != null) {
    4827             cr = this.childRules[n.parentNode.nodeName];
    4828 
    4829             if (typeof(cr) != "undefined" && !cr.test(n.nodeName)) {
    4830                 st = true;
    4831                 t = null;
    4832             }
    4833         }
    4834 
    4835         switch (n.nodeType) {
    4836             case 1: // Element
    4837                 hc = n.hasChildNodes();
    4838 
    4839                 if (st)
    4840                     break;
    4841 
    4842                 nn = n.nodeName;
    4843 
    4844                 if (tinyMCE.isRealIE) {
    4845                     // MSIE sometimes produces <//tag>
    4846                     if (n.nodeName.indexOf('/') != -1)
    4847                         break;
    4848 
    4849                     // MSIE has it's NS in a separate attrib
    4850                     if (n.scopeName && n.scopeName != 'HTML')
    4851                         nn = n.scopeName.toUpperCase() + ':' + nn.toUpperCase();
    4852                 } else if (tinyMCE.isOpera && nn.indexOf(':') > 0)
    4853                     nn = nn.toUpperCase();
    4854 
    4855                 // Convert fonts to spans
    4856                 if (this.settings.convert_fonts_to_spans) {
    4857                     // On get content FONT -> SPAN
    4858                     if (this.settings.on_save && nn == 'FONT')
    4859                         nn = 'SPAN';
    4860 
    4861                     // On insert content SPAN -> FONT
    4862                     if (!this.settings.on_save && nn == 'SPAN')
    4863                         nn = 'FONT';
    4864                 }
    4865 
    4866                 if (this.vElementsRe.test(nn) && (!this.iveRe || !this.iveRe.test(nn)) && !inn) {
    4867                     va = true;
    4868 
    4869                     r = this.rules[nn];
    4870                     if (!r) {
    4871                         at = this.rules;
    4872                         for (no in at) {
    4873                             if (at[no] && at[no].validRe.test(nn)) {
    4874                                 r = at[no];
    4875                                 break;
    4876                             }
    4877                         }
    4878                     }
    4879 
    4880                     en = r.isWild ? nn.toLowerCase() : r.oTagName;
    4881                     f = r.fill;
    4882 
    4883                     if (r.removeEmpty && !hc)
    4884                         return "";
    4885 
    4886                     t = '<' + en;
    4887 
    4888                     if (r.vAttribsReIsWild) {
    4889                         // Serialize wildcard attributes
    4890                         at = n.attributes;
    4891                         for (i=at.length-1; i>-1; i--) {
    4892                             no = at[i];
    4893                             if (no.specified && r.vAttribsRe.test(no.nodeName))
    4894                                 t += this._serializeAttribute(n, r, no.nodeName);
    4895                         }
    4896                     } else {
    4897                         // Serialize specific attributes
    4898                         for (i=r.vAttribs.length-1; i>-1; i--)
    4899                             t += this._serializeAttribute(n, r, r.vAttribs[i]);
    4900                     }
    4901 
    4902                     // Serialize mce_ atts
    4903                     if (!this.settings.on_save) {
    4904                         at = this.mceAttribs;
    4905 
    4906                         for (no in at) {
    4907                             if (at[no])
    4908                                 t += this._serializeAttribute(n, r, at[no]);
    4909                         }
    4910                     }
    4911 
    4912                     // Check for required attribs
    4913                     if (r.reqAttribsRe && !t.match(r.reqAttribsRe))
    4914                         t = null;
    4915 
    4916                     // Close these
    4917                     if (t != null && this.closeElementsRe.test(nn))
    4918                         return t + ' />';
    4919 
    4920                     if (t != null)
    4921                         h += t + '>';
    4922 
    4923                     if (this.isIE && this.codeElementsRe.test(nn))
    4924                         h += n.innerHTML;
    4925                 }
    4926             break;
    4927 
    4928             case 3: // Text
    4929                 if (st)
    4930                     break;
    4931 
    4932                 if (n.parentNode && this.codeElementsRe.test(n.parentNode.nodeName))
    4933                     return this.isIE ? '' : n.nodeValue;
    4934 
    4935                 return this.xmlEncode(n.nodeValue);
    4936 
    4937             case 8: // Comment
    4938                 if (st)
    4939                     break;
    4940 
    4941                 return "<!--" + this._trimComment(n.nodeValue) + "-->";
    4942         }
    4943 
    4944         if (hc) {
    4945             cn = n.childNodes;
    4946 
    4947             for (i=0, l=cn.length; i<l; i++)
    4948                 h += this.serializeNodeAsHTML(cn[i]);
    4949         }
    4950 
    4951         // Fill empty nodes
    4952         if (f && !hc)
    4953             h += this.fillStr;
    4954 
    4955         // End element
    4956         if (t != null && va)
    4957             h += '</' + en + '>';
    4958 
    4959         return h;
    4960     },
    4961 
    4962     _serializeAttribute : function(n, r, an) {
    4963         var av = '', t, os = this.settings.on_save;
    4964 
    4965         if (os && (an.indexOf('mce_') == 0 || an.indexOf('_moz') == 0))
    4966             return '';
    4967 
    4968         if (os && this.mceAttribs[an])
    4969             av = this._getAttrib(n, this.mceAttribs[an]);
    4970 
    4971         if (av.length == 0)
    4972             av = this._getAttrib(n, an);
    4973 
    4974         if (av.length == 0 && r.defaultAttribs && (t = r.defaultAttribs[an])) {
    4975             av = t;
    4976 
    4977             if (av == "mce_empty")
    4978                 return " " + an + '=""';
    4979         }
    4980 
    4981         if (r.forceAttribs && (t = r.forceAttribs[an]))
    4982             av = t;
    4983 
    4984         if (os && av.length != 0 && /^(src|href|longdesc)$/.test(an))
    4985             av = this._urlConverter(this, n, av);
    4986 
    4987         if (av.length != 0 && r.validAttribValues && r.validAttribValues[an] && !r.validAttribValues[an].test(av))
    4988             return "";
    4989 
    4990         if (av.length != 0 && av == "{$uid}")
    4991             av = "uid_" + (this.idCount++);
    4992 
    4993         if (av.length != 0) {
    4994             if (an.indexOf('on') != 0)
    4995                 av = this.xmlEncode(av, 1);
    4996 
    4997             return " " + an + "=" + '"' + av + '"';
    4998         }
    4999 
    5000         return "";
    5001     },
    5002 
    5003     formatHTML : function(h) {
    5004         var s = this.settings, p = '', i = 0, li = 0, o = '', l;
    5005 
    5006         // Replace BR in pre elements to \n
    5007         h = h.replace(/<pre([^>]*)>(.*?)<\/pre>/gi, function (a, b, c) {
    5008             c = c.replace(/<br\s*\/>/gi, '\n');
    5009             return '<pre' + b + '>' + c + '</pre>';
    5010         });
    5011 
    5012         h = h.replace(/\r/g, ''); // Windows sux, isn't carriage return a thing of the past :)
    5013         h = '\n' + h;
    5014         h = h.replace(new RegExp('\\n\\s+', 'gi'), '\n'); // Remove previous formatting
    5015         h = h.replace(this.nlBeforeRe, '\n<$1$2>');
    5016         h = h.replace(this.nlAfterRe, '<$1$2>\n');
    5017         h = h.replace(this.nlBeforeAfterRe, '\n<$1$2$3>\n');
    5018         h += '\n';
    5019 
    5020         //tinyMCE.debug(h);
    5021 
    5022         while ((i = h.indexOf('\n', i + 1)) != -1) {
    5023             if ((l = h.substring(li + 1, i)).length != 0) {
    5024                 if (this.ouRe.test(l) && p.length >= s.indent_levels)
    5025                     p = p.substring(s.indent_levels);
    5026 
    5027                 o += p + l + '\n';
    5028    
    5029                 if (this.inRe.test(l))
    5030                     p += this.inStr;
    5031             }
    5032 
    5033             li = i;
    5034         }
    5035 
    5036         //tinyMCE.debug(h);
    5037 
    5038         return o;
    5039     },
    5040 
    5041     xmlEncode : function(s) {
    5042         var cl = this, re = this.xmlEncodeRe;
    5043 
    5044         if (!this.entitiesDone)
    5045             this._setupEntities(); // Will intialize lookup table
    5046 
    5047         switch (this.settings.entity_encoding) {
    5048             case "raw":
    5049                 return tinyMCE.xmlEncode(s);
    5050 
    5051             case "named":
    5052                 return s.replace(re, function (c) {
    5053                     var b = cl.entities[c.charCodeAt(0)];
    5054 
    5055                     return b ? '&' + b + ';' : c;
    5056                 });
    5057 
    5058             case "numeric":
    5059                 return s.replace(re, function (c) {
    5060                     return '&#' + c.charCodeAt(0) + ';';
    5061                 });
    5062         }
    5063 
    5064         return s;
    5065     },
    5066 
    5067     split : function(re, s) {
    5068         var i, l, o = [], c = s.split(re);
    5069 
    5070         for (i=0, l=c.length; i<l; i++) {
    5071             if (c[i] !== '')
    5072                 o[i] = c[i];
    5073         }
    5074 
    5075         return o;
    5076     },
    5077 
    5078     _trimComment : function(s) {
    5079         // Remove mce_src, mce_href
    5080         s = s.replace(new RegExp('\\smce_src=\"[^\"]*\"', 'gi'), "");
    5081         s = s.replace(new RegExp('\\smce_href=\"[^\"]*\"', 'gi'), "");
    5082 
    5083         return s;
    5084     },
    5085 
    5086     _getAttrib : function(e, n, d) {
    5087         var v, ex, nn;
    5088 
    5089         if (typeof(d) == "undefined")
    5090             d = "";
    5091 
    5092         if (!e || e.nodeType != 1)
    5093             return d;
    5094 
    5095         try {
    5096             v = e.getAttribute(n, 0);
    5097         } catch (ex) {
    5098             // IE 7 may cast exception on invalid attributes
    5099             v = e.getAttribute(n, 2);
    5100         }
    5101 
    5102         if (n == "class" && !v)
    5103             v = e.className;
    5104 
    5105         if (this.isIE) {
    5106             if (n == "http-equiv")
    5107                 v = e.httpEquiv;
    5108 
    5109             nn = e.nodeName;
    5110 
    5111             // Skip the default values that IE returns
    5112             if (nn == "FORM" && n == "enctype" && v == "application/x-www-form-urlencoded")
    5113                 v = "";
    5114 
    5115             if (nn == "INPUT" && n == "size" && v == "20")
    5116                 v = "";
    5117 
    5118             if (nn == "INPUT" && n == "maxlength" && v == "2147483647")
    5119                 v = "";
    5120 
    5121             // Images
    5122             if (n == "width" || n == "height")
    5123                 v = e.getAttribute(n, 2);
    5124         }
    5125 
    5126         if (n == 'style' && v) {
    5127             if (!tinyMCE.isOpera)
    5128                 v = e.style.cssText;
    5129 
    5130             v = tinyMCE.serializeStyle(tinyMCE.parseStyle(v));
    5131         }
    5132 
    5133         if (this.settings.on_save && n.indexOf('on') != -1 && this.settings.on_save && v && v !== '')
    5134             v = tinyMCE.cleanupEventStr(v);
    5135 
    5136         return (v && v !== '') ? '' + v : d;
    5137     },
    5138 
    5139     _urlConverter : function(c, n, v) {
    5140         if (!c.settings.on_save)
    5141             return tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, v);
    5142         else if (tinyMCE.getParam('convert_urls')) {
    5143             if (!this.urlConverter)
    5144                 this.urlConverter = eval(tinyMCE.settings.urlconverter_callback);
    5145 
    5146             return this.urlConverter(v, n, true);
    5147         }
    5148 
    5149         return v;
    5150     },
    5151 
    5152     _arrayToRe : function(a, op, be, af) {
    5153         var i, r;
    5154 
    5155         op = typeof(op) == "undefined" ? "gi" : op;
    5156         be = typeof(be) == "undefined" ? "^(" : be;
    5157         af = typeof(af) == "undefined" ? ")$" : af;
    5158 
    5159         r = be;
    5160 
    5161         for (i=0; i<a.length; i++)
    5162             r += this._wildcardToRe(a[i]) + (i != a.length-1 ? "|" : "");
    5163 
    5164         r += af;
    5165 
    5166         return new RegExp(r, op);
    5167     },
    5168 
    5169     _wildcardToRe : function(s) {
    5170         s = s.replace(/\?/g, '(\\S?)');
    5171         s = s.replace(/\+/g, '(\\S+)');
    5172         s = s.replace(/\*/g, '(\\S*)');
    5173 
    5174         return s;
    5175     },
    5176 
    5177     _setupEntities : function() {
    5178         var n, a, i, s = this.settings;
    5179 
    5180         // Setup entities
    5181         if (s.entity_encoding == "named") {
    5182             n = tinyMCE.clearArray([]);
    5183             a = this.split(',', s.entities);
    5184             for (i=0; i<a.length; i+=2)
    5185                 n[a[i]] = a[i+1];
    5186 
    5187             this.entities = n;
    5188         }
    5189 
    5190         this.entitiesDone = true;
    5191     },
    5192 
    5193     _setupRules : function() {
    5194         var s = this.settings;
    5195 
    5196         // Setup default rule
    5197         this.addRuleStr(s.valid_elements);
    5198         this.addRuleStr(s.extended_valid_elements);
    5199         this.addChildRemoveRuleStr(s.valid_child_elements);
    5200 
    5201         this.rulesDone = true;
    5202     },
    5203 
    5204     _isDuplicate : function(n) {
    5205         var i, l, sn;
    5206 
    5207         if (!this.settings.fix_content_duplication)
    5208             return false;
    5209 
    5210         if (tinyMCE.isRealIE && n.nodeType == 1) {
    5211             // Mark elements
    5212             if (n.mce_serialized == this.serializationId)
    5213                 return true;
    5214 
    5215             n.setAttribute('mce_serialized', this.serializationId);
    5216         } else {
    5217             sn = this.serializedNodes;
    5218 
    5219             // Search lookup table for text nodes  and comments
    5220             for (i=0, l = sn.length; i<l; i++) {
    5221                 if (sn[i] == n)
    5222                     return true;
    5223             }
    5224 
    5225             sn.push(n);
    5226         }
    5227 
    5228         return false;
    5229     }
    5230 
    5231     };
    5232 
    5233 /* file:jscripts/tiny_mce/classes/TinyMCE_DOMUtils.class.js */
    5234 
    5235 tinyMCE.add(TinyMCE_Engine, {
    5236     createTagHTML : function(tn, a, h) {
    5237         var o = '', f = tinyMCE.xmlEncode, n;
    5238 
    5239         o = '<' + tn;
    5240 
    5241         if (a) {
    5242             for (n in a) {
    5243                 if (typeof(a[n]) != 'function' && a[n] != null)
    5244                     o += ' ' + f(n) + '="' + f('' + a[n]) + '"';
    5245             }
    5246         }
    5247 
    5248         o += !h ? ' />' : '>' + h + '</' + tn + '>';
    5249 
    5250         return o;
    5251     },
    5252 
    5253     createTag : function(d, tn, a, h) {
    5254         var o = d.createElement(tn), n;
    5255 
    5256         if (a) {
    5257             for (n in a) {
    5258                 if (typeof(a[n]) != 'function' && a[n] != null)
    5259                     tinyMCE.setAttrib(o, n, a[n]);
    5260             }
    5261         }
    5262 
    5263         if (h)
    5264             o.innerHTML = h;
    5265 
    5266         return o;
    5267     },
    5268 
    5269     getElementByAttributeValue : function(n, e, a, v) {
    5270         return (n = this.getElementsByAttributeValue(n, e, a, v)).length == 0 ? null : n[0];
    5271     },
    5272 
    5273     getElementsByAttributeValue : function(n, e, a, v) {
    5274         var i, nl = n.getElementsByTagName(e), o = [];
    5275 
    5276         for (i=0; i<nl.length; i++) {
    5277             if (tinyMCE.getAttrib(nl[i], a).indexOf(v) != -1)
    5278                 o[o.length] = nl[i];
    5279         }
    5280 
    5281         return o;
    5282     },
    5283 
    5284     isBlockElement : function(n) {
    5285         return n != null && n.nodeType == 1 && this.blockRegExp.test(n.nodeName);
    5286     },
    5287 
    5288     getParentBlockElement : function(n, r) {
    5289         return this.getParentNode(n, function(n) {
    5290             return tinyMCE.isBlockElement(n);
    5291         }, r);
    5292 
    5293         return null;
    5294     },
    5295 
    5296     insertAfter : function(n, r){
    5297         if (r.nextSibling)
    5298             r.parentNode.insertBefore(n, r.nextSibling);
    5299         else
    5300             r.parentNode.appendChild(n);
    5301     },
    5302 
    5303     setInnerHTML : function(e, h) {
    5304         var i, nl, n;
    5305 
    5306         // Convert all strong/em to b/i in Gecko
    5307         if (tinyMCE.isGecko) {
    5308             h = h.replace(/<embed([^>]*)>/gi, '<tmpembed$1>');
    5309             h = h.replace(/<em([^>]*)>/gi, '<i$1>');
    5310             h = h.replace(/<tmpembed([^>]*)>/gi, '<embed$1>');
    5311             h = h.replace(/<strong([^>]*)>/gi, '<b$1>');
    5312             h = h.replace(/<\/strong>/gi, '</b>');
    5313             h = h.replace(/<\/em>/gi, '</i>');
    5314         }
    5315 
    5316         if (tinyMCE.isRealIE) {
    5317             // Since MSIE handles invalid HTML better that valid XHTML we
    5318             // need to make some things invalid. <hr /> gets converted to <hr>.
    5319             h = h.replace(/\s\/>/g, '>');
    5320 
    5321             // Since MSIE auto generated emtpy P tags some times we must tell it to keep the real ones
    5322             h = h.replace(/<p([^>]*)>\u00A0?<\/p>/gi, '<p$1 mce_keep="true">&nbsp;</p>'); // Keep empty paragraphs
    5323             h = h.replace(/<p([^>]*)>\s*&nbsp;\s*<\/p>/gi, '<p$1 mce_keep="true">&nbsp;</p>'); // Keep empty paragraphs
    5324             h = h.replace(/<p([^>]*)>\s+<\/p>/gi, '<p$1 mce_keep="true">&nbsp;</p>'); // Keep empty paragraphs
    5325 
    5326             // Remove first comment
    5327             e.innerHTML = tinyMCE.uniqueTag + h;
    5328             e.firstChild.removeNode(true);
    5329 
    5330             // Remove weird auto generated empty paragraphs unless it's supposed to be there
    5331             nl = e.getElementsByTagName("p");
    5332             for (i=nl.length-1; i>=0; i--) {
    5333                 n = nl[i];
    5334 
    5335                 if (n.nodeName == 'P' && !n.hasChildNodes() && !n.mce_keep)
    5336                     n.parentNode.removeChild(n);
    5337             }
    5338         } else {
    5339             h = this.fixGeckoBaseHREFBug(1, e, h);
    5340             e.innerHTML = h;
    5341             this.fixGeckoBaseHREFBug(2, e, h);
    5342         }
    5343     },
    5344 
    5345     getOuterHTML : function(e) {
    5346         var d;
    5347 
    5348         if (tinyMCE.isIE)
    5349             return e.outerHTML;
    5350 
    5351         d = e.ownerDocument.createElement("body");
    5352         d.appendChild(e.cloneNode(true));
    5353 
    5354         return d.innerHTML;
    5355     },
    5356 
    5357     setOuterHTML : function(e, h, d) {
    5358         var d = typeof(d) == "undefined" ? e.ownerDocument : d, i, nl, t;
    5359 
    5360         if (tinyMCE.isIE && e.nodeType == 1)
    5361             e.outerHTML = h;
    5362         else {
    5363             t = d.createElement("body");
    5364             t.innerHTML = h;
    5365 
    5366             for (i=0, nl=t.childNodes; i<nl.length; i++)
    5367                 e.parentNode.insertBefore(nl[i].cloneNode(true), e);
    5368 
    5369             e.parentNode.removeChild(e);
    5370         }
    5371     },
    5372 
    5373     _getElementById : function(id, d) {
    5374         var e, i, j, f;
    5375 
    5376         if (typeof(d) == "undefined")
    5377             d = document;
    5378 
    5379         e = d.getElementById(id);
    5380         if (!e) {
    5381             f = d.forms;
    5382 
    5383             for (i=0; i<f.length; i++) {
    5384                 for (j=0; j<f[i].elements.length; j++) {
    5385                     if (f[i].elements[j].name == id) {
    5386                         e = f[i].elements[j];
    5387                         break;
    5388                     }
    5389                 }
    5390             }
    5391         }
    5392 
    5393         return e;
    5394     },
    5395 
    5396     getNodeTree : function(n, na, t, nn) {
    5397         return this.selectNodes(n, function(n) {
    5398             return (!t || n.nodeType == t) && (!nn || n.nodeName == nn);
    5399         }, na ? na : []);
    5400     },
    5401 
    5402     getParentElement : function(n, na, f, r) {
    5403         var re = na ? new RegExp('^(' + na.toUpperCase().replace(/,/g, '|') + ')$') : 0, v;
    5404 
    5405         // Compatiblity with old scripts where f param was a attribute string
    5406         if (f && typeof(f) == 'string')
    5407             return this.getParentElement(n, na, function(no) {return tinyMCE.getAttrib(no, f) !== '';});
    5408 
    5409         return this.getParentNode(n, function(n) {
    5410             return ((n.nodeType == 1 && !re) || (re && re.test(n.nodeName))) && (!f || f(n));
    5411         }, r);
    5412     },
    5413 
    5414     getParentNode : function(n, f, r) {
    5415         while (n) {
    5416             if (n == r)
    5417                 return null;
    5418 
    5419             if (f(n))
    5420                 return n;
    5421 
    5422             n = n.parentNode;
    5423         }
    5424 
    5425         return null;
    5426     },
    5427 
    5428     getAttrib : function(elm, name, dv) {
    5429         var v;
    5430 
    5431         if (typeof(dv) == "undefined")
    5432             dv = "";
    5433 
    5434         // Not a element
    5435         if (!elm || elm.nodeType != 1)
    5436             return dv;
    5437 
    5438         try {
    5439             v = elm.getAttribute(name, 0);
    5440         } catch (ex) {
    5441             // IE 7 may cast exception on invalid attributes
    5442             v = elm.getAttribute(name, 2);
    5443         }
    5444 
    5445         // Try className for class attrib
    5446         if (name == "class" && !v)
    5447             v = elm.className;
    5448 
    5449         // Workaround for a issue with Firefox 1.5rc2+
    5450         if (tinyMCE.isGecko) {
    5451             if (name == "src" && elm.src != null && elm.src !== '')
    5452                 v = elm.src;
    5453 
    5454             // Workaround for a issue with Firefox 1.5rc2+
    5455             if (name == "href" && elm.href != null && elm.href !== '')
    5456                 v = elm.href;
    5457         } else if (tinyMCE.isIE) {
    5458             switch (name) {
    5459                 case "http-equiv":
    5460                     v = elm.httpEquiv;
    5461                     break;
    5462 
    5463                 case "width":
    5464                 case "height":
    5465                     v = elm.getAttribute(name, 2);
    5466                     break;
    5467             }
    5468         }
    5469 
    5470         if (name == "style" && !tinyMCE.isOpera)
    5471             v = elm.style.cssText;
    5472 
    5473         return (v && v !== '') ? v : dv;
    5474     },
    5475 
    5476     setAttrib : function(el, name, va, fix) {
    5477         if (typeof(va) == "number" && va != null)
    5478             va = "" + va;
    5479 
    5480         if (fix) {
    5481             if (va == null)
    5482                 va = "";
    5483 
    5484             va = va.replace(/[^0-9%]/g, '');
    5485         }
    5486 
    5487         if (name == "style")
    5488             el.style.cssText = va;
    5489 
    5490         if (name == "class")
    5491             el.className = va;
    5492 
    5493         if (va != null && va !== '' && va != -1)
    5494             el.setAttribute(name, va);
    5495         else
    5496             el.removeAttribute(name);
    5497     },
    5498 
    5499     setStyleAttrib : function(e, n, v) {
    5500         e.style[n] = v;
    5501 
    5502         // Style attrib deleted in IE
    5503         if (tinyMCE.isIE && v == null || v == '') {
    5504             v = tinyMCE.serializeStyle(tinyMCE.parseStyle(e.style.cssText));
    5505             e.style.cssText = v;
    5506             e.setAttribute("style", v);
    5507         }
    5508     },
    5509 
    5510     switchClass : function(ei, c) {
    5511         var e;
    5512 
    5513         if (tinyMCE.switchClassCache[ei])
    5514             e = tinyMCE.switchClassCache[ei];
    5515         else
    5516             e = tinyMCE.switchClassCache[ei] = document.getElementById(ei);
    5517 
    5518         if (e) {
    5519             // Keep tile mode
    5520             if (tinyMCE.settings.button_tile_map && e.className && e.className.indexOf('mceTiledButton') == 0)
    5521                 c = 'mceTiledButton ' + c;
    5522 
    5523             e.className = c;
    5524         }
    5525     },
    5526 
    5527     getAbsPosition : function(n, cn) {
    5528         var l = 0, t = 0;
    5529 
    5530         while (n && n != cn) {
    5531             l += n.offsetLeft;
    5532             t += n.offsetTop;
    5533             n = n.offsetParent;
    5534         }
    5535 
    5536         return {absLeft : l, absTop : t};
    5537     },
    5538 
    5539     prevNode : function(e, n) {
    5540         var a = n.split(','), i;
    5541 
    5542         while ((e = e.previousSibling) != null) {
    5543             for (i=0; i<a.length; i++) {
    5544                 if (e.nodeName == a[i])
    5545                     return e;
    5546             }
    5547         }
    5548 
    5549         return null;
    5550     },
    5551 
    5552     nextNode : function(e, n) {
    5553         var a = n.split(','), i;
    5554 
    5555         while ((e = e.nextSibling) != null) {
    5556             for (i=0; i<a.length; i++) {
    5557                 if (e.nodeName == a[i])
    5558                     return e;
    5559             }
    5560         }
    5561 
    5562         return null;
    5563     },
    5564 
    5565     selectElements : function(n, na, f) {
    5566         var i, a = [], nl, x;
    5567 
    5568         for (x=0, na = na.split(','); x<na.length; x++)
    5569             for (i=0, nl = n.getElementsByTagName(na[x]); i<nl.length; i++)
    5570                 (!f || f(nl[i])) && a.push(nl[i]);
    5571 
    5572         return a;
    5573     },
    5574 
    5575     selectNodes : function(n, f, a) {
    5576         var i;
    5577 
    5578         if (!a)
    5579             a = [];
    5580 
    5581         if (f(n))
    5582             a[a.length] = n;
    5583 
    5584         if (n.hasChildNodes()) {
    5585             for (i=0; i<n.childNodes.length; i++)
    5586                 tinyMCE.selectNodes(n.childNodes[i], f, a);
    5587         }
    5588 
    5589         return a;
    5590     },
    5591 
    5592     addCSSClass : function(e, c, b) {
    5593         var o = this.removeCSSClass(e, c);
    5594         return e.className = b ? c + (o !== '' ? (' ' + o) : '') : (o !== '' ? (o + ' ') : '') + c;
    5595     },
    5596 
    5597     removeCSSClass : function(e, c) {
    5598         c = e.className.replace(new RegExp("(^|\\s+)" + c + "(\\s+|$)"), ' ');
    5599         return e.className = c != ' ' ? c : '';
    5600     },
    5601 
    5602     hasCSSClass : function(n, c) {
    5603         return new RegExp('\\b' + c + '\\b', 'g').test(n.className);
    5604     },
    5605 
    5606     renameElement : function(e, n, d) {
    5607         var ne, i, ar;
    5608 
    5609         d = typeof(d) == "undefined" ? tinyMCE.selectedInstance.getDoc() : d;
    5610 
    5611         if (e) {
    5612             ne = d.createElement(n);
    5613 
    5614             ar = e.attributes;
    5615             for (i=ar.length-1; i>-1; i--) {
    5616                 if (ar[i].specified && ar[i].nodeValue)
    5617                     ne.setAttribute(ar[i].nodeName.toLowerCase(), ar[i].nodeValue);
    5618             }
    5619 
    5620             ar = e.childNodes;
    5621             for (i=0; i<ar.length; i++)
    5622                 ne.appendChild(ar[i].cloneNode(true));
    5623 
    5624             e.parentNode.replaceChild(ne, e);
    5625         }
    5626     },
    5627 
    5628     getViewPort : function(w) {
    5629         var d = w.document, m = d.compatMode == 'CSS1Compat', b = d.body, de = d.documentElement;
    5630 
    5631         return {
    5632             left : w.pageXOffset || (m ? de.scrollLeft : b.scrollLeft),
    5633             top : w.pageYOffset || (m ? de.scrollTop : b.scrollTop),
    5634             width : w.innerWidth || (m ? de.clientWidth : b.clientWidth),
    5635             height : w.innerHeight || (m ? de.clientHeight : b.clientHeight)
    5636         };
    5637     },
    5638 
    5639     getStyle : function(n, na, d) {
    5640         if (!n)
    5641             return false;
    5642 
    5643         // Gecko
    5644         if (tinyMCE.isGecko && n.ownerDocument.defaultView) {
    5645             try {
    5646                 return n.ownerDocument.defaultView.getComputedStyle(n, null).getPropertyValue(na);
    5647             } catch (n) {
    5648                 // Old safari might fail
    5649                 return null;
    5650             }
    5651         }
    5652 
    5653         // Camelcase it, if needed
    5654         na = na.replace(/-(\D)/g, function(a, b){
    5655             return b.toUpperCase();
    5656         });
    5657 
    5658         // IE & Opera
    5659         if (n.currentStyle)
    5660             return n.currentStyle[na];
    5661 
    5662         return false;
    5663     }
    5664 
    5665     });
    5666 
    5667 /* file:jscripts/tiny_mce/classes/TinyMCE_URL.class.js */
    5668 
    5669 tinyMCE.add(TinyMCE_Engine, {
    5670     parseURL : function(url_str) {
    5671         var urlParts = [], i, pos, lastPos, chr;
    5672 
    5673         if (url_str) {
    5674             // Parse protocol part
    5675             pos = url_str.indexOf('://');
    5676             if (pos != -1) {
    5677                 urlParts.protocol = url_str.substring(0, pos);
    5678                 lastPos = pos + 3;
    5679             }
    5680 
    5681             // Find port or path start
    5682             for (i=lastPos; i<url_str.length; i++) {
    5683                 chr = url_str.charAt(i);
    5684 
    5685                 if (chr == ':')
    5686                     break;
    5687 
    5688                 if (chr == '/')
    5689                     break;
    5690             }
    5691             pos = i;
    5692 
    5693             // Get host
    5694             urlParts.host = url_str.substring(lastPos, pos);
    5695 
    5696             // Get port
    5697             urlParts.port = "";
    5698             lastPos = pos;
    5699             if (url_str.charAt(pos) == ':') {
    5700                 pos = url_str.indexOf('/', lastPos);
    5701                 urlParts.port = url_str.substring(lastPos+1, pos);
    5702             }
    5703 
    5704             // Get path
    5705             lastPos = pos;
    5706             pos = url_str.indexOf('?', lastPos);
    5707 
    5708             if (pos == -1)
    5709                 pos = url_str.indexOf('#', lastPos);
    5710 
    5711             if (pos == -1)
    5712                 pos = url_str.length;
    5713 
    5714             urlParts.path = url_str.substring(lastPos, pos);
    5715 
    5716             // Get query
    5717             lastPos = pos;
    5718             if (url_str.charAt(pos) == '?') {
    5719                 pos = url_str.indexOf('#');
    5720                 pos = (pos == -1) ? url_str.length : pos;
    5721                 urlParts.query = url_str.substring(lastPos+1, pos);
    5722             }
    5723 
    5724             // Get anchor
    5725             lastPos = pos;
    5726             if (url_str.charAt(pos) == '#') {
    5727                 pos = url_str.length;
    5728                 urlParts.anchor = url_str.substring(lastPos+1, pos);
    5729             }
    5730         }
    5731 
    5732         return urlParts;
    5733     },
    5734 
    5735     serializeURL : function(up) {
    5736         var o = "";
    5737 
    5738         if (up.protocol)
    5739             o += up.protocol + "://";
    5740 
    5741         if (up.host)
    5742             o += up.host;
    5743 
    5744         if (up.port)
    5745             o += ":" + up.port;
    5746 
    5747         if (up.path)
    5748             o += up.path;
    5749 
    5750         if (up.query)
    5751             o += "?" + up.query;
    5752 
    5753         if (up.anchor)
    5754             o += "#" + up.anchor;
    5755 
    5756         return o;
    5757     },
    5758 
    5759     convertAbsoluteURLToRelativeURL : function(base_url, url_to_relative) {
    5760         var baseURL = this.parseURL(base_url), targetURL = this.parseURL(url_to_relative);
    5761         var i, strTok1, strTok2, breakPoint = 0, outPath = "", forceSlash = false;
    5762         var fileName, pos;
    5763 
    5764         if (targetURL.path == '')
    5765             targetURL.path = "/";
    5766         else
    5767             forceSlash = true;
    5768 
    5769         // Crop away last path part
    5770         base_url = baseURL.path.substring(0, baseURL.path.lastIndexOf('/'));
    5771         strTok1 = base_url.split('/');
    5772         strTok2 = targetURL.path.split('/');
    5773 
    5774         if (strTok1.length >= strTok2.length) {
    5775             for (i=0; i<strTok1.length; i++) {
    5776                 if (i >= strTok2.length || strTok1[i] != strTok2[i]) {
    5777                     breakPoint = i + 1;
    5778                     break;
    5779                 }
    5780             }
    5781         }
    5782 
    5783         if (strTok1.length < strTok2.length) {
    5784             for (i=0; i<strTok2.length; i++) {
    5785                 if (i >= strTok1.length || strTok1[i] != strTok2[i]) {
    5786                     breakPoint = i + 1;
    5787                     break;
    5788                 }
    5789             }
    5790         }
    5791 
    5792         if (breakPoint == 1)
    5793             return targetURL.path;
    5794 
    5795         for (i=0; i<(strTok1.length-(breakPoint-1)); i++)
    5796             outPath += "../";
    5797 
    5798         for (i=breakPoint-1; i<strTok2.length; i++) {
    5799             if (i != (breakPoint-1))
    5800                 outPath += "/" + strTok2[i];
    5801             else
    5802                 outPath += strTok2[i];
    5803         }
    5804 
    5805         targetURL.protocol = null;
    5806         targetURL.host = null;
    5807         targetURL.port = null;
    5808         targetURL.path = outPath == '' && forceSlash ? "/" : outPath;
    5809 
    5810         // Remove document prefix from local anchors
    5811         fileName = baseURL.path;
    5812 
    5813         if ((pos = fileName.lastIndexOf('/')) != -1)
    5814             fileName = fileName.substring(pos + 1);
    5815 
    5816         // Is local anchor
    5817         if (fileName == targetURL.path && targetURL.anchor !== '')
    5818             targetURL.path = "";
    5819 
    5820         // If empty and not local anchor force filename or slash
    5821         if (targetURL.path == '' && !targetURL.anchor)
    5822             targetURL.path = fileName !== '' ? fileName : "/";
    5823 
    5824         return this.serializeURL(targetURL);
    5825     },
    5826 
    5827     convertRelativeToAbsoluteURL : function(base_url, relative_url) {
    5828         var baseURL = this.parseURL(base_url), baseURLParts, relURLParts, newRelURLParts, numBack, relURL = this.parseURL(relative_url), i;
    5829         var len, absPath, start, end, newBaseURLParts;
    5830 
    5831         if (relative_url == '' || relative_url.indexOf('://') != -1 || /^(mailto:|javascript:|#|\/)/.test(relative_url))
    5832             return relative_url;
    5833 
    5834         // Split parts
    5835         baseURLParts = baseURL.path.split('/');
    5836         relURLParts = relURL.path.split('/');
    5837 
    5838         // Remove empty chunks
    5839         newBaseURLParts = [];
    5840         for (i=baseURLParts.length-1; i>=0; i--) {
    5841             if (baseURLParts[i].length == 0)
    5842                 continue;
    5843 
    5844             newBaseURLParts[newBaseURLParts.length] = baseURLParts[i];
    5845         }
    5846         baseURLParts = newBaseURLParts.reverse();
    5847 
    5848         // Merge relURLParts chunks
    5849         newRelURLParts = [];
    5850         numBack = 0;
    5851         for (i=relURLParts.length-1; i>=0; i--) {
    5852             if (relURLParts[i].length == 0 || relURLParts[i] == ".")
    5853                 continue;
    5854 
    5855             if (relURLParts[i] == '..') {
    5856                 numBack++;
    5857                 continue;
    5858             }
    5859 
    5860             if (numBack > 0) {
    5861                 numBack--;
    5862                 continue;
    5863             }
    5864 
    5865             newRelURLParts[newRelURLParts.length] = relURLParts[i];
    5866         }
    5867 
    5868         relURLParts = newRelURLParts.reverse();
    5869 
    5870         // Remove end from absolute path
    5871         len = baseURLParts.length-numBack;
    5872         absPath = (len <= 0 ? "" : "/") + baseURLParts.slice(0, len).join('/') + "/" + relURLParts.join('/');
    5873         start = "";
    5874         end = "";
    5875 
    5876         // Build output URL
    5877         relURL.protocol = baseURL.protocol;
    5878         relURL.host = baseURL.host;
    5879         relURL.port = baseURL.port;
    5880 
    5881         // Re-add trailing slash if it's removed
    5882         if (relURL.path.charAt(relURL.path.length-1) == "/")
    5883             absPath += "/";
    5884 
    5885         relURL.path = absPath;
    5886 
    5887         return this.serializeURL(relURL);
    5888     },
    5889 
    5890     convertURL : function(url, node, on_save) {
    5891         var dl = document.location, start, portPart, urlParts, baseUrlParts, tmpUrlParts, curl;
    5892         var prot = dl.protocol, host = dl.hostname, port = dl.port;
    5893 
    5894         // Pass through file protocol
    5895         if (prot == "file:")
    5896             return url;
    5897 
    5898         // Something is wrong, remove weirdness
    5899         url = tinyMCE.regexpReplace(url, '(http|https):///', '/');
    5900 
    5901         // Mailto link or anchor (Pass through)
    5902         if (url.indexOf('mailto:') != -1 || url.indexOf('javascript:') != -1 || /^[ \t\r\n\+]*[#\?]/.test(url))
    5903             return url;
    5904 
    5905         // Fix relative/Mozilla
    5906         if (!tinyMCE.isIE && !on_save && url.indexOf("://") == -1 && url.charAt(0) != '/')
    5907             return tinyMCE.settings.base_href + url;
    5908 
    5909         // Handle relative URLs
    5910         if (on_save && tinyMCE.getParam('relative_urls')) {
    5911             curl = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, url);
    5912             if (curl.charAt(0) == '/')
    5913                 curl = tinyMCE.settings.document_base_prefix + curl;
    5914 
    5915             urlParts = tinyMCE.parseURL(curl);
    5916             tmpUrlParts = tinyMCE.parseURL(tinyMCE.settings.document_base_url);
    5917 
    5918             // Force relative
    5919             if (urlParts.host == tmpUrlParts.host && (urlParts.port == tmpUrlParts.port))
    5920                 return tinyMCE.convertAbsoluteURLToRelativeURL(tinyMCE.settings.document_base_url, curl);
    5921         }
    5922 
    5923         // Handle absolute URLs
    5924         if (!tinyMCE.getParam('relative_urls')) {
    5925             urlParts = tinyMCE.parseURL(url);
    5926             baseUrlParts = tinyMCE.parseURL(tinyMCE.settings.base_href);
    5927 
    5928             // Force absolute URLs from relative URLs
    5929             url = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, url);
    5930 
    5931             // If anchor and path is the same page
    5932             if (urlParts.anchor && urlParts.path == baseUrlParts.path)
    5933                 return "#" + urlParts.anchor;
    5934         }
    5935 
    5936         // Remove current domain
    5937         if (tinyMCE.getParam('remove_script_host')) {
    5938             start = "";
    5939             portPart = "";
    5940 
    5941             if (port !== '')
    5942                 portPart = ":" + port;
    5943 
    5944             start = prot + "//" + host + portPart + "/";
    5945 
    5946             if (url.indexOf(start) == 0)
    5947                 url = url.substring(start.length-1);
    5948         }
    5949 
    5950         return url;
    5951     },
    5952 
    5953     convertAllRelativeURLs : function(body) {
    5954         var i, elms, src, href, mhref, msrc;
    5955 
    5956         // Convert all image URL:s to absolute URL
    5957         elms = body.getElementsByTagName("img");
    5958         for (i=0; i<elms.length; i++) {
    5959             src = tinyMCE.getAttrib(elms[i], 'src');
    5960 
    5961             msrc = tinyMCE.getAttrib(elms[i], 'mce_src');
    5962             if (msrc !== '')
    5963                 src = msrc;
    5964 
    5965             if (src !== '') {
    5966                 src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, src);
    5967                 elms[i].setAttribute("src", src);
    5968             }
    5969         }
    5970 
    5971         // Convert all link URL:s to absolute URL
    5972         elms = body.getElementsByTagName("a");
    5973         for (i=0; i<elms.length; i++) {
    5974             href = tinyMCE.getAttrib(elms[i], 'href');
    5975 
    5976             mhref = tinyMCE.getAttrib(elms[i], 'mce_href');
    5977             if (mhref !== '')
    5978                 href = mhref;
    5979 
    5980             if (href && href !== '') {
    5981                 href = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, href);
    5982                 elms[i].setAttribute("href", href);
    5983             }
    5984         }
    5985     }
    5986 
    5987     });
    5988 
    5989 /* file:jscripts/tiny_mce/classes/TinyMCE_Array.class.js */
    5990 
    5991 tinyMCE.add(TinyMCE_Engine, {
    5992     clearArray : function(a) {
    5993         var n;
    5994 
    5995         for (n in a)
    5996             a[n] = null;
    5997 
    5998         return a;
    5999     },
    6000 
    6001     explode : function(d, s) {
    6002         var ar = s.split(d), oar = [], i;
    6003 
    6004         for (i = 0; i<ar.length; i++) {
    6005             if (ar[i] !== '')
    6006                 oar[oar.length] = ar[i];
    6007         }
    6008 
    6009         return oar;
    6010     }
    6011 });
    6012 
    6013 /* file:jscripts/tiny_mce/classes/TinyMCE_Event.class.js */
    6014 
    6015 tinyMCE.add(TinyMCE_Engine, {
    6016     _setEventsEnabled : function(node, state) {
    6017         var evs, x, y, elms, i, event;
    6018         var events = ['onfocus','onblur','onclick','ondblclick',
    6019                     'onmousedown','onmouseup','onmouseover','onmousemove',
    6020                     'onmouseout','onkeypress','onkeydown','onkeydown','onkeyup'];
    6021 
    6022         evs = tinyMCE.settings.event_elements.split(',');
    6023         for (y=0; y<evs.length; y++){
    6024             elms = node.getElementsByTagName(evs[y]);
    6025             for (i=0; i<elms.length; i++) {
    6026                 event = "";
    6027 
    6028                 for (x=0; x<events.length; x++) {
    6029                     if ((event = tinyMCE.getAttrib(elms[i], events[x])) !== '') {
    6030                         event = tinyMCE.cleanupEventStr("" + event);
    6031 
    6032                         if (!state)
    6033                             event = "return true;" + event;
    6034                         else
    6035                             event = event.replace(/^return true;/gi, '');
    6036 
    6037                         elms[i].removeAttribute(events[x]);
    6038                         elms[i].setAttribute(events[x], event);
    6039                     }
    6040                 }
    6041             }
    6042         }
    6043     },
    6044 
    6045     _eventPatch : function(editor_id) {
    6046         var n, inst, win, e;
    6047 
    6048         // Remove odd, error
    6049         if (typeof(tinyMCE) == "undefined")
    6050             return true;
    6051 
    6052         try {
    6053             // Try selected instance first
    6054             if (tinyMCE.selectedInstance) {
    6055                 win = tinyMCE.selectedInstance.getWin();
    6056 
    6057                 if (win && win.event) {
    6058                     e = win.event;
    6059 
    6060                     if (!e.target)
    6061                         e.target = e.srcElement;
    6062 
    6063                     TinyMCE_Engine.prototype.handleEvent(e);
    6064                     return;
    6065                 }
    6066             }
    6067 
    6068             // Search for it
    6069             for (n in tinyMCE.instances) {
    6070                 inst = tinyMCE.instances[n];
    6071 
    6072                 if (!tinyMCE.isInstance(inst))
    6073                     continue;
    6074 
    6075                 inst.select();
    6076                 win = inst.getWin();
    6077 
    6078                 if (win && win.event) {
    6079                     e = win.event;
    6080 
    6081                     if (!e.target)
    6082                         e.target = e.srcElement;
    6083 
    6084                     TinyMCE_Engine.prototype.handleEvent(e);
    6085                     return;
    6086                 }
    6087             }
    6088         } catch (ex) {
    6089             // Ignore error if iframe is pointing to external URL
    6090         }
    6091     },
    6092 
    6093     findEvent : function(e) {
    6094         var n, inst;
    6095 
    6096         if (e)
     1028        },
     1029
     1030        get : function(e) {
     1031            if (typeof(e) == 'string')
     1032                return this.doc.getElementById(e);
     1033
    60971034            return e;
    6098 
    6099         for (n in tinyMCE.instances) {
    6100             inst = tinyMCE.instances[n];
    6101 
    6102             if (tinyMCE.isInstance(inst) && inst.getWin().event)
    6103                 return inst.getWin().event;
    6104         }
    6105 
    6106         return null;
    6107     },
    6108 
    6109     unloadHandler : function() {
    6110         tinyMCE.triggerSave(true, true);
    6111     },
    6112 
    6113     addEventHandlers : function(inst) {
    6114         this.setEventHandlers(inst, 1);
    6115     },
    6116 
    6117     setEventHandlers : function(inst, s) {
    6118         var doc = inst.getDoc(), ie, ot, i, f = s ? tinyMCE.addEvent : tinyMCE.removeEvent;
    6119 
    6120         ie = ['keypress', 'keyup', 'keydown', 'click', 'mouseup', 'mousedown', 'controlselect', 'dblclick'];
    6121         ot = ['keypress', 'keyup', 'keydown', 'click', 'mouseup', 'mousedown', 'focus', 'blur', 'dragdrop'];
    6122 
    6123         inst.switchSettings();
    6124 
    6125         if (tinyMCE.isIE) {
    6126             for (i=0; i<ie.length; i++)
    6127                 f(doc, ie[i], TinyMCE_Engine.prototype._eventPatch);
    6128         } else {
    6129             for (i=0; i<ot.length; i++)
    6130                 f(doc, ot[i], tinyMCE.handleEvent);
    6131 
    6132             // Force designmode
    6133             try {
    6134                 doc.designMode = "On";
    6135             } catch (e) {
    6136                 // Ignore
    6137             }
    6138         }
    6139     },
    6140 
    6141     onMouseMove : function() {
    6142         var inst, lh;
    6143 
    6144         // Fix for IE7 bug where it's not restoring hover on anchors correctly
    6145         if (tinyMCE.lastHover) {
    6146             lh = tinyMCE.lastHover;
    6147 
    6148             // Call out on menus and refresh class on normal buttons
    6149             if (lh.className.indexOf('mceMenu') != -1)
    6150                 tinyMCE._menuButtonEvent('out', lh);
    6151             else
    6152                 lh.className = lh.className;
    6153 
    6154             tinyMCE.lastHover = null;
    6155         }
    6156 
    6157         if (!tinyMCE.hasMouseMoved) {
    6158             inst = tinyMCE.selectedInstance;
    6159 
    6160             // Workaround for bug #1437457 (Odd MSIE bug)
    6161             if (inst.isFocused) {
    6162                 inst.undoBookmark = inst.selection.getBookmark();
    6163                 tinyMCE.hasMouseMoved = true;
    6164             }
    6165         }
    6166 
    6167     //  tinyMCE.cancelEvent(inst.getWin().event);
    6168     //  return false;
    6169     },
    6170 
    6171     cancelEvent : function(e) {
    6172         if (!e)
    6173             return false;
    6174 
    6175         if (tinyMCE.isIE) {
    6176             e.returnValue = false;
    6177             e.cancelBubble = true;
    6178         } else {
    6179             e.preventDefault();
    6180             e.stopPropagation && e.stopPropagation();
    6181         }
    6182 
    6183         return false;
    6184     },
    6185 
    6186     addEvent : function(o, n, h) {
    6187         // Add cleanup for all non unload events
    6188         if (n != 'unload') {
    6189             function clean() {
    6190                 var ex;
    6191 
    6192                 try {
    6193                     tinyMCE.removeEvent(o, n, h);
    6194                     tinyMCE.removeEvent(window, 'unload', clean);
    6195                     o = n = h = null;
    6196                 } catch (ex) {
    6197                     // IE may produce access denied exception on unload
    6198                 }
    6199             }
    6200 
    6201             // Add memory cleaner
    6202             tinyMCE.addEvent(window, 'unload', clean);
    6203         }
    6204 
    6205         if (o.attachEvent)
    6206             o.attachEvent("on" + n, h);
    6207         else
    6208             o.addEventListener(n, h, false);
    6209     },
    6210 
    6211     removeEvent : function(o, n, h) {
    6212         if (o.detachEvent)
    6213             o.detachEvent("on" + n, h);
    6214         else
    6215             o.removeEventListener(n, h, false);
    6216     },
    6217 
    6218     addSelectAccessibility : function(e, s, w) {
    6219         // Add event handlers
    6220         if (!s._isAccessible) {
    6221             s.onkeydown = tinyMCE.accessibleEventHandler;
    6222             s.onblur = tinyMCE.accessibleEventHandler;
    6223             s._isAccessible = true;
    6224             s._win = w;
    6225         }
    6226 
    6227         return false;
    6228     },
    6229 
    6230     accessibleEventHandler : function(e) {
    6231         var elm, win = this._win;
    6232 
    6233         e = tinyMCE.isIE ? win.event : e;
    6234         elm = tinyMCE.isIE ? e.srcElement : e.target;
    6235 
    6236         // Unpiggyback onchange on blur
    6237         if (e.type == "blur") {
    6238             if (elm.oldonchange) {
    6239                 elm.onchange = elm.oldonchange;
    6240                 elm.oldonchange = null;
    6241             }
    6242 
    6243             return true;
    6244         }
    6245 
    6246         // Piggyback onchange
    6247         if (elm.nodeName == "SELECT" && !elm.oldonchange) {
    6248             elm.oldonchange = elm.onchange;
    6249             elm.onchange = null;
    6250         }
    6251 
    6252         // Execute onchange and remove piggyback
    6253         if (e.keyCode == 13 || e.keyCode == 32) {
    6254             elm.onchange = elm.oldonchange;
    6255             elm.onchange();
    6256             elm.oldonchange = null;
    6257 
    6258             tinyMCE.cancelEvent(e);
    6259             return false;
    6260         }
    6261 
    6262         return true;
    6263     },
    6264 
    6265     _resetIframeHeight : function() {
    6266         var ife;
    6267 
    6268         if (tinyMCE.isRealIE) {
    6269             ife = tinyMCE.selectedInstance.iframeElement;
    6270 
    6271     /*      if (ife._oldWidth) {
    6272                 ife.style.width = ife._oldWidth;
    6273                 ife.width = ife._oldWidth;
    6274             }*/
    6275 
    6276             if (ife._oldHeight) {
    6277                 ife.style.height = ife._oldHeight;
    6278                 ife.height = ife._oldHeight;
    6279             }
    6280         }
    6281     }
    6282 
    6283     });
    6284 
    6285 /* file:jscripts/tiny_mce/classes/TinyMCE_Selection.class.js */
    6286 
    6287 function TinyMCE_Selection(inst) {
    6288     this.instance = inst;
    6289 };
    6290 
    6291 TinyMCE_Selection.prototype = {
    6292     getSelectedHTML : function() {
    6293         var inst = this.instance, e, r = this.getRng(), h;
    6294 
    6295         if (!r)
    6296             return null;
    6297 
    6298         e = document.createElement("body");
    6299 
    6300         if (r.cloneContents)
    6301             e.appendChild(r.cloneContents());
    6302         else if (typeof(r.item) != 'undefined' || typeof(r.htmlText) != 'undefined')
    6303             e.innerHTML = r.item ? r.item(0).outerHTML : r.htmlText;
    6304         else
    6305             e.innerHTML = r.toString(); // Failed, use text for now
    6306 
    6307         h = tinyMCE._cleanupHTML(inst, inst.contentDocument, inst.settings, e, e, false, true, false);
    6308 
    6309         // When editing always use fonts internaly
    6310         //if (tinyMCE.getParam("convert_fonts_to_spans"))
    6311         //  tinyMCE.convertSpansToFonts(inst.getDoc());
    6312 
    6313         return h;
    6314     },
    6315 
    6316     getSelectedText : function() {
    6317         var inst = this.instance, d, r, s, t;
    6318 
    6319         if (tinyMCE.isIE) {
    6320             d = inst.getDoc();
    6321 
    6322             if (d.selection.type == "Text") {
    6323                 r = d.selection.createRange();
    6324                 t = r.text;
    6325             } else
    6326                 t = '';
    6327         } else {
    6328             s = this.getSel();
    6329 
    6330             if (s && s.toString)
    6331                 t = s.toString();
    6332             else
    6333                 t = '';
    6334         }
    6335 
    6336         return t;
    6337     },
    6338 
    6339     getBookmark : function(simple) {
    6340         var inst = this.instance, rng = this.getRng(), doc = inst.getDoc(), b = inst.getBody();
    6341         var trng, sx, sy, xx = -999999999, vp = inst.getViewPort();
    6342         var sp, le, s, e, nl, i, si, ei, w;
    6343 
    6344         sx = vp.left;
    6345         sy = vp.top;
    6346 
    6347         if (simple)
    6348             return {rng : rng, scrollX : sx, scrollY : sy};
    6349 
    6350         if (tinyMCE.isRealIE) {
    6351             if (rng.item) {
    6352                 e = rng.item(0);
    6353 
    6354                 nl = b.getElementsByTagName(e.nodeName);
    6355                 for (i=0; i<nl.length; i++) {
    6356                     if (e == nl[i]) {
    6357                         sp = i;
    6358                         break;
    6359                     }
    6360                 }
    6361 
    6362                 return {
    6363                     tag : e.nodeName,
    6364                     index : sp,
    6365                     scrollX : sx,
    6366                     scrollY : sy
     1035        },
     1036
     1037        // #if !jquery
     1038
     1039        select : function(pa, s) {
     1040            var t = this, cs, c, pl, o = [], x, i, l, n;
     1041
     1042            s = t.get(s) || t.doc;
     1043
     1044            if (t.settings.strict) {
     1045                function get(s, n) {
     1046                    return s.getElementsByTagName(n.toLowerCase());
    63671047                };
    63681048            } else {
    6369                 trng = doc.body.createTextRange();
    6370                 trng.moveToElementText(inst.getBody());
    6371                 trng.collapse(true);
    6372                 bp = Math.abs(trng.move('character', xx));
    6373 
    6374                 trng = rng.duplicate();
    6375                 trng.collapse(true);
    6376                 sp = Math.abs(trng.move('character', xx));
    6377 
    6378                 trng = rng.duplicate();
    6379                 trng.collapse(false);
    6380                 le = Math.abs(trng.move('character', xx)) - sp;
     1049                function get(s, n) {
     1050                    return s.getElementsByTagName(n);
     1051                };
     1052            }
     1053
     1054            // Simple element pattern. For example: "p" or "*"
     1055            if (t.elmPattern.test(pa)) {
     1056                x = get(s, pa);
     1057
     1058                for (i = 0, l = x.length; i<l; i++)
     1059                    o.push(x[i]);
     1060
     1061                return o;
     1062            }
     1063
     1064            // Simple class pattern. For example: "p.class" or ".class"
     1065            if (t.elmClassPattern.test(pa)) {
     1066                pl = t.elmClassPattern.exec(pa);
     1067                x = get(s, pl[1] || '*');
     1068                c = ' ' + pl[2] + ' ';
     1069
     1070                for (i = 0, l = x.length; i<l; i++) {
     1071                    n = x[i];
     1072
     1073                    if (n.className && (' ' + n.className + ' ').indexOf(c) !== -1)
     1074                        o.push(n);
     1075                }
     1076
     1077                return o;
     1078            }
     1079
     1080            function collect(n) {
     1081                if (!n.mce_save) {
     1082                    n.mce_save = 1;
     1083                    o.push(n);
     1084                }
     1085            };
     1086
     1087            function collectIE(n) {
     1088                if (!n.getAttribute('mce_save')) {
     1089                    n.setAttribute('mce_save', '1');
     1090                    o.push(n);
     1091                }
     1092            };
     1093
     1094            function find(n, f, r) {
     1095                var i, l, nl = get(r, n);
     1096
     1097                for (i = 0, l = nl.length; i < l; i++)
     1098                    f(nl[i]);
     1099            };
     1100
     1101            each(pa.split(','), function(v, i) {
     1102                v = tinymce.trim(v);
     1103
     1104                // Simple element pattern, most common in TinyMCE
     1105                if (t.elmPattern.test(v)) {
     1106                    each(get(s, v), function(n) {
     1107                        collect(n);
     1108                    });
     1109
     1110                    return;
     1111                }
     1112
     1113                // Simple element pattern with class, fairly common in TinyMCE
     1114                if (t.elmClassPattern.test(v)) {
     1115                    x = t.elmClassPattern.exec(v);
     1116
     1117                    each(get(s, x[1]), function(n) {
     1118                        if (t.hasClass(n, x[2]))
     1119                            collect(n);
     1120                    });
     1121
     1122                    return;
     1123                }
     1124
     1125                if (!(cs = t.cache[pa])) {
     1126                    cs = 'x=(function(cf, s) {';
     1127                    pl = v.split(' ');
     1128
     1129                    each(pl, function(v) {
     1130                        var p = /^([\w\\*]+)?(?:#([\w\\]+))?(?:\.([\w\\\.]+))?(?:\[\@([\w\\]+)([\^\$\*!]?=)([\w\\]+)\])?(?:\:([\w\\]+))?/i.exec(v);
     1131
     1132                        // Find elements
     1133                        p[1] = p[1] || '*';
     1134                        cs += 'find("' + p[1] + '", function(n) {';
     1135
     1136                        // Check id
     1137                        if (p[2])
     1138                            cs += 'if (n.id !== "' + p[2] + '") return;';
     1139
     1140                        // Check classes
     1141                        if (p[3]) {
     1142                            cs += 'var c = " " + n.className + " ";';
     1143                            cs += 'if (';
     1144                            c = '';
     1145                            each(p[3].split('.'), function(v) {
     1146                                if (v)
     1147                                    c += (c ? '||' : '') + 'c.indexOf(" ' + v + ' ") === -1';
     1148                            });
     1149                            cs += c + ') return;';
     1150                        }
     1151                    });
     1152
     1153                    cs += 'cf(n);';
     1154
     1155                    for (i = pl.length - 1; i >= 0; i--)
     1156                        cs += '}, ' + (i ? 'n' : 's') + ');';
     1157
     1158                    cs += '})';
     1159
     1160                    // Compile CSS pattern function
     1161                    t.cache[pa] = cs = eval(cs);
     1162                }
     1163
     1164                // Run selector function
     1165                cs(isIE ? collectIE : collect, s);
     1166            });
     1167
     1168            // Cleanup
     1169            each(o, function(n) {
     1170                if (isIE)
     1171                    n.removeAttribute('mce_save');
     1172                else
     1173                    delete n.mce_save;
     1174            });
     1175
     1176            return o;
     1177        },
     1178
     1179        // #endif
     1180
     1181        add : function(p, n, a, h, c) {
     1182            var t = this;
     1183
     1184            return this.run(p, function(p) {
     1185                var e, k;
     1186
     1187                e = is(n, 'string') ? t.doc.createElement(n) : n;
     1188
     1189                if (a) {
     1190                    for (k in a) {
     1191                        if (a.hasOwnProperty(k) && !is(a[k], 'object'))
     1192                            t.setAttrib(e, k, '' + a[k]);
     1193                    }
     1194
     1195                    if (a.style && !is(a.style, 'string')) {
     1196                        each(a.style, function(v, n) {
     1197                            t.setStyle(e, n, v);
     1198                        });
     1199                    }
     1200                }
     1201
     1202                if (h) {
     1203                    if (h.nodeType)
     1204                        e.appendChild(h);
     1205                    else
     1206                        e.innerHTML = h;
     1207                }
     1208
     1209                return !c ? p.appendChild(e) : e;
     1210            });
     1211        },
     1212
     1213        create : function(n, a, h) {
     1214            return this.add(this.doc.createElement(n), n, a, h, 1);
     1215        },
     1216
     1217        createHTML : function(n, a, h) {
     1218            var o = '', t = this, k;
     1219
     1220            o += '<' + n;
     1221
     1222            for (k in a) {
     1223                if (a.hasOwnProperty(k))
     1224                    o += ' ' + k + '="' + t.encode(a[k]) + '"';
     1225            }
     1226
     1227            if (tinymce.is(h))
     1228                return o + '>' + h + '</' + n + '>';
     1229
     1230            return o + ' />';
     1231        },
     1232
     1233        remove : function(n, k) {
     1234            return this.run(n, function(n) {
     1235                var p;
     1236
     1237                p = n.parentNode;
     1238
     1239                if (!p)
     1240                    return null;
     1241
     1242                if (k) {
     1243                    each (n.childNodes, function(c) {
     1244                        p.insertBefore(c.cloneNode(true), n);
     1245                    });
     1246                }
     1247
     1248                return p.removeChild(n);
     1249            });
     1250        },
     1251
     1252        // #if !jquery
     1253
     1254        setStyle : function(n, na, v) {
     1255            var t = this;
     1256
     1257            return t.run(n, function(e) {
     1258                var s, i;
     1259
     1260                s = e.style;
     1261
     1262                // Camelcase it, if needed
     1263                na = na.replace(/-(\D)/g, function(a, b){
     1264                    return b.toUpperCase();
     1265                });
     1266
     1267                // Default px suffix on these
     1268                if (t.pixelStyles.test(na) && (tinymce.is(v, 'number') || /^[\-0-9\.]+$/.test(v)))
     1269                    v += 'px';
     1270
     1271                switch (na) {
     1272                    case 'opacity':
     1273                        // IE specific opacity
     1274                        if (isIE) {
     1275                            s.filter = v === '' ? '' : "alpha(opacity=" + (v * 100) + ")";
     1276
     1277                            if (!n.currentStyle || !n.currentStyle.hasLayout)
     1278                                s.display = 'inline-block';
     1279                        }
     1280
     1281                        // Fix for older browsers
     1282                        s['-moz-opacity'] = s['-khtml-opacity'] = v;
     1283                        break;
     1284
     1285                    case 'float':
     1286                        isIE ? s.styleFloat = v : s.cssFloat = v;
     1287                        break;
     1288                }
     1289
     1290                s[na] = v || '';
     1291
     1292                // Force update of the style data
     1293                if (t.settings.update_styles)
     1294                    t.setAttrib(e, 'mce_style');
     1295            });
     1296        },
     1297
     1298        getStyle : function(n, na, c) {
     1299            n = this.get(n);
     1300
     1301            if (!n)
     1302                return false;
     1303
     1304            // Gecko
     1305            if (this.doc.defaultView && c) {
     1306                // Remove camelcase
     1307                na = na.replace(/[A-Z]/g, function(a){
     1308                    return '-' + a;
     1309                });
     1310
     1311                try {
     1312                    return this.doc.defaultView.getComputedStyle(n, null).getPropertyValue(na);
     1313                } catch (ex) {
     1314                    // Old safari might fail
     1315                    return null;
     1316                }
     1317            }
     1318
     1319            // Camelcase it, if needed
     1320            na = na.replace(/-(\D)/g, function(a, b){
     1321                return b.toUpperCase();
     1322            });
     1323
     1324            if (na == 'float')
     1325                na = isIE ? 'styleFloat' : 'cssFloat';
     1326
     1327            // IE & Opera
     1328            if (n.currentStyle && c)
     1329                return n.currentStyle[na];
     1330
     1331            return n.style[na];
     1332        },
     1333
     1334        setStyles : function(e, o) {
     1335            var t = this, s = t.settings, ol;
     1336
     1337            ol = s.update_styles;
     1338            s.update_styles = 0;
     1339
     1340            each(o, function(v, n) {
     1341                t.setStyle(e, n, v);
     1342            });
     1343
     1344            // Update style info
     1345            s.update_styles = ol;
     1346            if (s.update_styles)
     1347                t.setAttrib(e, s.cssText);
     1348        },
     1349
     1350        setAttrib : function(e, n, v) {
     1351            var t = this;
     1352
     1353            // Strict XML mode
     1354            if (t.settings.strict)
     1355                n = n.toLowerCase();
     1356
     1357            return this.run(e, function(e) {
     1358                var s = t.settings;
     1359
     1360                switch (n) {
     1361                    case "style":
     1362                        if (s.keep_values) {
     1363                            if (v)
     1364                                e.setAttribute('mce_style', v, 2);
     1365                            else
     1366                                e.removeAttribute('mce_style', 2);
     1367                        }
     1368
     1369                        e.style.cssText = v;
     1370                        break;
     1371
     1372                    case "class":
     1373                        e.className = v;
     1374                        break;
     1375
     1376                    case "src":
     1377                    case "href":
     1378                        if (s.keep_values) {
     1379                            if (s.url_converter)
     1380                                v = s.url_converter.call(s.url_converter_scope || t, v, n, e);
     1381
     1382                            t.setAttrib(e, 'mce_' + n, v, 2);
     1383                        }
     1384
     1385                        break;
     1386                }
     1387
     1388                if (is(v) && v !== null && v.length !== 0)
     1389                    e.setAttribute(n, '' + v, 2);
     1390                else
     1391                    e.removeAttribute(n, 2);
     1392            });
     1393        },
     1394
     1395        setAttribs : function(e, o) {
     1396            var t = this;
     1397
     1398            return this.run(e, function(e) {
     1399                each(o, function(v, n) {
     1400                    t.setAttrib(e, n, v);
     1401                });
     1402            });
     1403        },
     1404
     1405        // #endif
     1406
     1407        getAttrib : function(e, n, dv) {
     1408            var v, t = this;
     1409
     1410            e = t.get(e);
     1411
     1412            if (!e)
     1413                return false;
     1414
     1415            if (!is(dv))
     1416                dv = "";
     1417
     1418            // Try the mce variant for these
     1419            if (/^(src|href|style)$/.test(n)) {
     1420                v = e.getAttribute("mce_" + n);
     1421
     1422                if (v)
     1423                    return v;
     1424            }
     1425
     1426            v = e.getAttribute(n, 2);
     1427
     1428            if (!v) {
     1429                switch (n) {
     1430                    case 'class':
     1431                        v = e.className;
     1432                        break;
     1433
     1434                    default:
     1435                        v = e.attributes[n];
     1436                        v = v && is(v.nodeValue) ? v.nodeValue : v;
     1437                }
     1438            }
     1439
     1440            switch (n) {
     1441                case 'style':
     1442                    v = v || e.style.cssText;
     1443
     1444                    if (v) {
     1445                        v = t.serializeStyle(t.parseStyle(v));
     1446
     1447                        if (t.settings.keep_values)
     1448                            e.setAttribute('mce_style', v);
     1449                    }
     1450
     1451                    break;
     1452            }
     1453
     1454            // Remove Apple and WebKit stuff
     1455            if (isWebKit && n === "class" && v)
     1456                v = v.replace(/(apple|webkit)\-[a-z\-]+/gi, '');
     1457
     1458            // Handle IE issues
     1459            if (isIE) {
     1460                switch (n) {
     1461                    case 'rowspan':
     1462                    case 'colspan':
     1463                        // IE returns 1 as default value
     1464                        if (v === 1)
     1465                            v = '';
     1466
     1467                        break;
     1468
     1469                    case 'size':
     1470                        // IE returns +0 as default value for size
     1471                        if (v === '+0')
     1472                            v = '';
     1473
     1474                        break;
     1475
     1476                    case 'hspace':
     1477                        // IE returns -1 as default value
     1478                        if (v === -1)
     1479                            v = '';
     1480
     1481                        break;
     1482
     1483                    case 'tabindex':
     1484                        // IE returns 32768 as default value
     1485                        if (v === 32768)
     1486                            v = '';
     1487
     1488                        break;
     1489
     1490                    default:
     1491                        // IE has odd anonymous function for event attributes
     1492                        if (n.indexOf('on') === 0 && v)
     1493                            v = ('' + v).replace(/^function\s+anonymous\(\)\s+\{\s+(.*)\s+\}$/, '$1');
     1494                }
     1495            }
     1496
     1497            return (v && v != '') ? '' + v : dv;
     1498        },
     1499
     1500        getPos : function(n) {
     1501            var t = this, x = 0, y = 0, e, d = t.doc;
     1502
     1503            n = t.get(n);
     1504
     1505            // Use getBoundingClientRect on IE, Opera has it but it's not perfect
     1506            if (n && isIE) {
     1507                n = n.getBoundingClientRect();
     1508                e = t.boxModel ? d.documentElement : d.body;
     1509                x = t.getStyle(t.select('html')[0], 'borderWidth'); // Remove border
     1510                x = (x == 'medium' || t.boxModel && !t.isIE6) && 2 || x;
     1511                n.top += window.self != window.top ? 2 : 0; // IE adds some strange extra cord if used in a frameset
     1512
     1513                return {x : n.left + e.scrollLeft - x, y : n.top + e.scrollTop - x};
     1514            }
     1515
     1516            while (n) {
     1517                x += n.offsetLeft || 0;
     1518                y += n.offsetTop || 0;
     1519                x -= n.scrollLeft || 0;
     1520                y -= n.scrollTop || 0;
     1521                n = n.offsetParent;
     1522            }
     1523
     1524            return {x : x, y : y};
     1525        },
     1526
     1527        parseStyle : function(st) {
     1528            var t = this, s = t.settings, o = {};
     1529
     1530            if (!st)
     1531                return o;
     1532
     1533            function compress(p, s, ot) {
     1534                var t, r, b, l;
     1535
     1536                // Get values and check it it needs compressing
     1537                t = o[p + '-top' + s];
     1538                if (!t)
     1539                    return;
     1540
     1541                r = o[p + '-right' + s];
     1542                if (t != r)
     1543                    return;
     1544
     1545                b = o[p + '-bottom' + s];
     1546                if (r != b)
     1547                    return;
     1548
     1549                l = o[p + '-left' + s];
     1550                if (b != l)
     1551                    return;
     1552
     1553                // Compress
     1554                o[ot] = l;
     1555                delete o[p + '-top' + s];
     1556                delete o[p + '-right' + s];
     1557                delete o[p + '-bottom' + s];
     1558                delete o[p + '-left' + s];
     1559            };
     1560
     1561            function compress2(ta, a, b, c) {
     1562                var t;
     1563
     1564                t = o[a];
     1565                if (!t)
     1566                    return;
     1567
     1568                t = o[b];
     1569                if (!t)
     1570                    return;
     1571
     1572                t = o[c];
     1573                if (!t)
     1574                    return;
     1575
     1576                // Compress
     1577                o[ta] = o[a] + ' ' + o[b] + ' ' + o[c];
     1578                delete o[a];
     1579                delete o[b];
     1580                delete o[c];
     1581            };
     1582
     1583            each(st.split(';'), function(v) {
     1584                var sv, ur = [];
     1585
     1586                if (v) {
     1587                    v = v.replace(/url\([^\)]+\)/g, function(v) {ur.push(v);return 'url(' + ur.length + ')';});
     1588                    v = v.split(':');
     1589                    sv = tinymce.trim(v[1]);
     1590                    sv = sv.replace(/url\(([^\)]+)\)/g, function(a, b) {return ur[parseInt(b) - 1];});
     1591
     1592                    sv = sv.replace(/rgb\([^\)]+\)/g, function(v) {
     1593                        return t.toHex(v);
     1594                    });
     1595
     1596                    if (s.url_converter) {
     1597                        sv = sv.replace(/url\([\'\"]?([^\)\'\"]+)[\'\"]?\)/g, function(x, c) {
     1598                            return 'url(' + t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), 'style', null)) + ')';
     1599                        });
     1600                    }
     1601
     1602                    o[tinymce.trim(v[0]).toLowerCase()] = sv;
     1603                }
     1604            });
     1605
     1606            compress("border", "", "border");
     1607            compress("border", "-width", "border-width");
     1608            compress("border", "-color", "border-color");
     1609            compress("border", "-style", "border-style");
     1610            compress("padding", "", "padding");
     1611            compress("margin", "", "margin");
     1612            compress2('border', 'border-width', 'border-style', 'border-color');
     1613
     1614            return o;
     1615        },
     1616
     1617        serializeStyle : function(o) {
     1618            var s = '';
     1619
     1620            each(o, function(v, k) {
     1621                if (k && v) {
     1622                    switch (k) {
     1623                        case 'color':
     1624                        case 'background-color':
     1625                            v = v.toLowerCase();
     1626                            break;
     1627                    }
     1628
     1629                    s += (s ? ' ' : '') + k + ': ' + v + ';';
     1630                }
     1631            });
     1632
     1633            return s;
     1634        },
     1635
     1636        loadCSS : function(u) {
     1637            var t = this, d = this.doc;
     1638
     1639            if (!u)
     1640                u = '';
     1641
     1642            each(u.split(','), function(u) {
     1643                if (t.files[u])
     1644                    return;
     1645
     1646                t.files[u] = true;
     1647
     1648                if (!d.createStyleSheet)
     1649                    t.add(t.select('head')[0], 'link', {rel : 'stylesheet', href : u});
     1650                else
     1651                    d.createStyleSheet(u);
     1652            });
     1653        },
     1654
     1655        // #if !jquery
     1656
     1657        addClass : function(e, c) {
     1658            return this.run(e, function(e) {
     1659                var o;
     1660
     1661                if (!c)
     1662                    return 0;
     1663
     1664                if (this.hasClass(e, c))
     1665                    return e.className;
     1666
     1667                o = this.removeClass(e, c);
     1668
     1669                return e.className = (o != '' ? (o + ' ') : '') + c;
     1670            });
     1671        },
     1672
     1673        removeClass : function(e, c) {
     1674            var t = this, re;
     1675
     1676            return t.run(e, function(e) {
     1677                var v;
     1678
     1679                if (t.hasClass(e, c)) {
     1680                    if (!re)
     1681                        re = new RegExp("(^|\\s+)" + c + "(\\s+|$)", "g");
     1682
     1683                    v = e.className.replace(re, ' ');
     1684
     1685                    return e.className = tinymce.trim(v != ' ' ? v : '');
     1686                }
     1687
     1688                return e.className;
     1689            });
     1690        },
     1691
     1692        hasClass : function(n, c) {
     1693            n = this.get(n);
     1694
     1695            if (!n || !c)
     1696                return false;
     1697
     1698            return (' ' + n.className + ' ').indexOf(' ' + c + ' ') !== -1;
     1699        },
     1700
     1701        show : function(e) {
     1702            return this.setStyle(e, 'display', 'block');
     1703        },
     1704
     1705        hide : function(e) {
     1706            return this.setStyle(e, 'display', 'none');
     1707        },
     1708
     1709        isHidden : function(e) {
     1710            e = this.get(e);
     1711
     1712            return e.style.display == 'none' || this.getStyle(e, 'display') == 'none';
     1713        },
     1714
     1715        // #endif
     1716
     1717        uniqueId : function(p) {
     1718            return (!p ? 'mce_' : p) + (this.counter++);
     1719        },
     1720
     1721        setHTML : function(e, h) {
     1722            var t = this;
     1723
     1724            return this.run(e, function(e) {
     1725                var r;
     1726
     1727                h = t.processHTML(h);
     1728
     1729                if (isIE) {
     1730                    e.innerHTML = '<br />' + h;
     1731                    e.removeChild(e.firstChild);
     1732                } else
     1733                    e.innerHTML = h;
     1734
     1735                return h;
     1736            });
     1737        },
     1738
     1739        processHTML : function(h) {
     1740            var t = this, s = t.settings;
     1741
     1742            // Convert strong and em to b and i in FF since it can't handle them
     1743            if (tinymce.isGecko) {
     1744                h = h.replace(/<(\/?)strong>|<strong( [^>]+)>/gi, '<$1b$2>');
     1745                h = h.replace(/<(\/?)em>|<em( [^>]+)>/gi, '<$1i$2>');
     1746            }
     1747
     1748            // Fix some issues
     1749            h = h.replace(/<(a)([^>]*)\/>/gi, '<$1$2></$1>'); // Force open
     1750
     1751            // Store away src and href in mce_src and mce_href since browsers mess them up
     1752            if (s.keep_values) {
     1753                // Wrap scripts in comments for serialization purposes
     1754                if (h.indexOf('<script') !== -1) {
     1755                    h = h.replace(/<script>/g, '<script type="text/javascript">');
     1756                    h = h.replace(/<script(|[^>]+)>(\s*<!--|\/\/\s*<\[CDATA\[)?[\r\n]*/g, '<mce:script$1><!--\n');
     1757                    h = h.replace(/\s*(\/\/\s*-->|\/\/\s*]]>)?<\/script>/g, '\n// --></mce:script>');
     1758                    h = h.replace(/<mce:script(|[^>]+)><!--\n\/\/ --><\/mce:script>/g, '<mce:script$1></mce:script>');
     1759                }
     1760
     1761                // Process all tags with src, href or style
     1762                h = h.replace(/<([\w:]+) [^>]*(src|href|style)[^>]*>/gi, function(a, n) {
     1763                    function handle(m, b, c) {
     1764                        var u = c;
     1765
     1766                        // Tag already got a mce_ version
     1767                        if (a.indexOf('mce_' + b) != -1)
     1768                            return m;
     1769
     1770                        if (b == 'style') {
     1771                            // Why did I need this one?
     1772                            //if (isIE)
     1773                            //  u = t.serializeStyle(t.parseStyle(u));
     1774
     1775                            if (s.hex_colors) {
     1776                                u = u.replace(/rgb\([^\)]+\)/g, function(v) {
     1777                                    return t.toHex(v);
     1778                                });
     1779                            }
     1780
     1781                            if (s.url_converter) {
     1782                                u = u.replace(/url\([\'\"]?([^\)\'\"]+)\)/g, function(x, c) {
     1783                                    return 'url(' + t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), b, n)) + ')';
     1784                                });
     1785                            }
     1786                        } else {
     1787                            if (s.url_converter)
     1788                                u = t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), b, n));
     1789                        }
     1790
     1791                        return ' ' + b + '="' + c + '" mce_' + b + '="' + u + '"';
     1792                    };
     1793
     1794                    a = a.replace(/ (src|href|style)=[\"]([^\"]+)[\"]/gi, handle); // W3C
     1795                    a = a.replace(/ (src|href|style)=[\']([^\']+)[\']/gi, handle); // W3C
     1796
     1797                    return a.replace(/ (src|href|style)=([^\s\"\'>]+)/gi, handle); // IE
     1798                });
     1799            }
     1800
     1801            return h;
     1802        },
     1803
     1804        getOuterHTML : function(e) {
     1805            var d;
     1806
     1807            e = this.get(e);
     1808
     1809            if (!e)
     1810                return null;
     1811
     1812            if (isIE)
     1813                return e.outerHTML;
     1814
     1815            d = (e.ownerDocument || this.doc).createElement("body");
     1816            d.appendChild(e.cloneNode(true));
     1817
     1818            return d.innerHTML;
     1819        },
     1820
     1821        setOuterHTML : function(e, h, d) {
     1822            var t = this;
     1823
     1824            return this.run(e, function(e) {
     1825                var n, tp;
     1826
     1827                e = t.get(e);
     1828                d = d || e.ownerDocument || t.doc;
     1829
     1830                if (isIE && e.nodeType == 1)
     1831                    e.outerHTML = h;
     1832                else {
     1833                    tp = d.createElement("body");
     1834                    tp.innerHTML = h;
     1835
     1836                    n = tp.lastChild;
     1837                    while (n) {
     1838                        t.insertAfter(n.cloneNode(true), e);
     1839                        n = n.previousSibling;
     1840                    }
     1841
     1842                    t.remove(e);
     1843                }
     1844            });
     1845        },
     1846
     1847        decode : function(s) {
     1848            var e = document.createElement("div");
     1849
     1850            e.innerHTML = s;
     1851
     1852            return !e.firstChild ? s : e.firstChild.nodeValue;
     1853        },
     1854
     1855        encode : function(s) {
     1856            return s ? ('' + s).replace(/[<>&\"]/g, function (c, b) {
     1857                switch (c) {
     1858                    case '&':
     1859                        return '&amp;';
     1860
     1861                    case '"':
     1862                        return '&quot;';
     1863
     1864                    case '<':
     1865                        return '&lt;';
     1866
     1867                    case '>':
     1868                        return '&gt;';
     1869                }
     1870
     1871                return c;
     1872            }) : s;
     1873        },
     1874
     1875        // #if !jquery
     1876
     1877        insertAfter : function(n, r) {
     1878            var t = this;
     1879
     1880            r = t.get(r);
     1881
     1882            return this.run(n, function(n) {
     1883                var p, ns;
     1884
     1885                p = r.parentNode;
     1886                ns = r.nextSibling;
     1887
     1888                if (ns)
     1889                    p.insertBefore(n, ns);
     1890                else
     1891                    p.appendChild(n);
     1892
     1893                return n;
     1894            });
     1895        },
     1896
     1897        // #endif
     1898
     1899        isBlock : function(n) {
     1900            if (n.nodeType && n.nodeType !== 1)
     1901                return false;
     1902
     1903            n = n.nodeName || n;
     1904
     1905            return /^(H[1-6]|HR|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|FORM|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP)$/.test(n);
     1906        },
     1907
     1908        // #if !jquery
     1909
     1910        replace : function(n, o, k) {
     1911            if (is(o, 'array'))
     1912                n = n.cloneNode(true);
     1913
     1914            return this.run(o, function(o) {
     1915                if (k) {
     1916                    each(o.childNodes, function(c) {
     1917                        n.appendChild(c.cloneNode(true));
     1918                    });
     1919                }
     1920
     1921                return o.parentNode.replaceChild(n, o);
     1922            });
     1923        },
     1924
     1925        // #endif
     1926
     1927        toHex : function(s) {
     1928            var c = /^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(s);
     1929
     1930            function hex(s) {
     1931                s = parseInt(s).toString(16);
     1932
     1933                return s.length > 1 ? s : '0' + s; // 0 -> 00
     1934            };
     1935
     1936            if (c) {
     1937                s = '#' + hex(c[1]) + hex(c[2]) + hex(c[3]);
     1938
     1939                return s;
     1940            }
     1941
     1942            return s;
     1943        },
     1944
     1945        getClasses : function() {
     1946            var t = this, cl = [], i, lo = {}, f = t.settings.class_filter;
     1947
     1948            if (t.classes)
     1949                return t.classes;
     1950
     1951            function addClasses(s) {
     1952                // IE style imports
     1953                each(s.imports, function(r) {
     1954                    addClasses(r);
     1955                });
     1956
     1957                each(s.cssRules || s.rules, function(r) {
     1958                    // Real type or fake it on IE
     1959                    switch (r.type || 1) {
     1960                        // Rule
     1961                        case 1:
     1962                            if (r.selectorText) {
     1963                                each(r.selectorText.split(','), function(v) {
     1964                                    v = v.replace(/^\s*|\s*$|^\s\./g, "");
     1965
     1966                                    if (f && !(v = f(v)))
     1967                                        return;
     1968
     1969                                    if (/^\.mce/.test(v) || !/^\.[\w\-]+$/.test(v))
     1970                                        return;
     1971
     1972                                    v = v.substring(1);
     1973                                    if (!lo[v]) {
     1974                                        cl.push({'class' : v});
     1975                                        lo[v] = 1;
     1976                                    }
     1977                                });
     1978                            }
     1979                            break;
     1980
     1981                        // Import
     1982                        case 3:
     1983                            addClasses(r.styleSheet);
     1984                            break;
     1985                    }
     1986                });
     1987            };
     1988
     1989            try {
     1990                each(t.doc.styleSheets, addClasses);
     1991            } catch (ex) {
     1992                // Ignore
     1993            }
     1994
     1995            if (cl.length > 0)
     1996                t.classes = cl;
     1997
     1998            return cl;
     1999        },
     2000
     2001        run : function(e, f, s) {
     2002            var t = this, o;
     2003
     2004            if (typeof(e) === 'string')
     2005                e = t.doc.getElementById(e);
     2006
     2007            if (!e)
     2008                return false;
     2009
     2010            s = s || this;
     2011            if (!e.nodeType && (e.length || e.length === 0)) {
     2012                o = [];
     2013
     2014                each(e, function(e, i) {
     2015                    if (e) {
     2016                        if (typeof(e) == 'string')
     2017                            e = t.doc.getElementById(e);
     2018
     2019                        o.push(f.call(s, e, i));
     2020                    }
     2021                });
     2022
     2023                return o;
     2024            }
     2025
     2026            return f.call(s, e);
     2027        }
     2028
     2029        /*
     2030        walk : function(n, f, s) {
     2031            var d = this.doc, w;
     2032
     2033            if (d.createTreeWalker) {
     2034                w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);
     2035
     2036                while ((n = w.nextNode()) != null)
     2037                    f.call(s || this, n);
     2038            } else
     2039                tinymce.walk(n, f, 'childNodes', s);
     2040        }
     2041        */
     2042
     2043        /*
     2044        toRGB : function(s) {
     2045            var c = /^\s*?#([0-9A-F]{2})([0-9A-F]{1,2})([0-9A-F]{2})?\s*?$/.exec(s);
     2046
     2047            if (c) {
     2048                // #FFF -> #FFFFFF
     2049                if (!is(c[3]))
     2050                    c[3] = c[2] = c[1];
     2051
     2052                return "rgb(" + parseInt(c[1], 16) + "," + parseInt(c[2], 16) + "," + parseInt(c[3], 16) + ")";
     2053            }
     2054
     2055            return s;
     2056        }
     2057        */
     2058
     2059        });
     2060
     2061    // Setup page DOM
     2062    tinymce.DOM = new tinymce.dom.DOMUtils(document);
     2063})();
     2064
     2065/* file:jscripts/tiny_mce/classes/dom/Event.js */
     2066
     2067(function() {
     2068    // Shorten names
     2069    var each = tinymce.each, DOM = tinymce.DOM, isIE = tinymce.isIE, isWebKit = tinymce.isWebKit, Event;
     2070
     2071    tinymce.create('static tinymce.dom.Event', {
     2072        inits : [],
     2073        events : [],
     2074
     2075        // #if !jquery
     2076
     2077        add : function(o, n, f, s) {
     2078            var cb, t = this, el = t.events, r;
     2079
     2080            // Handle array
     2081            if (o && o instanceof Array) {
     2082                r = [];
     2083
     2084                each(o, function(o) {
     2085                    o = DOM.get(o);
     2086                    r.push(t.add(o, n, f, s));
     2087                });
     2088
     2089                return r;
     2090            }
     2091
     2092            o = DOM.get(o);
     2093
     2094            if (!o)
     2095                return;
     2096
     2097            // Setup event callback
     2098            cb = function(e) {
     2099                e = e || window.event;
     2100
     2101                // Patch in target in IE it's W3C valid
     2102                if (e && !e.target && isIE)
     2103                    e.target = e.srcElement;
     2104
     2105                if (!s)
     2106                    return f(e);
     2107
     2108                return f.call(s, e);
     2109            };
     2110
     2111            if (n == 'unload') {
     2112                tinymce.unloads.unshift({func : cb});
     2113                return cb;
     2114            }
     2115
     2116            if (n == 'init') {
     2117                if (t.domLoaded)
     2118                    cb();
     2119                else
     2120                    t.inits.push(cb);
     2121
     2122                return cb;
     2123            }
     2124
     2125            // Store away listener reference
     2126            el.push({
     2127                obj : o,
     2128                name : n,
     2129                func : f,
     2130                cfunc : cb,
     2131                scope : s
     2132            });
     2133
     2134            t._add(o, n, cb);
     2135
     2136            return f;
     2137        },
     2138
     2139        remove : function(o, n, f) {
     2140            var t = this, a = t.events, s = false, r;
     2141
     2142            // Handle array
     2143            if (o && o instanceof Array) {
     2144                r = [];
     2145
     2146                each(o, function(o) {
     2147                    o = DOM.get(o);
     2148                    r.push(t.remove(o, n, f));
     2149                });
     2150
     2151                return r;
     2152            }
     2153
     2154            o = DOM.get(o);
     2155
     2156            each(a, function(e, i) {
     2157                if (e.obj == o && e.name == n && (!f || (e.func == f || e.cfunc == f))) {
     2158                    a.splice(i, 1);
     2159                    t._remove(o, n, e.cfunc);
     2160                    s = true;
     2161                    return false;
     2162                }
     2163            });
     2164
     2165            return s;
     2166        },
     2167
     2168        // #endif
     2169
     2170        cancel : function(e) {
     2171            if (!e)
     2172                return false;
     2173
     2174            this.stop(e);
     2175            return this.prevent(e);
     2176        },
     2177
     2178        stop : function(e) {
     2179            if (e.stopPropagation)
     2180                e.stopPropagation();
     2181            else
     2182                e.cancelBubble = true;
     2183
     2184            return false;
     2185        },
     2186
     2187        prevent : function(e) {
     2188            if (e.preventDefault)
     2189                e.preventDefault();
     2190            else
     2191                e.returnValue = false;
     2192
     2193            return false;
     2194        },
     2195
     2196        _unload : function() {
     2197            var t = Event;
     2198
     2199            each(t.events, function(e, i) {
     2200                t._remove(e.obj, e.name, e.cfunc);
     2201                e.obj = e.cfunc = null;
     2202            });
     2203
     2204            t.events = [];
     2205            t = null;
     2206        },
     2207
     2208        _add : function(o, n, f) {
     2209            if (o.attachEvent)
     2210                o.attachEvent('on' + n, f);
     2211            else if (o.addEventListener)
     2212                o.addEventListener(n, f, false);
     2213            else
     2214                o['on' + n] = f;
     2215        },
     2216
     2217        _remove : function(o, n, f) {
     2218            if (o.detachEvent)
     2219                o.detachEvent('on' + n, f);
     2220            else if (o.removeEventListener)
     2221                o.removeEventListener(n, f, false);
     2222            else
     2223                o['on' + n] = null;
     2224        },
     2225
     2226        _pageInit : function() {
     2227            var e = Event;
     2228
     2229            e._remove(window, 'DOMContentLoaded', e._pageInit);
     2230            e.domLoaded = true;
     2231
     2232            each(e.inits, function(c) {
     2233                c();
     2234            });
     2235
     2236            e.inits = [];
     2237        },
     2238
     2239        _wait : function() {
     2240            var t;
     2241
     2242            // No need since the document is already loaded
     2243            if (window.tinyMCE_GZ && tinyMCE_GZ.loaded)
     2244                return;
     2245
     2246            if (isIE && document.location.protocol != 'https:') {
     2247                // Fake DOMContentLoaded on IE
     2248                document.write('<script id=__ie_onload defer src=\'javascript:""\';><\/script>');
     2249                DOM.get("__ie_onload").onreadystatechange = function() {
     2250                    if (this.readyState == "complete") {
     2251                        Event._pageInit();
     2252                        DOM.get("__ie_onload").onreadystatechange = null; // Prevent leak
     2253                    }
     2254                };
     2255            } else {
     2256                Event._add(window, 'DOMContentLoaded', Event._pageInit, Event);
     2257
     2258                if (isIE || isWebKit) {
     2259                    t = setInterval(function() {
     2260                        if (/loaded|complete/.test(document.readyState)) {
     2261                            clearInterval(t);
     2262                            Event._pageInit();
     2263                        }
     2264                    }, 10);
     2265                }
     2266            }
     2267        }
     2268
     2269        });
     2270
     2271    // Shorten name
     2272    Event = tinymce.dom.Event;
     2273
     2274    // Dispatch DOM content loaded event for IE and Safari
     2275    Event._wait();
     2276    tinymce.addUnload(Event._unload);
     2277})();
     2278
     2279/* file:jscripts/tiny_mce/classes/dom/Element.js */
     2280
     2281(function() {
     2282    var each = tinymce.each;
     2283
     2284    tinymce.create('tinymce.dom.Element', {
     2285        Element : function(id, s) {
     2286            var t = this, dom, el;
     2287
     2288            s = s || {};
     2289            t.id = id;
     2290            t.dom = dom = s.dom || tinymce.DOM;
     2291            t.settings = s;
     2292
     2293            // Only IE leaks DOM references, this is a lot faster
     2294            if (!tinymce.isIE)
     2295                el = t.dom.get(t.id);
     2296
     2297            each([
     2298                'getPos',
     2299                'getRect',
     2300                'getParent',
     2301                'add',
     2302                'setStyle',
     2303                'getStyle',
     2304                'setStyles',
     2305                'setAttrib',
     2306                'setAttribs',
     2307                'getAttrib',
     2308                'addClass',
     2309                'removeClass',
     2310                'hasClass',
     2311                'getOuterHTML',
     2312                'setOuterHTML',
     2313                'remove',
     2314                'show',
     2315                'hide',
     2316                'isHidden',
     2317                'setHTML',
     2318                'get'
     2319            ], function(k) {
     2320                t[k] = function() {
     2321                    var a = arguments, o;
     2322
     2323                    // Opera fails
     2324                    if (tinymce.isOpera) {
     2325                        a = [id];
     2326
     2327                        each(arguments, function(v) {
     2328                            a.push(v);
     2329                        });
     2330                    } else
     2331                        Array.prototype.unshift.call(a, el || id);
     2332
     2333                    o = dom[k].apply(dom, a);
     2334                    t.update(k);
     2335
     2336                    return o;
     2337                };
     2338            });
     2339        },
     2340
     2341        on : function(n, f, s) {
     2342            return tinymce.dom.Event.add(this.id, n, f, s);
     2343        },
     2344
     2345        getXY : function() {
     2346            return {
     2347                x : parseInt(this.getStyle('left')),
     2348                y : parseInt(this.getStyle('top'))
     2349            };
     2350        },
     2351
     2352        getSize : function() {
     2353            var n = this.dom.get(this.id);
     2354
     2355            return {
     2356                w : parseInt(this.getStyle('width') || n.clientWidth),
     2357                h : parseInt(this.getStyle('height') || n.clientHeight)
     2358            };
     2359        },
     2360
     2361        moveTo : function(x, y) {
     2362            this.setStyles({left : x, top : y});
     2363        },
     2364
     2365        moveBy : function(x, y) {
     2366            var p = this.getXY();
     2367
     2368            this.moveTo(p.x + x, p.y + y);
     2369        },
     2370
     2371        resizeTo : function(w, h) {
     2372            this.setStyles({width : w, height : h});
     2373        },
     2374
     2375        resizeBy : function(w, h) {
     2376            var s = this.getSize();
     2377
     2378            this.resizeTo(s.w + w, s.h + h);
     2379        },
     2380
     2381        update : function(k) {
     2382            var t = this, b, dom = t.dom;
     2383
     2384            if (tinymce.isIE6 && t.settings.blocker) {
     2385                k = k || '';
     2386
     2387                // Ignore getters
     2388                if (k.indexOf('get') === 0 || k.indexOf('has') === 0 || k.indexOf('is') === 0)
     2389                    return;
     2390
     2391                // Remove blocker on remove
     2392                if (k == 'remove') {
     2393                    dom.remove(t.blocker);
     2394                    return;
     2395                }
     2396
     2397                if (!t.blocker) {
     2398                    t.blocker = dom.uniqueId();
     2399                    b = dom.add(t.settings.container || dom.getRoot(), 'iframe', {id : t.blocker, style : 'position:absolute;', frameBorder : 0, src : 'javascript:""'});
     2400                    dom.setStyle(b, 'opacity', 0);
     2401                } else
     2402                    b = dom.get(t.blocker);
     2403
     2404                dom.setStyle(b, 'left', t.getStyle('left', 1));
     2405                dom.setStyle(b, 'top', t.getStyle('top', 1));
     2406                dom.setStyle(b, 'width', t.getStyle('width', 1));
     2407                dom.setStyle(b, 'height', t.getStyle('height', 1));
     2408                dom.setStyle(b, 'display', t.getStyle('display', 1));
     2409                dom.setStyle(b, 'zIndex', parseInt(t.getStyle('zIndex', 1) || 0) - 1);
     2410            }
     2411        }
     2412
     2413        });
     2414})();
     2415
     2416/* file:jscripts/tiny_mce/classes/dom/Selection.js */
     2417
     2418(function() {
     2419    // Shorten names
     2420    var is = tinymce.is, isIE = tinymce.isIE, each = tinymce.each;
     2421
     2422    tinymce.create('tinymce.dom.Selection', {
     2423        Selection : function(dom, win, serializer) {
     2424            var t = this;
     2425
     2426            t.dom = dom;
     2427            t.win = win;
     2428            t.serializer = serializer;
     2429
     2430            // Prevent leaks
     2431            tinymce.addUnload(function() {
     2432                t.win = null;
     2433            });
     2434        },
     2435
     2436        getContent : function(s) {
     2437            var t = this, r = t.getRng(), e = t.dom.create("body"), se = t.getSel(), wb, wa, n;
     2438
     2439            s = s || {};
     2440            wb = wa = '';
     2441            s.get = true;
     2442            s.format = s.format || 'html';
     2443
     2444            if (s.format == 'text')
     2445                return t.isCollapsed() ? '' : (r.text || (se.toString ? se.toString() : ''));
     2446
     2447            if (r.cloneContents) {
     2448                n = r.cloneContents();
     2449
     2450                if (n)
     2451                    e.appendChild(n);
     2452            } else if (is(r.item) || is(r.htmlText))
     2453                e.innerHTML = r.item ? r.item(0).outerHTML : r.htmlText;
     2454            else
     2455                e.innerHTML = r.toString();
     2456
     2457            // Keep whitespace before and after
     2458            if (/^\s/.test(e.innerHTML))
     2459                wb = ' ';
     2460
     2461            if (/\s+$/.test(e.innerHTML))
     2462                wa = ' ';
     2463
     2464            return t.isCollapsed() ? '' : wb + t.serializer.serialize(e, s) + wa;
     2465        },
     2466
     2467        setContent : function(h, s) {
     2468            var t = this, r = t.getRng(), d;
     2469
     2470            s = s || {format : 'html'};
     2471            s.set = true;
     2472            h = t.dom.processHTML(h);
     2473
     2474            if (r.insertNode) {
     2475                d = t.win.document;
     2476
     2477                // Use insert HTML if it exists (places cursor after content)
     2478                if (d.queryCommandEnabled('InsertHTML'))
     2479                    return d.execCommand('InsertHTML', false, h);
     2480
     2481                r.deleteContents();
     2482                r.insertNode(t.getRng().createContextualFragment(h));
     2483            } else {
     2484                if (r.item)
     2485                    r.item(0).outerHTML = h;
     2486                else
     2487                    r.pasteHTML(h);
     2488            }
     2489        },
     2490
     2491        getStart : function() {
     2492            var t = this, r = t.getRng(), e;
     2493
     2494            if (isIE) {
     2495                if (r.item)
     2496                    return r.item(0);
     2497
     2498                r = r.duplicate();
     2499                r.collapse(1);
     2500                e = r.parentElement();
     2501
     2502                if (e.nodeName == 'BODY')
     2503                    return e.firstChild;
     2504
     2505                return e;
     2506            } else {
     2507                e = r.startContainer;
     2508
     2509                if (e.nodeName == 'BODY')
     2510                    return e.firstChild;
     2511
     2512                return t.dom.getParent(e, function(n) {return n.nodeType == 1;});
     2513            }
     2514        },
     2515
     2516        getEnd : function() {
     2517            var t = this, r = t.getRng(), e;
     2518
     2519            if (isIE) {
     2520                if (r.item)
     2521                    return r.item(0);
     2522
     2523                r = r.duplicate();
     2524                r.collapse(0);
     2525                e = r.parentElement();
     2526
     2527                if (e.nodeName == 'BODY')
     2528                    return e.lastChild;
     2529
     2530                return e;
     2531            } else {
     2532                e = r.endContainer;
     2533
     2534                if (e.nodeName == 'BODY')
     2535                    return e.lastChild;
     2536
     2537                return t.dom.getParent(e, function(n) {return n.nodeType == 1;});
     2538            }
     2539        },
     2540
     2541        getBookmark : function(si) {
     2542            var t = this, r = t.getRng(), tr, sx, sy, vp = t.dom.getViewPort(t.win), e, sp, bp, le, c = -0xFFFFFF, s, ro = t.dom.getRoot();
     2543
     2544            sx = vp.x;
     2545            sy = vp.y;
     2546
     2547            // Simple bookmark fast but not as persistent
     2548            if (si == 'simple')
     2549                return {rng : r, scrollX : sx, scrollY : sy};
     2550
     2551            // Handle IE
     2552            if (isIE) {
     2553                // Control selection
     2554                if (r.item) {
     2555                    e = r.item(0);
     2556
     2557                    each(t.dom.select(e.nodeName), function(n, i) {
     2558                        if (e == n) {
     2559                            sp = i;
     2560                            return false;
     2561                        }
     2562                    });
     2563
     2564                    return {
     2565                        tag : e.nodeName,
     2566                        index : sp,
     2567                        scrollX : sx,
     2568                        scrollY : sy
     2569                    };
     2570                }
     2571
     2572                // Text selection
     2573                tr = t.dom.doc.body.createTextRange();
     2574                tr.moveToElementText(ro);
     2575                tr.collapse(true);
     2576                bp = Math.abs(tr.move('character', c));
     2577
     2578                tr = r.duplicate();
     2579                tr.collapse(true);
     2580                sp = Math.abs(tr.move('character', c));
     2581
     2582                tr = r.duplicate();
     2583                tr.collapse(false);
     2584                le = Math.abs(tr.move('character', c)) - sp;
    63812585
    63822586                return {
     
    63872591                };
    63882592            }
    6389         } else {
    6390             s = this.getSel();
    6391             e = this.getFocusElement();
     2593
     2594            // Handle W3C
     2595            e = t.getNode();
     2596            s = t.getSel();
    63922597
    63932598            if (!s)
    63942599                return null;
    63952600
     2601            // Image selection
    63962602            if (e && e.nodeName == 'IMG') {
    6397                 /*nl = b.getElementsByTagName('IMG');
    6398                 for (i=0; i<nl.length; i++) {
    6399                     if (e == nl[i]) {
    6400                         sp = i;
    6401                         break;
    6402                     }
    6403                 }*/
    6404 
    64052603                return {
    6406                     start : -1,
    6407                     end : -1,
    6408                     index : sp,
    64092604                    scrollX : sx,
    64102605                    scrollY : sy
     
    64122607            }
    64132608
     2609            // Text selection
     2610
     2611            function getPos(r, sn, en) {
     2612                var w = document.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {};
     2613
     2614                while ((n = w.nextNode()) != null) {
     2615                    if (n == sn)
     2616                        d.start = p;
     2617
     2618                    if (n == en) {
     2619                        d.end = p;
     2620                        return d;
     2621                    }
     2622
     2623                    p += n.nodeValue ? n.nodeValue.length : 0;
     2624                }
     2625
     2626                return null;
     2627            };
     2628
    64142629            // Caret or selection
    64152630            if (s.anchorNode == s.focusNode && s.anchorOffset == s.focusOffset) {
    6416                 e = this._getPosText(b, s.anchorNode, s.focusNode);
     2631                e = getPos(ro, s.anchorNode, s.focusNode);
    64172632
    64182633                if (!e)
     
    64262641                };
    64272642            } else {
    6428                 e = this._getPosText(b, rng.startContainer, rng.endContainer);
     2643                e = getPos(ro, r.startContainer, r.endContainer);
    64292644
    64302645                if (!e)
     
    64322647
    64332648                return {
    6434                     start : e.start + rng.startOffset,
    6435                     end : e.end + rng.endOffset,
     2649                    start : e.start + r.startOffset,
     2650                    end : e.end + r.endOffset,
    64362651                    scrollX : sx,
    64372652                    scrollY : sy
    64382653                };
    64392654            }
     2655        },
     2656
     2657        moveToBookmark : function(b) {
     2658            var t = this, r = t.getRng(), s = t.getSel(), ro = t.dom.getRoot(), sd;
     2659
     2660            function getPos(r, sp, ep) {
     2661                var w = document.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {};
     2662
     2663                while ((n = w.nextNode()) != null) {
     2664                    p += n.nodeValue ? n.nodeValue.length : 0;
     2665
     2666                    if (p >= sp && !d.startNode) {
     2667                        d.startNode = n;
     2668                        d.startOffset = sp - (p - n.nodeValue.length);
     2669                    }
     2670
     2671                    if (p >= ep) {
     2672                        d.endNode = n;
     2673                        d.endOffset = ep - (p - n.nodeValue.length);
     2674
     2675                        return d;
     2676                    }
     2677                }
     2678
     2679                return null;
     2680            };
     2681
     2682            if (!b)
     2683                return false;
     2684
     2685            t.win.scrollTo(b.scrollX, b.scrollY);
     2686
     2687            // Handle explorer
     2688            if (isIE) {
     2689                // Handle simple
     2690                if (r = b.rng) {
     2691                    try {
     2692                        r.select();
     2693                    } catch (ex) {
     2694                        // Ignore
     2695                    }
     2696
     2697                    return true;
     2698                }
     2699
     2700                t.win.focus();
     2701
     2702                // Handle control bookmark
     2703                if (b.tag) {
     2704                    r = ro.createControlRange();
     2705
     2706                    each(t.dom.select(b.tag), function(n, i) {
     2707                        if (i == b.index)
     2708                            r.addElement(n);
     2709                    });
     2710                } else {
     2711                    // Try/catch needed since this operation breaks when TinyMCE is placed in hidden divs/tabs
     2712                    try {
     2713                        // Incorrect bookmark
     2714                        if (b.start < 0)
     2715                            return true;
     2716
     2717                        r = s.createRange();
     2718                        r.moveToElementText(ro);
     2719                        r.collapse(true);
     2720                        r.moveStart('character', b.start);
     2721                        r.moveEnd('character', b.length);
     2722                    } catch (ex2) {
     2723                        return true;
     2724                    }
     2725                }
     2726
     2727                r.select();
     2728
     2729                return true;
     2730            }
     2731
     2732            // Handle W3C
     2733            if (!s)
     2734                return false;
     2735
     2736            // Handle simple
     2737            if (b.rng) {
     2738                s.removeAllRanges();
     2739                s.addRange(b.rng);
     2740            } else {
     2741                if (is(b.start) && is(b.end)) {
     2742                    try {
     2743                        sd = getPos(ro, b.start, b.end);
     2744                        if (sd) {
     2745                            r = t.dom.doc.createRange();
     2746                            r.setStart(sd.startNode, sd.startOffset);
     2747                            r.setEnd(sd.endNode, sd.endOffset);
     2748                            s.removeAllRanges();
     2749                            s.addRange(r);
     2750                        }
     2751
     2752                        if (!tinymce.isOpera)
     2753                            t.win.focus();
     2754                    } catch (ex) {
     2755                        // Ignore
     2756                    }
     2757                }
     2758            }
     2759        },
     2760
     2761        select : function(n, c) {
     2762            var t = this, r = t.getRng(), s = t.getSel(), b, fn, ln, d = t.win.document;
     2763
     2764            function first(n) {
     2765                return n ? d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false).nextNode() : null;
     2766            };
     2767
     2768            function last(n) {
     2769                var c, o, w;
     2770
     2771                if (!n)
     2772                    return null;
     2773
     2774                w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);
     2775                while (c = w.nextNode())
     2776                    o = c;
     2777
     2778                return o;
     2779            };
     2780
     2781            if (isIE) {
     2782                try {
     2783                    b = d.body;
     2784
     2785                    if (/^(IMG|TABLE)$/.test(n.nodeName)) {
     2786                        r = b.createControlRange();
     2787                        r.addElement(n);
     2788                    } else {
     2789                        r = b.createTextRange();
     2790                        r.moveToElementText(n);
     2791                    }
     2792
     2793                    r.select();
     2794                } catch (ex) {
     2795                    // Throws illigal agrument in IE some times
     2796                }
     2797            } else {
     2798                if (c) {
     2799                    fn = first(n);
     2800                    ln = last(n);
     2801
     2802                    if (fn && ln) {
     2803                        //console.debug(fn, ln);
     2804                        r = d.createRange();
     2805                        r.setStart(fn, 0);
     2806                        r.setEnd(ln, ln.nodeValue.length);
     2807                    } else
     2808                        r.selectNode(n);
     2809                } else
     2810                    r.selectNode(n);
     2811
     2812                t.setRng(r);
     2813            }
     2814
     2815            return n;
     2816        },
     2817
     2818        isCollapsed : function() {
     2819            var t = this, r = t.getRng(), s = t.getSel();
     2820
     2821            if (!r || r.item)
     2822                return false;
     2823
     2824            return !s || r.boundingWidth == 0 || s.isCollapsed;
     2825        },
     2826
     2827        collapse : function(b) {
     2828            var t = this, r = t.getRng(), n;
     2829
     2830            // Control range on IE
     2831            if (r.item) {
     2832                n = r.item(0);
     2833                r = this.win.document.body.createTextRange();
     2834                r.moveToElementText(n);
     2835            }
     2836
     2837            r.collapse(!!b);
     2838            t.setRng(r);
     2839        },
     2840
     2841        getSel : function() {
     2842            var t = this, w = this.win;
     2843
     2844            return w.getSelection ? w.getSelection() : w.document.selection;
     2845        },
     2846
     2847        getRng : function() {
     2848            var t = this, s = t.getSel(), r;
     2849
     2850            try {
     2851                if (s)
     2852                    r = s.rangeCount > 0 ? s.getRangeAt(0) : (s.createRange ? s.createRange() : t.win.document.createRange());
     2853            } catch (ex) {
     2854                // IE throws unspecified error here if TinyMCE is placed in a frame/iframe
     2855            }
     2856
     2857            // No range found then create an empty one
     2858            // This can occur when the editor is placed in a hidden container element on Gecko
     2859            // Or on IE when there was an exception
     2860            if (!r)
     2861                r = isIE ? t.win.document.body.createTextRange() : t.win.document.createRange();
     2862
     2863            return r;
     2864        },
     2865
     2866        setRng : function(r) {
     2867            var s;
     2868
     2869            if (!isIE) {
     2870                s = this.getSel();
     2871
     2872                if (s) {
     2873                    s.removeAllRanges();
     2874                    s.addRange(r);
     2875                }
     2876            } else
     2877                r.select();
     2878        },
     2879
     2880        setNode : function(n) {
     2881            var t = this;
     2882
     2883            t.setContent(t.dom.getOuterHTML(n));
     2884
     2885            return n;
     2886        },
     2887
     2888        getNode : function() {
     2889            var t = this, r = t.getRng(), s = t.getSel(), e;
     2890
     2891            if (!isIE) {
     2892                // Range maybe lost after the editor is made visible again
     2893                if (!r)
     2894                    return t.dom.getRoot();
     2895
     2896                e = r.commonAncestorContainer;
     2897
     2898                // Handle selection a image or other control like element such as anchors
     2899                if (!r.collapsed) {
     2900                    if (r.startContainer == r.endContainer || (tinymce.isWebKit && r.startContainer == r.endContainer.parentNode)) {
     2901                        if (r.startOffset - r.endOffset < 2 || tinymce.isWebKit) {
     2902                            if (r.startContainer.hasChildNodes())
     2903                                e = r.startContainer.childNodes[r.startOffset];
     2904                        }
     2905                    }
     2906                }
     2907
     2908                return t.dom.getParent(e, function(n) {
     2909                    return n.nodeType == 1;
     2910                });
     2911            }
     2912
     2913            return r.item ? r.item(0) : r.parentElement();
    64402914        }
    64412915
    6442         return null;
     2916        });
     2917})();
     2918
     2919/* file:jscripts/tiny_mce/classes/dom/XMLWriter.js */
     2920
     2921(function() {
     2922    tinymce.create('tinymce.dom.XMLWriter', {
     2923        node : null,
     2924
     2925        XMLWriter : function(s) {
     2926            // Get XML document
     2927            function getXML() {
     2928                var i = document.implementation;
     2929
     2930                if (!i || !i.createDocument) {
     2931                    // Try IE objects
     2932                    try {return new ActiveXObject('MSXML2.DOMDocument');} catch (ex) {}
     2933                    try {return new ActiveXObject('Microsoft.XmlDom');} catch (ex) {}
     2934                } else
     2935                    return i.createDocument('', '', null);
     2936            };
     2937
     2938            this.doc = getXML();
     2939            this.reset();
     2940        },
     2941
     2942        reset : function() {
     2943            var t = this, d = t.doc;
     2944
     2945            if (d.firstChild)
     2946                d.removeChild(d.firstChild);
     2947
     2948            t.node = d.appendChild(d.createElement("html"));
     2949        },
     2950
     2951        writeStartElement : function(n) {
     2952            var t = this;
     2953
     2954            t.node = t.node.appendChild(t.doc.createElement(n));
     2955        },
     2956
     2957        writeAttribute : function(n, v) {
     2958            // Since Opera doesn't escape > into &gt; we need to do it our self
     2959            if (tinymce.isOpera)
     2960                v = v.replace(/>/g, '|>');
     2961
     2962            this.node.setAttribute(n, v);
     2963        },
     2964
     2965        writeEndElement : function() {
     2966            this.node = this.node.parentNode;
     2967        },
     2968
     2969        writeFullEndElement : function() {
     2970            var t = this, n = t.node;
     2971
     2972            n.appendChild(t.doc.createTextNode(""));
     2973            t.node = n.parentNode;
     2974        },
     2975
     2976        writeText : function(v) {
     2977            // Since Opera doesn't escape > into &gt; we need to do it our self
     2978            if (tinymce.isOpera)
     2979                v = v.replace(/>/g, '|>');
     2980
     2981            this.node.appendChild(this.doc.createTextNode(v));
     2982        },
     2983
     2984        writeCDATA : function(v) {
     2985            this.node.appendChild(this.doc.createCDATA(v));
     2986        },
     2987
     2988        writeComment : function(v) {
     2989            this.node.appendChild(this.doc.createComment(v));
     2990        },
     2991
     2992        getContent : function() {
     2993            var h;
     2994
     2995            h = this.doc.xml || new XMLSerializer().serializeToString(this.doc);
     2996            h = h.replace(/<\?[^?]+\?>|<html>|<\/html>|<html\/>|<!DOCTYPE[^>]+>/g, '');
     2997            h = h.replace(/ ?\/>/g, ' />');
     2998
     2999            // Since Opera doesn't escape > into &gt; we need to do it our self to normalize the output for all browsers
     3000            if (tinymce.isOpera)
     3001                h = h.replace(/\|>/g, '&gt;');
     3002
     3003            return h;
     3004        }
     3005
     3006        });
     3007})();
     3008
     3009/* file:jscripts/tiny_mce/classes/dom/Serializer.js */
     3010
     3011(function() {
     3012    // Shorten names
     3013    var extend = tinymce.extend, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher, isIE = tinymce.isIE;
     3014
     3015    // Returns only attribites that have values not all attributes in IE
     3016    function getIEAtts(n) {
     3017        var o = [];
     3018
     3019        // Object will throw exception in IE
     3020        if (n.nodeName == 'OBJECT')
     3021            return n.attributes;
     3022
     3023        n.cloneNode(false).outerHTML.replace(/([a-z0-9\-_]+)=/gi, function(a, b) {
     3024            o.push({specified : 1, nodeName : b});
     3025        });
     3026
     3027        return o;
     3028    };
     3029
     3030    function wildcardToRE(s) {
     3031        return s.replace(/([?+*])/g, '.$1');
     3032    };
     3033
     3034    tinymce.create('tinymce.dom.Serializer', {
     3035        Serializer : function(s) {
     3036            var t = this;
     3037
     3038            t.key = 0;
     3039            t.onPreProcess = new Dispatcher(t);
     3040            t.onPostProcess = new Dispatcher(t);
     3041            t.writer = new tinymce.dom.XMLWriter();
     3042
     3043            // Default settings
     3044            t.settings = s = extend({
     3045                dom : tinymce.DOM,
     3046                valid_nodes : 0,
     3047                node_filter : 0,
     3048                attr_filter : 0,
     3049                invalid_attrs : /^(mce_|_moz_$)/,
     3050                closed : /(br|hr|input|meta|img|link|param)/,
     3051                entity_encoding : 'named',
     3052                entities : '160,nbsp,161,iexcl,162,cent,163,pound,164,curren,165,yen,166,brvbar,167,sect,168,uml,169,copy,170,ordf,171,laquo,172,not,173,shy,174,reg,175,macr,176,deg,177,plusmn,178,sup2,179,sup3,180,acute,181,micro,182,para,183,middot,184,cedil,185,sup1,186,ordm,187,raquo,188,frac14,189,frac12,190,frac34,191,iquest,192,Agrave,193,Aacute,194,Acirc,195,Atilde,196,Auml,197,Aring,198,AElig,199,Ccedil,200,Egrave,201,Eacute,202,Ecirc,203,Euml,204,Igrave,205,Iacute,206,Icirc,207,Iuml,208,ETH,209,Ntilde,210,Ograve,211,Oacute,212,Ocirc,213,Otilde,214,Ouml,215,times,216,Oslash,217,Ugrave,218,Uacute,219,Ucirc,220,Uuml,221,Yacute,222,THORN,223,szlig,224,agrave,225,aacute,226,acirc,227,atilde,228,auml,229,aring,230,aelig,231,ccedil,232,egrave,233,eacute,234,ecirc,235,euml,236,igrave,237,iacute,238,icirc,239,iuml,240,eth,241,ntilde,242,ograve,243,oacute,244,ocirc,245,otilde,246,ouml,247,divide,248,oslash,249,ugrave,250,uacute,251,ucirc,252,uuml,253,yacute,254,thorn,255,yuml,402,fnof,913,Alpha,914,Beta,915,Gamma,916,Delta,917,Epsilon,918,Zeta,919,Eta,920,Theta,921,Iota,922,Kappa,923,Lambda,924,Mu,925,Nu,926,Xi,927,Omicron,928,Pi,929,Rho,931,Sigma,932,Tau,933,Upsilon,934,Phi,935,Chi,936,Psi,937,Omega,945,alpha,946,beta,947,gamma,948,delta,949,epsilon,950,zeta,951,eta,952,theta,953,iota,954,kappa,955,lambda,956,mu,957,nu,958,xi,959,omicron,960,pi,961,rho,962,sigmaf,963,sigma,964,tau,965,upsilon,966,phi,967,chi,968,psi,969,omega,977,thetasym,978,upsih,982,piv,8226,bull,8230,hellip,8242,prime,8243,Prime,8254,oline,8260,frasl,8472,weierp,8465,image,8476,real,8482,trade,8501,alefsym,8592,larr,8593,uarr,8594,rarr,8595,darr,8596,harr,8629,crarr,8656,lArr,8657,uArr,8658,rArr,8659,dArr,8660,hArr,8704,forall,8706,part,8707,exist,8709,empty,8711,nabla,8712,isin,8713,notin,8715,ni,8719,prod,8721,sum,8722,minus,8727,lowast,8730,radic,8733,prop,8734,infin,8736,ang,8743,and,8744,or,8745,cap,8746,cup,8747,int,8756,there4,8764,sim,8773,cong,8776,asymp,8800,ne,8801,equiv,8804,le,8805,ge,8834,sub,8835,sup,8836,nsub,8838,sube,8839,supe,8853,oplus,8855,otimes,8869,perp,8901,sdot,8968,lceil,8969,rceil,8970,lfloor,8971,rfloor,9001,lang,9002,rang,9674,loz,9824,spades,9827,clubs,9829,hearts,9830,diams,338,OElig,339,oelig,352,Scaron,353,scaron,376,Yuml,710,circ,732,tilde,8194,ensp,8195,emsp,8201,thinsp,8204,zwnj,8205,zwj,8206,lrm,8207,rlm,8211,ndash,8212,mdash,8216,lsquo,8217,rsquo,8218,sbquo,8220,ldquo,8221,rdquo,8222,bdquo,8224,dagger,8225,Dagger,8240,permil,8249,lsaquo,8250,rsaquo,8364,euro',
     3053                valid_elements : '*[*]',
     3054                extended_valid_elements : 0,
     3055                valid_child_elements : 0,
     3056                invalid_elements : 0,
     3057                fix_table_elements : 0,
     3058                fix_list_elements : true,
     3059                fix_content_duplication : true,
     3060                convert_fonts_to_spans : false,
     3061                font_size_classes : 0,
     3062                font_size_style_values : 0,
     3063                apply_source_formatting : 0,
     3064                indent_mode : 'simple',
     3065                indent_char : '\t',
     3066                indent_levels : 1,
     3067                remove_linebreaks : 1
     3068            }, s);
     3069
     3070            t.dom = s.dom;
     3071
     3072            if (s.fix_list_elements) {
     3073                t.onPreProcess.add(function(se, o) {
     3074                    var nl, x, a = ['ol', 'ul'], i, n, p, r = /^(OL|UL)$/, np;
     3075
     3076                    function prevNode(e, n) {
     3077                        var a = n.split(','), i;
     3078
     3079                        while ((e = e.previousSibling) != null) {
     3080                            for (i=0; i<a.length; i++) {
     3081                                if (e.nodeName == a[i])
     3082                                    return e;
     3083                            }
     3084                        }
     3085
     3086                        return null;
     3087                    };
     3088
     3089                    for (x=0; x<a.length; x++) {
     3090                        nl = t.dom.select(a[x], o.node);
     3091
     3092                        for (i=0; i<nl.length; i++) {
     3093                            n = nl[i];
     3094                            p = n.parentNode;
     3095
     3096                            if (r.test(p.nodeName)) {
     3097                                np = prevNode(n, 'LI');
     3098
     3099                                if (!np) {
     3100                                    np = t.dom.create('li');
     3101                                    np.innerHTML = '&nbsp;';
     3102                                    np.appendChild(n);
     3103                                    p.insertBefore(np, p.firstChild);
     3104                                } else
     3105                                    np.appendChild(n);
     3106                            }
     3107                        }
     3108                    }
     3109                });
     3110            }
     3111
     3112            if (s.fix_table_elements) {
     3113                t.onPreProcess.add(function(se, o) {
     3114                    var ta = [], d = t.dom.doc;
     3115
     3116                    // Build list of HTML chunks and replace tables with comment placeholders
     3117                    each(t.dom.select('table', o.node), function(e) {
     3118                        var pa = t.dom.getParent(e, 'H1,H2,H3,H4,H5,H6,P'), p = [], i, h;
     3119
     3120                        if (pa) {
     3121                            t.dom.getParent(e, function(n) {
     3122                                if (n != e)
     3123                                    p.push(n.nodeName);
     3124                            });
     3125
     3126                            h = '';
     3127
     3128                            for (i = 0; i < p.length; i++)
     3129                                h += '</' + p[i]+ '>';
     3130
     3131                            h += t.dom.getOuterHTML(e);
     3132
     3133                            for (i = p.length - 1; i >= 0; i--)
     3134                                h += '<' + p[i]+ '>';
     3135
     3136                            ta.push(h);
     3137                            e.parentNode.replaceChild(d.createComment('mcetable:' + (ta.length - 1)), e);
     3138                        }
     3139                    });
     3140
     3141                    // Replace table placeholders with end parents + table + start parents HTML code
     3142                    t.dom.setHTML(o.node, o.node.innerHTML.replace(/<!--mcetable:([0-9]+)-->/g, function(a, b) {
     3143                        return ta[parseInt(b)];
     3144                    }));
     3145                });
     3146            }
     3147        },
     3148
     3149        setEntities : function(s) {
     3150            var a, i, l = {}, re = '', v;
     3151
     3152            // No need to setup more than once
     3153            if (this.entityLookup)
     3154                return;
     3155
     3156            // Build regex and lookup array
     3157            a = s.split(',');
     3158            for (i = 0; i < a.length; i += 2) {
     3159                v = a[i];
     3160
     3161                // Don't add default &amp; &quot; etc.
     3162                if (v == 34 || v == 38 || v == 60 || v == 62)
     3163                    continue;
     3164
     3165                l[String.fromCharCode(a[i])] = a[i + 1];
     3166
     3167                v = parseInt(a[i]).toString(16);
     3168                re += '\\u' + '0000'.substring(v.length) + v;
     3169            }
     3170
     3171            this.entitiesRE = new RegExp('[' + re + ']', 'g');
     3172            this.entityLookup = l;
     3173        },
     3174
     3175        setValidChildRules : function(s) {
     3176            this.childRules = null;
     3177            this.addValidChildRules(s);
     3178        },
     3179
     3180        addValidChildRules : function(s) {
     3181            var t = this, inst, intr, bloc;
     3182
     3183            if (!s)
     3184                return;
     3185
     3186            inst = 'A|BR|SPAN|BDO|MAP|OBJECT|IMG|TT|I|B|BIG|SMALL|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|#text|#comment';
     3187            intr = 'A|BR|SPAN|BDO|OBJECT|APPLET|IMG|MAP|IFRAME|TT|I|B|U|S|STRIKE|BIG|SMALL|FONT|BASEFONT|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|INPUT|SELECT|TEXTAREA|LABEL|BUTTON|#text|#comment';
     3188            bloc = 'H[1-6]|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|FORM|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP';
     3189
     3190            each(s.split(','), function(s) {
     3191                var p = s.split(/\[|\]/), re;
     3192
     3193                s = '';
     3194                each(p[1].split('|'), function(v) {
     3195                    if (s)
     3196                        s += '|';
     3197
     3198                    switch (v) {
     3199                        case '%itrans':
     3200                            v = intr;
     3201                            break;
     3202
     3203                        case '%itrans_na':
     3204                            v = intr.substring(2);
     3205                            break;
     3206
     3207                        case '%istrict':
     3208                            v = inst;
     3209                            break;
     3210
     3211                        case '%istrict_na':
     3212                            v = inst.substring(2);
     3213                            break;
     3214
     3215                        case '%btrans':
     3216                            v = bloc;
     3217                            break;
     3218
     3219                        case '%bstrict':
     3220                            v = bloc;
     3221                            break;
     3222                    }
     3223
     3224                    s += v;
     3225                });
     3226                re = new RegExp('^(' + s.toLowerCase() + ')$', 'i');
     3227
     3228                each(p[0].split('/'), function(s) {
     3229                    t.childRules = t.childRules || {};
     3230                    t.childRules[s] = re;
     3231                });
     3232            });
     3233
     3234            // Build regex
     3235            s = '';
     3236            each(t.childRules, function(v, k) {
     3237                if (s)
     3238                    s += '|';
     3239
     3240                s += k;
     3241            });
     3242
     3243            t.parentElementsRE = new RegExp('^(' + s.toLowerCase() + ')$', 'i');
     3244
     3245            /*console.debug(t.parentElementsRE.toString());
     3246            each(t.childRules, function(v) {
     3247                console.debug(v.toString());
     3248            });*/
     3249        },
     3250
     3251        setRules : function(s) {
     3252            var t = this;
     3253
     3254            t._setup();
     3255            t.rules = {};
     3256            t.wildRules = [];
     3257            t.validElements = {};
     3258
     3259            return t.addRules(s);
     3260        },
     3261
     3262        addRules : function(s) {
     3263            var t = this, dr;
     3264
     3265            if (!s)
     3266                return;
     3267
     3268            t._setup();
     3269
     3270            each(s.split(','), function(s) {
     3271                var p = s.split(/\[|\]/), tn = p[0].split('/'), ra, at, wat, va = [];
     3272
     3273                // Extend with default rules
     3274                if (dr)
     3275                    at = tinymce.extend([], dr.attribs);
     3276
     3277                // Parse attributes
     3278                if (p.length > 1) {
     3279                    each(p[1].split('|'), function(s) {
     3280                        var ar = {}, i;
     3281
     3282                        at = at || [];
     3283
     3284                        // Parse attribute rule
     3285                        s = s.replace(/::/g, '~');
     3286                        s = /^([!\-])?([\w*.?~]+|)([=:<])?(.+)?$/.exec(s);
     3287                        s[2] = s[2].replace(/~/g, ':');
     3288
     3289                        // Add required attributes
     3290                        if (s[1] == '!') {
     3291                            ra = ra || [];
     3292                            ra.push(s[2]);
     3293                        }
     3294
     3295                        // Remove inherited attributes
     3296                        if (s[1] == '-') {
     3297                            for (i = 0; i <at.length; i++) {
     3298                                if (at[i].name == s[2]) {
     3299                                    at.splice(i, 1);
     3300                                    return;
     3301                                }
     3302                            }
     3303                        }
     3304
     3305                        switch (s[3]) {
     3306                            // Add default attrib values
     3307                            case '=':
     3308                                ar.defaultVal = s[4] || '';
     3309                                break;
     3310
     3311                            // Add forced attrib values
     3312                            case ':':
     3313                                ar.forcedVal = s[4];
     3314                                break;
     3315
     3316                            // Add validation values
     3317                            case '<':
     3318                                ar.validVals = s[4].split('?');
     3319                                break;
     3320                        }
     3321
     3322                        if (/[*.?]/.test(s[2])) {
     3323                            wat = wat || [];
     3324                            ar.nameRE = new RegExp('^' + wildcardToRE(s[2]) + '$');
     3325                            wat.push(ar);
     3326                        } else {
     3327                            ar.name = s[2];
     3328                            at.push(ar);
     3329                        }
     3330
     3331                        va.push(s[2]);
     3332                    });
     3333                }
     3334
     3335                // Handle element names
     3336                each(tn, function(s, i) {
     3337                    var pr = s.charAt(0), x = 1, ru = {};
     3338
     3339                    // Extend with default rule data
     3340                    if (dr) {
     3341                        if (dr.noEmpty)
     3342                            ru.noEmpty = dr.noEmpty;
     3343
     3344                        if (dr.fullEnd)
     3345                            ru.fullEnd = dr.fullEnd;
     3346
     3347                        if (dr.padd)
     3348                            ru.padd = dr.padd;
     3349                    }
     3350
     3351                    // Handle prefixes
     3352                    switch (pr) {
     3353                        case '-':
     3354                            ru.noEmpty = true;
     3355                            break;
     3356
     3357                        case '+':
     3358                            ru.fullEnd = true;
     3359                            break;
     3360
     3361                        case '#':
     3362                            ru.padd = true;
     3363                            break;
     3364
     3365                        default:
     3366                            x = 0;
     3367                    }
     3368
     3369                    tn[i] = s = s.substring(x);
     3370                    t.validElements[s] = 1;
     3371
     3372                    // Add element name or element regex
     3373                    if (/[*.?]/.test(tn[0])) {
     3374                        ru.nameRE = new RegExp('^' + wildcardToRE(tn[0]) + '$');
     3375                        t.wildRules = t.wildRules || {};
     3376                        t.wildRules.push(ru);
     3377                    } else {
     3378                        ru.name = tn[0];
     3379
     3380                        // Store away default rule
     3381                        if (tn[0] == '@')
     3382                            dr = ru;
     3383
     3384                        t.rules[s] = ru;
     3385                    }
     3386
     3387                    ru.attribs = at;
     3388
     3389                    if (ra)
     3390                        ru.requiredAttribs = ra;
     3391
     3392                    if (wat) {
     3393                        // Build valid attributes regexp
     3394                        s = '';
     3395                        each(va, function(v) {
     3396                            if (s)
     3397                                s += '|';
     3398
     3399                            s += '(' + wildcardToRE(v) + ')';
     3400                        });
     3401                        ru.validAttribsRE = new RegExp('^' + s.toLowerCase() + '$');
     3402                        ru.wildAttribs = wat;
     3403                    }
     3404                });
     3405            });
     3406
     3407            // Build valid elements regexp
     3408            s = '';
     3409            each(t.validElements, function(v, k) {
     3410                if (s)
     3411                    s += '|';
     3412
     3413                if (k != '@')
     3414                s += k;
     3415            });
     3416            t.validElementsRE = new RegExp('^(' + wildcardToRE(s.toLowerCase()) + ')$');
     3417
     3418            //console.debug(t.validElementsRE.toString());
     3419            //console.dir(t.rules);
     3420            //console.dir(t.wildRules);
     3421        },
     3422
     3423        findRule : function(n) {
     3424            var t = this, rl = t.rules, i, r;
     3425
     3426            t._setup();
     3427
     3428            // Exact match
     3429            r = rl[n];
     3430            if (r)
     3431                return r;
     3432
     3433            // Try wildcards
     3434            rl = t.wildRules;
     3435            for (i = 0; i < rl.length; i++) {
     3436                if (rl[i].nameRE.test(n))
     3437                    return rl[i];
     3438            }
     3439
     3440            return null;
     3441        },
     3442
     3443        findAttribRule : function(ru, n) {
     3444            var i, wa = ru.wildAttribs;
     3445
     3446            for (i = 0; i < wa.length; i++) {
     3447                if (wa[i].nameRE.test(n))
     3448                    return wa[i];
     3449            }
     3450
     3451            return null;
     3452        },
     3453
     3454        serialize : function(n, o) {
     3455            var h, t = this;
     3456
     3457            t._setup();
     3458            o = o || {};
     3459            o.format = o.format || 'html';
     3460            t.processObj = o;
     3461            n = n.cloneNode(true);
     3462            t.key = '' + (parseInt(t.key) + 1);
     3463
     3464            // Pre process
     3465            if (!o.no_events) {
     3466                o.node = n;
     3467                t.onPreProcess.dispatch(t, o);
     3468            }
     3469
     3470            // Serialize HTML DOM into a string
     3471            t.writer.reset();
     3472            t._serializeNode(n, o.getInner);
     3473
     3474            // Post process
     3475            o.content = t.writer.getContent();
     3476
     3477            if (!o.no_events)
     3478                t.onPostProcess.dispatch(t, o);
     3479
     3480            t._postProcess(o);
     3481            o.node = null;
     3482
     3483            return tinymce.trim(o.content);
     3484        },
     3485
     3486        // Internal functions
     3487
     3488        _postProcess : function(o) {
     3489            var t = this, s = t.settings, h = o.content, sc = [], p, l;
     3490
     3491            if (o.format == 'html') {
     3492                // Protect some elements
     3493                p = t._protect({
     3494                    content : h,
     3495                    patterns : [
     3496                        /(<script[^>]*>)(.*?)(<\/script>)/g,
     3497                        /(<style[^>]*>)(.*?)(<\/style>)/g,
     3498                        /(<pre[^>]*>)(.*?)(<\/pre>)/g
     3499                    ]
     3500                });
     3501
     3502                h = p.content;
     3503
     3504                // Entity encode
     3505                if (s.entity_encoding !== 'raw') {
     3506                    if (s.entity_encoding.indexOf('named') != -1) {
     3507                        t.setEntities(s.entities);
     3508                        l = t.entityLookup;
     3509
     3510                        h = h.replace(t.entitiesRE, function(a) {
     3511                            var v;
     3512
     3513                            if (v = l[a])
     3514                                a = '&' + v + ';';
     3515
     3516                            return a;
     3517                        });
     3518                    }
     3519
     3520                    if (s.entity_encoding.indexOf('numeric') != -1) {
     3521                        h = h.replace(/[\u007E-\uFFFF]/g, function(a) {
     3522                            return '&#' + a.charCodeAt(0) + ';';
     3523                        });
     3524                    }
     3525                }
     3526
     3527                // Use BR instead of &nbsp; padded P elements inside editor and use <p>&nbsp;</p> outside editor
     3528                if (o.set)
     3529                    h = h.replace(/<p>\s+(&nbsp;|&#160;|\u00a0|<br \/>)\s+<\/p>/g, '<p><br /></p>');
     3530                else
     3531                    h = h.replace(/<p>\s+(&nbsp;|&#160;|\u00a0|<br \/>)\s+<\/p>/g, '<p>$1</p>');
     3532
     3533                // Since Gecko and Safari keeps whitespace in the DOM we need to
     3534                // remove it inorder to match other browsers. But I think Gecko and Safari is right.
     3535                // This process is only done when getting contents out from the editor.
     3536                if (!o.set) {
     3537                    if (s.remove_linebreaks) {
     3538                        h = h.replace(/(<[^>]+>)\s+/g, '$1 ');
     3539                        h = h.replace(/\s+(<\/[^>]+>)/g, ' $1');
     3540                        h = h.replace(/<(p|h[1-6]|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object) ([^>]+)>\s+/g, '<$1 $2>'); // Trim block start
     3541                        h = h.replace(/<(p|h[1-6]|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object)>\s+/g, '<$1>'); // Trim block start
     3542                        h = h.replace(/\s+<\/(p|h[1-6]|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object)>/g, '</$1>'); // Trim block end
     3543                    }
     3544
     3545                    // Simple indentation
     3546                    if (s.apply_source_formatting && s.indent_mode == 'simple') {
     3547                        // Add line breaks before and after block elements
     3548                        h = h.replace(/<(\/?)(ul|hr|table|meta|link|tbody|tr|object|body|head|html)(|[^>]+)>\s*/g, '\n<$1$2$3>\n');
     3549                        h = h.replace(/\s*<(p|h[1-6]|div|title|style|pre|script|td|li)(|[^>]+)>/g, '\n<$1$2>');
     3550                        h = h.replace(/<\/(p|h[1-6]|div|title|style|pre|script|td|li)>\s*/g, '</$1>\n');
     3551                        h = h.replace(/\n\n/g, '\n');
     3552                    }
     3553                }
     3554
     3555                h = t._unprotect(h, p);
     3556            }
     3557
     3558            o.content = h;
     3559        },
     3560
     3561        _serializeNode : function(n, inn) {
     3562            var t = this, s = t.settings, w = t.writer, hc, el, cn, i, l, a, at, no, v, nn, ru, ar, iv;
     3563
     3564            if (!s.node_filter || s.node_filter(n)) {
     3565                switch (n.nodeType) {
     3566                    case 1: // Element
     3567                        if (n.hasAttribute ? n.hasAttribute('mce_bogus') : n.getAttribute('mce_bogus'))
     3568                            return;
     3569
     3570                        iv = false;
     3571                        hc = n.hasChildNodes();
     3572                        nn = n.getAttribute('mce_name') || n.nodeName.toLowerCase();
     3573
     3574                        // Add correct prefix on IE
     3575                        if (isIE) {
     3576                            if (n.scopeName !== 'HTML' && n.scopeName !== 'html')
     3577                                nn = n.scopeName + ':' + nn;
     3578                        }
     3579
     3580                        // Remove mce prefix on IE needed for the abbr element
     3581                        if (nn.indexOf('mce:') === 0)
     3582                            nn = nn.substring(4);
     3583
     3584                        // Check if valid
     3585                        if (!t.validElementsRE.test(nn) || (t.invalidElementsRE && t.invalidElementsRE.test(nn)) || inn) {
     3586                            iv = true;
     3587                            break;
     3588                        }
     3589
     3590                        if (isIE) {
     3591                            // Fix IE content duplication (DOM can have multiple copies of the same node)
     3592                            if (s.fix_content_duplication) {
     3593                                if (n.mce_serialized == t.key)
     3594                                    return;
     3595
     3596                                n.mce_serialized = t.key;
     3597                            }
     3598
     3599                            // IE sometimes adds a / infront of the node name
     3600                            if (nn.charAt(0) == '/')
     3601                                nn = nn.substring(1);
     3602                        }
     3603
     3604                        // Check if valid child
     3605                        if (t.childRules) {
     3606                            if (t.parentElementsRE.test(t.elementName)) {
     3607                                if (!t.childRules[t.elementName].test(nn)) {
     3608                                    iv = true;
     3609                                    break;
     3610                                }
     3611                            }
     3612
     3613                            t.elementName = nn;
     3614                        }
     3615
     3616                        ru = t.findRule(nn);
     3617                        nn = ru.name || nn;
     3618
     3619                        // Skip empty nodes or empty node name in IE
     3620                        if ((!hc && ru.noEmpty) || (isIE && !nn)) {
     3621                            iv = true;
     3622                            break;
     3623                        }
     3624
     3625                        // Check required
     3626                        if (ru.requiredAttribs) {
     3627                            a = ru.requiredAttribs;
     3628
     3629                            for (i = a.length - 1; i >= 0; i--) {
     3630                                if (this.dom.getAttrib(n, a[i]) !== '')
     3631                                    break;
     3632                            }
     3633
     3634                            // None of the required was there
     3635                            if (i == -1) {
     3636                                iv = true;
     3637                                break;
     3638                            }
     3639                        }
     3640
     3641                        w.writeStartElement(nn);
     3642
     3643                        // Add ordered attributes
     3644                        if (ru.attribs) {
     3645                            for (i=0, at = ru.attribs, l = at.length; i<l; i++) {
     3646                                a = at[i];
     3647                                v = t._getAttrib(n, a);
     3648
     3649                                if (v !== null)
     3650                                    w.writeAttribute(a.name, v);
     3651                            }
     3652                        }
     3653
     3654                        // Add wild attributes
     3655                        if (ru.validAttribsRE) {
     3656                            at = isIE ? getIEAtts(n) : n.attributes;
     3657                            for (i=at.length-1; i>-1; i--) {
     3658                                no = at[i];
     3659
     3660                                if (no.specified) {
     3661                                    a = no.nodeName.toLowerCase();
     3662
     3663                                    if (s.invalid_attrs.test(a) || !ru.validAttribsRE.test(a))
     3664                                        continue;
     3665
     3666                                    ar = t.findAttribRule(ru, a);
     3667                                    v = t._getAttrib(n, ar, a);
     3668
     3669                                    if (v !== null)
     3670                                        w.writeAttribute(a, v);
     3671                                }
     3672                            }
     3673                        }
     3674
     3675                        // Padd empty nodes with a &nbsp;
     3676                        if (!hc && ru.padd)
     3677                            w.writeText('\u00a0');
     3678
     3679                        break;
     3680
     3681                    case 3: // Text
     3682                        // Check if valid child
     3683                        if (t.childRules && t.parentElementsRE.test(t.elementName)) {
     3684                            if (!t.childRules[t.elementName].test(n.nodeName))
     3685                                return;
     3686                        }
     3687
     3688                        return w.writeText(n.nodeValue);
     3689
     3690                    case 4: // CDATA
     3691                        return w.writeCDATA(n.nodeValue);
     3692
     3693                    case 8: // Comment
     3694                        return w.writeComment(n.nodeValue);
     3695                }
     3696            } else if (n.nodeType == 1)
     3697                hc = n.hasChildNodes();
     3698
     3699            if (hc) {
     3700                cn = n.firstChild;
     3701
     3702                while (cn) {
     3703                    t._serializeNode(cn);
     3704                    t.elementName = nn;
     3705                    cn = cn.nextSibling;
     3706                }
     3707            }
     3708
     3709            // Write element end
     3710            if (!iv) {
     3711                if (hc || !s.closed.test(nn))
     3712                    w.writeFullEndElement();
     3713                else
     3714                    w.writeEndElement();
     3715            }
     3716        },
     3717
     3718        _protect : function(o) {
     3719            o.items = o.items || [];
     3720
     3721            function enc(s) {
     3722                return s.replace(/[\r\n]/g, function(c) {
     3723                    if (c === '\n')
     3724                        return '\\n';
     3725
     3726                    return '\\r';
     3727                });
     3728            };
     3729
     3730            function dec(s) {
     3731                return s.replace(/\\[rn]/g, function(c) {
     3732                    if (c === '\\n')
     3733                        return '\n';
     3734
     3735                    return '\r';
     3736                });
     3737            };
     3738
     3739            each(o.patterns, function(p) {
     3740                o.content = dec(enc(o.content).replace(p, function(x, a, b, c) {
     3741                    o.items.push(dec(b));
     3742                    return a + '<!--mce:' + (o.items.length - 1) + '-->' + c;
     3743                }));
     3744            });
     3745
     3746            return o;
     3747        },
     3748
     3749        _unprotect : function(h, o) {
     3750            h = h.replace(/\<!--mce:([0-9]+)--\>/g, function(a, b) {
     3751                return o.items[parseInt(b)];
     3752            });
     3753
     3754            o.items = [];
     3755
     3756            return h;
     3757        },
     3758
     3759        _setup : function() {
     3760            var t = this, s = this.settings;
     3761
     3762            if (t.done)
     3763                return;
     3764
     3765            t.done = 1;
     3766
     3767            t.setRules(s.valid_elements);
     3768            t.addRules(s.extended_valid_elements);
     3769            t.addValidChildRules(s.valid_child_elements);
     3770
     3771            if (s.invalid_elements)
     3772                t.invalidElementsRE = new RegExp('^(' + wildcardToRE(s.invalid_elements.replace(',', '|').toLowerCase()) + ')$');
     3773
     3774            if (s.attrib_value_filter)
     3775                t.attribValueFilter = s.attribValueFilter;
     3776        },
     3777
     3778        _getAttrib : function(n, a, na) {
     3779            var i, v;
     3780
     3781            na = na || a.name;
     3782
     3783            if (a.forcedVal && (v = a.forcedVal)) {
     3784                if (v === '{$uid}')
     3785                    return this.dom.uniqueId();
     3786
     3787                return v;
     3788            }
     3789
     3790            v = this.dom.getAttrib(n, na);
     3791
     3792            switch (na) {
     3793                case 'rowspan':
     3794                case 'colspan':
     3795                    // Whats the point? Remove usless attribute value
     3796                    if (v == '1')
     3797                        v = '';
     3798
     3799                    break;
     3800            }
     3801
     3802            if (this.attribValueFilter)
     3803                v = this.attribValueFilter(na, v, n);
     3804
     3805            if (a.validVals) {
     3806                for (i = a.validVals.length - 1; i >= 0; i--) {
     3807                    if (v == a.validVals[i])
     3808                        break;
     3809                }
     3810
     3811                if (i == -1)
     3812                    return null;
     3813            }
     3814
     3815            if (v === '' && typeof(a.defaultVal) != 'undefined') {
     3816                v = a.defaultVal;
     3817
     3818                if (v === '{$uid}')
     3819                    return this.dom.uniqueId();
     3820
     3821                return v;
     3822            } else {
     3823                // Remove internal mceItemXX classes when content is extracted from editor
     3824                if (na == 'class' && this.processObj.get)
     3825                    v = v.replace(/\bmceItem\w+\b/g, '');
     3826            }
     3827
     3828            if (v === '')
     3829                return null;
     3830
     3831
     3832            return v;
     3833        }
     3834
     3835        });
     3836})();
     3837
     3838/* file:jscripts/tiny_mce/classes/dom/ScriptLoader.js */
     3839
     3840(function() {
     3841    var each = tinymce.each;
     3842
     3843    tinymce.create('tinymce.dom.ScriptLoader', {
     3844        ScriptLoader : function(s) {
     3845            this.settings = s || {};
     3846            this.queue = [];
     3847            this.lookup = {};
     3848        },
     3849
     3850        markDone : function(u) {
     3851            this.lookup[u] = {state : 2, url : u};
     3852        },
     3853
     3854        add : function(u, cb, s, pr) {
     3855            var t = this, lo = t.lookup, o;
     3856
     3857            if (o = lo[u]) {
     3858                // Is loaded fire callback
     3859                if (cb && o.state == 2)
     3860                    cb.call(s || this);
     3861
     3862                return o;
     3863            }
     3864
     3865            o = {state : 0, url : u, func : cb, scope : s || this};
     3866
     3867            if (pr)
     3868                t.queue.unshift(o);
     3869            else
     3870                t.queue.push(o);
     3871
     3872            lo[u] = o;
     3873
     3874            return o;
     3875        },
     3876
     3877        load : function(u, cb, s) {
     3878            var o;
     3879
     3880            if (!tinymce.is(u, 'string')) {
     3881                o = [];
     3882
     3883                each(u, function(u) {
     3884                    o.push({state : 0, url : u});
     3885                });
     3886
     3887                this.loadScripts(o, cb, s);
     3888            } else
     3889                this.loadScripts([{state : 0, url : u}], cb, s);
     3890        },
     3891
     3892        loadQueue : function(cb, s) {
     3893            var t = this;
     3894
     3895            if (!t.queueLoading) {
     3896                t.queueLoading = 1;
     3897                t.queueCallbacks = [];
     3898
     3899                t.loadScripts(t.queue, function() {
     3900                    t.queueLoading = 0;
     3901
     3902                    if (cb)
     3903                        cb.call(s || t);
     3904
     3905                    each(t.queueCallbacks, function(o) {
     3906                        o.func.call(o.scope);
     3907                    });
     3908                });
     3909            } else if (cb)
     3910                t.queueCallbacks.push({func : cb, scope : s || t});
     3911        },
     3912
     3913        eval : function(co) {
     3914            var w = window;
     3915
     3916            // Evaluate script
     3917            if (!w.execScript) {
     3918                try {
     3919                    eval.call(w, co);
     3920                } catch (ex) {
     3921                    eval(co, w); // Firefox 3.0a8
     3922                }
     3923            } else
     3924                w.execScript(co); // IE
     3925        },
     3926
     3927        loadScripts : function(sc, cb, s) {
     3928            var t = this, lo = t.lookup;
     3929
     3930            function done(o) {
     3931                o.state = 2; // Has been loaded
     3932
     3933                // Run callback
     3934                if (o.func)
     3935                    o.func.call(o.scope || t);
     3936            };
     3937
     3938            function allDone() {
     3939                var l;
     3940
     3941                // Check if all files are loaded
     3942                l = sc.length;
     3943                each(sc, function(o) {
     3944                    o = lo[o.url];
     3945
     3946                    if (o.state === 2) {// It has finished loading
     3947                        done(o);
     3948                        l--;
     3949                    } else
     3950                        load(o);
     3951                });
     3952
     3953                // They are all loaded
     3954                if (l === 0 && cb) {
     3955                    cb.call(s || t);
     3956                    cb = 0;
     3957                }
     3958            };
     3959
     3960            function load(o) {
     3961                if (o.state > 0)
     3962                    return;
     3963
     3964                o.state = 1; // Is loading
     3965
     3966                tinymce.util.XHR.send({
     3967                    url : o.url,
     3968                    error : t.settings.error,
     3969                    success : function(co) {
     3970                        t.eval(co);
     3971                        done(o);
     3972                        allDone();
     3973                    }
     3974                });
     3975            };
     3976
     3977            each(sc, function(o) {
     3978                var u = o.url;
     3979
     3980                // Add to queue if needed
     3981                if (!lo[u]) {
     3982                    lo[u] = o;
     3983                    t.queue.push(o);
     3984                } else
     3985                    o = lo[u];
     3986
     3987                // Is already loading or has been loaded
     3988                if (o.state > 0)
     3989                    return;
     3990
     3991                if (!tinymce.dom.Event.domLoaded && !t.settings.strict_mode) {
     3992                    var ix, ol = '';
     3993
     3994                    // Add onload events
     3995                    if (cb || o.func) {
     3996                        o.state = 1; // Is loading
     3997
     3998                        ix = tinymce.dom.ScriptLoader._addOnLoad(function() {
     3999                            done(o);
     4000                            allDone();
     4001                        });
     4002
     4003                        if (tinymce.isIE)
     4004                            ol = ' onreadystatechange="';
     4005                        else
     4006                            ol = ' onload="';
     4007
     4008                        ol += 'tinymce.dom.ScriptLoader._onLoad(this,\'' + u + '\',' + ix + ');"';
     4009                    }
     4010
     4011                    document.write('<script type="text/javascript" src="' + u + '"' + ol + '></script>');
     4012
     4013                    if (!o.func)
     4014                        done(o);
     4015                } else
     4016                    load(o);
     4017            });
     4018
     4019            allDone();
     4020        },
     4021
     4022        // Static methods
     4023        'static' : {
     4024            _addOnLoad : function(f) {
     4025                var t = this;
     4026
     4027                t._funcs = t._funcs || [];
     4028                t._funcs.push(f);
     4029
     4030                return t._funcs.length - 1;
     4031            },
     4032
     4033            _onLoad : function(e, u, ix) {
     4034                if (!tinymce.isIE || e.readyState == 'complete')
     4035                    this._funcs[ix].call(this);
     4036            }
     4037        }
     4038
     4039        });
     4040
     4041    // Global script loader
     4042    tinymce.ScriptLoader = new tinymce.dom.ScriptLoader();
     4043})();
     4044
     4045/* file:jscripts/tiny_mce/classes/ui/Control.js */
     4046
     4047(function() {
     4048    // Shorten class names
     4049    var DOM = tinymce.DOM, is = tinymce.is;
     4050
     4051    tinymce.create('tinymce.ui.Control', {
     4052        Control : function(id, s) {
     4053            this.id = id;
     4054            this.settings = s = s || {};
     4055            this.rendered = false;
     4056            this.onRender = new tinymce.util.Dispatcher(this);
     4057            this.classPrefix = '';
     4058            this.scope = s.scope || this;
     4059            this.disabled = 0;
     4060            this.active = 0;
     4061        },
     4062
     4063        setDisabled : function(s) {
     4064            var e;
     4065
     4066            if (s != this.disabled) {
     4067                e = DOM.get(this.id);
     4068
     4069                // Add accessibility title for unavailable actions
     4070                if (e && this.settings.unavailable_prefix) {
     4071                    if (s) {
     4072                        this.prevTitle = e.title;
     4073                        e.title = this.settings.unavailable_prefix + ": " + e.title;
     4074                    } else
     4075                        e.title = this.prevTitle;
     4076                }
     4077
     4078                this.setState('Disabled', s);
     4079                this.setState('Enabled', !s);
     4080                this.disabled = s;
     4081            }
     4082        },
     4083
     4084        isDisabled : function() {
     4085            return this.disabled;
     4086        },
     4087
     4088        setActive : function(s) {
     4089            if (s != this.active) {
     4090                this.setState('Active', s);
     4091                this.active = s;
     4092            }
     4093        },
     4094
     4095        isActive : function() {
     4096            return this.active;
     4097        },
     4098
     4099        setState : function(c, s) {
     4100            var n = DOM.get(this.id);
     4101
     4102            c = this.classPrefix + c;
     4103
     4104            if (s)
     4105                DOM.addClass(n, c);
     4106            else
     4107                DOM.removeClass(n, c);
     4108        },
     4109
     4110        isRendered : function() {
     4111            return this.rendered;
     4112        },
     4113
     4114        renderHTML : function() {
     4115        },
     4116
     4117        renderTo : function(n) {
     4118            n.innerHTML = this.renderHTML();
     4119        },
     4120
     4121        postRender : function() {
     4122            var t = this, b;
     4123
     4124            // Set pending states
     4125            if (is(t.disabled)) {
     4126                b = t.disabled;
     4127                t.disabled = -1;
     4128                t.setDisabled(b);
     4129            }
     4130
     4131            if (is(t.active)) {
     4132                b = t.active;
     4133                t.active = -1;
     4134                t.setActive(b);
     4135            }
     4136        },
     4137
     4138        destroy : function() {
     4139            DOM.remove(this.id);
     4140        }
     4141
     4142        });
     4143})();
     4144/* file:jscripts/tiny_mce/classes/ui/Container.js */
     4145
     4146tinymce.create('tinymce.ui.Container:tinymce.ui.Control', {
     4147    Container : function(id, s) {
     4148        this.parent(id, s);
     4149        this.controls = [];
     4150        this.lookup = {};
    64434151    },
    64444152
    6445     moveToBookmark : function(bookmark) {
    6446         var inst = this.instance, rng, nl, i, ex, b = inst.getBody(), sd;
    6447         var doc = inst.getDoc(), win = inst.getWin(), sel = this.getSel();
    6448 
    6449         if (!bookmark)
     4153    add : function(c) {
     4154        this.lookup[c.id] = c;
     4155        this.controls.push(c);
     4156
     4157        return c;
     4158    },
     4159
     4160    get : function(n) {
     4161        return this.lookup[n];
     4162    }
     4163
     4164    });
     4165
     4166
     4167/* file:jscripts/tiny_mce/classes/ui/Separator.js */
     4168
     4169tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
     4170    renderHTML : function() {
     4171        return tinymce.DOM.createHTML('span', {'class' : 'mceSeparator'});
     4172    }
     4173
     4174    });
     4175
     4176/* file:jscripts/tiny_mce/classes/ui/MenuItem.js */
     4177
     4178(function() {
     4179    var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk;
     4180
     4181    tinymce.create('tinymce.ui.MenuItem:tinymce.ui.Control', {
     4182        MenuItem : function(id, s) {
     4183            this.parent(id, s);
     4184            this.classPrefix = 'mceMenuItem';
     4185        },
     4186
     4187        setSelected : function(s) {
     4188            this.setState('Selected', s);
     4189            this.selected = s;
     4190        },
     4191
     4192        isSelected : function() {
     4193            return this.selected;
     4194        },
     4195
     4196        postRender : function() {
     4197            var t = this;
     4198           
     4199            t.parent();
     4200
     4201            // Set pending state
     4202            if (is(t.selected))
     4203                t.setSelected(t.selected);
     4204        }
     4205
     4206        });
     4207})();
     4208
     4209/* file:jscripts/tiny_mce/classes/ui/Menu.js */
     4210
     4211(function() {
     4212    var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk;
     4213
     4214    tinymce.create('tinymce.ui.Menu:tinymce.ui.MenuItem', {
     4215        Menu : function(id, s) {
     4216            var t = this;
     4217
     4218            t.parent(id, s);
     4219            t.items = {};
     4220            t.collapsed = false;
     4221            t.menuCount = 0;
     4222            t.onAddItem = new tinymce.util.Dispatcher(this);
     4223        },
     4224
     4225        expand : function(d) {
     4226            var t = this;
     4227
     4228            if (d) {
     4229                walk(t, function(o) {
     4230                    if (o.expand)
     4231                        o.expand();
     4232                }, 'items', t);
     4233            }
     4234
     4235            t.collapsed = false;
     4236        },
     4237
     4238        collapse : function(d) {
     4239            var t = this;
     4240
     4241            if (d) {
     4242                walk(t, function(o) {
     4243                    if (o.collapse)
     4244                        o.collapse();
     4245                }, 'items', t);
     4246            }
     4247
     4248            t.collapsed = true;
     4249        },
     4250
     4251        isCollapsed : function() {
     4252            return this.collapsed;
     4253        },
     4254
     4255        add : function(o) {
     4256            if (!o.settings)
     4257                o = new tinymce.ui.MenuItem(o.id || DOM.uniqueId(), o);
     4258
     4259            this.onAddItem.dispatch(this, o);
     4260
     4261            return this.items[o.id] = o;
     4262        },
     4263
     4264        addSeparator : function() {
     4265            return this.add({separator : true});
     4266        },
     4267
     4268        addMenu : function(o) {
     4269            if (!o.collapse)
     4270                o = this.createMenu(o);
     4271
     4272            this.menuCount++;
     4273
     4274            return this.add(o);
     4275        },
     4276
     4277        hasMenus : function() {
     4278            return this.menuCount !== 0;
     4279        },
     4280
     4281        remove : function(o) {
     4282            delete this.items[o.id];
     4283        },
     4284
     4285        removeAll : function() {
     4286            var t = this;
     4287
     4288            walk(t, function(o) {
     4289                if (o.removeAll)
     4290                    o.removeAll();
     4291
     4292                o.destroy();
     4293            }, 'items', t);
     4294
     4295            t.items = {};
     4296        },
     4297
     4298        createMenu : function(o) {
     4299            var m = new tinymce.ui.Menu(o.id || DOM.uniqueId(), o);
     4300
     4301            m.onAddItem.add(this.onAddItem.dispatch, this.onAddItem);
     4302
     4303            return m;
     4304        }
     4305
     4306        });
     4307})();
     4308/* file:jscripts/tiny_mce/classes/ui/DropMenu.js */
     4309
     4310(function() {
     4311    var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, Event = tinymce.dom.Event, Element = tinymce.dom.Element;
     4312
     4313    tinymce.create('tinymce.ui.DropMenu:tinymce.ui.Menu', {
     4314        DropMenu : function(id, s) {
     4315            s = s || {};
     4316            s.container = s.container || document.body;
     4317            s.offset_x = s.offset_x || 0;
     4318            s.offset_y = s.offset_y || 0;
     4319            s.vp_offset_x = s.vp_offset_x || 0;
     4320            s.vp_offset_y = s.vp_offset_y || 0;
     4321            this.parent(id, s);
     4322            this.onHideMenu = new tinymce.util.Dispatcher(this);
     4323            this.classPrefix = 'mceMenu';
     4324        },
     4325
     4326        createMenu : function(s) {
     4327            var t = this, cs = t.settings, m;
     4328
     4329            s.container = s.container || cs.container;
     4330            s.parent = t;
     4331            s.constrain = s.constrain || cs.constrain;
     4332            s['class'] = s['class'] || cs['class'];
     4333            s.vp_offset_x = s.vp_offset_x || cs.vp_offset_x;
     4334            s.vp_offset_y = s.vp_offset_y || cs.vp_offset_y;
     4335            m = new tinymce.ui.DropMenu(s.id || DOM.uniqueId(), s);
     4336
     4337            m.onAddItem.add(t.onAddItem.dispatch, t.onAddItem);
     4338
     4339            return m;
     4340        },
     4341
     4342        update : function() {
     4343            var t = this, s = t.settings, tb = DOM.get('menu_' + t.id + '_tbl'), co = DOM.get('menu_' + t.id + '_co'), tw, th;
     4344
     4345            tw = s.max_width ? Math.min(tb.clientWidth, s.max_width) : tb.clientWidth;
     4346            th = s.max_height ? Math.min(tb.clientHeight, s.max_height) : tb.clientHeight;
     4347
     4348            if (!DOM.boxModel)
     4349                t.element.setStyles({width : tw + 2, height : th + 2});
     4350            else
     4351                t.element.setStyles({width : tw, height : th});
     4352
     4353            if (s.max_width)
     4354                DOM.setStyle(co, 'width', tw);
     4355
     4356            if (s.max_height) {
     4357                DOM.setStyle(co, 'height', th);
     4358
     4359                if (tb.clientHeight < s.max_height)
     4360                    DOM.setStyle(co, 'overflow', 'hidden');
     4361            }
     4362        },
     4363
     4364        showMenu : function(x, y, px) {
     4365            var t = this, s = t.settings, co, vp = DOM.getViewPort(), w, h, mx, my, ot = 2, dm, tb;
     4366
     4367            t.collapse(1);
     4368
     4369            if (t.isMenuVisible)
     4370                return;
     4371
     4372            if (!t.rendered) {
     4373                co = DOM.add(t.settings.container, t.renderNode());
     4374
     4375                each(t.items, function(o) {
     4376                    o.postRender();
     4377                });
     4378
     4379                t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container});
     4380            } else
     4381                co = DOM.get('menu_' + t.id);
     4382
     4383            DOM.setStyles(co, {left : -0xFFFF , top : -0xFFFF});
     4384            DOM.show(co);
     4385            t.update();
     4386
     4387            x += s.offset_x || 0;
     4388            y += s.offset_y || 0;
     4389            vp.w -= 4;
     4390            vp.h -= 4;
     4391
     4392            // Move inside viewport if not submenu
     4393            if (s.constrain) {
     4394                w = co.clientWidth - ot;
     4395                h = co.clientHeight - ot;
     4396                mx = vp.x + vp.w;
     4397                my = vp.y + vp.h;
     4398
     4399                if ((x + s.vp_offset_x + w) > mx)
     4400                    x = px ? px - w : Math.max(0, (mx - s.vp_offset_x) - w);
     4401
     4402                if ((y + s.vp_offset_y + h) > my)
     4403                    y = Math.max(0, (my - s.vp_offset_y) - h);
     4404            }
     4405
     4406            DOM.setStyles(co, {left : x , top : y});
     4407            t.element.update();
     4408
     4409            t.isMenuVisible = 1;
     4410            t.mouseClickFunc = Event.add(co, 'click', function(e) {
     4411                var m;
     4412
     4413                e = e.target;
     4414
     4415                if (e && (e = DOM.getParent(e, 'TR')) && !DOM.hasClass(e, 'mceMenuItemSub')) {
     4416                    m = t.items[e.id];
     4417
     4418                    if (m.isDisabled())
     4419                        return;
     4420
     4421                    if (m.settings.onclick)
     4422                        m.settings.onclick(e);
     4423
     4424                    dm = t;
     4425
     4426                    while (dm) {
     4427                        if (dm.hideMenu)
     4428                            dm.hideMenu();
     4429
     4430                        dm = dm.settings.parent;
     4431                    }
     4432
     4433                    return Event.cancel(e); // Cancel to fix onbeforeunload problem
     4434                }
     4435            });
     4436
     4437            if (t.hasMenus()) {
     4438                t.mouseOverFunc = Event.add(co, 'mouseover', function(e) {
     4439                    var m, r, mi;
     4440
     4441                    e = e.target;
     4442                    if (e && (e = DOM.getParent(e, 'TR'))) {
     4443                        m = t.items[e.id];
     4444
     4445                        if (t.lastMenu)
     4446                            t.lastMenu.collapse(1);
     4447
     4448                        if (m.isDisabled())
     4449                            return;
     4450
     4451                        if (e && DOM.hasClass(e, 'mceMenuItemSub')) {
     4452                            //p = DOM.getPos(s.container);
     4453                            r = DOM.getRect(e);
     4454                            m.showMenu((r.x + r.w - ot), r.y - ot, r.x);
     4455                            t.lastMenu = m;
     4456                            DOM.addClass(DOM.get(m.id).firstChild, 'mceMenuItemActive');
     4457                        }
     4458                    }
     4459                });
     4460            }
     4461        },
     4462
     4463        hideMenu : function() {
     4464            var t = this, co = DOM.get('menu_' + t.id), e;
     4465
     4466            if (!t.isMenuVisible)
     4467                return;
     4468
     4469            Event.remove(co, 'mouseover', t.mouseOverFunc);
     4470            Event.remove(co, 'click', t.mouseClickFunc);
     4471            DOM.hide(co);
     4472            t.isMenuVisible = 0;
     4473
     4474            if (t.element)
     4475                t.element.hide();
     4476
     4477            if (e = DOM.get(t.id))
     4478                DOM.removeClass(e.firstChild, 'mceMenuItemActive');
     4479
     4480            t.onHideMenu.dispatch(t);
     4481        },
     4482
     4483        add : function(o) {
     4484            var t = this, co;
     4485
     4486            o = t.parent(o);
     4487
     4488            if (t.isRendered && (co = DOM.get('menu_' + t.id)))
     4489                t._add(DOM.select('tbody', co)[0], o);
     4490
     4491            return o;
     4492        },
     4493
     4494        collapse : function(d) {
     4495            this.parent(d);
     4496            this.hideMenu();
     4497        },
     4498
     4499        remove : function(o) {
     4500            DOM.remove(o.id);
     4501
     4502            return this.parent(o);
     4503        },
     4504
     4505        destroy : function() {
     4506            var t = this, co = DOM.get('menu_' + t.id);
     4507
     4508            Event.remove(co, 'mouseover', t.mouseOverFunc);
     4509            Event.remove(co, 'click', t.mouseClickFunc);
     4510
     4511            if (t.element)
     4512                t.element.remove();
     4513
     4514            DOM.remove(co);
     4515        },
     4516
     4517        renderNode : function() {
     4518            var t = this, s = t.settings, n, tb, co, w;
     4519
     4520            w = DOM.create('div', {id : 'menu_' + t.id, 'class' : s['class'], 'style' : 'position:absolute;left:0;top:0;z-index:150'});
     4521            co = DOM.add(w, 'div', {id : 'menu_' + t.id + '_co', 'class' : 'mceMenu' + (s['class'] ? ' ' + s['class'] : '')});
     4522            t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container});
     4523
     4524            if (s.menu_line)
     4525                DOM.add(co, 'span', {'class' : 'mceMenuLine'});
     4526
     4527//          n = DOM.add(co, 'div', {id : 'menu_' + t.id + '_co', 'class' : 'mceMenuContainer'});
     4528            n = DOM.add(co, 'table', {id : 'menu_' + t.id + '_tbl', border : 0, cellPadding : 0, cellSpacing : 0});
     4529            tb = DOM.add(n, 'tbody');
     4530
     4531            each(t.items, function(o) {
     4532                t._add(tb, o);
     4533            });
     4534
     4535            t.rendered = true;
     4536
     4537            return w;
     4538        },
     4539
     4540        // Internal functions
     4541
     4542        _add : function(tb, o) {
     4543            var n, s = o.settings, a, ro, it;
     4544
     4545            if (s.separator) {
     4546                ro = DOM.add(tb, 'tr', {id : o.id, 'class' : 'mceMenuItemSeparator'});
     4547                DOM.add(ro, 'td', {'class' : 'mceMenuItemSeparator'});
     4548
     4549                if (n = ro.previousSibling)
     4550                    DOM.addClass(n, 'last');
     4551
     4552                return;
     4553            }
     4554
     4555            n = ro = DOM.add(tb, 'tr', {id : o.id, 'class' : 'mceMenuItem mceMenuItemEnabled'});
     4556            n = it = DOM.add(n, 'td');
     4557            n = a = DOM.add(n, 'a', {href : 'javascript:;', onclick : "return false;", onmousedown : 'return false;'});
     4558
     4559            DOM.addClass(it, s['class']);
     4560//          n = DOM.add(n, 'span', {'class' : 'item'});
     4561            DOM.add(n, 'span', {'class' : 'icon' + (s.icon ? ' ' + s.icon : '')});
     4562            n = DOM.add(n, s.element || 'span', {'class' : 'text', title : o.settings.title}, o.settings.title);
     4563
     4564            if (o.settings.style)
     4565                DOM.setAttrib(n, 'style', o.settings.style);
     4566
     4567            if (tb.childNodes.length == 1)
     4568                DOM.addClass(ro, 'first');
     4569
     4570            if ((n = ro.previousSibling) && DOM.hasClass(n, 'mceMenuItemSeparator'))
     4571                DOM.addClass(ro, 'first');
     4572
     4573            if (o.collapse)
     4574                DOM.addClass(ro, 'mceMenuItemSub');
     4575
     4576            if (n = ro.previousSibling)
     4577                DOM.removeClass(n, 'last');
     4578
     4579            DOM.addClass(ro, 'last');
     4580        }
     4581
     4582        });
     4583})();
     4584/* file:jscripts/tiny_mce/classes/ui/Button.js */
     4585
     4586(function() {
     4587    var DOM = tinymce.DOM;
     4588
     4589    tinymce.create('tinymce.ui.Button:tinymce.ui.Control', {
     4590        Button : function(id, s) {
     4591            this.parent(id, s);
     4592            this.classPrefix = 'mceButton';
     4593        },
     4594
     4595        renderHTML : function() {
     4596            var s = this.settings, h = '<a id="' + this.id + '" href="javascript:;" class="mceButton mceButtonEnabled ' + s['class'] + '" onmousedown="return false;" onclick="return false;" title="' + DOM.encode(s.title) + '">';
     4597
     4598            if (s.image)
     4599                h += '<img class="icon" src="' + s.image + '" /></a>';
     4600            else
     4601                h += '<span class="icon ' + s['class'] + '"></span></a>';
     4602
     4603            return h;
     4604        },
     4605
     4606        postRender : function() {
     4607            var t = this, s = t.settings;
     4608
     4609            tinymce.dom.Event.add(t.id, 'click', function(e) {
     4610                if (!t.isDisabled())
     4611                    return s.onclick.call(s.scope, e);
     4612            });
     4613        }
     4614
     4615        });
     4616})();
     4617
     4618/* file:jscripts/tiny_mce/classes/ui/ListBox.js */
     4619
     4620(function() {
     4621    var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher;
     4622
     4623    tinymce.create('tinymce.ui.ListBox:tinymce.ui.Control', {
     4624        ListBox : function(id, s) {
     4625            var t = this;
     4626
     4627            t.parent(id, s);
     4628            t.items = [];
     4629            t.onChange = new Dispatcher(t);
     4630            t.onPostRender = new Dispatcher(t);
     4631            t.onAdd = new Dispatcher(t);
     4632            t.onRenderMenu = new tinymce.util.Dispatcher(this);
     4633            t.classPrefix = 'mceListBox';
     4634        },
     4635
     4636        select : function(v) {
     4637            var t = this, e, fv;
     4638
     4639            // Do we need to do something?
     4640            if (v != t.selectedValue) {
     4641                e = DOM.get(t.id + '_text');
     4642                t.selectedValue = v;
     4643
     4644                // Find item
     4645                each(t.items, function(o) {
     4646                    if (o.value == v) {
     4647                        DOM.setHTML(e, DOM.encode(o.title));
     4648                        fv = 1;
     4649                        return false;
     4650                    }
     4651                });
     4652
     4653                // If no item was found then present title
     4654                if (!fv) {
     4655                    DOM.setHTML(e, DOM.encode(t.settings.title));
     4656                    DOM.addClass(e, 'title');
     4657                    e = 0;
     4658                    return;
     4659                } else
     4660                    DOM.removeClass(e, 'title');
     4661            }
     4662
     4663            e = 0;
     4664        },
     4665
     4666        add : function(n, v, o) {
     4667            var t = this;
     4668
     4669            o = o || {};
     4670            o = tinymce.extend(o, {
     4671                title : n,
     4672                value : v
     4673            });
     4674
     4675            t.items.push(o);
     4676            t.onAdd.dispatch(t, o);
     4677        },
     4678
     4679        getLength : function() {
     4680            return this.items.length;
     4681        },
     4682
     4683        renderHTML : function() {
     4684            var h = '', t = this, s = t.settings;
     4685
     4686            h = '<table id="' + t.id + '" cellpadding="0" cellspacing="0" class="mceListBox mceListBoxEnabled' + (s['class'] ? (' ' + s['class']) : '') + '"><tbody><tr>';
     4687            h += '<td>' + DOM.createHTML('a', {id : t.id + '_text', href : 'javascript:;', 'class' : 'text', onclick : "return false;", onmousedown : 'return false;'}, DOM.encode(t.settings.title)) + '</td>';
     4688            h += '<td>' + DOM.createHTML('a', {id : t.id + '_open', href : 'javascript:;', 'class' : 'open', onclick : "return false;", onmousedown : 'return false;'}, '<span></span>') + '</td>';
     4689            h += '</tr></tbody></table>';
     4690
     4691            return h;
     4692        },
     4693
     4694        showMenu : function() {
     4695            var t = this, p1, p2, e = DOM.get(this.id), m;
     4696
     4697            if (t.isDisabled() || t.items.length == 0)
     4698                return;
     4699
     4700            if (!t.isMenuRendered) {
     4701                t.renderMenu();
     4702                t.isMenuRendered = true;
     4703            }
     4704
     4705            p1 = DOM.getPos(this.settings.menu_container);
     4706            p2 = DOM.getPos(e);
     4707
     4708            m = t.menu;
     4709            m.settings.offset_x = p2.x;
     4710            m.settings.offset_y = p2.y;
     4711
     4712            // Select in menu
     4713            if (t.oldID)
     4714                m.items[t.oldID].setSelected(0);
     4715
     4716            each(t.items, function(o) {
     4717                if (o.value === t.selectedValue) {
     4718                    m.items[o.id].setSelected(1);
     4719                    t.oldID = o.id;
     4720                }
     4721            });
     4722
     4723            m.showMenu(0, e.clientHeight);
     4724
     4725            Event.add(document, 'mousedown', t.hideMenu, t);
     4726            DOM.addClass(t.id, 'mceListBoxSelected');
     4727        },
     4728
     4729        hideMenu : function(e) {
     4730            var t = this;
     4731
     4732            if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceMenu');})) {
     4733                DOM.removeClass(t.id, 'mceListBoxSelected');
     4734                Event.remove(document, 'mousedown', t.hideMenu, t);
     4735
     4736                if (t.menu)
     4737                    t.menu.hideMenu();
     4738            }
     4739        },
     4740
     4741        renderMenu : function() {
     4742            var t = this, m;
     4743
     4744            m = t.settings.control_manager.createDropMenu(t.id + '_menu', {
     4745                menu_line : 1,
     4746                'class' : 'mceListBoxMenu noIcons',
     4747                max_width : 150,
     4748                max_height : 150
     4749            });
     4750
     4751            m.onHideMenu.add(t.hideMenu, t);
     4752
     4753            m.add({
     4754                title : t.settings.title,
     4755                'class' : 'mceMenuItemTitle'
     4756            }).setDisabled(1);
     4757
     4758            each(t.items, function(o) {
     4759                o.id = DOM.uniqueId();
     4760                o.onclick = function() {
     4761                    if (t.settings.onselect(o.value) !== false)
     4762                        t.select(o.value); // Must be runned after
     4763                };
     4764
     4765                m.add(o);
     4766            });
     4767
     4768            t.onRenderMenu.dispatch(t, m);
     4769            t.menu = m;
     4770        },
     4771
     4772        postRender : function() {
     4773            var t = this;
     4774
     4775            Event.add(t.id, 'click', t.showMenu, t);
     4776
     4777            // Old IE doesn't have hover on all elements
     4778            if (tinymce.isIE6 || !DOM.boxModel) {
     4779                Event.add(t.id, 'mouseover', function() {
     4780                    if (!DOM.hasClass(t.id, 'mceListBoxDisabled'))
     4781                        DOM.addClass(t.id, 'mceListBoxHover');
     4782                });
     4783
     4784                Event.add(t.id, 'mouseout', function() {
     4785                    if (!DOM.hasClass(t.id, 'mceListBoxDisabled'))
     4786                        DOM.removeClass(t.id, 'mceListBoxHover');
     4787                });
     4788            }
     4789
     4790            t.onPostRender.dispatch(t, DOM.get(t.id));
     4791        }
     4792
     4793        });
     4794})();
     4795/* file:jscripts/tiny_mce/classes/ui/NativeListBox.js */
     4796
     4797(function() {
     4798    var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher;
     4799
     4800    tinymce.create('tinymce.ui.NativeListBox:tinymce.ui.ListBox', {
     4801        NativeListBox : function(id, s) {
     4802            this.parent(id, s);
     4803            this.classPrefix = 'mceNativeListBox';
     4804        },
     4805
     4806        setDisabled : function(s) {
     4807            DOM.get(this.id).disabled = s;
     4808        },
     4809
     4810        isDisabled : function() {
     4811            return DOM.get(this.id).disabled;
     4812        },
     4813
     4814        select : function(v) {
     4815            var e = DOM.get(this.id), ol = e.options;
     4816
     4817            v = '' + (v || '');
     4818
     4819            e.selectedIndex = 0;
     4820            each(ol, function(o, i) {
     4821                if (o.value == v) {
     4822                    e.selectedIndex = i;
     4823                    return false;
     4824                }
     4825            });
     4826        },
     4827
     4828        add : function(n, v, a) {
     4829            var o, t = this;
     4830
     4831            a = a || {};
     4832            a.value = v;
     4833
     4834            if (t.isRendered())
     4835                DOM.add(DOM.get(this.id), 'option', a, n);
     4836
     4837            o = {
     4838                title : n,
     4839                value : v,
     4840                attribs : a
     4841            };
     4842
     4843            t.items.push(o);
     4844            t.onAdd.dispatch(t, o);
     4845        },
     4846
     4847        getLength : function() {
     4848            return DOM.get(this.id).options.length - 1;
     4849        },
     4850
     4851        renderHTML : function() {
     4852            var h, t = this;
     4853
     4854            h = DOM.createHTML('option', {value : ''}, '-- ' + t.settings.title + ' --');
     4855
     4856            each(t.items, function(it) {
     4857                h += DOM.createHTML('option', {value : it.value}, it.title);
     4858            });
     4859
     4860            h = DOM.createHTML('select', {id : t.id, 'class' : 'mceNativeListBox'}, h);
     4861
     4862            return h;
     4863        },
     4864
     4865        postRender : function() {
     4866            var t = this, ch;
     4867
     4868            t.rendered = true;
     4869
     4870            function onChange(e) {
     4871                var v = e.target.options[e.target.selectedIndex].value;
     4872
     4873                t.onChange.dispatch(t, v);
     4874
     4875                if (t.settings.onselect)
     4876                    t.settings.onselect(v);
     4877            };
     4878
     4879            Event.add(t.id, 'change', onChange);
     4880
     4881            // Accessibility keyhandler
     4882            Event.add(t.id, 'keydown', function(e) {
     4883                var bf;
     4884
     4885                Event.remove(t.id, 'change', ch);
     4886
     4887                bf = Event.add(t.id, 'blur', function() {
     4888                    Event.add(t.id, 'change', onChange);
     4889                    Event.remove(t.id, 'blur', bf);
     4890                });
     4891
     4892                if (e.keyCode == 13 || e.keyCode == 32) {
     4893                    onChange(e);
     4894                    return Event.cancel(e);
     4895                }
     4896            });
     4897
     4898            t.onPostRender.dispatch(t, DOM.get(t.id));
     4899        }
     4900
     4901        });
     4902})();
     4903/* file:jscripts/tiny_mce/classes/ui/MenuButton.js */
     4904
     4905(function() {
     4906    var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each;
     4907
     4908    tinymce.create('tinymce.ui.MenuButton:tinymce.ui.Button', {
     4909        MenuButton : function(id, s) {
     4910            this.parent(id, s);
     4911            this.onRenderMenu = new tinymce.util.Dispatcher(this);
     4912            s.menu_container = s.menu_container || document.body;
     4913        },
     4914
     4915        showMenu : function() {
     4916            var t = this, p1, p2, e = DOM.get(t.id), m;
     4917
     4918            if (t.isDisabled())
     4919                return;
     4920
     4921            if (!t.isMenuRendered) {
     4922                t.renderMenu();
     4923                t.isMenuRendered = true;
     4924            }
     4925
     4926            p1 = DOM.getPos(t.settings.menu_container);
     4927            p2 = DOM.getPos(e);
     4928
     4929            m = t.menu;
     4930            m.settings.offset_x = p2.x;
     4931            m.settings.offset_y = p2.y;
     4932            m.settings.vp_offset_x = p2.x;
     4933            m.settings.vp_offset_y = p2.y;
     4934            m.showMenu(0, e.clientHeight);
     4935
     4936            Event.add(document, 'mousedown', t.hideMenu, t);
     4937            t.setState('Selected', 1);
     4938        },
     4939
     4940        renderMenu : function() {
     4941            var t = this, m;
     4942
     4943            m = t.settings.control_manager.createDropMenu(t.id + '_menu', {
     4944                menu_line : 1,
     4945                'class' : this.classPrefix + 'Menu'
     4946            });
     4947
     4948            m.onHideMenu.add(t.hideMenu, t);
     4949
     4950            t.onRenderMenu.dispatch(t, m);
     4951            t.menu = m;
     4952        },
     4953
     4954        hideMenu : function(e) {
     4955            var t = this;
     4956
     4957            if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceMenu');})) {
     4958                t.setState('Selected', 0);
     4959                Event.remove(document, 'mousedown', t.hideMenu, t);
     4960                if (t.menu)
     4961                    t.menu.hideMenu();
     4962            }
     4963        },
     4964
     4965        postRender : function() {
     4966            var t = this, s = t.settings;
     4967
     4968            Event.add(t.id, 'click', function() {
     4969                if (!t.isDisabled()) {
     4970                    if (s.onclick)
     4971                        s.onclick(t.value);
     4972
     4973                    t.showMenu();
     4974                }
     4975            });
     4976        }
     4977
     4978        });
     4979})();
     4980
     4981/* file:jscripts/tiny_mce/classes/ui/SplitButton.js */
     4982
     4983(function() {
     4984    var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each;
     4985
     4986    tinymce.create('tinymce.ui.SplitButton:tinymce.ui.MenuButton', {
     4987        SplitButton : function(id, s) {
     4988            this.parent(id, s);
     4989            this.classPrefix = 'mceSplitButton';
     4990        },
     4991
     4992        renderHTML : function() {
     4993            var h, t = this, s = t.settings, h1;
     4994
     4995            h = '<tbody><tr>';
     4996
     4997            if (s.image)
     4998                h1 = DOM.createHTML('img ', {src : s.image, 'class' : 'action ' + s['class']});
     4999            else
     5000                h1 = DOM.createHTML('span', {'class' : 'action ' + s['class']});
     5001
     5002            h += '<td>' + DOM.createHTML('a', {id : t.id + '_action', href : 'javascript:;', 'class' : 'action ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + '</td>';
     5003   
     5004            h1 = DOM.createHTML('span', {'class' : 'open ' + s['class']});
     5005            h += '<td>' + DOM.createHTML('a', {id : t.id + '_open', href : 'javascript:;', 'class' : 'open ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + '</td>';
     5006
     5007            h += '</tr></tbody>';
     5008
     5009            return DOM.createHTML('table', {id : t.id, 'class' : 'mceSplitButton mceSplitButtonEnabled ' + s['class'], cellpadding : '0', cellspacing : '0', onmousedown : 'return false;', title : s.title}, h);
     5010        },
     5011
     5012        postRender : function() {
     5013            var t = this, s = t.settings;
     5014
     5015            if (s.onclick) {
     5016                Event.add(t.id + '_action', 'click', function() {
     5017                    if (!t.isDisabled())
     5018                        s.onclick(t.value);
     5019                });
     5020            }
     5021
     5022            Event.add(t.id + '_open', 'click', t.showMenu, t);
     5023
     5024            // Old IE doesn't have hover on all elements
     5025            if (tinymce.isIE6 || !DOM.boxModel) {
     5026                Event.add(t.id, 'mouseover', function() {
     5027                    if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled'))
     5028                        DOM.addClass(t.id, 'mceSplitButtonHover');
     5029                });
     5030
     5031                Event.add(t.id, 'mouseout', function() {
     5032                    if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled'))
     5033                        DOM.removeClass(t.id, 'mceSplitButtonHover');
     5034                });
     5035            }
     5036        }
     5037
     5038        });
     5039})();
     5040
     5041/* file:jscripts/tiny_mce/classes/ui/ColorSplitButton.js */
     5042
     5043(function() {
     5044    var DOM = tinymce.DOM, Event = tinymce.dom.Event, is = tinymce.is, each = tinymce.each;
     5045
     5046    tinymce.create('tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton', {
     5047        ColorSplitButton : function(id, s) {
     5048            var t = this;
     5049
     5050            t.parent(id, s);
     5051
     5052            t.settings = s = tinymce.extend({
     5053                colors : '000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF',
     5054                grid_width : 8,
     5055                default_color : '#888888'
     5056            }, t.settings);
     5057
     5058            t.value = s.default_color;
     5059        },
     5060
     5061        showMenu : function() {
     5062            var t = this, r, p, e;
     5063
     5064            if (t.isDisabled())
     5065                return;
     5066
     5067            if (!t.isMenuRendered) {
     5068                t.renderMenu();
     5069                t.isMenuRendered = true;
     5070            }
     5071
     5072            e = DOM.get(t.id);
     5073            DOM.show(t.id + '_menu');
     5074            DOM.addClass(e, 'mceSplitButtonSelected');
     5075            p2 = DOM.getPos(e);
     5076            DOM.setStyles(t.id + '_menu', {
     5077                left : p2.x,
     5078                top : p2.y + e.clientHeight,
     5079                zIndex : 150
     5080            });
     5081            e = 0;
     5082
     5083            Event.add(document, 'mousedown', t.hideMenu, t);
     5084        },
     5085
     5086        hideMenu : function(e) {
     5087            var t = this;
     5088
     5089            if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceSplitButtonMenu');})) {
     5090                DOM.removeClass(t.id, 'mceSplitButtonSelected');
     5091                Event.remove(document, 'mousedown', t.hideMenu, t);
     5092                DOM.hide(t.id + '_menu');
     5093            }
     5094        },
     5095
     5096        renderMenu : function() {
     5097            var t = this, m, i = 0, s = t.settings, n, tb, tr, w;
     5098
     5099            w = DOM.add(s.menu_container, 'div', {id : t.id + '_menu', 'class' : s['menu_class'] + ' ' + s['class'], style : 'position:absolute;left:0;top:-1000px;'});
     5100            m = DOM.add(w, 'div', {'class' : s['class'] + ' mceSplitButtonMenu'});
     5101            DOM.add(m, 'span', {'class' : 'mceMenuLine'});
     5102
     5103            n = DOM.add(m, 'table', {'class' : 'mceColorSplitMenu'});
     5104            tb = DOM.add(n, 'tbody');
     5105
     5106            // Generate color grid
     5107            i = 0;
     5108            each(is(s.colors, 'array') ? s.colors : s.colors.split(','), function(c) {
     5109                c = c.replace(/^#/, '');
     5110
     5111                if (!i--) {
     5112                    tr = DOM.add(tb, 'tr');
     5113                    i = s.grid_width - 1;
     5114                }
     5115
     5116                n = DOM.add(tr, 'td');
     5117
     5118                n = DOM.add(n, 'a', {
     5119                    href : 'javascript:;',
     5120                    style : {
     5121                        backgroundColor : '#' + c
     5122                    }
     5123                });
     5124
     5125                Event.add(n, 'mousedown', function() {
     5126                    t.setColor('#' + c);
     5127                });
     5128            });
     5129
     5130            if (s.more_colors_func) {
     5131                n = DOM.add(tb, 'tr');
     5132                n = DOM.add(n, 'td', {colspan : s.grid_width, 'class' : 'morecolors'});
     5133                n = DOM.add(n, 'a', {href : 'javascript:;', onclick : 'return false;', 'class' : 'morecolors'}, s.more_colors_title);
     5134
     5135                Event.add(n, 'click', function(e) {
     5136                    s.more_colors_func.call(s.more_colors_scope || this);
     5137                    return Event.cancel(e); // Cancel to fix onbeforeunload problem
     5138                });
     5139            }
     5140
     5141            DOM.addClass(m, 'mceColorSplitMenu');
     5142
     5143            return w;
     5144        },
     5145
     5146        setColor : function(c) {
     5147            var t = this, p, s = this.settings, co = s.menu_container, po, cp, id = t.id + '_preview';
     5148
     5149            if (!(p = DOM.get(id))) {
     5150                DOM.setStyle(t.id + '_action', 'position', 'relative');
     5151                p = DOM.add(t.id + '_action', 'div', {id : id, 'class' : 'mceColorPreview'});
     5152            }
     5153
     5154            p.style.backgroundColor = c;
     5155
     5156            t.value = c;
     5157            t.hideMenu();
     5158            s.onselect(c);
     5159        }
     5160
     5161        });
     5162})();
     5163
     5164/* file:jscripts/tiny_mce/classes/ui/Toolbar.js */
     5165
     5166tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
     5167    renderHTML : function() {
     5168        var t = this, h = '', c = 'mceToolbarEnd', co, dom = tinymce.DOM, s = t.settings;
     5169
     5170        h += dom.createHTML('td', {'class' : 'mceToolbarStart'}, dom.createHTML('span', null, '<!-- IE -->'));
     5171
     5172        tinymce.each(t.controls, function(c) {
     5173            h += '<td>' + c.renderHTML() + '</td>';
     5174        });
     5175
     5176        co = t.controls[t.controls.length - 1].constructor;
     5177
     5178        if (co === tinymce.ui.Button)
     5179            c += ' mceToolbarEndButton';
     5180        else if (co === tinymce.ui.SplitButton)
     5181            c += ' mceToolbarEndSplitButton';
     5182        else if (co === tinymce.ui.ListBox)
     5183            c += ' mceToolbarEndListBox';
     5184
     5185        h += dom.createHTML('td', {'class' : c}, dom.createHTML('span', null, '<!-- IE -->'));
     5186
     5187        return dom.createHTML('table', {id : t.id, 'class' : 'mceToolbar' + (s['class'] ? ' ' + s['class'] : ''), cellpadding : '0', cellspacing : '0', align : t.settings.align || ''}, '<tbody><tr>' + h + '</tr></tbody>');
     5188    }
     5189
     5190    });
     5191
     5192/* file:jscripts/tiny_mce/classes/AddOnManager.js */
     5193
     5194(function() {
     5195    var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each;
     5196
     5197    tinymce.create('tinymce.AddOnManager', {
     5198        items : [],
     5199        urls : {},
     5200        lookup : {},
     5201        onAdd : new Dispatcher(this),
     5202
     5203        get : function(n) {
     5204            return this.lookup[n];
     5205        },
     5206
     5207        requireLangPack : function(n) {
     5208            var u, s;
     5209
     5210            if (tinymce.EditorManager.settings) {
     5211                u = this.urls[n] + '/langs/' + tinymce.EditorManager.settings.language + '.js';
     5212                s = tinymce.EditorManager.settings;
     5213
     5214                if (s) {
     5215                    if (!tinymce.dom.Event.domLoaded && !s.strict_mode)
     5216                        tinymce.ScriptLoader.load(u);
     5217                    else
     5218                        tinymce.ScriptLoader.add(u);
     5219                }
     5220            }
     5221        },
     5222
     5223        add : function(id, o) {
     5224            this.items.push(o);
     5225            this.lookup[id] = o;
     5226            this.onAdd.dispatch(this, id, o);
     5227
     5228            return o;
     5229        },
     5230
     5231        load : function(n, u, cb, s) {
     5232            if (u.indexOf('/') != 0 && u.indexOf('://') == -1)
     5233                u = tinymce.baseURL + '/' +  u;
     5234
     5235            this.urls[n] = u.substring(0, u.lastIndexOf('/'));
     5236            tinymce.ScriptLoader.add(u, cb, s);
     5237        }
     5238
     5239        });
     5240
     5241    // Create plugin and theme managers
     5242    tinymce.PluginManager = new tinymce.AddOnManager();
     5243    tinymce.ThemeManager = new tinymce.AddOnManager();
     5244}());
     5245/* file:jscripts/tiny_mce/classes/EditorManager.js */
     5246
     5247(function() {
     5248    // Shorten names
     5249    var each = tinymce.each, extend = tinymce.extend, DOM = tinymce.DOM, Event = tinymce.dom.Event, ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager;
     5250
     5251    tinymce.create('static tinymce.EditorManager', {
     5252        editors : {},
     5253        i18n : {},
     5254        activeEditor : null,
     5255
     5256        init : function(s) {
     5257            var t = this, pl, sl = tinymce.ScriptLoader;
     5258
     5259            function execCallback(se, n, s) {
     5260                var f = se[n];
     5261
     5262                if (!f)
     5263                    return;
     5264
     5265                if (tinymce.is(f, 'string')) {
     5266                    s = f.replace(/\.\w+$/, '');
     5267                    s = s ? tinymce.resolve(s) : 0;
     5268                    f = tinymce.resolve(f);
     5269                }
     5270
     5271                return f.apply(s || this, Array.prototype.slice.call(arguments, 2));
     5272            };
     5273
     5274            s = extend({
     5275                theme : "simple",
     5276                language : "en",
     5277                strict_loading_mode : document.contentType == 'application/xhtml+xml'
     5278            }, s);
     5279
     5280            t.settings = s;
     5281
     5282            // If page not loaded and strict mode isn't enabled then load them
     5283            if (!Event.domLoaded && !s.strict_loading_mode) {
     5284                // Load language
     5285                if (s.language)
     5286                    sl.add(tinymce.baseURL + '/langs/' + s.language + '.js');
     5287
     5288                // Load theme
     5289                if (s.theme && s.theme.charAt(0) != '-')
     5290                    ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js');
     5291
     5292                // Load plugins
     5293                if (s.plugins) {
     5294                    pl = s.plugins.split(',');
     5295
     5296                    // Load compat2x first
     5297                    if (tinymce.inArray(pl, 'compat2x') != -1)
     5298                        PluginManager.load('compat2x', 'plugins/compat2x/editor_plugin' + tinymce.suffix + '.js');
     5299
     5300                    // Load rest if plugins
     5301                    each(pl, function(v) {
     5302                        if (v && v.charAt(0) != '-') {
     5303                            // Skip safari plugin for other browsers
     5304                            if (!tinymce.isWebKit && v == 'safari')
     5305                                return;
     5306
     5307                            PluginManager.load(v, 'plugins/' + v + '/editor_plugin' + tinymce.suffix + '.js');
     5308                        }
     5309                    });
     5310                }
     5311
     5312                sl.loadQueue();
     5313            }
     5314
     5315            // Legacy call
     5316            Event.add(document, 'init', function() {
     5317                var l, co;
     5318
     5319                execCallback(s, 'onpageload');
     5320
     5321                // Verify that it's a valid browser
     5322                if (s.browsers) {
     5323                    l = false;
     5324
     5325                    each(s.browsers.split(','), function(v) {
     5326                        switch (v) {
     5327                            case 'ie':
     5328                            case 'msie':
     5329                                if (tinymce.isIE)
     5330                                    l = true;
     5331                                break;
     5332
     5333                            case 'gecko':
     5334                                if (tinymce.isGecko)
     5335                                    l = true;
     5336                                break;
     5337
     5338                            case 'safari':
     5339                            case 'webkit':
     5340                                if (tinymce.isWebKit)
     5341                                    l = true;
     5342                                break;
     5343
     5344                            case 'opera':
     5345                                if (tinymce.isOpera)
     5346                                    l = true;
     5347
     5348                                break;
     5349                        }
     5350                    });
     5351
     5352                    // Not a valid one
     5353                    if (!l)
     5354                        return;
     5355                }
     5356
     5357                switch (s.mode) {
     5358                    case "exact":
     5359                        l = s.elements || '';
     5360                        each(l.split(','), function(v) {
     5361                            new tinymce.Editor(v, s).render();
     5362                        });
     5363                        break;
     5364
     5365                    case "textareas":
     5366                        function hasClass(n, c) {
     5367                            return new RegExp('\\b' + c + '\\b', 'g').test(n.className);
     5368                        };
     5369
     5370                        each(DOM.select('textarea'), function(v) {
     5371                            if (s.editor_deselector && hasClass(v, s.editor_deselector))
     5372                                return;
     5373
     5374                            if (!s.editor_selector || hasClass(v, s.editor_selector))
     5375                                new tinymce.Editor(v.id = (v.id || v.name || (v.id = DOM.uniqueId())), s).render();
     5376                        });
     5377                        break;
     5378                }
     5379
     5380                // Call onInit when all editors are initialized
     5381                if (s.oninit) {
     5382                    l = co = 0;
     5383
     5384                    each (t.editors, function(ed) {
     5385                        co++;
     5386
     5387                        if (!ed.initialized) {
     5388                            // Wait for it
     5389                            ed.onInit.add(function() {
     5390                                l++;
     5391
     5392                                // All done
     5393                                if (l == co)
     5394                                    execCallback(s, 'oninit');
     5395                            });
     5396                        } else
     5397                            l++;
     5398
     5399                        // All done
     5400                        if (l == co)
     5401                            execCallback(s, 'oninit');                 
     5402                    });
     5403                }
     5404            });
     5405        },
     5406
     5407        get : function(id) {
     5408            return this.editors[id];
     5409        },
     5410
     5411        getInstanceById : function(id) {
     5412            return this.get(id);
     5413        },
     5414
     5415        add : function(e) {
     5416            this.editors[e.id] = e;
     5417            this._setActive(e);
     5418
     5419            return e;
     5420        },
     5421
     5422        remove : function(e) {
     5423            var t = this;
     5424
     5425            // Not in the collection
     5426            if (!t.editors[e.id])
     5427                return null;
     5428
     5429            delete t.editors[e.id];
     5430
     5431            // Select another editor since the active one was removed
     5432            if (t.activeEditor == e) {
     5433                each(t.editors, function(e) {
     5434                    t._setActive(e);
     5435                    return false; // Break
     5436                });
     5437            }
     5438
     5439            e._destroy();
     5440
     5441            return e;
     5442        },
     5443
     5444        execCommand : function(c, u, v) {
     5445            var t = this, ed = t.get(v);
     5446
     5447            // Manager commands
     5448            switch (c) {
     5449                case "mceFocus":
     5450                    ed.focus();
     5451                    return true;
     5452
     5453                case "mceAddEditor":
     5454                case "mceAddControl":
     5455                    new tinymce.Editor(v, t.settings).render();
     5456                    return true;
     5457
     5458                case "mceAddFrameControl":
     5459                    // TODO: Implement this
     5460                    return true;
     5461
     5462                case "mceRemoveEditor":
     5463                case "mceRemoveControl":
     5464                    ed.remove();
     5465                    return true;
     5466
     5467                case 'mceToggleEditor':
     5468                    if (!ed) {
     5469                        t.execCommand('mceAddControl', 0, v);
     5470                        return true;
     5471                    }
     5472
     5473                    if (ed.isHidden())
     5474                        ed.show();
     5475                    else
     5476                        ed.hide();
     5477
     5478                    return true;
     5479            }
     5480
     5481            // Run command on active editor
     5482            if (t.activeEditor)
     5483                return t.activeEditor.execCommand(c, u, v);
     5484
    64505485            return false;
    6451 
    6452         if (tinyMCE.isSafari && bookmark.rng) {
    6453             sel.setBaseAndExtent(bookmark.rng.startContainer, bookmark.rng.startOffset, bookmark.rng.endContainer, bookmark.rng.endOffset);
     5486        },
     5487
     5488        execInstanceCommand : function(id, c, u, v) {
     5489            var ed = this.get(id);
     5490
     5491            if (ed)
     5492                return ed.execCommand(c, u, v);
     5493
     5494            return false;
     5495        },
     5496
     5497        triggerSave : function() {
     5498            each(this.editors, function(e) {
     5499                e.save();
     5500            });
     5501        },
     5502
     5503        addI18n : function(p, o) {
     5504            var lo, i18n = this.i18n;
     5505
     5506            if (!tinymce.is(p, 'string')) {
     5507                each(p, function(o, lc) {
     5508                    each(o, function(o, g) {
     5509                        each(o, function(o, k) {
     5510                            if (g === 'common')
     5511                                i18n[lc + '.' + k] = o;
     5512                            else
     5513                                i18n[lc + '.' + g + '.' + k] = o;
     5514                        });
     5515                    });
     5516                });
     5517            } else {
     5518                each(o, function(o, k) {
     5519                    i18n[p + '.' + k] = o;
     5520                });
     5521            }
     5522        },
     5523
     5524        // Private methods
     5525
     5526        _setActive : function(e) {
     5527            this.selectedInstance = this.activeEditor = e;
     5528        }
     5529
     5530        });
     5531
     5532    // Setup some URLs where the editor API is located and where the document is
     5533    tinymce.documentBaseURL = window.location.href.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');
     5534    if (!/[\/\\]$/.test(tinymce.documentBaseURL))
     5535        tinymce.documentBaseURL += '/';
     5536
     5537    tinymce.baseURL = new tinymce.util.URI(tinymce.documentBaseURL).toAbsolute(tinymce.baseURL);
     5538    tinymce.EditorManager.baseURI = new tinymce.util.URI(tinymce.baseURL);
     5539})();
     5540
     5541// Short for editor manager window.tinyMCE is needed when TinyMCE gets loaded though a XHR call
     5542var tinyMCE = window.tinyMCE = tinymce.EditorManager;
     5543
     5544/* file:jscripts/tiny_mce/classes/Editor.js */
     5545
     5546(function() {
     5547    var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, Dispatcher = tinymce.util.Dispatcher;
     5548    var each = tinymce.each, isGecko = tinymce.isGecko, isIE = tinymce.isIE, isWebKit = tinymce.isWebKit;
     5549    var is = tinymce.is, ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, EditorManager = tinymce.EditorManager;
     5550    var inArray = tinymce.inArray, grep = tinymce.grep;
     5551
     5552    tinymce.create('tinymce.Editor', {
     5553        Editor : function(id, s) {
     5554            var t = this;
     5555
     5556            t.id = t.editorId = id;
     5557            t.execCommands = {};
     5558            t.queryStateCommands = {};
     5559            t.queryValueCommands = {};
     5560            t.plugins = {};
     5561
     5562            // Add events to the editor
     5563            each([
     5564                'onPreInit',
     5565                'onBeforeRenderUI',
     5566                'onPostRender',
     5567                'onInit',
     5568                'onRemove',
     5569                'onActivate',
     5570                'onDeactivate',
     5571                'onClick',
     5572                'onEvent',
     5573                'onMouseUp',
     5574                'onMouseDown',
     5575                'onDblClick',
     5576                'onKeyDown',
     5577                'onKeyUp',
     5578                'onKeyPress',
     5579                'onContextMenu',
     5580                'onSubmit',
     5581                'onReset',
     5582                'onPaste',
     5583                'onPreProcess',
     5584                'onPostProcess',
     5585                'onBeforeSetContent',
     5586                'onBeforeGetContent',
     5587                'onSetContent',
     5588                'onGetContent',
     5589                'onLoadContent',
     5590                'onSaveContent',
     5591                'onNodeChange',
     5592                'onChange',
     5593                'onBeforeExecCommand',
     5594                'onExecCommand',
     5595                'onUndo',
     5596                'onRedo',
     5597                'onVisualAid',
     5598                'onSetProgressState'
     5599            ], function(e) {
     5600                t[e] = new Dispatcher(t);
     5601            });
     5602
     5603            // Default editor config
     5604            t.settings = s = extend({
     5605                id : id,
     5606                language : 'en',
     5607                docs_language : 'en',
     5608                theme : 'simple',
     5609                skin : 'default',
     5610                delta_width : 0,
     5611                delta_height : 0,
     5612                popup_css : '',
     5613                plugins : '',
     5614                document_base_url : tinymce.documentBaseURL,
     5615                add_form_submit_trigger : 1,
     5616                submit_patch : 1,
     5617                add_unload_trigger : 1,
     5618                convert_urls : 1,
     5619                relative_urls : 1,
     5620                remove_script_host : 1,
     5621                table_inline_editing : 0,
     5622                object_resizing : 1,
     5623                cleanup : 1,
     5624                accessibility_focus : 1,
     5625                custom_shortcuts : 1,
     5626                custom_undo_redo_keyboard_shortcuts : 1,
     5627                custom_undo_redo_restore_selection : 1,
     5628                custom_undo_redo : 1,
     5629                doctype : '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">',
     5630                visual_table_class : 'mceItemTable',
     5631                visual : 1,
     5632                inline_styles : true,
     5633                convert_fonts_to_spans : true,
     5634                font_size_style_values : 'xx-small,x-small,small,medium,large,x-large,xx-large',
     5635                apply_source_formatting : 1,
     5636                directionality : 'ltr',
     5637                forced_root_block : 'p',
     5638                valid_elements : '@[id|class|style|title|dir<ltr?rtl|lang|xml::lang|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],a[rel|rev|charset|hreflang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur],strong/b,em/i,strike,u,#p[align],-ol[type|compact],-ul[type|compact],-li,br,img[longdesc|usemap|src|border|alt=|title|hspace|vspace|width|height|align],-sub,-sup,-blockquote,-table[border=0|cellspacing|cellpadding|width|frame|rules|height|align|summary|bgcolor|background|bordercolor],-tr[rowspan|width|height|align|valign|bgcolor|background|bordercolor],tbody,thead,tfoot,#td[colspan|rowspan|width|height|align|valign|bgcolor|background|bordercolor|scope],#th[colspan|rowspan|width|height|align|valign|scope],caption,-div,-span,-pre,address,-h1,-h2,-h3,-h4,-h5,-h6,hr[size|noshade],-font[face|size|color],dd,dl,dt,cite,abbr,acronym,del[datetime|cite],ins[datetime|cite],object[classid|width|height|codebase|*],param[name|value|_value],embed[type|width|height|src|*],script[type]',
     5639                hidden_input : 1,
     5640                padd_empty_editor : 1,
     5641                render_ui : 1,
     5642                init_theme : 1,
     5643                indentation : '30px'
     5644            }, s);
     5645
     5646            // Setup URIs
     5647            t.documentBaseURI = new tinymce.util.URI(s.document_base_url || tinymce.documentBaseURL, {
     5648                base_uri : tinyMCE.baseURI
     5649            });
     5650            t.baseURI = EditorManager.baseURI;
     5651
     5652            // Call setup
     5653            t.execCallback('setup', t);
     5654        },
     5655
     5656        render : function() {
     5657            var t = this, s = t.settings, id = t.id, sl = tinymce.ScriptLoader;
     5658
     5659            // Element not found, then skip initialization
     5660            if (!t.getElement())
     5661                return;
     5662
     5663            if (s.strict_loading_mode) {
     5664                sl.settings.strict_mode = s.strict_loading_mode;
     5665                tinymce.DOM.settings.strict = 1;
     5666            }
     5667
     5668            // Add hidden input for non input elements inside form elements
     5669            if (!/TEXTAREA|INPUT/i.test(t.getElement().nodeName) && s.hidden_input && DOM.getParent(id, 'form'))
     5670                DOM.insertAfter(DOM.create('input', {type : 'hidden', name : id}), id);
     5671
     5672            t.windowManager = new tinymce.WindowManager(t);
     5673
     5674            if (s.encoding == 'xml') {
     5675                t.onGetContent.add(function(ed, o) {
     5676                    if (o.get)
     5677                        o.content = DOM.encode(o.content);
     5678                });
     5679            }
     5680
     5681            if (s.add_form_submit_trigger) {
     5682                t.onSubmit.addToTop(function() {
     5683                    if (t.initialized) {
     5684                        t.save();
     5685                        t.isNotDirty = 1;
     5686                    }
     5687                });
     5688            }
     5689
     5690            Event.add(document, 'unload', function() {
     5691                if (t.initialized && !t.destroyed && s.add_unload_trigger)
     5692                    t.save({format : 'raw', no_events : true});
     5693            });
     5694
     5695            tinymce.addUnload(t._destroy, t);
     5696
     5697            if (s.submit_patch) {
     5698                t.onBeforeRenderUI.add(function() {
     5699                    var n = t.getElement().form;
     5700
     5701                    if (!n)
     5702                        return;
     5703
     5704                    // Already patched
     5705                    if (n._mceOldSubmit)
     5706                        return;
     5707
     5708                    // Check page uses id="submit" or name="submit" for it's submit button
     5709                    if (!n.submit.nodeType) {
     5710                        t.formElement = n;
     5711                        n._mceOldSubmit = n.submit;
     5712                        n.submit = function() {
     5713                            // Save all instances
     5714                            EditorManager.triggerSave();
     5715                            t.isNotDirty = 1;
     5716
     5717                            return this._mceOldSubmit(this);
     5718                        };
     5719                    }
     5720
     5721                    n = null;
     5722                });
     5723            }
     5724
     5725            // Load scripts
     5726            function loadScripts() {
     5727                sl.add(tinymce.baseURL + '/langs/' + s.language + '.js');
     5728
     5729                if (s.theme.charAt(0) != '-')
     5730                    ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js');
     5731
     5732                each(s.plugins.split(','), function(p) {
     5733                    if (p && p.charAt(0) != '-') {
     5734                        // Skip safari plugin for other browsers
     5735                        if (!isWebKit && p == 'safari')
     5736                            return;
     5737
     5738                        PluginManager.load(p, 'plugins/' + p + '/editor_plugin' + tinymce.suffix + '.js');
     5739                    }
     5740                });
     5741
     5742                // Init when que is loaded
     5743                sl.loadQueue(function() {
     5744                    if (s.ask) {
     5745                        function ask() {
     5746                            t.windowManager.confirm(t.getLang('edit_confirm'), function(s) {
     5747                                if (s)
     5748                                    t.init();
     5749                                else
     5750                                    Event.remove(t.id, 'focus', ask);
     5751                            });
     5752                        };
     5753
     5754                        Event.add(t.id, 'focus', ask);
     5755                        return;
     5756                    }
     5757
     5758                    if (!t.removed)
     5759                        t.init();
     5760                });
     5761            };
     5762
     5763            // Load compat2x first
     5764            if (s.plugins.indexOf('compat2x') != -1) {
     5765                PluginManager.load('compat2x', 'plugins/compat2x/editor_plugin' + tinymce.suffix + '.js');
     5766                sl.loadQueue(loadScripts);
     5767            } else
     5768                loadScripts();
     5769        },
     5770
     5771        init : function() {
     5772            var n, t = this, s = t.settings, w, h, e = t.getElement(), o, ti;
     5773
     5774            EditorManager.add(t);
     5775
     5776            // Create theme
     5777            s.theme = s.theme.replace(/-/, '');
     5778            o = ThemeManager.get(s.theme);
     5779            t.theme = new o();
     5780
     5781            if (t.theme.init && s.init_theme)
     5782                t.theme.init(t, ThemeManager.urls[s.theme] || tinymce.documentBaseURL.replace(/\/$/, ''));
     5783
     5784            // Create all plugins
     5785            each(s.plugins.replace(/\-/g, '').split(','), function(p) {
     5786                var c = PluginManager.get(p), u = PluginManager.urls[p] || tinymce.documentBaseURL.replace(/\/$/, ''), po;
     5787
     5788                if (c) {
     5789                    po = new c(t, u);
     5790
     5791                    t.plugins[p] = po;
     5792
     5793                    if (po.init)
     5794                        po.init(t, u);
     5795                }
     5796            });
     5797
     5798            // Setup popup CSS path(s)
     5799            s.popup_css = t.baseURI.toAbsolute(s.popup_css || "themes/" + s.theme + "/skins/" + s.skin + "/dialog.css");
     5800
     5801            if (s.popup_css_add)
     5802                s.popup_css += ',' + s.popup_css_add;
     5803
     5804            // Setup control factory
     5805            t.controlManager = new tinymce.ControlManager(t);
     5806            t.undoManager = new tinymce.UndoManager(t);
     5807
     5808            // Pass through
     5809            t.undoManager.onAdd.add(function(um, l) {
     5810                return t.onChange.dispatch(t, l, um);
     5811            });
     5812
     5813            t.undoManager.onUndo.add(function(um, l) {
     5814                return t.onUndo.dispatch(t, l, um);
     5815            });
     5816
     5817            t.undoManager.onRedo.add(function(um, l) {
     5818                return t.onRedo.dispatch(t, l, um);
     5819            });
     5820
     5821            if (s.custom_undo_redo) {
     5822                t.onExecCommand.add(function(ed, cmd) {
     5823                    if (cmd != 'Undo' && cmd != 'Redo' && cmd != 'mceRepaint')
     5824                        t.undoManager.add();
     5825                });
     5826            }
     5827
     5828            t.onExecCommand.add(function(ed, c) {
     5829                // Don't refresh the select lists until caret move
     5830                if (!/^(FontName|FontSize)$/.test(c))
     5831                    t.nodeChanged();
     5832            });
     5833
     5834            // Remove ghost selections on images and tables in Gecko
     5835            if (isGecko) {
     5836                function repaint() {
     5837                    t.execCommand('mceRepaint');
     5838                };
     5839
     5840                t.onUndo.add(repaint);
     5841                t.onRedo.add(repaint);
     5842                t.onSetContent.add(repaint);
     5843            }
     5844
     5845            // Enables users to override the control factory
     5846            t.onBeforeRenderUI.dispatch(t, t.controlManager);
     5847
     5848            // Measure box
     5849            if (s.render_ui) {
     5850                w = s.width || e.style.width || e.clientWidth;
     5851                h = s.height || e.style.height || e.clientHeight;
     5852                t.orgDisplay = e.style.display;
     5853
     5854                if (('' + w).indexOf('%') == -1)
     5855                    w = Math.max(parseInt(w) + (o.deltaWidth || 0), 100);
     5856
     5857                if (('' + h).indexOf('%') == -1)
     5858                    h = Math.max(parseInt(h) + (o.deltaHeight || 0), 100);
     5859
     5860                // Render UI
     5861                o = t.theme.renderUI({
     5862                    targetNode : e,
     5863                    width : w,
     5864                    height : h,
     5865                    deltaWidth : s.delta_width,
     5866                    deltaHeight : s.delta_height
     5867                });
     5868
     5869                t.editorContainer = o.editorContainer;
     5870            }
     5871
     5872           
     5873            // Resize editor
     5874            DOM.setStyles(o.sizeContainer || o.editorContainer, {
     5875                width : w,
     5876                height : h
     5877            });
     5878
     5879            h = (o.iframeHeight || h) + ((h + '').indexOf('%') == -1 ? (o.deltaHeight || 0) : '');
     5880            if (h < 100)
     5881                h = 100;
     5882
     5883            // Create iframe
     5884            n = DOM.add(o.iframeContainer, 'iframe', {
     5885                id : s.id + "_ifr",
     5886                src : 'javascript:""', // Workaround for HTTPS warning in IE6/7
     5887                frameBorder : '0',
     5888                style : {
     5889                    width : '100%',
     5890                    height : h
     5891                }
     5892            });
     5893
     5894            t.contentAreaContainer = o.iframeContainer;
     5895            DOM.get(o.editorContainer).style.display = t.orgDisplay;
     5896            DOM.get(s.id).style.display = 'none';
     5897
     5898            // Safari 2.x requires us to wait for the load event and load a real HTML doc
     5899            if (tinymce.isOldWebKit) {
     5900                Event.add(n, 'load', t.setupIframe, t);
     5901                n.src = tinymce.baseURL + '/plugins/safari/blank.htm';
     5902            } else {
     5903                t.setupIframe();
     5904                e = n = o = null; // Cleanup
     5905            }
     5906
     5907/*          function createIfr() {
     5908                h = (o.iframeHeight || h) + ((h + '').indexOf('%') == -1 ? (o.deltaHeight || 0) : '');
     5909                if (h < 100)
     5910                    h = 100;
     5911
     5912                // Create iframe
     5913                n = DOM.add(o.iframeContainer, 'iframe', {
     5914                    id : s.id + "_ifr",
     5915                    src : 'javascript:""', // Workaround for HTTPS warning in IE6/7
     5916                    frameBorder : '0',
     5917                    style : {
     5918                        width : '100%',
     5919                        height : h
     5920                    }
     5921                });
     5922
     5923                t.contentAreaContainer = o.iframeContainer;
     5924                DOM.get(o.editorContainer).style.display = t.orgDisplay;
     5925                DOM.get(s.id).style.display = 'none';
     5926
     5927                // Safari 2.x requires us to wait for the load event and load a real HTML doc
     5928                if (tinymce.isOldWebKit) {
     5929                    Event.add(n, 'load', t.setupIframe, t);
     5930                    n.src = tinymce.baseURL + '/plugins/safari/blank.htm';
     5931                } else {
     5932                    t.setupIframe();
     5933                    e = n = o = null; // Cleanup
     5934                }
     5935            };
     5936*/
     5937            // Waits for the editor to become visible, then it will run the init
     5938            // This method is somewhat ugly but this is the best way to deal with it without
     5939            // forcing the user to add some logic to their application.
     5940/*          if (isGecko) {
     5941                function check() {
     5942                    var hi;
     5943
     5944                    DOM.getParent(t.id, function(e) {
     5945                        if (DOM.getStyle(e, 'display', true) == 'none') {
     5946                            hi = 1;
     5947                            return true;
     5948                        }
     5949                    });
     5950
     5951                    return hi;
     5952                };
     5953
     5954                if (check()) {
     5955                    ti = window.setInterval(function() {
     5956                        if (!check()) {
     5957                            createIfr();
     5958                            window.clearInterval(ti);
     5959                        }
     5960                    }, 300);
     5961
     5962                    return;
     5963                }
     5964            }
     5965
     5966            createIfr();
     5967*/
     5968        },
     5969
     5970        setupIframe : function() {
     5971            var t = this, s = t.settings, e = DOM.get(s.id), d = t.getDoc();
     5972
     5973            // Setup body
     5974            d.open();
     5975            d.write(s.doctype + '<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="' + t.documentBaseURI.getURI() + '" /><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /></head><body id="tinymce" class="mceContentBody"></body></html>');
     5976            d.close();
     5977
     5978            // Design mode needs to be added here Ctrl+A will fail otherwise
     5979            if (!isIE) {
     5980                try {
     5981                    d.designMode = 'On';
     5982                } catch (ex) {
     5983                    // Will fail on Gecko if the editor is placed in an hidden container element
     5984                    // The design mode will be set ones the editor is focused
     5985                }
     5986            }
     5987
     5988            // IE needs to use contentEditable or it will display non secure items for HTTPS
     5989            if (isIE)
     5990                t.getBody().contentEditable = true;
     5991
     5992            // Setup objects
     5993            t.dom = new tinymce.DOM.DOMUtils(t.getDoc(), {
     5994                keep_values : true,
     5995                url_converter : t.convertURL,
     5996                url_converter_scope : t,
     5997                hex_colors : s.force_hex_style_colors,
     5998                class_filter : s.class_filter,
     5999                update_styles : 1
     6000            });
     6001
     6002            t.serializer = new tinymce.dom.Serializer({
     6003                entity_encoding : s.entity_encoding,
     6004                entities : s.entities,
     6005                valid_elements : s.verify_html === false ? '*[*]' : s.valid_elements,
     6006                extended_valid_elements : s.extended_valid_elements,
     6007                valid_child_elements : s.valid_child_elements,
     6008                invalid_elements : s.invalid_elements,
     6009                fix_table_elements : s.fix_table_elements,
     6010                fix_list_elements : s.fix_list_elements,
     6011                fix_content_duplication : s.fix_content_duplication,
     6012                convert_fonts_to_spans : s.convert_fonts_to_spans,
     6013                font_size_classes  : s.font_size_classes,
     6014                font_size_style_values : s.font_size_style_values,
     6015                apply_source_formatting : s.apply_source_formatting,
     6016                remove_linebreaks : s.remove_linebreaks,
     6017                dom : t.dom
     6018            });
     6019
     6020            t.selection = new tinymce.dom.Selection(t.dom, t.getWin(), t.serializer);
     6021            t.forceBlocks = new tinymce.ForceBlocks(t, {
     6022                forced_root_block : s.forced_root_block
     6023            });
     6024            t.editorCommands = new tinymce.EditorCommands(t);
     6025
     6026            // Pass through
     6027            t.serializer.onPreProcess.add(function(se, o) {
     6028                return t.onPreProcess.dispatch(t, o, se);
     6029            });
     6030
     6031            t.serializer.onPostProcess.add(function(se, o) {
     6032                return t.onPostProcess.dispatch(t, o, se);
     6033            });
     6034
     6035            t.onPreInit.dispatch(t);
     6036
     6037            if (!s.gecko_spellcheck)
     6038                t.getBody().spellcheck = 0;
     6039
     6040            t._addEvents();
     6041
     6042            t.controlManager.onPostRender.dispatch(t, t.controlManager);
     6043            t.onPostRender.dispatch(t);
     6044
     6045            if (s.directionality)
     6046                t.getBody().dir = s.directionality;
     6047
     6048            if (s.nowrap)
     6049                t.getBody().style.whiteSpace = "nowrap";
     6050
     6051            if (s.auto_resize)
     6052                t.onNodeChange.add(t.resizeToContent, t);
     6053
     6054            if (s.handle_node_change_callback) {
     6055                t.onNodeChange.add(function(ed, cm, n) {
     6056                    t.execCallback('handle_node_change_callback', t.id, n, -1, -1, true, t.selection.isCollapsed());
     6057                });
     6058            }
     6059
     6060            if (s.save_callback) {
     6061                t.onSaveContent.add(function(ed, o) {
     6062                    var h = t.execCallback('save_callback', t.id, o.content, t.getBody());
     6063
     6064                    if (h)
     6065                        o.content = h;
     6066                });
     6067            }
     6068
     6069            if (s.onchange_callback) {
     6070                t.onChange.add(function(ed, l) {
     6071                    t.execCallback('onchange_callback', t, l);
     6072                });
     6073            }
     6074
     6075            if (s.convert_newlines_to_brs) {
     6076                t.onBeforeSetContent.add(function(ed, o) {
     6077                    if (o.initial)
     6078                        o.content = o.content.replace(/\r?\n/g, '<br />');
     6079                });
     6080            }
     6081
     6082            if (s.fix_nesting && isIE) {
     6083                t.onBeforeSetContent.add(function(ed, o) {
     6084                    o.content = t._fixNesting(o.content);
     6085                });
     6086            }
     6087
     6088            if (s.preformatted) {
     6089                t.onPostProcess.add(function(ed, o) {
     6090                    o.content = o.content.replace(/^\s*<pre.*?>/, '');
     6091                    o.content = o.content.replace(/<\/pre>\s*$/, '');
     6092
     6093                    if (o.set)
     6094                        o.content = '<pre class="mceItemHidden">' + o.content + '</pre>';
     6095                });
     6096            }
     6097
     6098            if (s.verify_css_classes) {
     6099                t.serializer.attribValueFilter = function(n, v) {
     6100                    var s, cl;
     6101
     6102                    if (n == 'class') {
     6103                        // Build regexp for classes
     6104                        if (!t.classesRE) {
     6105                            cl = t.dom.getClasses();
     6106
     6107                            if (cl.length > 0) {
     6108                                s = '';
     6109
     6110                                each (cl, function(o) {
     6111                                    s += (s ? '|' : '') + o['class'];
     6112                                });
     6113
     6114                                t.classesRE = new RegExp('(' + s + ')', 'gi');
     6115                            }
     6116                        }
     6117
     6118                        return !t.classesRE || /(\bmceItem\w+\b|\bmceTemp\w+\b)/g.test(v) || t.classesRE.test(v) ? v : '';
     6119                    }
     6120
     6121                    return v;
     6122                };
     6123            }
     6124
     6125            if (s.convert_fonts_to_spans)
     6126                t._convertFonts();
     6127
     6128            if (s.inline_styles)
     6129                t._convertInlineElements();
     6130
     6131            if (s.cleanup_callback) {
     6132                t.onSetContent.add(function(ed, o) {
     6133                    if (o.initial) {
     6134                        t.setContent(t.execCallback('cleanup_callback', 'insert_to_editor', o.content, o), {format : 'raw', no_events : true});
     6135                        t.execCallback('cleanup_callback', 'insert_to_editor_dom', t.getDoc(), o);
     6136                    }
     6137                });
     6138
     6139                t.onPreProcess.add(function(ed, o) {
     6140                    if (o.set)
     6141                        t.execCallback('cleanup_callback', 'insert_to_editor_dom', o.node, o);
     6142
     6143                    if (o.get)
     6144                        t.execCallback('cleanup_callback', 'get_from_editor_dom', o.node, o);
     6145                });
     6146
     6147                t.onPostProcess.add(function(ed, o) {
     6148                    if (o.set)
     6149                        o.content = t.execCallback('cleanup_callback', 'insert_to_editor', o.content, o);
     6150
     6151                    if (o.get)                     
     6152                        o.content = t.execCallback('cleanup_callback', 'get_from_editor', o.content, o);
     6153                });
     6154            }
     6155
     6156            if (s.save_callback) {
     6157                t.onGetContent.add(function(ed, o) {
     6158                    if (o.save)
     6159                        o.content = t.execCallback('save_callback', t.id, o.content, t.getBody());
     6160                });
     6161            }
     6162
     6163            if (s.handle_event_callback) {
     6164                t.onEvent.add(function(ed, e, o) {
     6165                    if (t.execCallback('handle_event_callback', e, ed, o) === false)
     6166                        Event.cancel(e);
     6167                });
     6168            }
     6169
     6170            t.onSetContent.add(function() {
     6171                // Safari needs some time, it will crash the browser when a link is created otherwise
     6172                // I think this crash issue is resolved in the latest 3.0.4
     6173                //window.setTimeout(function() {
     6174                    t.addVisual(t.getBody());
     6175                //}, 1);
     6176            });
     6177
     6178            // Remove empty contents
     6179            if (s.padd_empty_editor) {
     6180                t.onPostProcess.add(function(ed, o) {
     6181                    o.content = o.content.replace(/^<p>(&nbsp;|#160;|\s)<\/p>$/, '');
     6182                });
     6183            }
     6184
     6185            // A small timeout was needed since firefox will remove. Bug: #1838304
     6186            setTimeout(function () {
     6187                if (t.removed)
     6188                    return;
     6189
     6190                t.load({initial : true, format : (s.cleanup_on_startup ? 'html' : 'raw')});
     6191                t.startContent = t.getContent({format : 'raw'});
     6192                t.undoManager.add({initial : true});
     6193                t.initialized = true;
     6194
     6195                t.onInit.dispatch(t);
     6196                t.execCallback('setupcontent_callback', t.id, t.getBody(), t.getDoc());
     6197                t.execCallback('init_instance_callback', t);
     6198                t.focus(true);
     6199                t.nodeChanged({initial : 1});
     6200
     6201                // Load specified content CSS last
     6202                if (s.content_css) {
     6203                    tinymce.each(s.content_css.split(','), function(u) {
     6204                        t.dom.loadCSS(t.documentBaseURI.toAbsolute(u));
     6205                    });
     6206                }
     6207
     6208                // Handle auto focus
     6209                if (s.auto_focus) {
     6210                    setTimeout(function () {
     6211                        var ed = EditorManager.get(s.auto_focus);
     6212
     6213                        ed.selection.select(ed.getBody(), 1);
     6214                        ed.selection.collapse(1);
     6215                        ed.getWin().focus();
     6216                    }, 100);
     6217                }
     6218            }, 1);
     6219
     6220            e = null;
     6221        },
     6222
     6223       
     6224        focus : function(sf) {
     6225            var oed, t = this;
     6226
     6227            if (!sf) {
     6228                t.getWin().focus();
     6229
     6230                            }
     6231
     6232            if (EditorManager.activeEditor != t) {
     6233                if ((oed = EditorManager.activeEditor) != null)
     6234                    oed.onDeactivate.dispatch(oed, t);
     6235
     6236                t.onActivate.dispatch(t, oed);
     6237            }
     6238
     6239            EditorManager._setActive(t);
     6240        },
     6241
     6242        execCallback : function(n) {
     6243            var t = this, f = t.settings[n], s;
     6244
     6245            if (!f)
     6246                return;
     6247
     6248            // Look through lookup
     6249            if (t.callbackLookup && (s = t.callbackLookup[n])) {
     6250                f = s.func;
     6251                s = s.scope;
     6252            }
     6253
     6254            if (is(f, 'string')) {
     6255                s = f.replace(/\.\w+$/, '');
     6256                s = s ? tinymce.resolve(s) : 0;
     6257                f = tinymce.resolve(f);
     6258                t.callbackLookup = t.callbackLookup || {};
     6259                t.callbackLookup[n] = {func : f, scope : s};
     6260            }
     6261
     6262            return f.apply(s || t, Array.prototype.slice.call(arguments, 1));
     6263        },
     6264
     6265        translate : function(s) {
     6266            var c = this.settings.language, i18n = EditorManager.i18n;
     6267
     6268            if (!s)
     6269                return '';
     6270
     6271            return i18n[c + '.' + s] || s.replace(/{\#([^}]+)\}/g, function(a, b) {
     6272                return i18n[c + '.' + b] || '{#' + b + '}';
     6273            });
     6274        },
     6275
     6276        getLang : function(n, dv) {
     6277            return EditorManager.i18n[this.settings.language + '.' + n] || (is(dv) ? dv : '{#' + n + '}');
     6278        },
     6279
     6280        getParam : function(n, dv) {
     6281            return is(this.settings[n]) ? this.settings[n] : dv;
     6282        },
     6283
     6284        nodeChanged : function(o) {
     6285            var t = this, s = t.selection, n = s.getNode() || this.getBody();
     6286
     6287            this.onNodeChange.dispatch(
     6288                t,
     6289                o ? o.controlManager || t.controlManager : t.controlManager,
     6290                isIE && n.ownerDocument != t.getDoc() ? this.getBody() : n, // Fix for IE initial state
     6291                s.isCollapsed(),
     6292                o
     6293            );
     6294        },
     6295
     6296        addButton : function(n, s) {
     6297            var t = this;
     6298
     6299            t.buttons = t.buttons || {};
     6300            t.buttons[n] = s;
     6301        },
     6302
     6303        addCommand : function(n, f, s) {
     6304            this.execCommands[n] = {func : f, scope : s || this};
     6305        },
     6306
     6307        addQueryStateHandler : function(n, f, s) {
     6308            this.queryStateCommands[n] = {func : f, scope : s || this};
     6309        },
     6310
     6311        addQueryValueHandler : function(n, f, s) {
     6312            this.queryValueCommands[n] = {func : f, scope : s || this};
     6313        },
     6314
     6315        addShortcut : function(pa, desc, cmd_func, sc) {
     6316            var t = this, c;
     6317
     6318            if (!t.settings.custom_shortcuts)
     6319                return false;
     6320
     6321            t.shortcuts = t.shortcuts || {};
     6322
     6323            if (is(cmd_func, 'string')) {
     6324                c = cmd_func;
     6325
     6326                cmd_func = function() {
     6327                    t.execCommand(c, false, null);
     6328                };
     6329            }
     6330
     6331            if (is(cmd_func, 'object')) {
     6332                c = cmd_func;
     6333
     6334                cmd_func = function() {
     6335                    t.execCommand(c[0], c[1], c[2]);
     6336                };
     6337            }
     6338
     6339            each(pa.split(','), function(pa) {
     6340                var o = {
     6341                    func : cmd_func,
     6342                    scope : sc || this,
     6343                    desc : desc,
     6344                    alt : false,
     6345                    ctrl : false,
     6346                    shift : false
     6347                };
     6348
     6349                each(pa.split('+'), function(v) {
     6350                    switch (v) {
     6351                        case 'alt':
     6352                        case 'ctrl':
     6353                        case 'shift':
     6354                            o[v] = true;
     6355                            break;
     6356
     6357                        default:
     6358                            o.charCode = v.charCodeAt(0);
     6359                            o.keyCode = v.toUpperCase().charCodeAt(0);
     6360                    }
     6361                });
     6362
     6363                t.shortcuts[(o.ctrl ? 'ctrl' : '') + ',' + (o.alt ? 'alt' : '') + ',' + (o.shift ? 'shift' : '') + ',' + o.keyCode] = o;
     6364            });
     6365
    64546366            return true;
     6367        },
     6368
     6369        execCommand : function(cmd, ui, val, a) {
     6370            var t = this, s = 0, o;
     6371
     6372            if (!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(cmd) && (!a || !a.skip_focus))
     6373                t.focus();
     6374
     6375            o = {};
     6376            t.onBeforeExecCommand.dispatch(t, cmd, ui, val, o);
     6377            if (o.terminate)
     6378                return false;
     6379
     6380            // Comamnd callback
     6381            if (t.execCallback('execcommand_callback', null, t.id, t.selection.getNode(), cmd, ui, val)) {
     6382                t.onExecCommand.dispatch(t, cmd, ui, val);
     6383                return true;
     6384            }
     6385
     6386            // Registred commands
     6387            if (o = t.execCommands[cmd]) {
     6388                s = o.func.call(o.scope, ui, val);
     6389                t.onExecCommand.dispatch(t, cmd, ui, val);
     6390                return s;
     6391            }
     6392
     6393            // Plugin commands
     6394            each(t.plugins, function(p) {
     6395                if (p.execCommand && p.execCommand(cmd, ui, val)) {
     6396                    t.onExecCommand.dispatch(t, cmd, ui, val);
     6397                    s = 1;
     6398                    return false;
     6399                }
     6400            });
     6401
     6402            if (s)
     6403                return true;
     6404
     6405            // Theme commands
     6406            if (t.theme.execCommand && t.theme.execCommand(cmd, ui, val)) {
     6407                t.onExecCommand.dispatch(t, cmd, ui, val);
     6408                return true;
     6409            }
     6410
     6411            // Editor commands
     6412            if (t.editorCommands.execCommand(cmd, ui, val)) {
     6413                t.onExecCommand.dispatch(t, cmd, ui, val);
     6414                return true;
     6415            }
     6416
     6417            // Browser commands
     6418            t.getDoc().execCommand(cmd, ui, val);
     6419            t.onExecCommand.dispatch(t, cmd, ui, val);
     6420        },
     6421
     6422        queryCommandState : function(c) {
     6423            var t = this, o;
     6424
     6425            // Is hidden then return undefined
     6426            if (t._isHidden())
     6427                return;
     6428
     6429            // Registred commands
     6430            if (o = t.queryStateCommands[c])
     6431                return o.func.call(o.scope);
     6432
     6433            // Registred commands
     6434            o = t.editorCommands.queryCommandState(c);
     6435            if (o !== -1)
     6436                return o;
     6437
     6438            // Browser commands
     6439            return this.getDoc().queryCommandState(c);
     6440        },
     6441
     6442        queryCommandValue : function(c) {
     6443            var t = this, o;
     6444
     6445            // Is hidden then return undefined
     6446            if (t._isHidden())
     6447                return;
     6448
     6449            // Registred commands
     6450            if (o = t.queryValueCommands[c])
     6451                return o.func.call(o.scope);
     6452
     6453            // Registred commands
     6454            o = t.editorCommands.queryCommandValue(c);
     6455            if (is(o))
     6456                return o;
     6457
     6458            // Browser commands
     6459            return this.getDoc().queryCommandValue(c);
     6460        },
     6461
     6462        show : function() {
     6463            var t = this;
     6464
     6465            DOM.show(t.getContainer());
     6466            DOM.hide(t.id);
     6467            t.load();
     6468        },
     6469
     6470        hide : function() {
     6471            var t = this, s = t.settings, d = t.getDoc();
     6472
     6473            // Fixed bug where IE has a blinking cursor left from the editor
     6474            if (isIE && d)
     6475                d.execCommand('SelectAll');
     6476
     6477            DOM.hide(t.getContainer());
     6478            DOM.setStyle(s.id, 'display', t.orgDisplay);
     6479            t.save();
     6480        },
     6481
     6482        isHidden : function() {
     6483            return !DOM.isHidden(this.id);
     6484        },
     6485
     6486        setProgressState : function(b, ti, o) {
     6487            this.onSetProgressState.dispatch(this, b, ti, o);
     6488
     6489            return b;
     6490        },
     6491
     6492        remove : function() {
     6493            var t = this;
     6494
     6495            t.removed = 1; // Cancels post remove event execution
     6496            t.hide();
     6497            DOM.remove(t.getContainer());
     6498
     6499            t.execCallback('remove_instance_callback', t);
     6500            t.onRemove.dispatch(t);
     6501
     6502            EditorManager.remove(t);
     6503        },
     6504
     6505        resizeToContent : function() {
     6506            var t = this;
     6507
     6508            DOM.setStyle(t.id + "_ifr", 'height', t.getBody().scrollHeight);
     6509        },
     6510
     6511        load : function(o) {
     6512            var t = this, e = t.getElement(), h;
     6513
     6514            o = o || {};
     6515            o.load = true;
     6516
     6517            h = t.setContent(is(e.value) ? e.value : e.innerHTML, o);
     6518            o.element = e;
     6519
     6520            if (!o.no_events)
     6521                t.onLoadContent.dispatch(t, o);
     6522
     6523            o.element = e = null;
     6524
     6525            return h;
     6526        },
     6527
     6528        save : function(o) {
     6529            var t = this, e = t.getElement(), h, f;
     6530
     6531            if (!t.initialized)
     6532                return;
     6533
     6534            o = o || {};
     6535            o.save = true;
     6536
     6537            o.element = e;
     6538            h = o.content = t.getContent(o);
     6539
     6540            if (!o.no_events)
     6541                t.onSaveContent.dispatch(t, o);
     6542
     6543            h = o.content;
     6544
     6545            if (!/TEXTAREA|INPUT/i.test(e.nodeName)) {
     6546                e.innerHTML = h;
     6547
     6548                // Update hidden form element
     6549                if (f = DOM.getParent(t.id, 'form')) {
     6550                    each(f.elements, function(e) {
     6551                        if (e.name == t.id) {
     6552                            e.value = h;
     6553                            return false;
     6554                        }
     6555                    });
     6556                }
     6557            } else
     6558                e.value = h;
     6559
     6560            o.element = e = null;
     6561
     6562            return h;
     6563        },
     6564
     6565        setContent : function(h, o) {
     6566            var t = this;
     6567
     6568            o = o || {};
     6569            o.format = o.format || 'html';
     6570            o.set = true;
     6571            o.content = h;
     6572
     6573            if (!o.no_events)
     6574                t.onBeforeSetContent.dispatch(t, o);
     6575
     6576            // Padd empty content in Gecko and Safari. Commands will otherwise fail on the content
     6577            // It will also be impossible to place the caret in the editor unless there is a BR element present
     6578            if (!tinymce.isIE && (h.length === 0 || /^\s+$/.test(h))) {
     6579                o.content = t.dom.setHTML(t.getBody(), '<br mce_bogus="1" />', 1);
     6580                o.format = 'raw';
     6581            }
     6582
     6583            o.content = t.dom.setHTML(t.getBody(), o.content);
     6584
     6585            if (o.format != 'raw' && t.settings.cleanup) {
     6586                o.getInner = true;
     6587                o.content = t.dom.setHTML(t.getBody(), t.serializer.serialize(t.getBody(), o));
     6588            }
     6589
     6590            if (!o.no_events)
     6591                t.onSetContent.dispatch(t, o);
     6592
     6593            return o.content;
     6594        },
     6595
     6596        getContent : function(o) {
     6597            var t = this, h;
     6598
     6599            o = o || {};
     6600            o.format = o.format || 'html';
     6601            o.get = true;
     6602
     6603            if (!o.no_events)
     6604                t.onBeforeGetContent.dispatch(t, o);
     6605
     6606            if (o.format != 'raw' && t.settings.cleanup) {
     6607                o.getInner = true;
     6608                h = t.serializer.serialize(t.getBody(), o);
     6609            } else
     6610                h = t.getBody().innerHTML;
     6611
     6612            h = h.replace(/^\s*|\s*$/g, '');
     6613            o = {content : h};
     6614            t.onGetContent.dispatch(t, o);
     6615
     6616            return o.content;
     6617        },
     6618
     6619        isDirty : function() {
     6620            var t = this;
     6621
     6622            return tinymce.trim(t.startContent) != tinymce.trim(t.getContent({format : 'raw', no_events : 1})) && !t.isNotDirty;
     6623        },
     6624
     6625        getContainer : function() {
     6626            var t = this;
     6627
     6628            if (!t.container)
     6629                t.container = DOM.get(t.editorContainer || t.id + '_parent');
     6630
     6631            return t.container;
     6632        },
     6633
     6634        getContentAreaContainer : function() {
     6635            return this.contentAreaContainer;
     6636        },
     6637
     6638        getElement : function() {
     6639            return DOM.get(this.settings.content_element || this.id);
     6640        },
     6641
     6642        getWin : function() {
     6643            var t = this, e;
     6644
     6645            if (!t.contentWindow) {
     6646                e = DOM.get(t.id + "_ifr");
     6647
     6648                if (e)
     6649                    t.contentWindow = e.contentWindow;
     6650            }
     6651
     6652            return t.contentWindow;
     6653        },
     6654
     6655        getDoc : function() {
     6656            var t = this, w;
     6657
     6658            if (!t.contentDocument) {
     6659                w = this.getWin();
     6660
     6661                if (w)
     6662                    t.contentDocument = w.document;
     6663            }
     6664
     6665            return t.contentDocument;
     6666        },
     6667
     6668        getBody : function() {
     6669            return this.bodyElement || this.getDoc().body;
     6670        },
     6671
     6672        convertURL : function(u, n, e) {
     6673            var t = this, s = t.settings;
     6674
     6675            // Use callback instead
     6676            if (s.urlconverter_callback)
     6677                return t.execCallback('urlconverter_callback', u, e, true, n);
     6678
     6679            // Don't convert link href since thats the CSS files that gets loaded into the editor
     6680            if (!s.convert_urls || (e && e.nodeName == 'LINK'))
     6681                return u;
     6682
     6683            // Convert to relative
     6684            if (s.relative_urls)
     6685                return t.documentBaseURI.toRelative(u);
     6686
     6687            // Convert to absolute
     6688            u = t.documentBaseURI.toAbsolute(u, s.remove_script_host);
     6689
     6690            return u;
     6691        },
     6692
     6693        addVisual : function(e) {
     6694            var t = this, s = t.settings;
     6695
     6696            e = e || t.getBody();
     6697
     6698            if (!is(t.hasVisual))
     6699                t.hasVisual = s.visual;
     6700
     6701            each(t.dom.select('table,a', e), function(e) {
     6702                var v;
     6703
     6704                switch (e.nodeName) {
     6705                    case 'TABLE':
     6706                        v = t.dom.getAttrib(e, 'border');
     6707
     6708                        if (!v || v == '0') {
     6709                            if (t.hasVisual)
     6710                                t.dom.addClass(e, s.visual_table_class);
     6711                            else
     6712                                t.dom.removeClass(e, s.visual_table_class);
     6713                        }
     6714
     6715                        return;
     6716
     6717                    case 'A':
     6718                        v = t.dom.getAttrib(e, 'name');
     6719
     6720                        if (v) {
     6721                            if (t.hasVisual)
     6722                                t.dom.addClass(e, 'mceItemAnchor');
     6723                            else
     6724                                t.dom.removeClass(e, 'mceItemAnchor');
     6725                        }
     6726
     6727                        return;
     6728                }
     6729            });
     6730
     6731            t.onVisualAid.dispatch(t, e, t.hasVisual);
     6732        },
     6733
     6734        // Internal functions
     6735
     6736        _addEvents : function() {
     6737            // 'focus', 'blur', 'dblclick', 'beforedeactivate', submit, reset
     6738            var t = this, i, s = t.settings, lo = {
     6739                mouseup : 'onMouseUp',
     6740                mousedown : 'onMouseDown',
     6741                click : 'onClick',
     6742                keyup : 'onKeyUp',
     6743                keydown : 'onKeyDown',
     6744                keypress : 'onKeyPress',
     6745                submit : 'onSubmit',
     6746                reset : 'onReset',
     6747                contextmenu : 'onContextMenu',
     6748                dblclick : 'onDblClick',
     6749                paste : 'onPaste' // Doesn't work in all browsers yet
     6750            };
     6751
     6752            function eventHandler(e, o) {
     6753                var ty = e.type;
     6754
     6755                // Don't fire events when it's removed
     6756                if (t.removed)
     6757                    return;
     6758
     6759                // Generic event handler
     6760                if (t.onEvent.dispatch(t, e, o) !== false) {
     6761                    // Specific event handler
     6762                    t[lo[e.fakeType || e.type]].dispatch(t, e, o);
     6763                }
     6764            };
     6765
     6766            // Add DOM events
     6767            each(lo, function(v, k) {
     6768                switch (k) {
     6769                    case 'contextmenu':
     6770                        if (tinymce.isOpera) {
     6771                            // Fake contextmenu on Opera
     6772                            Event.add(t.getDoc(), 'mousedown', function(e) {
     6773                                if (e.ctrlKey) {
     6774                                    e.fakeType = 'contextmenu';
     6775                                    eventHandler(e);
     6776                                }
     6777                            });
     6778                        } else
     6779                            Event.add(t.getDoc(), k, eventHandler);
     6780                        break;
     6781
     6782                    case 'paste':
     6783                        Event.add(t.getBody(), k, function(e) {
     6784                            var tx, h, el, r;
     6785
     6786                            // Get plain text data
     6787                            if (e.clipboardData)
     6788                                tx = e.clipboardData.getData('text/plain');
     6789                            else if (tinymce.isIE)
     6790                                tx = t.getWin().clipboardData.getData('Text');
     6791
     6792                            // Get HTML data
     6793                            /*if (tinymce.isIE) {
     6794                                el = DOM.add(document.body, 'div', {style : 'visibility:hidden;overflow:hidden;position:absolute;width:1px;height:1px'});
     6795                                r = document.body.createTextRange();
     6796                                r.moveToElementText(el);
     6797                                r.execCommand('Paste');
     6798                                h = el.innerHTML;
     6799                                DOM.remove(el);
     6800                            }*/
     6801
     6802                            eventHandler(e, {text : tx, html : h});
     6803                        });
     6804                        break;
     6805
     6806                    case 'submit':
     6807                    case 'reset':
     6808                        Event.add(t.getElement().form || DOM.getParent(t.id, 'form'), k, eventHandler);
     6809                        break;
     6810
     6811                    default:
     6812                        Event.add(s.content_editable ? t.getBody() : t.getDoc(), k, eventHandler);
     6813                }
     6814            });
     6815
     6816            Event.add(s.content_editable ? t.getBody() : (isGecko ? t.getDoc() : t.getWin()), 'focus', function(e) {
     6817                t.focus(true);
     6818            });
     6819
     6820            // Fixes bug where a specified document_base_uri could result in broken images
     6821            // This will also fix drag drop of images in Gecko
     6822            if (tinymce.isGecko) {
     6823                // Convert all images to absolute URLs
     6824/*              t.onSetContent.add(function(ed, o) {
     6825                    each(ed.dom.select('img'), function(e) {
     6826                        var v;
     6827
     6828                        if (v = e.getAttribute('mce_src'))
     6829                            e.src = t.documentBaseURI.toAbsolute(v);
     6830                    })
     6831                });*/
     6832
     6833                Event.add(t.getDoc(), 'DOMNodeInserted', function(e) {
     6834                    var v;
     6835
     6836                    e = e.target;
     6837
     6838                    if (e.nodeType === 1 && e.nodeName === 'IMG' && (v = e.getAttribute('mce_src')))
     6839                        e.src = t.documentBaseURI.toAbsolute(v);
     6840                });
     6841            }
     6842
     6843            // Set various midas options in Gecko
     6844            if (isGecko) {
     6845                function setOpts() {
     6846                    var t = this, d = t.getDoc(), s = t.settings;
     6847
     6848                    if (isGecko) {
     6849                        if (t._isHidden()) {
     6850                            try {
     6851                                d.designMode = 'On';
     6852                            } catch (ex) {
     6853                                // Fails if it's hidden
     6854                            }
     6855                        }
     6856
     6857                        try {
     6858                            // Try new Gecko method
     6859                            d.execCommand("styleWithCSS", 0, false);
     6860                        } catch (ex) {
     6861                            // Use old method
     6862                            if (!t._isHidden())
     6863                                d.execCommand("useCSS", 0, true);
     6864                        }
     6865
     6866                        if (!s.table_inline_editing)
     6867                            try {d.execCommand('enableInlineTableEditing', false, false);} catch (ex) {}
     6868
     6869                        if (!s.object_resizing)
     6870                            try {d.execCommand('enableObjectResizing', false, false);} catch (ex) {}
     6871                    }
     6872                };
     6873
     6874                t.onBeforeExecCommand.add(setOpts);
     6875                t.onMouseDown.add(setOpts);
     6876            }
     6877
     6878            // Add node change handlers
     6879            t.onMouseUp.add(t.nodeChanged);
     6880            t.onClick.add(t.nodeChanged);
     6881            t.onKeyUp.add(function(ed, e) {
     6882                if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45 || e.keyCode == 46 || e.keyCode == 8 || e.ctrlKey)
     6883                    t.nodeChanged();
     6884            });
     6885
     6886            // Add reset handler
     6887            t.onReset.add(function() {
     6888                t.setContent(t.startContent, {format : 'raw'});
     6889            });
     6890
     6891            if (t.getParam('tab_focus')) {
     6892                function tabCancel(ed, e) {
     6893                    if (e.keyCode === 9)
     6894                        return Event.cancel(e);
     6895                };
     6896
     6897                function tabHandler(ed, e) {
     6898                    var v, f, el;
     6899
     6900                    if (e.keyCode === 9) {
     6901                        v = ed.getParam('tab_focus');
     6902
     6903                        if (v == ':next') {
     6904                            f = DOM.getParent(ed.id, 'form');
     6905
     6906                            if (f) {
     6907                                each(f.elements, function(e, i) {
     6908                                    if (e.id == ed.id)
     6909                                        el = f.elements[i + 1];
     6910                                });
     6911                            }
     6912                        } else
     6913                            el = DOM.get(v);
     6914
     6915                        if (el) {
     6916                            window.setTimeout(function() {window.focus();el.focus();}, 10);
     6917                            return Event.cancel(e);
     6918                        }
     6919                    }
     6920                };
     6921
     6922                t.onKeyUp.add(tabCancel);
     6923
     6924                if (isGecko) {
     6925                    t.onKeyPress.add(tabHandler);
     6926                    t.onKeyDown.add(tabCancel);
     6927                } else
     6928                    t.onKeyDown.add(tabHandler);
     6929            }
     6930
     6931            // Add shortcuts
     6932            if (s.custom_shortcuts) {
     6933                if (s.custom_undo_redo_keyboard_shortcuts) {
     6934                    t.addShortcut('ctrl+z', t.getLang('undo_desc'), 'Undo');
     6935                    t.addShortcut('ctrl+y', t.getLang('redo_desc'), 'Redo');
     6936                }
     6937
     6938                // Add default shortcuts for gecko
     6939                if (isGecko) {
     6940                    t.addShortcut('ctrl+b', t.getLang('bold_desc'), 'Bold');
     6941                    t.addShortcut('ctrl+i', t.getLang('italic_desc'), 'Italic');
     6942                    t.addShortcut('ctrl+u', t.getLang('underline_desc'), 'Underline');
     6943                }
     6944
     6945                // BlockFormat shortcuts keys
     6946                for (i=1; i<=6; i++)
     6947                    t.addShortcut('ctrl+' + i, '', ['FormatBlock', false, '<h' + i + '>']);
     6948
     6949                t.addShortcut('ctrl+7', '', ['FormatBlock', false, '<p>']);
     6950                t.addShortcut('ctrl+8', '', ['FormatBlock', false, '<div>']);
     6951                t.addShortcut('ctrl+9', '', ['FormatBlock', false, '<address>']);
     6952
     6953                function find(e) {
     6954                    var v = null;
     6955
     6956                    if (!e.altKey && !e.ctrlKey && !e.metaKey)
     6957                        return v;
     6958
     6959                    each(t.shortcuts, function(o) {
     6960                        if (o.ctrl != e.ctrlKey && (!tinymce.isMac || o.ctrl == e.metaKey))
     6961                            return;
     6962
     6963                        if (o.alt != e.altKey)
     6964                            return;
     6965
     6966                        if (o.shift != e.shiftKey)
     6967                            return;
     6968
     6969                        if (e.keyCode == o.keyCode || (e.charCode && e.charCode == o.charCode)) {
     6970                            v = o;
     6971                            return false;
     6972                        }
     6973                    });
     6974
     6975                    return v;
     6976                };
     6977
     6978                t.onKeyUp.add(function(ed, e) {
     6979                    var o = find(e);
     6980
     6981                    if (o)
     6982                        return Event.cancel(e);
     6983                });
     6984
     6985                t.onKeyPress.add(function(ed, e) {
     6986                    var o = find(e);
     6987
     6988                    if (o)
     6989                        return Event.cancel(e);
     6990                });
     6991
     6992                t.onKeyDown.add(function(ed, e) {
     6993                    var o = find(e);
     6994
     6995                    if (o) {
     6996                        o.func.call(o.scope);
     6997                        return Event.cancel(e);
     6998                    }
     6999                });
     7000            }
     7001
     7002            if (tinymce.isIE) {
     7003                // Fix so resize will only update the width and height attributes not the styles of an image
     7004                // It will also block mceItemNoResize items
     7005                Event.add(t.getDoc(), 'controlselect', function(e) {
     7006                    var re = t.resizeInfo, cb;
     7007
     7008                    e = e.target;
     7009
     7010                    if (re)
     7011                        Event.remove(re.node, re.ev, re.cb);
     7012
     7013                    if (!t.dom.hasClass(e, 'mceItemNoResize')) {
     7014                        ev = 'resizeend';
     7015                        cb = Event.add(e, ev, function(e) {
     7016                            var v;
     7017
     7018                            e = e.target;
     7019
     7020                            if (v = t.dom.getStyle(e, 'width')) {
     7021                                t.dom.setAttrib(e, 'width', v.replace(/[^0-9%]+/g, ''));
     7022                                t.dom.setStyle(e, 'width', '');
     7023                            }
     7024
     7025                            if (v = t.dom.getStyle(e, 'height')) {
     7026                                t.dom.setAttrib(e, 'height', v.replace(/[^0-9%]+/g, ''));
     7027                                t.dom.setStyle(e, 'height', '');
     7028                            }
     7029                        });
     7030                    } else {
     7031                        ev = 'resizestart';
     7032                        cb = Event.add(e, 'resizestart', Event.cancel, Event);
     7033                    }
     7034
     7035                    re = t.resizeInfo = {
     7036                        node : e,
     7037                        ev : ev,
     7038                        cb : cb
     7039                    };
     7040                });
     7041
     7042                t.onKeyDown.add(function(ed, e) {
     7043                    switch (e.keyCode) {
     7044                        case 8:
     7045                            // Fix IE control + backspace browser bug
     7046                            if (t.selection.getRng().item) {
     7047                                t.selection.getRng().item(0).removeNode();
     7048                                return Event.cancel(e);
     7049                            }
     7050                    }
     7051                });
     7052            }
     7053
     7054            if (tinymce.isOpera) {
     7055                t.onClick.add(function(ed, e) {
     7056                    Event.prevent(e);
     7057                });
     7058            }
     7059
     7060            // Add custom undo/redo handlers
     7061            if (s.custom_undo_redo) {
     7062                function addUndo() {
     7063                    t.undoManager.typing = 0;
     7064                    t.undoManager.add();
     7065                };
     7066
     7067                // Add undo level on editor blur
     7068                if (tinymce.isIE) {
     7069                    Event.add(t.getWin(), 'blur', function(e) {
     7070                        var n;
     7071
     7072                        // Check added for fullscreen bug
     7073                        if (t.selection) {
     7074                            n = t.selection.getNode();
     7075
     7076                            // Add undo level is selection was lost to another document
     7077                            if (!t.removed && n.ownerDocument && n.ownerDocument != t.getDoc())
     7078                                addUndo();
     7079                        }
     7080                    });
     7081                } else {
     7082                    Event.add(t.getDoc(), 'blur', function() {
     7083                        if (t.selection && !t.removed)
     7084                            addUndo();
     7085                    });
     7086                }
     7087
     7088                t.onMouseDown.add(addUndo);
     7089
     7090                t.onKeyUp.add(function(ed, e) {
     7091                    if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45 || e.ctrlKey) {
     7092                        t.undoManager.typing = 0;
     7093                        t.undoManager.add();
     7094                    }
     7095                });
     7096
     7097                t.onKeyDown.add(function(ed, e) {
     7098                    // Is caracter positon keys
     7099                    if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45) {
     7100                        if (t.undoManager.typing) {
     7101                            t.undoManager.add();
     7102                            t.undoManager.typing = 0;
     7103                        }
     7104
     7105                        return;
     7106                    }
     7107
     7108                    if (!t.undoManager.typing) {
     7109                        t.undoManager.add();
     7110                        t.undoManager.typing = 1;
     7111                    }
     7112                });
     7113            }
     7114        },
     7115
     7116        _destroy : function() {
     7117            var t = this;
     7118
     7119            if (t.formElement) {
     7120                t.formElement.submit = t.formElement._mceOldSubmit;
     7121                t.formElement._mceOldSubmit = null;
     7122            }
     7123
     7124            t.contentAreaContainer = t.formElement = t.container = t.contentDocument = t.contentWindow = null;
     7125
     7126            if (t.selection)
     7127                t.selection = t.selection.win = t.selection.dom = t.selection.dom.doc = null;
     7128
     7129            t.destroyed = 1;
     7130        },
     7131
     7132        _convertInlineElements : function() {
     7133            var t = this, s = t.settings, dom = t.dom;
     7134
     7135            function convert(ed, o) {
     7136                if (!s.inline_styles)
     7137                    return;
     7138
     7139                if (o.get) {
     7140                    each(t.dom.select('table,u,strike', o.node), function(n) {
     7141                        switch (n.nodeName) {
     7142                            case 'TABLE':
     7143                                if (v = dom.getAttrib(n, 'height')) {
     7144                                    dom.setStyle(n, 'height', v);
     7145                                    dom.setAttrib(n, 'height', '');
     7146                                }
     7147                                break;
     7148
     7149                            case 'U':
     7150                                dom.replace(dom.create('span', {style : 'text-decoration: underline;'}), n, 1);
     7151                                break;
     7152
     7153                            case 'STRIKE':
     7154                                dom.replace(dom.create('span', {style : 'text-decoration: line-through;'}), n, 1);
     7155                                break;
     7156                        }
     7157                    });
     7158                } else if (o.set) {
     7159                    each(t.dom.select('table,span', o.node), function(n) {
     7160                        if (n.nodeName == 'TABLE') {
     7161                            if (v = dom.getStyle(n, 'height'))
     7162                                dom.setAttrib(n, 'height', v.replace(/[^0-9%]+/g, ''));
     7163                        } else {
     7164                            // Convert spans to elements
     7165                            if (n.style.textDecoration == 'underline')
     7166                                dom.replace(dom.create('u'), n, 1);
     7167                            else if (n.style.textDecoration == 'line-through')
     7168                                dom.replace(dom.create('strike'), n, 1);
     7169                        }
     7170                    });
     7171                }
     7172            };
     7173
     7174            t.onPreProcess.add(convert);
     7175
     7176            if (!s.cleanup_on_startup) {
     7177                t.onInit.add(function() {
     7178                    convert(t, {node : t.getBody(), set : 1});
     7179                });
     7180            }
     7181        },
     7182
     7183        _convertFonts : function() {
     7184            var t = this, s = t.settings, dom = t.dom, sl, cl, fz, fzn, v, i;
     7185
     7186            // Font pt values and font size names
     7187            fz = [8, 10, 12, 14, 18, 24, 36];
     7188            fzn = ['xx-small', 'x-small','small','medium','large','x-large', 'xx-large'];
     7189
     7190            if (sl = s.font_size_style_values)
     7191                sl = sl.split(',');
     7192
     7193            if (cl = s.font_size_classes)
     7194                cl = cl.split(',');
     7195
     7196            t.onPreProcess.add(function(ed, o) {
     7197                if (!s.inline_styles)
     7198                    return;
     7199
     7200                if (o.set) {
     7201                    // Convert spans to fonts on non WebKit browsers
     7202                    if (tinymce.isWebKit)
     7203                        return;
     7204
     7205                    each(t.dom.select('span', o.node), function(n) {
     7206                        var f = dom.create('font', {
     7207                            color : dom.toHex(dom.getStyle(n, 'color')),
     7208                            face : dom.getStyle(n, 'fontFamily')
     7209                        });
     7210
     7211                        if (sl) {
     7212                            i = inArray(sl, dom.getStyle(n, 'fontSize'));
     7213
     7214                            if (i != -1)
     7215                                dom.setAttrib(f, 'size', '' + (i + 1 || 1));
     7216                        } else if (cl) {
     7217                            i = inArray(cl, dom.getAttrib(n, 'class'));
     7218
     7219                            v = dom.getStyle(n, 'fontSize');
     7220
     7221                            if (i == -1 && v.indexOf('pt') > 0)
     7222                                i = inArray(fz, parseInt(v));
     7223
     7224                            if (i == -1)
     7225                                i = inArray(fzn, v);
     7226
     7227                            if (i != -1)
     7228                                dom.setAttrib(f, 'size', '' + (i + 1 || 1));
     7229                        }
     7230
     7231                        if (f.color || f.face || f.size)
     7232                            dom.replace(f, n, 1);
     7233                    });
     7234                } else if (o.get) {
     7235                    each(t.dom.select('font', o.node), function(n) {
     7236                        var sp = dom.create('span', {
     7237                            style : {
     7238                                fontFamily : dom.getAttrib(n, 'face'),
     7239                                color : dom.getAttrib(n, 'color'),
     7240                                backgroundColor : n.style.backgroundColor
     7241                            }
     7242                        });
     7243
     7244                        if (n.size) {
     7245                            if (sl)
     7246                                dom.setStyle(sp, 'fontSize', sl[parseInt(n.size) - 1]);
     7247                            else
     7248                                dom.setAttrib(sp, 'class', cl[parseInt(n.size) - 1]);
     7249                        }
     7250
     7251                        dom.replace(sp, n, 1);
     7252                    });
     7253                }
     7254            });
     7255        },
     7256
     7257        _isHidden : function() {
     7258            var s;
     7259
     7260            if (!isGecko)
     7261                return 0;
     7262
     7263            // Weird, wheres that cursor selection?
     7264            s = this.selection.getSel();
     7265            return (!s || !s.rangeCount || s.rangeCount == 0);
     7266        },
     7267
     7268        _fixNesting : function(s) {
     7269            var d = [], i;
     7270
     7271            s = s.replace(/<(\/)?([^\s>]+)[^>]*?>/g, function(a, b, c) {
     7272                var e;
     7273
     7274                // Handle end element
     7275                if (b === '/') {
     7276                    if (!d.length)
     7277                        return '';
     7278
     7279                    if (c !== d[d.length - 1].tag) {
     7280                        for (i=d.length - 1; i>=0; i--) {
     7281                            if (d[i].tag === c) {
     7282                                d[i].close = 1;
     7283                                break;
     7284                            }
     7285                        }
     7286
     7287                        return '';
     7288                    } else {
     7289                        d.pop();
     7290
     7291                        if (d.length && d[d.length - 1].close) {
     7292                            a = a + '</' + d[d.length - 1].tag + '>';
     7293                            d.pop();
     7294                        }
     7295                    }
     7296                } else {
     7297                    // Ignore these
     7298                    if (/^(br|hr|input|meta|img|link|param)$/i.test(c))
     7299                        return a;
     7300
     7301                    // Ignore closed ones
     7302                    if (/\/>$/.test(a))
     7303                        return a;
     7304
     7305                    d.push({tag : c}); // Push start element
     7306                }
     7307
     7308                return a;
     7309            });
     7310
     7311            // End all open tags
     7312            for (i=d.length - 1; i>=0; i--)
     7313                s += '</' + d[i].tag + '>';
     7314
     7315            return s;
    64557316        }
    64567317
    6457         if (tinyMCE.isRealIE) {
    6458             if (bookmark.rng) {
     7318        });
     7319})();
     7320
     7321/* file:jscripts/tiny_mce/classes/EditorCommands.js */
     7322
     7323(function() {
     7324    var each = tinymce.each, isIE = tinymce.isIE, isGecko = tinymce.isGecko, isOpera = tinymce.isOpera, isWebKit = tinymce.isWebKit;
     7325
     7326    tinymce.create('tinymce.EditorCommands', {
     7327        EditorCommands : function(ed) {
     7328            this.editor = ed;
     7329        },
     7330
     7331        execCommand : function(cmd, ui, val) {
     7332            var t = this, ed = t.editor, f;
     7333
     7334            switch (cmd) {
     7335                case 'Cut':
     7336                case 'Copy':
     7337                case 'Paste':
     7338                    try {
     7339                        ed.getDoc().execCommand(cmd, ui, val);
     7340                    } catch (ex) {
     7341                        if (isGecko) {
     7342                            ed.windowManager.confirm(ed.getLang('clipboard_msg'), function(s) {
     7343                                if (s)
     7344                                    window.open('http://www.mozilla.org/editor/midasdemo/securityprefs.html', 'mceExternal');
     7345                            });
     7346                        } else
     7347                            ed.windowManager.alert(ed.getLang('clipboard_no_support'));
     7348                    }
     7349
     7350                    return true;
     7351
     7352                // Ignore these
     7353                case 'mceResetDesignMode':
     7354                case 'mceBeginUndoLevel':
     7355                    return true;
     7356
     7357                // Ignore these
     7358                case 'unlink':
     7359                    t.UnLink();
     7360                    return true;
     7361
     7362                // Bundle these together
     7363                case 'JustifyLeft':
     7364                case 'JustifyCenter':
     7365                case 'JustifyRight':
     7366                case 'JustifyFull':
     7367                    t.mceJustify(cmd, cmd.substring(7).toLowerCase());
     7368                    return true;
     7369
     7370                case 'mceEndUndoLevel':
     7371                case 'mceAddUndoLevel':
     7372                    ed.undoManager.add();
     7373                    return true;
     7374
     7375                default:
     7376                    f = this[cmd];
     7377
     7378                    if (f) {
     7379                        f.call(this, ui, val);
     7380                        return true;
     7381                    }
     7382            }
     7383
     7384            return false;
     7385        },
     7386
     7387        Indent : function() {
     7388            var ed = this.editor, d = ed.dom, s = ed.selection, e, iv, iu;
     7389
     7390            // Setup indent level
     7391            iv = ed.settings.indentation;
     7392            iu = /[a-z%]+$/i.exec(iv);
     7393            iv = parseInt(iv);
     7394
     7395            if (ed.settings.inline_styles && (!this.queryStateInsertUnorderedList() && !this.queryStateInsertOrderedList())) {
     7396                each(this._getSelectedBlocks(), function(e) {
     7397                    d.setStyle(e, 'paddingLeft', (parseInt(e.style.paddingLeft || 0) + iv) + iu);
     7398                });
     7399
     7400                return;
     7401            }
     7402
     7403            ed.getDoc().execCommand('Indent', false, null);
     7404
     7405            if (isIE) {
     7406                d.getParent(s.getNode(), function(n) {
     7407                    if (n.nodeName == 'BLOCKQUOTE') {
     7408                        n.dir = n.style.cssText = '';
     7409                    }
     7410                });
     7411            }
     7412        },
     7413
     7414        Outdent : function() {
     7415            var ed = this.editor, d = ed.dom, s = ed.selection, e, v, iv, iu;
     7416
     7417            // Setup indent level
     7418            iv = ed.settings.indentation;
     7419            iu = /[a-z%]+$/i.exec(iv);
     7420            iv = parseInt(iv);
     7421
     7422            if (ed.settings.inline_styles && (!this.queryStateInsertUnorderedList() && !this.queryStateInsertOrderedList())) {
     7423                each(this._getSelectedBlocks(), function(e) {
     7424                    v = Math.max(0, parseInt(e.style.paddingLeft || 0) - iv);
     7425                    d.setStyle(e, 'paddingLeft', v ? v + iu : '');
     7426                });
     7427
     7428                return;
     7429            }
     7430
     7431            ed.getDoc().execCommand('Outdent', false, null);
     7432        },
     7433
     7434        mceSetAttribute : function(u, v) {
     7435            var ed = this.editor, d = ed.dom, e;
     7436
     7437            if (e = d.getParent(ed.selection.getNode(), d.isBlock))
     7438                d.setAttrib(e, v.name, v.value);
     7439        },
     7440
     7441        mceSetContent : function(u, v) {
     7442            this.editor.setContent(v);
     7443        },
     7444
     7445        mceToggleVisualAid : function() {
     7446            var ed = this.editor;
     7447
     7448            ed.hasVisual = !ed.hasVisual;
     7449            ed.addVisual();
     7450        },
     7451
     7452        mceReplaceContent : function(u, v) {
     7453            var s = this.editor.selection;
     7454
     7455            s.setContent(v.replace(/\{\$selection\}/g, s.getContent({format : 'text'})));
     7456        },
     7457
     7458        mceInsertLink : function(u, v) {
     7459            var ed = this.editor, e = ed.dom.getParent(ed.selection.getNode(), 'A');
     7460
     7461            if (tinymce.is(v, 'string'))
     7462                v = {href : v};
     7463
     7464            function set(e) {
     7465                each(v, function(v, k) {
     7466                    ed.dom.setAttrib(e, k, v);
     7467                });
     7468            };
     7469
     7470            if (!e) {
     7471                ed.execCommand('CreateLink', false, 'javascript:mctmp(0);');
     7472                each(ed.dom.select('a'), function(e) {
     7473                    if (e.href == 'javascript:mctmp(0);')
     7474                        set(e);
     7475                });
     7476            } else {
     7477                if (v.href)
     7478                    set(e);
     7479                else
     7480                    ed.dom.remove(e, 1);
     7481            }
     7482        },
     7483
     7484        UnLink : function() {
     7485            var ed = this.editor, s = ed.selection;
     7486
     7487            if (s.isCollapsed())
     7488                s.select(s.getNode());
     7489
     7490            ed.getDoc().execCommand('unlink', false, null);
     7491            s.collapse(0);
     7492        },
     7493
     7494        FontName : function(u, v) {
     7495            var t = this, ed = t.editor, s = ed.selection, e;
     7496
     7497            if (!v) {
     7498                if (s.isCollapsed())
     7499                    s.select(s.getNode());
     7500
     7501                t.RemoveFormat();
     7502            } else
     7503                ed.getDoc().execCommand('FontName', false, v);
     7504        },
     7505
     7506        queryCommandValue : function(c) {
     7507            var f = this['queryValue' + c];
     7508
     7509            if (f)
     7510                return f.call(this, c);
     7511
     7512            return false;
     7513        },
     7514
     7515        queryCommandState : function(cmd) {
     7516            var f;
     7517
     7518            switch (cmd) {
     7519                // Bundle these together
     7520                case 'JustifyLeft':
     7521                case 'JustifyCenter':
     7522                case 'JustifyRight':
     7523                case 'JustifyFull':
     7524                    return this.queryStateJustify(cmd, cmd.substring(7).toLowerCase());
     7525
     7526                default:
     7527                    if (f = this['queryState' + cmd])
     7528                        return f.call(this, cmd);
     7529            }
     7530
     7531            return -1;
     7532        },
     7533
     7534        queryValueFontSize : function() {
     7535            var ed = this.editor, v = 0, p;
     7536
     7537            if (isOpera || isWebKit) {
     7538                if (p = ed.dom.getParent(ed.selection.getNode(), 'FONT'))
     7539                    v = p.size;
     7540
     7541                return v;
     7542            }
     7543
     7544            return ed.getDoc().queryCommandValue('FontSize');
     7545        },
     7546
     7547        queryValueFontName : function() {
     7548            var ed = this.editor, v = 0, p;
     7549
     7550            if (p = ed.dom.getParent(ed.selection.getNode(), 'FONT'))
     7551                v = p.face;
     7552
     7553            if (!v)
     7554                v = ed.getDoc().queryCommandValue('FontName');
     7555
     7556            return v;
     7557        },
     7558
     7559        mceJustify : function(c, v) {
     7560            var ed = this.editor, se = ed.selection, n = se.getNode(), nn = n.nodeName, bl, nb, dom = ed.dom, rm;
     7561
     7562            if (ed.settings.inline_styles && this.queryStateJustify(c, v))
     7563                rm = 1;
     7564
     7565            bl = dom.getParent(n, ed.dom.isBlock);
     7566
     7567            if (nn == 'IMG') {
     7568                if (v == 'full')
     7569                    return;
     7570
     7571                if (rm) {
     7572                    dom.setStyle(n, 'float', '');
     7573                    this.mceRepaint();
     7574                    return;
     7575                }
     7576
     7577                if (v == 'center') {
     7578                    if (!bl || bl.childNodes.length > 1) {
     7579                        nb = dom.create('p');
     7580                        nb.appendChild(n.cloneNode(false));
     7581
     7582                        if (bl)
     7583                            dom.insertAfter(nb, bl);
     7584                        else
     7585                            dom.insertAfter(nb, n);
     7586
     7587                        dom.remove(n);
     7588                        n = nb.firstChild;
     7589                        bl = nb;
     7590                    }
     7591
     7592                    dom.setStyle(bl, 'textAlign', v);
     7593                    dom.setStyle(n, 'float', '');
     7594                } else
     7595                    dom.setStyle(n, 'float', v);
     7596
     7597                this.mceRepaint();
     7598                return;
     7599            }
     7600
     7601            // Handle the alignment outselfs, less quirks in all browsers
     7602            if (ed.settings.inline_styles && ed.settings.forced_root_block) {
     7603                if (rm)
     7604                    v = '';
     7605
     7606                each(this._getSelectedBlocks(dom.getParent(se.getStart(), dom.isBlock), dom.getParent(se.getEnd(), dom.isBlock)), function(e) {
     7607                    dom.setAttrib(e, 'align', '');
     7608                    dom.setStyle(e, 'textAlign', v == 'full' ? 'justify' : v);
     7609                });
     7610
     7611                return;
     7612            } else if (!rm)
     7613                ed.getDoc().execCommand(c, false, null);
     7614
     7615            if (ed.settings.inline_styles) {
     7616                if (rm) {
     7617                    dom.getParent(ed.selection.getNode(), function(n) {
     7618                        if (n.style && n.style.textAlign)
     7619                            dom.setStyle(n, 'textAlign', '');
     7620                    });
     7621
     7622                    return;
     7623                }
     7624
     7625                each(dom.select('*'), function(n) {
     7626                    var v = n.align;
     7627
     7628                    if (v) {
     7629                        if (v == 'full')
     7630                            v = 'justify';
     7631
     7632                        dom.setStyle(n, 'textAlign', v);
     7633                        dom.setAttrib(n, 'align', '');
     7634                    }
     7635                });
     7636            }
     7637        },
     7638
     7639        mceSetCSSClass : function(u, v) {
     7640            this.mceSetStyleInfo(0, {command : 'setattrib', name : 'class', value : v});
     7641        },
     7642
     7643        getSelectedElement : function() {
     7644            var t = this, ed = t.editor, dom = ed.dom, se = ed.selection, r = se.getRng(), r1, r2, sc, ec, so, eo, e, sp, ep, re;
     7645
     7646            if (se.isCollapsed() || r.item)
     7647                return se.getNode();
     7648
     7649            // Setup regexp
     7650            re = ed.settings.merge_styles_invalid_parents;
     7651            if (tinymce.is(re, 'string'))
     7652                re = new RegExp(re, 'i');
     7653
     7654            if (isIE) {
     7655                r1 = r.duplicate();
     7656                r1.collapse(true);
     7657                sc = r1.parentElement();
     7658
     7659                r2 = r.duplicate();
     7660                r2.collapse(false);
     7661                ec = r2.parentElement();
     7662
     7663                if (sc != ec) {
     7664                    r1.move('character', 1);
     7665                    sc = r1.parentElement();
     7666                }
     7667
     7668                if (sc == ec) {
     7669                    r1 = r.duplicate();
     7670                    r1.moveToElementText(sc);
     7671
     7672                    if (r1.compareEndPoints('StartToStart', r) == 0 && r1.compareEndPoints('EndToEnd', r) == 0)
     7673                        return re && re.test(sc.nodeName) ? null : sc;
     7674                }
     7675            } else {
     7676                function getParent(n) {
     7677                    return dom.getParent(n, function(n) {return n.nodeType == 1;});
     7678                };
     7679
     7680                sc = r.startContainer;
     7681                ec = r.endContainer;
     7682                so = r.startOffset;
     7683                eo = r.endOffset;
     7684
     7685                if (!r.collapsed) {
     7686                    if (sc == ec) {
     7687                        if (so - eo < 2) {
     7688                            if (sc.hasChildNodes()) {
     7689                                sp = sc.childNodes[so];
     7690                                return re && re.test(sp.nodeName) ? null : sp;
     7691                            }
     7692                        }
     7693                    }
     7694                }
     7695
     7696                if (sc.nodeType != 3 || ec.nodeType != 3)
     7697                    return null;
     7698
     7699                if (so == 0) {
     7700                    sp = getParent(sc);
     7701
     7702                    if (sp && sp.firstChild != sc)
     7703                        sp = null;
     7704                }
     7705
     7706                if (so == sc.nodeValue.length) {
     7707                    e = sc.nextSibling;
     7708
     7709                    if (e && e.nodeType == 1)
     7710                        sp = sc.nextSibling;
     7711                }
     7712
     7713                if (eo == 0) {
     7714                    e = ec.previousSibling;
     7715
     7716                    if (e && e.nodeType == 1)
     7717                        ep = e;
     7718                }
     7719
     7720                if (eo == ec.nodeValue.length) {
     7721                    ep = getParent(ec);
     7722
     7723                    if (ep && ep.lastChild != ec)
     7724                        ep = null;
     7725                }
     7726
     7727                // Same element
     7728                if (sp == ep)
     7729                    return re && sp && re.test(sp.nodeName) ? null : sp;
     7730            }
     7731
     7732            return null;
     7733        },
     7734
     7735        InsertHorizontalRule : function() {
     7736            // Fix for Gecko <hr size="1" /> issue and IE bug rep(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]");
     7737            if (isGecko || isIE)
     7738                this.editor.selection.setContent('<hr />');
     7739            else
     7740                this.editor.getDoc().execCommand('InsertHorizontalRule', false, '');
     7741        },
     7742
     7743        RemoveFormat : function() {
     7744            var t = this, ed = t.editor, s = ed.selection, b;
     7745
     7746            // Safari breaks tables
     7747            if (isWebKit)
     7748                s.setContent(s.getContent({format : 'raw'}).replace(/(<(span|b|i|strong|em|strike) [^>]+>|<(span|b|i|strong|em|strike)>|<\/(span|b|i|strong|em|strike)>|)/g, ''), {format : 'raw'});
     7749            else
     7750                ed.getDoc().execCommand('RemoveFormat', false, null);
     7751
     7752            t.mceSetStyleInfo(0, {command : 'removeformat'});
     7753            ed.addVisual();
     7754        },
     7755
     7756        mceSetStyleInfo : function(u, v) {
     7757            var t = this, ed = t.editor, d = ed.getDoc(), dom = ed.dom, e, b, s = ed.selection, nn = v.wrapper || 'span', b = s.getBookmark(), re;
     7758
     7759            function set(n, e) {
     7760                if (n.nodeType == 1) {
     7761                    switch (v.command) {
     7762                        case 'setattrib':
     7763                            return dom.setAttrib(n, v.name, v.value);
     7764
     7765                        case 'setstyle':
     7766                            return dom.setStyle(n, v.name, v.value);
     7767
     7768                        case 'removeformat':
     7769                            return dom.setAttrib(n, 'class', '');
     7770                    }
     7771                }
     7772            };
     7773
     7774            // Setup regexp
     7775            re = ed.settings.merge_styles_invalid_parents;
     7776            if (tinymce.is(re, 'string'))
     7777                re = new RegExp(re, 'i');
     7778
     7779            // Set style info on selected element
     7780            if (e = t.getSelectedElement())
     7781                set(e, 1);
     7782            else {
     7783                // Generate wrappers and set styles on them
     7784                d.execCommand('FontName', false, '__');
     7785                each(isWebKit ? dom.select('span') : dom.select('font'), function(n) {
     7786                    var sp, e;
     7787
     7788                    if (dom.getAttrib(n, 'face') == '__' || n.style.fontFamily === '__') {
     7789                        sp = dom.create(nn, {mce_new : '1'});
     7790
     7791                        set(sp);
     7792
     7793                        each (n.childNodes, function(n) {
     7794                            sp.appendChild(n.cloneNode(true));
     7795                        });
     7796
     7797                        dom.replace(sp, n);
     7798                    }
     7799                });
     7800            }
     7801
     7802            // Remove wrappers inside new ones
     7803            each(dom.select(nn).reverse(), function(n) {
     7804                var p = n.parentNode;
     7805
     7806                dom.setAttrib(n, 'mce_new', '');
     7807
     7808                // Check if it's an old span in a new wrapper
     7809                if (!dom.getAttrib(n, 'mce_new')) {
     7810                    // Find new wrapper
     7811                    p = dom.getParent(n, function(n) {
     7812                        return n.nodeType == 1 && dom.getAttrib(n, 'mce_new');
     7813                    });
     7814
     7815                    if (p)
     7816                        dom.remove(n, 1);
     7817                }
     7818            });
     7819
     7820            // Merge wrappers with parent wrappers
     7821            each(dom.select(nn).reverse(), function(n) {
     7822                var p = n.parentNode;
     7823
     7824                if (!p)
     7825                    return;
     7826
     7827                // Has parent of the same type and only child
     7828                if (p.nodeName == nn.toUpperCase() && p.childNodes.length == 1)
     7829                    return dom.remove(p, 1);
     7830
     7831                // Has parent that is more suitable to have the class and only child
     7832                if (n.nodeType == 1 && (!re || !re.test(p.nodeName)) && p.childNodes.length == 1) {
     7833                    set(p); // Set style info on parent instead
     7834                    dom.setAttrib(n, 'class', '');
     7835                }
     7836            });
     7837
     7838            // Remove empty wrappers
     7839            each(dom.select(nn).reverse(), function(n) {
     7840                if (!dom.getAttrib(n, 'class') && !dom.getAttrib(n, 'style'))
     7841                    return dom.remove(n, 1);
     7842            });
     7843
     7844            s.moveToBookmark(b);
     7845        },
     7846
     7847        queryStateJustify : function(c, v) {
     7848            var ed = this.editor, n = ed.selection.getNode(), dom = ed.dom;
     7849
     7850            if (n && n.nodeName == 'IMG')
     7851                return dom.getStyle(n, 'float') == v;
     7852
     7853            n = dom.getParent(ed.selection.getStart(), function(n) {
     7854                return n.nodeType == 1 && n.style.textAlign;
     7855            });
     7856
     7857            if (v == 'full')
     7858                v = 'justify';
     7859
     7860            if (ed.settings.inline_styles)
     7861                return (n && n.style.textAlign == v);
     7862
     7863            return ed.getDoc().queryCommandState(c);
     7864        },
     7865
     7866        HiliteColor : function(ui, val) {
     7867            var t = this, ed = t.editor, d = ed.getDoc();
     7868
     7869            function set(s) {
     7870                if (!isGecko)
     7871                    return;
     7872
    64597873                try {
    6460                     bookmark.rng.select();
     7874                    // Try new Gecko method
     7875                    d.execCommand("styleWithCSS", 0, s);
     7876                } catch (ex) {
     7877                    // Use old
     7878                    d.execCommand("useCSS", 0, !s);
     7879                }
     7880            };
     7881
     7882            if (isGecko || isOpera) {
     7883                set(true);
     7884                d.execCommand('hilitecolor', false, val);
     7885                set(false);
     7886            } else
     7887                d.execCommand('BackColor', false, val);
     7888        },
     7889
     7890        Undo : function() {
     7891            var ed = this.editor;
     7892
     7893            if (ed.settings.custom_undo_redo) {
     7894                ed.undoManager.undo();
     7895                ed.nodeChanged();
     7896            } else
     7897                ed.getDoc().execCommand('Undo', false, null);
     7898        },
     7899
     7900        Redo : function() {
     7901            var ed = this.editor;
     7902
     7903            if (ed.settings.custom_undo_redo) {
     7904                ed.undoManager.redo();
     7905                ed.nodeChanged();
     7906            } else
     7907                ed.getDoc().execCommand('Redo', false, null);
     7908        },
     7909
     7910        FormatBlock : function(ui, val) {
     7911            var t = this, ed = t.editor;
     7912
     7913            val = ed.settings.forced_root_block ? (val || '<p>') : val;
     7914            t.mceRemoveNode();
     7915
     7916            if (val.indexOf('<') == -1)
     7917                val = '<' + val + '>';
     7918
     7919            if (tinymce.isGecko)
     7920                val = val.replace(/<(div|blockquote|code|dt|dd|dl|samp)>/gi, '$1');
     7921
     7922            ed.getDoc().execCommand('FormatBlock', false, val);
     7923        },
     7924
     7925        mceCleanup : function() {
     7926            var ed = this.editor, s = ed.selection, b = s.getBookmark();
     7927            ed.setContent(ed.getContent());
     7928            s.moveToBookmark(b);
     7929        },
     7930
     7931        mceRemoveNode : function(ui, val) {
     7932            var ed = this.editor, s = ed.selection, b, n = val || s.getNode();
     7933
     7934            // Make sure that the body node isn't removed
     7935            if (n == ed.getBody())
     7936                return;
     7937
     7938            b = s.getBookmark();
     7939            ed.dom.remove(n, 1);
     7940            s.moveToBookmark(b);
     7941            ed.nodeChanged();
     7942        },
     7943
     7944        mceSelectNodeDepth : function(ui, val) {
     7945            var ed = this.editor, s = ed.selection, c = 0;
     7946
     7947            ed.dom.getParent(s.getNode(), function(n) {
     7948                if (n.nodeType == 1 && c++ == val) {
     7949                    s.select(n);
     7950                    ed.nodeChanged();
     7951                    return false;
     7952                }
     7953            }, ed.getBody());
     7954        },
     7955
     7956        mceSelectNode : function(u, v) {
     7957            this.editor.selection.select(v);
     7958        },
     7959
     7960        mceInsertContent : function(ui, val) {
     7961            this.editor.selection.setContent(val);
     7962        },
     7963
     7964        mceInsertRawHTML : function(ui, val) {
     7965            var ed = this.editor;
     7966
     7967            ed.execCommand('mceInsertContent', false, 'tiny_mce_marker');
     7968            ed.setContent(ed.getContent().replace(/tiny_mce_marker/g, val));
     7969        },
     7970
     7971        mceRepaint : function() {
     7972            var s, b, e = this.editor;
     7973
     7974            if (tinymce.isGecko) {
     7975                try {
     7976                    s = e.selection;
     7977                    b = s.getBookmark(true);
     7978
     7979                    if (s.getSel())
     7980                        s.getSel().selectAllChildren(e.getBody());
     7981
     7982                    s.collapse(true);
     7983                    s.moveToBookmark(b);
    64617984                } catch (ex) {
    64627985                    // Ignore
    64637986                }
    6464 
     7987            }
     7988        },
     7989
     7990        queryStateUnderline : function() {
     7991            var ed = this.editor, n;
     7992
     7993            if (n && n.nodeName == 'A')
     7994                return false;
     7995
     7996            return ed.getDoc().queryCommandState('Underline');
     7997        },
     7998
     7999        queryStateOutdent : function() {
     8000            var ed = this.editor, n;
     8001
     8002            if (ed.settings.inline_styles) {
     8003                if ((n = ed.dom.getParent(ed.selection.getStart(), ed.dom.isBlock)) && parseInt(n.style.paddingLeft) > 0)
     8004                    return true;
     8005
     8006                if ((n = ed.dom.getParent(ed.selection.getEnd(), ed.dom.isBlock)) && parseInt(n.style.paddingLeft) > 0)
     8007                    return true;
     8008            } else
     8009                return !!ed.dom.getParent(ed.selection.getNode(), 'BLOCKQUOTE');
     8010
     8011            return this.queryStateInsertUnorderedList() || this.queryStateInsertOrderedList();
     8012        },
     8013
     8014        queryStateInsertUnorderedList : function() {
     8015            return this.editor.dom.getParent(this.editor.selection.getNode(), 'UL');
     8016        },
     8017
     8018        queryStateInsertOrderedList : function() {
     8019            return this.editor.dom.getParent(this.editor.selection.getNode(), 'OL');
     8020        },
     8021
     8022        queryStatemceBlockQuote : function() {
     8023            return !!this.editor.dom.getParent(this.editor.selection.getStart(), function(n) {return n.nodeName === 'BLOCKQUOTE';});
     8024        },
     8025
     8026        mceBlockQuote : function() {
     8027            var t = this, s = t.editor.selection, b = s.getBookmark(), bq, dom = t.editor.dom;
     8028
     8029            function findBQ(e) {
     8030                return dom.getParent(e, function(n) {return n.nodeName === 'BLOCKQUOTE';});
     8031            };
     8032
     8033            // Remove blockquote(s)
     8034            if (findBQ(s.getStart())) {
     8035                each(t._getSelectedBlocks(findBQ(s.getStart()), findBQ(s.getEnd())), function(e) {
     8036                    // Found BQ lets remove it
     8037                    if (e.nodeName == 'BLOCKQUOTE')
     8038                        dom.remove(e, 1);
     8039                });
     8040
     8041                t.editor.selection.moveToBookmark(b);
     8042                return;
     8043            }
     8044
     8045            each(t._getSelectedBlocks(findBQ(s.getStart()), findBQ(s.getEnd())), function(e) {
     8046                var n;
     8047
     8048                // Found existing BQ add to this one
     8049                if (e.nodeName == 'BLOCKQUOTE' && !bq) {
     8050                    bq = e;
     8051                    return;
     8052                }
     8053
     8054                // No BQ found, create one
     8055                if (!bq) {
     8056                    bq = dom.create('blockquote');
     8057                    e.parentNode.insertBefore(bq, e);
     8058                }
     8059
     8060                // Add children from existing BQ
     8061                if (e.nodeName == 'BLOCKQUOTE' && bq) {
     8062                    n = e.firstChild;
     8063
     8064                    while (n) {
     8065                        bq.appendChild(n.cloneNode(true));
     8066                        n = n.nextSibling;
     8067                    }
     8068
     8069                    dom.remove(e);
     8070
     8071                    return;
     8072                }
     8073
     8074                // Add non BQ element to BQ
     8075                bq.appendChild(dom.remove(e));
     8076            });
     8077
     8078            t.editor.selection.moveToBookmark(b);
     8079        },
     8080
     8081        _getSelectedBlocks : function(st, en) {
     8082            var ed = this.editor, dom = ed.dom, s = ed.selection, sb, eb, n, bl = [];
     8083
     8084            sb = dom.getParent(st || s.getStart(), dom.isBlock);
     8085            eb = dom.getParent(en || s.getEnd(), dom.isBlock);
     8086
     8087            if (sb)
     8088                bl.push(sb);
     8089
     8090            if (sb && eb && sb != eb) {
     8091                n = sb;
     8092
     8093                while ((n = n.nextSibling) && n != eb) {
     8094                    if (dom.isBlock(n))
     8095                        bl.push(n);
     8096                }
     8097            }
     8098
     8099            if (eb && sb != eb)
     8100                bl.push(eb);
     8101
     8102            return bl;
     8103        }
     8104    });
     8105})();
     8106
     8107
     8108/* file:jscripts/tiny_mce/classes/UndoManager.js */
     8109
     8110tinymce.create('tinymce.UndoManager', {
     8111    index : 0,
     8112    data : null,
     8113    typing : 0,
     8114
     8115    UndoManager : function(ed) {
     8116        var t = this, Dispatcher = tinymce.util.Dispatcher;
     8117
     8118        t.editor = ed;
     8119        t.data = [];
     8120        t.onAdd = new Dispatcher(this);
     8121        t.onUndo = new Dispatcher(this);
     8122        t.onRedo = new Dispatcher(this);
     8123    },
     8124
     8125    add : function(l) {
     8126        var t = this, i, ed = t.editor, b, s = ed.settings, la;
     8127
     8128        l = l || {};
     8129        l.content = l.content || ed.getContent({format : 'raw', no_events : 1});
     8130
     8131        // Add undo level if needed
     8132        l.content = l.content.replace(/^\s*|\s*$/g, '');
     8133        la = t.data[t.index > 0 ? t.index - 1 : 0];
     8134        if (!l.initial && la && l.content == la.content)
     8135            return null;
     8136
     8137        // Time to compress
     8138        if (s.custom_undo_redo_levels) {
     8139            if (t.data.length > s.custom_undo_redo_levels) {
     8140                for (i = 0; i < t.data.length - 1; i++)
     8141                    t.data[i] = t.data[i + 1];
     8142
     8143                t.data.length--;
     8144                t.index = t.data.length;
     8145            }
     8146        }
     8147
     8148        if (s.custom_undo_redo_restore_selection)
     8149            l.bookmark = b = l.bookmark || ed.selection.getBookmark();
     8150
     8151        if (t.index < t.data.length && t.data[t.index].initial)
     8152            t.index++;
     8153
     8154        // Add level
     8155        t.data.length = t.index + 1;
     8156        t.data[t.index++] = l;
     8157
     8158        if (l.initial)
     8159            t.index = 0;
     8160
     8161        // Set initial bookmark use first real undo level
     8162        if (t.data.length == 2 && t.data[0].initial)
     8163            t.data[0].bookmark = b;
     8164
     8165        t.onAdd.dispatch(t, l);
     8166
     8167        //console.dir(t.data);
     8168
     8169        return l;
     8170    },
     8171
     8172    undo : function() {
     8173        var t = this, ed = t.editor, l = l, i;
     8174
     8175        if (t.typing) {
     8176            t.add();
     8177            t.typing = 0;
     8178        }
     8179
     8180        if (t.index > 0) {
     8181            // If undo on last index then take snapshot
     8182            if (t.index == t.data.length && t.index > 1) {
     8183                i = t.index;
     8184                t.typing = 0;
     8185
     8186                if (!t.add())
     8187                    t.index = i;
     8188
     8189                --t.index;
     8190            }
     8191
     8192            l = t.data[--t.index];
     8193            ed.setContent(l.content, {format : 'raw'});
     8194            ed.selection.moveToBookmark(l.bookmark);
     8195
     8196            t.onUndo.dispatch(t, l);
     8197        }
     8198
     8199        return l;
     8200    },
     8201
     8202    redo : function() {
     8203        var t = this, ed = t.editor, l = null;
     8204
     8205        if (t.index < t.data.length - 1) {
     8206            l = t.data[++t.index];
     8207            ed.setContent(l.content, {format : 'raw'});
     8208            ed.selection.moveToBookmark(l.bookmark);
     8209
     8210            t.onRedo.dispatch(t, l);
     8211        }
     8212
     8213        return l;
     8214    },
     8215
     8216    clear : function() {
     8217        var t = this;
     8218
     8219        t.data = [];
     8220        t.index = 0;
     8221        t.typing = 0;
     8222        t.add({initial : true});
     8223    },
     8224
     8225    hasUndo : function() {
     8226        return this.index != 0 || this.typing;
     8227    },
     8228
     8229    hasRedo : function() {
     8230        return this.index < this.data.length - 1;
     8231    }
     8232
     8233    });
     8234/* file:jscripts/tiny_mce/classes/ForceBlocks.js */
     8235
     8236(function() {
     8237    // Shorten names
     8238    var Event, isIE, isGecko, isOpera, each, extend;
     8239
     8240    Event = tinymce.dom.Event;
     8241    isIE = tinymce.isIE;
     8242    isGecko = tinymce.isGecko;
     8243    isOpera = tinymce.isOpera;
     8244    each = tinymce.each;
     8245    extend = tinymce.extend;
     8246
     8247    tinymce.create('tinymce.ForceBlocks', {
     8248        ForceBlocks : function(ed) {
     8249            var t = this, s;
     8250
     8251            t.editor = ed;
     8252            t.dom = ed.dom;
     8253
     8254            // Default settings
     8255            t.settings = s = extend({
     8256                element : 'P',
     8257                forced_root_block : 'p',
     8258                force_p_newlines : true
     8259            }, ed.settings);
     8260
     8261            ed.onPreInit.add(t.setup, t);
     8262
     8263            if (!isIE) {
     8264                ed.onSetContent.add(function(ed, o) {
     8265                    o.content = o.content.replace(/<p>[\s\u00a0]+<\/p>/g, '<p><br /></p>');
     8266                });
     8267            }
     8268
     8269            ed.onPostProcess.add(function(ed, o) {
     8270                if (isOpera)
     8271                    o.content = o.content.replace(/(\u00a0|&#160;|&nbsp;)<\/p>/g, '</p>');
     8272
     8273                o.content = o.content.replace(/<p><\/p>/g, '<p>\u00a0</p>');
     8274
     8275                // Use BR instead of &nbsp; padded paragraphs
     8276                o.content = o.content.replace(/<p>\s*<br \/>\s*<\/p>/g, '<p>\u00a0</p>');
     8277                o.content = o.content.replace(/\s*<br \/>\s*<\/p>/g, '</p>');
     8278            });
     8279
     8280            if (s.forced_root_block) {
     8281                ed.onInit.add(t.forceRoots, t);
     8282                ed.onSetContent.add(t.forceRoots, t);
     8283                ed.onBeforeGetContent.add(t.forceRoots, t);
     8284            }
     8285        },
     8286
     8287        setup : function() {
     8288            var t = this, ed = t.editor, s = t.settings;
     8289
     8290            // Force root blocks when typing and when getting output
     8291            if (s.forced_root_block) {
     8292                ed.onKeyUp.add(t.forceRoots, t);
     8293                ed.onPreProcess.add(t.forceRoots, t);
     8294            }
     8295
     8296            if (s.force_br_newlines) {
     8297                // Force IE to produce BRs on enter
     8298                if (isIE) {
     8299                    ed.onKeyPress.add(function(ed, e) {
     8300                        var n, s = ed.selection;
     8301
     8302                        if (e.keyCode == 13) {
     8303                            s.setContent('<br id="__" /> ', {format : 'raw'});
     8304                            n = ed.dom.get('__');
     8305                            n.removeAttribute('id');
     8306                            s.select(n);
     8307                            s.collapse();
     8308                            return Event.cancel(e);
     8309                        }
     8310                    });
     8311                }
     8312
     8313                return;
     8314            }
     8315
     8316            if (!isIE && s.force_p_newlines) {
     8317                ed.onPreProcess.add(function(ed, o) {
     8318                    each(ed.dom.select('br', o.node), function(n) {
     8319                        var p = n.parentNode;
     8320
     8321                        // Replace <p><br /></p> with <p>&nbsp;</p>
     8322                        if (p && p.nodeName == 'p' && (p.childNodes.length == 1 || p.lastChild == n))
     8323                            p.replaceChild(ed.getDoc().createTextNode('\u00a0'), n);
     8324                    });
     8325                });
     8326
     8327                ed.onKeyPress.add(function(ed, e) {
     8328                    if (e.keyCode == 13 && !e.shiftKey) {
     8329                        if (!t.insertPara(e))
     8330                            Event.cancel(e);
     8331                    }
     8332                });
     8333
     8334                if (isGecko) {
     8335                    ed.onKeyDown.add(function(ed, e) {
     8336                        if ((e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey)
     8337                            t.backspaceDelete(e, e.keyCode == 8);
     8338                    });
     8339                }
     8340            }
     8341        },
     8342
     8343        find : function(n, t, s) {
     8344            var ed = this.editor, w = ed.getDoc().createTreeWalker(n, 4, null, false), c = -1;
     8345
     8346            while (n = w.nextNode()) {
     8347                c++;
     8348
     8349                // Index by node
     8350                if (t == 0 && n == s)
     8351                    return c;
     8352
     8353                // Node by index
     8354                if (t == 1 && c == s)
     8355                    return n;
     8356            }
     8357
     8358            return -1;
     8359        },
     8360
     8361        forceRoots : function(ed, e) {
     8362            var t = this, ed = t.editor, b = ed.getBody(), d = ed.getDoc(), se = ed.selection, s = se.getSel(), r = se.getRng(), si = -2, ei, so, eo, tr, c = -0xFFFFFF;
     8363            var nx, bl, bp, sp, le, nl = b.childNodes, i;
     8364
     8365            // Fix for bug #1863847
     8366            if (e && e.keyCode == 13)
    64658367                return true;
    6466             }
    6467 
    6468             win.focus();
    6469 
    6470             if (bookmark.tag) {
    6471                 rng = b.createControlRange();
    6472 
    6473                 nl = b.getElementsByTagName(bookmark.tag);
    6474 
    6475                 if (nl.length > bookmark.index) {
     8368
     8369            // Wrap non blocks into blocks
     8370            for (i = nl.length - 1; i >= 0; i--) {
     8371                nx = nl[i];
     8372
     8373                // Is text or non block element
     8374                if (nx.nodeType == 3 || !t.dom.isBlock(nx)) {
     8375                    if (!bl) {
     8376                        // Create new block but ignore whitespace
     8377                        if (nx.nodeType != 3 || /[^\s]/g.test(nx.nodeValue)) {
     8378                            // Store selection
     8379                            if (si == -2 && r) {
     8380                                if (!isIE) {
     8381                                    so = r.startOffset;
     8382                                    eo = r.endOffset;
     8383                                    si = t.find(b, 0, r.startContainer);
     8384                                    ei = t.find(b, 0, r.endContainer);
     8385                                } else {
     8386                                    tr = d.body.createTextRange();
     8387                                    tr.moveToElementText(b);
     8388                                    tr.collapse(1);
     8389                                    bp = tr.move('character', c) * -1;
     8390
     8391                                    tr = r.duplicate();
     8392                                    tr.collapse(1);
     8393                                    sp = tr.move('character', c) * -1;
     8394
     8395                                    tr = r.duplicate();
     8396                                    tr.collapse(0);
     8397                                    le = (tr.move('character', c) * -1) - sp;
     8398
     8399                                    si = sp - bp;
     8400                                    ei = le;
     8401                                }
     8402                            }
     8403
     8404                            bl = ed.dom.create(t.settings.forced_root_block);
     8405                            bl.appendChild(nx.cloneNode(1));
     8406                            b.replaceChild(bl, nx);
     8407                        }
     8408                    } else {
     8409                        if (bl.hasChildNodes())
     8410                            bl.insertBefore(nx, bl.firstChild);
     8411                        else
     8412                            bl.appendChild(nx);
     8413                    }
     8414                } else
     8415                    bl = null; // Time to create new block
     8416            }
     8417
     8418            // Restore selection
     8419            if (si != -2) {
     8420                if (!isIE) {
     8421                    bl = d.getElementsByTagName(t.settings.element)[0];
     8422                    r = d.createRange();
     8423
     8424                    // Select last location or generated block
     8425                    if (si != -1)
     8426                        r.setStart(t.find(b, 1, si), so);
     8427                    else
     8428                        r.setStart(bl, 0);
     8429
     8430                    // Select last location or generated block
     8431                    if (ei != -1)
     8432                        r.setEnd(t.find(b, 1, ei), eo);
     8433                    else
     8434                        r.setEnd(bl, 0);
     8435
     8436                    if (s) {
     8437                        s.removeAllRanges();
     8438                        s.addRange(r);
     8439                    }
     8440                } else {
    64768441                    try {
    6477                         rng.addElement(nl[bookmark.index]);
     8442                        r = s.createRange();
     8443                        r.moveToElementText(b);
     8444                        r.collapse(1);
     8445                        r.moveStart('character', si);
     8446                        r.moveEnd('character', ei);
     8447                        r.select();
    64788448                    } catch (ex) {
    6479                         // Might be thrown if the node no longer exists
     8449                        // Ignore
    64808450                    }
    64818451                }
     8452            }
     8453        },
     8454
     8455        getParentBlock : function(n) {
     8456            var d = this.dom;
     8457
     8458            return d.getParent(n, d.isBlock);
     8459        },
     8460
     8461        insertPara : function(e) {
     8462            var t = this, ed = t.editor, d = ed.getDoc(), se = t.settings, s = ed.selection.getSel(), r = s.getRangeAt(0), b = d.body;
     8463            var rb, ra, dir, sn, so, en, eo, sb, eb, bn, bef, aft, sc, ec, n;
     8464
     8465            function isEmpty(n) {
     8466                n = n.innerHTML;
     8467                n = n.replace(/<(img|hr|table)/gi, '-'); // Keep these convert them to - chars
     8468                n = n.replace(/<[^>]+>/g, ''); // Remove all tags
     8469
     8470                return n.replace(/[ \t\r\n]+/g, '') == '';
     8471            };
     8472
     8473            // If root blocks are forced then use Operas default behavior since it's really good
     8474// Removed due to bug: #1853816
     8475//          if (se.forced_root_block && isOpera)
     8476//              return true;
     8477
     8478            // Setup before range
     8479            rb = d.createRange();
     8480
     8481            // If is before the first block element and in body, then move it into first block element
     8482            rb.setStart(s.anchorNode, s.anchorOffset);
     8483            rb.collapse(true);
     8484
     8485            // Setup after range
     8486            ra = d.createRange();
     8487
     8488            // If is before the first block element and in body, then move it into first block element
     8489            ra.setStart(s.focusNode, s.focusOffset);
     8490            ra.collapse(true);
     8491
     8492            // Setup start/end points
     8493            dir = rb.compareBoundaryPoints(rb.START_TO_END, ra) < 0;
     8494            sn = dir ? s.anchorNode : s.focusNode;
     8495            so = dir ? s.anchorOffset : s.focusOffset;
     8496            en = dir ? s.focusNode : s.anchorNode;
     8497            eo = dir ? s.focusOffset : s.anchorOffset;
     8498
     8499            // If the caret is in an invalid location in FF we need to move it into the first block
     8500            if (sn == b && en == b && b.firstChild && ed.dom.isBlock(b.firstChild)) {
     8501                sn = en = sn.firstChild;
     8502                so = eo = 0;
     8503                rb = d.createRange();
     8504                rb.setStart(sn, 0);
     8505                ra = d.createRange();
     8506                ra.setStart(en, 0);
     8507            }
     8508
     8509            // Never use body as start or end node
     8510            sn = sn.nodeName == "BODY" ? sn.firstChild : sn;
     8511            en = en.nodeName == "BODY" ? en.firstChild : en;
     8512
     8513            // Get start and end blocks
     8514            sb = t.getParentBlock(sn);
     8515            eb = t.getParentBlock(en);
     8516            bn = sb ? sb.nodeName : se.element; // Get block name to create
     8517
     8518            // Return inside list use default browser behavior
     8519            if (t.dom.getParent(sb, function(n) { return /OL|UL|PRE/.test(n.nodeName); }))
     8520                return true;
     8521
     8522            // If caption or absolute layers then always generate new blocks within
     8523            if (sb && (sb.nodeName == 'CAPTION' || /absolute|relative|static/gi.test(sb.style.position))) {
     8524                bn = se.element;
     8525                sb = null;
     8526            }
     8527
     8528            // If caption or absolute layers then always generate new blocks within
     8529            if (eb && (eb.nodeName == 'CAPTION' || /absolute|relative|static/gi.test(eb.style.position))) {
     8530                bn = se.element;
     8531                eb = null;
     8532            }
     8533
     8534            // Use P instead
     8535            if (/(TD|TABLE|TH|CAPTION)/.test(bn) || (sb && bn == "DIV" && /left|right/gi.test(sb.style.cssFloat))) {
     8536                bn = se.element;
     8537                sb = eb = null;
     8538            }
     8539
     8540            // Setup new before and after blocks
     8541            bef = (sb && sb.nodeName == bn) ? sb.cloneNode(0) : ed.dom.create(bn);
     8542            aft = (eb && eb.nodeName == bn) ? eb.cloneNode(0) : ed.dom.create(bn);
     8543
     8544            // Remove id from after clone
     8545            aft.removeAttribute('id');
     8546
     8547            // Is header and cursor is at the end, then force paragraph under
     8548            if (/^(H[1-6])$/.test(bn) && sn.nodeValue && so == sn.nodeValue.length)
     8549                aft = ed.dom.create(se.element);
     8550
     8551            // Find start chop node
     8552            n = sc = sn;
     8553            do {
     8554                if (n == b || n.nodeType == 9 || t.dom.isBlock(n) || /(TD|TABLE|TH|CAPTION)/.test(n.nodeName))
     8555                    break;
     8556
     8557                sc = n;
     8558            } while ((n = n.previousSibling ? n.previousSibling : n.parentNode));
     8559
     8560            // Find end chop node
     8561            n = ec = en;
     8562            do {
     8563                if (n == b || n.nodeType == 9 || t.dom.isBlock(n) || /(TD|TABLE|TH|CAPTION)/.test(n.nodeName))
     8564                    break;
     8565
     8566                ec = n;
     8567            } while ((n = n.nextSibling ? n.nextSibling : n.parentNode));
     8568
     8569            // Place first chop part into before block element
     8570            if (sc.nodeName == bn)
     8571                rb.setStart(sc, 0);
     8572            else
     8573                rb.setStartBefore(sc);
     8574
     8575            rb.setEnd(sn, so);
     8576            bef.appendChild(rb.cloneContents() || d.createTextNode('')); // Empty text node needed for Safari
     8577
     8578            // Place secnd chop part within new block element
     8579            try {
     8580                ra.setEndAfter(ec);
     8581            } catch(ex) {
     8582                //console.debug(s.focusNode, s.focusOffset);
     8583            }
     8584
     8585            ra.setStart(en, eo);
     8586            aft.appendChild(ra.cloneContents() || d.createTextNode('')); // Empty text node needed for Safari
     8587
     8588            // Create range around everything
     8589            r = d.createRange();
     8590            if (!sc.previousSibling && sc.parentNode.nodeName == bn) {
     8591                r.setStartBefore(sc.parentNode);
    64828592            } else {
    6483                 // Try/catch needed since this operation breaks when TinyMCE is placed in hidden divs/tabs
    6484                 try {
    6485                     // Incorrect bookmark
    6486                     if (bookmark.start < 0)
    6487                         return true;
    6488 
    6489                     rng = inst.getSel().createRange();
    6490                     rng.moveToElementText(inst.getBody());
    6491                     rng.collapse(true);
    6492                     rng.moveStart('character', bookmark.start);
    6493                     rng.moveEnd('character', bookmark.length);
    6494                 } catch (ex) {
    6495                     return true;
    6496                 }
    6497             }
    6498 
    6499             rng.select();
    6500 
    6501             win.scrollTo(bookmark.scrollX, bookmark.scrollY);
    6502             return true;
     8593                if (rb.startContainer.nodeName == bn && rb.startOffset == 0)
     8594                    r.setStartBefore(rb.startContainer);
     8595                else
     8596                    r.setStart(rb.startContainer, rb.startOffset);
     8597            }
     8598
     8599            if (!ec.nextSibling && ec.parentNode.nodeName == bn)
     8600                r.setEndAfter(ec.parentNode);
     8601            else
     8602                r.setEnd(ra.endContainer, ra.endOffset);
     8603
     8604            // Delete and replace it with new block elements
     8605            r.deleteContents();
     8606
     8607            // Never wrap blocks in blocks
     8608            if (bef.firstChild && bef.firstChild.nodeName == bn)
     8609                bef.innerHTML = bef.firstChild.innerHTML;
     8610
     8611            if (aft.firstChild && aft.firstChild.nodeName == bn)
     8612                aft.innerHTML = aft.firstChild.innerHTML;
     8613
     8614            // Padd empty blocks
     8615            if (isEmpty(bef))
     8616                bef.innerHTML = '<br />';
     8617
     8618            if (isEmpty(aft))
     8619                aft.innerHTML = isOpera ? '&nbsp;' : '<br />'; // Extra space for Opera so that the caret can move there
     8620
     8621            // Opera needs this one backwards
     8622            if (isOpera) {
     8623                r.insertNode(bef);
     8624                r.insertNode(aft);
     8625            } else {
     8626                r.insertNode(aft);
     8627                r.insertNode(bef);
     8628            }
     8629
     8630            // Normalize
     8631            aft.normalize();
     8632            bef.normalize();
     8633
     8634            // Move cursor and scroll into view
     8635            r = d.createRange();
     8636            r.selectNodeContents(aft);
     8637            r.collapse(1);
     8638            s.removeAllRanges();
     8639            s.addRange(r);
     8640            aft.scrollIntoView(0);
     8641
     8642            return false;
     8643        },
     8644
     8645        backspaceDelete : function(e, bs) {
     8646            var t = this, ed = t.editor, b = ed.getBody(), n, se = ed.selection, r = se.getRng(), sc = r.startContainer, n;
     8647
     8648            // The caret sometimes gets stuck in Gecko if you delete empty paragraphs
     8649            // This workaround removes the element by hand and moves the caret to the previous element
     8650            if (sc && ed.dom.isBlock(sc) && bs) {
     8651                if (sc.childNodes.length == 1 && sc.firstChild.nodeName == 'BR') {
     8652                    n = sc.previousSibling;
     8653                    if (n) {
     8654                        ed.dom.remove(sc);
     8655                        se.select(n, 1);
     8656                        se.collapse(0);
     8657                        return Event.cancel(e);
     8658                    }
     8659                }
     8660            }
     8661
     8662            // Gecko generates BR elements here and there, we don't like those so lets remove them
     8663            function handler(e) {
     8664                e = e.target;
     8665
     8666                // A new BR was created in a block element, remove it
     8667                if (e && e.parentNode && e.nodeName == 'BR' && t.getParentBlock(e)) {
     8668                    ed.dom.remove(e);
     8669                    Event.remove(b, 'DOMNodeInserted', handler);
     8670                }
     8671            };
     8672
     8673            // Listen for new nodes
     8674            Event._add(b, 'DOMNodeInserted', handler);
     8675
     8676            // Remove listener
     8677            window.setTimeout(function() {
     8678                Event._remove(b, 'DOMNodeInserted', handler);
     8679            }, 1);
    65038680        }
    6504 
    6505         if (tinyMCE.isGecko || tinyMCE.isOpera) {
    6506             if (!sel)
    6507                 return false;
    6508 
    6509             if (bookmark.rng) {
    6510                 sel.removeAllRanges();
    6511                 sel.addRange(bookmark.rng);
    6512             }
    6513 
    6514             if (bookmark.start != -1 && bookmark.end != -1) {
    6515                 try {
    6516                     sd = this._getTextPos(b, bookmark.start, bookmark.end);
    6517                     rng = doc.createRange();
    6518                     rng.setStart(sd.startNode, sd.startOffset);
    6519                     rng.setEnd(sd.endNode, sd.endOffset);
    6520                     sel.removeAllRanges();
    6521                     sel.addRange(rng);
    6522 
    6523                     if (!tinyMCE.isOpera)
    6524                         win.focus();
    6525                 } catch (ex) {
    6526                     // Ignore
    6527                 }
    6528             }
    6529 
    6530             /*
    6531             if (typeof(bookmark.index) != 'undefined') {
    6532                 tinyMCE.selectElements(b, 'IMG', function (n) {
    6533                     if (bookmark.index-- == 0) {
    6534                         // Select image in Gecko here
    6535                     }
    6536 
    6537                     return false;
     8681    });
     8682})();
     8683
     8684/* file:jscripts/tiny_mce/classes/ControlManager.js */
     8685
     8686(function() {
     8687    // Shorten names
     8688    var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, extend = tinymce.extend;
     8689
     8690    tinymce.create('tinymce.ControlManager', {
     8691        ControlManager : function(ed, s) {
     8692            var t = this, i;
     8693
     8694            s = s || {};
     8695            t.editor = ed;
     8696            t.controls = {};
     8697            t.onAdd = new tinymce.util.Dispatcher(t);
     8698            t.onPostRender = new tinymce.util.Dispatcher(t);
     8699            t.prefix = s.prefix || ed.id + '_';
     8700
     8701            t.onPostRender.add(function() {
     8702                each(t.controls, function(c) {
     8703                    c.postRender();
    65388704                });
    6539             }
    6540             */
    6541 
    6542             win.scrollTo(bookmark.scrollX, bookmark.scrollY);
    6543             return true;
     8705            });
     8706        },
     8707
     8708        get : function(id) {
     8709            return this.controls[this.prefix + id] || this.controls[id];
     8710        },
     8711
     8712        setActive : function(id, s) {
     8713            var c = null;
     8714
     8715            if (c = this.get(id))
     8716                c.setActive(s);
     8717
     8718            return c;
     8719        },
     8720
     8721        setDisabled : function(id, s) {
     8722            var c = null;
     8723
     8724            if (c = this.get(id))
     8725                c.setDisabled(s);
     8726
     8727            return c;
     8728        },
     8729
     8730        add : function(c) {
     8731            var t = this;
     8732
     8733            if (c) {
     8734                t.controls[c.id] = c;
     8735                t.onAdd.dispatch(c, t);
     8736            }
     8737
     8738            return c;
     8739        },
     8740
     8741        createControl : function(n) {
     8742            var c, t = this, ed = t.editor;
     8743
     8744            each(ed.plugins, function(p) {
     8745                if (p.createControl) {
     8746                    c = p.createControl(n, t);
     8747
     8748                    if (c)
     8749                        return false;
     8750                }
     8751            });
     8752
     8753            switch (n) {
     8754                case "|":
     8755                case "separator":
     8756                    return t.createSeparator();
     8757            }
     8758
     8759            if (!c && ed.buttons && (c = ed.buttons[n]))
     8760                return t.createButton(n, c);
     8761
     8762            return t.add(c);
     8763        },
     8764
     8765        createDropMenu : function(id, s) {
     8766            var t = this, ed = t.editor, c;
     8767
     8768            s = extend({
     8769                'class' : 'mceDropDown'
     8770            }, s);
     8771
     8772            s['class'] = s['class'] + ' ' + ed.getParam('skin') + 'Skin';
     8773
     8774            id = t.prefix + id;
     8775            c = t.controls[id] = new tinymce.ui.DropMenu(id, s);
     8776            c.onAddItem.add(function(c, o) {
     8777                var s = o.settings;
     8778
     8779                s.title = ed.getLang(s.title, s.title);
     8780
     8781                if (!s.onclick) {
     8782                    s.onclick = function(v) {
     8783                        ed.execCommand(s.cmd, s.ui || false, v || s.value);
     8784                    };
     8785                }
     8786            });
     8787
     8788            ed.onRemove.add(function() {
     8789                c.destroy();
     8790            });
     8791
     8792            return t.add(c);
     8793        },
     8794
     8795        createListBox : function(id, s) {
     8796            var t = this, ed = t.editor, cmd, c;
     8797
     8798            if (t.get(id))
     8799                return null;
     8800
     8801            s.title = ed.translate(s.title);
     8802            s.scope = s.scope || ed;
     8803
     8804            if (!s.onselect) {
     8805                s.onselect = function(v) {
     8806                    ed.execCommand(s.cmd, s.ui || false, v || s.value);
     8807                };
     8808            }
     8809
     8810            s = extend({
     8811                title : s.title,
     8812                'class' : id,
     8813                scope : s.scope,
     8814                control_manager : t
     8815            }, s);
     8816
     8817            id = t.prefix + id;
     8818
     8819            if (ed.settings.use_native_selects)
     8820                c = new tinymce.ui.NativeListBox(id, s);
     8821            else
     8822                c = new tinymce.ui.ListBox(id, s);
     8823
     8824            t.controls[id] = c;
     8825
     8826            // Fix focus problem in Safari
     8827            if (tinymce.isWebKit) {
     8828                c.onPostRender.add(function(c, n) {
     8829                    // Store bookmark on mousedown
     8830                    Event.add(n, 'mousedown', function() {
     8831                        ed.bookmark = ed.selection.getBookmark('simple');
     8832                    });
     8833
     8834                    // Restore on focus, since it might be lost
     8835                    Event.add(n, 'focus', function() {
     8836                        ed.selection.moveToBookmark(ed.bookmark);
     8837                        ed.bookmark = null;
     8838                    });
     8839                });
     8840            }
     8841
     8842            if (c.hideMenu)
     8843                ed.onMouseDown.add(c.hideMenu, c);
     8844
     8845            return t.add(c);
     8846        },
     8847
     8848        createButton : function(id, s) {
     8849            var t = this, ed = t.editor, o, c;
     8850
     8851            if (t.get(id))
     8852                return null;
     8853
     8854            s.title = ed.translate(s.title);
     8855            s.scope = s.scope || ed;
     8856
     8857            if (!s.onclick && !s.menu_button) {
     8858                s.onclick = function() {
     8859                    ed.execCommand(s.cmd, s.ui || false, s.value);
     8860                };
     8861            }
     8862
     8863            s = extend({
     8864                title : s.title,
     8865                'class' : id,
     8866                unavailable_prefix : ed.getLang('unavailable', ''),
     8867                scope : s.scope,
     8868                control_manager : t
     8869            }, s);
     8870
     8871            id = t.prefix + id;
     8872
     8873            if (s.menu_button) {
     8874                c = new tinymce.ui.MenuButton(id, s);
     8875                ed.onMouseDown.add(c.hideMenu, c);
     8876            } else
     8877                c = new tinymce.ui.Button(id, s);
     8878
     8879            return t.add(c);
     8880        },
     8881
     8882        createMenuButton : function(id, s) {
     8883            s = s || {};
     8884            s.menu_button = 1;
     8885
     8886            return this.createButton(id, s);
     8887        },
     8888
     8889        createSplitButton : function(id, s) {
     8890            var t = this, ed = t.editor, cmd, c;
     8891
     8892            if (t.get(id))
     8893                return null;
     8894
     8895            s.title = ed.translate(s.title);
     8896            s.scope = s.scope || ed;
     8897
     8898            if (!s.onclick) {
     8899                s.onclick = function(v) {
     8900                    ed.execCommand(s.cmd, s.ui || false, v || s.value);
     8901                };
     8902            }
     8903
     8904            if (!s.onselect) {
     8905                s.onselect = function(v) {
     8906                    ed.execCommand(s.cmd, s.ui || false, v || s.value);
     8907                };
     8908            }
     8909
     8910            s = extend({
     8911                title : s.title,
     8912                'class' : id,
     8913                scope : s.scope,
     8914                control_manager : t
     8915            }, s);
     8916
     8917            id = t.prefix + id;
     8918            c = t.add(new tinymce.ui.SplitButton(id, s));
     8919            ed.onMouseDown.add(c.hideMenu, c);
     8920
     8921            return c;
     8922        },
     8923
     8924        createColorSplitButton : function(id, s) {
     8925            var t = this, ed = t.editor, cmd, c;
     8926
     8927            if (t.get(id))
     8928                return null;
     8929
     8930            s.title = ed.translate(s.title);
     8931            s.scope = s.scope || ed;
     8932
     8933            if (!s.onclick) {
     8934                s.onclick = function(v) {
     8935                    ed.execCommand(s.cmd, s.ui || false, v || s.value);
     8936                };
     8937            }
     8938
     8939            if (!s.onselect) {
     8940                s.onselect = function(v) {
     8941                    ed.execCommand(s.cmd, s.ui || false, v || s.value);
     8942                };
     8943            }
     8944
     8945            s = extend({
     8946                title : s.title,
     8947                'class' : id,
     8948                'menu_class' : ed.getParam('skin') + 'Skin',
     8949                scope : s.scope,
     8950                more_colors_title : ed.getLang('more_colors')
     8951            }, s);
     8952
     8953            id = t.prefix + id;
     8954            c = new tinymce.ui.ColorSplitButton(id, s);
     8955            ed.onMouseDown.add(c.hideMenu, c);
     8956
     8957            return t.add(c);
     8958        },
     8959
     8960        createToolbar : function(id, s) {
     8961            var c, t = this;
     8962
     8963            id = t.prefix + id;
     8964            c = new tinymce.ui.Toolbar(id, s);
     8965
     8966            if (t.get(id))
     8967                return null;
     8968
     8969            return t.add(c);
     8970        },
     8971
     8972        createSeparator : function() {
     8973            return new tinymce.ui.Separator();
    65448974        }
    65458975
    6546         return false;
    6547     },
    6548 
    6549     _getPosText : function(r, sn, en) {
    6550         var w = document.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {};
    6551 
    6552         while ((n = w.nextNode()) != null) {
    6553             if (n == sn)
    6554                 d.start = p;
    6555 
    6556             if (n == en) {
    6557                 d.end = p;
    6558                 return d;
    6559             }
    6560 
    6561             p += n.nodeValue ? n.nodeValue.length : 0;
     8976        });
     8977})();
     8978
     8979/* file:jscripts/tiny_mce/classes/WindowManager.js */
     8980
     8981(function() {
     8982    var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each, isIE = tinymce.isIE, isOpera = tinymce.isOpera;
     8983
     8984    tinymce.create('tinymce.WindowManager', {
     8985        WindowManager : function(ed) {
     8986            var t = this;
     8987
     8988            t.editor = ed;
     8989            t.onOpen = new Dispatcher(t);
     8990            t.onClose = new Dispatcher(t);
     8991            t.params = {};
     8992            t.features = {};
     8993        },
     8994
     8995        open : function(s, p) {
     8996            var t = this, f = '', x, y, mo = t.editor.settings.dialog_type == 'modal', w, sw, sh, vp = tinymce.DOM.getViewPort();
     8997
     8998            // Default some options
     8999            s = s || {};
     9000            p = p || {};
     9001            sw = isOpera ? vp.w : screen.width; // Opera uses windows inside the Opera window
     9002            sh = isOpera ? vp.h : screen.height;
     9003            s.name = s.name || 'mc_' + new Date().getTime();
     9004            s.width = parseInt(s.width || 320);
     9005            s.height = parseInt(s.height || 240);
     9006            s.resizable = true;
     9007            s.left = s.left || parseInt(sw / 2.0) - (s.width / 2.0);
     9008            s.top = s.top || parseInt(sh / 2.0) - (s.height / 2.0);
     9009            p.inline = false;
     9010            p.mce_width = s.width;
     9011            p.mce_height = s.height;
     9012
     9013            if (mo) {
     9014                if (isIE) {
     9015                    s.center = true;
     9016                    s.help = false;
     9017                    s.dialogWidth = s.width + 'px';
     9018                    s.dialogHeight = s.height + 'px';
     9019                    s.scroll = s.scrollbars || false;
     9020                } else
     9021                    s.modal = s.alwaysRaised = s.dialog = s.centerscreen = s.dependent = true;
     9022            }
     9023
     9024            // Build features string
     9025            each(s, function(v, k) {
     9026                if (tinymce.is(v, 'boolean'))
     9027                    v = v ? 'yes' : 'no';
     9028
     9029                if (!/^(name|url)$/.test(k)) {
     9030                    if (isIE && mo)
     9031                        f += (f ? ';' : '') + k + ':' + v;
     9032                    else
     9033                        f += (f ? ',' : '') + k + '=' + v;
     9034                }
     9035            });
     9036
     9037            t.features = s;
     9038            t.params = p;
     9039            t.onOpen.dispatch(t, s, p);
     9040
     9041            try {
     9042                if (isIE && mo) {
     9043                    w = 1;
     9044                    window.showModalDialog(s.url || s.file, window, f);
     9045                } else
     9046                    w = window.open(s.url || s.file, s.name, f);
     9047            } catch (ex) {
     9048                // Ignore
     9049            }
     9050
     9051            if (!w)
     9052                alert(t.editor.getLang('popup_blocked'));
     9053        },
     9054
     9055        close : function(w) {
     9056            w.close();
     9057            this.onClose.dispatch(this);
     9058        },
     9059
     9060        createInstance : function(cl) {
     9061            var a = arguments, i, f = tinymce.resolve(cl), s = '';
     9062
     9063            // Is there a better way to dynamically create
     9064            // a class with a dynamic number of arguments
     9065            for (i=1; i<a.length; i++)
     9066                s += (i > 1 ? ',' : '') + 'a[' + i + ']';
     9067
     9068            return eval('(new f(' + s + '))');
     9069        },
     9070
     9071        confirm : function(t, cb, s) {
     9072            cb.call(s || this, confirm(this._decode(this.editor.getLang(t, t))));
     9073        },
     9074
     9075        alert : function(t, cb, s) {
     9076            alert(this._decode(t));
     9077
     9078            if (cb)
     9079                cb.call(s || this);
     9080        },
     9081
     9082        // Internal functions
     9083
     9084        _decode : function(s) {
     9085            return tinymce.DOM.decode(s).replace(/\\n/g, '\n');
    65629086        }
    65639087
    6564         return null;
    6565     },
    6566 
    6567     _getTextPos : function(r, sp, ep) {
    6568         var w = document.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {};
    6569 
    6570         while ((n = w.nextNode()) != null) {
    6571             p += n.nodeValue ? n.nodeValue.length : 0;
    6572 
    6573             if (p >= sp && !d.startNode) {
    6574                 d.startNode = n;
    6575                 d.startOffset = sp - (p - n.nodeValue.length);
    6576             }
    6577 
    6578             if (p >= ep) {
    6579                 d.endNode = n;
    6580                 d.endOffset = ep - (p - n.nodeValue.length);
    6581 
    6582                 return d;
    6583             }
    6584         }
    6585 
    6586         return null;
    6587     },
    6588 
    6589     selectNode : function(node, collapse, select_text_node, to_start) {
    6590         var inst = this.instance, sel, rng, nodes;
    6591 
    6592         if (!node)
    6593             return;
    6594 
    6595         if (typeof(collapse) == "undefined")
    6596             collapse = true;
    6597 
    6598         if (typeof(select_text_node) == "undefined")
    6599             select_text_node = false;
    6600 
    6601         if (typeof(to_start) == "undefined")
    6602             to_start = true;
    6603 
    6604         if (inst.settings.auto_resize)
    6605             inst.resizeToContent();
    6606 
    6607         if (tinyMCE.isRealIE) {
    6608             rng = inst.getDoc().body.createTextRange();
    6609 
    6610             try {
    6611                 rng.moveToElementText(node);
    6612 
    6613                 if (collapse)
    6614                     rng.collapse(to_start);
    6615 
    6616                 rng.select();
    6617             } catch (e) {
    6618                 // Throws illigal agrument in MSIE some times
    6619             }
    6620         } else {
    6621             sel = this.getSel();
    6622 
    6623             if (!sel)
    6624                 return;
    6625 
    6626             if (tinyMCE.isSafari) {
    6627                 sel.setBaseAndExtent(node, 0, node, node.innerText.length);
    6628 
    6629                 if (collapse) {
    6630                     if (to_start)
    6631                         sel.collapseToStart();
    6632                     else
    6633                         sel.collapseToEnd();
    6634                 }
    6635 
    6636                 this.scrollToNode(node);
    6637 
    6638                 return;
    6639             }
    6640 
    6641             rng = inst.getDoc().createRange();
    6642 
    6643             if (select_text_node) {
    6644                 // Find first textnode in tree
    6645                 nodes = tinyMCE.getNodeTree(node, [], 3);
    6646                 if (nodes.length > 0)
    6647                     rng.selectNodeContents(nodes[0]);
    6648                 else
    6649                     rng.selectNodeContents(node);
    6650             } else
    6651                 rng.selectNode(node);
    6652 
    6653             if (collapse) {
    6654                 // Special treatment of textnode collapse
    6655                 if (!to_start && node.nodeType == 3) {
    6656                     rng.setStart(node, node.nodeValue.length);
    6657                     rng.setEnd(node, node.nodeValue.length);
    6658                 } else
    6659                     rng.collapse(to_start);
    6660             }
    6661 
    6662             sel.removeAllRanges();
    6663             sel.addRange(rng);
    6664         }
    6665 
    6666         this.scrollToNode(node);
    6667 
    6668         // Set selected element
    6669         tinyMCE.selectedElement = null;
    6670         if (node.nodeType == 1)
    6671             tinyMCE.selectedElement = node;
    6672     },
    6673 
    6674     scrollToNode : function(node) {
    6675         var inst = this.instance, w = inst.getWin(), vp = inst.getViewPort(), pos = tinyMCE.getAbsPosition(node), cvp, p, cwin;
    6676 
    6677         // Only scroll if out of visible area
    6678         if (pos.absLeft < vp.left || pos.absLeft > vp.left + vp.width || pos.absTop < vp.top || pos.absTop > vp.top + (vp.height-25))
    6679             w.scrollTo(pos.absLeft, pos.absTop - vp.height + 25);
    6680 
    6681         // Scroll container window
    6682         if (inst.settings.auto_resize) {
    6683             cwin = inst.getContainerWin();
    6684             cvp = tinyMCE.getViewPort(cwin);
    6685             p = this.getAbsPosition(node);
    6686 
    6687             if (p.absLeft < cvp.left || p.absLeft > cvp.left + cvp.width || p.absTop < cvp.top || p.absTop > cvp.top + cvp.height)
    6688                 cwin.scrollTo(p.absLeft, p.absTop - cvp.height + 25);
    6689         }
    6690     },
    6691 
    6692     getAbsPosition : function(n) {
    6693         var pos = tinyMCE.getAbsPosition(n), ipos = tinyMCE.getAbsPosition(this.instance.iframeElement);
    6694 
    6695         return {
    6696             absLeft : ipos.absLeft + pos.absLeft,
    6697             absTop : ipos.absTop + pos.absTop
    6698         };
    6699     },
    6700 
    6701     getSel : function() {
    6702         var inst = this.instance;
    6703 
    6704         if (tinyMCE.isRealIE)
    6705             return inst.getDoc().selection;
    6706 
    6707         return inst.contentWindow.getSelection();
    6708     },
    6709 
    6710     getRng : function() {
    6711         var s = this.getSel();
    6712 
    6713         if (s == null)
    6714             return null;
    6715 
    6716         if (tinyMCE.isRealIE)
    6717             return s.createRange();
    6718 
    6719         if (tinyMCE.isSafari && !s.getRangeAt)
    6720             return '' + window.getSelection();
    6721 
    6722         if (s.rangeCount > 0)
    6723             return s.getRangeAt(0);
    6724 
    6725         return null;
    6726     },
    6727 
    6728     isCollapsed : function() {
    6729         var r = this.getRng();
    6730 
    6731         if (r.item)
    6732             return false;
    6733 
    6734         return r.boundingWidth == 0 || this.getSel().isCollapsed;
    6735     },
    6736 
    6737     collapse : function(b) {
    6738         var r = this.getRng(), s = this.getSel();
    6739 
    6740         if (r.select) {
    6741             r.collapse(b);
    6742             r.select();
    6743         } else {
    6744             if (b)
    6745                 s.collapseToStart();
    6746             else
    6747                 s.collapseToEnd();
    6748         }
    6749     },
    6750 
    6751     getFocusElement : function() {
    6752         var inst = this.instance, doc, rng, sel, elm;
    6753 
    6754         if (tinyMCE.isRealIE) {
    6755             doc = inst.getDoc();
    6756             rng = doc.selection.createRange();
    6757 
    6758     //      if (rng.collapse)
    6759     //          rng.collapse(true);
    6760 
    6761             elm = rng.item ? rng.item(0) : rng.parentElement();
    6762         } else {
    6763             if (!tinyMCE.isSafari && inst.isHidden())
    6764                 return inst.getBody();
    6765 
    6766             sel = this.getSel();
    6767             rng = this.getRng();
    6768 
    6769             if (!sel || !rng)
    6770                 return null;
    6771 
    6772             elm = rng.commonAncestorContainer;
    6773             //elm = (sel && sel.anchorNode) ? sel.anchorNode : null;
    6774 
    6775             // Handle selection a image or other control like element such as anchors
    6776             if (!rng.collapsed) {
    6777                 // Is selection small
    6778                 if (rng.startContainer == rng.endContainer) {
    6779                     if (rng.startOffset - rng.endOffset < 2) {
    6780                         if (rng.startContainer.hasChildNodes())
    6781                             elm = rng.startContainer.childNodes[rng.startOffset];
    6782                     }
    6783                 }
    6784             }
    6785 
    6786             // Get the element parent of the node
    6787             elm = tinyMCE.getParentElement(elm);
    6788 
    6789             //if (tinyMCE.selectedElement != null && tinyMCE.selectedElement.nodeName.toLowerCase() == "img")
    6790             //  elm = tinyMCE.selectedElement;
    6791         }
    6792 
    6793         return elm;
    6794     }
    6795 
    6796     };
    6797 
    6798 /* file:jscripts/tiny_mce/classes/TinyMCE_UndoRedo.class.js */
    6799 
    6800 function TinyMCE_UndoRedo(inst) {
    6801     this.instance = inst;
    6802     this.undoLevels = [];
    6803     this.undoIndex = 0;
    6804     this.typingUndoIndex = -1;
    6805     this.undoRedo = true;
    6806 };
    6807 
    6808 TinyMCE_UndoRedo.prototype = {
    6809     add : function(l) {
    6810         var b, customUndoLevels, newHTML, inst = this.instance, i, ul, ur;
    6811 
    6812         if (l) {
    6813             this.undoLevels[this.undoLevels.length] = l;
    6814             return true;
    6815         }
    6816 
    6817         if (this.typingUndoIndex != -1) {
    6818             this.undoIndex = this.typingUndoIndex;
    6819 
    6820             if (tinyMCE.typingUndoIndex != -1)
    6821                 tinyMCE.undoIndex = tinyMCE.typingUndoIndex;
    6822         }
    6823 
    6824         newHTML = tinyMCE.trim(inst.getBody().innerHTML);
    6825         if (this.undoLevels[this.undoIndex] && newHTML != this.undoLevels[this.undoIndex].content) {
    6826             //tinyMCE.debug(newHTML, this.undoLevels[this.undoIndex].content);
    6827 
    6828             // Is dirty again
    6829             inst.isNotDirty = false;
    6830 
    6831             tinyMCE.dispatchCallback(inst, 'onchange_callback', 'onChange', inst);
    6832 
    6833             // Time to compress
    6834             customUndoLevels = tinyMCE.settings.custom_undo_redo_levels;
    6835             if (customUndoLevels != -1 && this.undoLevels.length > customUndoLevels) {
    6836                 for (i=0; i<this.undoLevels.length-1; i++)
    6837                     this.undoLevels[i] = this.undoLevels[i+1];
    6838 
    6839                 this.undoLevels.length--;
    6840                 this.undoIndex--;
    6841 
    6842                 // Todo: Implement global undo/redo logic here
    6843             }
    6844 
    6845             b = inst.undoBookmark;
    6846 
    6847             if (!b)
    6848                 b = inst.selection.getBookmark();
    6849 
    6850             this.undoIndex++;
    6851             this.undoLevels[this.undoIndex] = {
    6852                 content : newHTML,
    6853                 bookmark : b
    6854             };
    6855 
    6856             // Remove all above from global undo/redo
    6857             ul = tinyMCE.undoLevels;
    6858             for (i=tinyMCE.undoIndex + 1; i<ul.length; i++) {
    6859                 ur = ul[i].undoRedo;
    6860 
    6861                 if (ur.undoIndex == ur.undoLevels.length -1)
    6862                     ur.undoIndex--;
    6863 
    6864                 ur.undoLevels.length--;
    6865             }
    6866 
    6867             // Add global undo level
    6868             tinyMCE.undoLevels[tinyMCE.undoIndex++] = inst;
    6869             tinyMCE.undoLevels.length = tinyMCE.undoIndex;
    6870 
    6871             this.undoLevels.length = this.undoIndex + 1;
    6872 
    6873             return true;
    6874         }
    6875 
    6876         return false;
    6877     },
    6878 
    6879     undo : function() {
    6880         var inst = this.instance;
    6881 
    6882         // Do undo
    6883         if (this.undoIndex > 0) {
    6884             this.undoIndex--;
    6885 
    6886             tinyMCE.setInnerHTML(inst.getBody(), this.undoLevels[this.undoIndex].content);
    6887             inst.repaint();
    6888 
    6889             if (inst.settings.custom_undo_redo_restore_selection)
    6890                 inst.selection.moveToBookmark(this.undoLevels[this.undoIndex].bookmark);
    6891         }
    6892     },
    6893 
    6894     redo : function() {
    6895         var inst = this.instance;
    6896 
    6897         tinyMCE.execCommand("mceEndTyping");
    6898 
    6899         if (this.undoIndex < (this.undoLevels.length-1)) {
    6900             this.undoIndex++;
    6901 
    6902             tinyMCE.setInnerHTML(inst.getBody(), this.undoLevels[this.undoIndex].content);
    6903             inst.repaint();
    6904 
    6905             if (inst.settings.custom_undo_redo_restore_selection)
    6906                 inst.selection.moveToBookmark(this.undoLevels[this.undoIndex].bookmark);
    6907         }
    6908 
    6909         tinyMCE.triggerNodeChange();
    6910     }
    6911 
    6912     };
    6913 
    6914 /* file:jscripts/tiny_mce/classes/TinyMCE_ForceParagraphs.class.js */
    6915 
    6916 var TinyMCE_ForceParagraphs = {
    6917     _insertPara : function(inst, e) {
    6918         var doc = inst.getDoc(), sel = inst.getSel(), body = inst.getBody(), win = inst.contentWindow, rng = sel.getRangeAt(0);
    6919         var rootElm = doc.documentElement, blockName = "P", startNode, endNode, startBlock, endBlock;
    6920         var rngBefore, rngAfter, direct, startNode, startOffset, endNode, endOffset, b = tinyMCE.isOpera ? inst.selection.getBookmark() : null;
    6921         var paraBefore, paraAfter, startChop, endChop, contents, i;
    6922 
    6923         function isEmpty(para) {
    6924             var nodes;
    6925 
    6926             function isEmptyHTML(html) {
    6927                 return html.replace(new RegExp('[ \t\r\n]+', 'g'), '').toLowerCase() == '';
    6928             }
    6929 
    6930             // Check for images
    6931             if (para.getElementsByTagName("img").length > 0)
    6932                 return false;
    6933 
    6934             // Check for tables
    6935             if (para.getElementsByTagName("table").length > 0)
    6936                 return false;
    6937 
    6938             // Check for HRs
    6939             if (para.getElementsByTagName("hr").length > 0)
    6940                 return false;
    6941 
    6942             // Check all textnodes
    6943             nodes = tinyMCE.getNodeTree(para, [], 3);
    6944             for (i=0; i<nodes.length; i++) {
    6945                 if (!isEmptyHTML(nodes[i].nodeValue))
    6946                     return false;
    6947             }
    6948 
    6949             // No images, no tables, no hrs, no text content then it's empty
    6950             return true;
    6951         }
    6952 
    6953     //  tinyMCE.debug(body.innerHTML);
    6954 
    6955     //  debug(e.target, sel.anchorNode.nodeName, sel.focusNode.nodeName, rng.startContainer, rng.endContainer, rng.commonAncestorContainer, sel.anchorOffset, sel.focusOffset, rng.toString());
    6956 
    6957         // Setup before range
    6958         rngBefore = doc.createRange();
    6959         rngBefore.setStart(sel.anchorNode, sel.anchorOffset);
    6960         rngBefore.collapse(true);
    6961 
    6962         // Setup after range
    6963         rngAfter = doc.createRange();
    6964         rngAfter.setStart(sel.focusNode, sel.focusOffset);
    6965         rngAfter.collapse(true);
    6966 
    6967         // Setup start/end points
    6968         direct = rngBefore.compareBoundaryPoints(rngBefore.START_TO_END, rngAfter) < 0;
    6969         startNode = direct ? sel.anchorNode : sel.focusNode;
    6970         startOffset = direct ? sel.anchorOffset : sel.focusOffset;
    6971         endNode = direct ? sel.focusNode : sel.anchorNode;
    6972         endOffset = direct ? sel.focusOffset : sel.anchorOffset;
    6973 
    6974         startNode = startNode.nodeName == "BODY" ? startNode.firstChild : startNode;
    6975         endNode = endNode.nodeName == "BODY" ? endNode.firstChild : endNode;
    6976 
    6977         // Get block elements
    6978         startBlock = inst.getParentBlockElement(startNode);
    6979         endBlock = inst.getParentBlockElement(endNode);
    6980 
    6981         // If absolute force paragraph generation within
    6982         if (startBlock && (startBlock.nodeName == 'CAPTION' || /absolute|relative|static/gi.test(startBlock.style.position)))
    6983             startBlock = null;
    6984 
    6985         if (endBlock && (endBlock.nodeName == 'CAPTION' || /absolute|relative|static/gi.test(endBlock.style.position)))
    6986             endBlock = null;
    6987 
    6988         // Use current block name
    6989         if (startBlock != null) {
    6990             blockName = startBlock.nodeName;
    6991 
    6992             // Use P instead
    6993             if (/(TD|TABLE|TH|CAPTION)/.test(blockName) || (blockName == "DIV" && /left|right/gi.test(startBlock.style.cssFloat)))
    6994                 blockName = "P";
    6995         }
    6996 
    6997         // Within a list use normal behaviour
    6998         if (tinyMCE.getParentElement(startBlock, "OL,UL", null, body) != null)
    6999             return false;
    7000 
    7001         // Within a table create new paragraphs
    7002         if ((startBlock != null && startBlock.nodeName == "TABLE") || (endBlock != null && endBlock.nodeName == "TABLE"))
    7003             startBlock = endBlock = null;
    7004 
    7005         // Setup new paragraphs
    7006         paraBefore = (startBlock != null && startBlock.nodeName == blockName) ? startBlock.cloneNode(false) : doc.createElement(blockName);
    7007         paraAfter = (endBlock != null && endBlock.nodeName == blockName) ? endBlock.cloneNode(false) : doc.createElement(blockName);
    7008 
    7009         // Is header, then force paragraph under
    7010         if (/^(H[1-6])$/.test(blockName))
    7011             paraAfter = doc.createElement("p");
    7012 
    7013         // Setup chop nodes
    7014         startChop = startNode;
    7015         endChop = endNode;
    7016 
    7017         // Get startChop node
    7018         node = startChop;
    7019         do {
    7020             if (node == body || node.nodeType == 9 || tinyMCE.isBlockElement(node))
    7021                 break;
    7022 
    7023             startChop = node;
    7024         } while ((node = node.previousSibling ? node.previousSibling : node.parentNode));
    7025 
    7026         // Get endChop node
    7027         node = endChop;
    7028         do {
    7029             if (node == body || node.nodeType == 9 || tinyMCE.isBlockElement(node))
    7030                 break;
    7031 
    7032             endChop = node;
    7033         } while ((node = node.nextSibling ? node.nextSibling : node.parentNode));
    7034 
    7035         // Fix when only a image is within the TD
    7036         if (startChop.nodeName == "TD")
    7037             startChop = startChop.firstChild;
    7038 
    7039         if (endChop.nodeName == "TD")
    7040             endChop = endChop.lastChild;
    7041 
    7042         // If not in a block element
    7043         if (startBlock == null) {
    7044             // Delete selection
    7045             rng.deleteContents();
    7046 
    7047             if (!tinyMCE.isSafari)
    7048                 sel.removeAllRanges();
    7049 
    7050             if (startChop != rootElm && endChop != rootElm) {
    7051                 // Insert paragraph before
    7052                 rngBefore = rng.cloneRange();
    7053 
    7054                 if (startChop == body)
    7055                     rngBefore.setStart(startChop, 0);
    7056                 else
    7057                     rngBefore.setStartBefore(startChop);
    7058 
    7059                 paraBefore.appendChild(rngBefore.cloneContents());
    7060 
    7061                 // Insert paragraph after
    7062                 if (endChop.parentNode.nodeName == blockName)
    7063                     endChop = endChop.parentNode;
    7064 
    7065                 // If not after image
    7066                 //if (rng.startContainer.nodeName != "BODY" && rng.endContainer.nodeName != "BODY")
    7067                     rng.setEndAfter(endChop);
    7068 
    7069                 if (endChop.nodeName != "#text" && endChop.nodeName != "BODY")
    7070                     rngBefore.setEndAfter(endChop);
    7071 
    7072                 contents = rng.cloneContents();
    7073                 if (contents.firstChild && (contents.firstChild.nodeName == blockName || contents.firstChild.nodeName == "BODY"))
    7074                     paraAfter.innerHTML = contents.firstChild.innerHTML;
    7075                 else
    7076                     paraAfter.appendChild(contents);
    7077 
    7078                 // Check if it's a empty paragraph
    7079                 if (isEmpty(paraBefore))
    7080                     paraBefore.innerHTML = "&nbsp;";
    7081 
    7082                 // Check if it's a empty paragraph
    7083                 if (isEmpty(paraAfter))
    7084                     paraAfter.innerHTML = "&nbsp;";
    7085 
    7086                 // Delete old contents
    7087                 rng.deleteContents();
    7088                 rngAfter.deleteContents();
    7089                 rngBefore.deleteContents();
    7090 
    7091                 // Insert new paragraphs
    7092                 if (tinyMCE.isOpera) {
    7093                     paraBefore.normalize();
    7094                     rngBefore.insertNode(paraBefore);
    7095                     paraAfter.normalize();
    7096                     rngBefore.insertNode(paraAfter);
    7097                 } else {
    7098                     paraAfter.normalize();
    7099                     rngBefore.insertNode(paraAfter);
    7100                     paraBefore.normalize();
    7101                     rngBefore.insertNode(paraBefore);
    7102                 }
    7103 
    7104                 //tinyMCE.debug("1: ", paraBefore.innerHTML, paraAfter.innerHTML);
    7105             } else {
    7106                 body.innerHTML = "<" + blockName + ">&nbsp;</" + blockName + "><" + blockName + ">&nbsp;</" + blockName + ">";
    7107                 paraAfter = body.childNodes[1];
    7108             }
    7109 
    7110             inst.selection.moveToBookmark(b);
    7111             inst.selection.selectNode(paraAfter, true, true);
    7112 
    7113             return true;
    7114         }
    7115 
    7116         // Place first part within new paragraph
    7117         if (startChop.nodeName == blockName)
    7118             rngBefore.setStart(startChop, 0);
    7119         else
    7120             rngBefore.setStartBefore(startChop);
    7121 
    7122         rngBefore.setEnd(startNode, startOffset);
    7123         paraBefore.appendChild(rngBefore.cloneContents());
    7124 
    7125         // Place secound part within new paragraph
    7126         rngAfter.setEndAfter(endChop);
    7127         rngAfter.setStart(endNode, endOffset);
    7128         contents = rngAfter.cloneContents();
    7129 
    7130         if (contents.firstChild && contents.firstChild.nodeName == blockName) {
    7131     /*      var nodes = contents.firstChild.childNodes;
    7132             for (i=0; i<nodes.length; i++) {
    7133                 //tinyMCE.debug(nodes[i].nodeName);
    7134                 if (nodes[i].nodeName != "BODY")
    7135                     paraAfter.appendChild(nodes[i]);
    7136             }
    7137     */
    7138             paraAfter.innerHTML = contents.firstChild.innerHTML;
    7139         } else
    7140             paraAfter.appendChild(contents);
    7141 
    7142         // Check if it's a empty paragraph
    7143         if (isEmpty(paraBefore))
    7144             paraBefore.innerHTML = "&nbsp;";
    7145 
    7146         // Check if it's a empty paragraph
    7147         if (isEmpty(paraAfter))
    7148             paraAfter.innerHTML = "&nbsp;";
    7149 
    7150         // Create a range around everything
    7151         rng = doc.createRange();
    7152 
    7153         if (!startChop.previousSibling && startChop.parentNode.nodeName.toUpperCase() == blockName) {
    7154             rng.setStartBefore(startChop.parentNode);
    7155         } else {
    7156             if (rngBefore.startContainer.nodeName.toUpperCase() == blockName && rngBefore.startOffset == 0)
    7157                 rng.setStartBefore(rngBefore.startContainer);
    7158             else
    7159                 rng.setStart(rngBefore.startContainer, rngBefore.startOffset);
    7160         }
    7161 
    7162         if (!endChop.nextSibling && endChop.parentNode.nodeName.toUpperCase() == blockName)
    7163             rng.setEndAfter(endChop.parentNode);
    7164         else
    7165             rng.setEnd(rngAfter.endContainer, rngAfter.endOffset);
    7166 
    7167         // Delete all contents and insert new paragraphs
    7168         rng.deleteContents();
    7169 
    7170         if (tinyMCE.isOpera) {
    7171             rng.insertNode(paraBefore);
    7172             rng.insertNode(paraAfter);
    7173         } else {
    7174             rng.insertNode(paraAfter);
    7175             rng.insertNode(paraBefore);
    7176         }
    7177 
    7178         //tinyMCE.debug("2", paraBefore.innerHTML, paraAfter.innerHTML);
    7179 
    7180         // Normalize
    7181         paraAfter.normalize();
    7182         paraBefore.normalize();
    7183 
    7184         inst.selection.moveToBookmark(b);
    7185         inst.selection.selectNode(paraAfter, true, true);
    7186 
    7187         return true;
    7188     },
    7189 
    7190     _handleBackSpace : function(inst) {
    7191         var r = inst.getRng(), sn = r.startContainer, nv, s = false;
    7192 
    7193         // Added body check for bug #1527787
    7194         if (sn && sn.nextSibling && sn.nextSibling.nodeName == "BR" && sn.parentNode.nodeName != "BODY") {
    7195             nv = sn.nodeValue;
    7196 
    7197             // Handle if a backspace is pressed after a space character #bug 1466054 removed since fix for #1527787
    7198             /*if (nv != null && nv.length >= r.startOffset && nv.charAt(r.startOffset - 1) == ' ')
    7199                 s = true;*/
    7200 
    7201             // Only remove BRs if we are at the end of line #bug 1464152
    7202             if (nv != null && r.startOffset == nv.length)
    7203                 sn.nextSibling.parentNode.removeChild(sn.nextSibling);
    7204         }
    7205 
    7206         if (inst.settings.auto_resize)
    7207             inst.resizeToContent();
    7208 
    7209         return s;
    7210     }
    7211 
    7212     };
    7213 
    7214 /* file:jscripts/tiny_mce/classes/TinyMCE_Layer.class.js */
    7215 
    7216 function TinyMCE_Layer(id, bm) {
    7217     this.id = id;
    7218     this.blockerElement = null;
    7219     this.events = false;
    7220     this.element = null;
    7221     this.blockMode = typeof(bm) != 'undefined' ? bm : true;
    7222     this.doc = document;
    7223 };
    7224 
    7225 TinyMCE_Layer.prototype = {
    7226     moveRelativeTo : function(re, p) {
    7227         var rep = this.getAbsPosition(re), e = this.getElement(), x, y;
    7228         var w = parseInt(re.offsetWidth), h = parseInt(re.offsetHeight);
    7229         var ew = parseInt(e.offsetWidth), eh = parseInt(e.offsetHeight);
    7230 
    7231         switch (p) {
    7232             case "tl":
    7233                 x = rep.absLeft;
    7234                 y = rep.absTop;
    7235                 break;
    7236 
    7237             case "tr":
    7238                 x = rep.absLeft + w;
    7239                 y = rep.absTop;
    7240                 break;
    7241 
    7242             case "bl":
    7243                 x = rep.absLeft;
    7244                 y = rep.absTop + h;
    7245                 break;
    7246 
    7247             case "br":
    7248                 x = rep.absLeft + w;
    7249                 y = rep.absTop + h;
    7250                 break;
    7251 
    7252             case "cc":
    7253                 x = rep.absLeft + (w / 2) - (ew / 2);
    7254                 y = rep.absTop + (h / 2) - (eh / 2);
    7255                 break;
    7256         }
    7257 
    7258         this.moveTo(x, y);
    7259     },
    7260 
    7261     moveBy : function(x, y) {
    7262         var e = this.getElement();
    7263         this.moveTo(parseInt(e.style.left) + x, parseInt(e.style.top) + y);
    7264     },
    7265 
    7266     moveTo : function(x, y) {
    7267         var e = this.getElement();
    7268 
    7269         e.style.left = x + "px";
    7270         e.style.top = y + "px";
    7271 
    7272         this.updateBlocker();
    7273     },
    7274 
    7275     resizeBy : function(w, h) {
    7276         var e = this.getElement();
    7277         this.resizeTo(parseInt(e.style.width) + w, parseInt(e.style.height) + h);
    7278     },
    7279 
    7280     resizeTo : function(w, h) {
    7281         var e = this.getElement();
    7282 
    7283         if (w != null)
    7284             e.style.width = w + "px";
    7285 
    7286         if (h != null)
    7287             e.style.height = h + "px";
    7288 
    7289         this.updateBlocker();
    7290     },
    7291 
    7292     show : function() {
    7293         var el = this.getElement();
    7294 
    7295         if (el) {
    7296             el.style.display = 'block';
    7297             this.updateBlocker();
    7298         }
    7299     },
    7300 
    7301     hide : function() {
    7302         var el = this.getElement();
    7303 
    7304         if (el) {
    7305             el.style.display = 'none';
    7306             this.updateBlocker();
    7307         }
    7308     },
    7309 
    7310     isVisible : function() {
    7311         return this.getElement().style.display == 'block';
    7312     },
    7313 
    7314     getElement : function() {
    7315         if (!this.element)
    7316             this.element = this.doc.getElementById(this.id);
    7317 
    7318         return this.element;
    7319     },
    7320 
    7321     setBlockMode : function(s) {
    7322         this.blockMode = s;
    7323     },
    7324 
    7325     updateBlocker : function() {
    7326         var e, b, x, y, w, h;
    7327 
    7328         b = this.getBlocker();
    7329         if (b) {
    7330             if (this.blockMode) {
    7331                 e = this.getElement();
    7332                 x = this.parseInt(e.style.left);
    7333                 y = this.parseInt(e.style.top);
    7334                 w = this.parseInt(e.offsetWidth);
    7335                 h = this.parseInt(e.offsetHeight);
    7336 
    7337                 b.style.left = x + 'px';
    7338                 b.style.top = y + 'px';
    7339                 b.style.width = w + 'px';
    7340                 b.style.height = h + 'px';
    7341                 b.style.display = e.style.display;
    7342             } else
    7343                 b.style.display = 'none';
    7344         }
    7345     },
    7346 
    7347     getBlocker : function() {
    7348         var d, b;
    7349 
    7350         if (!this.blockerElement && this.blockMode) {
    7351             d = this.doc;
    7352             b = d.getElementById(this.id + "_blocker");
    7353 
    7354             if (!b) {
    7355                 b = d.createElement("iframe");
    7356 
    7357                 b.setAttribute('id', this.id + "_blocker");
    7358                 b.style.cssText = 'display: none; position: absolute; left: 0; top: 0';
    7359                 b.src = 'javascript:false;';
    7360                 b.frameBorder = '0';
    7361                 b.scrolling = 'no';
    7362    
    7363                 d.body.appendChild(b);
    7364             }
    7365 
    7366             this.blockerElement = b;
    7367         }
    7368 
    7369         return this.blockerElement;
    7370     },
    7371 
    7372     getAbsPosition : function(n) {
    7373         var p = {absLeft : 0, absTop : 0};
    7374 
    7375         while (n) {
    7376             p.absLeft += n.offsetLeft;
    7377             p.absTop += n.offsetTop;
    7378             n = n.offsetParent;
    7379         }
    7380 
    7381         return p;
    7382     },
    7383 
    7384     create : function(n, c, p, h) {
    7385         var d = this.doc, e = d.createElement(n);
    7386 
    7387         e.setAttribute('id', this.id);
    7388 
    7389         if (c)
    7390             e.className = c;
    7391 
    7392         if (!p)
    7393             p = d.body;
    7394 
    7395         if (h)
    7396             e.innerHTML = h;
    7397 
    7398         p.appendChild(e);
    7399 
    7400         return this.element = e;
    7401     },
    7402 
    7403     exists : function() {
    7404         return this.doc.getElementById(this.id) != null;
    7405     },
    7406 
    7407     parseInt : function(s) {
    7408         if (s == null || s == '')
    7409             return 0;
    7410 
    7411         return parseInt(s);
    7412     },
    7413 
    7414     remove : function() {
    7415         var e = this.getElement(), b = this.getBlocker();
    7416 
    7417         if (e)
    7418             e.parentNode.removeChild(e);
    7419 
    7420         if (b)
    7421             b.parentNode.removeChild(b);
    7422     }
    7423 
    7424     };
    7425 
    7426 /* file:jscripts/tiny_mce/classes/TinyMCE_Menu.class.js */
    7427 
    7428 function TinyMCE_Menu() {
    7429     var id;
    7430 
    7431     if (typeof(tinyMCE.menuCounter) == "undefined")
    7432         tinyMCE.menuCounter = 0;
    7433 
    7434     id = "mc_menu_" + tinyMCE.menuCounter++;
    7435 
    7436     TinyMCE_Layer.call(this, id, true);
    7437 
    7438     this.id = id;
    7439     this.items = [];
    7440     this.needsUpdate = true;
    7441 };
    7442 
    7443 TinyMCE_Menu.prototype = tinyMCE.extend(TinyMCE_Layer.prototype, {
    7444     init : function(s) {
    7445         var n;
    7446 
    7447         // Default params
    7448         this.settings = {
    7449             separator_class : 'mceMenuSeparator',
    7450             title_class : 'mceMenuTitle',
    7451             disabled_class : 'mceMenuDisabled',
    7452             menu_class : 'mceMenu',
    7453             drop_menu : true
    7454         };
    7455 
    7456         for (n in s)
    7457             this.settings[n] = s[n];
    7458 
    7459         this.create('div', this.settings.menu_class);
    7460     },
    7461 
    7462     clear : function() {
    7463         this.items = [];
    7464     },
    7465 
    7466     addTitle : function(t) {
    7467         this.add({type : 'title', text : t});
    7468     },
    7469 
    7470     addDisabled : function(t) {
    7471         this.add({type : 'disabled', text : t});
    7472     },
    7473 
    7474     addSeparator : function() {
    7475         this.add({type : 'separator'});
    7476     },
    7477 
    7478     addItem : function(t, js) {
    7479         this.add({text : t, js : js});
    7480     },
    7481 
    7482     add : function(mi) {
    7483         this.items[this.items.length] = mi;
    7484         this.needsUpdate = true;
    7485     },
    7486 
    7487     update : function() {
    7488         var e = this.getElement(), h = '', i, t, m = this.items, s = this.settings;
    7489 
    7490         if (this.settings.drop_menu)
    7491             h += '<span class="mceMenuLine"></span>';
    7492 
    7493         h += '<table border="0" cellpadding="0" cellspacing="0">';
    7494 
    7495         for (i=0; i<m.length; i++) {
    7496             t = tinyMCE.xmlEncode(m[i].text);
    7497             c = m[i].class_name ? ' class="' + m[i].class_name + '"' : '';
    7498 
    7499             switch (m[i].type) {
    7500                 case 'separator':
    7501                     h += '<tr class="' + s.separator_class + '"><td>';
    7502                     break;
    7503 
    7504                 case 'title':
    7505                     h += '<tr class="' + s.title_class + '"><td><span' + c +'>' + t + '</span>';
    7506                     break;
    7507 
    7508                 case 'disabled':
    7509                     h += '<tr class="' + s.disabled_class + '"><td><span' + c +'>' + t + '</span>';
    7510                     break;
    7511 
    7512                 default:
    7513                     h += '<tr><td><a href="' + tinyMCE.xmlEncode(m[i].js) + '" onmousedown="' + tinyMCE.xmlEncode(m[i].js) + ';return tinyMCE.cancelEvent(event);" onclick="return tinyMCE.cancelEvent(event);" onmouseup="return tinyMCE.cancelEvent(event);"><span' + c +'>' + t + '</span></a>';
    7514             }
    7515 
    7516             h += '</td></tr>';
    7517         }
    7518 
    7519         h += '</table>';
    7520 
    7521         e.innerHTML = h;
    7522 
    7523         this.needsUpdate = false;
    7524         this.updateBlocker();
    7525     },
    7526 
    7527     show : function() {
    7528         var nl, i;
    7529 
    7530         if (tinyMCE.lastMenu == this)
    7531             return;
    7532 
    7533         if (this.needsUpdate)
    7534             this.update();
    7535 
    7536         if (tinyMCE.lastMenu && tinyMCE.lastMenu != this)
    7537             tinyMCE.lastMenu.hide();
    7538 
    7539         TinyMCE_Layer.prototype.show.call(this);
    7540 
    7541         if (!tinyMCE.isOpera) {
    7542             // Accessibility stuff
    7543 /*          nl = this.getElement().getElementsByTagName("a");
    7544             if (nl.length > 0)
    7545                 nl[0].focus();*/
    7546         }
    7547 
    7548         tinyMCE.lastMenu = this;
    7549     }
    7550 
    7551     });
    7552 
    7553 /* file:jscripts/tiny_mce/classes/TinyMCE_Debug.class.js */
    7554 
    7555 tinyMCE.add(TinyMCE_Engine, {
    7556     debug : function() {
    7557         var m = "", a, i, l = tinyMCE.log.length;
    7558 
    7559         for (i=0, a = this.debug.arguments; i<a.length; i++) {
    7560             m += a[i];
    7561 
    7562             if (i<a.length-1)
    7563                 m += ', ';
    7564         }
    7565 
    7566         if (l < 1000)
    7567             tinyMCE.log[l] = "[debug] " + m;
    7568     }
    7569 
    7570     });
    7571 
     9088        });
     9089}());
  • trunk/wp-includes/js/tinymce/tiny_mce_config.php

    r6575 r6632  
    2828    $invalid_elements = apply_filters('mce_invalid_elements', '');
    2929
    30     $plugins = array('inlinepopups', 'autosave', 'spellchecker', 'paste', 'wordpress');
     30    $plugins = array( 'safari', 'inlinepopups', 'autosave', 'spellchecker', 'paste', 'wordpress', 'media' );
    3131    $plugins = apply_filters('mce_plugins', $plugins);
    3232    $plugins = implode($plugins, ',');
    3333
    34     $mce_buttons = apply_filters('mce_buttons', array('bold', 'italic', 'strikethrough', 'separator', 'bullist', 'numlist', 'outdent', 'indent', 'separator', 'justifyleft', 'justifycenter', 'justifyright', 'separator', 'link', 'unlink', 'image', 'wp_more', 'separator', 'spellchecker', 'separator', 'wp_help', 'wp_adv', 'wp_adv_start', 'formatselect', 'underline', 'justifyfull', 'forecolor', 'separator', 'pastetext', 'pasteword', 'separator', 'removeformat', 'cleanup', 'separator', 'charmap', 'separator', 'undo', 'redo', 'wp_adv_end'));
     34    $mce_buttons = apply_filters('mce_buttons', array('bold', 'italic', 'strikethrough', 'separator', 'bullist', 'numlist', 'outdent', 'indent', 'separator', 'justifyleft', 'justifycenter', 'justifyright', 'separator', 'link', 'unlink', 'image', 'wp_more', 'separator', 'spellchecker', 'separator', 'wp_help', 'wp_adv', 'wp_adv_start', 'wp_adv_end'));
    3535    $mce_buttons = implode($mce_buttons, ',');
    3636
    37     $mce_buttons_2 = apply_filters('mce_buttons_2', array());
     37    $mce_buttons_2 = apply_filters('mce_buttons_2', array('formatselect', 'underline', 'justifyfull', 'forecolor', 'media', 'separator', 'pastetext', 'pasteword', 'separator', 'removeformat', 'cleanup', 'separator', 'charmap', 'separator', 'undo', 'redo'));
    3838    $mce_buttons_2 = implode($mce_buttons_2, ',');
    3939
     
    5555?>
    5656
     57/*
    5758wpEditorInit = function() {
    5859    // Activate tinyMCE if it's the user's default editor
    5960    if ( ( 'undefined' == typeof wpTinyMCEConfig ) || 'tinymce' == wpTinyMCEConfig.defaultEditor )
    60         tinyMCE.execCommand("mceAddControl", true, 'content');
     61        tinyMCE.execCommand('mceAddControl', false, 'content');
    6162};
     63*/
     64
     65wpEditorInit = function() {
     66    if ( ( 'undefined' != typeof wpTinyMCEConfig ) && 'tinymce' != wpTinyMCEConfig.defaultEditor )
     67        tinyMCE.get('content').hide();
     68}
    6269
    6370initArray = {
    64     mode : "specific_textareas",
    65     editor_selector : "mceEditor",
     71    mode : "exact",
     72    elements : "content",
     73//  editor_selector : "mceEditor",
    6674    oninit : "wpEditorInit",
    6775    width : "100%",
    6876    theme : "advanced",
     77    skin : "o2k7",
    6978    theme_advanced_buttons1 : "<?php echo $mce_buttons; ?>",
    7079    theme_advanced_buttons2 : "<?php echo $mce_buttons_2; ?>",
     
    7382    theme_advanced_toolbar_location : "top",
    7483    theme_advanced_toolbar_align : "left",
    75     theme_advanced_path_location : "bottom",
     84    theme_advanced_statusbar_location : "bottom",
    7685    theme_advanced_resizing : true,
    7786    browsers : "<?php echo $mce_browsers; ?>",
  • trunk/wp-includes/js/tinymce/tiny_mce_gzip.php

    r5700 r6632  
    1010 * Notice: This script defaults the button_tile_map option to true for extra performance.
    1111 */
    12 
    13     @require_once('../../../wp-config.php');  // For get_bloginfo().
    14 
     12   
     13    @require_once('../../../wp-config.php');  // For get_bloginfo().
     14?>
     15    var scriptURL = '<?php echo get_bloginfo('wpurl') . '/' . WPINC; ?>/js/tinymce/tiny_mce.js';
     16    document.write('<sc'+'ript language="javascript" type="text/javascript" src="' + scriptURL + '"></script>');
     17<?php     
     18    exit; // tiny_mce_gzip.php needs changes, but also it's much easier to test the js when it's not in one big file
     19   
    1520    // Get input
    1621    $plugins = explode(',', getParam("plugins", ""));
  • trunk/wp-includes/js/tinymce/tiny_mce_popup.js

    r5577 r6632  
    1 // Some global instances, this will be filled later
    2 var tinyMCE = null, tinyMCELang = null;
    3 
    4 function TinyMCE_Popup() {
    5 };
    6 
    7 TinyMCE_Popup.prototype = {
    8     findWin : function(w) {
    9         var c;
    10 
    11         // Check parents
    12         c = w;
    13         while (c && (c = c.parent) != null) {
    14             if (typeof(c.tinyMCE) != "undefined")
    15                 return c;
     1// Some global instances
     2var tinymce = null, tinyMCEPopup, tinyMCE;
     3
     4tinyMCEPopup = {
     5    init : function() {
     6        var t = this, w = t.getWin(), ti;
     7
     8        // Find API
     9        tinymce = w.tinymce;
     10        tinyMCE = w.tinyMCE;
     11        t.editor = tinymce.EditorManager.activeEditor;
     12        t.params = t.editor.windowManager.params;
     13
     14        // Setup local DOM
     15        t.dom = t.editor.windowManager.createInstance('tinymce.dom.DOMUtils', document);
     16        t.dom.loadCSS(t.editor.settings.popup_css);
     17
     18        // Setup on init listeners
     19        t.listeners = [];
     20        t.onInit = {
     21            add : function(f, s) {
     22                t.listeners.push({func : f, scope : s});
     23            }
     24        };
     25
     26        t.isWindow = !t.getWindowArg('mce_inline');
     27        t.id = t.getWindowArg('mce_window_id');
     28        t.editor.windowManager.onOpen.dispatch(t.editor.windowManager, window);
     29    },
     30
     31    getWin : function() {
     32        return window.dialogArguments || opener || parent || top;
     33    },
     34
     35    getWindowArg : function(n, dv) {
     36        var v = this.params[n];
     37
     38        return tinymce.is(v) ? v : dv;
     39    },
     40
     41    getParam : function(n, dv) {
     42        return this.editor.getParam(n, dv);
     43    },
     44
     45    getLang : function(n, dv) {
     46        return this.editor.getLang(n, dv);
     47    },
     48
     49    execCommand : function(cmd, ui, val) {
     50        this.restoreSelection();
     51        return this.editor.execCommand(cmd, ui, val);
     52    },
     53
     54    resizeToInnerSize : function() {
     55        var t = this, n, b = document.body, vp = t.dom.getViewPort(window), dw, dh;
     56
     57        dw = t.getWindowArg('mce_width') - vp.w;
     58        dh = t.getWindowArg('mce_height') - vp.h;
     59
     60        if (t.isWindow)
     61            window.resizeBy(dw, dh);
     62        else
     63            t.editor.windowManager.resizeBy(dw, dh, t.id);
     64    },
     65
     66    executeOnLoad : function(s) {
     67        this.onInit.add(function() {
     68            eval(s);
     69        });
     70    },
     71
     72    storeSelection : function() {
     73        this.editor.windowManager.bookmark = tinyMCEPopup.editor.selection.getBookmark('simple');
     74    },
     75
     76    restoreSelection : function() {
     77        var t = tinyMCEPopup;
     78
     79        if (!t.isWindow && tinymce.isIE)
     80            t.editor.selection.moveToBookmark(t.editor.windowManager.bookmark);
     81    },
     82
     83    requireLangPack : function() {
     84        var u = this.getWindowArg('plugin_url') || this.getWindowArg('theme_url');
     85
     86        if (u)
     87            document.write('<script type="text/javascript" src="' + u + '/langs/' + this.editor.settings.language + '_dlg.js' + '"></script>');
     88    },
     89
     90    pickColor : function(e, element_id) {
     91        this.execCommand('mceColorPicker', true, {
     92            color : document.getElementById(element_id).value,
     93            func : function(c) {
     94                document.getElementById(element_id).value = c;
     95
     96                if (tinymce.is(document.getElementById(element_id).onchange, 'function'))
     97                    document.getElementById(element_id).onchange();
     98            }
     99        });
     100    },
     101
     102    openBrowser : function(element_id, type, option) {
     103        tinyMCEPopup.restoreSelection();
     104        this.editor.execCallback('file_browser_callback', element_id, document.getElementById(element_id).value, type, window);
     105    },
     106
     107    close : function() {
     108        var t = this;
     109
     110        t.dom = t.dom.doc = null; // Cleanup
     111        t.editor.windowManager.close(window, t.id);
     112    },
     113
     114    // Internal functions   
     115
     116    _restoreSelection : function() {
     117        var e = window.event.srcElement;
     118
     119        if (e.nodeName == 'INPUT' && (e.type == 'submit' || e.type == 'button'))
     120            tinyMCEPopup.restoreSelection();
     121    },
     122
     123/*  _restoreSelection : function() {
     124        var e = window.event.srcElement;
     125
     126        // If user focus a non text input or textarea
     127        if ((e.nodeName != 'INPUT' && e.nodeName != 'TEXTAREA') || e.type != 'text')
     128            tinyMCEPopup.restoreSelection();
     129    },*/
     130
     131    _onDOMLoaded : function() {
     132        var t = this, ti = document.title, bm, h;
     133
     134        // Translate page
     135        h = document.body.innerHTML;
     136
     137        // Replace a=x with a="x" in IE
     138        if (tinymce.isIE)
     139            h = h.replace(/ (value|title|alt)=([^\s>]+)/gi, ' $1="$2"');
     140
     141        document.body.innerHTML = t.editor.translate(h);
     142        document.title = ti = t.editor.translate(ti);
     143        document.body.style.display = '';
     144
     145        // Restore selection in IE when focus is placed on a non textarea or input element of the type text
     146        if (tinymce.isIE)
     147            document.attachEvent('onmouseup', tinyMCEPopup._restoreSelection);
     148
     149        t.restoreSelection();
     150
     151        // Call onInit
     152        tinymce.each(t.listeners, function(o) {
     153            o.func.call(o.scope, t.editor);
     154        });
     155
     156        t.resizeToInnerSize();
     157
     158        if (t.isWindow)
     159            window.focus();
     160        else
     161            t.editor.windowManager.setTitle(ti, t.id);
     162
     163        if (!tinymce.isIE && !t.isWindow) {
     164            tinymce.dom.Event._add(document, 'focus', function() {
     165                t.editor.windowManager.focus(t.id)
     166            });
    16167        }
    17168
    18         // Check openers
    19         c = w;
    20         while (c && (c = c.opener) != null) {
    21             if (typeof(c.tinyMCE) != "undefined")
    22                 return c;
     169        // Patch for accessibility
     170        tinymce.each(t.dom.select('select'), function(e) {
     171            e.onkeydown = tinyMCEPopup._accessHandler;
     172        });
     173
     174        // Move focus to window
     175        window.focus();
     176    },
     177
     178    _accessHandler : function(e) {
     179        var e = e || window.event;
     180
     181        if (e.keyCode == 13 || e.keyCode == 32) {
     182            e = e.target || e.srcElement;
     183
     184            if (e.onchange)
     185                e.onchange();
     186
     187            return tinymce.dom.Event.cancel(e);
    23188        }
    24 
    25         // Try top
    26         if (typeof(top.tinyMCE) != "undefined")
    27             return top;
    28 
    29         return null;
    30     },
    31 
    32     init : function() {
    33         var win = window.opener ? window.opener : window.dialogArguments, c;
    34         var inst, re, title, divElm;
    35 
    36         if (!win)
    37             win = this.findWin(window);
    38 
    39         if (!win) {
    40             alert("tinyMCE object reference not found from popup.");
    41             return;
    42         }
    43 
    44         window.opener = win;
    45         this.windowOpener = win;
    46         this.onLoadEval = "";
    47 
    48         // Setup parent references
    49         tinyMCE = win.tinyMCE;
    50         tinyMCELang = win.tinyMCELang;
    51 
    52         inst = tinyMCE.selectedInstance;
    53         this.isWindow = tinyMCE.getWindowArg('mce_inside_iframe', false) == false;
    54         this.storeSelection = (tinyMCE.isRealIE) && !this.isWindow && tinyMCE.getWindowArg('mce_store_selection', true);
    55 
    56         if (this.isWindow)
    57             window.focus();
    58 
    59         // Store selection
    60         if (this.storeSelection)
    61             inst.selectionBookmark = inst.selection.getBookmark(true);
    62 
    63         // Setup dir
    64         if (tinyMCELang.lang_dir)
    65             document.dir = tinyMCELang.lang_dir;
    66 
    67         // Setup title
    68         re = new RegExp('{|\\\$|}', 'g');
    69         title = document.title.replace(re, "");
    70         if (typeof(tinyMCELang[title]) != "undefined") {
    71             divElm = document.createElement("div");
    72             divElm.innerHTML = tinyMCELang[title];
    73             document.title = divElm.innerHTML;
    74 
    75             if (typeof(tinyMCE.setWindowTitle) != 'undefined')
    76                 tinyMCE.setWindowTitle(window, divElm.innerHTML);
    77         }
    78 
    79         // Output Popup CSS class
    80         document.write('<link href="' + tinyMCE.getParam("popups_css") + '" rel="stylesheet" type="text/css">');
    81 
    82         if (tinyMCE.getParam("popups_css_add")) {
    83             c = tinyMCE.getParam("popups_css_add");
    84 
    85             // Is relative
    86             if (c.indexOf('://') == -1 && c.charAt(0) != '/')
    87                 c = tinyMCE.documentBasePath + "/" + c;
    88 
    89             document.write('<link href="' + c + '" rel="stylesheet" type="text/css">');
    90         }
    91 
    92         tinyMCE.addEvent(window, "load", this.onLoad);
    93     },
    94 
    95     onLoad : function() {
    96         var dir, i, elms, body = document.body;
    97 
    98         if (tinyMCE.getWindowArg('mce_replacevariables', true))
    99             body.innerHTML = tinyMCE.applyTemplate(body.innerHTML, tinyMCE.windowArgs);
    100 
    101         dir = tinyMCE.selectedInstance.settings.directionality;
    102         if (dir == "rtl" && document.forms && document.forms.length > 0) {
    103             elms = document.forms[0].elements;
    104             for (i=0; i<elms.length; i++) {
    105                 if ((elms[i].type == "text" || elms[i].type == "textarea") && elms[i].getAttribute("dir") != "ltr")
    106                     elms[i].dir = dir;
     189    },
     190
     191    _wait : function() {
     192        var t = this, ti;
     193
     194        if (tinymce.isIE && document.location.protocol != 'https:') {
     195            // Fake DOMContentLoaded on IE
     196            document.write('<script id=__ie_onload defer src=\'javascript:""\';><\/script>');
     197            document.getElementById("__ie_onload").onreadystatechange = function() {
     198                if (this.readyState == "complete") {
     199                    t._onDOMLoaded();
     200                    document.getElementById("__ie_onload").onreadystatechange = null; // Prevent leak
     201                }
     202            };
     203        } else {
     204            if (tinymce.isIE || tinymce.isWebKit) {
     205                ti = setInterval(function() {
     206                    if (/loaded|complete/.test(document.readyState)) {
     207                        clearInterval(ti);
     208                        t._onDOMLoaded();
     209                    }
     210                }, 10);
     211            } else {
     212                window.addEventListener('DOMContentLoaded', function() {
     213                    t._onDOMLoaded();
     214                }, false);
    107215            }
    108216        }
    109 
    110         if (body.style.display == 'none')
    111             body.style.display = 'block';
    112 
    113         // Execute real onload (Opera fix)
    114         if (tinyMCEPopup.onLoadEval !== '')
    115             eval(tinyMCEPopup.onLoadEval);
    116     },
    117 
    118     executeOnLoad : function(str) {
    119         if (tinyMCE.isOpera)
    120             this.onLoadEval = str;
    121         else
    122             eval(str);
    123     },
    124 
    125     resizeToInnerSize : function() {
    126         var i, doc, body, oldMargin, wrapper, iframe, nodes, dx, dy;
    127 
    128         // Netscape 7.1 workaround
    129         if (this.isWindow && tinyMCE.isNS71) {
    130             window.resizeBy(0, 10);
    131             return;
    132         }
    133 
    134         if (this.isWindow) {
    135             doc = document;
    136             body = doc.body;
    137 
    138             if (body.style.display == 'none')
    139                 body.style.display = 'block';
    140 
    141             // Remove margin
    142             oldMargin = body.style.margin;
    143             body.style.margin = '0';
    144 
    145             // Create wrapper
    146             wrapper = doc.createElement("div");
    147             wrapper.id = 'mcBodyWrapper';
    148             wrapper.style.display = 'none';
    149             wrapper.style.margin = '0';
    150 
    151             // Wrap body elements
    152             nodes = doc.body.childNodes;
    153             for (i=nodes.length-1; i>=0; i--) {
    154                 if (wrapper.hasChildNodes())
    155                     wrapper.insertBefore(nodes[i].cloneNode(true), wrapper.firstChild);
    156                 else
    157                     wrapper.appendChild(nodes[i].cloneNode(true));
    158 
    159                 nodes[i].parentNode.removeChild(nodes[i]);
    160             }
    161 
    162             // Add wrapper
    163             doc.body.appendChild(wrapper);
    164 
    165             // Create iframe
    166             iframe = document.createElement("iframe");
    167             iframe.id = "mcWinIframe";
    168             iframe.src = document.location.href.toLowerCase().indexOf('https') == -1 ? "about:blank" : tinyMCE.settings.default_document;
    169             iframe.width = "100%";
    170             iframe.height = "100%";
    171             iframe.style.margin = '0';
    172 
    173             // Add iframe
    174             doc.body.appendChild(iframe);
    175 
    176             // Measure iframe
    177             iframe = document.getElementById('mcWinIframe');
    178             dx = tinyMCE.getWindowArg('mce_width') - iframe.clientWidth;
    179             dy = tinyMCE.getWindowArg('mce_height') - iframe.clientHeight;
    180 
    181             // Resize window
    182             // tinyMCE.debug(tinyMCE.getWindowArg('mce_width') + "," + tinyMCE.getWindowArg('mce_height') + " - " + dx + "," + dy);
    183             window.resizeBy(dx, dy);
    184 
    185             // Hide iframe and show wrapper
    186             body.style.margin = oldMargin;
    187             iframe.style.display = 'none';
    188             wrapper.style.display = 'block';
    189         }
    190     },
    191 
    192     resizeToContent : function() {
    193         var isMSIE = (navigator.appName == "Microsoft Internet Explorer");
    194         var isOpera = (navigator.userAgent.indexOf("Opera") != -1);
    195         var elm, width, height, x, y, dx, dy;
    196 
    197         if (isOpera)
    198             return;
    199 
    200         if (isMSIE) {
    201             try { window.resizeTo(10, 10); } catch (e) {}
    202 
    203             elm = document.body;
    204             width = elm.offsetWidth;
    205             height = elm.offsetHeight;
    206             dx = (elm.scrollWidth - width) + 4;
    207             dy = elm.scrollHeight - height;
    208 
    209             try { window.resizeBy(dx, dy); } catch (e) {}
    210         } else {
    211             window.scrollBy(1000, 1000);
    212             if (window.scrollX > 0 || window.scrollY > 0) {
    213                 window.resizeBy(window.innerWidth * 2, window.innerHeight * 2);
    214                 window.sizeToContent();
    215                 window.scrollTo(0, 0);
    216                 x = parseInt(screen.width / 2.0) - (window.outerWidth / 2.0);
    217                 y = parseInt(screen.height / 2.0) - (window.outerHeight / 2.0);
    218                 window.moveTo(x, y);
    219             }
    220         }
    221     },
    222 
    223     getWindowArg : function(name, default_value) {
    224         return tinyMCE.getWindowArg(name, default_value);
    225     },
    226 
    227     restoreSelection : function() {
    228         var inst;
    229 
    230         if (this.storeSelection) {
    231             inst = tinyMCE.selectedInstance;
    232 
    233             inst.getWin().focus();
    234 
    235             if (inst.selectionBookmark)
    236                 inst.selection.moveToBookmark(inst.selectionBookmark);
    237         }
    238     },
    239 
    240     execCommand : function(command, user_interface, value) {
    241         var inst = tinyMCE.selectedInstance;
    242 
    243         this.restoreSelection();
    244         inst.execCommand(command, user_interface, value);
    245 
    246         // Store selection
    247         if (this.storeSelection)
    248             inst.selectionBookmark = inst.selection.getBookmark(true);
    249     },
    250 
    251     close : function() {
    252         tinyMCE.closeWindow(window);
    253     },
    254 
    255     pickColor : function(e, element_id) {
    256         tinyMCE.selectedInstance.execCommand('mceColorPicker', true, {
    257             element_id : element_id,
    258             document : document,
    259             window : window,
    260             store_selection : false
    261         });
    262     },
    263 
    264     openBrowser : function(element_id, type, option) {
    265         var cb = tinyMCE.getParam(option, tinyMCE.getParam("file_browser_callback"));
    266         var url = document.getElementById(element_id).value;
    267 
    268         tinyMCE.setWindowArg("window", window);
    269         tinyMCE.setWindowArg("document", document);
    270 
    271         // Call to external callback
    272         if (eval('typeof(tinyMCEPopup.windowOpener.' + cb + ')') == "undefined")
    273             alert("Callback function: " + cb + " could not be found.");
    274         else
    275             eval("tinyMCEPopup.windowOpener." + cb + "(element_id, url, type, window);");
    276     },
    277 
    278     importClass : function(c) {
    279         var n;
    280 
    281         window[c] = function() {};
    282 
    283         for (n in window.opener[c].prototype)
    284             window[c].prototype[n] = window.opener[c].prototype[n];
    285 
    286         window[c].constructor = window.opener[c].constructor;
    287217    }
    288 
    289     };
    290 
    291 // Setup global instance
    292 var tinyMCEPopup = new TinyMCE_Popup();
     218};
    293219
    294220tinyMCEPopup.init();
     221tinyMCEPopup._wait(); // Wait for DOM Content Loaded
  • trunk/wp-includes/js/tinymce/utils/editable_selects.js

    • Property svn:eol-style set to native
    r4799 r6632  
    11/**
    2  * $Id: editable_selects.js 162 2007-01-03 16:16:52Z spocke $
     2 * $Id: editable_selects.js 520 2008-01-07 16:30:32Z spocke $
    33 *
    44 * Makes select boxes editable.
    55 *
    66 * @author Moxiecode
    7  * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
     7 * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
    88 */
    99
     
    2121
    2222                nl[i].options[nl[i].options.length] = o;
    23                 nl[i].setAttribute('onchange', 'TinyMCE_EditableSelects.onChangeEditableSelect(this);');
     23                nl[i].onchange = TinyMCE_EditableSelects.onChangeEditableSelect;
    2424            }
    2525        }
    2626    },
    2727
    28     onChangeEditableSelect : function(se) {
    29         var d = document, ne;
     28    onChangeEditableSelect : function(e) {
     29        var d = document, ne, se = window.event ? window.event.srcElement : e.target;
    3030
    3131        if (se.options[se.selectedIndex].value == '__mce_add_custom__') {
     
    3535            ne.type = "text";
    3636
    37             ne.style.width = se.clientWidth;
     37            ne.style.width = se.offsetWidth + 'px';
    3838            se.parentNode.insertBefore(ne, se);
    3939            se.style.display = 'none';
  • trunk/wp-includes/js/tinymce/utils/form_utils.js

    r4799 r6632  
    11/**
    2  * $Id: form_utils.js 162 2007-01-03 16:16:52Z spocke $
     2 * $Id: form_utils.js 520 2008-01-07 16:30:32Z spocke $
    33 *
    44 * Various form utilitiy functions.
    55 *
    66 * @author Moxiecode
    7  * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
     7 * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
    88 */
    99
    10 var themeBaseURL = tinyMCE.baseURL + '/themes/' + tinyMCE.getParam("theme");
     10var themeBaseURL = tinyMCEPopup.editor.baseURI.toAbsolute('themes/' + tinyMCEPopup.getParam("theme"));
    1111
    1212function getColorPickerHTML(id, target_form_element) {
    1313    var h = "";
    1414
    15     h += '<a id="' + id + '_link" href="javascript:void(0);" onkeydown="pickColor(event,\'' + target_form_element +'\');" onmousedown="pickColor(event,\'' + target_form_element +'\');return false;">';
    16     h += '<img id="' + id + '" src="' + themeBaseURL + '/images/color.gif"';
    17     h += ' onmouseover="this.className=\'mceButtonOver\'"';
    18     h += ' onmouseout="this.className=\'mceButtonNormal\'"';
    19     h += ' onmousedown="this.className=\'mceButtonDown\'"';
    20     h += ' width="20" height="16" border="0" title="' + tinyMCE.getLang('lang_browse') + '"';
    21     h += ' class="mceButtonNormal" alt="' + tinyMCE.getLang('lang_browse') + '" /></a>';
     15    h += '<a id="' + id + '_link" href="javascript:;" onclick="tinyMCEPopup.pickColor(event,\'' + target_form_element +'\');" onmousedown="return false;" class="pickcolor">';
     16    h += '<span id="' + id + '" title="' + tinyMCEPopup.getLang('browse') + '"></span></a>';
    2217
    2318    return h;
    24 }
    25 
    26 function pickColor(e, target_form_element) {
    27     if ((e.keyCode == 32 || e.keyCode == 13) || e.type == "mousedown")
    28         tinyMCEPopup.pickColor(e, target_form_element);
    2919}
    3020
     
    4131            lnk.setAttribute("realhref", lnk.getAttribute("href"));
    4232            lnk.removeAttribute("href");
    43             tinyMCE.switchClass(img, 'mceButtonDisabled', true);
     33            tinyMCEPopup.dom.addClass(img, 'disabled');
    4434        } else {
    4535            lnk.setAttribute("href", lnk.getAttribute("realhref"));
    46             tinyMCE.switchClass(img, 'mceButtonNormal', false);
     36            tinyMCEPopup.dom.removeClass(img, 'disabled');
    4737        }
    4838    }
     
    5040
    5141function getBrowserHTML(id, target_form_element, type, prefix) {
    52     var option = prefix + "_" + type + "_browser_callback";
    53     var cb = tinyMCE.getParam(option, tinyMCE.getParam("file_browser_callback"));
    54     if (cb == null)
     42    var option = prefix + "_" + type + "_browser_callback", cb, html;
     43
     44    cb = tinyMCEPopup.getParam(option, tinyMCEPopup.getParam("file_browser_callback"));
     45
     46    if (!cb)
    5547        return "";
    5648
    57     var html = "";
    58 
    59     html += '<a id="' + id + '_link" href="javascript:openBrower(\'' + id + '\',\'' + target_form_element + '\', \'' + type + '\',\'' + option + '\');" onmousedown="return false;">';
    60     html += '<img id="' + id + '" src="' + themeBaseURL + '/images/browse.gif"';
    61     html += ' onmouseover="this.className=\'mceButtonOver\';"';
    62     html += ' onmouseout="this.className=\'mceButtonNormal\';"';
    63     html += ' onmousedown="this.className=\'mceButtonDown\';"';
    64     html += ' width="20" height="18" border="0" title="' + tinyMCE.getLang('lang_browse') + '"';
    65     html += ' class="mceButtonNormal" alt="' + tinyMCE.getLang('lang_browse') + '" /></a>';
     49    html = "";
     50    html += '<a id="' + id + '_link" href="javascript:openBrowser(\'' + id + '\',\'' + target_form_element + '\', \'' + type + '\',\'' + option + '\');" onmousedown="return false;" class="browse">';
     51    html += '<span id="' + id + '" title="' + tinyMCEPopup.getLang('browse') + '"></span></a>';
    6652
    6753    return html;
    6854}
    6955
    70 function openBrower(img_id, target_form_element, type, option) {
     56function openBrowser(img_id, target_form_element, type, option) {
    7157    var img = document.getElementById(img_id);
    7258
     
    120106    // Setup class droplist
    121107    var styleSelectElm = document.getElementById(list_id);
    122     var styles = tinyMCE.getParam('theme_advanced_styles', false);
    123     styles = tinyMCE.getParam(specific_option, styles);
     108    var styles = tinyMCEPopup.getParam('theme_advanced_styles', false);
     109    styles = tinyMCEPopup.getParam(specific_option, styles);
    124110
    125111    if (styles) {
     
    137123        }
    138124    } else {
    139         // Use auto impored classes
    140         var csses = tinyMCE.getCSSClasses(tinyMCE.getWindowArg('editor_id'));
    141         for (var i=0; i<csses.length; i++)
    142             styleSelectElm.options[styleSelectElm.length] = new Option(csses[i], csses[i]);
     125        tinymce.each(tinyMCEPopup.editor.dom.getClasses(), function(o) {
     126            styleSelectElm.options[styleSelectElm.length] = new Option(o.title || o['class'], o['class']);
     127        });
    143128    }
    144129}
     
    197182
    198183function getStyle(elm, attrib, style) {
    199     var val = tinyMCE.getAttrib(elm, attrib);
     184    var val = tinyMCEPopup.dom.getAttrib(elm, attrib);
    200185
    201186    if (val != '')
     
    205190        style = attrib;
    206191
    207     val = eval('elm.style.' + style);
    208 
    209     return val == null ? '' : '' + val;
     192    return tinyMCEPopup.dom.getStyle(elm, style);
    210193}
  • trunk/wp-includes/js/tinymce/utils/mclayer.js

    r4799 r6632  
    11/**
    2  * $Id: mclayer.js 162 2007-01-03 16:16:52Z spocke $
     2 * $Id: mclayer.js 520 2008-01-07 16:30:32Z spocke $
    33 *
    44 * Moxiecode floating layer script.
    55 *
    66 * @author Moxiecode
    7  * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
     7 * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
    88 */
    99
  • trunk/wp-includes/js/tinymce/utils/mctabs.js

    r4799 r6632  
    11/**
    2  * $Id: mctabs.js 162 2007-01-03 16:16:52Z spocke $
     2 * $Id: mctabs.js 520 2008-01-07 16:30:32Z spocke $
    33 *
    44 * Moxiecode DHTML Tabs script.
    55 *
    66 * @author Moxiecode
    7  * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
     7 * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
    88 */
    99
  • trunk/wp-includes/js/tinymce/utils/validate.js

    r4799 r6632  
    11/**
    2  * $Id: validate.js 162 2007-01-03 16:16:52Z spocke $
     2 * $Id: validate.js 520 2008-01-07 16:30:32Z spocke $
    33 *
    44 * Various form validation methods.
    55 *
    66 * @author Moxiecode
    7  * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
     7 * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
    88 */
    99
Note: See TracChangeset for help on using the changeset viewer.