Mercurial > hg > AnnotationManager
comparison WebContent/jscripts/tiny_mce/plugins/media/editor_plugin_src.js @ 5:0be9d53a6967
editor for annotations
| author | dwinter |
|---|---|
| date | Tue, 13 Dec 2011 17:43:46 +0100 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 4:c32080f364c6 | 5:0be9d53a6967 |
|---|---|
| 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 })(); |
