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 | })(); |
---|