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