annotate static/js/tiny_mce/plugins/media/editor_plugin_src.js @ 645:99f7917702ca

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