WordPress.org

Make WordPress Core

Ticket #20055: 20055.diff

File 20055.diff, 148.0 KB (added by ericlewis, 2 years ago)

packaged .dev.js non-WP plugin files from TinyMCE source; also themes/advanced/editor_template.dev.js added ternary declaration of suffix of tinyMCEPreInit depending on SCRIPT_DEBUG constant.

  • wp-includes/js/tinymce/plugins/media/editor_plugin.dev.js

     
     1/** 
     2 * editor_plugin_src.js 
     3 * 
     4 * Copyright 2009, Moxiecode Systems AB 
     5 * Released under LGPL License. 
     6 * 
     7 * License: http://tinymce.moxiecode.com/license 
     8 * Contributing: http://tinymce.moxiecode.com/contributing 
     9 */ 
     10 
     11(function() { 
     12        var rootAttributes = tinymce.explode('id,name,width,height,style,align,class,hspace,vspace,bgcolor,type'), excludedAttrs = tinymce.makeMap(rootAttributes.join(',')), Node = tinymce.html.Node, 
     13                mediaTypes, scriptRegExp, JSON = tinymce.util.JSON, mimeTypes; 
     14 
     15        // Media types supported by this plugin 
     16        mediaTypes = [ 
     17                // Type, clsid:s, mime types, codebase 
     18                ["Flash", "d27cdb6e-ae6d-11cf-96b8-444553540000", "application/x-shockwave-flash", "http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"], 
     19                ["ShockWave", "166b1bca-3f9c-11cf-8075-444553540000", "application/x-director", "http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0"], 
     20                ["WindowsMedia", "6bf52a52-394a-11d3-b153-00c04f79faa6,22d6f312-b0f6-11d0-94ab-0080c74c7e95,05589fa1-c356-11ce-bf01-00aa0055595a", "application/x-mplayer2", "http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701"], 
     21                ["QuickTime", "02bf25d5-8c17-4b23-bc80-d3488abddc6b", "video/quicktime", "http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0"], 
     22                ["RealMedia", "cfcdaa03-8be4-11cf-b84b-0020afbbccfa", "audio/x-pn-realaudio-plugin", "http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"], 
     23                ["Java", "8ad9c840-044e-11d1-b3e9-00805f499d93", "application/x-java-applet", "http://java.sun.com/products/plugin/autodl/jinstall-1_5_0-windows-i586.cab#Version=1,5,0,0"], 
     24                ["Silverlight", "dfeaf541-f3e1-4c24-acac-99c30715084a", "application/x-silverlight-2"], 
     25                ["Iframe"], 
     26                ["Video"], 
     27                ["EmbeddedAudio"], 
     28                ["Audio"] 
     29        ]; 
     30 
     31        function toArray(obj) { 
     32                var undef, out, i; 
     33 
     34                if (obj && !obj.splice) { 
     35                        out = []; 
     36 
     37                        for (i = 0; true; i++) { 
     38                                if (obj[i]) 
     39                                        out[i] = obj[i]; 
     40                                else 
     41                                        break; 
     42                        } 
     43 
     44                        return out; 
     45                } 
     46 
     47                return obj; 
     48        }; 
     49 
     50        tinymce.create('tinymce.plugins.MediaPlugin', { 
     51                init : function(ed, url) { 
     52                        var self = this, lookup = {}, i, y, item, name; 
     53 
     54                        function isMediaImg(node) { 
     55                                return node && node.nodeName === 'IMG' && ed.dom.hasClass(node, 'mceItemMedia'); 
     56                        }; 
     57 
     58                        self.editor = ed; 
     59                        self.url = url; 
     60 
     61                        // Parse media types into a lookup table 
     62                        scriptRegExp = ''; 
     63                        for (i = 0; i < mediaTypes.length; i++) { 
     64                                name = mediaTypes[i][0]; 
     65 
     66                                item = { 
     67                                        name : name, 
     68                                        clsids : tinymce.explode(mediaTypes[i][1] || ''), 
     69                                        mimes : tinymce.explode(mediaTypes[i][2] || ''), 
     70                                        codebase : mediaTypes[i][3] 
     71                                }; 
     72 
     73                                for (y = 0; y < item.clsids.length; y++) 
     74                                        lookup['clsid:' + item.clsids[y]] = item; 
     75 
     76                                for (y = 0; y < item.mimes.length; y++) 
     77                                        lookup[item.mimes[y]] = item; 
     78 
     79                                lookup['mceItem' + name] = item; 
     80                                lookup[name.toLowerCase()] = item; 
     81 
     82                                scriptRegExp += (scriptRegExp ? '|' : '') + name; 
     83                        } 
     84 
     85                        // Handle the media_types setting 
     86                        tinymce.each(ed.getParam("media_types", 
     87                                "video=mp4,m4v,ogv,webm;" + 
     88                                "silverlight=xap;" + 
     89                                "flash=swf,flv;" + 
     90                                "shockwave=dcr;" + 
     91                                "quicktime=mov,qt,mpg,mpeg;" + 
     92                                "shockwave=dcr;" + 
     93                                "windowsmedia=avi,wmv,wm,asf,asx,wmx,wvx;" + 
     94                                "realmedia=rm,ra,ram;" + 
     95                                "java=jar;" + 
     96                                "audio=mp3,ogg" 
     97                        ).split(';'), function(item) { 
     98                                var i, extensions, type; 
     99 
     100                                item = item.split(/=/); 
     101                                extensions = tinymce.explode(item[1].toLowerCase()); 
     102                                for (i = 0; i < extensions.length; i++) { 
     103                                        type = lookup[item[0].toLowerCase()]; 
     104 
     105                                        if (type) 
     106                                                lookup[extensions[i]] = type; 
     107                                } 
     108                        }); 
     109 
     110                        scriptRegExp = new RegExp('write(' + scriptRegExp + ')\\(([^)]+)\\)'); 
     111                        self.lookup = lookup; 
     112 
     113                        ed.onPreInit.add(function() { 
     114                                // Allow video elements 
     115                                ed.schema.addValidElements('object[id|style|width|height|classid|codebase|*],param[name|value],embed[id|style|width|height|type|src|*],video[*],audio[*],source[*]'); 
     116 
     117                                // Convert video elements to image placeholder 
     118                                ed.parser.addNodeFilter('object,embed,video,audio,script,iframe', function(nodes) { 
     119                                        var i = nodes.length; 
     120 
     121                                        while (i--) 
     122                                                self.objectToImg(nodes[i]); 
     123                                }); 
     124 
     125                                // Convert image placeholders to video elements 
     126                                ed.serializer.addNodeFilter('img', function(nodes, name, args) { 
     127                                        var i = nodes.length, node; 
     128 
     129                                        while (i--) { 
     130                                                node = nodes[i]; 
     131                                                if ((node.attr('class') || '').indexOf('mceItemMedia') !== -1) 
     132                                                        self.imgToObject(node, args); 
     133                                        } 
     134                                }); 
     135                        }); 
     136 
     137                        ed.onInit.add(function() { 
     138                                // Display "media" instead of "img" in element path 
     139                                if (ed.theme && ed.theme.onResolveName) { 
     140                                        ed.theme.onResolveName.add(function(theme, path_object) { 
     141                                                if (path_object.name === 'img' && ed.dom.hasClass(path_object.node, 'mceItemMedia')) 
     142                                                        path_object.name = 'media'; 
     143                                        }); 
     144                                } 
     145 
     146                                // Add contect menu if it's loaded 
     147                                if (ed && ed.plugins.contextmenu) { 
     148                                        ed.plugins.contextmenu.onContextMenu.add(function(plugin, menu, element) { 
     149                                                if (element.nodeName === 'IMG' && element.className.indexOf('mceItemMedia') !== -1) 
     150                                                        menu.add({title : 'media.edit', icon : 'media', cmd : 'mceMedia'}); 
     151                                        }); 
     152                                } 
     153                        }); 
     154 
     155                        // Register commands 
     156                        ed.addCommand('mceMedia', function() { 
     157                                var data, img; 
     158 
     159                                img = ed.selection.getNode(); 
     160                                if (isMediaImg(img)) { 
     161                                        data = ed.dom.getAttrib(img, 'data-mce-json'); 
     162                                        if (data) { 
     163                                                data = JSON.parse(data); 
     164 
     165                                                // Add some extra properties to the data object 
     166                                                tinymce.each(rootAttributes, function(name) { 
     167                                                        var value = ed.dom.getAttrib(img, name); 
     168 
     169                                                        if (value) 
     170                                                                data[name] = value; 
     171                                                }); 
     172 
     173                                                data.type = self.getType(img.className).name.toLowerCase(); 
     174                                        } 
     175                                } 
     176 
     177                                if (!data) { 
     178                                        data = { 
     179                                                type : 'flash', 
     180                                                video: {sources:[]}, 
     181                                                params: {} 
     182                                        }; 
     183                                } 
     184 
     185                                ed.windowManager.open({ 
     186                                        file : url + '/media.htm', 
     187                                        width : 430 + parseInt(ed.getLang('media.delta_width', 0)), 
     188                                        height : 500 + parseInt(ed.getLang('media.delta_height', 0)), 
     189                                        inline : 1 
     190                                }, { 
     191                                        plugin_url : url, 
     192                                        data : data 
     193                                }); 
     194                        }); 
     195 
     196                        // Register buttons 
     197                        ed.addButton('media', {title : 'media.desc', cmd : 'mceMedia'}); 
     198 
     199                        // Update media selection status 
     200                        ed.onNodeChange.add(function(ed, cm, node) { 
     201                                cm.setActive('media', isMediaImg(node)); 
     202                        }); 
     203                }, 
     204 
     205                convertUrl : function(url, force_absolute) { 
     206                        var self = this, editor = self.editor, settings = editor.settings, 
     207                                urlConverter = settings.url_converter, 
     208                                urlConverterScope = settings.url_converter_scope || self; 
     209 
     210                        if (!url) 
     211                                return url; 
     212 
     213                        if (force_absolute) 
     214                                return editor.documentBaseURI.toAbsolute(url); 
     215 
     216                        return urlConverter.call(urlConverterScope, url, 'src', 'object'); 
     217                }, 
     218 
     219                getInfo : function() { 
     220                        return { 
     221                                longname : 'Media', 
     222                                author : 'Moxiecode Systems AB', 
     223                                authorurl : 'http://tinymce.moxiecode.com', 
     224                                infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/media', 
     225                                version : tinymce.majorVersion + "." + tinymce.minorVersion 
     226                        }; 
     227                }, 
     228 
     229                /** 
     230                 * Converts the JSON data object to an img node. 
     231                 */ 
     232                dataToImg : function(data, force_absolute) { 
     233                        var self = this, editor = self.editor, baseUri = editor.documentBaseURI, sources, attrs, img, i; 
     234 
     235                        data.params.src = self.convertUrl(data.params.src, force_absolute); 
     236 
     237                        attrs = data.video.attrs; 
     238                        if (attrs) 
     239                                attrs.src = self.convertUrl(attrs.src, force_absolute); 
     240 
     241                        if (attrs) 
     242                                attrs.poster = self.convertUrl(attrs.poster, force_absolute); 
     243 
     244                        sources = toArray(data.video.sources); 
     245                        if (sources) { 
     246                                for (i = 0; i < sources.length; i++) 
     247                                        sources[i].src = self.convertUrl(sources[i].src, force_absolute); 
     248                        } 
     249 
     250                        img = self.editor.dom.create('img', { 
     251                                id : data.id, 
     252                                style : data.style, 
     253                                align : data.align, 
     254                                hspace : data.hspace, 
     255                                vspace : data.vspace, 
     256                                src : self.editor.theme.url + '/img/trans.gif', 
     257                                'class' : 'mceItemMedia mceItem' + self.getType(data.type).name, 
     258                                'data-mce-json' : JSON.serialize(data, "'") 
     259                        }); 
     260 
     261                        img.width = data.width || (data.type == 'audio' ? "300" : "320"); 
     262                        img.height = data.height || (data.type == 'audio' ? "32" : "240"); 
     263 
     264                        return img; 
     265                }, 
     266 
     267                /** 
     268                 * Converts the JSON data object to a HTML string. 
     269                 */ 
     270                dataToHtml : function(data, force_absolute) { 
     271                        return this.editor.serializer.serialize(this.dataToImg(data, force_absolute), {forced_root_block : '', force_absolute : force_absolute}); 
     272                }, 
     273 
     274                /** 
     275                 * Converts the JSON data object to a HTML string. 
     276                 */ 
     277                htmlToData : function(html) { 
     278                        var fragment, img, data; 
     279 
     280                        data = { 
     281                                type : 'flash', 
     282                                video: {sources:[]}, 
     283                                params: {} 
     284                        }; 
     285 
     286                        fragment = this.editor.parser.parse(html); 
     287                        img = fragment.getAll('img')[0]; 
     288 
     289                        if (img) { 
     290                                data = JSON.parse(img.attr('data-mce-json')); 
     291                                data.type = this.getType(img.attr('class')).name.toLowerCase(); 
     292 
     293                                // Add some extra properties to the data object 
     294                                tinymce.each(rootAttributes, function(name) { 
     295                                        var value = img.attr(name); 
     296 
     297                                        if (value) 
     298                                                data[name] = value; 
     299                                }); 
     300                        } 
     301 
     302                        return data; 
     303                }, 
     304 
     305                /** 
     306                 * Get type item by extension, class, clsid or mime type. 
     307                 * 
     308                 * @method getType 
     309                 * @param {String} value Value to get type item by. 
     310                 * @return {Object} Type item object or undefined. 
     311                 */ 
     312                getType : function(value) { 
     313                        var i, values, typeItem; 
     314 
     315                        // Find type by checking the classes 
     316                        values = tinymce.explode(value, ' '); 
     317                        for (i = 0; i < values.length; i++) { 
     318                                typeItem = this.lookup[values[i]]; 
     319 
     320                                if (typeItem) 
     321                                        return typeItem; 
     322                        } 
     323                }, 
     324 
     325                /** 
     326                 * Converts a tinymce.html.Node image element to video/object/embed. 
     327                 */ 
     328                imgToObject : function(node, args) { 
     329                        var self = this, editor = self.editor, video, object, embed, iframe, name, value, data, 
     330                                source, sources, params, param, typeItem, i, item, mp4Source, replacement, 
     331                                posterSrc, style, audio; 
     332 
     333                        // Adds the flash player 
     334                        function addPlayer(video_src, poster_src) { 
     335                                var baseUri, flashVars, flashVarsOutput, params, flashPlayer; 
     336 
     337                                flashPlayer = editor.getParam('flash_video_player_url', self.convertUrl(self.url + '/moxieplayer.swf')); 
     338                                if (flashPlayer) { 
     339                                        baseUri = editor.documentBaseURI; 
     340                                        data.params.src = flashPlayer; 
     341 
     342                                        // Convert the movie url to absolute urls 
     343                                        if (editor.getParam('flash_video_player_absvideourl', true)) { 
     344                                                video_src = baseUri.toAbsolute(video_src || '', true); 
     345                                                poster_src = baseUri.toAbsolute(poster_src || '', true); 
     346                                        } 
     347 
     348                                        // Generate flash vars 
     349                                        flashVarsOutput = ''; 
     350                                        flashVars = editor.getParam('flash_video_player_flashvars', {url : '$url', poster : '$poster'}); 
     351                                        tinymce.each(flashVars, function(value, name) { 
     352                                                // Replace $url and $poster variables in flashvars value 
     353                                                value = value.replace(/\$url/, video_src || ''); 
     354                                                value = value.replace(/\$poster/, poster_src || ''); 
     355 
     356                                                if (value.length > 0) 
     357                                                        flashVarsOutput += (flashVarsOutput ? '&' : '') + name + '=' + escape(value); 
     358                                        }); 
     359 
     360                                        if (flashVarsOutput.length) 
     361                                                data.params.flashvars = flashVarsOutput; 
     362 
     363                                        params = editor.getParam('flash_video_player_params', { 
     364                                                allowfullscreen: true, 
     365                                                allowscriptaccess: true 
     366                                        }); 
     367 
     368                                        tinymce.each(params, function(value, name) { 
     369                                                data.params[name] = "" + value; 
     370                                        }); 
     371                                } 
     372                        }; 
     373 
     374                        data = node.attr('data-mce-json'); 
     375                        if (!data) 
     376                                return; 
     377 
     378                        data = JSON.parse(data); 
     379                        typeItem = this.getType(node.attr('class')); 
     380 
     381                        style = node.attr('data-mce-style') 
     382                        if (!style) { 
     383                                style = node.attr('style'); 
     384 
     385                                if (style) 
     386                                        style = editor.dom.serializeStyle(editor.dom.parseStyle(style, 'img')); 
     387                        } 
     388 
     389                        // Handle iframe 
     390                        if (typeItem.name === 'Iframe') { 
     391                                replacement = new Node('iframe', 1); 
     392 
     393                                tinymce.each(rootAttributes, function(name) { 
     394                                        var value = node.attr(name); 
     395 
     396                                        if (name == 'class' && value) 
     397                                                value = value.replace(/mceItem.+ ?/g, ''); 
     398 
     399                                        if (value && value.length > 0) 
     400                                                replacement.attr(name, value); 
     401                                }); 
     402 
     403                                for (name in data.params) 
     404                                        replacement.attr(name, data.params[name]); 
     405 
     406                                replacement.attr({ 
     407                                        style: style, 
     408                                        src: data.params.src 
     409                                }); 
     410 
     411                                node.replace(replacement); 
     412 
     413                                return; 
     414                        } 
     415 
     416                        // Handle scripts 
     417                        if (this.editor.settings.media_use_script) { 
     418                                replacement = new Node('script', 1).attr('type', 'text/javascript'); 
     419 
     420                                value = new Node('#text', 3); 
     421                                value.value = 'write' + typeItem.name + '(' + JSON.serialize(tinymce.extend(data.params, { 
     422                                        width: node.attr('width'), 
     423                                        height: node.attr('height') 
     424                                })) + ');'; 
     425 
     426                                replacement.append(value); 
     427                                node.replace(replacement); 
     428 
     429                                return; 
     430                        } 
     431 
     432                        // Add HTML5 video element 
     433                        if (typeItem.name === 'Video' && data.video.sources[0]) { 
     434                                // Create new object element 
     435                                video = new Node('video', 1).attr(tinymce.extend({ 
     436                                        id : node.attr('id'), 
     437                                        width: node.attr('width'), 
     438                                        height: node.attr('height'), 
     439                                        style : style 
     440                                }, data.video.attrs)); 
     441 
     442                                // Get poster source and use that for flash fallback 
     443                                if (data.video.attrs) 
     444                                        posterSrc = data.video.attrs.poster; 
     445 
     446                                sources = data.video.sources = toArray(data.video.sources); 
     447                                for (i = 0; i < sources.length; i++) { 
     448                                        if (/\.mp4$/.test(sources[i].src)) 
     449                                                mp4Source = sources[i].src; 
     450                                } 
     451 
     452                                if (!sources[0].type) { 
     453                                        video.attr('src', sources[0].src); 
     454                                        sources.splice(0, 1); 
     455                                } 
     456 
     457                                for (i = 0; i < sources.length; i++) { 
     458                                        source = new Node('source', 1).attr(sources[i]); 
     459                                        source.shortEnded = true; 
     460                                        video.append(source); 
     461                                } 
     462 
     463                                // Create flash fallback for video if we have a mp4 source 
     464                                if (mp4Source) { 
     465                                        addPlayer(mp4Source, posterSrc); 
     466                                        typeItem = self.getType('flash'); 
     467                                } else 
     468                                        data.params.src = ''; 
     469                        } 
     470 
     471                        // Add HTML5 audio element 
     472                        if (typeItem.name === 'Audio' && data.video.sources[0]) { 
     473                                // Create new object element 
     474                                audio = new Node('audio', 1).attr(tinymce.extend({ 
     475                                        id : node.attr('id'), 
     476                                        width: node.attr('width'), 
     477                                        height: node.attr('height'), 
     478                                        style : style 
     479                                }, data.video.attrs)); 
     480 
     481                                // Get poster source and use that for flash fallback 
     482                                if (data.video.attrs) 
     483                                        posterSrc = data.video.attrs.poster; 
     484 
     485                                sources = data.video.sources = toArray(data.video.sources); 
     486                                if (!sources[0].type) { 
     487                                        audio.attr('src', sources[0].src); 
     488                                        sources.splice(0, 1); 
     489                                } 
     490 
     491                                for (i = 0; i < sources.length; i++) { 
     492                                        source = new Node('source', 1).attr(sources[i]); 
     493                                        source.shortEnded = true; 
     494                                        audio.append(source); 
     495                                } 
     496 
     497                                data.params.src = ''; 
     498                        } 
     499 
     500                        if (typeItem.name === 'EmbeddedAudio') { 
     501                                embed = new Node('embed', 1); 
     502                                embed.shortEnded = true; 
     503                                embed.attr({ 
     504                                        id: node.attr('id'), 
     505                                        width: node.attr('width'), 
     506                                        height: node.attr('height'), 
     507                                        style : style, 
     508                                        type: node.attr('type') 
     509                                }); 
     510 
     511                                for (name in data.params) 
     512                                        embed.attr(name, data.params[name]); 
     513 
     514                                tinymce.each(rootAttributes, function(name) { 
     515                                        if (data[name] && name != 'type') 
     516                                                embed.attr(name, data[name]); 
     517                                }); 
     518 
     519                                data.params.src = ''; 
     520                        } 
     521 
     522                        // Do we have a params src then we can generate object 
     523                        if (data.params.src) { 
     524                                // Is flv movie add player for it 
     525                                if (/\.flv$/i.test(data.params.src)) 
     526                                        addPlayer(data.params.src, ''); 
     527 
     528                                if (args && args.force_absolute) 
     529                                        data.params.src = editor.documentBaseURI.toAbsolute(data.params.src); 
     530 
     531                                // Create new object element 
     532                                object = new Node('object', 1).attr({ 
     533                                        id : node.attr('id'), 
     534                                        width: node.attr('width'), 
     535                                        height: node.attr('height'), 
     536                                        style : style 
     537                                }); 
     538 
     539                                tinymce.each(rootAttributes, function(name) { 
     540                                        var value = data[name]; 
     541 
     542                                        if (name == 'class' && value) 
     543                                                value = value.replace(/mceItem.+ ?/g, ''); 
     544 
     545                                        if (value && name != 'type') 
     546                                                object.attr(name, value); 
     547                                }); 
     548 
     549                                // Add params 
     550                                for (name in data.params) { 
     551                                        param = new Node('param', 1); 
     552                                        param.shortEnded = true; 
     553                                        value = data.params[name]; 
     554 
     555                                        // Windows media needs to use url instead of src for the media URL 
     556                                        if (name === 'src' && typeItem.name === 'WindowsMedia') 
     557                                                name = 'url'; 
     558 
     559                                        param.attr({name: name, value: value}); 
     560                                        object.append(param); 
     561                                } 
     562 
     563                                // Setup add type and classid if strict is disabled 
     564                                if (this.editor.getParam('media_strict', true)) { 
     565                                        object.attr({ 
     566                                                data: data.params.src, 
     567                                                type: typeItem.mimes[0] 
     568                                        }); 
     569                                } else { 
     570                                        object.attr({ 
     571                                                classid: "clsid:" + typeItem.clsids[0], 
     572                                                codebase: typeItem.codebase 
     573                                        }); 
     574 
     575                                        embed = new Node('embed', 1); 
     576                                        embed.shortEnded = true; 
     577                                        embed.attr({ 
     578                                                id: node.attr('id'), 
     579                                                width: node.attr('width'), 
     580                                                height: node.attr('height'), 
     581                                                style : style, 
     582                                                type: typeItem.mimes[0] 
     583                                        }); 
     584 
     585                                        for (name in data.params) 
     586                                                embed.attr(name, data.params[name]); 
     587 
     588                                        tinymce.each(rootAttributes, function(name) { 
     589                                                if (data[name] && name != 'type') 
     590                                                        embed.attr(name, data[name]); 
     591                                        }); 
     592 
     593                                        object.append(embed); 
     594                                } 
     595 
     596                                // Insert raw HTML 
     597                                if (data.object_html) { 
     598                                        value = new Node('#text', 3); 
     599                                        value.raw = true; 
     600                                        value.value = data.object_html; 
     601                                        object.append(value); 
     602                                } 
     603 
     604                                // Append object to video element if it exists 
     605                                if (video) 
     606                                        video.append(object); 
     607                        } 
     608 
     609                        if (video) { 
     610                                // Insert raw HTML 
     611                                if (data.video_html) { 
     612                                        value = new Node('#text', 3); 
     613                                        value.raw = true; 
     614                                        value.value = data.video_html; 
     615                                        video.append(value); 
     616                                } 
     617                        } 
     618 
     619                        if (audio) { 
     620                                // Insert raw HTML 
     621                                if (data.video_html) { 
     622                                        value = new Node('#text', 3); 
     623                                        value.raw = true; 
     624                                        value.value = data.video_html; 
     625                                        audio.append(value); 
     626                                } 
     627                        } 
     628 
     629                        var n = video || audio || object || embed; 
     630                        if (n) 
     631                                node.replace(n); 
     632                        else 
     633                                node.remove(); 
     634                }, 
     635 
     636                /** 
     637                 * Converts a tinymce.html.Node video/object/embed to an img element. 
     638                 * 
     639                 * The video/object/embed will be converted into an image placeholder with a JSON data attribute like this: 
     640                 * <img class="mceItemMedia mceItemFlash" width="100" height="100" data-mce-json="{..}" /> 
     641                 * 
     642                 * The JSON structure will be like this: 
     643                 * {'params':{'flashvars':'something','quality':'high','src':'someurl'}, 'video':{'sources':[{src: 'someurl', type: 'video/mp4'}]}} 
     644                 */ 
     645                objectToImg : function(node) { 
     646                        var object, embed, video, iframe, img, name, id, width, height, style, i, html, 
     647                                param, params, source, sources, data, type, lookup = this.lookup, 
     648                                matches, attrs, urlConverter = this.editor.settings.url_converter, 
     649                                urlConverterScope = this.editor.settings.url_converter_scope, 
     650                                hspace, vspace, align, bgcolor; 
     651 
     652                        function getInnerHTML(node) { 
     653                                return new tinymce.html.Serializer({ 
     654                                        inner: true, 
     655                                        validate: false 
     656                                }).serialize(node); 
     657                        }; 
     658 
     659                        function lookupAttribute(o, attr) { 
     660                                return lookup[(o.attr(attr) || '').toLowerCase()]; 
     661                        } 
     662 
     663                        function lookupExtension(src) { 
     664                                var ext = src.replace(/^.*\.([^.]+)$/, '$1'); 
     665                                return lookup[ext.toLowerCase() || '']; 
     666                        } 
     667 
     668                        // If node isn't in document 
     669                        if (!node.parent) 
     670                                return; 
     671 
     672                        // Handle media scripts 
     673                        if (node.name === 'script') { 
     674                                if (node.firstChild) 
     675                                        matches = scriptRegExp.exec(node.firstChild.value); 
     676 
     677                                if (!matches) 
     678                                        return; 
     679 
     680                                type = matches[1]; 
     681                                data = {video : {}, params : JSON.parse(matches[2])}; 
     682                                width = data.params.width; 
     683                                height = data.params.height; 
     684                        } 
     685 
     686                        // Setup data objects 
     687                        data = data || { 
     688                                video : {}, 
     689                                params : {} 
     690                        }; 
     691 
     692                        // Setup new image object 
     693                        img = new Node('img', 1); 
     694                        img.attr({ 
     695                                src : this.editor.theme.url + '/img/trans.gif' 
     696                        }); 
     697 
     698                        // Video element 
     699                        name = node.name; 
     700                        if (name === 'video' || name == 'audio') { 
     701                                video = node; 
     702                                object = node.getAll('object')[0]; 
     703                                embed = node.getAll('embed')[0]; 
     704                                width = video.attr('width'); 
     705                                height = video.attr('height'); 
     706                                id = video.attr('id'); 
     707                                data.video = {attrs : {}, sources : []}; 
     708 
     709                                // Get all video attributes 
     710                                attrs = data.video.attrs; 
     711                                for (name in video.attributes.map) 
     712                                        attrs[name] = video.attributes.map[name]; 
     713 
     714                                source = node.attr('src'); 
     715                                if (source) 
     716                                        data.video.sources.push({src : urlConverter.call(urlConverterScope, source, 'src', node.name)}); 
     717 
     718                                // Get all sources 
     719                                sources = video.getAll("source"); 
     720                                for (i = 0; i < sources.length; i++) { 
     721                                        source = sources[i].remove(); 
     722 
     723                                        data.video.sources.push({ 
     724                                                src: urlConverter.call(urlConverterScope, source.attr('src'), 'src', 'source'), 
     725                                                type: source.attr('type'), 
     726                                                media: source.attr('media') 
     727                                        }); 
     728                                } 
     729 
     730                                // Convert the poster URL 
     731                                if (attrs.poster) 
     732                                        attrs.poster = urlConverter.call(urlConverterScope, attrs.poster, 'poster', node.name); 
     733                        } 
     734 
     735                        // Object element 
     736                        if (node.name === 'object') { 
     737                                object = node; 
     738                                embed = node.getAll('embed')[0]; 
     739                        } 
     740 
     741                        // Embed element 
     742                        if (node.name === 'embed') 
     743                                embed = node; 
     744 
     745                        // Iframe element 
     746                        if (node.name === 'iframe') { 
     747                                iframe = node; 
     748                                type = 'Iframe'; 
     749                        } 
     750 
     751                        if (object) { 
     752                                // Get width/height 
     753                                width = width || object.attr('width'); 
     754                                height = height || object.attr('height'); 
     755                                style = style || object.attr('style'); 
     756                                id = id || object.attr('id'); 
     757                                hspace = hspace || object.attr('hspace'); 
     758                                vspace = vspace || object.attr('vspace'); 
     759                                align = align || object.attr('align'); 
     760                                bgcolor = bgcolor || object.attr('bgcolor'); 
     761                                data.name = object.attr('name'); 
     762 
     763                                // Get all object params 
     764                                params = object.getAll("param"); 
     765                                for (i = 0; i < params.length; i++) { 
     766                                        param = params[i]; 
     767                                        name = param.remove().attr('name'); 
     768 
     769                                        if (!excludedAttrs[name]) 
     770                                                data.params[name] = param.attr('value'); 
     771                                } 
     772 
     773                                data.params.src = data.params.src || object.attr('data'); 
     774                        } 
     775 
     776                        if (embed) { 
     777                                // Get width/height 
     778                                width = width || embed.attr('width'); 
     779                                height = height || embed.attr('height'); 
     780                                style = style || embed.attr('style'); 
     781                                id = id || embed.attr('id'); 
     782                                hspace = hspace || embed.attr('hspace'); 
     783                                vspace = vspace || embed.attr('vspace'); 
     784                                align = align || embed.attr('align'); 
     785                                bgcolor = bgcolor || embed.attr('bgcolor'); 
     786 
     787                                // Get all embed attributes 
     788                                for (name in embed.attributes.map) { 
     789                                        if (!excludedAttrs[name] && !data.params[name]) 
     790                                                data.params[name] = embed.attributes.map[name]; 
     791                                } 
     792                        } 
     793 
     794                        if (iframe) { 
     795                                // Get width/height 
     796                                width = iframe.attr('width'); 
     797                                height = iframe.attr('height'); 
     798                                style = style || iframe.attr('style'); 
     799                                id = iframe.attr('id'); 
     800                                hspace = iframe.attr('hspace'); 
     801                                vspace = iframe.attr('vspace'); 
     802                                align = iframe.attr('align'); 
     803                                bgcolor = iframe.attr('bgcolor'); 
     804 
     805                                tinymce.each(rootAttributes, function(name) { 
     806                                        img.attr(name, iframe.attr(name)); 
     807                                }); 
     808 
     809                                // Get all iframe attributes 
     810                                for (name in iframe.attributes.map) { 
     811                                        if (!excludedAttrs[name] && !data.params[name]) 
     812                                                data.params[name] = iframe.attributes.map[name]; 
     813                                } 
     814                        } 
     815 
     816                        // Use src not movie 
     817                        if (data.params.movie) { 
     818                                data.params.src = data.params.src || data.params.movie; 
     819                                delete data.params.movie; 
     820                        } 
     821 
     822                        // Convert the URL to relative/absolute depending on configuration 
     823                        if (data.params.src) 
     824                                data.params.src = urlConverter.call(urlConverterScope, data.params.src, 'src', 'object'); 
     825 
     826                        if (video) { 
     827                                if (node.name === 'video') 
     828                                        type = lookup.video.name; 
     829                                else if (node.name === 'audio') 
     830                                        type = lookup.audio.name; 
     831                        } 
     832 
     833                        if (object && !type) 
     834                                type = (lookupAttribute(object, 'clsid') || lookupAttribute(object, 'classid') || lookupAttribute(object, 'type') || {}).name; 
     835 
     836                        if (embed && !type) 
     837                                type = (lookupAttribute(embed, 'type') || lookupExtension(data.params.src) || {}).name; 
     838 
     839                        // for embedded audio we preserve the original specified type 
     840                        if (embed && type == 'EmbeddedAudio') { 
     841                                data.params.type = embed.attr('type'); 
     842                        } 
     843 
     844                        // Replace the video/object/embed element with a placeholder image containing the data 
     845                        node.replace(img); 
     846 
     847                        // Remove embed 
     848                        if (embed) 
     849                                embed.remove(); 
     850 
     851                        // Serialize the inner HTML of the object element 
     852                        if (object) { 
     853                                html = getInnerHTML(object.remove()); 
     854 
     855                                if (html) 
     856                                        data.object_html = html; 
     857                        } 
     858 
     859                        // Serialize the inner HTML of the video element 
     860                        if (video) { 
     861                                html = getInnerHTML(video.remove()); 
     862 
     863                                if (html) 
     864                                        data.video_html = html; 
     865                        } 
     866 
     867                        data.hspace = hspace; 
     868                        data.vspace = vspace; 
     869                        data.align = align; 
     870                        data.bgcolor = bgcolor; 
     871 
     872                        // Set width/height of placeholder 
     873                        img.attr({ 
     874                                id : id, 
     875                                'class' : 'mceItemMedia mceItem' + (type || 'Flash'), 
     876                                style : style, 
     877                                width : width || (node.name == 'audio' ? "300" : "320"), 
     878                                height : height || (node.name == 'audio' ? "32" : "240"), 
     879                                hspace : hspace, 
     880                                vspace : vspace, 
     881                                align : align, 
     882                                bgcolor : bgcolor, 
     883                                "data-mce-json" : JSON.serialize(data, "'") 
     884                        }); 
     885                } 
     886        }); 
     887 
     888        // Register plugin 
     889        tinymce.PluginManager.add('media', tinymce.plugins.MediaPlugin); 
     890})(); 
  • wp-includes/js/tinymce/plugins/wpeditimage/editor_plugin.js

     
     1 
    12(function(){tinymce.create("tinymce.plugins.wpEditImage",{init:function(a,c){var d=this,b={};d.url=c;d._createButtons();a.addCommand("WP_EditImage",function(){var i=a.selection.getNode(),g=tinymce.DOM.getViewPort(),h=g.h,e=(720<g.w)?720:g.w,f=a.dom.getAttrib(i,"class");if(f.indexOf("mceItem")!=-1||f.indexOf("wpGallery")!=-1||i.nodeName!="IMG"){return}tb_show("",c+"/editimage.html?ver=321&TB_iframe=true");tinymce.DOM.setStyles("TB_window",{width:(e-50)+"px",height:(h-45)+"px","margin-left":"-"+parseInt(((e-50)/2),10)+"px"});if(!tinymce.isIE6){tinymce.DOM.setStyles("TB_window",{top:"20px",marginTop:"0"})}tinymce.DOM.setStyles("TB_iframeContent",{width:(e-50)+"px",height:(h-75)+"px"});tinymce.DOM.setStyle(["TB_overlay","TB_window","TB_load"],"z-index","999999")});a.onInit.add(function(e){tinymce.dom.Event.add(e.getBody(),"dragstart",function(f){if(!tinymce.isGecko&&f.target.nodeName=="IMG"&&e.dom.getParent(f.target,"dl.wp-caption")){return tinymce.dom.Event.cancel(f)}})});a.onMouseUp.add(function(f,g){if(tinymce.isWebKit||tinymce.isOpera){return}if(b.x&&(g.clientX!=b.x||g.clientY!=b.y)){var h=f.selection.getNode();if("IMG"==h.nodeName){window.setTimeout(function(){var e,i;if(h.width!=b.img_w||h.height!=b.img_h){h.className=h.className.replace(/size-[^ "']+/,"")}if(f.dom.getParent(h,"div.mceTemp")){e=f.dom.getParent(h,"dl.wp-caption");if(e){i=f.dom.getAttrib(h,"width")||h.width;i=parseInt(i,10);f.dom.setStyle(e,"width",10+i);f.execCommand("mceRepaint")}}},100)}}b={}});a.onMouseDown.add(function(f,g){if(g.target&&(g.target.nodeName=="IMG"||(g.target.firstChild&&g.target.firstChild.nodeName=="IMG"))){b={x:g.clientX,y:g.clientY,img_w:g.target.clientWidth,img_h:g.target.clientHeight};if(f.dom.getAttrib(g.target,"class").indexOf("mceItem")==-1){f.plugins.wordpress._showButtons(g.target,"wp_editbtns")}}});a.onKeyPress.add(function(f,j){var k,g,i,h;if(j.keyCode==13){k=f.selection.getNode();g=f.dom.getParent(k,"dl.wp-caption");i=f.dom.getParent(g,"div.mceTemp");if(g&&i){h=f.dom.create("p",{},"&nbsp;");f.dom.insertAfter(h,i);if(h.firstChild){f.selection.select(h.firstChild)}else{f.selection.select(h)}tinymce.dom.Event.cancel(j);return false}}});a.onBeforeSetContent.add(function(e,f){f.content=d._do_shcode(f.content)});a.onPostProcess.add(function(e,f){if(f.get){f.content=d._get_shcode(f.content)}})},_do_shcode:function(a){return a.replace(/(?:<p>)?\[(?:wp_)?caption([^\]]+)\]([\s\S]+?)\[\/(?:wp_)?caption\](?:<\/p>)?[\s\u00a0]*/g,function(g,d,k){var j,f,e,h,i;d=d.replace(/\\'|\\&#39;|\\&#039;/g,"&#39;").replace(/\\"|\\&quot;/g,"&quot;");k=k.replace(/\\&#39;|\\&#039;/g,"&#39;").replace(/\\&quot;/g,"&quot;");j=d.match(/id=['"]([^'"]+)/i);f=d.match(/align=['"]([^'"]+)/i);e=d.match(/width=['"]([0-9]+)/);h=d.match(/caption=['"]([^'"]+)/i);j=(j&&j[1])?j[1]:"";f=(f&&f[1])?f[1]:"alignnone";e=(e&&e[1])?e[1]:"";h=(h&&h[1])?h[1]:"";if(!e||!h){return k}i=(f=="aligncenter")?"mceTemp mceIEcenter":"mceTemp";return'<div class="'+i+'" draggable><dl id="'+j+'" class="wp-caption '+f+'" style="width: '+(10+parseInt(e))+'px"><dt class="wp-caption-dt">'+k+'</dt><dd class="wp-caption-dd">'+h+"</dd></dl></div>"})},_get_shcode:function(a){return a.replace(/<div class="mceTemp[^"]*">\s*<dl([^>]+)>\s*<dt[^>]+>([\s\S]+?)<\/dt>\s*<dd[^>]+>(.+?)<\/dd>\s*<\/dl>\s*<\/div>\s*/gi,function(g,d,j,h){var i,f,e;i=d.match(/id=['"]([^'"]+)/i);f=d.match(/class=['"]([^'"]+)/i);e=j.match(/width=['"]([0-9]+)/);i=(i&&i[1])?i[1]:"";f=(f&&f[1])?f[1]:"alignnone";e=(e&&e[1])?e[1]:"";if(!e||!h){return j}f=f.match(/align[^ '"]+/)||"alignnone";h=h.replace(/<\S[^<>]*>/gi,"").replace(/'/g,"&#39;").replace(/"/g,"&quot;");return'[caption id="'+i+'" align="'+f+'" width="'+e+'" caption="'+h+'"]'+j+"[/caption]"})},_createButtons:function(){var b=this,a=tinyMCE.activeEditor,d=tinymce.DOM,e,c;d.remove("wp_editbtns");d.add(document.body,"div",{id:"wp_editbtns",style:"display:none;"});e=d.add("wp_editbtns","img",{src:b.url+"/img/image.png",id:"wp_editimgbtn",width:"24",height:"24",title:a.getLang("wpeditimage.edit_img")});tinymce.dom.Event.add(e,"mousedown",function(g){var f=tinyMCE.activeEditor;f.windowManager.bookmark=f.selection.getBookmark("simple");f.execCommand("WP_EditImage")});c=d.add("wp_editbtns","img",{src:b.url+"/img/delete.png",id:"wp_delimgbtn",width:"24",height:"24",title:a.getLang("wpeditimage.del_img")});tinymce.dom.Event.add(c,"mousedown",function(i){var f=tinyMCE.activeEditor,g=f.selection.getNode(),h;if(g.nodeName=="IMG"&&f.dom.getAttrib(g,"class").indexOf("mceItem")==-1){if((h=f.dom.getParent(g,"div"))&&f.dom.hasClass(h,"mceTemp")){f.dom.remove(h)}else{if((h=f.dom.getParent(g,"A"))&&h.childNodes.length==1){f.dom.remove(h)}else{f.dom.remove(g)}}f.execCommand("mceRepaint");return false}})},getInfo:function(){return{longname:"Edit Image",author:"WordPress",authorurl:"http://wordpress.org",infourl:"",version:"1.0"}}});tinymce.PluginManager.add("wpeditimage",tinymce.plugins.wpEditImage)})(); 
     3 No newline at end of file 
  • wp-includes/js/tinymce/plugins/fullscreen/editor_plugin.dev.js

     
     1/** 
     2 * editor_plugin_src.js 
     3 * 
     4 * Copyright 2009, Moxiecode Systems AB 
     5 * Released under LGPL License. 
     6 * 
     7 * License: http://tinymce.moxiecode.com/license 
     8 * Contributing: http://tinymce.moxiecode.com/contributing 
     9 */ 
     10 
     11(function() { 
     12        var DOM = tinymce.DOM; 
     13 
     14        tinymce.create('tinymce.plugins.FullScreenPlugin', { 
     15                init : function(ed, url) { 
     16                        var t = this, s = {}, vp, posCss; 
     17 
     18                        t.editor = ed; 
     19 
     20                        // Register commands 
     21                        ed.addCommand('mceFullScreen', function() { 
     22                                var win, de = DOM.doc.documentElement; 
     23 
     24                                if (ed.getParam('fullscreen_is_enabled')) { 
     25                                        if (ed.getParam('fullscreen_new_window')) 
     26                                                closeFullscreen(); // Call to close in new window 
     27                                        else { 
     28                                                DOM.win.setTimeout(function() { 
     29                                                        tinymce.dom.Event.remove(DOM.win, 'resize', t.resizeFunc); 
     30                                                        tinyMCE.get(ed.getParam('fullscreen_editor_id')).setContent(ed.getContent()); 
     31                                                        tinyMCE.remove(ed); 
     32                                                        DOM.remove('mce_fullscreen_container'); 
     33                                                        de.style.overflow = ed.getParam('fullscreen_html_overflow'); 
     34                                                        DOM.setStyle(DOM.doc.body, 'overflow', ed.getParam('fullscreen_overflow')); 
     35                                                        DOM.win.scrollTo(ed.getParam('fullscreen_scrollx'), ed.getParam('fullscreen_scrolly')); 
     36                                                        tinyMCE.settings = tinyMCE.oldSettings; // Restore old settings 
     37                                                }, 10); 
     38                                        } 
     39 
     40                                        return; 
     41                                } 
     42 
     43                                if (ed.getParam('fullscreen_new_window')) { 
     44                                        win = DOM.win.open(url + "/fullscreen.htm", "mceFullScreenPopup", "fullscreen=yes,menubar=no,toolbar=no,scrollbars=no,resizable=yes,left=0,top=0,width=" + screen.availWidth + ",height=" + screen.availHeight); 
     45                                        try { 
     46                                                win.resizeTo(screen.availWidth, screen.availHeight); 
     47                                        } catch (e) { 
     48                                                // Ignore 
     49                                        } 
     50                                } else { 
     51                                        tinyMCE.oldSettings = tinyMCE.settings; // Store old settings 
     52                                        s.fullscreen_overflow = DOM.getStyle(DOM.doc.body, 'overflow', 1) || 'auto'; 
     53                                        s.fullscreen_html_overflow = DOM.getStyle(de, 'overflow', 1); 
     54                                        vp = DOM.getViewPort(); 
     55                                        s.fullscreen_scrollx = vp.x; 
     56                                        s.fullscreen_scrolly = vp.y; 
     57 
     58                                        // Fixes an Opera bug where the scrollbars doesn't reappear 
     59                                        if (tinymce.isOpera && s.fullscreen_overflow == 'visible') 
     60                                                s.fullscreen_overflow = 'auto'; 
     61 
     62                                        // Fixes an IE bug where horizontal scrollbars would appear 
     63                                        if (tinymce.isIE && s.fullscreen_overflow == 'scroll') 
     64                                                s.fullscreen_overflow = 'auto'; 
     65 
     66                                        // Fixes an IE bug where the scrollbars doesn't reappear 
     67                                        if (tinymce.isIE && (s.fullscreen_html_overflow == 'visible' || s.fullscreen_html_overflow == 'scroll')) 
     68                                                s.fullscreen_html_overflow = 'auto';  
     69 
     70                                        if (s.fullscreen_overflow == '0px') 
     71                                                s.fullscreen_overflow = ''; 
     72 
     73                                        DOM.setStyle(DOM.doc.body, 'overflow', 'hidden'); 
     74                                        de.style.overflow = 'hidden'; //Fix for IE6/7 
     75                                        vp = DOM.getViewPort(); 
     76                                        DOM.win.scrollTo(0, 0); 
     77 
     78                                        if (tinymce.isIE) 
     79                                                vp.h -= 1; 
     80 
     81                                        // Use fixed position if it exists 
     82                                        if (tinymce.isIE6) 
     83                                                posCss = 'absolute;top:' + vp.y; 
     84                                        else 
     85                                                posCss = 'fixed;top:0'; 
     86 
     87                                        n = DOM.add(DOM.doc.body, 'div', { 
     88                                                id : 'mce_fullscreen_container',  
     89                                                style : 'position:' + posCss + ';left:0;width:' + vp.w + 'px;height:' + vp.h + 'px;z-index:200000;'}); 
     90                                        DOM.add(n, 'div', {id : 'mce_fullscreen'}); 
     91 
     92                                        tinymce.each(ed.settings, function(v, n) { 
     93                                                s[n] = v; 
     94                                        }); 
     95 
     96                                        s.id = 'mce_fullscreen'; 
     97                                        s.width = n.clientWidth; 
     98                                        s.height = n.clientHeight - 15; 
     99                                        s.fullscreen_is_enabled = true; 
     100                                        s.fullscreen_editor_id = ed.id; 
     101                                        s.theme_advanced_resizing = false; 
     102                                        s.save_onsavecallback = function() { 
     103                                                ed.setContent(tinyMCE.get(s.id).getContent()); 
     104                                                ed.execCommand('mceSave'); 
     105                                        }; 
     106 
     107                                        tinymce.each(ed.getParam('fullscreen_settings'), function(v, k) { 
     108                                                s[k] = v; 
     109                                        }); 
     110 
     111                                        if (s.theme_advanced_toolbar_location === 'external') 
     112                                                s.theme_advanced_toolbar_location = 'top'; 
     113 
     114                                        t.fullscreenEditor = new tinymce.Editor('mce_fullscreen', s); 
     115                                        t.fullscreenEditor.onInit.add(function() { 
     116                                                t.fullscreenEditor.setContent(ed.getContent()); 
     117                                                t.fullscreenEditor.focus(); 
     118                                        }); 
     119 
     120                                        t.fullscreenEditor.render(); 
     121 
     122                                        t.fullscreenElement = new tinymce.dom.Element('mce_fullscreen_container'); 
     123                                        t.fullscreenElement.update(); 
     124                                        //document.body.overflow = 'hidden'; 
     125 
     126                                        t.resizeFunc = tinymce.dom.Event.add(DOM.win, 'resize', function() { 
     127                                                var vp = tinymce.DOM.getViewPort(), fed = t.fullscreenEditor, outerSize, innerSize; 
     128 
     129                                                // Get outer/inner size to get a delta size that can be used to calc the new iframe size 
     130                                                outerSize = fed.dom.getSize(fed.getContainer().firstChild); 
     131                                                innerSize = fed.dom.getSize(fed.getContainer().getElementsByTagName('iframe')[0]); 
     132 
     133                                                fed.theme.resizeTo(vp.w - outerSize.w + innerSize.w, vp.h - outerSize.h + innerSize.h); 
     134                                        }); 
     135                                } 
     136                        }); 
     137 
     138                        // Register buttons 
     139                        ed.addButton('fullscreen', {title : 'fullscreen.desc', cmd : 'mceFullScreen'}); 
     140 
     141                        ed.onNodeChange.add(function(ed, cm) { 
     142                                cm.setActive('fullscreen', ed.getParam('fullscreen_is_enabled')); 
     143                        }); 
     144                }, 
     145 
     146                getInfo : function() { 
     147                        return { 
     148                                longname : 'Fullscreen', 
     149                                author : 'Moxiecode Systems AB', 
     150                                authorurl : 'http://tinymce.moxiecode.com', 
     151                                infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullscreen', 
     152                                version : tinymce.majorVersion + "." + tinymce.minorVersion 
     153                        }; 
     154                } 
     155        }); 
     156 
     157        // Register plugin 
     158        tinymce.PluginManager.add('fullscreen', tinymce.plugins.FullScreenPlugin); 
     159})(); 
     160 No newline at end of file 
  • wp-includes/js/tinymce/plugins/directionality/editor_plugin.dev.js

     
     1/** 
     2 * editor_plugin_src.js 
     3 * 
     4 * Copyright 2009, Moxiecode Systems AB 
     5 * Released under LGPL License. 
     6 * 
     7 * License: http://tinymce.moxiecode.com/license 
     8 * Contributing: http://tinymce.moxiecode.com/contributing 
     9 */ 
     10 
     11(function() { 
     12        tinymce.create('tinymce.plugins.Directionality', { 
     13                init : function(ed, url) { 
     14                        var t = this; 
     15 
     16                        t.editor = ed; 
     17 
     18                        ed.addCommand('mceDirectionLTR', function() { 
     19                                var e = ed.dom.getParent(ed.selection.getNode(), ed.dom.isBlock); 
     20 
     21                                if (e) { 
     22                                        if (ed.dom.getAttrib(e, "dir") != "ltr") 
     23                                                ed.dom.setAttrib(e, "dir", "ltr"); 
     24                                        else 
     25                                                ed.dom.setAttrib(e, "dir", ""); 
     26                                } 
     27 
     28                                ed.nodeChanged(); 
     29                        }); 
     30 
     31                        ed.addCommand('mceDirectionRTL', function() { 
     32                                var e = ed.dom.getParent(ed.selection.getNode(), ed.dom.isBlock); 
     33 
     34                                if (e) { 
     35                                        if (ed.dom.getAttrib(e, "dir") != "rtl") 
     36                                                ed.dom.setAttrib(e, "dir", "rtl"); 
     37                                        else 
     38                                                ed.dom.setAttrib(e, "dir", ""); 
     39                                } 
     40 
     41                                ed.nodeChanged(); 
     42                        }); 
     43 
     44                        ed.addButton('ltr', {title : 'directionality.ltr_desc', cmd : 'mceDirectionLTR'}); 
     45                        ed.addButton('rtl', {title : 'directionality.rtl_desc', cmd : 'mceDirectionRTL'}); 
     46 
     47                        ed.onNodeChange.add(t._nodeChange, t); 
     48                }, 
     49 
     50                getInfo : function() { 
     51                        return { 
     52                                longname : 'Directionality', 
     53                                author : 'Moxiecode Systems AB', 
     54                                authorurl : 'http://tinymce.moxiecode.com', 
     55                                infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/directionality', 
     56                                version : tinymce.majorVersion + "." + tinymce.minorVersion 
     57                        }; 
     58                }, 
     59 
     60                // Private methods 
     61 
     62                _nodeChange : function(ed, cm, n) { 
     63                        var dom = ed.dom, dir; 
     64 
     65                        n = dom.getParent(n, dom.isBlock); 
     66                        if (!n) { 
     67                                cm.setDisabled('ltr', 1); 
     68                                cm.setDisabled('rtl', 1); 
     69                                return; 
     70                        } 
     71 
     72                        dir = dom.getAttrib(n, 'dir'); 
     73                        cm.setActive('ltr', dir == "ltr"); 
     74                        cm.setDisabled('ltr', 0); 
     75                        cm.setActive('rtl', dir == "rtl"); 
     76                        cm.setDisabled('rtl', 0); 
     77                } 
     78        }); 
     79 
     80        // Register plugin 
     81        tinymce.PluginManager.add('directionality', tinymce.plugins.Directionality); 
     82})(); 
     83 No newline at end of file 
  • wp-includes/js/tinymce/plugins/spellchecker/editor_plugin.dev.js

     
     1/** 
     2 * editor_plugin_src.js 
     3 * 
     4 * Copyright 2009, Moxiecode Systems AB 
     5 * Released under LGPL License. 
     6 * 
     7 * License: http://tinymce.moxiecode.com/license 
     8 * Contributing: http://tinymce.moxiecode.com/contributing 
     9 */ 
     10 
     11(function() { 
     12        var JSONRequest = tinymce.util.JSONRequest, each = tinymce.each, DOM = tinymce.DOM; 
     13 
     14        tinymce.create('tinymce.plugins.SpellcheckerPlugin', { 
     15                getInfo : function() { 
     16                        return { 
     17                                longname : 'Spellchecker', 
     18                                author : 'Moxiecode Systems AB', 
     19                                authorurl : 'http://tinymce.moxiecode.com', 
     20                                infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/spellchecker', 
     21                                version : tinymce.majorVersion + "." + tinymce.minorVersion 
     22                        }; 
     23                }, 
     24 
     25                init : function(ed, url) { 
     26                        var t = this, cm; 
     27 
     28                        t.url = url; 
     29                        t.editor = ed; 
     30                        t.rpcUrl = ed.getParam("spellchecker_rpc_url", "{backend}"); 
     31 
     32                        if (t.rpcUrl == '{backend}') { 
     33                                // Sniff if the browser supports native spellchecking (Don't know of a better way) 
     34                                if (tinymce.isIE) 
     35                                        return; 
     36 
     37                                t.hasSupport = true; 
     38 
     39                                // Disable the context menu when spellchecking is active 
     40                                ed.onContextMenu.addToTop(function(ed, e) { 
     41                                        if (t.active) 
     42                                                return false; 
     43                                }); 
     44                        } 
     45 
     46                        // Register commands 
     47                        ed.addCommand('mceSpellCheck', function() { 
     48                                if (t.rpcUrl == '{backend}') { 
     49                                        // Enable/disable native spellchecker 
     50                                        t.editor.getBody().spellcheck = t.active = !t.active; 
     51                                        return; 
     52                                } 
     53 
     54                                if (!t.active) { 
     55                                        ed.setProgressState(1); 
     56                                        t._sendRPC('checkWords', [t.selectedLang, t._getWords()], function(r) { 
     57                                                if (r.length > 0) { 
     58                                                        t.active = 1; 
     59                                                        t._markWords(r); 
     60                                                        ed.setProgressState(0); 
     61                                                        ed.nodeChanged(); 
     62                                                } else { 
     63                                                        ed.setProgressState(0); 
     64 
     65                                                        if (ed.getParam('spellchecker_report_no_misspellings', true)) 
     66                                                                ed.windowManager.alert('spellchecker.no_mpell'); 
     67                                                } 
     68                                        }); 
     69                                } else 
     70                                        t._done(); 
     71                        }); 
     72 
     73                        if (ed.settings.content_css !== false) 
     74                                ed.contentCSS.push(url + '/css/content.css'); 
     75 
     76                        ed.onClick.add(t._showMenu, t); 
     77                        ed.onContextMenu.add(t._showMenu, t); 
     78                        ed.onBeforeGetContent.add(function() { 
     79                                if (t.active) 
     80                                        t._removeWords(); 
     81                        }); 
     82 
     83                        ed.onNodeChange.add(function(ed, cm) { 
     84                                cm.setActive('spellchecker', t.active); 
     85                        }); 
     86 
     87                        ed.onSetContent.add(function() { 
     88                                t._done(); 
     89                        }); 
     90 
     91                        ed.onBeforeGetContent.add(function() { 
     92                                t._done(); 
     93                        }); 
     94 
     95                        ed.onBeforeExecCommand.add(function(ed, cmd) { 
     96                                if (cmd == 'mceFullScreen') 
     97                                        t._done(); 
     98                        }); 
     99 
     100                        // Find selected language 
     101                        t.languages = {}; 
     102                        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', 'hash'), function(v, k) { 
     103                                if (k.indexOf('+') === 0) { 
     104                                        k = k.substring(1); 
     105                                        t.selectedLang = v; 
     106                                } 
     107 
     108                                t.languages[k] = v; 
     109                        }); 
     110                }, 
     111 
     112                createControl : function(n, cm) { 
     113                        var t = this, c, ed = t.editor; 
     114 
     115                        if (n == 'spellchecker') { 
     116                                // Use basic button if we use the native spellchecker 
     117                                if (t.rpcUrl == '{backend}') { 
     118                                        // Create simple toggle button if we have native support 
     119                                        if (t.hasSupport) 
     120                                                c = cm.createButton(n, {title : 'spellchecker.desc', cmd : 'mceSpellCheck', scope : t}); 
     121 
     122                                        return c; 
     123                                } 
     124 
     125                                c = cm.createSplitButton(n, {title : 'spellchecker.desc', cmd : 'mceSpellCheck', scope : t}); 
     126 
     127                                c.onRenderMenu.add(function(c, m) { 
     128                                        m.add({title : 'spellchecker.langs', 'class' : 'mceMenuItemTitle'}).setDisabled(1); 
     129                                        each(t.languages, function(v, k) { 
     130                                                var o = {icon : 1}, mi; 
     131 
     132                                                o.onclick = function() { 
     133                                                        if (v == t.selectedLang) { 
     134                                                                return; 
     135                                                        } 
     136                                                        mi.setSelected(1); 
     137                                                        t.selectedItem.setSelected(0); 
     138                                                        t.selectedItem = mi; 
     139                                                        t.selectedLang = v; 
     140                                                }; 
     141 
     142                                                o.title = k; 
     143                                                mi = m.add(o); 
     144                                                mi.setSelected(v == t.selectedLang); 
     145 
     146                                                if (v == t.selectedLang) 
     147                                                        t.selectedItem = mi; 
     148                                        }) 
     149                                }); 
     150 
     151                                return c; 
     152                        } 
     153                }, 
     154 
     155                // Internal functions 
     156 
     157                _walk : function(n, f) { 
     158                        var d = this.editor.getDoc(), w; 
     159 
     160                        if (d.createTreeWalker) { 
     161                                w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false); 
     162 
     163                                while ((n = w.nextNode()) != null) 
     164                                        f.call(this, n); 
     165                        } else 
     166                                tinymce.walk(n, f, 'childNodes'); 
     167                }, 
     168 
     169                _getSeparators : function() { 
     170                        var re = '', i, str = this.editor.getParam('spellchecker_word_separator_chars', '\\s!"#$%&()*+,-./:;<=>?@[\]^_{|}§©«®±¶·¸»¼½¾¿×÷¤\u201d\u201c'); 
     171 
     172                        // Build word separator regexp 
     173                        for (i=0; i<str.length; i++) 
     174                                re += '\\' + str.charAt(i); 
     175 
     176                        return re; 
     177                }, 
     178 
     179                _getWords : function() { 
     180                        var ed = this.editor, wl = [], tx = '', lo = {}, rawWords = []; 
     181 
     182                        // Get area text 
     183                        this._walk(ed.getBody(), function(n) { 
     184                                if (n.nodeType == 3) 
     185                                        tx += n.nodeValue + ' '; 
     186                        }); 
     187 
     188                        // split the text up into individual words 
     189                        if (ed.getParam('spellchecker_word_pattern')) { 
     190                                // look for words that match the pattern 
     191                                rawWords = tx.match('(' + ed.getParam('spellchecker_word_pattern') + ')', 'gi'); 
     192                        } else { 
     193                                // Split words by separator 
     194                                tx = tx.replace(new RegExp('([0-9]|[' + this._getSeparators() + '])', 'g'), ' '); 
     195                                tx = tinymce.trim(tx.replace(/(\s+)/g, ' ')); 
     196                                rawWords = tx.split(' '); 
     197                        } 
     198 
     199                        // Build word array and remove duplicates 
     200                        each(rawWords, function(v) { 
     201                                if (!lo[v]) { 
     202                                        wl.push(v); 
     203                                        lo[v] = 1; 
     204                                } 
     205                        }); 
     206 
     207                        return wl; 
     208                }, 
     209 
     210                _removeWords : function(w) { 
     211                        var ed = this.editor, dom = ed.dom, se = ed.selection, b = se.getBookmark(); 
     212 
     213                        each(dom.select('span').reverse(), function(n) { 
     214                                if (n && (dom.hasClass(n, 'mceItemHiddenSpellWord') || dom.hasClass(n, 'mceItemHidden'))) { 
     215                                        if (!w || dom.decode(n.innerHTML) == w) 
     216                                                dom.remove(n, 1); 
     217                                } 
     218                        }); 
     219 
     220                        se.moveToBookmark(b); 
     221                }, 
     222 
     223                _markWords : function(wl) { 
     224                        var ed = this.editor, dom = ed.dom, doc = ed.getDoc(), se = ed.selection, b = se.getBookmark(), nl = [], 
     225                                w = wl.join('|'), re = this._getSeparators(), rx = new RegExp('(^|[' + re + '])(' + w + ')(?=[' + re + ']|$)', 'g'); 
     226 
     227                        // Collect all text nodes 
     228                        this._walk(ed.getBody(), function(n) { 
     229                                if (n.nodeType == 3) { 
     230                                        nl.push(n); 
     231                                } 
     232                        }); 
     233 
     234                        // Wrap incorrect words in spans 
     235                        each(nl, function(n) { 
     236                                var node, elem, txt, pos, v = n.nodeValue; 
     237 
     238                                if (rx.test(v)) { 
     239                                        // Encode the content 
     240                                        v = dom.encode(v); 
     241                                        // Create container element 
     242                                        elem = dom.create('span', {'class' : 'mceItemHidden'}); 
     243 
     244                                        // Following code fixes IE issues by creating text nodes 
     245                                        // using DOM methods instead of innerHTML. 
     246                                        // Bug #3124: <PRE> elements content is broken after spellchecking. 
     247                                        // Bug #1408: Preceding whitespace characters are removed 
     248                                        // @TODO: I'm not sure that both are still issues on IE9. 
     249                                        if (tinymce.isIE) { 
     250                                                // Enclose mispelled words with temporal tag 
     251                                                v = v.replace(rx, '$1<mcespell>$2</mcespell>'); 
     252                                                // Loop over the content finding mispelled words 
     253                                                while ((pos = v.indexOf('<mcespell>')) != -1) { 
     254                                                        // Add text node for the content before the word 
     255                                                        txt = v.substring(0, pos); 
     256                                                        if (txt.length) { 
     257                                                                node = doc.createTextNode(dom.decode(txt)); 
     258                                                                elem.appendChild(node); 
     259                                                        } 
     260                                                        v = v.substring(pos+10); 
     261                                                        pos = v.indexOf('</mcespell>'); 
     262                                                        txt = v.substring(0, pos); 
     263                                                        v = v.substring(pos+11); 
     264                                                        // Add span element for the word 
     265                                                        elem.appendChild(dom.create('span', {'class' : 'mceItemHiddenSpellWord'}, txt)); 
     266                                                } 
     267                                                // Add text node for the rest of the content 
     268                                                if (v.length) { 
     269                                                        node = doc.createTextNode(dom.decode(v)); 
     270                                                        elem.appendChild(node); 
     271                                                } 
     272                                        } else { 
     273                                                // Other browsers preserve whitespace characters on innerHTML usage 
     274                                                elem.innerHTML = v.replace(rx, '$1<span class="mceItemHiddenSpellWord">$2</span>'); 
     275                                        } 
     276 
     277                                        // Finally, replace the node with the container 
     278                                        dom.replace(elem, n); 
     279                                } 
     280                        }); 
     281 
     282                        se.moveToBookmark(b); 
     283                }, 
     284 
     285                _showMenu : function(ed, e) { 
     286                        var t = this, ed = t.editor, m = t._menu, p1, dom = ed.dom, vp = dom.getViewPort(ed.getWin()), wordSpan = e.target; 
     287 
     288                        e = 0; // Fixes IE memory leak 
     289 
     290                        if (!m) { 
     291                                m = ed.controlManager.createDropMenu('spellcheckermenu', {'class' : 'mceNoIcons'}); 
     292                                t._menu = m; 
     293                        } 
     294 
     295                        if (dom.hasClass(wordSpan, 'mceItemHiddenSpellWord')) { 
     296                                m.removeAll(); 
     297                                m.add({title : 'spellchecker.wait', 'class' : 'mceMenuItemTitle'}).setDisabled(1); 
     298 
     299                                t._sendRPC('getSuggestions', [t.selectedLang, dom.decode(wordSpan.innerHTML)], function(r) { 
     300                                        var ignoreRpc; 
     301 
     302                                        m.removeAll(); 
     303 
     304                                        if (r.length > 0) { 
     305                                                m.add({title : 'spellchecker.sug', 'class' : 'mceMenuItemTitle'}).setDisabled(1); 
     306                                                each(r, function(v) { 
     307                                                        m.add({title : v, onclick : function() { 
     308                                                                dom.replace(ed.getDoc().createTextNode(v), wordSpan); 
     309                                                                t._checkDone(); 
     310                                                        }}); 
     311                                                }); 
     312 
     313                                                m.addSeparator(); 
     314                                        } else 
     315                                                m.add({title : 'spellchecker.no_sug', 'class' : 'mceMenuItemTitle'}).setDisabled(1); 
     316 
     317                                        if (ed.getParam('show_ignore_words', true)) { 
     318                                                ignoreRpc = t.editor.getParam("spellchecker_enable_ignore_rpc", ''); 
     319                                                m.add({ 
     320                                                        title : 'spellchecker.ignore_word', 
     321                                                        onclick : function() { 
     322                                                                var word = wordSpan.innerHTML; 
     323 
     324                                                                dom.remove(wordSpan, 1); 
     325                                                                t._checkDone(); 
     326 
     327                                                                // tell the server if we need to 
     328                                                                if (ignoreRpc) { 
     329                                                                        ed.setProgressState(1); 
     330                                                                        t._sendRPC('ignoreWord', [t.selectedLang, word], function(r) { 
     331                                                                                ed.setProgressState(0); 
     332                                                                        }); 
     333                                                                } 
     334                                                        } 
     335                                                }); 
     336 
     337                                                m.add({ 
     338                                                        title : 'spellchecker.ignore_words', 
     339                                                        onclick : function() { 
     340                                                                var word = wordSpan.innerHTML; 
     341 
     342                                                                t._removeWords(dom.decode(word)); 
     343                                                                t._checkDone(); 
     344 
     345                                                                // tell the server if we need to 
     346                                                                if (ignoreRpc) { 
     347                                                                        ed.setProgressState(1); 
     348                                                                        t._sendRPC('ignoreWords', [t.selectedLang, word], function(r) { 
     349                                                                                ed.setProgressState(0); 
     350                                                                        }); 
     351                                                                } 
     352                                                        } 
     353                                                }); 
     354                                        } 
     355 
     356                                        if (t.editor.getParam("spellchecker_enable_learn_rpc")) { 
     357                                                m.add({ 
     358                                                        title : 'spellchecker.learn_word', 
     359                                                        onclick : function() { 
     360                                                                var word = wordSpan.innerHTML; 
     361 
     362                                                                dom.remove(wordSpan, 1); 
     363                                                                t._checkDone(); 
     364 
     365                                                                ed.setProgressState(1); 
     366                                                                t._sendRPC('learnWord', [t.selectedLang, word], function(r) { 
     367                                                                        ed.setProgressState(0); 
     368                                                                }); 
     369                                                        } 
     370                                                }); 
     371                                        } 
     372 
     373                                        m.update(); 
     374                                }); 
     375 
     376                                p1 = DOM.getPos(ed.getContentAreaContainer()); 
     377                                m.settings.offset_x = p1.x; 
     378                                m.settings.offset_y = p1.y; 
     379 
     380                                ed.selection.select(wordSpan); 
     381                                p1 = dom.getPos(wordSpan); 
     382                                m.showMenu(p1.x, p1.y + wordSpan.offsetHeight - vp.y); 
     383 
     384                                return tinymce.dom.Event.cancel(e); 
     385                        } else 
     386                                m.hideMenu(); 
     387                }, 
     388 
     389                _checkDone : function() { 
     390                        var t = this, ed = t.editor, dom = ed.dom, o; 
     391 
     392                        each(dom.select('span'), function(n) { 
     393                                if (n && dom.hasClass(n, 'mceItemHiddenSpellWord')) { 
     394                                        o = true; 
     395                                        return false; 
     396                                } 
     397                        }); 
     398 
     399                        if (!o) 
     400                                t._done(); 
     401                }, 
     402 
     403                _done : function() { 
     404                        var t = this, la = t.active; 
     405 
     406                        if (t.active) { 
     407                                t.active = 0; 
     408                                t._removeWords(); 
     409 
     410                                if (t._menu) 
     411                                        t._menu.hideMenu(); 
     412 
     413                                if (la) 
     414                                        t.editor.nodeChanged(); 
     415                        } 
     416                }, 
     417 
     418                _sendRPC : function(m, p, cb) { 
     419                        var t = this; 
     420 
     421                        JSONRequest.sendRPC({ 
     422                                url : t.rpcUrl, 
     423                                method : m, 
     424                                params : p, 
     425                                success : cb, 
     426                                error : function(e, x) { 
     427                                        t.editor.setProgressState(0); 
     428                                        t.editor.windowManager.alert(e.errstr || ('Error response: ' + x.responseText)); 
     429                                } 
     430                        }); 
     431                } 
     432        }); 
     433 
     434        // Register plugin 
     435        tinymce.PluginManager.add('spellchecker', tinymce.plugins.SpellcheckerPlugin); 
     436})(); 
  • wp-includes/js/tinymce/plugins/inlinepopups/editor_plugin.dev.js

     
     1/** 
     2 * editor_plugin_src.js 
     3 * 
     4 * Copyright 2009, Moxiecode Systems AB 
     5 * Released under LGPL License. 
     6 * 
     7 * License: http://tinymce.moxiecode.com/license 
     8 * Contributing: http://tinymce.moxiecode.com/contributing 
     9 */ 
     10 
     11(function() { 
     12        var DOM = tinymce.DOM, Element = tinymce.dom.Element, Event = tinymce.dom.Event, each = tinymce.each, is = tinymce.is; 
     13 
     14        tinymce.create('tinymce.plugins.InlinePopups', { 
     15                init : function(ed, url) { 
     16                        // Replace window manager 
     17                        ed.onBeforeRenderUI.add(function() { 
     18                                ed.windowManager = new tinymce.InlineWindowManager(ed); 
     19                                DOM.loadCSS(url + '/skins/' + (ed.settings.inlinepopups_skin || 'clearlooks2') + "/window.css"); 
     20                        }); 
     21                }, 
     22 
     23                getInfo : function() { 
     24                        return { 
     25                                longname : 'InlinePopups', 
     26                                author : 'Moxiecode Systems AB', 
     27                                authorurl : 'http://tinymce.moxiecode.com', 
     28                                infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/inlinepopups', 
     29                                version : tinymce.majorVersion + "." + tinymce.minorVersion 
     30                        }; 
     31                } 
     32        }); 
     33 
     34        tinymce.create('tinymce.InlineWindowManager:tinymce.WindowManager', { 
     35                InlineWindowManager : function(ed) { 
     36                        var t = this; 
     37 
     38                        t.parent(ed); 
     39                        t.zIndex = 300000; 
     40                        t.count = 0; 
     41                        t.windows = {}; 
     42                }, 
     43 
     44                open : function(f, p) { 
     45                        var t = this, id, opt = '', ed = t.editor, dw = 0, dh = 0, vp, po, mdf, clf, we, w, u, parentWindow; 
     46 
     47                        f = f || {}; 
     48                        p = p || {}; 
     49 
     50                        // Run native windows 
     51                        if (!f.inline) 
     52                                return t.parent(f, p); 
     53 
     54                        parentWindow = t._frontWindow(); 
     55                        if (parentWindow && DOM.get(parentWindow.id + '_ifr')) { 
     56                                parentWindow.focussedElement = DOM.get(parentWindow.id + '_ifr').contentWindow.document.activeElement; 
     57                        } 
     58                         
     59                        // Only store selection if the type is a normal window 
     60                        if (!f.type) 
     61                                t.bookmark = ed.selection.getBookmark(1); 
     62 
     63                        id = DOM.uniqueId(); 
     64                        vp = DOM.getViewPort(); 
     65                        f.width = parseInt(f.width || 320); 
     66                        f.height = parseInt(f.height || 240) + (tinymce.isIE ? 8 : 0); 
     67                        f.min_width = parseInt(f.min_width || 150); 
     68                        f.min_height = parseInt(f.min_height || 100); 
     69                        f.max_width = parseInt(f.max_width || 2000); 
     70                        f.max_height = parseInt(f.max_height || 2000); 
     71                        f.left = f.left || Math.round(Math.max(vp.x, vp.x + (vp.w / 2.0) - (f.width / 2.0))); 
     72                        f.top = f.top || Math.round(Math.max(vp.y, vp.y + (vp.h / 2.0) - (f.height / 2.0))); 
     73                        f.movable = f.resizable = true; 
     74                        p.mce_width = f.width; 
     75                        p.mce_height = f.height; 
     76                        p.mce_inline = true; 
     77                        p.mce_window_id = id; 
     78                        p.mce_auto_focus = f.auto_focus; 
     79 
     80                        // Transpose 
     81//                      po = DOM.getPos(ed.getContainer()); 
     82//                      f.left -= po.x; 
     83//                      f.top -= po.y; 
     84 
     85                        t.features = f; 
     86                        t.params = p; 
     87                        t.onOpen.dispatch(t, f, p); 
     88 
     89                        if (f.type) { 
     90                                opt += ' mceModal'; 
     91 
     92                                if (f.type) 
     93                                        opt += ' mce' + f.type.substring(0, 1).toUpperCase() + f.type.substring(1); 
     94 
     95                                f.resizable = false; 
     96                        } 
     97 
     98                        if (f.statusbar) 
     99                                opt += ' mceStatusbar'; 
     100 
     101                        if (f.resizable) 
     102                                opt += ' mceResizable'; 
     103 
     104                        if (f.minimizable) 
     105                                opt += ' mceMinimizable'; 
     106 
     107                        if (f.maximizable) 
     108                                opt += ' mceMaximizable'; 
     109 
     110                        if (f.movable) 
     111                                opt += ' mceMovable'; 
     112 
     113                        // Create DOM objects 
     114                        t._addAll(DOM.doc.body,  
     115                                ['div', {id : id, role : 'dialog', 'aria-labelledby': f.type ? id + '_content' : id + '_title', 'class' : (ed.settings.inlinepopups_skin || 'clearlooks2') + (tinymce.isIE && window.getSelection ? ' ie9' : ''), style : 'width:100px;height:100px'},  
     116                                        ['div', {id : id + '_wrapper', 'class' : 'mceWrapper' + opt}, 
     117                                                ['div', {id : id + '_top', 'class' : 'mceTop'},  
     118                                                        ['div', {'class' : 'mceLeft'}], 
     119                                                        ['div', {'class' : 'mceCenter'}], 
     120                                                        ['div', {'class' : 'mceRight'}], 
     121                                                        ['span', {id : id + '_title'}, f.title || ''] 
     122                                                ], 
     123 
     124                                                ['div', {id : id + '_middle', 'class' : 'mceMiddle'},  
     125                                                        ['div', {id : id + '_left', 'class' : 'mceLeft', tabindex : '0'}], 
     126                                                        ['span', {id : id + '_content'}], 
     127                                                        ['div', {id : id + '_right', 'class' : 'mceRight', tabindex : '0'}] 
     128                                                ], 
     129 
     130                                                ['div', {id : id + '_bottom', 'class' : 'mceBottom'}, 
     131                                                        ['div', {'class' : 'mceLeft'}], 
     132                                                        ['div', {'class' : 'mceCenter'}], 
     133                                                        ['div', {'class' : 'mceRight'}], 
     134                                                        ['span', {id : id + '_status'}, 'Content'] 
     135                                                ], 
     136 
     137                                                ['a', {'class' : 'mceMove', tabindex : '-1', href : 'javascript:;'}], 
     138                                                ['a', {'class' : 'mceMin', tabindex : '-1', href : 'javascript:;', onmousedown : 'return false;'}], 
     139                                                ['a', {'class' : 'mceMax', tabindex : '-1', href : 'javascript:;', onmousedown : 'return false;'}], 
     140                                                ['a', {'class' : 'mceMed', tabindex : '-1', href : 'javascript:;', onmousedown : 'return false;'}], 
     141                                                ['a', {'class' : 'mceClose', tabindex : '-1', href : 'javascript:;', onmousedown : 'return false;'}], 
     142                                                ['a', {id : id + '_resize_n', 'class' : 'mceResize mceResizeN', tabindex : '-1', href : 'javascript:;'}], 
     143                                                ['a', {id : id + '_resize_s', 'class' : 'mceResize mceResizeS', tabindex : '-1', href : 'javascript:;'}], 
     144                                                ['a', {id : id + '_resize_w', 'class' : 'mceResize mceResizeW', tabindex : '-1', href : 'javascript:;'}], 
     145                                                ['a', {id : id + '_resize_e', 'class' : 'mceResize mceResizeE', tabindex : '-1', href : 'javascript:;'}], 
     146                                                ['a', {id : id + '_resize_nw', 'class' : 'mceResize mceResizeNW', tabindex : '-1', href : 'javascript:;'}], 
     147                                                ['a', {id : id + '_resize_ne', 'class' : 'mceResize mceResizeNE', tabindex : '-1', href : 'javascript:;'}], 
     148                                                ['a', {id : id + '_resize_sw', 'class' : 'mceResize mceResizeSW', tabindex : '-1', href : 'javascript:;'}], 
     149                                                ['a', {id : id + '_resize_se', 'class' : 'mceResize mceResizeSE', tabindex : '-1', href : 'javascript:;'}] 
     150                                        ] 
     151                                ] 
     152                        ); 
     153 
     154                        DOM.setStyles(id, {top : -10000, left : -10000}); 
     155 
     156                        // Fix gecko rendering bug, where the editors iframe messed with window contents 
     157                        if (tinymce.isGecko) 
     158                                DOM.setStyle(id, 'overflow', 'auto'); 
     159 
     160                        // Measure borders 
     161                        if (!f.type) { 
     162                                dw += DOM.get(id + '_left').clientWidth; 
     163                                dw += DOM.get(id + '_right').clientWidth; 
     164                                dh += DOM.get(id + '_top').clientHeight; 
     165                                dh += DOM.get(id + '_bottom').clientHeight; 
     166                        } 
     167 
     168                        // Resize window 
     169                        DOM.setStyles(id, {top : f.top, left : f.left, width : f.width + dw, height : f.height + dh}); 
     170 
     171                        u = f.url || f.file; 
     172                        if (u) { 
     173                                if (tinymce.relaxedDomain) 
     174                                        u += (u.indexOf('?') == -1 ? '?' : '&') + 'mce_rdomain=' + tinymce.relaxedDomain; 
     175 
     176                                u = tinymce._addVer(u); 
     177                        } 
     178 
     179                        if (!f.type) { 
     180                                DOM.add(id + '_content', 'iframe', {id : id + '_ifr', src : 'javascript:""', frameBorder : 0, style : 'border:0;width:10px;height:10px'}); 
     181                                DOM.setStyles(id + '_ifr', {width : f.width, height : f.height}); 
     182                                DOM.setAttrib(id + '_ifr', 'src', u); 
     183                        } else { 
     184                                DOM.add(id + '_wrapper', 'a', {id : id + '_ok', 'class' : 'mceButton mceOk', href : 'javascript:;', onmousedown : 'return false;'}, 'Ok'); 
     185 
     186                                if (f.type == 'confirm') 
     187                                        DOM.add(id + '_wrapper', 'a', {'class' : 'mceButton mceCancel', href : 'javascript:;', onmousedown : 'return false;'}, 'Cancel'); 
     188 
     189                                DOM.add(id + '_middle', 'div', {'class' : 'mceIcon'}); 
     190                                DOM.setHTML(id + '_content', f.content.replace('\n', '<br />')); 
     191                                 
     192                                Event.add(id, 'keyup', function(evt) { 
     193                                        var VK_ESCAPE = 27; 
     194                                        if (evt.keyCode === VK_ESCAPE) { 
     195                                                f.button_func(false); 
     196                                                return Event.cancel(evt); 
     197                                        } 
     198                                }); 
     199 
     200                                Event.add(id, 'keydown', function(evt) { 
     201                                        var cancelButton, VK_TAB = 9; 
     202                                        if (evt.keyCode === VK_TAB) { 
     203                                                cancelButton = DOM.select('a.mceCancel', id + '_wrapper')[0]; 
     204                                                if (cancelButton && cancelButton !== evt.target) { 
     205                                                        cancelButton.focus(); 
     206                                                } else { 
     207                                                        DOM.get(id + '_ok').focus(); 
     208                                                } 
     209                                                return Event.cancel(evt); 
     210                                        } 
     211                                }); 
     212                        } 
     213 
     214                        // Register events 
     215                        mdf = Event.add(id, 'mousedown', function(e) { 
     216                                var n = e.target, w, vp; 
     217 
     218                                w = t.windows[id]; 
     219                                t.focus(id); 
     220 
     221                                if (n.nodeName == 'A' || n.nodeName == 'a') { 
     222                                        if (n.className == 'mceClose') { 
     223                                                t.close(null, id); 
     224                                                return Event.cancel(e); 
     225                                        } else if (n.className == 'mceMax') { 
     226                                                w.oldPos = w.element.getXY(); 
     227                                                w.oldSize = w.element.getSize(); 
     228 
     229                                                vp = DOM.getViewPort(); 
     230 
     231                                                // Reduce viewport size to avoid scrollbars 
     232                                                vp.w -= 2; 
     233                                                vp.h -= 2; 
     234 
     235                                                w.element.moveTo(vp.x, vp.y); 
     236                                                w.element.resizeTo(vp.w, vp.h); 
     237                                                DOM.setStyles(id + '_ifr', {width : vp.w - w.deltaWidth, height : vp.h - w.deltaHeight}); 
     238                                                DOM.addClass(id + '_wrapper', 'mceMaximized'); 
     239                                        } else if (n.className == 'mceMed') { 
     240                                                // Reset to old size 
     241                                                w.element.moveTo(w.oldPos.x, w.oldPos.y); 
     242                                                w.element.resizeTo(w.oldSize.w, w.oldSize.h); 
     243                                                w.iframeElement.resizeTo(w.oldSize.w - w.deltaWidth, w.oldSize.h - w.deltaHeight); 
     244 
     245                                                DOM.removeClass(id + '_wrapper', 'mceMaximized'); 
     246                                        } else if (n.className == 'mceMove') 
     247                                                return t._startDrag(id, e, n.className); 
     248                                        else if (DOM.hasClass(n, 'mceResize')) 
     249                                                return t._startDrag(id, e, n.className.substring(13)); 
     250                                } 
     251                        }); 
     252 
     253                        clf = Event.add(id, 'click', function(e) { 
     254                                var n = e.target; 
     255 
     256                                t.focus(id); 
     257 
     258                                if (n.nodeName == 'A' || n.nodeName == 'a') { 
     259                                        switch (n.className) { 
     260                                                case 'mceClose': 
     261                                                        t.close(null, id); 
     262                                                        return Event.cancel(e); 
     263 
     264                                                case 'mceButton mceOk': 
     265                                                case 'mceButton mceCancel': 
     266                                                        f.button_func(n.className == 'mceButton mceOk'); 
     267                                                        return Event.cancel(e); 
     268                                        } 
     269                                } 
     270                        }); 
     271                         
     272                        // Make sure the tab order loops within the dialog. 
     273                        Event.add([id + '_left', id + '_right'], 'focus', function(evt) { 
     274                                var iframe = DOM.get(id + '_ifr'); 
     275                                if (iframe) { 
     276                                        var body = iframe.contentWindow.document.body; 
     277                                        var focusable = DOM.select(':input:enabled,*[tabindex=0]', body); 
     278                                        if (evt.target.id === (id + '_left')) { 
     279                                                focusable[focusable.length - 1].focus(); 
     280                                        } else { 
     281                                                focusable[0].focus(); 
     282                                        } 
     283                                } else { 
     284                                        DOM.get(id + '_ok').focus(); 
     285                                } 
     286                        }); 
     287                         
     288                        // Add window 
     289                        w = t.windows[id] = { 
     290                                id : id, 
     291                                mousedown_func : mdf, 
     292                                click_func : clf, 
     293                                element : new Element(id, {blocker : 1, container : ed.getContainer()}), 
     294                                iframeElement : new Element(id + '_ifr'), 
     295                                features : f, 
     296                                deltaWidth : dw, 
     297                                deltaHeight : dh 
     298                        }; 
     299 
     300                        w.iframeElement.on('focus', function() { 
     301                                t.focus(id); 
     302                        }); 
     303 
     304                        // Setup blocker 
     305                        if (t.count == 0 && t.editor.getParam('dialog_type', 'modal') == 'modal') { 
     306                                DOM.add(DOM.doc.body, 'div', { 
     307                                        id : 'mceModalBlocker', 
     308                                        'class' : (t.editor.settings.inlinepopups_skin || 'clearlooks2') + '_modalBlocker', 
     309                                        style : {zIndex : t.zIndex - 1} 
     310                                }); 
     311 
     312                                DOM.show('mceModalBlocker'); // Reduces flicker in IE 
     313                                DOM.setAttrib(DOM.doc.body, 'aria-hidden', 'true'); 
     314                        } else 
     315                                DOM.setStyle('mceModalBlocker', 'z-index', t.zIndex - 1); 
     316 
     317                        if (tinymce.isIE6 || /Firefox\/2\./.test(navigator.userAgent) || (tinymce.isIE && !DOM.boxModel)) 
     318                                DOM.setStyles('mceModalBlocker', {position : 'absolute', left : vp.x, top : vp.y, width : vp.w - 2, height : vp.h - 2}); 
     319 
     320                        DOM.setAttrib(id, 'aria-hidden', 'false'); 
     321                        t.focus(id); 
     322                        t._fixIELayout(id, 1); 
     323 
     324                        // Focus ok button 
     325                        if (DOM.get(id + '_ok')) 
     326                                DOM.get(id + '_ok').focus(); 
     327                        t.count++; 
     328 
     329                        return w; 
     330                }, 
     331 
     332                focus : function(id) { 
     333                        var t = this, w; 
     334 
     335                        if (w = t.windows[id]) { 
     336                                w.zIndex = this.zIndex++; 
     337                                w.element.setStyle('zIndex', w.zIndex); 
     338                                w.element.update(); 
     339 
     340                                id = id + '_wrapper'; 
     341                                DOM.removeClass(t.lastId, 'mceFocus'); 
     342                                DOM.addClass(id, 'mceFocus'); 
     343                                t.lastId = id; 
     344                                 
     345                                if (w.focussedElement) { 
     346                                        w.focussedElement.focus(); 
     347                                } else if (DOM.get(id + '_ok')) { 
     348                                        DOM.get(w.id + '_ok').focus(); 
     349                                } else if (DOM.get(w.id + '_ifr')) { 
     350                                        DOM.get(w.id + '_ifr').focus(); 
     351                                } 
     352                        } 
     353                }, 
     354 
     355                _addAll : function(te, ne) { 
     356                        var i, n, t = this, dom = tinymce.DOM; 
     357 
     358                        if (is(ne, 'string')) 
     359                                te.appendChild(dom.doc.createTextNode(ne)); 
     360                        else if (ne.length) { 
     361                                te = te.appendChild(dom.create(ne[0], ne[1])); 
     362 
     363                                for (i=2; i<ne.length; i++) 
     364                                        t._addAll(te, ne[i]); 
     365                        } 
     366                }, 
     367 
     368                _startDrag : function(id, se, ac) { 
     369                        var t = this, mu, mm, d = DOM.doc, eb, w = t.windows[id], we = w.element, sp = we.getXY(), p, sz, ph, cp, vp, sx, sy, sex, sey, dx, dy, dw, dh; 
     370 
     371                        // Get positons and sizes 
     372//                      cp = DOM.getPos(t.editor.getContainer()); 
     373                        cp = {x : 0, y : 0}; 
     374                        vp = DOM.getViewPort(); 
     375 
     376                        // Reduce viewport size to avoid scrollbars while dragging 
     377                        vp.w -= 2; 
     378                        vp.h -= 2; 
     379 
     380                        sex = se.screenX; 
     381                        sey = se.screenY; 
     382                        dx = dy = dw = dh = 0; 
     383 
     384                        // Handle mouse up 
     385                        mu = Event.add(d, 'mouseup', function(e) { 
     386                                Event.remove(d, 'mouseup', mu); 
     387                                Event.remove(d, 'mousemove', mm); 
     388 
     389                                if (eb) 
     390                                        eb.remove(); 
     391 
     392                                we.moveBy(dx, dy); 
     393                                we.resizeBy(dw, dh); 
     394                                sz = we.getSize(); 
     395                                DOM.setStyles(id + '_ifr', {width : sz.w - w.deltaWidth, height : sz.h - w.deltaHeight}); 
     396                                t._fixIELayout(id, 1); 
     397 
     398                                return Event.cancel(e); 
     399                        }); 
     400 
     401                        if (ac != 'Move') 
     402                                startMove(); 
     403 
     404                        function startMove() { 
     405                                if (eb) 
     406                                        return; 
     407 
     408                                t._fixIELayout(id, 0); 
     409 
     410                                // Setup event blocker 
     411                                DOM.add(d.body, 'div', { 
     412                                        id : 'mceEventBlocker', 
     413                                        'class' : 'mceEventBlocker ' + (t.editor.settings.inlinepopups_skin || 'clearlooks2'), 
     414                                        style : {zIndex : t.zIndex + 1} 
     415                                }); 
     416 
     417                                if (tinymce.isIE6 || (tinymce.isIE && !DOM.boxModel)) 
     418                                        DOM.setStyles('mceEventBlocker', {position : 'absolute', left : vp.x, top : vp.y, width : vp.w - 2, height : vp.h - 2}); 
     419 
     420                                eb = new Element('mceEventBlocker'); 
     421                                eb.update(); 
     422 
     423                                // Setup placeholder 
     424                                p = we.getXY(); 
     425                                sz = we.getSize(); 
     426                                sx = cp.x + p.x - vp.x; 
     427                                sy = cp.y + p.y - vp.y; 
     428                                DOM.add(eb.get(), 'div', {id : 'mcePlaceHolder', 'class' : 'mcePlaceHolder', style : {left : sx, top : sy, width : sz.w, height : sz.h}}); 
     429                                ph = new Element('mcePlaceHolder'); 
     430                        }; 
     431 
     432                        // Handle mouse move/drag 
     433                        mm = Event.add(d, 'mousemove', function(e) { 
     434                                var x, y, v; 
     435 
     436                                startMove(); 
     437 
     438                                x = e.screenX - sex; 
     439                                y = e.screenY - sey; 
     440 
     441                                switch (ac) { 
     442                                        case 'ResizeW': 
     443                                                dx = x; 
     444                                                dw = 0 - x; 
     445                                                break; 
     446 
     447                                        case 'ResizeE': 
     448                                                dw = x; 
     449                                                break; 
     450 
     451                                        case 'ResizeN': 
     452                                        case 'ResizeNW': 
     453                                        case 'ResizeNE': 
     454                                                if (ac == "ResizeNW") { 
     455                                                        dx = x; 
     456                                                        dw = 0 - x; 
     457                                                } else if (ac == "ResizeNE") 
     458                                                        dw = x; 
     459 
     460                                                dy = y; 
     461                                                dh = 0 - y; 
     462                                                break; 
     463 
     464                                        case 'ResizeS': 
     465                                        case 'ResizeSW': 
     466                                        case 'ResizeSE': 
     467                                                if (ac == "ResizeSW") { 
     468                                                        dx = x; 
     469                                                        dw = 0 - x; 
     470                                                } else if (ac == "ResizeSE") 
     471                                                        dw = x; 
     472 
     473                                                dh = y; 
     474                                                break; 
     475 
     476                                        case 'mceMove': 
     477                                                dx = x; 
     478                                                dy = y; 
     479                                                break; 
     480                                } 
     481 
     482                                // Boundary check 
     483                                if (dw < (v = w.features.min_width - sz.w)) { 
     484                                        if (dx !== 0) 
     485                                                dx += dw - v; 
     486 
     487                                        dw = v; 
     488                                } 
     489         
     490                                if (dh < (v = w.features.min_height - sz.h)) { 
     491                                        if (dy !== 0) 
     492                                                dy += dh - v; 
     493 
     494                                        dh = v; 
     495                                } 
     496 
     497                                dw = Math.min(dw, w.features.max_width - sz.w); 
     498                                dh = Math.min(dh, w.features.max_height - sz.h); 
     499                                dx = Math.max(dx, vp.x - (sx + vp.x)); 
     500                                dy = Math.max(dy, vp.y - (sy + vp.y)); 
     501                                dx = Math.min(dx, (vp.w + vp.x) - (sx + sz.w + vp.x)); 
     502                                dy = Math.min(dy, (vp.h + vp.y) - (sy + sz.h + vp.y)); 
     503 
     504                                // Move if needed 
     505                                if (dx + dy !== 0) { 
     506                                        if (sx + dx < 0) 
     507                                                dx = 0; 
     508         
     509                                        if (sy + dy < 0) 
     510                                                dy = 0; 
     511 
     512                                        ph.moveTo(sx + dx, sy + dy); 
     513                                } 
     514 
     515                                // Resize if needed 
     516                                if (dw + dh !== 0) 
     517                                        ph.resizeTo(sz.w + dw, sz.h + dh); 
     518 
     519                                return Event.cancel(e); 
     520                        }); 
     521 
     522                        return Event.cancel(se); 
     523                }, 
     524 
     525                resizeBy : function(dw, dh, id) { 
     526                        var w = this.windows[id]; 
     527 
     528                        if (w) { 
     529                                w.element.resizeBy(dw, dh); 
     530                                w.iframeElement.resizeBy(dw, dh); 
     531                        } 
     532                }, 
     533 
     534                close : function(win, id) { 
     535                        var t = this, w, d = DOM.doc, fw, id; 
     536 
     537                        id = t._findId(id || win); 
     538 
     539                        // Probably not inline 
     540                        if (!t.windows[id]) { 
     541                                t.parent(win); 
     542                                return; 
     543                        } 
     544 
     545                        t.count--; 
     546 
     547                        if (t.count == 0) { 
     548                                DOM.remove('mceModalBlocker'); 
     549                                DOM.setAttrib(DOM.doc.body, 'aria-hidden', 'false'); 
     550                                t.editor.focus(); 
     551                        } 
     552 
     553                        if (w = t.windows[id]) { 
     554                                t.onClose.dispatch(t); 
     555                                Event.remove(d, 'mousedown', w.mousedownFunc); 
     556                                Event.remove(d, 'click', w.clickFunc); 
     557                                Event.clear(id); 
     558                                Event.clear(id + '_ifr'); 
     559 
     560                                DOM.setAttrib(id + '_ifr', 'src', 'javascript:""'); // Prevent leak 
     561                                w.element.remove(); 
     562                                delete t.windows[id]; 
     563 
     564                                fw = t._frontWindow(); 
     565 
     566                                if (fw) 
     567                                        t.focus(fw.id); 
     568                        } 
     569                }, 
     570                 
     571                // Find front most window 
     572                _frontWindow : function() { 
     573                        var fw, ix = 0; 
     574                        // Find front most window and focus that 
     575                        each (this.windows, function(w) { 
     576                                if (w.zIndex > ix) { 
     577                                        fw = w; 
     578                                        ix = w.zIndex; 
     579                                } 
     580                        }); 
     581                        return fw; 
     582                }, 
     583 
     584                setTitle : function(w, ti) { 
     585                        var e; 
     586 
     587                        w = this._findId(w); 
     588 
     589                        if (e = DOM.get(w + '_title')) 
     590                                e.innerHTML = DOM.encode(ti); 
     591                }, 
     592 
     593                alert : function(txt, cb, s) { 
     594                        var t = this, w; 
     595 
     596                        w = t.open({ 
     597                                title : t, 
     598                                type : 'alert', 
     599                                button_func : function(s) { 
     600                                        if (cb) 
     601                                                cb.call(s || t, s); 
     602 
     603                                        t.close(null, w.id); 
     604                                }, 
     605                                content : DOM.encode(t.editor.getLang(txt, txt)), 
     606                                inline : 1, 
     607                                width : 400, 
     608                                height : 130 
     609                        }); 
     610                }, 
     611 
     612                confirm : function(txt, cb, s) { 
     613                        var t = this, w; 
     614 
     615                        w = t.open({ 
     616                                title : t, 
     617                                type : 'confirm', 
     618                                button_func : function(s) { 
     619                                        if (cb) 
     620                                                cb.call(s || t, s); 
     621 
     622                                        t.close(null, w.id); 
     623                                }, 
     624                                content : DOM.encode(t.editor.getLang(txt, txt)), 
     625                                inline : 1, 
     626                                width : 400, 
     627                                height : 130 
     628                        }); 
     629                }, 
     630 
     631                // Internal functions 
     632 
     633                _findId : function(w) { 
     634                        var t = this; 
     635 
     636                        if (typeof(w) == 'string') 
     637                                return w; 
     638 
     639                        each(t.windows, function(wo) { 
     640                                var ifr = DOM.get(wo.id + '_ifr'); 
     641 
     642                                if (ifr && w == ifr.contentWindow) { 
     643                                        w = wo.id; 
     644                                        return false; 
     645                                } 
     646                        }); 
     647 
     648                        return w; 
     649                }, 
     650 
     651                _fixIELayout : function(id, s) { 
     652                        var w, img; 
     653 
     654                        if (!tinymce.isIE6) 
     655                                return; 
     656 
     657                        // Fixes the bug where hover flickers and does odd things in IE6 
     658                        each(['n','s','w','e','nw','ne','sw','se'], function(v) { 
     659                                var e = DOM.get(id + '_resize_' + v); 
     660 
     661                                DOM.setStyles(e, { 
     662                                        width : s ? e.clientWidth : '', 
     663                                        height : s ? e.clientHeight : '', 
     664                                        cursor : DOM.getStyle(e, 'cursor', 1) 
     665                                }); 
     666 
     667                                DOM.setStyle(id + "_bottom", 'bottom', '-1px'); 
     668 
     669                                e = 0; 
     670                        }); 
     671 
     672                        // Fixes graphics glitch 
     673                        if (w = this.windows[id]) { 
     674                                // Fixes rendering bug after resize 
     675                                w.element.hide(); 
     676                                w.element.show(); 
     677 
     678                                // Forced a repaint of the window 
     679                                //DOM.get(id).style.filter = ''; 
     680 
     681                                // IE has a bug where images used in CSS won't get loaded 
     682                                // sometimes when the cache in the browser is disabled 
     683                                // This fix tries to solve it by loading the images using the image object 
     684                                each(DOM.select('div,a', id), function(e, i) { 
     685                                        if (e.currentStyle.backgroundImage != 'none') { 
     686                                                img = new Image(); 
     687                                                img.src = e.currentStyle.backgroundImage.replace(/url\(\"(.+)\"\)/, '$1'); 
     688                                        } 
     689                                }); 
     690 
     691                                DOM.get(id).style.filter = ''; 
     692                        } 
     693                } 
     694        }); 
     695 
     696        // Register plugin 
     697        tinymce.PluginManager.add('inlinepopups', tinymce.plugins.InlinePopups); 
     698})(); 
     699 
  • wp-includes/js/tinymce/plugins/tabfocus/editor_plugin.dev.js

     
     1/** 
     2 * editor_plugin_src.js 
     3 * 
     4 * Copyright 2009, Moxiecode Systems AB 
     5 * Released under LGPL License. 
     6 * 
     7 * License: http://tinymce.moxiecode.com/license 
     8 * Contributing: http://tinymce.moxiecode.com/contributing 
     9 */ 
     10 
     11(function() { 
     12        var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, explode = tinymce.explode; 
     13 
     14        tinymce.create('tinymce.plugins.TabFocusPlugin', { 
     15                init : function(ed, url) { 
     16                        function tabCancel(ed, e) { 
     17                                if (e.keyCode === 9) 
     18                                        return Event.cancel(e); 
     19                        } 
     20 
     21                        function tabHandler(ed, e) { 
     22                                var x, i, f, el, v; 
     23 
     24                                function find(d) { 
     25                                        el = DOM.select(':input:enabled,*[tabindex]'); 
     26 
     27                                        function canSelectRecursive(e) { 
     28                                                return e.nodeName==="BODY" || (e.type != 'hidden' && 
     29                                                        !(e.style.display == "none") && 
     30                                                        !(e.style.visibility == "hidden") && canSelectRecursive(e.parentNode)); 
     31                                        } 
     32                                        function canSelectInOldIe(el) { 
     33                                                return el.attributes["tabIndex"].specified || el.nodeName == "INPUT" || el.nodeName == "TEXTAREA"; 
     34                                        } 
     35                                        function isOldIe() { 
     36                                                return tinymce.isIE6 || tinymce.isIE7; 
     37                                        } 
     38                                        function canSelect(el) { 
     39                                                return ((!isOldIe() || canSelectInOldIe(el))) && el.getAttribute("tabindex") != '-1' && canSelectRecursive(el); 
     40                                        } 
     41 
     42                                        each(el, function(e, i) { 
     43                                                if (e.id == ed.id) { 
     44                                                        x = i; 
     45                                                        return false; 
     46                                                } 
     47                                        }); 
     48                                        if (d > 0) { 
     49                                                for (i = x + 1; i < el.length; i++) { 
     50                                                        if (canSelect(el[i])) 
     51                                                                return el[i]; 
     52                                                } 
     53                                        } else { 
     54                                                for (i = x - 1; i >= 0; i--) { 
     55                                                        if (canSelect(el[i])) 
     56                                                                return el[i]; 
     57                                                } 
     58                                        } 
     59 
     60                                        return null; 
     61                                } 
     62 
     63                                if (e.keyCode === 9) { 
     64                                        v = explode(ed.getParam('tab_focus', ed.getParam('tabfocus_elements', ':prev,:next'))); 
     65 
     66                                        if (v.length == 1) { 
     67                                                v[1] = v[0]; 
     68                                                v[0] = ':prev'; 
     69                                        } 
     70 
     71                                        // Find element to focus 
     72                                        if (e.shiftKey) { 
     73                                                if (v[0] == ':prev') 
     74                                                        el = find(-1); 
     75                                                else 
     76                                                        el = DOM.get(v[0]); 
     77                                        } else { 
     78                                                if (v[1] == ':next') 
     79                                                        el = find(1); 
     80                                                else 
     81                                                        el = DOM.get(v[1]); 
     82                                        } 
     83 
     84                                        if (el) { 
     85                                                if (el.id && (ed = tinymce.get(el.id || el.name))) 
     86                                                        ed.focus(); 
     87                                                else 
     88                                                        window.setTimeout(function() { 
     89                                                                if (!tinymce.isWebKit) 
     90                                                                        window.focus(); 
     91                                                                el.focus(); 
     92                                                        }, 10); 
     93 
     94                                                return Event.cancel(e); 
     95                                        } 
     96                                } 
     97                        } 
     98 
     99                        ed.onKeyUp.add(tabCancel); 
     100 
     101                        if (tinymce.isGecko) { 
     102                                ed.onKeyPress.add(tabHandler); 
     103                                ed.onKeyDown.add(tabCancel); 
     104                        } else 
     105                                ed.onKeyDown.add(tabHandler); 
     106 
     107                }, 
     108 
     109                getInfo : function() { 
     110                        return { 
     111                                longname : 'Tabfocus', 
     112                                author : 'Moxiecode Systems AB', 
     113                                authorurl : 'http://tinymce.moxiecode.com', 
     114                                infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/tabfocus', 
     115                                version : tinymce.majorVersion + "." + tinymce.minorVersion 
     116                        }; 
     117                } 
     118        }); 
     119 
     120        // Register plugin 
     121        tinymce.PluginManager.add('tabfocus', tinymce.plugins.TabFocusPlugin); 
     122})(); 
  • wp-includes/js/tinymce/plugins/paste/editor_plugin.dev.js

     
     1/** 
     2 * editor_plugin_src.js 
     3 * 
     4 * Copyright 2009, Moxiecode Systems AB 
     5 * Released under LGPL License. 
     6 * 
     7 * License: http://tinymce.moxiecode.com/license 
     8 * Contributing: http://tinymce.moxiecode.com/contributing 
     9 */ 
     10 
     11(function() { 
     12        var each = tinymce.each, 
     13                defs = { 
     14                        paste_auto_cleanup_on_paste : true, 
     15                        paste_enable_default_filters : true, 
     16                        paste_block_drop : false, 
     17                        paste_retain_style_properties : "none", 
     18                        paste_strip_class_attributes : "mso", 
     19                        paste_remove_spans : false, 
     20                        paste_remove_styles : false, 
     21                        paste_remove_styles_if_webkit : true, 
     22                        paste_convert_middot_lists : true, 
     23                        paste_convert_headers_to_strong : false, 
     24                        paste_dialog_width : "450", 
     25                        paste_dialog_height : "400", 
     26                        paste_text_use_dialog : false, 
     27                        paste_text_sticky : false, 
     28                        paste_text_sticky_default : false, 
     29                        paste_text_notifyalways : false, 
     30                        paste_text_linebreaktype : "combined", 
     31                        paste_text_replacements : [ 
     32                                [/\u2026/g, "..."], 
     33                                [/[\x93\x94\u201c\u201d]/g, '"'], 
     34                                [/[\x60\x91\x92\u2018\u2019]/g, "'"] 
     35                        ] 
     36                }; 
     37 
     38        function getParam(ed, name) { 
     39                return ed.getParam(name, defs[name]); 
     40        } 
     41 
     42        tinymce.create('tinymce.plugins.PastePlugin', { 
     43                init : function(ed, url) { 
     44                        var t = this; 
     45 
     46                        t.editor = ed; 
     47                        t.url = url; 
     48 
     49                        // Setup plugin events 
     50                        t.onPreProcess = new tinymce.util.Dispatcher(t); 
     51                        t.onPostProcess = new tinymce.util.Dispatcher(t); 
     52 
     53                        // Register default handlers 
     54                        t.onPreProcess.add(t._preProcess); 
     55                        t.onPostProcess.add(t._postProcess); 
     56 
     57                        // Register optional preprocess handler 
     58                        t.onPreProcess.add(function(pl, o) { 
     59                                ed.execCallback('paste_preprocess', pl, o); 
     60                        }); 
     61 
     62                        // Register optional postprocess 
     63                        t.onPostProcess.add(function(pl, o) { 
     64                                ed.execCallback('paste_postprocess', pl, o); 
     65                        }); 
     66 
     67                        ed.onKeyDown.addToTop(function(ed, e) { 
     68                                // Block ctrl+v from adding an undo level since the default logic in tinymce.Editor will add that 
     69                                if (((tinymce.isMac ? e.metaKey : e.ctrlKey) && e.keyCode == 86) || (e.shiftKey && e.keyCode == 45)) 
     70                                        return false; // Stop other listeners 
     71                        }); 
     72 
     73                        // Initialize plain text flag 
     74                        ed.pasteAsPlainText = getParam(ed, 'paste_text_sticky_default'); 
     75 
     76                        // This function executes the process handlers and inserts the contents 
     77                        // force_rich overrides plain text mode set by user, important for pasting with execCommand 
     78                        function process(o, force_rich) { 
     79                                var dom = ed.dom, rng; 
     80 
     81                                // Execute pre process handlers 
     82                                t.onPreProcess.dispatch(t, o); 
     83 
     84                                // Create DOM structure 
     85                                o.node = dom.create('div', 0, o.content); 
     86 
     87                                // If pasting inside the same element and the contents is only one block 
     88                                // remove the block and keep the text since Firefox will copy parts of pre and h1-h6 as a pre element 
     89                                if (tinymce.isGecko) { 
     90                                        rng = ed.selection.getRng(true); 
     91                                        if (rng.startContainer == rng.endContainer && rng.startContainer.nodeType == 3) { 
     92                                                // Is only one block node and it doesn't contain word stuff 
     93                                                if (o.node.childNodes.length === 1 && /^(p|h[1-6]|pre)$/i.test(o.node.firstChild.nodeName) && o.content.indexOf('__MCE_ITEM__') === -1) 
     94                                                        dom.remove(o.node.firstChild, true); 
     95                                        } 
     96                                } 
     97 
     98                                // Execute post process handlers 
     99                                t.onPostProcess.dispatch(t, o); 
     100 
     101                                // Serialize content 
     102                                o.content = ed.serializer.serialize(o.node, {getInner : 1, forced_root_block : ''}); 
     103 
     104                                // Plain text option active? 
     105                                if ((!force_rich) && (ed.pasteAsPlainText)) { 
     106                                        t._insertPlainText(o.content); 
     107 
     108                                        if (!getParam(ed, "paste_text_sticky")) { 
     109                                                ed.pasteAsPlainText = false; 
     110                                                ed.controlManager.setActive("pastetext", false); 
     111                                        } 
     112                                } else { 
     113                                        t._insert(o.content); 
     114                                } 
     115                        } 
     116 
     117                        // Add command for external usage 
     118                        ed.addCommand('mceInsertClipboardContent', function(u, o) { 
     119                                process(o, true); 
     120                        }); 
     121 
     122                        if (!getParam(ed, "paste_text_use_dialog")) { 
     123                                ed.addCommand('mcePasteText', function(u, v) { 
     124                                        var cookie = tinymce.util.Cookie; 
     125 
     126                                        ed.pasteAsPlainText = !ed.pasteAsPlainText; 
     127                                        ed.controlManager.setActive('pastetext', ed.pasteAsPlainText); 
     128 
     129                                        if ((ed.pasteAsPlainText) && (!cookie.get("tinymcePasteText"))) { 
     130                                                if (getParam(ed, "paste_text_sticky")) { 
     131                                                        ed.windowManager.alert(ed.translate('paste.plaintext_mode_sticky')); 
     132                                                } else { 
     133                                                        ed.windowManager.alert(ed.translate('paste.plaintext_mode')); 
     134                                                } 
     135 
     136                                                if (!getParam(ed, "paste_text_notifyalways")) { 
     137                                                        cookie.set("tinymcePasteText", "1", new Date(new Date().getFullYear() + 1, 12, 31)) 
     138                                                } 
     139                                        } 
     140                                }); 
     141                        } 
     142 
     143                        ed.addButton('pastetext', {title: 'paste.paste_text_desc', cmd: 'mcePasteText'}); 
     144                        ed.addButton('selectall', {title: 'paste.selectall_desc', cmd: 'selectall'}); 
     145 
     146                        // This function grabs the contents from the clipboard by adding a 
     147                        // hidden div and placing the caret inside it and after the browser paste 
     148                        // is done it grabs that contents and processes that 
     149                        function grabContent(e) { 
     150                                var n, or, rng, oldRng, sel = ed.selection, dom = ed.dom, body = ed.getBody(), posY, textContent; 
     151 
     152                                // Check if browser supports direct plaintext access 
     153                                if (e.clipboardData || dom.doc.dataTransfer) { 
     154                                        textContent = (e.clipboardData || dom.doc.dataTransfer).getData('Text'); 
     155 
     156                                        if (ed.pasteAsPlainText) { 
     157                                                e.preventDefault(); 
     158                                                process({content : dom.encode(textContent).replace(/\r?\n/g, '<br />')}); 
     159                                                return; 
     160                                        } 
     161                                } 
     162 
     163                                if (dom.get('_mcePaste')) 
     164                                        return; 
     165 
     166                                // Create container to paste into 
     167                                n = dom.add(body, 'div', {id : '_mcePaste', 'class' : 'mcePaste', 'data-mce-bogus' : '1'}, '\uFEFF\uFEFF'); 
     168 
     169                                // If contentEditable mode we need to find out the position of the closest element 
     170                                if (body != ed.getDoc().body) 
     171                                        posY = dom.getPos(ed.selection.getStart(), body).y; 
     172                                else 
     173                                        posY = body.scrollTop + dom.getViewPort(ed.getWin()).y; 
     174 
     175                                // Styles needs to be applied after the element is added to the document since WebKit will otherwise remove all styles 
     176                                // If also needs to be in view on IE or the paste would fail 
     177                                dom.setStyles(n, { 
     178                                        position : 'absolute', 
     179                                        left : tinymce.isGecko ? -40 : 0, // Need to move it out of site on Gecko since it will othewise display a ghost resize rect for the div 
     180                                        top : posY - 25, 
     181                                        width : 1, 
     182                                        height : 1, 
     183                                        overflow : 'hidden' 
     184                                }); 
     185 
     186                                if (tinymce.isIE) { 
     187                                        // Store away the old range 
     188                                        oldRng = sel.getRng(); 
     189 
     190                                        // Select the container 
     191                                        rng = dom.doc.body.createTextRange(); 
     192                                        rng.moveToElementText(n); 
     193                                        rng.execCommand('Paste'); 
     194 
     195                                        // Remove container 
     196                                        dom.remove(n); 
     197 
     198                                        // Check if the contents was changed, if it wasn't then clipboard extraction failed probably due 
     199                                        // to IE security settings so we pass the junk though better than nothing right 
     200                                        if (n.innerHTML === '\uFEFF\uFEFF') { 
     201                                                ed.execCommand('mcePasteWord'); 
     202                                                e.preventDefault(); 
     203                                                return; 
     204                                        } 
     205 
     206                                        // Restore the old range and clear the contents before pasting 
     207                                        sel.setRng(oldRng); 
     208                                        sel.setContent(''); 
     209 
     210                                        // For some odd reason we need to detach the the mceInsertContent call from the paste event 
     211                                        // It's like IE has a reference to the parent element that you paste in and the selection gets messed up 
     212                                        // when it tries to restore the selection 
     213                                        setTimeout(function() { 
     214                                                // Process contents 
     215                                                process({content : n.innerHTML}); 
     216                                        }, 0); 
     217 
     218                                        // Block the real paste event 
     219                                        return tinymce.dom.Event.cancel(e); 
     220                                } else { 
     221                                        function block(e) { 
     222                                                e.preventDefault(); 
     223                                        }; 
     224 
     225                                        // Block mousedown and click to prevent selection change 
     226                                        dom.bind(ed.getDoc(), 'mousedown', block); 
     227                                        dom.bind(ed.getDoc(), 'keydown', block); 
     228 
     229                                        or = ed.selection.getRng(); 
     230 
     231                                        // Move select contents inside DIV 
     232                                        n = n.firstChild; 
     233                                        rng = ed.getDoc().createRange(); 
     234                                        rng.setStart(n, 0); 
     235                                        rng.setEnd(n, 2); 
     236                                        sel.setRng(rng); 
     237 
     238                                        // Wait a while and grab the pasted contents 
     239                                        window.setTimeout(function() { 
     240                                                var h = '', nl; 
     241 
     242                                                // Paste divs duplicated in paste divs seems to happen when you paste plain text so lets first look for that broken behavior in WebKit 
     243                                                if (!dom.select('div.mcePaste > div.mcePaste').length) { 
     244                                                        nl = dom.select('div.mcePaste'); 
     245 
     246                                                        // WebKit will split the div into multiple ones so this will loop through then all and join them to get the whole HTML string 
     247                                                        each(nl, function(n) { 
     248                                                                var child = n.firstChild; 
     249 
     250                                                                // WebKit inserts a DIV container with lots of odd styles 
     251                                                                if (child && child.nodeName == 'DIV' && child.style.marginTop && child.style.backgroundColor) { 
     252                                                                        dom.remove(child, 1); 
     253                                                                } 
     254 
     255                                                                // Remove apply style spans 
     256                                                                each(dom.select('span.Apple-style-span', n), function(n) { 
     257                                                                        dom.remove(n, 1); 
     258                                                                }); 
     259 
     260                                                                // Remove bogus br elements 
     261                                                                each(dom.select('br[data-mce-bogus]', n), function(n) { 
     262                                                                        dom.remove(n); 
     263                                                                }); 
     264 
     265                                                                // WebKit will make a copy of the DIV for each line of plain text pasted and insert them into the DIV 
     266                                                                if (n.parentNode.className != 'mcePaste') 
     267                                                                        h += n.innerHTML; 
     268                                                        }); 
     269                                                } else { 
     270                                                        // Found WebKit weirdness so force the content into paragraphs this seems to happen when you paste plain text from Nodepad etc 
     271                                                        // So this logic will replace double enter with paragraphs and single enter with br so it kind of looks the same 
     272                                                        h = '<p>' + dom.encode(textContent).replace(/\r?\n\r?\n/g, '</p><p>').replace(/\r?\n/g, '<br />') + '</p>'; 
     273                                                } 
     274 
     275                                                // Remove the nodes 
     276                                                each(dom.select('div.mcePaste'), function(n) { 
     277                                                        dom.remove(n); 
     278                                                }); 
     279 
     280                                                // Restore the old selection 
     281                                                if (or) 
     282                                                        sel.setRng(or); 
     283 
     284                                                process({content : h}); 
     285 
     286                                                // Unblock events ones we got the contents 
     287                                                dom.unbind(ed.getDoc(), 'mousedown', block); 
     288                                                dom.unbind(ed.getDoc(), 'keydown', block); 
     289                                        }, 0); 
     290                                } 
     291                        } 
     292 
     293                        // Check if we should use the new auto process method                    
     294                        if (getParam(ed, "paste_auto_cleanup_on_paste")) { 
     295                                // Is it's Opera or older FF use key handler 
     296                                if (tinymce.isOpera || /Firefox\/2/.test(navigator.userAgent)) { 
     297                                        ed.onKeyDown.addToTop(function(ed, e) { 
     298                                                if (((tinymce.isMac ? e.metaKey : e.ctrlKey) && e.keyCode == 86) || (e.shiftKey && e.keyCode == 45)) 
     299                                                        grabContent(e); 
     300                                        }); 
     301                                } else { 
     302                                        // Grab contents on paste event on Gecko and WebKit 
     303                                        ed.onPaste.addToTop(function(ed, e) { 
     304                                                return grabContent(e); 
     305                                        }); 
     306                                } 
     307                        } 
     308 
     309                        ed.onInit.add(function() { 
     310                                ed.controlManager.setActive("pastetext", ed.pasteAsPlainText); 
     311 
     312                                // Block all drag/drop events 
     313                                if (getParam(ed, "paste_block_drop")) { 
     314                                        ed.dom.bind(ed.getBody(), ['dragend', 'dragover', 'draggesture', 'dragdrop', 'drop', 'drag'], function(e) { 
     315                                                e.preventDefault(); 
     316                                                e.stopPropagation(); 
     317 
     318                                                return false; 
     319                                        }); 
     320                                } 
     321                        }); 
     322 
     323                        // Add legacy support 
     324                        t._legacySupport(); 
     325                }, 
     326 
     327                getInfo : function() { 
     328                        return { 
     329                                longname : 'Paste text/word', 
     330                                author : 'Moxiecode Systems AB', 
     331                                authorurl : 'http://tinymce.moxiecode.com', 
     332                                infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste', 
     333                                version : tinymce.majorVersion + "." + tinymce.minorVersion 
     334                        }; 
     335                }, 
     336 
     337                _preProcess : function(pl, o) { 
     338                        var ed = this.editor, 
     339                                h = o.content, 
     340                                grep = tinymce.grep, 
     341                                explode = tinymce.explode, 
     342                                trim = tinymce.trim, 
     343                                len, stripClass; 
     344 
     345                        //console.log('Before preprocess:' + o.content); 
     346 
     347                        function process(items) { 
     348                                each(items, function(v) { 
     349                                        // Remove or replace 
     350                                        if (v.constructor == RegExp) 
     351                                                h = h.replace(v, ''); 
     352                                        else 
     353                                                h = h.replace(v[0], v[1]); 
     354                                }); 
     355                        } 
     356                         
     357                        if (ed.settings.paste_enable_default_filters == false) { 
     358                                return; 
     359                        } 
     360 
     361                        // IE9 adds BRs before/after block elements when contents is pasted from word or for example another browser 
     362                        if (tinymce.isIE && document.documentMode >= 9) { 
     363                                // IE9 adds BRs before/after block elements when contents is pasted from word or for example another browser 
     364                                process([[/(?:<br>&nbsp;[\s\r\n]+|<br>)*(<\/?(h[1-6r]|p|div|address|pre|form|table|tbody|thead|tfoot|th|tr|td|li|ol|ul|caption|blockquote|center|dl|dt|dd|dir|fieldset)[^>]*>)(?:<br>&nbsp;[\s\r\n]+|<br>)*/g, '$1']]); 
     365 
     366                                // IE9 also adds an extra BR element for each soft-linefeed and it also adds a BR for each word wrap break 
     367                                process([ 
     368                                        [/<br><br>/g, '<BR><BR>'], // Replace multiple BR elements with uppercase BR to keep them intact 
     369                                        [/<br>/g, ' '], // Replace single br elements with space since they are word wrap BR:s 
     370                                        [/<BR><BR>/g, '<br>'] // Replace back the double brs but into a single BR 
     371                                ]); 
     372                        } 
     373 
     374                        // Detect Word content and process it more aggressive 
     375                        if (/class="?Mso|style="[^"]*\bmso-|w:WordDocument/i.test(h) || o.wordContent) { 
     376                                o.wordContent = true;                   // Mark the pasted contents as word specific content 
     377                                //console.log('Word contents detected.'); 
     378 
     379                                // Process away some basic content 
     380                                process([ 
     381                                        /^\s*(&nbsp;)+/gi,                              // &nbsp; entities at the start of contents 
     382                                        /(&nbsp;|<br[^>]*>)+\s*$/gi             // &nbsp; entities at the end of contents 
     383                                ]); 
     384 
     385                                if (getParam(ed, "paste_convert_headers_to_strong")) { 
     386                                        h = h.replace(/<p [^>]*class="?MsoHeading"?[^>]*>(.*?)<\/p>/gi, "<p><strong>$1</strong></p>"); 
     387                                } 
     388 
     389                                if (getParam(ed, "paste_convert_middot_lists")) { 
     390                                        process([ 
     391                                                [/<!--\[if !supportLists\]-->/gi, '$&__MCE_ITEM__'],                                    // Convert supportLists to a list item marker 
     392                                                [/(<span[^>]+(?:mso-list:|:\s*symbol)[^>]+>)/gi, '$1__MCE_ITEM__'],             // Convert mso-list and symbol spans to item markers 
     393                                                [/(<p[^>]+(?:MsoListParagraph)[^>]+>)/gi, '$1__MCE_ITEM__']                             // Convert mso-list and symbol paragraphs to item markers (FF) 
     394                                        ]); 
     395                                } 
     396 
     397                                process([ 
     398                                        // Word comments like conditional comments etc 
     399                                        /<!--[\s\S]+?-->/gi, 
     400 
     401                                        // Remove comments, scripts (e.g., msoShowComment), XML tag, VML content, MS Office namespaced tags, and a few other tags 
     402                                        /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi, 
     403 
     404                                        // Convert <s> into <strike> for line-though 
     405                                        [/<(\/?)s>/gi, "<$1strike>"], 
     406 
     407                                        // Replace nsbp entites to char since it's easier to handle 
     408                                        [/&nbsp;/gi, "\u00a0"] 
     409                                ]); 
     410 
     411                                // Remove bad attributes, with or without quotes, ensuring that attribute text is really inside a tag. 
     412                                // If JavaScript had a RegExp look-behind, we could have integrated this with the last process() array and got rid of the loop. But alas, it does not, so we cannot. 
     413                                do { 
     414                                        len = h.length; 
     415                                        h = h.replace(/(<[a-z][^>]*\s)(?:id|name|language|type|on\w+|\w+:\w+)=(?:"[^"]*"|\w+)\s?/gi, "$1"); 
     416                                } while (len != h.length); 
     417 
     418                                // Remove all spans if no styles is to be retained 
     419                                if (getParam(ed, "paste_retain_style_properties").replace(/^none$/i, "").length == 0) { 
     420                                        h = h.replace(/<\/?span[^>]*>/gi, ""); 
     421                                } else { 
     422                                        // We're keeping styles, so at least clean them up. 
     423                                        // CSS Reference: http://msdn.microsoft.com/en-us/library/aa155477.aspx 
     424 
     425                                        process([ 
     426                                                // Convert <span style="mso-spacerun:yes">___</span> to string of alternating breaking/non-breaking spaces of same length 
     427                                                [/<span\s+style\s*=\s*"\s*mso-spacerun\s*:\s*yes\s*;?\s*"\s*>([\s\u00a0]*)<\/span>/gi, 
     428                                                        function(str, spaces) { 
     429                                                                return (spaces.length > 0)? spaces.replace(/./, " ").slice(Math.floor(spaces.length/2)).split("").join("\u00a0") : ""; 
     430                                                        } 
     431                                                ], 
     432 
     433                                                // Examine all styles: delete junk, transform some, and keep the rest 
     434                                                [/(<[a-z][^>]*)\sstyle="([^"]*)"/gi, 
     435                                                        function(str, tag, style) { 
     436                                                                var n = [], 
     437                                                                        i = 0, 
     438                                                                        s = explode(trim(style).replace(/&quot;/gi, "'"), ";"); 
     439 
     440                                                                // Examine each style definition within the tag's style attribute 
     441                                                                each(s, function(v) { 
     442                                                                        var name, value, 
     443                                                                                parts = explode(v, ":"); 
     444 
     445                                                                        function ensureUnits(v) { 
     446                                                                                return v + ((v !== "0") && (/\d$/.test(v)))? "px" : ""; 
     447                                                                        } 
     448 
     449                                                                        if (parts.length == 2) { 
     450                                                                                name = parts[0].toLowerCase(); 
     451                                                                                value = parts[1].toLowerCase(); 
     452 
     453                                                                                // Translate certain MS Office styles into their CSS equivalents 
     454                                                                                switch (name) { 
     455                                                                                        case "mso-padding-alt": 
     456                                                                                        case "mso-padding-top-alt": 
     457                                                                                        case "mso-padding-right-alt": 
     458                                                                                        case "mso-padding-bottom-alt": 
     459                                                                                        case "mso-padding-left-alt": 
     460                                                                                        case "mso-margin-alt": 
     461                                                                                        case "mso-margin-top-alt": 
     462                                                                                        case "mso-margin-right-alt": 
     463                                                                                        case "mso-margin-bottom-alt": 
     464                                                                                        case "mso-margin-left-alt": 
     465                                                                                        case "mso-table-layout-alt": 
     466                                                                                        case "mso-height": 
     467                                                                                        case "mso-width": 
     468                                                                                        case "mso-vertical-align-alt": 
     469                                                                                                n[i++] = name.replace(/^mso-|-alt$/g, "") + ":" + ensureUnits(value); 
     470                                                                                                return; 
     471 
     472                                                                                        case "horiz-align": 
     473                                                                                                n[i++] = "text-align:" + value; 
     474                                                                                                return; 
     475 
     476                                                                                        case "vert-align": 
     477                                                                                                n[i++] = "vertical-align:" + value; 
     478                                                                                                return; 
     479 
     480                                                                                        case "font-color": 
     481                                                                                        case "mso-foreground": 
     482                                                                                                n[i++] = "color:" + value; 
     483                                                                                                return; 
     484 
     485                                                                                        case "mso-background": 
     486                                                                                        case "mso-highlight": 
     487                                                                                                n[i++] = "background:" + value; 
     488                                                                                                return; 
     489 
     490                                                                                        case "mso-default-height": 
     491                                                                                                n[i++] = "min-height:" + ensureUnits(value); 
     492                                                                                                return; 
     493 
     494                                                                                        case "mso-default-width": 
     495                                                                                                n[i++] = "min-width:" + ensureUnits(value); 
     496                                                                                                return; 
     497 
     498                                                                                        case "mso-padding-between-alt": 
     499                                                                                                n[i++] = "border-collapse:separate;border-spacing:" + ensureUnits(value); 
     500                                                                                                return; 
     501 
     502                                                                                        case "text-line-through": 
     503                                                                                                if ((value == "single") || (value == "double")) { 
     504                                                                                                        n[i++] = "text-decoration:line-through"; 
     505                                                                                                } 
     506                                                                                                return; 
     507 
     508                                                                                        case "mso-zero-height": 
     509                                                                                                if (value == "yes") { 
     510                                                                                                        n[i++] = "display:none"; 
     511                                                                                                } 
     512                                                                                                return; 
     513                                                                                } 
     514 
     515                                                                                // Eliminate all MS Office style definitions that have no CSS equivalent by examining the first characters in the name 
     516                                                                                if (/^(mso|column|font-emph|lang|layout|line-break|list-image|nav|panose|punct|row|ruby|sep|size|src|tab-|table-border|text-(?!align|decor|indent|trans)|top-bar|version|vnd|word-break)/.test(name)) { 
     517                                                                                        return; 
     518                                                                                } 
     519 
     520                                                                                // If it reached this point, it must be a valid CSS style 
     521                                                                                n[i++] = name + ":" + parts[1];         // Lower-case name, but keep value case 
     522                                                                        } 
     523                                                                }); 
     524 
     525                                                                // If style attribute contained any valid styles the re-write it; otherwise delete style attribute. 
     526                                                                if (i > 0) { 
     527                                                                        return tag + ' style="' + n.join(';') + '"'; 
     528                                                                } else { 
     529                                                                        return tag; 
     530                                                                } 
     531                                                        } 
     532                                                ] 
     533                                        ]); 
     534                                } 
     535                        } 
     536 
     537                        // Replace headers with <strong> 
     538                        if (getParam(ed, "paste_convert_headers_to_strong")) { 
     539                                process([ 
     540                                        [/<h[1-6][^>]*>/gi, "<p><strong>"], 
     541                                        [/<\/h[1-6][^>]*>/gi, "</strong></p>"] 
     542                                ]); 
     543                        } 
     544 
     545                        process([ 
     546                                // Copy paste from Java like Open Office will produce this junk on FF 
     547                                [/Version:[\d.]+\nStartHTML:\d+\nEndHTML:\d+\nStartFragment:\d+\nEndFragment:\d+/gi, ''] 
     548                        ]); 
     549 
     550                        // Class attribute options are: leave all as-is ("none"), remove all ("all"), or remove only those starting with mso ("mso"). 
     551                        // Note:-  paste_strip_class_attributes: "none", verify_css_classes: true is also a good variation. 
     552                        stripClass = getParam(ed, "paste_strip_class_attributes"); 
     553 
     554                        if (stripClass !== "none") { 
     555                                function removeClasses(match, g1) { 
     556                                                if (stripClass === "all") 
     557                                                        return ''; 
     558 
     559                                                var cls = grep(explode(g1.replace(/^(["'])(.*)\1$/, "$2"), " "), 
     560                                                        function(v) { 
     561                                                                return (/^(?!mso)/i.test(v)); 
     562                                                        } 
     563                                                ); 
     564 
     565                                                return cls.length ? ' class="' + cls.join(" ") + '"' : ''; 
     566                                }; 
     567 
     568                                h = h.replace(/ class="([^"]+)"/gi, removeClasses); 
     569                                h = h.replace(/ class=([\-\w]+)/gi, removeClasses); 
     570                        } 
     571 
     572                        // Remove spans option 
     573                        if (getParam(ed, "paste_remove_spans")) { 
     574                                h = h.replace(/<\/?span[^>]*>/gi, ""); 
     575                        } 
     576 
     577                        //console.log('After preprocess:' + h); 
     578 
     579                        o.content = h; 
     580                }, 
     581 
     582                /** 
     583                 * Various post process items. 
     584                 */ 
     585                _postProcess : function(pl, o) { 
     586                        var t = this, ed = t.editor, dom = ed.dom, styleProps; 
     587 
     588                        if (ed.settings.paste_enable_default_filters == false) { 
     589                                return; 
     590                        } 
     591                         
     592                        if (o.wordContent) { 
     593                                // Remove named anchors or TOC links 
     594                                each(dom.select('a', o.node), function(a) { 
     595                                        if (!a.href || a.href.indexOf('#_Toc') != -1) 
     596                                                dom.remove(a, 1); 
     597                                }); 
     598 
     599                                if (getParam(ed, "paste_convert_middot_lists")) { 
     600                                        t._convertLists(pl, o); 
     601                                } 
     602 
     603                                // Process styles 
     604                                styleProps = getParam(ed, "paste_retain_style_properties"); // retained properties 
     605 
     606                                // Process only if a string was specified and not equal to "all" or "*" 
     607                                if ((tinymce.is(styleProps, "string")) && (styleProps !== "all") && (styleProps !== "*")) { 
     608                                        styleProps = tinymce.explode(styleProps.replace(/^none$/i, "")); 
     609 
     610                                        // Retains some style properties 
     611                                        each(dom.select('*', o.node), function(el) { 
     612                                                var newStyle = {}, npc = 0, i, sp, sv; 
     613 
     614                                                // Store a subset of the existing styles 
     615                                                if (styleProps) { 
     616                                                        for (i = 0; i < styleProps.length; i++) { 
     617                                                                sp = styleProps[i]; 
     618                                                                sv = dom.getStyle(el, sp); 
     619 
     620                                                                if (sv) { 
     621                                                                        newStyle[sp] = sv; 
     622                                                                        npc++; 
     623                                                                } 
     624                                                        } 
     625                                                } 
     626 
     627                                                // Remove all of the existing styles 
     628                                                dom.setAttrib(el, 'style', ''); 
     629 
     630                                                if (styleProps && npc > 0) 
     631                                                        dom.setStyles(el, newStyle); // Add back the stored subset of styles 
     632                                                else // Remove empty span tags that do not have class attributes 
     633                                                        if (el.nodeName == 'SPAN' && !el.className) 
     634                                                                dom.remove(el, true); 
     635                                        }); 
     636                                } 
     637                        } 
     638 
     639                        // Remove all style information or only specifically on WebKit to avoid the style bug on that browser 
     640                        if (getParam(ed, "paste_remove_styles") || (getParam(ed, "paste_remove_styles_if_webkit") && tinymce.isWebKit)) { 
     641                                each(dom.select('*[style]', o.node), function(el) { 
     642                                        el.removeAttribute('style'); 
     643                                        el.removeAttribute('data-mce-style'); 
     644                                }); 
     645                        } else { 
     646                                if (tinymce.isWebKit) { 
     647                                        // We need to compress the styles on WebKit since if you paste <img border="0" /> it will become <img border="0" style="... lots of junk ..." /> 
     648                                        // Removing the mce_style that contains the real value will force the Serializer engine to compress the styles 
     649                                        each(dom.select('*', o.node), function(el) { 
     650                                                el.removeAttribute('data-mce-style'); 
     651                                        }); 
     652                                } 
     653                        } 
     654                }, 
     655 
     656                /** 
     657                 * Converts the most common bullet and number formats in Office into a real semantic UL/LI list. 
     658                 */ 
     659                _convertLists : function(pl, o) { 
     660                        var dom = pl.editor.dom, listElm, li, lastMargin = -1, margin, levels = [], lastType, html; 
     661 
     662                        // Convert middot lists into real semantic lists 
     663                        each(dom.select('p', o.node), function(p) { 
     664                                var sib, val = '', type, html, idx, parents; 
     665 
     666                                // Get text node value at beginning of paragraph 
     667                                for (sib = p.firstChild; sib && sib.nodeType == 3; sib = sib.nextSibling) 
     668                                        val += sib.nodeValue; 
     669 
     670                                val = p.innerHTML.replace(/<\/?\w+[^>]*>/gi, '').replace(/&nbsp;/g, '\u00a0'); 
     671 
     672                                // Detect unordered lists look for bullets 
     673                                if (/^(__MCE_ITEM__)+[\u2022\u00b7\u00a7\u00d8o\u25CF]\s*\u00a0*/.test(val)) 
     674                                        type = 'ul'; 
     675 
     676                                // Detect ordered lists 1., a. or ixv. 
     677                                if (/^__MCE_ITEM__\s*\w+\.\s*\u00a0+/.test(val)) 
     678                                        type = 'ol'; 
     679 
     680                                // Check if node value matches the list pattern: o&nbsp;&nbsp; 
     681                                if (type) { 
     682                                        margin = parseFloat(p.style.marginLeft || 0); 
     683 
     684                                        if (margin > lastMargin) 
     685                                                levels.push(margin); 
     686 
     687                                        if (!listElm || type != lastType) { 
     688                                                listElm = dom.create(type); 
     689                                                dom.insertAfter(listElm, p); 
     690                                        } else { 
     691                                                // Nested list element 
     692                                                if (margin > lastMargin) { 
     693                                                        listElm = li.appendChild(dom.create(type)); 
     694                                                } else if (margin < lastMargin) { 
     695                                                        // Find parent level based on margin value 
     696                                                        idx = tinymce.inArray(levels, margin); 
     697                                                        parents = dom.getParents(listElm.parentNode, type); 
     698                                                        listElm = parents[parents.length - 1 - idx] || listElm; 
     699                                                } 
     700                                        } 
     701 
     702                                        // Remove middot or number spans if they exists 
     703                                        each(dom.select('span', p), function(span) { 
     704                                                var html = span.innerHTML.replace(/<\/?\w+[^>]*>/gi, ''); 
     705 
     706                                                // Remove span with the middot or the number 
     707                                                if (type == 'ul' && /^__MCE_ITEM__[\u2022\u00b7\u00a7\u00d8o\u25CF]/.test(html)) 
     708                                                        dom.remove(span); 
     709                                                else if (/^__MCE_ITEM__[\s\S]*\w+\.(&nbsp;|\u00a0)*\s*/.test(html)) 
     710                                                        dom.remove(span); 
     711                                        }); 
     712 
     713                                        html = p.innerHTML; 
     714 
     715                                        // Remove middot/list items 
     716                                        if (type == 'ul') 
     717                                                html = p.innerHTML.replace(/__MCE_ITEM__/g, '').replace(/^[\u2022\u00b7\u00a7\u00d8o\u25CF]\s*(&nbsp;|\u00a0)+\s*/, ''); 
     718                                        else 
     719                                                html = p.innerHTML.replace(/__MCE_ITEM__/g, '').replace(/^\s*\w+\.(&nbsp;|\u00a0)+\s*/, ''); 
     720 
     721                                        // Create li and add paragraph data into the new li 
     722                                        li = listElm.appendChild(dom.create('li', 0, html)); 
     723                                        dom.remove(p); 
     724 
     725                                        lastMargin = margin; 
     726                                        lastType = type; 
     727                                } else 
     728                                        listElm = lastMargin = 0; // End list element 
     729                        }); 
     730 
     731                        // Remove any left over makers 
     732                        html = o.node.innerHTML; 
     733                        if (html.indexOf('__MCE_ITEM__') != -1) 
     734                                o.node.innerHTML = html.replace(/__MCE_ITEM__/g, ''); 
     735                }, 
     736 
     737                /** 
     738                 * Inserts the specified contents at the caret position. 
     739                 */ 
     740                _insert : function(h, skip_undo) { 
     741                        var ed = this.editor, r = ed.selection.getRng(); 
     742 
     743                        // First delete the contents seems to work better on WebKit when the selection spans multiple list items or multiple table cells. 
     744                        if (!ed.selection.isCollapsed() && r.startContainer != r.endContainer) 
     745                                ed.getDoc().execCommand('Delete', false, null); 
     746 
     747                        ed.execCommand('mceInsertContent', false, h, {skip_undo : skip_undo}); 
     748                }, 
     749 
     750                /** 
     751                 * Instead of the old plain text method which tried to re-create a paste operation, the 
     752                 * new approach adds a plain text mode toggle switch that changes the behavior of paste. 
     753                 * This function is passed the same input that the regular paste plugin produces. 
     754                 * It performs additional scrubbing and produces (and inserts) the plain text. 
     755                 * This approach leverages all of the great existing functionality in the paste 
     756                 * plugin, and requires minimal changes to add the new functionality. 
     757                 * Speednet - June 2009 
     758                 */ 
     759                _insertPlainText : function(content) { 
     760                        var ed = this.editor, 
     761                                linebr = getParam(ed, "paste_text_linebreaktype"), 
     762                                rl = getParam(ed, "paste_text_replacements"), 
     763                                is = tinymce.is; 
     764 
     765                        function process(items) { 
     766                                each(items, function(v) { 
     767                                        if (v.constructor == RegExp) 
     768                                                content = content.replace(v, ""); 
     769                                        else 
     770                                                content = content.replace(v[0], v[1]); 
     771                                }); 
     772                        }; 
     773 
     774                        if ((typeof(content) === "string") && (content.length > 0)) { 
     775                                // If HTML content with line-breaking tags, then remove all cr/lf chars because only tags will break a line 
     776                                if (/<(?:p|br|h[1-6]|ul|ol|dl|table|t[rdh]|div|blockquote|fieldset|pre|address|center)[^>]*>/i.test(content)) { 
     777                                        process([ 
     778                                                /[\n\r]+/g 
     779                                        ]); 
     780                                } else { 
     781                                        // Otherwise just get rid of carriage returns (only need linefeeds) 
     782                                        process([ 
     783                                                /\r+/g 
     784                                        ]); 
     785                                } 
     786 
     787                                process([ 
     788                                        [/<\/(?:p|h[1-6]|ul|ol|dl|table|div|blockquote|fieldset|pre|address|center)>/gi, "\n\n"],               // Block tags get a blank line after them 
     789                                        [/<br[^>]*>|<\/tr>/gi, "\n"],                           // Single linebreak for <br /> tags and table rows 
     790                                        [/<\/t[dh]>\s*<t[dh][^>]*>/gi, "\t"],           // Table cells get tabs betweem them 
     791                                        /<[a-z!\/?][^>]*>/gi,                                           // Delete all remaining tags 
     792                                        [/&nbsp;/gi, " "],                                                      // Convert non-break spaces to regular spaces (remember, *plain text*) 
     793                                        [/(?:(?!\n)\s)*(\n+)(?:(?!\n)\s)*/gi, "$1"],// Cool little RegExp deletes whitespace around linebreak chars. 
     794                                        [/\n{3,}/g, "\n\n"]                                                     // Max. 2 consecutive linebreaks 
     795                                ]); 
     796 
     797                                content = ed.dom.decode(tinymce.html.Entities.encodeRaw(content)); 
     798 
     799                                // Perform default or custom replacements 
     800                                if (is(rl, "array")) { 
     801                                        process(rl); 
     802                                } else if (is(rl, "string")) { 
     803                                        process(new RegExp(rl, "gi")); 
     804                                } 
     805 
     806                                // Treat paragraphs as specified in the config 
     807                                if (linebr == "none") { 
     808                                        // Convert all line breaks to space 
     809                                        process([ 
     810                                                [/\n+/g, " "] 
     811                                        ]); 
     812                                } else if (linebr == "br") { 
     813                                        // Convert all line breaks to <br /> 
     814                                        process([ 
     815                                                [/\n/g, "<br />"] 
     816                                        ]); 
     817                                } else if (linebr == "p") { 
     818                                        // Convert all line breaks to <p>...</p> 
     819                                        process([ 
     820                                                [/\n+/g, "</p><p>"], 
     821                                                [/^(.*<\/p>)(<p>)$/, '<p>$1'] 
     822                                        ]); 
     823                                } else { 
     824                                        // defaults to "combined" 
     825                                        // Convert single line breaks to <br /> and double line breaks to <p>...</p> 
     826                                        process([ 
     827                                                [/\n\n/g, "</p><p>"], 
     828                                                [/^(.*<\/p>)(<p>)$/, '<p>$1'], 
     829                                                [/\n/g, "<br />"] 
     830                                        ]); 
     831                                } 
     832 
     833                                ed.execCommand('mceInsertContent', false, content); 
     834                        } 
     835                }, 
     836 
     837                /** 
     838                 * This method will open the old style paste dialogs. Some users might want the old behavior but still use the new cleanup engine. 
     839                 */ 
     840                _legacySupport : function() { 
     841                        var t = this, ed = t.editor; 
     842 
     843                        // Register command(s) for backwards compatibility 
     844                        ed.addCommand("mcePasteWord", function() { 
     845                                ed.windowManager.open({ 
     846                                        file: t.url + "/pasteword.htm", 
     847                                        width: parseInt(getParam(ed, "paste_dialog_width")), 
     848                                        height: parseInt(getParam(ed, "paste_dialog_height")), 
     849                                        inline: 1 
     850                                }); 
     851                        }); 
     852 
     853                        if (getParam(ed, "paste_text_use_dialog")) { 
     854                                ed.addCommand("mcePasteText", function() { 
     855                                        ed.windowManager.open({ 
     856                                                file : t.url + "/pastetext.htm", 
     857                                                width: parseInt(getParam(ed, "paste_dialog_width")), 
     858                                                height: parseInt(getParam(ed, "paste_dialog_height")), 
     859                                                inline : 1 
     860                                        }); 
     861                                }); 
     862                        } 
     863 
     864                        // Register button for backwards compatibility 
     865                        ed.addButton("pasteword", {title : "paste.paste_word_desc", cmd : "mcePasteWord"}); 
     866                } 
     867        }); 
     868 
     869        // Register plugin 
     870        tinymce.PluginManager.add("paste", tinymce.plugins.PastePlugin); 
     871})(); 
  • wp-includes/js/tinymce/themes/advanced/editor_template.dev.js

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