Mercurial > public > sg101
comparison static/js/tiny_mce/plugins/media/editor_plugin_src.js @ 442:6c182ceb7147
Fixing #217; upgrade TinyMCE to 3.4.2 and enable the paste plugin.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Thu, 26 May 2011 00:43:49 +0000 |
parents | 88b2b9cb8c1f |
children |
comparison
equal
deleted
inserted
replaced
441:33d0c55e57a9 | 442:6c182ceb7147 |
---|---|
7 * License: http://tinymce.moxiecode.com/license | 7 * License: http://tinymce.moxiecode.com/license |
8 * Contributing: http://tinymce.moxiecode.com/contributing | 8 * Contributing: http://tinymce.moxiecode.com/contributing |
9 */ | 9 */ |
10 | 10 |
11 (function() { | 11 (function() { |
12 var each = tinymce.each; | 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 }; | |
13 | 47 |
14 tinymce.create('tinymce.plugins.MediaPlugin', { | 48 tinymce.create('tinymce.plugins.MediaPlugin', { |
15 init : function(ed, url) { | 49 init : function(ed, url) { |
16 var t = this; | 50 var self = this, lookup = {}, i, y, item, name; |
17 | 51 |
18 t.editor = ed; | 52 function isMediaImg(node) { |
19 t.url = url; | 53 return node && node.nodeName === 'IMG' && ed.dom.hasClass(node, 'mceItemMedia'); |
20 | |
21 function isMediaElm(n) { | |
22 return /^(mceItemFlash|mceItemShockWave|mceItemWindowsMedia|mceItemQuickTime|mceItemRealMedia)$/.test(n.className); | |
23 }; | 54 }; |
24 | 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 | |
25 ed.onPreInit.add(function() { | 110 ed.onPreInit.add(function() { |
26 // Force in _value parameter this extra parameter is required for older Opera versions | 111 // Allow video elements |
27 ed.serializer.addRules('param[name|value|_mce_value]'); | 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 } | |
28 }); | 150 }); |
29 | 151 |
30 // Register commands | 152 // Register commands |
31 ed.addCommand('mceMedia', function() { | 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 | |
32 ed.windowManager.open({ | 179 ed.windowManager.open({ |
33 file : url + '/media.htm', | 180 file : url + '/media.htm', |
34 width : 430 + parseInt(ed.getLang('media.delta_width', 0)), | 181 width : 430 + parseInt(ed.getLang('media.delta_width', 0)), |
35 height : 470 + parseInt(ed.getLang('media.delta_height', 0)), | 182 height : 500 + parseInt(ed.getLang('media.delta_height', 0)), |
36 inline : 1 | 183 inline : 1 |
37 }, { | 184 }, { |
38 plugin_url : url | 185 plugin_url : url, |
186 data : data | |
39 }); | 187 }); |
40 }); | 188 }); |
41 | 189 |
42 // Register buttons | 190 // Register buttons |
43 ed.addButton('media', {title : 'media.desc', cmd : 'mceMedia'}); | 191 ed.addButton('media', {title : 'media.desc', cmd : 'mceMedia'}); |
44 | 192 |
45 ed.onNodeChange.add(function(ed, cm, n) { | 193 // Update media selection status |
46 cm.setActive('media', n.nodeName == 'IMG' && isMediaElm(n)); | 194 ed.onNodeChange.add(function(ed, cm, node) { |
195 cm.setActive('media', isMediaImg(node)); | |
47 }); | 196 }); |
48 | 197 }, |
49 ed.onInit.add(function() { | 198 |
50 var lo = { | 199 convertUrl : function(url, force_absolute) { |
51 mceItemFlash : 'flash', | 200 var self = this, editor = self.editor, settings = editor.settings, |
52 mceItemShockWave : 'shockwave', | 201 urlConverter = settings.url_converter, |
53 mceItemWindowsMedia : 'windowsmedia', | 202 urlConverterScope = settings.url_converter_scope || self; |
54 mceItemQuickTime : 'quicktime', | 203 |
55 mceItemRealMedia : 'realmedia' | 204 if (!url) |
56 }; | 205 return url; |
57 | 206 |
58 ed.selection.onSetContent.add(function() { | 207 if (force_absolute) |
59 t._spansToImgs(ed.getBody()); | 208 return editor.documentBaseURI.toAbsolute(url); |
60 }); | 209 |
61 | 210 return urlConverter.call(urlConverterScope, url, 'src', 'object'); |
62 ed.selection.onBeforeSetContent.add(t._objectsToSpans, t); | |
63 | |
64 if (ed.settings.content_css !== false) | |
65 ed.dom.loadCSS(url + "/css/content.css"); | |
66 | |
67 if (ed.theme && ed.theme.onResolveName) { | |
68 ed.theme.onResolveName.add(function(th, o) { | |
69 if (o.name == 'img') { | |
70 each(lo, function(v, k) { | |
71 if (ed.dom.hasClass(o.node, k)) { | |
72 o.name = v; | |
73 o.title = ed.dom.getAttrib(o.node, 'title'); | |
74 return false; | |
75 } | |
76 }); | |
77 } | |
78 }); | |
79 } | |
80 | |
81 if (ed && ed.plugins.contextmenu) { | |
82 ed.plugins.contextmenu.onContextMenu.add(function(th, m, e) { | |
83 if (e.nodeName == 'IMG' && /mceItem(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)/.test(e.className)) { | |
84 m.add({title : 'media.edit', icon : 'media', cmd : 'mceMedia'}); | |
85 } | |
86 }); | |
87 } | |
88 }); | |
89 | |
90 ed.onBeforeSetContent.add(t._objectsToSpans, t); | |
91 | |
92 ed.onSetContent.add(function() { | |
93 t._spansToImgs(ed.getBody()); | |
94 }); | |
95 | |
96 ed.onPreProcess.add(function(ed, o) { | |
97 var dom = ed.dom; | |
98 | |
99 if (o.set) { | |
100 t._spansToImgs(o.node); | |
101 | |
102 each(dom.select('IMG', o.node), function(n) { | |
103 var p; | |
104 | |
105 if (isMediaElm(n)) { | |
106 p = t._parse(n.title); | |
107 dom.setAttrib(n, 'width', dom.getAttrib(n, 'width', p.width || 100)); | |
108 dom.setAttrib(n, 'height', dom.getAttrib(n, 'height', p.height || 100)); | |
109 } | |
110 }); | |
111 } | |
112 | |
113 if (o.get) { | |
114 each(dom.select('IMG', o.node), function(n) { | |
115 var ci, cb, mt; | |
116 | |
117 if (ed.getParam('media_use_script')) { | |
118 if (isMediaElm(n)) | |
119 n.className = n.className.replace(/mceItem/g, 'mceTemp'); | |
120 | |
121 return; | |
122 } | |
123 | |
124 switch (n.className) { | |
125 case 'mceItemFlash': | |
126 ci = 'd27cdb6e-ae6d-11cf-96b8-444553540000'; | |
127 cb = 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0'; | |
128 mt = 'application/x-shockwave-flash'; | |
129 break; | |
130 | |
131 case 'mceItemShockWave': | |
132 ci = '166b1bca-3f9c-11cf-8075-444553540000'; | |
133 cb = 'http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0'; | |
134 mt = 'application/x-director'; | |
135 break; | |
136 | |
137 case 'mceItemWindowsMedia': | |
138 ci = ed.getParam('media_wmp6_compatible') ? '05589fa1-c356-11ce-bf01-00aa0055595a' : '6bf52a52-394a-11d3-b153-00c04f79faa6'; | |
139 cb = 'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701'; | |
140 mt = 'application/x-mplayer2'; | |
141 break; | |
142 | |
143 case 'mceItemQuickTime': | |
144 ci = '02bf25d5-8c17-4b23-bc80-d3488abddc6b'; | |
145 cb = 'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0'; | |
146 mt = 'video/quicktime'; | |
147 break; | |
148 | |
149 case 'mceItemRealMedia': | |
150 ci = 'cfcdaa03-8be4-11cf-b84b-0020afbbccfa'; | |
151 cb = 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0'; | |
152 mt = 'audio/x-pn-realaudio-plugin'; | |
153 break; | |
154 } | |
155 | |
156 if (ci) { | |
157 dom.replace(t._buildObj({ | |
158 classid : ci, | |
159 codebase : cb, | |
160 type : mt | |
161 }, n), n); | |
162 } | |
163 }); | |
164 } | |
165 }); | |
166 | |
167 ed.onPostProcess.add(function(ed, o) { | |
168 o.content = o.content.replace(/_mce_value=/g, 'value='); | |
169 }); | |
170 | |
171 function getAttr(s, n) { | |
172 n = new RegExp(n + '=\"([^\"]+)\"', 'g').exec(s); | |
173 | |
174 return n ? ed.dom.decode(n[1]) : ''; | |
175 }; | |
176 | |
177 ed.onPostProcess.add(function(ed, o) { | |
178 if (ed.getParam('media_use_script')) { | |
179 o.content = o.content.replace(/<img[^>]+>/g, function(im) { | |
180 var cl = getAttr(im, 'class'); | |
181 | |
182 if (/^(mceTempFlash|mceTempShockWave|mceTempWindowsMedia|mceTempQuickTime|mceTempRealMedia)$/.test(cl)) { | |
183 at = t._parse(getAttr(im, 'title')); | |
184 at.width = getAttr(im, 'width'); | |
185 at.height = getAttr(im, 'height'); | |
186 im = '<script type="text/javascript">write' + cl.substring(7) + '({' + t._serialize(at) + '});</script>'; | |
187 } | |
188 | |
189 return im; | |
190 }); | |
191 } | |
192 }); | |
193 }, | 211 }, |
194 | 212 |
195 getInfo : function() { | 213 getInfo : function() { |
196 return { | 214 return { |
197 longname : 'Media', | 215 longname : 'Media', |
200 infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/media', | 218 infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/media', |
201 version : tinymce.majorVersion + "." + tinymce.minorVersion | 219 version : tinymce.majorVersion + "." + tinymce.minorVersion |
202 }; | 220 }; |
203 }, | 221 }, |
204 | 222 |
205 // Private methods | 223 /** |
206 _objectsToSpans : function(ed, o) { | 224 * Converts the JSON data object to an img node. |
207 var t = this, h = o.content; | 225 */ |
208 | 226 dataToImg : function(data, force_absolute) { |
209 h = h.replace(/<script[^>]*>\s*write(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)\(\{([^\)]*)\}\);\s*<\/script>/gi, function(a, b, c) { | 227 var self = this, editor = self.editor, baseUri = editor.documentBaseURI, sources, attrs, img, i; |
210 var o = t._parse(c); | 228 |
211 | 229 data.params.src = self.convertUrl(data.params.src, force_absolute); |
212 return '<img class="mceItem' + b + '" title="' + ed.dom.encode(c) + '" src="' + t.url + '/img/trans.gif" width="' + o.width + '" height="' + o.height + '" />' | 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, "'") | |
213 }); | 251 }); |
214 | 252 |
215 h = h.replace(/<object([^>]*)>/gi, '<span class="mceItemObject" $1>'); | 253 img.width = data.width || "320"; |
216 h = h.replace(/<embed([^>]*)\/?>/gi, '<span class="mceItemEmbed" $1></span>'); | 254 img.height = data.height || "240"; |
217 h = h.replace(/<embed([^>]*)>/gi, '<span class="mceItemEmbed" $1>'); | 255 |
218 h = h.replace(/<\/(object)([^>]*)>/gi, '</span>'); | 256 return img; |
219 h = h.replace(/<\/embed>/gi, ''); | |
220 h = h.replace(/<param([^>]*)>/gi, function(a, b) {return '<span ' + b.replace(/value=/gi, '_mce_value=') + ' class="mceItemParam"></span>'}); | |
221 h = h.replace(/\/ class=\"mceItemParam\"><\/span>/gi, 'class="mceItemParam"></span>'); | |
222 | |
223 o.content = h; | |
224 }, | 257 }, |
225 | 258 |
226 _buildObj : function(o, n) { | 259 /** |
227 var ob, ed = this.editor, dom = ed.dom, p = this._parse(n.title), stc; | 260 * Converts the JSON data object to a HTML string. |
228 | 261 */ |
229 stc = ed.getParam('media_strict', true) && o.type == 'application/x-shockwave-flash'; | 262 dataToHtml : function(data, force_absolute) { |
230 | 263 return this.editor.serializer.serialize(this.dataToImg(data, force_absolute), {force_absolute : force_absolute}); |
231 p.width = o.width = dom.getAttrib(n, 'width') || 100; | 264 }, |
232 p.height = o.height = dom.getAttrib(n, 'height') || 100; | 265 |
233 | 266 /** |
234 if (p.src) | 267 * Converts the JSON data object to a HTML string. |
235 p.src = ed.convertURL(p.src, 'src', n); | 268 */ |
236 | 269 htmlToData : function(html) { |
237 if (stc) { | 270 var fragment, img, data; |
238 ob = dom.create('span', { | 271 |
239 id : p.id, | 272 data = { |
240 _mce_name : 'object', | 273 type : 'flash', |
241 type : 'application/x-shockwave-flash', | 274 video: {sources:[]}, |
242 data : p.src, | 275 params: {} |
243 style : dom.getAttrib(n, 'style'), | 276 }; |
244 width : o.width, | 277 |
245 height : o.height | 278 fragment = this.editor.parser.parse(html); |
246 }); | 279 img = fragment.getAll('img')[0]; |
247 } else { | 280 |
248 ob = dom.create('span', { | 281 if (img) { |
249 id : p.id, | 282 data = JSON.parse(img.attr('data-mce-json')); |
250 _mce_name : 'object', | 283 data.type = this.getType(img.attr('class')).name.toLowerCase(); |
251 classid : "clsid:" + o.classid, | 284 |
252 style : dom.getAttrib(n, 'style'), | 285 // Add some extra properties to the data object |
253 codebase : o.codebase, | 286 tinymce.each(rootAttributes, function(name) { |
254 width : o.width, | 287 var value = img.attr(name); |
255 height : o.height | 288 |
256 }); | 289 if (value) |
257 } | 290 data[name] = value; |
258 | 291 }); |
259 each (p, function(v, k) { | 292 } |
260 if (!/^(width|height|codebase|classid|id|_cx|_cy)$/.test(k)) { | 293 |
261 // Use url instead of src in IE for Windows media | 294 return data; |
262 if (o.type == 'application/x-mplayer2' && k == 'src' && !p.url) | 295 }, |
263 k = 'url'; | 296 |
264 | 297 /** |
265 if (v) | 298 * Get type item by extension, class, clsid or mime type. |
266 dom.add(ob, 'span', {_mce_name : 'param', name : k, '_mce_value' : v}); | 299 * |
267 } | 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' | |
268 }); | 607 }); |
269 | 608 |
270 if (!stc) | 609 // Video element |
271 dom.add(ob, 'span', tinymce.extend({_mce_name : 'embed', type : o.type, style : dom.getAttrib(n, 'style')}, p)); | 610 name = node.name; |
272 | 611 if (name === 'video') { |
273 return ob; | 612 video = node; |
274 }, | 613 object = node.getAll('object')[0]; |
275 | 614 embed = node.getAll('embed')[0]; |
276 _spansToImgs : function(p) { | 615 width = video.attr('width'); |
277 var t = this, dom = t.editor.dom, im, ci; | 616 height = video.attr('height'); |
278 | 617 id = video.attr('id'); |
279 each(dom.select('span', p), function(n) { | 618 data.video = {attrs : {}, sources : []}; |
280 // Convert object into image | 619 |
281 if (dom.getAttrib(n, 'class') == 'mceItemObject') { | 620 // Get all video attributes |
282 ci = dom.getAttrib(n, "classid").toLowerCase().replace(/\s+/g, ''); | 621 attrs = data.video.attrs; |
283 | 622 for (name in video.attributes.map) |
284 switch (ci) { | 623 attrs[name] = video.attributes.map[name]; |
285 case 'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000': | 624 |
286 dom.replace(t._createImg('mceItemFlash', n), n); | 625 source = node.attr('src'); |
287 break; | 626 if (source) |
288 | 627 data.video.sources.push({src : urlConverter.call(urlConverterScope, source, 'src', 'video')}); |
289 case 'clsid:166b1bca-3f9c-11cf-8075-444553540000': | 628 |
290 dom.replace(t._createImg('mceItemShockWave', n), n); | 629 // Get all sources |
291 break; | 630 sources = video.getAll("source"); |
292 | 631 for (i = 0; i < sources.length; i++) { |
293 case 'clsid:6bf52a52-394a-11d3-b153-00c04f79faa6': | 632 source = sources[i].remove(); |
294 case 'clsid:22d6f312-b0f6-11d0-94ab-0080c74c7e95': | 633 |
295 case 'clsid:05589fa1-c356-11ce-bf01-00aa0055595a': | 634 data.video.sources.push({ |
296 dom.replace(t._createImg('mceItemWindowsMedia', n), n); | 635 src: urlConverter.call(urlConverterScope, source.attr('src'), 'src', 'source'), |
297 break; | 636 type: source.attr('type'), |
298 | 637 media: source.attr('media') |
299 case 'clsid:02bf25d5-8c17-4b23-bc80-d3488abddc6b': | 638 }); |
300 dom.replace(t._createImg('mceItemQuickTime', n), n); | 639 } |
301 break; | 640 |
302 | 641 // Convert the poster URL |
303 case 'clsid:cfcdaa03-8be4-11cf-b84b-0020afbbccfa': | 642 if (attrs.poster) |
304 dom.replace(t._createImg('mceItemRealMedia', n), n); | 643 attrs.poster = urlConverter.call(urlConverterScope, attrs.poster, 'poster', 'video'); |
305 break; | 644 } |
306 | 645 |
307 default: | 646 // Object element |
308 dom.replace(t._createImg('mceItemFlash', n), n); | 647 if (node.name === 'object') { |
309 } | 648 object = node; |
310 | 649 embed = node.getAll('embed')[0]; |
311 return; | 650 } |
312 } | 651 |
313 | 652 // Embed element |
314 // Convert embed into image | 653 if (node.name === 'embed') |
315 if (dom.getAttrib(n, 'class') == 'mceItemEmbed') { | 654 embed = node; |
316 switch (dom.getAttrib(n, 'type')) { | 655 |
317 case 'application/x-shockwave-flash': | 656 // Iframe element |
318 dom.replace(t._createImg('mceItemFlash', n), n); | 657 if (node.name === 'iframe') { |
319 break; | 658 iframe = node; |
320 | 659 type = 'Iframe'; |
321 case 'application/x-director': | 660 } |
322 dom.replace(t._createImg('mceItemShockWave', n), n); | 661 |
323 break; | 662 if (object) { |
324 | 663 // Get width/height |
325 case 'application/x-mplayer2': | 664 width = width || object.attr('width'); |
326 dom.replace(t._createImg('mceItemWindowsMedia', n), n); | 665 height = height || object.attr('height'); |
327 break; | 666 style = style || object.attr('style'); |
328 | 667 id = id || object.attr('id'); |
329 case 'video/quicktime': | 668 |
330 dom.replace(t._createImg('mceItemQuickTime', n), n); | 669 // Get all object params |
331 break; | 670 params = object.getAll("param"); |
332 | 671 for (i = 0; i < params.length; i++) { |
333 case 'audio/x-pn-realaudio-plugin': | 672 param = params[i]; |
334 dom.replace(t._createImg('mceItemRealMedia', n), n); | 673 name = param.remove().attr('name'); |
335 break; | 674 |
336 | 675 if (!excludedAttrs[name]) |
337 default: | 676 data.params[name] = param.attr('value'); |
338 dom.replace(t._createImg('mceItemFlash', n), n); | 677 } |
339 } | 678 |
340 } | 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, "'") | |
341 }); | 764 }); |
342 }, | |
343 | |
344 _createImg : function(cl, n) { | |
345 var im, dom = this.editor.dom, pa = {}, ti = '', args; | |
346 | |
347 args = ['id', 'name', 'width', 'height', 'bgcolor', 'align', 'flashvars', 'src', 'wmode', 'allowfullscreen', 'quality', 'data']; | |
348 | |
349 // Create image | |
350 im = dom.create('img', { | |
351 src : this.url + '/img/trans.gif', | |
352 width : dom.getAttrib(n, 'width') || 100, | |
353 height : dom.getAttrib(n, 'height') || 100, | |
354 style : dom.getAttrib(n, 'style'), | |
355 'class' : cl | |
356 }); | |
357 | |
358 // Setup base parameters | |
359 each(args, function(na) { | |
360 var v = dom.getAttrib(n, na); | |
361 | |
362 if (v) | |
363 pa[na] = v; | |
364 }); | |
365 | |
366 // Add optional parameters | |
367 each(dom.select('span', n), function(n) { | |
368 if (dom.hasClass(n, 'mceItemParam')) | |
369 pa[dom.getAttrib(n, 'name')] = dom.getAttrib(n, '_mce_value'); | |
370 }); | |
371 | |
372 // Use src not movie | |
373 if (pa.movie) { | |
374 pa.src = pa.movie; | |
375 delete pa.movie; | |
376 } | |
377 | |
378 // No src try data | |
379 if (!pa.src) { | |
380 pa.src = pa.data; | |
381 delete pa.data; | |
382 } | |
383 | |
384 // Merge with embed args | |
385 n = dom.select('.mceItemEmbed', n)[0]; | |
386 if (n) { | |
387 each(args, function(na) { | |
388 var v = dom.getAttrib(n, na); | |
389 | |
390 if (v && !pa[na]) | |
391 pa[na] = v; | |
392 }); | |
393 } | |
394 | |
395 delete pa.width; | |
396 delete pa.height; | |
397 | |
398 im.title = this._serialize(pa); | |
399 | |
400 return im; | |
401 }, | |
402 | |
403 _parse : function(s) { | |
404 return tinymce.util.JSON.parse('{' + s + '}'); | |
405 }, | |
406 | |
407 _serialize : function(o) { | |
408 return tinymce.util.JSON.serialize(o).replace(/[{}]/g, ''); | |
409 } | 765 } |
410 }); | 766 }); |
411 | 767 |
412 // Register plugin | 768 // Register plugin |
413 tinymce.PluginManager.add('media', tinymce.plugins.MediaPlugin); | 769 tinymce.PluginManager.add('media', tinymce.plugins.MediaPlugin); |