WordPress.org

Make WordPress Core

Ticket #20055: 20055.1.diff

File 20055.1.diff, 154.0 KB (added by ericlewis, 8 years ago)

As per Nacin's suggestion, remove script_concat_settings(), move logic for compressions and concatenations to the function calls. Still has respect to the globals in case any plugin sets them. Just saw azaozz's comment, this will need to be ammended to use MCE debug mode.

  • 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                                                        if (v = DOM.getAttrib(n, 'color'))
     1149                                                                ti += 'color: ' + v + ' ';
     1150
     1151                                                        break;
     1152
     1153                                                case 'span':
     1154                                                        if (v = DOM.getAttrib(n, 'style'))
     1155                                                                ti += 'style: ' + v + ' ';
     1156
     1157                                                        break;
     1158                                        }
     1159
     1160                                        if (v = DOM.getAttrib(n, 'id'))
     1161                                                ti += 'id: ' + v + ' ';
     1162
     1163                                        if (v = n.className) {
     1164                                                v = v.replace(/\b\s*(webkit|mce|Apple-)\w+\s*\b/g, '')
     1165
     1166                                                if (v) {