5a920362 |
1 | var tinymce = {\r |
2 | majorVersion : '3',\r |
3 | minorVersion : '2.7',\r |
4 | releaseDate : '2009-09-22',\r |
5 | \r |
6 | _init : function() {\r |
7 | var t = this, d = document, w = window, na = navigator, ua = na.userAgent, i, nl, n, base, p, v;\r |
8 | \r |
9 | t.isOpera = w.opera && opera.buildNumber;\r |
10 | \r |
11 | t.isWebKit = /WebKit/.test(ua);\r |
12 | \r |
13 | t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(na.appName);\r |
14 | \r |
15 | t.isIE6 = t.isIE && /MSIE [56]/.test(ua);\r |
16 | \r |
17 | t.isGecko = !t.isWebKit && /Gecko/.test(ua);\r |
18 | \r |
19 | t.isMac = ua.indexOf('Mac') != -1;\r |
20 | \r |
21 | t.isAir = /adobeair/i.test(ua);\r |
22 | \r |
23 | // TinyMCE .NET webcontrol might be setting the values for TinyMCE\r |
24 | if (w.tinyMCEPreInit) {\r |
25 | t.suffix = tinyMCEPreInit.suffix;\r |
26 | t.baseURL = tinyMCEPreInit.base;\r |
27 | t.query = tinyMCEPreInit.query;\r |
28 | return;\r |
29 | }\r |
30 | \r |
31 | // Get suffix and base\r |
32 | t.suffix = '';\r |
33 | \r |
34 | // If base element found, add that infront of baseURL\r |
35 | nl = d.getElementsByTagName('base');\r |
36 | for (i=0; i<nl.length; i++) {\r |
37 | if (v = nl[i].href) {\r |
38 | // Host only value like http://site.com or http://site.com:8008\r |
39 | if (/^https?:\/\/[^\/]+$/.test(v))\r |
40 | v += '/';\r |
41 | \r |
42 | base = v ? v.match(/.*\//)[0] : ''; // Get only directory\r |
43 | }\r |
44 | }\r |
45 | \r |
46 | function getBase(n) {\r |
47 | if (n.src && /tiny_mce(|_gzip|_jquery|_prototype)(_dev|_src)?.js/.test(n.src)) {\r |
48 | if (/_(src|dev)\.js/g.test(n.src))\r |
49 | t.suffix = '_src';\r |
50 | \r |
51 | if ((p = n.src.indexOf('?')) != -1)\r |
52 | t.query = n.src.substring(p + 1);\r |
53 | \r |
54 | t.baseURL = n.src.substring(0, n.src.lastIndexOf('/'));\r |
55 | \r |
56 | // If path to script is relative and a base href was found add that one infront\r |
57 | // the src property will always be an absolute one on non IE browsers and IE 8\r |
58 | // so this logic will basically only be executed on older IE versions\r |
59 | if (base && t.baseURL.indexOf('://') == -1 && t.baseURL.indexOf('/') !== 0)\r |
60 | t.baseURL = base + t.baseURL;\r |
61 | \r |
62 | return t.baseURL;\r |
63 | }\r |
64 | \r |
65 | return null;\r |
66 | };\r |
67 | \r |
68 | // Check document\r |
69 | nl = d.getElementsByTagName('script');\r |
70 | for (i=0; i<nl.length; i++) {\r |
71 | if (getBase(nl[i]))\r |
72 | return;\r |
73 | }\r |
74 | \r |
75 | // Check head\r |
76 | n = d.getElementsByTagName('head')[0];\r |
77 | if (n) {\r |
78 | nl = n.getElementsByTagName('script');\r |
79 | for (i=0; i<nl.length; i++) {\r |
80 | if (getBase(nl[i]))\r |
81 | return;\r |
82 | }\r |
83 | }\r |
84 | \r |
85 | return;\r |
86 | },\r |
87 | \r |
88 | is : function(o, t) {\r |
89 | var n = typeof(o);\r |
90 | \r |
91 | if (!t)\r |
92 | return n != 'undefined';\r |
93 | \r |
94 | if (t == 'array' && (o.hasOwnProperty && o instanceof Array))\r |
95 | return true;\r |
96 | \r |
97 | return n == t;\r |
98 | },\r |
99 | \r |
100 | each : function(o, cb, s) {\r |
101 | var n, l;\r |
102 | \r |
103 | if (!o)\r |
104 | return 0;\r |
105 | \r |
106 | s = s || o;\r |
107 | \r |
108 | if (typeof(o.length) != 'undefined') {\r |
109 | // Indexed arrays, needed for Safari\r |
110 | for (n=0, l = o.length; n<l; n++) {\r |
111 | if (cb.call(s, o[n], n, o) === false)\r |
112 | return 0;\r |
113 | }\r |
114 | } else {\r |
115 | // Hashtables\r |
116 | for (n in o) {\r |
117 | if (o.hasOwnProperty(n)) {\r |
118 | if (cb.call(s, o[n], n, o) === false)\r |
119 | return 0;\r |
120 | }\r |
121 | }\r |
122 | }\r |
123 | \r |
124 | return 1;\r |
125 | },\r |
126 | \r |
127 | map : function(a, f) {\r |
128 | var o = [];\r |
129 | \r |
130 | tinymce.each(a, function(v) {\r |
131 | o.push(f(v));\r |
132 | });\r |
133 | \r |
134 | return o;\r |
135 | },\r |
136 | \r |
137 | grep : function(a, f) {\r |
138 | var o = [];\r |
139 | \r |
140 | tinymce.each(a, function(v) {\r |
141 | if (!f || f(v))\r |
142 | o.push(v);\r |
143 | });\r |
144 | \r |
145 | return o;\r |
146 | },\r |
147 | \r |
148 | inArray : function(a, v) {\r |
149 | var i, l;\r |
150 | \r |
151 | if (a) {\r |
152 | for (i = 0, l = a.length; i < l; i++) {\r |
153 | if (a[i] === v)\r |
154 | return i;\r |
155 | }\r |
156 | }\r |
157 | \r |
158 | return -1;\r |
159 | },\r |
160 | \r |
161 | extend : function(o, e) {\r |
162 | var i, a = arguments;\r |
163 | \r |
164 | for (i=1; i<a.length; i++) {\r |
165 | e = a[i];\r |
166 | \r |
167 | tinymce.each(e, function(v, n) {\r |
168 | if (typeof(v) !== 'undefined')\r |
169 | o[n] = v;\r |
170 | });\r |
171 | }\r |
172 | \r |
173 | return o;\r |
174 | },\r |
175 | \r |
176 | trim : function(s) {\r |
177 | return (s ? '' + s : '').replace(/^\s*|\s*$/g, '');\r |
178 | },\r |
179 | \r |
180 | create : function(s, p) {\r |
181 | var t = this, sp, ns, cn, scn, c, de = 0;\r |
182 | \r |
183 | // Parse : <prefix> <class>:<super class>\r |
184 | s = /^((static) )?([\w.]+)(:([\w.]+))?/.exec(s);\r |
185 | cn = s[3].match(/(^|\.)(\w+)$/i)[2]; // Class name\r |
186 | \r |
187 | // Create namespace for new class\r |
188 | ns = t.createNS(s[3].replace(/\.\w+$/, ''));\r |
189 | \r |
190 | // Class already exists\r |
191 | if (ns[cn])\r |
192 | return;\r |
193 | \r |
194 | // Make pure static class\r |
195 | if (s[2] == 'static') {\r |
196 | ns[cn] = p;\r |
197 | \r |
198 | if (this.onCreate)\r |
199 | this.onCreate(s[2], s[3], ns[cn]);\r |
200 | \r |
201 | return;\r |
202 | }\r |
203 | \r |
204 | // Create default constructor\r |
205 | if (!p[cn]) {\r |
206 | p[cn] = function() {};\r |
207 | de = 1;\r |
208 | }\r |
209 | \r |
210 | // Add constructor and methods\r |
211 | ns[cn] = p[cn];\r |
212 | t.extend(ns[cn].prototype, p);\r |
213 | \r |
214 | // Extend\r |
215 | if (s[5]) {\r |
216 | sp = t.resolve(s[5]).prototype;\r |
217 | scn = s[5].match(/\.(\w+)$/i)[1]; // Class name\r |
218 | \r |
219 | // Extend constructor\r |
220 | c = ns[cn];\r |
221 | if (de) {\r |
222 | // Add passthrough constructor\r |
223 | ns[cn] = function() {\r |
224 | return sp[scn].apply(this, arguments);\r |
225 | };\r |
226 | } else {\r |
227 | // Add inherit constructor\r |
228 | ns[cn] = function() {\r |
229 | this.parent = sp[scn];\r |
230 | return c.apply(this, arguments);\r |
231 | };\r |
232 | }\r |
233 | ns[cn].prototype[cn] = ns[cn];\r |
234 | \r |
235 | // Add super methods\r |
236 | t.each(sp, function(f, n) {\r |
237 | ns[cn].prototype[n] = sp[n];\r |
238 | });\r |
239 | \r |
240 | // Add overridden methods\r |
241 | t.each(p, function(f, n) {\r |
242 | // Extend methods if needed\r |
243 | if (sp[n]) {\r |
244 | ns[cn].prototype[n] = function() {\r |
245 | this.parent = sp[n];\r |
246 | return f.apply(this, arguments);\r |
247 | };\r |
248 | } else {\r |
249 | if (n != cn)\r |
250 | ns[cn].prototype[n] = f;\r |
251 | }\r |
252 | });\r |
253 | }\r |
254 | \r |
255 | // Add static methods\r |
256 | t.each(p['static'], function(f, n) {\r |
257 | ns[cn][n] = f;\r |
258 | });\r |
259 | \r |
260 | if (this.onCreate)\r |
261 | this.onCreate(s[2], s[3], ns[cn].prototype);\r |
262 | },\r |
263 | \r |
264 | walk : function(o, f, n, s) {\r |
265 | s = s || this;\r |
266 | \r |
267 | if (o) {\r |
268 | if (n)\r |
269 | o = o[n];\r |
270 | \r |
271 | tinymce.each(o, function(o, i) {\r |
272 | if (f.call(s, o, i, n) === false)\r |
273 | return false;\r |
274 | \r |
275 | tinymce.walk(o, f, n, s);\r |
276 | });\r |
277 | }\r |
278 | },\r |
279 | \r |
280 | createNS : function(n, o) {\r |
281 | var i, v;\r |
282 | \r |
283 | o = o || window;\r |
284 | \r |
285 | n = n.split('.');\r |
286 | for (i=0; i<n.length; i++) {\r |
287 | v = n[i];\r |
288 | \r |
289 | if (!o[v])\r |
290 | o[v] = {};\r |
291 | \r |
292 | o = o[v];\r |
293 | }\r |
294 | \r |
295 | return o;\r |
296 | },\r |
297 | \r |
298 | resolve : function(n, o) {\r |
299 | var i, l;\r |
300 | \r |
301 | o = o || window;\r |
302 | \r |
303 | n = n.split('.');\r |
304 | for (i = 0, l = n.length; i < l; i++) {\r |
305 | o = o[n[i]];\r |
306 | \r |
307 | if (!o)\r |
308 | break;\r |
309 | }\r |
310 | \r |
311 | return o;\r |
312 | },\r |
313 | \r |
314 | addUnload : function(f, s) {\r |
315 | var t = this, w = window;\r |
316 | \r |
317 | f = {func : f, scope : s || this};\r |
318 | \r |
319 | if (!t.unloads) {\r |
320 | function unload() {\r |
321 | var li = t.unloads, o, n;\r |
322 | \r |
323 | if (li) {\r |
324 | // Call unload handlers\r |
325 | for (n in li) {\r |
326 | o = li[n];\r |
327 | \r |
328 | if (o && o.func)\r |
329 | o.func.call(o.scope, 1); // Send in one arg to distinct unload and user destroy\r |
330 | }\r |
331 | \r |
332 | // Detach unload function\r |
333 | if (w.detachEvent) {\r |
334 | w.detachEvent('onbeforeunload', fakeUnload);\r |
335 | w.detachEvent('onunload', unload);\r |
336 | } else if (w.removeEventListener)\r |
337 | w.removeEventListener('unload', unload, false);\r |
338 | \r |
339 | // Destroy references\r |
340 | t.unloads = o = li = w = unload = 0;\r |
341 | \r |
342 | // Run garbarge collector on IE\r |
343 | if (window.CollectGarbage)\r |
344 | window.CollectGarbage();\r |
345 | }\r |
346 | };\r |
347 | \r |
348 | function fakeUnload() {\r |
349 | var d = document;\r |
350 | \r |
351 | // Is there things still loading, then do some magic\r |
352 | if (d.readyState == 'interactive') {\r |
353 | function stop() {\r |
354 | // Prevent memory leak\r |
355 | d.detachEvent('onstop', stop);\r |
356 | \r |
357 | // Call unload handler\r |
358 | if (unload)\r |
359 | unload();\r |
360 | \r |
361 | d = 0;\r |
362 | };\r |
363 | \r |
364 | // Fire unload when the currently loading page is stopped\r |
365 | if (d)\r |
366 | d.attachEvent('onstop', stop);\r |
367 | \r |
368 | // Remove onstop listener after a while to prevent the unload function\r |
369 | // to execute if the user presses cancel in an onbeforeunload\r |
370 | // confirm dialog and then presses the browser stop button\r |
371 | window.setTimeout(function() {\r |
372 | if (d)\r |
373 | d.detachEvent('onstop', stop);\r |
374 | }, 0);\r |
375 | }\r |
376 | };\r |
377 | \r |
378 | // Attach unload handler\r |
379 | if (w.attachEvent) {\r |
380 | w.attachEvent('onunload', unload);\r |
381 | w.attachEvent('onbeforeunload', fakeUnload);\r |
382 | } else if (w.addEventListener)\r |
383 | w.addEventListener('unload', unload, false);\r |
384 | \r |
385 | // Setup initial unload handler array\r |
386 | t.unloads = [f];\r |
387 | } else\r |
388 | t.unloads.push(f);\r |
389 | \r |
390 | return f;\r |
391 | },\r |
392 | \r |
393 | removeUnload : function(f) {\r |
394 | var u = this.unloads, r = null;\r |
395 | \r |
396 | tinymce.each(u, function(o, i) {\r |
397 | if (o && o.func == f) {\r |
398 | u.splice(i, 1);\r |
399 | r = f;\r |
400 | return false;\r |
401 | }\r |
402 | });\r |
403 | \r |
404 | return r;\r |
405 | },\r |
406 | \r |
407 | explode : function(s, d) {\r |
408 | return s ? tinymce.map(s.split(d || ','), tinymce.trim) : s;\r |
409 | },\r |
410 | \r |
411 | _addVer : function(u) {\r |
412 | var v;\r |
413 | \r |
414 | if (!this.query)\r |
415 | return u;\r |
416 | \r |
417 | v = (u.indexOf('?') == -1 ? '?' : '&') + this.query;\r |
418 | \r |
419 | if (u.indexOf('#') == -1)\r |
420 | return u + v;\r |
421 | \r |
422 | return u.replace('#', v + '#');\r |
423 | }\r |
424 | \r |
425 | };\r |
426 | \r |
427 | // Required for GZip AJAX loading\r |
428 | window.tinymce = tinymce;\r |
429 | \r |
430 | // Initialize the API\r |
431 | tinymce._init();\r |
432 | tinymce.create('tinymce.util.Dispatcher', {\r |
433 | scope : null,\r |
434 | listeners : null,\r |
435 | \r |
436 | Dispatcher : function(s) {\r |
437 | this.scope = s || this;\r |
438 | this.listeners = [];\r |
439 | },\r |
440 | \r |
441 | add : function(cb, s) {\r |
442 | this.listeners.push({cb : cb, scope : s || this.scope});\r |
443 | \r |
444 | return cb;\r |
445 | },\r |
446 | \r |
447 | addToTop : function(cb, s) {\r |
448 | this.listeners.unshift({cb : cb, scope : s || this.scope});\r |
449 | \r |
450 | return cb;\r |
451 | },\r |
452 | \r |
453 | remove : function(cb) {\r |
454 | var l = this.listeners, o = null;\r |
455 | \r |
456 | tinymce.each(l, function(c, i) {\r |
457 | if (cb == c.cb) {\r |
458 | o = cb;\r |
459 | l.splice(i, 1);\r |
460 | return false;\r |
461 | }\r |
462 | });\r |
463 | \r |
464 | return o;\r |
465 | },\r |
466 | \r |
467 | dispatch : function() {\r |
468 | var s, a = arguments, i, li = this.listeners, c;\r |
469 | \r |
470 | // Needs to be a real loop since the listener count might change while looping\r |
471 | // And this is also more efficient\r |
472 | for (i = 0; i<li.length; i++) {\r |
473 | c = li[i];\r |
474 | s = c.cb.apply(c.scope, a);\r |
475 | \r |
476 | if (s === false)\r |
477 | break;\r |
478 | }\r |
479 | \r |
480 | return s;\r |
481 | }\r |
482 | \r |
483 | });\r |
484 | (function() {\r |
485 | var each = tinymce.each;\r |
486 | \r |
487 | tinymce.create('tinymce.util.URI', {\r |
488 | URI : function(u, s) {\r |
489 | var t = this, o, a, b;\r |
490 | \r |
491 | // Trim whitespace\r |
492 | u = tinymce.trim(u);\r |
493 | \r |
494 | // Default settings\r |
495 | s = t.settings = s || {};\r |
496 | \r |
497 | // Strange app protocol or local anchor\r |
498 | if (/^(mailto|tel|news|javascript|about|data):/i.test(u) || /^\s*#/.test(u)) {\r |
499 | t.source = u;\r |
500 | return;\r |
501 | }\r |
502 | \r |
503 | // Absolute path with no host, fake host and protocol\r |
504 | if (u.indexOf('/') === 0 && u.indexOf('//') !== 0)\r |
505 | u = (s.base_uri ? s.base_uri.protocol || 'http' : 'http') + '://mce_host' + u;\r |
506 | \r |
507 | // Relative path http:// or protocol relative //path\r |
508 | if (!/^\w*:?\/\//.test(u))\r |
509 | u = (s.base_uri.protocol || 'http') + '://mce_host' + t.toAbsPath(s.base_uri.path, u);\r |
510 | \r |
511 | // Parse URL (Credits goes to Steave, http://blog.stevenlevithan.com/archives/parseuri)\r |
512 | u = u.replace(/@/g, '(mce_at)'); // Zope 3 workaround, they use @@something\r |
513 | u = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(u);\r |
514 | each(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], function(v, i) {\r |
515 | var s = u[i];\r |
516 | \r |
517 | // Zope 3 workaround, they use @@something\r |
518 | if (s)\r |
519 | s = s.replace(/\(mce_at\)/g, '@');\r |
520 | \r |
521 | t[v] = s;\r |
522 | });\r |
523 | \r |
524 | if (b = s.base_uri) {\r |
525 | if (!t.protocol)\r |
526 | t.protocol = b.protocol;\r |
527 | \r |
528 | if (!t.userInfo)\r |
529 | t.userInfo = b.userInfo;\r |
530 | \r |
531 | if (!t.port && t.host == 'mce_host')\r |
532 | t.port = b.port;\r |
533 | \r |
534 | if (!t.host || t.host == 'mce_host')\r |
535 | t.host = b.host;\r |
536 | \r |
537 | t.source = '';\r |
538 | }\r |
539 | \r |
540 | //t.path = t.path || '/';\r |
541 | },\r |
542 | \r |
543 | setPath : function(p) {\r |
544 | var t = this;\r |
545 | \r |
546 | p = /^(.*?)\/?(\w+)?$/.exec(p);\r |
547 | \r |
548 | // Update path parts\r |
549 | t.path = p[0];\r |
550 | t.directory = p[1];\r |
551 | t.file = p[2];\r |
552 | \r |
553 | // Rebuild source\r |
554 | t.source = '';\r |
555 | t.getURI();\r |
556 | },\r |
557 | \r |
558 | toRelative : function(u) {\r |
559 | var t = this, o;\r |
560 | \r |
561 | if (u === "./")\r |
562 | return u;\r |
563 | \r |
564 | u = new tinymce.util.URI(u, {base_uri : t});\r |
565 | \r |
566 | // Not on same domain/port or protocol\r |
567 | if ((u.host != 'mce_host' && t.host != u.host && u.host) || t.port != u.port || t.protocol != u.protocol)\r |
568 | return u.getURI();\r |
569 | \r |
570 | o = t.toRelPath(t.path, u.path);\r |
571 | \r |
572 | // Add query\r |
573 | if (u.query)\r |
574 | o += '?' + u.query;\r |
575 | \r |
576 | // Add anchor\r |
577 | if (u.anchor)\r |
578 | o += '#' + u.anchor;\r |
579 | \r |
580 | return o;\r |
581 | },\r |
582 | \r |
583 | toAbsolute : function(u, nh) {\r |
584 | var u = new tinymce.util.URI(u, {base_uri : this});\r |
585 | \r |
586 | return u.getURI(this.host == u.host && this.protocol == u.protocol ? nh : 0);\r |
587 | },\r |
588 | \r |
589 | toRelPath : function(base, path) {\r |
590 | var items, bp = 0, out = '', i, l;\r |
591 | \r |
592 | // Split the paths\r |
593 | base = base.substring(0, base.lastIndexOf('/'));\r |
594 | base = base.split('/');\r |
595 | items = path.split('/');\r |
596 | \r |
597 | if (base.length >= items.length) {\r |
598 | for (i = 0, l = base.length; i < l; i++) {\r |
599 | if (i >= items.length || base[i] != items[i]) {\r |
600 | bp = i + 1;\r |
601 | break;\r |
602 | }\r |
603 | }\r |
604 | }\r |
605 | \r |
606 | if (base.length < items.length) {\r |
607 | for (i = 0, l = items.length; i < l; i++) {\r |
608 | if (i >= base.length || base[i] != items[i]) {\r |
609 | bp = i + 1;\r |
610 | break;\r |
611 | }\r |
612 | }\r |
613 | }\r |
614 | \r |
615 | if (bp == 0) {\r |
616 | return "./";\r |
617 | }\r |
618 | \r |
619 | if (bp == 1)\r |
620 | return path;\r |
621 | \r |
622 | for (i = 0, l = base.length - (bp - 1); i < l; i++)\r |
623 | out += "../";\r |
624 | \r |
625 | for (i = bp - 1, l = items.length; i < l; i++) {\r |
626 | if (i != bp - 1)\r |
627 | out += "/" + items[i];\r |
628 | else\r |
629 | out += items[i];\r |
630 | }\r |
631 | \r |
632 | return out;\r |
633 | },\r |
634 | \r |
635 | toAbsPath : function(base, path) {\r |
636 | var i, nb = 0, o = [], tr, outPath;\r |
637 | \r |
638 | // Split paths\r |
639 | tr = /\/$/.test(path) ? '/' : '';\r |
640 | base = base.split('/');\r |
641 | path = path.split('/');\r |
642 | \r |
643 | // Remove empty chunks\r |
644 | each(base, function(k) {\r |
645 | if (k)\r |
646 | o.push(k);\r |
647 | });\r |
648 | \r |
649 | base = o;\r |
650 | \r |
651 | // Merge relURLParts chunks\r |
652 | for (i = path.length - 1, o = []; i >= 0; i--) {\r |
653 | // Ignore empty or .\r |
654 | if (path[i].length == 0 || path[i] == ".")\r |
655 | continue;\r |
656 | \r |
657 | // Is parent\r |
658 | if (path[i] == '..') {\r |
659 | nb++;\r |
660 | continue;\r |
661 | }\r |
662 | \r |
663 | // Move up\r |
664 | if (nb > 0) {\r |
665 | nb--;\r |
666 | continue;\r |
667 | }\r |
668 | \r |
669 | o.push(path[i]);\r |
670 | }\r |
671 | \r |
672 | i = base.length - nb;\r |
673 | \r |
674 | // If /a/b/c or /\r |
675 | if (i <= 0)\r |
676 | outPath = o.reverse().join('/');\r |
677 | else\r |
678 | outPath = base.slice(0, i).join('/') + '/' + o.reverse().join('/');\r |
679 | \r |
680 | // Add front / if it's needed\r |
681 | if (outPath.indexOf('/') !== 0)\r |
682 | outPath = '/' + outPath;\r |
683 | \r |
684 | // Add traling / if it's needed\r |
685 | if (tr && outPath.lastIndexOf('/') !== outPath.length - 1)\r |
686 | outPath += tr;\r |
687 | \r |
688 | return outPath;\r |
689 | },\r |
690 | \r |
691 | getURI : function(nh) {\r |
692 | var s, t = this;\r |
693 | \r |
694 | // Rebuild source\r |
695 | if (!t.source || nh) {\r |
696 | s = '';\r |
697 | \r |
698 | if (!nh) {\r |
699 | if (t.protocol)\r |
700 | s += t.protocol + '://';\r |
701 | \r |
702 | if (t.userInfo)\r |
703 | s += t.userInfo + '@';\r |
704 | \r |
705 | if (t.host)\r |
706 | s += t.host;\r |
707 | \r |
708 | if (t.port)\r |
709 | s += ':' + t.port;\r |
710 | }\r |
711 | \r |
712 | if (t.path)\r |
713 | s += t.path;\r |
714 | \r |
715 | if (t.query)\r |
716 | s += '?' + t.query;\r |
717 | \r |
718 | if (t.anchor)\r |
719 | s += '#' + t.anchor;\r |
720 | \r |
721 | t.source = s;\r |
722 | }\r |
723 | \r |
724 | return t.source;\r |
725 | }\r |
726 | });\r |
727 | })();\r |
728 | \r |
729 | (function() {\r |
730 | var each = tinymce.each;\r |
731 | \r |
732 | tinymce.create('static tinymce.util.Cookie', {\r |
733 | getHash : function(n) {\r |
734 | var v = this.get(n), h;\r |
735 | \r |
736 | if (v) {\r |
737 | each(v.split('&'), function(v) {\r |
738 | v = v.split('=');\r |
739 | h = h || {};\r |
740 | h[unescape(v[0])] = unescape(v[1]);\r |
741 | });\r |
742 | }\r |
743 | \r |
744 | return h;\r |
745 | },\r |
746 | \r |
747 | setHash : function(n, v, e, p, d, s) {\r |
748 | var o = '';\r |
749 | \r |
750 | each(v, function(v, k) {\r |
751 | o += (!o ? '' : '&') + escape(k) + '=' + escape(v);\r |
752 | });\r |
753 | \r |
754 | this.set(n, o, e, p, d, s);\r |
755 | },\r |
756 | \r |
757 | get : function(n) {\r |
758 | var c = document.cookie, e, p = n + "=", b;\r |
759 | \r |
760 | // Strict mode\r |
761 | if (!c)\r |
762 | return;\r |
763 | \r |
764 | b = c.indexOf("; " + p);\r |
765 | \r |
766 | if (b == -1) {\r |
767 | b = c.indexOf(p);\r |
768 | \r |
769 | if (b != 0)\r |
770 | return null;\r |
771 | } else\r |
772 | b += 2;\r |
773 | \r |
774 | e = c.indexOf(";", b);\r |
775 | \r |
776 | if (e == -1)\r |
777 | e = c.length;\r |
778 | \r |
779 | return unescape(c.substring(b + p.length, e));\r |
780 | },\r |
781 | \r |
782 | set : function(n, v, e, p, d, s) {\r |
783 | document.cookie = n + "=" + escape(v) +\r |
784 | ((e) ? "; expires=" + e.toGMTString() : "") +\r |
785 | ((p) ? "; path=" + escape(p) : "") +\r |
786 | ((d) ? "; domain=" + d : "") +\r |
787 | ((s) ? "; secure" : "");\r |
788 | },\r |
789 | \r |
790 | remove : function(n, p) {\r |
791 | var d = new Date();\r |
792 | \r |
793 | d.setTime(d.getTime() - 1000);\r |
794 | \r |
795 | this.set(n, '', d, p, d);\r |
796 | }\r |
797 | });\r |
798 | })();\r |
799 | tinymce.create('static tinymce.util.JSON', {\r |
800 | serialize : function(o) {\r |
801 | var i, v, s = tinymce.util.JSON.serialize, t;\r |
802 | \r |
803 | if (o == null)\r |
804 | return 'null';\r |
805 | \r |
806 | t = typeof o;\r |
807 | \r |
808 | if (t == 'string') {\r |
809 | v = '\bb\tt\nn\ff\rr\""\'\'\\\\';\r |
810 | \r |
811 | return '"' + o.replace(/([\u0080-\uFFFF\x00-\x1f\"])/g, function(a, b) {\r |
812 | i = v.indexOf(b);\r |
813 | \r |
814 | if (i + 1)\r |
815 | return '\\' + v.charAt(i + 1);\r |
816 | \r |
817 | a = b.charCodeAt().toString(16);\r |
818 | \r |
819 | return '\\u' + '0000'.substring(a.length) + a;\r |
820 | }) + '"';\r |
821 | }\r |
822 | \r |
823 | if (t == 'object') {\r |
824 | if (o.hasOwnProperty && o instanceof Array) {\r |
825 | for (i=0, v = '['; i<o.length; i++)\r |
826 | v += (i > 0 ? ',' : '') + s(o[i]);\r |
827 | \r |
828 | return v + ']';\r |
829 | }\r |
830 | \r |
831 | v = '{';\r |
832 | \r |
833 | for (i in o)\r |
834 | v += typeof o[i] != 'function' ? (v.length > 1 ? ',"' : '"') + i + '":' + s(o[i]) : '';\r |
835 | \r |
836 | return v + '}';\r |
837 | }\r |
838 | \r |
839 | return '' + o;\r |
840 | },\r |
841 | \r |
842 | parse : function(s) {\r |
843 | try {\r |
844 | return eval('(' + s + ')');\r |
845 | } catch (ex) {\r |
846 | // Ignore\r |
847 | }\r |
848 | }\r |
849 | \r |
850 | });\r |
851 | tinymce.create('static tinymce.util.XHR', {\r |
852 | send : function(o) {\r |
853 | var x, t, w = window, c = 0;\r |
854 | \r |
855 | // Default settings\r |
856 | o.scope = o.scope || this;\r |
857 | o.success_scope = o.success_scope || o.scope;\r |
858 | o.error_scope = o.error_scope || o.scope;\r |
859 | o.async = o.async === false ? false : true;\r |
860 | o.data = o.data || '';\r |
861 | \r |
862 | function get(s) {\r |
863 | x = 0;\r |
864 | \r |
865 | try {\r |
866 | x = new ActiveXObject(s);\r |
867 | } catch (ex) {\r |
868 | }\r |
869 | \r |
870 | return x;\r |
871 | };\r |
872 | \r |
873 | x = w.XMLHttpRequest ? new XMLHttpRequest() : get('Microsoft.XMLHTTP') || get('Msxml2.XMLHTTP');\r |
874 | \r |
875 | if (x) {\r |
876 | if (x.overrideMimeType)\r |
877 | x.overrideMimeType(o.content_type);\r |
878 | \r |
879 | x.open(o.type || (o.data ? 'POST' : 'GET'), o.url, o.async);\r |
880 | \r |
881 | if (o.content_type)\r |
882 | x.setRequestHeader('Content-Type', o.content_type);\r |
883 | \r |
884 | x.setRequestHeader('X-Requested-With', 'XMLHttpRequest');\r |
885 | \r |
886 | x.send(o.data);\r |
887 | \r |
888 | function ready() {\r |
889 | if (!o.async || x.readyState == 4 || c++ > 10000) {\r |
890 | if (o.success && c < 10000 && x.status == 200)\r |
891 | o.success.call(o.success_scope, '' + x.responseText, x, o);\r |
892 | else if (o.error)\r |
893 | o.error.call(o.error_scope, c > 10000 ? 'TIMED_OUT' : 'GENERAL', x, o);\r |
894 | \r |
895 | x = null;\r |
896 | } else\r |
897 | w.setTimeout(ready, 10);\r |
898 | };\r |
899 | \r |
900 | // Syncronous request\r |
901 | if (!o.async)\r |
902 | return ready();\r |
903 | \r |
904 | // Wait for response, onReadyStateChange can not be used since it leaks memory in IE\r |
905 | t = w.setTimeout(ready, 10);\r |
906 | }\r |
907 | }\r |
908 | });\r |
909 | (function() {\r |
910 | var extend = tinymce.extend, JSON = tinymce.util.JSON, XHR = tinymce.util.XHR;\r |
911 | \r |
912 | tinymce.create('tinymce.util.JSONRequest', {\r |
913 | JSONRequest : function(s) {\r |
914 | this.settings = extend({\r |
915 | }, s);\r |
916 | this.count = 0;\r |
917 | },\r |
918 | \r |
919 | send : function(o) {\r |
920 | var ecb = o.error, scb = o.success;\r |
921 | \r |
922 | o = extend(this.settings, o);\r |
923 | \r |
924 | o.success = function(c, x) {\r |
925 | c = JSON.parse(c);\r |
926 | \r |
927 | if (typeof(c) == 'undefined') {\r |
928 | c = {\r |
929 | error : 'JSON Parse error.'\r |
930 | };\r |
931 | }\r |
932 | \r |
933 | if (c.error)\r |
934 | ecb.call(o.error_scope || o.scope, c.error, x);\r |
935 | else\r |
936 | scb.call(o.success_scope || o.scope, c.result);\r |
937 | };\r |
938 | \r |
939 | o.error = function(ty, x) {\r |
940 | ecb.call(o.error_scope || o.scope, ty, x);\r |
941 | };\r |
942 | \r |
943 | o.data = JSON.serialize({\r |
944 | id : o.id || 'c' + (this.count++),\r |
945 | method : o.method,\r |
946 | params : o.params\r |
947 | });\r |
948 | \r |
949 | // JSON content type for Ruby on rails. Bug: #1883287\r |
950 | o.content_type = 'application/json';\r |
951 | \r |
952 | XHR.send(o);\r |
953 | },\r |
954 | \r |
955 | 'static' : {\r |
956 | sendRPC : function(o) {\r |
957 | return new tinymce.util.JSONRequest().send(o);\r |
958 | }\r |
959 | }\r |
960 | });\r |
961 | }());\r |
962 | (function(tinymce) {\r |
963 | // Shorten names\r |
964 | var each = tinymce.each, is = tinymce.is;\r |
965 | var isWebKit = tinymce.isWebKit, isIE = tinymce.isIE;\r |
966 | \r |
967 | tinymce.create('tinymce.dom.DOMUtils', {\r |
968 | doc : null,\r |
969 | root : null,\r |
970 | files : null,\r |
971 | pixelStyles : /^(top|left|bottom|right|width|height|borderWidth)$/,\r |
972 | props : {\r |
973 | "for" : "htmlFor",\r |
974 | "class" : "className",\r |
975 | className : "className",\r |
976 | checked : "checked",\r |
977 | disabled : "disabled",\r |
978 | maxlength : "maxLength",\r |
979 | readonly : "readOnly",\r |
980 | selected : "selected",\r |
981 | value : "value",\r |
982 | id : "id",\r |
983 | name : "name",\r |
984 | type : "type"\r |
985 | },\r |
986 | \r |
987 | DOMUtils : function(d, s) {\r |
988 | var t = this;\r |
989 | \r |
990 | t.doc = d;\r |
991 | t.win = window;\r |
992 | t.files = {};\r |
993 | t.cssFlicker = false;\r |
994 | t.counter = 0;\r |
995 | t.boxModel = !tinymce.isIE || d.compatMode == "CSS1Compat"; \r |
996 | t.stdMode = d.documentMode === 8;\r |
997 | \r |
998 | t.settings = s = tinymce.extend({\r |
999 | keep_values : false,\r |
1000 | hex_colors : 1,\r |
1001 | process_html : 1\r |
1002 | }, s);\r |
1003 | \r |
1004 | // Fix IE6SP2 flicker and check it failed for pre SP2\r |
1005 | if (tinymce.isIE6) {\r |
1006 | try {\r |
1007 | d.execCommand('BackgroundImageCache', false, true);\r |
1008 | } catch (e) {\r |
1009 | t.cssFlicker = true;\r |
1010 | }\r |
1011 | }\r |
1012 | \r |
1013 | tinymce.addUnload(t.destroy, t);\r |
1014 | },\r |
1015 | \r |
1016 | getRoot : function() {\r |
1017 | var t = this, s = t.settings;\r |
1018 | \r |
1019 | return (s && t.get(s.root_element)) || t.doc.body;\r |
1020 | },\r |
1021 | \r |
1022 | getViewPort : function(w) {\r |
1023 | var d, b;\r |
1024 | \r |
1025 | w = !w ? this.win : w;\r |
1026 | d = w.document;\r |
1027 | b = this.boxModel ? d.documentElement : d.body;\r |
1028 | \r |
1029 | // Returns viewport size excluding scrollbars\r |
1030 | return {\r |
1031 | x : w.pageXOffset || b.scrollLeft,\r |
1032 | y : w.pageYOffset || b.scrollTop,\r |
1033 | w : w.innerWidth || b.clientWidth,\r |
1034 | h : w.innerHeight || b.clientHeight\r |
1035 | };\r |
1036 | },\r |
1037 | \r |
1038 | getRect : function(e) {\r |
1039 | var p, t = this, sr;\r |
1040 | \r |
1041 | e = t.get(e);\r |
1042 | p = t.getPos(e);\r |
1043 | sr = t.getSize(e);\r |
1044 | \r |
1045 | return {\r |
1046 | x : p.x,\r |
1047 | y : p.y,\r |
1048 | w : sr.w,\r |
1049 | h : sr.h\r |
1050 | };\r |
1051 | },\r |
1052 | \r |
1053 | getSize : function(e) {\r |
1054 | var t = this, w, h;\r |
1055 | \r |
1056 | e = t.get(e);\r |
1057 | w = t.getStyle(e, 'width');\r |
1058 | h = t.getStyle(e, 'height');\r |
1059 | \r |
1060 | // Non pixel value, then force offset/clientWidth\r |
1061 | if (w.indexOf('px') === -1)\r |
1062 | w = 0;\r |
1063 | \r |
1064 | // Non pixel value, then force offset/clientWidth\r |
1065 | if (h.indexOf('px') === -1)\r |
1066 | h = 0;\r |
1067 | \r |
1068 | return {\r |
1069 | w : parseInt(w) || e.offsetWidth || e.clientWidth,\r |
1070 | h : parseInt(h) || e.offsetHeight || e.clientHeight\r |
1071 | };\r |
1072 | },\r |
1073 | \r |
1074 | getParent : function(n, f, r) {\r |
1075 | return this.getParents(n, f, r, false);\r |
1076 | },\r |
1077 | \r |
1078 | getParents : function(n, f, r, c) {\r |
1079 | var t = this, na, se = t.settings, o = [];\r |
1080 | \r |
1081 | n = t.get(n);\r |
1082 | c = c === undefined;\r |
1083 | \r |
1084 | if (se.strict_root)\r |
1085 | r = r || t.getRoot();\r |
1086 | \r |
1087 | // Wrap node name as func\r |
1088 | if (is(f, 'string')) {\r |
1089 | na = f;\r |
1090 | \r |
1091 | if (f === '*') {\r |
1092 | f = function(n) {return n.nodeType == 1;};\r |
1093 | } else {\r |
1094 | f = function(n) {\r |
1095 | return t.is(n, na);\r |
1096 | };\r |
1097 | }\r |
1098 | }\r |
1099 | \r |
1100 | while (n) {\r |
1101 | if (n == r || !n.nodeType || n.nodeType === 9)\r |
1102 | break;\r |
1103 | \r |
1104 | if (!f || f(n)) {\r |
1105 | if (c)\r |
1106 | o.push(n);\r |
1107 | else\r |
1108 | return n;\r |
1109 | }\r |
1110 | \r |
1111 | n = n.parentNode;\r |
1112 | }\r |
1113 | \r |
1114 | return c ? o : null;\r |
1115 | },\r |
1116 | \r |
1117 | get : function(e) {\r |
1118 | var n;\r |
1119 | \r |
1120 | if (e && this.doc && typeof(e) == 'string') {\r |
1121 | n = e;\r |
1122 | e = this.doc.getElementById(e);\r |
1123 | \r |
1124 | // IE and Opera returns meta elements when they match the specified input ID, but getElementsByName seems to do the trick\r |
1125 | if (e && e.id !== n)\r |
1126 | return this.doc.getElementsByName(n)[1];\r |
1127 | }\r |
1128 | \r |
1129 | return e;\r |
1130 | },\r |
1131 | \r |
1132 | getNext : function(node, selector) {\r |
1133 | return this._findSib(node, selector, 'nextSibling');\r |
1134 | },\r |
1135 | \r |
1136 | getPrev : function(node, selector) {\r |
1137 | return this._findSib(node, selector, 'previousSibling');\r |
1138 | },\r |
1139 | \r |
1140 | select : function(pa, s) {\r |
1141 | var t = this;\r |
1142 | \r |
1143 | return tinymce.dom.Sizzle(pa, t.get(s) || t.get(t.settings.root_element) || t.doc, []);\r |
1144 | },\r |
1145 | \r |
1146 | is : function(n, patt) {\r |
1147 | return tinymce.dom.Sizzle.matches(patt, n.nodeType ? [n] : n).length > 0;\r |
1148 | },\r |
1149 | \r |
1150 | add : function(p, n, a, h, c) {\r |
1151 | var t = this;\r |
1152 | \r |
1153 | return this.run(p, function(p) {\r |
1154 | var e, k;\r |
1155 | \r |
1156 | e = is(n, 'string') ? t.doc.createElement(n) : n;\r |
1157 | t.setAttribs(e, a);\r |
1158 | \r |
1159 | if (h) {\r |
1160 | if (h.nodeType)\r |
1161 | e.appendChild(h);\r |
1162 | else\r |
1163 | t.setHTML(e, h);\r |
1164 | }\r |
1165 | \r |
1166 | return !c ? p.appendChild(e) : e;\r |
1167 | });\r |
1168 | },\r |
1169 | \r |
1170 | create : function(n, a, h) {\r |
1171 | return this.add(this.doc.createElement(n), n, a, h, 1);\r |
1172 | },\r |
1173 | \r |
1174 | createHTML : function(n, a, h) {\r |
1175 | var o = '', t = this, k;\r |
1176 | \r |
1177 | o += '<' + n;\r |
1178 | \r |
1179 | for (k in a) {\r |
1180 | if (a.hasOwnProperty(k))\r |
1181 | o += ' ' + k + '="' + t.encode(a[k]) + '"';\r |
1182 | }\r |
1183 | \r |
1184 | if (tinymce.is(h))\r |
1185 | return o + '>' + h + '</' + n + '>';\r |
1186 | \r |
1187 | return o + ' />';\r |
1188 | },\r |
1189 | \r |
1190 | remove : function(n, k) {\r |
1191 | var t = this;\r |
1192 | \r |
1193 | return this.run(n, function(n) {\r |
1194 | var p, g, i;\r |
1195 | \r |
1196 | p = n.parentNode;\r |
1197 | \r |
1198 | if (!p)\r |
1199 | return null;\r |
1200 | \r |
1201 | if (k) {\r |
1202 | for (i = n.childNodes.length - 1; i >= 0; i--)\r |
1203 | t.insertAfter(n.childNodes[i], n);\r |
1204 | \r |
1205 | //each(n.childNodes, function(c) {\r |
1206 | // p.insertBefore(c.cloneNode(true), n);\r |
1207 | //});\r |
1208 | }\r |
1209 | \r |
1210 | // Fix IE psuedo leak\r |
1211 | if (t.fixPsuedoLeaks) {\r |
1212 | p = n.cloneNode(true);\r |
1213 | k = 'IELeakGarbageBin';\r |
1214 | g = t.get(k) || t.add(t.doc.body, 'div', {id : k, style : 'display:none'});\r |
1215 | g.appendChild(n);\r |
1216 | g.innerHTML = '';\r |
1217 | \r |
1218 | return p;\r |
1219 | }\r |
1220 | \r |
1221 | return p.removeChild(n);\r |
1222 | });\r |
1223 | },\r |
1224 | \r |
1225 | setStyle : function(n, na, v) {\r |
1226 | var t = this;\r |
1227 | \r |
1228 | return t.run(n, function(e) {\r |
1229 | var s, i;\r |
1230 | \r |
1231 | s = e.style;\r |
1232 | \r |
1233 | // Camelcase it, if needed\r |
1234 | na = na.replace(/-(\D)/g, function(a, b){\r |
1235 | return b.toUpperCase();\r |
1236 | });\r |
1237 | \r |
1238 | // Default px suffix on these\r |
1239 | if (t.pixelStyles.test(na) && (tinymce.is(v, 'number') || /^[\-0-9\.]+$/.test(v)))\r |
1240 | v += 'px';\r |
1241 | \r |
1242 | switch (na) {\r |
1243 | case 'opacity':\r |
1244 | // IE specific opacity\r |
1245 | if (isIE) {\r |
1246 | s.filter = v === '' ? '' : "alpha(opacity=" + (v * 100) + ")";\r |
1247 | \r |
1248 | if (!n.currentStyle || !n.currentStyle.hasLayout)\r |
1249 | s.display = 'inline-block';\r |
1250 | }\r |
1251 | \r |
1252 | // Fix for older browsers\r |
1253 | s[na] = s['-moz-opacity'] = s['-khtml-opacity'] = v || '';\r |
1254 | break;\r |
1255 | \r |
1256 | case 'float':\r |
1257 | isIE ? s.styleFloat = v : s.cssFloat = v;\r |
1258 | break;\r |
1259 | \r |
1260 | default:\r |
1261 | s[na] = v || '';\r |
1262 | }\r |
1263 | \r |
1264 | // Force update of the style data\r |
1265 | if (t.settings.update_styles)\r |
1266 | t.setAttrib(e, 'mce_style');\r |
1267 | });\r |
1268 | },\r |
1269 | \r |
1270 | getStyle : function(n, na, c) {\r |
1271 | n = this.get(n);\r |
1272 | \r |
1273 | if (!n)\r |
1274 | return false;\r |
1275 | \r |
1276 | // Gecko\r |
1277 | if (this.doc.defaultView && c) {\r |
1278 | // Remove camelcase\r |
1279 | na = na.replace(/[A-Z]/g, function(a){\r |
1280 | return '-' + a;\r |
1281 | });\r |
1282 | \r |
1283 | try {\r |
1284 | return this.doc.defaultView.getComputedStyle(n, null).getPropertyValue(na);\r |
1285 | } catch (ex) {\r |
1286 | // Old safari might fail\r |
1287 | return null;\r |
1288 | }\r |
1289 | }\r |
1290 | \r |
1291 | // Camelcase it, if needed\r |
1292 | na = na.replace(/-(\D)/g, function(a, b){\r |
1293 | return b.toUpperCase();\r |
1294 | });\r |
1295 | \r |
1296 | if (na == 'float')\r |
1297 | na = isIE ? 'styleFloat' : 'cssFloat';\r |
1298 | \r |
1299 | // IE & Opera\r |
1300 | if (n.currentStyle && c)\r |
1301 | return n.currentStyle[na];\r |
1302 | \r |
1303 | return n.style[na];\r |
1304 | },\r |
1305 | \r |
1306 | setStyles : function(e, o) {\r |
1307 | var t = this, s = t.settings, ol;\r |
1308 | \r |
1309 | ol = s.update_styles;\r |
1310 | s.update_styles = 0;\r |
1311 | \r |
1312 | each(o, function(v, n) {\r |
1313 | t.setStyle(e, n, v);\r |
1314 | });\r |
1315 | \r |
1316 | // Update style info\r |
1317 | s.update_styles = ol;\r |
1318 | if (s.update_styles)\r |
1319 | t.setAttrib(e, s.cssText);\r |
1320 | },\r |
1321 | \r |
1322 | setAttrib : function(e, n, v) {\r |
1323 | var t = this;\r |
1324 | \r |
1325 | // Whats the point\r |
1326 | if (!e || !n)\r |
1327 | return;\r |
1328 | \r |
1329 | // Strict XML mode\r |
1330 | if (t.settings.strict)\r |
1331 | n = n.toLowerCase();\r |
1332 | \r |
1333 | return this.run(e, function(e) {\r |
1334 | var s = t.settings;\r |
1335 | \r |
1336 | switch (n) {\r |
1337 | case "style":\r |
1338 | if (!is(v, 'string')) {\r |
1339 | each(v, function(v, n) {\r |
1340 | t.setStyle(e, n, v);\r |
1341 | });\r |
1342 | \r |
1343 | return;\r |
1344 | }\r |
1345 | \r |
1346 | // No mce_style for elements with these since they might get resized by the user\r |
1347 | if (s.keep_values) {\r |
1348 | if (v && !t._isRes(v))\r |
1349 | e.setAttribute('mce_style', v, 2);\r |
1350 | else\r |
1351 | e.removeAttribute('mce_style', 2);\r |
1352 | }\r |
1353 | \r |
1354 | e.style.cssText = v;\r |
1355 | break;\r |
1356 | \r |
1357 | case "class":\r |
1358 | e.className = v || ''; // Fix IE null bug\r |
1359 | break;\r |
1360 | \r |
1361 | case "src":\r |
1362 | case "href":\r |
1363 | if (s.keep_values) {\r |
1364 | if (s.url_converter)\r |
1365 | v = s.url_converter.call(s.url_converter_scope || t, v, n, e);\r |
1366 | \r |
1367 | t.setAttrib(e, 'mce_' + n, v, 2);\r |
1368 | }\r |
1369 | \r |
1370 | break;\r |
1371 | \r |
1372 | case "shape":\r |
1373 | e.setAttribute('mce_style', v);\r |
1374 | break;\r |
1375 | }\r |
1376 | \r |
1377 | if (is(v) && v !== null && v.length !== 0)\r |
1378 | e.setAttribute(n, '' + v, 2);\r |
1379 | else\r |
1380 | e.removeAttribute(n, 2);\r |
1381 | });\r |
1382 | },\r |
1383 | \r |
1384 | setAttribs : function(e, o) {\r |
1385 | var t = this;\r |
1386 | \r |
1387 | return this.run(e, function(e) {\r |
1388 | each(o, function(v, n) {\r |
1389 | t.setAttrib(e, n, v);\r |
1390 | });\r |
1391 | });\r |
1392 | },\r |
1393 | \r |
1394 | getAttrib : function(e, n, dv) {\r |
1395 | var v, t = this;\r |
1396 | \r |
1397 | e = t.get(e);\r |
1398 | \r |
1399 | if (!e || e.nodeType !== 1)\r |
1400 | return false;\r |
1401 | \r |
1402 | if (!is(dv))\r |
1403 | dv = '';\r |
1404 | \r |
1405 | // Try the mce variant for these\r |
1406 | if (/^(src|href|style|coords|shape)$/.test(n)) {\r |
1407 | v = e.getAttribute("mce_" + n);\r |
1408 | \r |
1409 | if (v)\r |
1410 | return v;\r |
1411 | }\r |
1412 | \r |
1413 | if (isIE && t.props[n]) {\r |
1414 | v = e[t.props[n]];\r |
1415 | v = v && v.nodeValue ? v.nodeValue : v;\r |
1416 | }\r |
1417 | \r |
1418 | if (!v)\r |
1419 | v = e.getAttribute(n, 2);\r |
1420 | \r |
1421 | // Check boolean attribs\r |
1422 | if (/^(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)$/.test(n)) {\r |
1423 | if (e[t.props[n]] === true && v === '')\r |
1424 | return n;\r |
1425 | \r |
1426 | return v ? n : '';\r |
1427 | }\r |
1428 | \r |
1429 | // Inner input elements will override attributes on form elements\r |
1430 | if (e.nodeName === "FORM" && e.getAttributeNode(n))\r |
1431 | return e.getAttributeNode(n).nodeValue;\r |
1432 | \r |
1433 | if (n === 'style') {\r |
1434 | v = v || e.style.cssText;\r |
1435 | \r |
1436 | if (v) {\r |
1437 | v = t.serializeStyle(t.parseStyle(v));\r |
1438 | \r |
1439 | if (t.settings.keep_values && !t._isRes(v))\r |
1440 | e.setAttribute('mce_style', v);\r |
1441 | }\r |
1442 | }\r |
1443 | \r |
1444 | // Remove Apple and WebKit stuff\r |
1445 | if (isWebKit && n === "class" && v)\r |
1446 | v = v.replace(/(apple|webkit)\-[a-z\-]+/gi, '');\r |
1447 | \r |
1448 | // Handle IE issues\r |
1449 | if (isIE) {\r |
1450 | switch (n) {\r |
1451 | case 'rowspan':\r |
1452 | case 'colspan':\r |
1453 | // IE returns 1 as default value\r |
1454 | if (v === 1)\r |
1455 | v = '';\r |
1456 | \r |
1457 | break;\r |
1458 | \r |
1459 | case 'size':\r |
1460 | // IE returns +0 as default value for size\r |
1461 | if (v === '+0' || v === 20 || v === 0)\r |
1462 | v = '';\r |
1463 | \r |
1464 | break;\r |
1465 | \r |
1466 | case 'width':\r |
1467 | case 'height':\r |
1468 | case 'vspace':\r |
1469 | case 'checked':\r |
1470 | case 'disabled':\r |
1471 | case 'readonly':\r |
1472 | if (v === 0)\r |
1473 | v = '';\r |
1474 | \r |
1475 | break;\r |
1476 | \r |
1477 | case 'hspace':\r |
1478 | // IE returns -1 as default value\r |
1479 | if (v === -1)\r |
1480 | v = '';\r |
1481 | \r |
1482 | break;\r |
1483 | \r |
1484 | case 'maxlength':\r |
1485 | case 'tabindex':\r |
1486 | // IE returns default value\r |
1487 | if (v === 32768 || v === 2147483647 || v === '32768')\r |
1488 | v = '';\r |
1489 | \r |
1490 | break;\r |
1491 | \r |
1492 | case 'multiple':\r |
1493 | case 'compact':\r |
1494 | case 'noshade':\r |
1495 | case 'nowrap':\r |
1496 | if (v === 65535)\r |
1497 | return n;\r |
1498 | \r |
1499 | return dv;\r |
1500 | \r |
1501 | case 'shape':\r |
1502 | v = v.toLowerCase();\r |
1503 | break;\r |
1504 | \r |
1505 | default:\r |
1506 | // IE has odd anonymous function for event attributes\r |
1507 | if (n.indexOf('on') === 0 && v)\r |
1508 | v = ('' + v).replace(/^function\s+\w+\(\)\s+\{\s+(.*)\s+\}$/, '$1');\r |
1509 | }\r |
1510 | }\r |
1511 | \r |
1512 | return (v !== undefined && v !== null && v !== '') ? '' + v : dv;\r |
1513 | },\r |
1514 | \r |
1515 | getPos : function(n, ro) {\r |
1516 | var t = this, x = 0, y = 0, e, d = t.doc, r;\r |
1517 | \r |
1518 | n = t.get(n);\r |
1519 | ro = ro || d.body;\r |
1520 | \r |
1521 | if (n) {\r |
1522 | // Use getBoundingClientRect on IE, Opera has it but it's not perfect\r |
1523 | if (isIE && !t.stdMode) {\r |
1524 | n = n.getBoundingClientRect();\r |
1525 | e = t.boxModel ? d.documentElement : d.body;\r |
1526 | x = t.getStyle(t.select('html')[0], 'borderWidth'); // Remove border\r |
1527 | x = (x == 'medium' || t.boxModel && !t.isIE6) && 2 || x;\r |
1528 | n.top += t.win.self != t.win.top ? 2 : 0; // IE adds some strange extra cord if used in a frameset\r |
1529 | \r |
1530 | return {x : n.left + e.scrollLeft - x, y : n.top + e.scrollTop - x};\r |
1531 | }\r |
1532 | \r |
1533 | r = n;\r |
1534 | while (r && r != ro && r.nodeType) {\r |
1535 | x += r.offsetLeft || 0;\r |
1536 | y += r.offsetTop || 0;\r |
1537 | r = r.offsetParent;\r |
1538 | }\r |
1539 | \r |
1540 | r = n.parentNode;\r |
1541 | while (r && r != ro && r.nodeType) {\r |
1542 | x -= r.scrollLeft || 0;\r |
1543 | y -= r.scrollTop || 0;\r |
1544 | r = r.parentNode;\r |
1545 | }\r |
1546 | }\r |
1547 | \r |
1548 | return {x : x, y : y};\r |
1549 | },\r |
1550 | \r |
1551 | parseStyle : function(st) {\r |
1552 | var t = this, s = t.settings, o = {};\r |
1553 | \r |
1554 | if (!st)\r |
1555 | return o;\r |
1556 | \r |
1557 | function compress(p, s, ot) {\r |
1558 | var t, r, b, l;\r |
1559 | \r |
1560 | // Get values and check it it needs compressing\r |
1561 | t = o[p + '-top' + s];\r |
1562 | if (!t)\r |
1563 | return;\r |
1564 | \r |
1565 | r = o[p + '-right' + s];\r |
1566 | if (t != r)\r |
1567 | return;\r |
1568 | \r |
1569 | b = o[p + '-bottom' + s];\r |
1570 | if (r != b)\r |
1571 | return;\r |
1572 | \r |
1573 | l = o[p + '-left' + s];\r |
1574 | if (b != l)\r |
1575 | return;\r |
1576 | \r |
1577 | // Compress\r |
1578 | o[ot] = l;\r |
1579 | delete o[p + '-top' + s];\r |
1580 | delete o[p + '-right' + s];\r |
1581 | delete o[p + '-bottom' + s];\r |
1582 | delete o[p + '-left' + s];\r |
1583 | };\r |
1584 | \r |
1585 | function compress2(ta, a, b, c) {\r |
1586 | var t;\r |
1587 | \r |
1588 | t = o[a];\r |
1589 | if (!t)\r |
1590 | return;\r |
1591 | \r |
1592 | t = o[b];\r |
1593 | if (!t)\r |
1594 | return;\r |
1595 | \r |
1596 | t = o[c];\r |
1597 | if (!t)\r |
1598 | return;\r |
1599 | \r |
1600 | // Compress\r |
1601 | o[ta] = o[a] + ' ' + o[b] + ' ' + o[c];\r |
1602 | delete o[a];\r |
1603 | delete o[b];\r |
1604 | delete o[c];\r |
1605 | };\r |
1606 | \r |
1607 | st = st.replace(/&(#?[a-z0-9]+);/g, '&$1_MCE_SEMI_'); // Protect entities\r |
1608 | \r |
1609 | each(st.split(';'), function(v) {\r |
1610 | var sv, ur = [];\r |
1611 | \r |
1612 | if (v) {\r |
1613 | v = v.replace(/_MCE_SEMI_/g, ';'); // Restore entities\r |
1614 | v = v.replace(/url\([^\)]+\)/g, function(v) {ur.push(v);return 'url(' + ur.length + ')';});\r |
1615 | v = v.split(':');\r |
1616 | sv = tinymce.trim(v[1]);\r |
1617 | sv = sv.replace(/url\(([^\)]+)\)/g, function(a, b) {return ur[parseInt(b) - 1];});\r |
1618 | \r |
1619 | sv = sv.replace(/rgb\([^\)]+\)/g, function(v) {\r |
1620 | return t.toHex(v);\r |
1621 | });\r |
1622 | \r |
1623 | if (s.url_converter) {\r |
1624 | sv = sv.replace(/url\([\'\"]?([^\)\'\"]+)[\'\"]?\)/g, function(x, c) {\r |
1625 | return 'url(' + s.url_converter.call(s.url_converter_scope || t, t.decode(c), 'style', null) + ')';\r |
1626 | });\r |
1627 | }\r |
1628 | \r |
1629 | o[tinymce.trim(v[0]).toLowerCase()] = sv;\r |
1630 | }\r |
1631 | });\r |
1632 | \r |
1633 | compress("border", "", "border");\r |
1634 | compress("border", "-width", "border-width");\r |
1635 | compress("border", "-color", "border-color");\r |
1636 | compress("border", "-style", "border-style");\r |
1637 | compress("padding", "", "padding");\r |
1638 | compress("margin", "", "margin");\r |
1639 | compress2('border', 'border-width', 'border-style', 'border-color');\r |
1640 | \r |
1641 | if (isIE) {\r |
1642 | // Remove pointless border\r |
1643 | if (o.border == 'medium none')\r |
1644 | o.border = '';\r |
1645 | }\r |
1646 | \r |
1647 | return o;\r |
1648 | },\r |
1649 | \r |
1650 | serializeStyle : function(o) {\r |
1651 | var s = '';\r |
1652 | \r |
1653 | each(o, function(v, k) {\r |
1654 | if (k && v) {\r |
1655 | if (tinymce.isGecko && k.indexOf('-moz-') === 0)\r |
1656 | return;\r |
1657 | \r |
1658 | switch (k) {\r |
1659 | case 'color':\r |
1660 | case 'background-color':\r |
1661 | v = v.toLowerCase();\r |
1662 | break;\r |
1663 | }\r |
1664 | \r |
1665 | s += (s ? ' ' : '') + k + ': ' + v + ';';\r |
1666 | }\r |
1667 | });\r |
1668 | \r |
1669 | return s;\r |
1670 | },\r |
1671 | \r |
1672 | loadCSS : function(u) {\r |
1673 | var t = this, d = t.doc, head;\r |
1674 | \r |
1675 | if (!u)\r |
1676 | u = '';\r |
1677 | \r |
1678 | head = t.select('head')[0];\r |
1679 | \r |
1680 | each(u.split(','), function(u) {\r |
1681 | var link;\r |
1682 | \r |
1683 | if (t.files[u])\r |
1684 | return;\r |
1685 | \r |
1686 | t.files[u] = true;\r |
1687 | link = t.create('link', {rel : 'stylesheet', href : tinymce._addVer(u)});\r |
1688 | \r |
1689 | // IE 8 has a bug where dynamically loading stylesheets would produce a 1 item remaining bug\r |
1690 | // This fix seems to resolve that issue by realcing the document ones a stylesheet finishes loading\r |
1691 | // It's ugly but it seems to work fine.\r |
1692 | if (isIE && d.documentMode) {\r |
1693 | link.onload = function() {\r |
1694 | d.recalc();\r |
1695 | link.onload = null;\r |
1696 | };\r |
1697 | }\r |
1698 | \r |
1699 | head.appendChild(link);\r |
1700 | });\r |
1701 | },\r |
1702 | \r |
1703 | addClass : function(e, c) {\r |
1704 | return this.run(e, function(e) {\r |
1705 | var o;\r |
1706 | \r |
1707 | if (!c)\r |
1708 | return 0;\r |
1709 | \r |
1710 | if (this.hasClass(e, c))\r |
1711 | return e.className;\r |
1712 | \r |
1713 | o = this.removeClass(e, c);\r |
1714 | \r |
1715 | return e.className = (o != '' ? (o + ' ') : '') + c;\r |
1716 | });\r |
1717 | },\r |
1718 | \r |
1719 | removeClass : function(e, c) {\r |
1720 | var t = this, re;\r |
1721 | \r |
1722 | return t.run(e, function(e) {\r |
1723 | var v;\r |
1724 | \r |
1725 | if (t.hasClass(e, c)) {\r |
1726 | if (!re)\r |
1727 | re = new RegExp("(^|\\s+)" + c + "(\\s+|$)", "g");\r |
1728 | \r |
1729 | v = e.className.replace(re, ' ');\r |
1730 | \r |
1731 | return e.className = tinymce.trim(v != ' ' ? v : '');\r |
1732 | }\r |
1733 | \r |
1734 | return e.className;\r |
1735 | });\r |
1736 | },\r |
1737 | \r |
1738 | hasClass : function(n, c) {\r |
1739 | n = this.get(n);\r |
1740 | \r |
1741 | if (!n || !c)\r |
1742 | return false;\r |
1743 | \r |
1744 | return (' ' + n.className + ' ').indexOf(' ' + c + ' ') !== -1;\r |
1745 | },\r |
1746 | \r |
1747 | show : function(e) {\r |
1748 | return this.setStyle(e, 'display', 'block');\r |
1749 | },\r |
1750 | \r |
1751 | hide : function(e) {\r |
1752 | return this.setStyle(e, 'display', 'none');\r |
1753 | },\r |
1754 | \r |
1755 | isHidden : function(e) {\r |
1756 | e = this.get(e);\r |
1757 | \r |
1758 | return !e || e.style.display == 'none' || this.getStyle(e, 'display') == 'none';\r |
1759 | },\r |
1760 | \r |
1761 | uniqueId : function(p) {\r |
1762 | return (!p ? 'mce_' : p) + (this.counter++);\r |
1763 | },\r |
1764 | \r |
1765 | setHTML : function(e, h) {\r |
1766 | var t = this;\r |
1767 | \r |
1768 | return this.run(e, function(e) {\r |
1769 | var x, i, nl, n, p, x;\r |
1770 | \r |
1771 | h = t.processHTML(h);\r |
1772 | \r |
1773 | if (isIE) {\r |
1774 | function set() {\r |
1775 | try {\r |
1776 | // IE will remove comments from the beginning\r |
1777 | // unless you padd the contents with something\r |
1778 | e.innerHTML = '<br />' + h;\r |
1779 | e.removeChild(e.firstChild);\r |
1780 | } catch (ex) {\r |
1781 | // IE sometimes produces an unknown runtime error on innerHTML if it's an block element within a block element for example a div inside a p\r |
1782 | // This seems to fix this problem\r |
1783 | \r |
1784 | // Remove all child nodes\r |
1785 | while (e.firstChild)\r |
1786 | e.firstChild.removeNode();\r |
1787 | \r |
1788 | // Create new div with HTML contents and a BR infront to keep comments\r |
1789 | x = t.create('div');\r |
1790 | x.innerHTML = '<br />' + h;\r |
1791 | \r |
1792 | // Add all children from div to target\r |
1793 | each (x.childNodes, function(n, i) {\r |
1794 | // Skip br element\r |
1795 | if (i)\r |
1796 | e.appendChild(n);\r |
1797 | });\r |
1798 | }\r |
1799 | };\r |
1800 | \r |
1801 | // IE has a serious bug when it comes to paragraphs it can produce an invalid\r |
1802 | // DOM tree if contents like this <p><ul><li>Item 1</li></ul></p> is inserted\r |
1803 | // It seems to be that IE doesn't like a root block element placed inside another root block element\r |
1804 | if (t.settings.fix_ie_paragraphs)\r |
1805 | h = h.replace(/<p><\/p>|<p([^>]+)><\/p>|<p[^\/+]\/>/gi, '<p$1 mce_keep="true"> </p>');\r |
1806 | \r |
1807 | set();\r |
1808 | \r |
1809 | if (t.settings.fix_ie_paragraphs) {\r |
1810 | // Check for odd paragraphs this is a sign of a broken DOM\r |
1811 | nl = e.getElementsByTagName("p");\r |
1812 | for (i = nl.length - 1, x = 0; i >= 0; i--) {\r |
1813 | n = nl[i];\r |
1814 | \r |
1815 | if (!n.hasChildNodes()) {\r |
1816 | if (!n.mce_keep) {\r |
1817 | x = 1; // Is broken\r |
1818 | break;\r |
1819 | }\r |
1820 | \r |
1821 | n.removeAttribute('mce_keep');\r |
1822 | }\r |
1823 | }\r |
1824 | }\r |
1825 | \r |
1826 | // Time to fix the madness IE left us\r |
1827 | if (x) {\r |
1828 | // So if we replace the p elements with divs and mark them and then replace them back to paragraphs\r |
1829 | // after we use innerHTML we can fix the DOM tree\r |
1830 | h = h.replace(/<p ([^>]+)>|<p>/ig, '<div $1 mce_tmp="1">');\r |
1831 | h = h.replace(/<\/p>/g, '</div>');\r |
1832 | \r |
1833 | // Set the new HTML with DIVs\r |
1834 | set();\r |
1835 | \r |
1836 | // Replace all DIV elements with he mce_tmp attibute back to paragraphs\r |
1837 | // This is needed since IE has a annoying bug see above for details\r |
1838 | // This is a slow process but it has to be done. :(\r |
1839 | if (t.settings.fix_ie_paragraphs) {\r |
1840 | nl = e.getElementsByTagName("DIV");\r |
1841 | for (i = nl.length - 1; i >= 0; i--) {\r |
1842 | n = nl[i];\r |
1843 | \r |
1844 | // Is it a temp div\r |
1845 | if (n.mce_tmp) {\r |
1846 | // Create new paragraph\r |
1847 | p = t.doc.createElement('p');\r |
1848 | \r |
1849 | // Copy all attributes\r |
1850 | n.cloneNode(false).outerHTML.replace(/([a-z0-9\-_]+)=/gi, function(a, b) {\r |
1851 | var v;\r |
1852 | \r |
1853 | if (b !== 'mce_tmp') {\r |
1854 | v = n.getAttribute(b);\r |
1855 | \r |
1856 | if (!v && b === 'class')\r |
1857 | v = n.className;\r |
1858 | \r |
1859 | p.setAttribute(b, v);\r |
1860 | }\r |
1861 | });\r |
1862 | \r |
1863 | // Append all children to new paragraph\r |
1864 | for (x = 0; x<n.childNodes.length; x++)\r |
1865 | p.appendChild(n.childNodes[x].cloneNode(true));\r |
1866 | \r |
1867 | // Replace div with new paragraph\r |
1868 | n.swapNode(p);\r |
1869 | }\r |
1870 | }\r |
1871 | }\r |
1872 | }\r |
1873 | } else\r |
1874 | e.innerHTML = h;\r |
1875 | \r |
1876 | return h;\r |
1877 | });\r |
1878 | },\r |
1879 | \r |
1880 | processHTML : function(h) {\r |
1881 | var t = this, s = t.settings, codeBlocks = [];\r |
1882 | \r |
1883 | if (!s.process_html)\r |
1884 | return h;\r |
1885 | \r |
1886 | // Convert strong and em to b and i in FF since it can't handle them\r |
1887 | if (tinymce.isGecko) {\r |
1888 | h = h.replace(/<(\/?)strong>|<strong( [^>]+)>/gi, '<$1b$2>');\r |
1889 | h = h.replace(/<(\/?)em>|<em( [^>]+)>/gi, '<$1i$2>');\r |
1890 | } else if (isIE) {\r |
1891 | h = h.replace(/'/g, '''); // IE can't handle apos\r |
1892 | h = h.replace(/\s+(disabled|checked|readonly|selected)\s*=\s*[\"\']?(false|0)[\"\']?/gi, ''); // IE doesn't handle default values correct\r |
1893 | }\r |
1894 | \r |
1895 | // Fix some issues\r |
1896 | h = h.replace(/<a( )([^>]+)\/>|<a\/>/gi, '<a$1$2></a>'); // Force open\r |
1897 | \r |
1898 | // Store away src and href in mce_src and mce_href since browsers mess them up\r |
1899 | if (s.keep_values) {\r |
1900 | // Wrap scripts and styles in comments for serialization purposes\r |
1901 | if (/<script|noscript|style/i.test(h)) {\r |
1902 | function trim(s) {\r |
1903 | // Remove prefix and suffix code for element\r |
1904 | s = s.replace(/(<!--\[CDATA\[|\]\]-->)/g, '\n');\r |
1905 | s = s.replace(/^[\r\n]*|[\r\n]*$/g, '');\r |
1906 | s = s.replace(/^\s*(\/\/\s*<!--|\/\/\s*<!\[CDATA\[|<!--|<!\[CDATA\[)[\r\n]*/g, '');\r |
1907 | s = s.replace(/\s*(\/\/\s*\]\]>|\/\/\s*-->|\]\]>|-->|\]\]-->)\s*$/g, '');\r |
1908 | \r |
1909 | return s;\r |
1910 | };\r |
1911 | \r |
1912 | // Wrap the script contents in CDATA and keep them from executing\r |
1913 | h = h.replace(/<script([^>]+|)>([\s\S]*?)<\/script>/gi, function(v, attribs, text) {\r |
1914 | // Force type attribute\r |
1915 | if (!attribs)\r |
1916 | attribs = ' type="text/javascript"';\r |
1917 | \r |
1918 | // Convert the src attribute of the scripts\r |
1919 | attribs = attribs.replace(/src=\"([^\"]+)\"?/i, function(a, url) {\r |
1920 | if (s.url_converter)\r |
1921 | url = t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(url), 'src', 'script'));\r |
1922 | \r |
1923 | return 'mce_src="' + url + '"';\r |
1924 | });\r |
1925 | \r |
1926 | // Wrap text contents\r |
1927 | if (tinymce.trim(text)) {\r |
1928 | codeBlocks.push(trim(text));\r |
1929 | text = '<!--\nMCE_SCRIPT:' + (codeBlocks.length - 1) + '\n// -->';\r |
1930 | }\r |
1931 | \r |
1932 | return '<mce:script' + attribs + '>' + text + '</mce:script>';\r |
1933 | });\r |
1934 | \r |
1935 | // Wrap style elements\r |
1936 | h = h.replace(/<style([^>]+|)>([\s\S]*?)<\/style>/gi, function(v, attribs, text) {\r |
1937 | // Wrap text contents\r |
1938 | if (text) {\r |
1939 | codeBlocks.push(trim(text));\r |
1940 | text = '<!--\nMCE_SCRIPT:' + (codeBlocks.length - 1) + '\n-->';\r |
1941 | }\r |
1942 | \r |
1943 | return '<mce:style' + attribs + '>' + text + '</mce:style><style ' + attribs + ' mce_bogus="1">' + text + '</style>';\r |
1944 | });\r |
1945 | \r |
1946 | // Wrap noscript elements\r |
1947 | h = h.replace(/<noscript([^>]+|)>([\s\S]*?)<\/noscript>/g, function(v, attribs, text) {\r |
1948 | return '<mce:noscript' + attribs + '><!--' + t.encode(text).replace(/--/g, '--') + '--></mce:noscript>';\r |
1949 | });\r |
1950 | }\r |
1951 | \r |
1952 | h = h.replace(/<!\[CDATA\[([\s\S]+)\]\]>/g, '<!--[CDATA[$1]]-->');\r |
1953 | \r |
1954 | // Remove false bool attributes and force attributes into xhtml style attr="attr"\r |
1955 | h = h.replace(/<([\w:]+) [^>]*(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)[^>]*>/gi, function(val) {\r |
1956 | function handle(val, name, value) {\r |
1957 | // Remove false/0 attribs\r |
1958 | if (value === 'false' || value === '0')\r |
1959 | return '';\r |
1960 | \r |
1961 | return ' ' + name + '="' + name + '"';\r |
1962 | };\r |
1963 | \r |
1964 | val = val.replace(/ (checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)=[\"]([^\"]+)[\"]/gi, handle); // W3C\r |
1965 | val = val.replace(/ (checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)=[\']([^\']+)[\']/gi, handle); // W3C\r |
1966 | val = val.replace(/ (checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)=([^\s\"\'>]+)/gi, handle); // IE\r |
1967 | val = val.replace(/ (checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)([\s>])/gi, ' $1="$1"$2'); // Force attr="attr"\r |
1968 | \r |
1969 | return val;\r |
1970 | });\r |
1971 | \r |
1972 | // Process all tags with src, href or style\r |
1973 | h = h.replace(/<([\w:]+) [^>]*(src|href|style|shape|coords)[^>]*>/gi, function(a, n) {\r |
1974 | function handle(m, b, c) {\r |
1975 | var u = c;\r |
1976 | \r |
1977 | // Tag already got a mce_ version\r |
1978 | if (a.indexOf('mce_' + b) != -1)\r |
1979 | return m;\r |
1980 | \r |
1981 | if (b == 'style') {\r |
1982 | // No mce_style for elements with these since they might get resized by the user\r |
1983 | if (t._isRes(c))\r |
1984 | return m;\r |
1985 | \r |
1986 | // Parse and serialize the style to convert for example uppercase styles like "BORDER: 1px"\r |
1987 | u = t.encode(t.serializeStyle(t.parseStyle(u)));\r |
1988 | } else if (b != 'coords' && b != 'shape') {\r |
1989 | if (s.url_converter)\r |
1990 | u = t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), b, n));\r |
1991 | }\r |
1992 | \r |
1993 | return ' ' + b + '="' + c + '" mce_' + b + '="' + u + '"';\r |
1994 | };\r |
1995 | \r |
1996 | a = a.replace(/ (src|href|style|coords|shape)=[\"]([^\"]+)[\"]/gi, handle); // W3C\r |
1997 | a = a.replace(/ (src|href|style|coords|shape)=[\']([^\']+)[\']/gi, handle); // W3C\r |
1998 | \r |
1999 | return a.replace(/ (src|href|style|coords|shape)=([^\s\"\'>]+)/gi, handle); // IE\r |
2000 | });\r |
2001 | \r |
2002 | // Restore script blocks\r |
2003 | h = h.replace(/MCE_SCRIPT:([0-9]+)/g, function(val, idx) {\r |
2004 | return codeBlocks[idx];\r |
2005 | });\r |
2006 | }\r |
2007 | \r |
2008 | return h;\r |
2009 | },\r |
2010 | \r |
2011 | getOuterHTML : function(e) {\r |
2012 | var d;\r |
2013 | \r |
2014 | e = this.get(e);\r |
2015 | \r |
2016 | if (!e)\r |
2017 | return null;\r |
2018 | \r |
2019 | if (e.outerHTML !== undefined)\r |
2020 | return e.outerHTML;\r |
2021 | \r |
2022 | d = (e.ownerDocument || this.doc).createElement("body");\r |
2023 | d.appendChild(e.cloneNode(true));\r |
2024 | \r |
2025 | return d.innerHTML;\r |
2026 | },\r |
2027 | \r |
2028 | setOuterHTML : function(e, h, d) {\r |
2029 | var t = this;\r |
2030 | \r |
2031 | function setHTML(e, h, d) {\r |
2032 | var n, tp;\r |
2033 | \r |
2034 | tp = d.createElement("body");\r |
2035 | tp.innerHTML = h;\r |
2036 | \r |
2037 | n = tp.lastChild;\r |
2038 | while (n) {\r |
2039 | t.insertAfter(n.cloneNode(true), e);\r |
2040 | n = n.previousSibling;\r |
2041 | }\r |
2042 | \r |
2043 | t.remove(e);\r |
2044 | };\r |
2045 | \r |
2046 | return this.run(e, function(e) {\r |
2047 | e = t.get(e);\r |
2048 | \r |
2049 | // Only set HTML on elements\r |
2050 | if (e.nodeType == 1) {\r |
2051 | d = d || e.ownerDocument || t.doc;\r |
2052 | \r |
2053 | if (isIE) {\r |
2054 | try {\r |
2055 | // Try outerHTML for IE it sometimes produces an unknown runtime error\r |
2056 | if (isIE && e.nodeType == 1)\r |
2057 | e.outerHTML = h;\r |
2058 | else\r |
2059 | setHTML(e, h, d);\r |
2060 | } catch (ex) {\r |
2061 | // Fix for unknown runtime error\r |
2062 | setHTML(e, h, d);\r |
2063 | }\r |
2064 | } else\r |
2065 | setHTML(e, h, d);\r |
2066 | }\r |
2067 | });\r |
2068 | },\r |
2069 | \r |
2070 | decode : function(s) {\r |
2071 | var e, n, v;\r |
2072 | \r |
2073 | // Look for entities to decode\r |
2074 | if (/&[^;]+;/.test(s)) {\r |
2075 | // Decode the entities using a div element not super efficient but less code\r |
2076 | e = this.doc.createElement("div");\r |
2077 | e.innerHTML = s;\r |
2078 | \r |
2079 | n = e.firstChild;\r |
2080 | v = '';\r |
2081 | \r |
2082 | if (n) {\r |
2083 | do {\r |
2084 | v += n.nodeValue;\r |
2085 | } while (n.nextSibling);\r |
2086 | }\r |
2087 | \r |
2088 | return v || s;\r |
2089 | }\r |
2090 | \r |
2091 | return s;\r |
2092 | },\r |
2093 | \r |
2094 | encode : function(s) {\r |
2095 | return s ? ('' + s).replace(/[<>&\"]/g, function (c, b) {\r |
2096 | switch (c) {\r |
2097 | case '&':\r |
2098 | return '&';\r |
2099 | \r |
2100 | case '"':\r |
2101 | return '"';\r |
2102 | \r |
2103 | case '<':\r |
2104 | return '<';\r |
2105 | \r |
2106 | case '>':\r |
2107 | return '>';\r |
2108 | }\r |
2109 | \r |
2110 | return c;\r |
2111 | }) : s;\r |
2112 | },\r |
2113 | \r |
2114 | insertAfter : function(n, r) {\r |
2115 | var t = this;\r |
2116 | \r |
2117 | r = t.get(r);\r |
2118 | \r |
2119 | return this.run(n, function(n) {\r |
2120 | var p, ns;\r |
2121 | \r |
2122 | p = r.parentNode;\r |
2123 | ns = r.nextSibling;\r |
2124 | \r |
2125 | if (ns)\r |
2126 | p.insertBefore(n, ns);\r |
2127 | else\r |
2128 | p.appendChild(n);\r |
2129 | \r |
2130 | return n;\r |
2131 | });\r |
2132 | },\r |
2133 | \r |
2134 | isBlock : function(n) {\r |
2135 | if (n.nodeType && n.nodeType !== 1)\r |
2136 | return false;\r |
2137 | \r |
2138 | n = n.nodeName || n;\r |
2139 | \r |
2140 | return /^(H[1-6]|HR|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TH|TBODY|TR|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP)$/.test(n);\r |
2141 | },\r |
2142 | \r |
2143 | replace : function(n, o, k) {\r |
2144 | var t = this;\r |
2145 | \r |
2146 | if (is(o, 'array'))\r |
2147 | n = n.cloneNode(true);\r |
2148 | \r |
2149 | return t.run(o, function(o) {\r |
2150 | if (k) {\r |
2151 | each(o.childNodes, function(c) {\r |
2152 | n.appendChild(c.cloneNode(true));\r |
2153 | });\r |
2154 | }\r |
2155 | \r |
2156 | // Fix IE psuedo leak for elements since replacing elements if fairly common\r |
2157 | // Will break parentNode for some unknown reason\r |
2158 | if (t.fixPsuedoLeaks && o.nodeType === 1) {\r |
2159 | o.parentNode.insertBefore(n, o);\r |
2160 | t.remove(o);\r |
2161 | return n;\r |
2162 | }\r |
2163 | \r |
2164 | return o.parentNode.replaceChild(n, o);\r |
2165 | });\r |
2166 | },\r |
2167 | \r |
2168 | findCommonAncestor : function(a, b) {\r |
2169 | var ps = a, pe;\r |
2170 | \r |
2171 | while (ps) {\r |
2172 | pe = b;\r |
2173 | \r |
2174 | while (pe && ps != pe)\r |
2175 | pe = pe.parentNode;\r |
2176 | \r |
2177 | if (ps == pe)\r |
2178 | break;\r |
2179 | \r |
2180 | ps = ps.parentNode;\r |
2181 | }\r |
2182 | \r |
2183 | if (!ps && a.ownerDocument)\r |
2184 | return a.ownerDocument.documentElement;\r |
2185 | \r |
2186 | return ps;\r |
2187 | },\r |
2188 | \r |
2189 | toHex : function(s) {\r |
2190 | var c = /^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(s);\r |
2191 | \r |
2192 | function hex(s) {\r |
2193 | s = parseInt(s).toString(16);\r |
2194 | \r |
2195 | return s.length > 1 ? s : '0' + s; // 0 -> 00\r |
2196 | };\r |
2197 | \r |
2198 | if (c) {\r |
2199 | s = '#' + hex(c[1]) + hex(c[2]) + hex(c[3]);\r |
2200 | \r |
2201 | return s;\r |
2202 | }\r |
2203 | \r |
2204 | return s;\r |
2205 | },\r |
2206 | \r |
2207 | getClasses : function() {\r |
2208 | var t = this, cl = [], i, lo = {}, f = t.settings.class_filter, ov;\r |
2209 | \r |
2210 | if (t.classes)\r |
2211 | return t.classes;\r |
2212 | \r |
2213 | function addClasses(s) {\r |
2214 | // IE style imports\r |
2215 | each(s.imports, function(r) {\r |
2216 | addClasses(r);\r |
2217 | });\r |
2218 | \r |
2219 | each(s.cssRules || s.rules, function(r) {\r |
2220 | // Real type or fake it on IE\r |
2221 | switch (r.type || 1) {\r |
2222 | // Rule\r |
2223 | case 1:\r |
2224 | if (r.selectorText) {\r |
2225 | each(r.selectorText.split(','), function(v) {\r |
2226 | v = v.replace(/^\s*|\s*$|^\s\./g, "");\r |
2227 | \r |
2228 | // Is internal or it doesn't contain a class\r |
2229 | if (/\.mce/.test(v) || !/\.[\w\-]+$/.test(v))\r |
2230 | return;\r |
2231 | \r |
2232 | // Remove everything but class name\r |
2233 | ov = v;\r |
2234 | v = v.replace(/.*\.([a-z0-9_\-]+).*/i, '$1');\r |
2235 | \r |
2236 | // Filter classes\r |
2237 | if (f && !(v = f(v, ov)))\r |
2238 | return;\r |
2239 | \r |
2240 | if (!lo[v]) {\r |
2241 | cl.push({'class' : v});\r |
2242 | lo[v] = 1;\r |
2243 | }\r |
2244 | });\r |
2245 | }\r |
2246 | break;\r |
2247 | \r |
2248 | // Import\r |
2249 | case 3:\r |
2250 | addClasses(r.styleSheet);\r |
2251 | break;\r |
2252 | }\r |
2253 | });\r |
2254 | };\r |
2255 | \r |
2256 | try {\r |
2257 | each(t.doc.styleSheets, addClasses);\r |
2258 | } catch (ex) {\r |
2259 | // Ignore\r |
2260 | }\r |
2261 | \r |
2262 | if (cl.length > 0)\r |
2263 | t.classes = cl;\r |
2264 | \r |
2265 | return cl;\r |
2266 | },\r |
2267 | \r |
2268 | run : function(e, f, s) {\r |
2269 | var t = this, o;\r |
2270 | \r |
2271 | if (t.doc && typeof(e) === 'string')\r |
2272 | e = t.get(e);\r |
2273 | \r |
2274 | if (!e)\r |
2275 | return false;\r |
2276 | \r |
2277 | s = s || this;\r |
2278 | if (!e.nodeType && (e.length || e.length === 0)) {\r |
2279 | o = [];\r |
2280 | \r |
2281 | each(e, function(e, i) {\r |
2282 | if (e) {\r |
2283 | if (typeof(e) == 'string')\r |
2284 | e = t.doc.getElementById(e);\r |
2285 | \r |
2286 | o.push(f.call(s, e, i));\r |
2287 | }\r |
2288 | });\r |
2289 | \r |
2290 | return o;\r |
2291 | }\r |
2292 | \r |
2293 | return f.call(s, e);\r |
2294 | },\r |
2295 | \r |
2296 | getAttribs : function(n) {\r |
2297 | var o;\r |
2298 | \r |
2299 | n = this.get(n);\r |
2300 | \r |
2301 | if (!n)\r |
2302 | return [];\r |
2303 | \r |
2304 | if (isIE) {\r |
2305 | o = [];\r |
2306 | \r |
2307 | // Object will throw exception in IE\r |
2308 | if (n.nodeName == 'OBJECT')\r |
2309 | return n.attributes;\r |
2310 | \r |
2311 | // IE doesn't keep the selected attribute if you clone option elements\r |
2312 | if (n.nodeName === 'OPTION' && this.getAttrib(n, 'selected'))\r |
2313 | o.push({specified : 1, nodeName : 'selected'});\r |
2314 | \r |
2315 | // It's crazy that this is faster in IE but it's because it returns all attributes all the time\r |
2316 | n.cloneNode(false).outerHTML.replace(/<\/?[\w:]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=\w+|>/gi, '').replace(/[\w:]+/gi, function(a) {\r |
2317 | o.push({specified : 1, nodeName : a});\r |
2318 | });\r |
2319 | \r |
2320 | return o;\r |
2321 | }\r |
2322 | \r |
2323 | return n.attributes;\r |
2324 | },\r |
2325 | \r |
2326 | destroy : function(s) {\r |
2327 | var t = this;\r |
2328 | \r |
2329 | if (t.events)\r |
2330 | t.events.destroy();\r |
2331 | \r |
2332 | t.win = t.doc = t.root = t.events = null;\r |
2333 | \r |
2334 | // Manual destroy then remove unload handler\r |
2335 | if (!s)\r |
2336 | tinymce.removeUnload(t.destroy);\r |
2337 | },\r |
2338 | \r |
2339 | createRng : function() {\r |
2340 | var d = this.doc;\r |
2341 | \r |
2342 | return d.createRange ? d.createRange() : new tinymce.dom.Range(this);\r |
2343 | },\r |
2344 | \r |
2345 | split : function(pe, e, re) {\r |
2346 | var t = this, r = t.createRng(), bef, aft, pa;\r |
2347 | \r |
2348 | // W3C valid browsers tend to leave empty nodes to the left/right side of the contents, this makes sence\r |
2349 | // but we don't want that in our code since it serves no purpose\r |
2350 | // For example if this is chopped:\r |
2351 | // <p>text 1<span><b>CHOP</b></span>text 2</p>\r |
2352 | // would produce:\r |
2353 | // <p>text 1<span></span></p><b>CHOP</b><p><span></span>text 2</p>\r |
2354 | // this function will then trim of empty edges and produce:\r |
2355 | // <p>text 1</p><b>CHOP</b><p>text 2</p>\r |
2356 | function trimEdge(n, na) {\r |
2357 | n = n[na];\r |
2358 | \r |
2359 | if (n && n[na] && n[na].nodeType == 1 && isEmpty(n[na]))\r |
2360 | t.remove(n[na]);\r |
2361 | };\r |
2362 | \r |
2363 | function isEmpty(n) {\r |
2364 | n = t.getOuterHTML(n);\r |
2365 | n = n.replace(/<(img|hr|table)/gi, '-'); // Keep these convert them to - chars\r |
2366 | n = n.replace(/<[^>]+>/g, ''); // Remove all tags\r |
2367 | \r |
2368 | return n.replace(/[ \t\r\n]+| | /g, '') == '';\r |
2369 | };\r |
2370 | \r |
2371 | // Added until Gecko can create real HTML documents using implementation.createHTMLDocument\r |
2372 | // this is to future proof it if Gecko decides to implement the error checking for range methods.\r |
2373 | function nodeIndex(n) {\r |
2374 | var i = 0;\r |
2375 | \r |
2376 | while (n.previousSibling) {\r |
2377 | i++;\r |
2378 | n = n.previousSibling;\r |
2379 | }\r |
2380 | \r |
2381 | return i;\r |
2382 | };\r |
2383 | \r |
2384 | if (pe && e) {\r |
2385 | // Get before chunk\r |
2386 | r.setStart(pe.parentNode, nodeIndex(pe));\r |
2387 | r.setEnd(e.parentNode, nodeIndex(e));\r |
2388 | bef = r.extractContents();\r |
2389 | \r |
2390 | // Get after chunk\r |
2391 | r = t.createRng();\r |
2392 | r.setStart(e.parentNode, nodeIndex(e) + 1);\r |
2393 | r.setEnd(pe.parentNode, nodeIndex(pe) + 1);\r |
2394 | aft = r.extractContents();\r |
2395 | \r |
2396 | // Insert chunks and remove parent\r |
2397 | pa = pe.parentNode;\r |
2398 | \r |
2399 | // Remove right side edge of the before contents\r |
2400 | trimEdge(bef, 'lastChild');\r |
2401 | \r |
2402 | if (!isEmpty(bef))\r |
2403 | pa.insertBefore(bef, pe);\r |
2404 | \r |
2405 | if (re)\r |
2406 | pa.replaceChild(re, e);\r |
2407 | else\r |
2408 | pa.insertBefore(e, pe);\r |
2409 | \r |
2410 | // Remove left site edge of the after contents\r |
2411 | trimEdge(aft, 'firstChild');\r |
2412 | \r |
2413 | if (!isEmpty(aft))\r |
2414 | pa.insertBefore(aft, pe);\r |
2415 | \r |
2416 | t.remove(pe);\r |
2417 | \r |
2418 | return re || e;\r |
2419 | }\r |
2420 | },\r |
2421 | \r |
2422 | bind : function(target, name, func, scope) {\r |
2423 | var t = this;\r |
2424 | \r |
2425 | if (!t.events)\r |
2426 | t.events = new tinymce.dom.EventUtils();\r |
2427 | \r |
2428 | return t.events.add(target, name, func, scope || this);\r |
2429 | },\r |
2430 | \r |
2431 | unbind : function(target, name, func) {\r |
2432 | var t = this;\r |
2433 | \r |
2434 | if (!t.events)\r |
2435 | t.events = new tinymce.dom.EventUtils();\r |
2436 | \r |
2437 | return t.events.remove(target, name, func);\r |
2438 | },\r |
2439 | \r |
2440 | _findSib : function(node, selector, name) {\r |
2441 | var t = this, f = selector;\r |
2442 | \r |
2443 | if (node) {\r |
2444 | // If expression make a function of it using is\r |
2445 | if (is(f, 'string')) {\r |
2446 | f = function(node) {\r |
2447 | return t.is(node, selector);\r |
2448 | };\r |
2449 | }\r |
2450 | \r |
2451 | // Loop all siblings\r |
2452 | for (node = node[name]; node; node = node[name]) {\r |
2453 | if (f(node))\r |
2454 | return node;\r |
2455 | }\r |
2456 | }\r |
2457 | \r |
2458 | return null;\r |
2459 | },\r |
2460 | \r |
2461 | _isRes : function(c) {\r |
2462 | // Is live resizble element\r |
2463 | return /^(top|left|bottom|right|width|height)/i.test(c) || /;\s*(top|left|bottom|right|width|height)/i.test(c);\r |
2464 | }\r |
2465 | \r |
2466 | /*\r |
2467 | walk : function(n, f, s) {\r |
2468 | var d = this.doc, w;\r |
2469 | \r |
2470 | if (d.createTreeWalker) {\r |
2471 | w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);\r |
2472 | \r |
2473 | while ((n = w.nextNode()) != null)\r |
2474 | f.call(s || this, n);\r |
2475 | } else\r |
2476 | tinymce.walk(n, f, 'childNodes', s);\r |
2477 | }\r |
2478 | */\r |
2479 | \r |
2480 | /*\r |
2481 | toRGB : function(s) {\r |
2482 | var c = /^\s*?#([0-9A-F]{2})([0-9A-F]{1,2})([0-9A-F]{2})?\s*?$/.exec(s);\r |
2483 | \r |
2484 | if (c) {\r |
2485 | // #FFF -> #FFFFFF\r |
2486 | if (!is(c[3]))\r |
2487 | c[3] = c[2] = c[1];\r |
2488 | \r |
2489 | return "rgb(" + parseInt(c[1], 16) + "," + parseInt(c[2], 16) + "," + parseInt(c[3], 16) + ")";\r |
2490 | }\r |
2491 | \r |
2492 | return s;\r |
2493 | }\r |
2494 | */\r |
2495 | });\r |
2496 | \r |
2497 | tinymce.DOM = new tinymce.dom.DOMUtils(document, {process_html : 0});\r |
2498 | })(tinymce);\r |
2499 | \r |
2500 | (function(ns) {\r |
2501 | // Traverse constants\r |
2502 | var EXTRACT = 0, CLONE = 1, DELETE = 2, extend = tinymce.extend;\r |
2503 | \r |
2504 | function indexOf(child, parent) {\r |
2505 | var i, node;\r |
2506 | \r |
2507 | if (child.parentNode != parent)\r |
2508 | return -1;\r |
2509 | \r |
2510 | for (node = parent.firstChild, i = 0; node != child; node = node.nextSibling)\r |
2511 | i++;\r |
2512 | \r |
2513 | return i;\r |
2514 | };\r |
2515 | \r |
2516 | function nodeIndex(n) {\r |
2517 | var i = 0;\r |
2518 | \r |
2519 | while (n.previousSibling) {\r |
2520 | i++;\r |
2521 | n = n.previousSibling;\r |
2522 | }\r |
2523 | \r |
2524 | return i;\r |
2525 | };\r |
2526 | \r |
2527 | function getSelectedNode(container, offset) {\r |
2528 | var child;\r |
2529 | \r |
2530 | if (container.nodeType == 3 /* TEXT_NODE */)\r |
2531 | return container;\r |
2532 | \r |
2533 | if (offset < 0)\r |
2534 | return container;\r |
2535 | \r |
2536 | child = container.firstChild;\r |
2537 | while (child != null && offset > 0) {\r |
2538 | --offset;\r |
2539 | child = child.nextSibling;\r |
2540 | }\r |
2541 | \r |
2542 | if (child != null)\r |
2543 | return child;\r |
2544 | \r |
2545 | return container;\r |
2546 | };\r |
2547 | \r |
2548 | // Range constructor\r |
2549 | function Range(dom) {\r |
2550 | var d = dom.doc;\r |
2551 | \r |
2552 | extend(this, {\r |
2553 | dom : dom,\r |
2554 | \r |
2555 | // Inital states\r |
2556 | startContainer : d,\r |
2557 | startOffset : 0,\r |
2558 | endContainer : d,\r |
2559 | endOffset : 0,\r |
2560 | collapsed : true,\r |
2561 | commonAncestorContainer : d,\r |
2562 | \r |
2563 | // Range constants\r |
2564 | START_TO_START : 0,\r |
2565 | START_TO_END : 1,\r |
2566 | END_TO_END : 2,\r |
2567 | END_TO_START : 3\r |
2568 | });\r |
2569 | };\r |
2570 | \r |
2571 | // Add range methods\r |
2572 | extend(Range.prototype, {\r |
2573 | setStart : function(n, o) {\r |
2574 | this._setEndPoint(true, n, o);\r |
2575 | },\r |
2576 | \r |
2577 | setEnd : function(n, o) {\r |
2578 | this._setEndPoint(false, n, o);\r |
2579 | },\r |
2580 | \r |
2581 | setStartBefore : function(n) {\r |
2582 | this.setStart(n.parentNode, nodeIndex(n));\r |
2583 | },\r |
2584 | \r |
2585 | setStartAfter : function(n) {\r |
2586 | this.setStart(n.parentNode, nodeIndex(n) + 1);\r |
2587 | },\r |
2588 | \r |
2589 | setEndBefore : function(n) {\r |
2590 | this.setEnd(n.parentNode, nodeIndex(n));\r |
2591 | },\r |
2592 | \r |
2593 | setEndAfter : function(n) {\r |
2594 | this.setEnd(n.parentNode, nodeIndex(n) + 1);\r |
2595 | },\r |
2596 | \r |
2597 | collapse : function(ts) {\r |
2598 | var t = this;\r |
2599 | \r |
2600 | if (ts) {\r |
2601 | t.endContainer = t.startContainer;\r |
2602 | t.endOffset = t.startOffset;\r |
2603 | } else {\r |
2604 | t.startContainer = t.endContainer;\r |
2605 | t.startOffset = t.endOffset;\r |
2606 | }\r |
2607 | \r |
2608 | t.collapsed = true;\r |
2609 | },\r |
2610 | \r |
2611 | selectNode : function(n) {\r |
2612 | this.setStartBefore(n);\r |
2613 | this.setEndAfter(n);\r |
2614 | },\r |
2615 | \r |
2616 | selectNodeContents : function(n) {\r |
2617 | this.setStart(n, 0);\r |
2618 | this.setEnd(n, n.nodeType === 1 ? n.childNodes.length : n.nodeValue.length);\r |
2619 | },\r |
2620 | \r |
2621 | compareBoundaryPoints : function(h, r) {\r |
2622 | var t = this, sc = t.startContainer, so = t.startOffset, ec = t.endContainer, eo = t.endOffset;\r |
2623 | \r |
2624 | // Check START_TO_START\r |
2625 | if (h === 0)\r |
2626 | return t._compareBoundaryPoints(sc, so, sc, so);\r |
2627 | \r |
2628 | // Check START_TO_END\r |
2629 | if (h === 1)\r |
2630 | return t._compareBoundaryPoints(sc, so, ec, eo);\r |
2631 | \r |
2632 | // Check END_TO_END\r |
2633 | if (h === 2)\r |
2634 | return t._compareBoundaryPoints(ec, eo, ec, eo);\r |
2635 | \r |
2636 | // Check END_TO_START\r |
2637 | if (h === 3)\r |
2638 | return t._compareBoundaryPoints(ec, eo, sc, so);\r |
2639 | },\r |
2640 | \r |
2641 | deleteContents : function() {\r |
2642 | this._traverse(DELETE);\r |
2643 | },\r |
2644 | \r |
2645 | extractContents : function() {\r |
2646 | return this._traverse(EXTRACT);\r |
2647 | },\r |
2648 | \r |
2649 | cloneContents : function() {\r |
2650 | return this._traverse(CLONE);\r |
2651 | },\r |
2652 | \r |
2653 | insertNode : function(n) {\r |
2654 | var t = this, nn, o;\r |
2655 | \r |
2656 | // Node is TEXT_NODE or CDATA\r |
2657 | if (n.nodeType === 3 || n.nodeType === 4) {\r |
2658 | nn = t.startContainer.splitText(t.startOffset);\r |
2659 | t.startContainer.parentNode.insertBefore(n, nn);\r |
2660 | } else {\r |
2661 | // Insert element node\r |
2662 | if (t.startContainer.childNodes.length > 0)\r |
2663 | o = t.startContainer.childNodes[t.startOffset];\r |
2664 | \r |
2665 | t.startContainer.insertBefore(n, o);\r |
2666 | }\r |
2667 | },\r |
2668 | \r |
2669 | surroundContents : function(n) {\r |
2670 | var t = this, f = t.extractContents();\r |
2671 | \r |
2672 | t.insertNode(n);\r |
2673 | n.appendChild(f);\r |
2674 | t.selectNode(n);\r |
2675 | },\r |
2676 | \r |
2677 | cloneRange : function() {\r |
2678 | var t = this;\r |
2679 | \r |
2680 | return extend(new Range(t.dom), {\r |
2681 | startContainer : t.startContainer,\r |
2682 | startOffset : t.startOffset,\r |
2683 | endContainer : t.endContainer,\r |
2684 | endOffset : t.endOffset,\r |
2685 | collapsed : t.collapsed,\r |
2686 | commonAncestorContainer : t.commonAncestorContainer\r |
2687 | });\r |
2688 | },\r |
2689 | \r |
2690 | /*\r |
2691 | detach : function() {\r |
2692 | // Not implemented\r |
2693 | },\r |
2694 | */\r |
2695 | // Internal methods\r |
2696 | \r |
2697 | _isCollapsed : function() {\r |
2698 | return (this.startContainer == this.endContainer && this.startOffset == this.endOffset);\r |
2699 | },\r |
2700 | \r |
2701 | _compareBoundaryPoints : function (containerA, offsetA, containerB, offsetB) {\r |
2702 | var c, offsetC, n, cmnRoot, childA, childB;\r |
2703 | \r |
2704 | // In the first case the boundary-points have the same container. A is before B \r |
2705 | // if its offset is less than the offset of B, A is equal to B if its offset is \r |
2706 | // equal to the offset of B, and A is after B if its offset is greater than the \r |
2707 | // offset of B.\r |
2708 | if (containerA == containerB) {\r |
2709 | if (offsetA == offsetB) {\r |
2710 | return 0; // equal\r |
2711 | } else if (offsetA < offsetB) {\r |
2712 | return -1; // before\r |
2713 | } else {\r |
2714 | return 1; // after\r |
2715 | }\r |
2716 | }\r |
2717 | \r |
2718 | // In the second case a child node C of the container of A is an ancestor \r |
2719 | // container of B. In this case, A is before B if the offset of A is less than or \r |
2720 | // equal to the index of the child node C and A is after B otherwise.\r |
2721 | c = containerB;\r |
2722 | while (c && c.parentNode != containerA) {\r |
2723 | c = c.parentNode;\r |
2724 | }\r |
2725 | if (c) {\r |
2726 | offsetC = 0;\r |
2727 | n = containerA.firstChild;\r |
2728 | \r |
2729 | while (n != c && offsetC < offsetA) {\r |
2730 | offsetC++;\r |
2731 | n = n.nextSibling;\r |
2732 | }\r |
2733 | \r |
2734 | if (offsetA <= offsetC) {\r |
2735 | return -1; // before\r |
2736 | } else {\r |
2737 | return 1; // after\r |
2738 | }\r |
2739 | }\r |
2740 | \r |
2741 | // In the third case a child node C of the container of B is an ancestor container \r |
2742 | // of A. In this case, A is before B if the index of the child node C is less than \r |
2743 | // the offset of B and A is after B otherwise.\r |
2744 | c = containerA;\r |
2745 | while (c && c.parentNode != containerB) {\r |
2746 | c = c.parentNode;\r |
2747 | }\r |
2748 | \r |
2749 | if (c) {\r |
2750 | offsetC = 0;\r |
2751 | n = containerB.firstChild;\r |
2752 | \r |
2753 | while (n != c && offsetC < offsetB) {\r |
2754 | offsetC++;\r |
2755 | n = n.nextSibling;\r |
2756 | }\r |
2757 | \r |
2758 | if (offsetC < offsetB) {\r |
2759 | return -1; // before\r |
2760 | } else {\r |
2761 | return 1; // after\r |
2762 | }\r |
2763 | }\r |
2764 | \r |
2765 | // In the fourth case, none of three other cases hold: the containers of A and B \r |
2766 | // are siblings or descendants of sibling nodes. In this case, A is before B if \r |
2767 | // the container of A is before the container of B in a pre-order traversal of the\r |
2768 | // Ranges' context tree and A is after B otherwise.\r |
2769 | cmnRoot = this.dom.findCommonAncestor(containerA, containerB);\r |
2770 | childA = containerA;\r |
2771 | \r |
2772 | while (childA && childA.parentNode != cmnRoot) {\r |
2773 | childA = childA.parentNode; \r |
2774 | }\r |
2775 | \r |
2776 | if (!childA) {\r |
2777 | childA = cmnRoot;\r |
2778 | }\r |
2779 | \r |
2780 | childB = containerB;\r |
2781 | while (childB && childB.parentNode != cmnRoot) {\r |
2782 | childB = childB.parentNode;\r |
2783 | }\r |
2784 | \r |
2785 | if (!childB) {\r |
2786 | childB = cmnRoot;\r |
2787 | }\r |
2788 | \r |
2789 | if (childA == childB) {\r |
2790 | return 0; // equal\r |
2791 | }\r |
2792 | \r |
2793 | n = cmnRoot.firstChild;\r |
2794 | while (n) {\r |
2795 | if (n == childA) {\r |
2796 | return -1; // before\r |
2797 | }\r |
2798 | \r |
2799 | if (n == childB) {\r |
2800 | return 1; // after\r |
2801 | }\r |
2802 | \r |
2803 | n = n.nextSibling;\r |
2804 | }\r |
2805 | },\r |
2806 | \r |
2807 | _setEndPoint : function(st, n, o) {\r |
2808 | var t = this, ec, sc;\r |
2809 | \r |
2810 | if (st) {\r |
2811 | t.startContainer = n;\r |
2812 | t.startOffset = o;\r |
2813 | } else {\r |
2814 | t.endContainer = n;\r |
2815 | t.endOffset = o;\r |
2816 | }\r |
2817 | \r |
2818 | // If one boundary-point of a Range is set to have a root container \r |
2819 | // other than the current one for the Range, the Range is collapsed to \r |
2820 | // the new position. This enforces the restriction that both boundary-\r |
2821 | // points of a Range must have the same root container.\r |
2822 | ec = t.endContainer;\r |
2823 | while (ec.parentNode)\r |
2824 | ec = ec.parentNode;\r |
2825 | \r |
2826 | sc = t.startContainer;\r |
2827 | while (sc.parentNode)\r |
2828 | sc = sc.parentNode;\r |
2829 | \r |
2830 | if (sc != ec) {\r |
2831 | t.collapse(st);\r |
2832 | } else {\r |
2833 | // The start position of a Range is guaranteed to never be after the \r |
2834 | // end position. To enforce this restriction, if the start is set to \r |
2835 | // be at a position after the end, the Range is collapsed to that \r |
2836 | // position.\r |
2837 | if (t._compareBoundaryPoints(t.startContainer, t.startOffset, t.endContainer, t.endOffset) > 0)\r |
2838 | t.collapse(st);\r |
2839 | }\r |
2840 | \r |
2841 | t.collapsed = t._isCollapsed();\r |
2842 | t.commonAncestorContainer = t.dom.findCommonAncestor(t.startContainer, t.endContainer);\r |
2843 | },\r |
2844 | \r |
2845 | // This code is heavily "inspired" by the Apache Xerces implementation. I hope they don't mind. :)\r |
2846 | \r |
2847 | _traverse : function(how) {\r |
2848 | var t = this, c, endContainerDepth = 0, startContainerDepth = 0, p, depthDiff, startNode, endNode, sp, ep;\r |
2849 | \r |
2850 | if (t.startContainer == t.endContainer)\r |
2851 | return t._traverseSameContainer(how);\r |
2852 | \r |
2853 | for (c = t.endContainer, p = c.parentNode; p != null; c = p, p = p.parentNode) {\r |
2854 | if (p == t.startContainer)\r |
2855 | return t._traverseCommonStartContainer(c, how);\r |
2856 | \r |
2857 | ++endContainerDepth;\r |
2858 | }\r |
2859 | \r |
2860 | for (c = t.startContainer, p = c.parentNode; p != null; c = p, p = p.parentNode) {\r |
2861 | if (p == t.endContainer)\r |
2862 | return t._traverseCommonEndContainer(c, how);\r |
2863 | \r |
2864 | ++startContainerDepth;\r |
2865 | }\r |
2866 | \r |
2867 | depthDiff = startContainerDepth - endContainerDepth;\r |
2868 | \r |
2869 | startNode = t.startContainer;\r |
2870 | while (depthDiff > 0) {\r |
2871 | startNode = startNode.parentNode;\r |
2872 | depthDiff--;\r |
2873 | }\r |
2874 | \r |
2875 | endNode = t.endContainer;\r |
2876 | while (depthDiff < 0) {\r |
2877 | endNode = endNode.parentNode;\r |
2878 | depthDiff++;\r |
2879 | }\r |
2880 | \r |
2881 | // ascend the ancestor hierarchy until we have a common parent.\r |
2882 | for (sp = startNode.parentNode, ep = endNode.parentNode; sp != ep; sp = sp.parentNode, ep = ep.parentNode) {\r |
2883 | startNode = sp;\r |
2884 | endNode = ep;\r |
2885 | }\r |
2886 | \r |
2887 | return t._traverseCommonAncestors(startNode, endNode, how);\r |
2888 | },\r |
2889 | \r |
2890 | _traverseSameContainer : function(how) {\r |
2891 | var t = this, frag, s, sub, n, cnt, sibling, xferNode;\r |
2892 | \r |
2893 | if (how != DELETE)\r |
2894 | frag = t.dom.doc.createDocumentFragment();\r |
2895 | \r |
2896 | // If selection is empty, just return the fragment\r |
2897 | if (t.startOffset == t.endOffset)\r |
2898 | return frag;\r |
2899 | \r |
2900 | // Text node needs special case handling\r |
2901 | if (t.startContainer.nodeType == 3 /* TEXT_NODE */) {\r |
2902 | // get the substring\r |
2903 | s = t.startContainer.nodeValue;\r |
2904 | sub = s.substring(t.startOffset, t.endOffset);\r |
2905 | \r |
2906 | // set the original text node to its new value\r |
2907 | if (how != CLONE) {\r |
2908 | t.startContainer.deleteData(t.startOffset, t.endOffset - t.startOffset);\r |
2909 | \r |
2910 | // Nothing is partially selected, so collapse to start point\r |
2911 | t.collapse(true);\r |
2912 | }\r |
2913 | \r |
2914 | if (how == DELETE)\r |
2915 | return null;\r |
2916 | \r |
2917 | frag.appendChild(t.dom.doc.createTextNode(sub));\r |
2918 | return frag;\r |
2919 | }\r |
2920 | \r |
2921 | // Copy nodes between the start/end offsets.\r |
2922 | n = getSelectedNode(t.startContainer, t.startOffset);\r |
2923 | cnt = t.endOffset - t.startOffset;\r |
2924 | \r |
2925 | while (cnt > 0) {\r |
2926 | sibling = n.nextSibling;\r |
2927 | xferNode = t._traverseFullySelected(n, how);\r |
2928 | \r |
2929 | if (frag)\r |
2930 | frag.appendChild( xferNode );\r |
2931 | \r |
2932 | --cnt;\r |
2933 | n = sibling;\r |
2934 | }\r |
2935 | \r |
2936 | // Nothing is partially selected, so collapse to start point\r |
2937 | if (how != CLONE)\r |
2938 | t.collapse(true);\r |
2939 | \r |
2940 | return frag;\r |
2941 | },\r |
2942 | \r |
2943 | _traverseCommonStartContainer : function(endAncestor, how) {\r |
2944 | var t = this, frag, n, endIdx, cnt, sibling, xferNode;\r |
2945 | \r |
2946 | if (how != DELETE)\r |
2947 | frag = t.dom.doc.createDocumentFragment();\r |
2948 | \r |
2949 | n = t._traverseRightBoundary(endAncestor, how);\r |
2950 | \r |
2951 | if (frag)\r |
2952 | frag.appendChild(n);\r |
2953 | \r |
2954 | endIdx = indexOf(endAncestor, t.startContainer);\r |
2955 | cnt = endIdx - t.startOffset;\r |
2956 | \r |
2957 | if (cnt <= 0) {\r |
2958 | // Collapse to just before the endAncestor, which \r |
2959 | // is partially selected.\r |
2960 | if (how != CLONE) {\r |
2961 | t.setEndBefore(endAncestor);\r |
2962 | t.collapse(false);\r |
2963 | }\r |
2964 | \r |
2965 | return frag;\r |
2966 | }\r |
2967 | \r |
2968 | n = endAncestor.previousSibling;\r |
2969 | while (cnt > 0) {\r |
2970 | sibling = n.previousSibling;\r |
2971 | xferNode = t._traverseFullySelected(n, how);\r |
2972 | \r |
2973 | if (frag)\r |
2974 | frag.insertBefore(xferNode, frag.firstChild);\r |
2975 | \r |
2976 | --cnt;\r |
2977 | n = sibling;\r |
2978 | }\r |
2979 | \r |
2980 | // Collapse to just before the endAncestor, which \r |
2981 | // is partially selected.\r |
2982 | if (how != CLONE) {\r |
2983 | t.setEndBefore(endAncestor);\r |
2984 | t.collapse(false);\r |
2985 | }\r |
2986 | \r |
2987 | return frag;\r |
2988 | },\r |
2989 | \r |
2990 | _traverseCommonEndContainer : function(startAncestor, how) {\r |
2991 | var t = this, frag, startIdx, n, cnt, sibling, xferNode;\r |
2992 | \r |
2993 | if (how != DELETE)\r |
2994 | frag = t.dom.doc.createDocumentFragment();\r |
2995 | \r |
2996 | n = t._traverseLeftBoundary(startAncestor, how);\r |
2997 | if (frag)\r |
2998 | frag.appendChild(n);\r |
2999 | \r |
3000 | startIdx = indexOf(startAncestor, t.endContainer);\r |
3001 | ++startIdx; // Because we already traversed it....\r |
3002 | \r |
3003 | cnt = t.endOffset - startIdx;\r |
3004 | n = startAncestor.nextSibling;\r |
3005 | while (cnt > 0) {\r |
3006 | sibling = n.nextSibling;\r |
3007 | xferNode = t._traverseFullySelected(n, how);\r |
3008 | \r |
3009 | if (frag)\r |
3010 | frag.appendChild(xferNode);\r |
3011 | \r |
3012 | --cnt;\r |
3013 | n = sibling;\r |
3014 | }\r |
3015 | \r |
3016 | if (how != CLONE) {\r |
3017 | t.setStartAfter(startAncestor);\r |
3018 | t.collapse(true);\r |
3019 | }\r |
3020 | \r |
3021 | return frag;\r |
3022 | },\r |
3023 | \r |
3024 | _traverseCommonAncestors : function(startAncestor, endAncestor, how) {\r |
3025 | var t = this, n, frag, commonParent, startOffset, endOffset, cnt, sibling, nextSibling;\r |
3026 | \r |
3027 | if (how != DELETE)\r |
3028 | frag = t.dom.doc.createDocumentFragment();\r |
3029 | \r |
3030 | n = t._traverseLeftBoundary(startAncestor, how);\r |
3031 | if (frag)\r |
3032 | frag.appendChild(n);\r |
3033 | \r |
3034 | commonParent = startAncestor.parentNode;\r |
3035 | startOffset = indexOf(startAncestor, commonParent);\r |
3036 | endOffset = indexOf(endAncestor, commonParent);\r |
3037 | ++startOffset;\r |
3038 | \r |
3039 | cnt = endOffset - startOffset;\r |
3040 | sibling = startAncestor.nextSibling;\r |
3041 | \r |
3042 | while (cnt > 0) {\r |
3043 | nextSibling = sibling.nextSibling;\r |
3044 | n = t._traverseFullySelected(sibling, how);\r |
3045 | \r |
3046 | if (frag)\r |
3047 | frag.appendChild(n);\r |
3048 | \r |
3049 | sibling = nextSibling;\r |
3050 | --cnt;\r |
3051 | }\r |
3052 | \r |
3053 | n = t._traverseRightBoundary(endAncestor, how);\r |
3054 | \r |
3055 | if (frag)\r |
3056 | frag.appendChild(n);\r |
3057 | \r |
3058 | if (how != CLONE) {\r |
3059 | t.setStartAfter(startAncestor);\r |
3060 | t.collapse(true);\r |
3061 | }\r |
3062 | \r |
3063 | return frag;\r |
3064 | },\r |
3065 | \r |
3066 | _traverseRightBoundary : function(root, how) {\r |
3067 | var t = this, next = getSelectedNode(t.endContainer, t.endOffset - 1), parent, clonedParent, prevSibling, clonedChild, clonedGrandParent;\r |
3068 | var isFullySelected = next != t.endContainer;\r |
3069 | \r |
3070 | if (next == root)\r |
3071 | return t._traverseNode(next, isFullySelected, false, how);\r |
3072 | \r |
3073 | parent = next.parentNode;\r |
3074 | clonedParent = t._traverseNode(parent, false, false, how);\r |
3075 | \r |
3076 | while (parent != null) {\r |
3077 | while (next != null) {\r |
3078 | prevSibling = next.previousSibling;\r |
3079 | clonedChild = t._traverseNode(next, isFullySelected, false, how);\r |
3080 | \r |
3081 | if (how != DELETE)\r |
3082 | clonedParent.insertBefore(clonedChild, clonedParent.firstChild);\r |
3083 | \r |
3084 | isFullySelected = true;\r |
3085 | next = prevSibling;\r |
3086 | }\r |
3087 | \r |
3088 | if (parent == root)\r |
3089 | return clonedParent;\r |
3090 | \r |
3091 | next = parent.previousSibling;\r |
3092 | parent = parent.parentNode;\r |
3093 | \r |
3094 | clonedGrandParent = t._traverseNode(parent, false, false, how);\r |
3095 | \r |
3096 | if (how != DELETE)\r |
3097 | clonedGrandParent.appendChild(clonedParent);\r |
3098 | \r |
3099 | clonedParent = clonedGrandParent;\r |
3100 | }\r |
3101 | \r |
3102 | // should never occur\r |
3103 | return null;\r |
3104 | },\r |
3105 | \r |
3106 | _traverseLeftBoundary : function(root, how) {\r |
3107 | var t = this, next = getSelectedNode(t.startContainer, t.startOffset);\r |
3108 | var isFullySelected = next != t.startContainer, parent, clonedParent, nextSibling, clonedChild, clonedGrandParent;\r |
3109 | \r |
3110 | if (next == root)\r |
3111 | return t._traverseNode(next, isFullySelected, true, how);\r |
3112 | \r |
3113 | parent = next.parentNode;\r |
3114 | clonedParent = t._traverseNode(parent, false, true, how);\r |
3115 | \r |
3116 | while (parent != null) {\r |
3117 | while (next != null) {\r |
3118 | nextSibling = next.nextSibling;\r |
3119 | clonedChild = t._traverseNode(next, isFullySelected, true, how);\r |
3120 | \r |
3121 | if (how != DELETE)\r |
3122 | clonedParent.appendChild(clonedChild);\r |
3123 | \r |
3124 | isFullySelected = true;\r |
3125 | next = nextSibling;\r |
3126 | }\r |
3127 | \r |
3128 | if (parent == root)\r |
3129 | return clonedParent;\r |
3130 | \r |
3131 | next = parent.nextSibling;\r |
3132 | parent = parent.parentNode;\r |
3133 | \r |
3134 | clonedGrandParent = t._traverseNode(parent, false, true, how);\r |
3135 | \r |
3136 | if (how != DELETE)\r |
3137 | clonedGrandParent.appendChild(clonedParent);\r |
3138 | \r |
3139 | clonedParent = clonedGrandParent;\r |
3140 | }\r |
3141 | \r |
3142 | // should never occur\r |
3143 | return null;\r |
3144 | },\r |
3145 | \r |
3146 | _traverseNode : function(n, isFullySelected, isLeft, how) {\r |
3147 | var t = this, txtValue, newNodeValue, oldNodeValue, offset, newNode;\r |
3148 | \r |
3149 | if (isFullySelected)\r |
3150 | return t._traverseFullySelected(n, how);\r |
3151 | \r |
3152 | if (n.nodeType == 3 /* TEXT_NODE */) {\r |
3153 | txtValue = n.nodeValue;\r |
3154 | \r |
3155 | if (isLeft) {\r |
3156 | offset = t.startOffset;\r |
3157 | newNodeValue = txtValue.substring(offset);\r |
3158 | oldNodeValue = txtValue.substring(0, offset);\r |
3159 | } else {\r |
3160 | offset = t.endOffset;\r |
3161 | newNodeValue = txtValue.substring(0, offset);\r |
3162 | oldNodeValue = txtValue.substring(offset);\r |
3163 | }\r |
3164 | \r |
3165 | if (how != CLONE)\r |
3166 | n.nodeValue = oldNodeValue;\r |
3167 | \r |
3168 | if (how == DELETE)\r |
3169 | return null;\r |
3170 | \r |
3171 | newNode = n.cloneNode(false);\r |
3172 | newNode.nodeValue = newNodeValue;\r |
3173 | \r |
3174 | return newNode;\r |
3175 | }\r |
3176 | \r |
3177 | if (how == DELETE)\r |
3178 | return null;\r |
3179 | \r |
3180 | return n.cloneNode(false);\r |
3181 | },\r |
3182 | \r |
3183 | _traverseFullySelected : function(n, how) {\r |
3184 | var t = this;\r |
3185 | \r |
3186 | if (how != DELETE)\r |
3187 | return how == CLONE ? n.cloneNode(true) : n;\r |
3188 | \r |
3189 | n.parentNode.removeChild(n);\r |
3190 | return null;\r |
3191 | }\r |
3192 | });\r |
3193 | \r |
3194 | ns.Range = Range;\r |
3195 | })(tinymce.dom);\r |
3196 | (function() {\r |
3197 | function Selection(selection) {\r |
3198 | var t = this, invisibleChar = '\uFEFF', range, lastIERng;\r |
3199 | \r |
3200 | function compareRanges(rng1, rng2) {\r |
3201 | if (rng1 && rng2) {\r |
3202 | // Both are control ranges and the selected element matches\r |
3203 | if (rng1.item && rng2.item && rng1.item(0) === rng2.item(0))\r |
3204 | return 1;\r |
3205 | \r |
3206 | // Both are text ranges and the range matches\r |
3207 | if (rng1.isEqual && rng2.isEqual && rng2.isEqual(rng1))\r |
3208 | return 1;\r |
3209 | }\r |
3210 | \r |
3211 | return 0;\r |
3212 | };\r |
3213 | \r |
3214 | function getRange() {\r |
3215 | var dom = selection.dom, ieRange = selection.getRng(), domRange = dom.createRng(), startPos, endPos, element, sc, ec, collapsed;\r |
3216 | \r |
3217 | function findIndex(element) {\r |
3218 | var nl = element.parentNode.childNodes, i;\r |
3219 | \r |
3220 | for (i = nl.length - 1; i >= 0; i--) {\r |
3221 | if (nl[i] == element)\r |
3222 | return i;\r |
3223 | }\r |
3224 | \r |
3225 | return -1;\r |
3226 | };\r |
3227 | \r |
3228 | function findEndPoint(start) {\r |
3229 | var rng = ieRange.duplicate(), parent, i, nl, n, offset = 0, index = 0, pos, tmpRng;\r |
3230 | \r |
3231 | // Insert marker character\r |
3232 | rng.collapse(start);\r |
3233 | parent = rng.parentElement();\r |
3234 | rng.pasteHTML(invisibleChar); // Needs to be a pasteHTML instead of .text = since IE has a bug with nodeValue\r |
3235 | \r |
3236 | // Find marker character\r |
3237 | nl = parent.childNodes;\r |
3238 | for (i = 0; i < nl.length; i++) {\r |
3239 | n = nl[i];\r |
3240 | \r |
3241 | // Calculate node index excluding text node fragmentation\r |
3242 | if (i > 0 && (n.nodeType !== 3 || nl[i - 1].nodeType !== 3))\r |
3243 | index++;\r |
3244 | \r |
3245 | // If text node then calculate offset\r |
3246 | if (n.nodeType === 3) {\r |
3247 | // Look for marker\r |
3248 | pos = n.nodeValue.indexOf(invisibleChar);\r |
3249 | if (pos !== -1) {\r |
3250 | offset += pos;\r |
3251 | break;\r |
3252 | }\r |
3253 | \r |
3254 | offset += n.nodeValue.length;\r |
3255 | } else\r |
3256 | offset = 0;\r |
3257 | }\r |
3258 | \r |
3259 | // Remove marker character\r |
3260 | rng.moveStart('character', -1);\r |
3261 | rng.text = '';\r |
3262 | \r |
3263 | return {index : index, offset : offset, parent : parent};\r |
3264 | };\r |
3265 | \r |
3266 | // If selection is outside the current document just return an empty range\r |
3267 | element = ieRange.item ? ieRange.item(0) : ieRange.parentElement();\r |
3268 | if (element.ownerDocument != dom.doc)\r |
3269 | return domRange;\r |
3270 | \r |
3271 | // Handle control selection or text selection of a image\r |
3272 | if (ieRange.item || !element.hasChildNodes()) {\r |
3273 | domRange.setStart(element.parentNode, findIndex(element));\r |
3274 | domRange.setEnd(domRange.startContainer, domRange.startOffset + 1);\r |
3275 | \r |
3276 | return domRange;\r |
3277 | }\r |
3278 | \r |
3279 | // Check collapsed state\r |
3280 | collapsed = selection.isCollapsed();\r |
3281 | \r |
3282 | // Find start and end pos index and offset\r |
3283 | startPos = findEndPoint(true);\r |
3284 | endPos = findEndPoint(false);\r |
3285 | \r |
3286 | // Normalize the elements to avoid fragmented dom\r |
3287 | startPos.parent.normalize();\r |
3288 | endPos.parent.normalize();\r |
3289 | \r |
3290 | // Set start container and offset\r |
3291 | sc = startPos.parent.childNodes[Math.min(startPos.index, startPos.parent.childNodes.length - 1)];\r |
3292 | \r |
3293 | if (sc.nodeType != 3)\r |
3294 | domRange.setStart(startPos.parent, startPos.index);\r |
3295 | else\r |
3296 | domRange.setStart(startPos.parent.childNodes[startPos.index], startPos.offset);\r |
3297 | \r |
3298 | // Set end container and offset\r |
3299 | ec = endPos.parent.childNodes[Math.min(endPos.index, endPos.parent.childNodes.length - 1)];\r |
3300 | \r |
3301 | if (ec.nodeType != 3) {\r |
3302 | if (!collapsed)\r |
3303 | endPos.index++;\r |
3304 | \r |
3305 | domRange.setEnd(endPos.parent, endPos.index);\r |
3306 | } else\r |
3307 | domRange.setEnd(endPos.parent.childNodes[endPos.index], endPos.offset);\r |
3308 | \r |
3309 | // If not collapsed then make sure offsets are valid\r |
3310 | if (!collapsed) {\r |
3311 | sc = domRange.startContainer;\r |
3312 | if (sc.nodeType == 1)\r |
3313 | domRange.setStart(sc, Math.min(domRange.startOffset, sc.childNodes.length));\r |
3314 | \r |
3315 | ec = domRange.endContainer;\r |
3316 | if (ec.nodeType == 1)\r |
3317 | domRange.setEnd(ec, Math.min(domRange.endOffset, ec.childNodes.length));\r |
3318 | }\r |
3319 | \r |
3320 | // Restore selection to new range\r |
3321 | t.addRange(domRange);\r |
3322 | \r |
3323 | return domRange;\r |
3324 | };\r |
3325 | \r |
3326 | this.addRange = function(rng) {\r |
3327 | var ieRng, body = selection.dom.doc.body, startPos, endPos, sc, so, ec, eo;\r |
3328 | \r |
3329 | // Setup some shorter versions\r |
3330 | sc = rng.startContainer;\r |
3331 | so = rng.startOffset;\r |
3332 | ec = rng.endContainer;\r |
3333 | eo = rng.endOffset;\r |
3334 | ieRng = body.createTextRange();\r |
3335 | \r |
3336 | // Find element\r |
3337 | sc = sc.nodeType == 1 ? sc.childNodes[Math.min(so, sc.childNodes.length - 1)] : sc;\r |
3338 | ec = ec.nodeType == 1 ? ec.childNodes[Math.min(so == eo ? eo : eo - 1, ec.childNodes.length - 1)] : ec;\r |
3339 | \r |
3340 | // Single element selection\r |
3341 | if (sc == ec && sc.nodeType == 1) {\r |
3342 | // Make control selection for some elements\r |
3343 | if (/^(IMG|TABLE)$/.test(sc.nodeName) && so != eo) {\r |
3344 | ieRng = body.createControlRange();\r |
3345 | ieRng.addElement(sc);\r |
3346 | } else {\r |
3347 | ieRng = body.createTextRange();\r |
3348 | \r |
3349 | // Padd empty elements with invisible character\r |
3350 | if (!sc.hasChildNodes() && sc.canHaveHTML)\r |
3351 | sc.innerHTML = invisibleChar;\r |
3352 | \r |
3353 | // Select element contents\r |
3354 | ieRng.moveToElementText(sc);\r |
3355 | \r |
3356 | // If it's only containing a padding remove it so the caret remains\r |
3357 | if (sc.innerHTML == invisibleChar) {\r |
3358 | ieRng.collapse(true);\r |
3359 | sc.removeChild(sc.firstChild);\r |
3360 | }\r |
3361 | }\r |
3362 | \r |
3363 | if (so == eo)\r |
3364 | ieRng.collapse(eo <= rng.endContainer.childNodes.length - 1);\r |
3365 | \r |
3366 | ieRng.select();\r |
3367 | \r |
3368 | return;\r |
3369 | }\r |
3370 | \r |
3371 | function getCharPos(container, offset) {\r |
3372 | var nodeVal, rng, pos;\r |
3373 | \r |
3374 | if (container.nodeType != 3)\r |
3375 | return -1;\r |
3376 | \r |
3377 | nodeVal = container.nodeValue;\r |
3378 | rng = body.createTextRange();\r |
3379 | \r |
3380 | // Insert marker at offset position\r |
3381 | container.nodeValue = nodeVal.substring(0, offset) + invisibleChar + nodeVal.substring(offset);\r |
3382 | \r |
3383 | // Find char pos of marker and remove it\r |
3384 | rng.moveToElementText(container.parentNode);\r |
3385 | rng.findText(invisibleChar);\r |
3386 | pos = Math.abs(rng.moveStart('character', -0xFFFFF));\r |
3387 | container.nodeValue = nodeVal;\r |
3388 | \r |
3389 | return pos;\r |
3390 | };\r |
3391 | \r |
3392 | // Collapsed range\r |
3393 | if (rng.collapsed) {\r |
3394 | pos = getCharPos(sc, so);\r |
3395 | \r |
3396 | ieRng = body.createTextRange();\r |
3397 | ieRng.move('character', pos);\r |
3398 | ieRng.select();\r |
3399 | \r |
3400 | return;\r |
3401 | } else {\r |
3402 | // If same text container\r |
3403 | if (sc == ec && sc.nodeType == 3) {\r |
3404 | startPos = getCharPos(sc, so);\r |
3405 | \r |
3406 | ieRng = body.createTextRange();\r |
3407 | ieRng.move('character', startPos);\r |
3408 | ieRng.moveEnd('character', eo - so);\r |
3409 | ieRng.select();\r |
3410 | \r |
3411 | return;\r |
3412 | }\r |
3413 | \r |
3414 | // Get caret positions\r |
3415 | startPos = getCharPos(sc, so);\r |
3416 | endPos = getCharPos(ec, eo);\r |
3417 | ieRng = body.createTextRange();\r |
3418 | \r |
3419 | // Move start of range to start character position or start element\r |
3420 | if (startPos == -1) {\r |
3421 | ieRng.moveToElementText(sc);\r |
3422 | startPos = 0;\r |
3423 | } else\r |
3424 | ieRng.move('character', startPos);\r |
3425 | \r |
3426 | // Move end of range to end character position or end element\r |
3427 | tmpRng = body.createTextRange();\r |
3428 | \r |
3429 | if (endPos == -1)\r |
3430 | tmpRng.moveToElementText(ec);\r |
3431 | else\r |
3432 | tmpRng.move('character', endPos);\r |
3433 | \r |
3434 | ieRng.setEndPoint('EndToEnd', tmpRng);\r |
3435 | ieRng.select();\r |
3436 | \r |
3437 | return;\r |
3438 | }\r |
3439 | };\r |
3440 | \r |
3441 | this.getRangeAt = function() {\r |
3442 | // Setup new range if the cache is empty\r |
3443 | if (!range || !compareRanges(lastIERng, selection.getRng())) {\r |
3444 | range = getRange();\r |
3445 | \r |
3446 | // Store away text range for next call\r |
3447 | lastIERng = selection.getRng();\r |
3448 | }\r |
3449 | \r |
3450 | // Return cached range\r |
3451 | return range;\r |
3452 | };\r |
3453 | \r |
3454 | this.destroy = function() {\r |
3455 | // Destroy cached range and last IE range to avoid memory leaks\r |
3456 | lastIERng = range = null;\r |
3457 | };\r |
3458 | };\r |
3459 | \r |
3460 | // Expose the selection object\r |
3461 | tinymce.dom.TridentSelection = Selection;\r |
3462 | })();\r |
3463 | \r |
3464 | /*\r |
3465 | * Sizzle CSS Selector Engine - v1.0\r |
3466 | * Copyright 2009, The Dojo Foundation\r |
3467 | * Released under the MIT, BSD, and GPL Licenses.\r |
3468 | * More information: http://sizzlejs.com/\r |
3469 | */\r |
3470 | (function(){\r |
3471 | \r |
3472 | var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,\r |
3473 | done = 0,\r |
3474 | toString = Object.prototype.toString,\r |
3475 | hasDuplicate = false;\r |
3476 | \r |
3477 | var Sizzle = function(selector, context, results, seed) {\r |
3478 | results = results || [];\r |
3479 | var origContext = context = context || document;\r |
3480 | \r |
3481 | if ( context.nodeType !== 1 && context.nodeType !== 9 ) {\r |
3482 | return [];\r |
3483 | }\r |
3484 | \r |
3485 | if ( !selector || typeof selector !== "string" ) {\r |
3486 | return results;\r |
3487 | }\r |
3488 | \r |
3489 | var parts = [], m, set, checkSet, check, mode, extra, prune = true, contextXML = isXML(context);\r |
3490 | \r |
3491 | // Reset the position of the chunker regexp (start from head)\r |
3492 | chunker.lastIndex = 0;\r |
3493 | \r |
3494 | while ( (m = chunker.exec(selector)) !== null ) {\r |
3495 | parts.push( m[1] );\r |
3496 | \r |
3497 | if ( m[2] ) {\r |
3498 | extra = RegExp.rightContext;\r |
3499 | break;\r |
3500 | }\r |
3501 | }\r |
3502 | \r |
3503 | if ( parts.length > 1 && origPOS.exec( selector ) ) {\r |
3504 | if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\r |
3505 | set = posProcess( parts[0] + parts[1], context );\r |
3506 | } else {\r |
3507 | set = Expr.relative[ parts[0] ] ?\r |
3508 | [ context ] :\r |
3509 | Sizzle( parts.shift(), context );\r |
3510 | \r |
3511 | while ( parts.length ) {\r |
3512 | selector = parts.shift();\r |
3513 | \r |
3514 | if ( Expr.relative[ selector ] )\r |
3515 | selector += parts.shift();\r |
3516 | \r |
3517 | set = posProcess( selector, set );\r |
3518 | }\r |
3519 | }\r |
3520 | } else {\r |
3521 | // Take a shortcut and set the context if the root selector is an ID\r |
3522 | // (but not if it'll be faster if the inner selector is an ID)\r |
3523 | if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\r |
3524 | Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\r |
3525 | var ret = Sizzle.find( parts.shift(), context, contextXML );\r |
3526 | context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];\r |
3527 | }\r |
3528 | \r |
3529 | if ( context ) {\r |
3530 | var ret = seed ?\r |
3531 | { expr: parts.pop(), set: makeArray(seed) } :\r |
3532 | Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );\r |
3533 | set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;\r |
3534 | \r |
3535 | if ( parts.length > 0 ) {\r |
3536 | checkSet = makeArray(set);\r |
3537 | } else {\r |
3538 | prune = false;\r |
3539 | }\r |
3540 | \r |
3541 | while ( parts.length ) {\r |
3542 | var cur = parts.pop(), pop = cur;\r |
3543 | \r |
3544 | if ( !Expr.relative[ cur ] ) {\r |
3545 | cur = "";\r |
3546 | } else {\r |
3547 | pop = parts.pop();\r |
3548 | }\r |
3549 | \r |
3550 | if ( pop == null ) {\r |
3551 | pop = context;\r |
3552 | }\r |
3553 | \r |
3554 | Expr.relative[ cur ]( checkSet, pop, contextXML );\r |
3555 | }\r |
3556 | } else {\r |
3557 | checkSet = parts = [];\r |
3558 | }\r |
3559 | }\r |
3560 | \r |
3561 | if ( !checkSet ) {\r |
3562 | checkSet = set;\r |
3563 | }\r |
3564 | \r |
3565 | if ( !checkSet ) {\r |
3566 | throw "Syntax error, unrecognized expression: " + (cur || selector);\r |
3567 | }\r |
3568 | \r |
3569 | if ( toString.call(checkSet) === "[object Array]" ) {\r |
3570 | if ( !prune ) {\r |
3571 | results.push.apply( results, checkSet );\r |
3572 | } else if ( context && context.nodeType === 1 ) {\r |
3573 | for ( var i = 0; checkSet[i] != null; i++ ) {\r |
3574 | if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {\r |
3575 | results.push( set[i] );\r |
3576 | }\r |
3577 | }\r |
3578 | } else {\r |
3579 | for ( var i = 0; checkSet[i] != null; i++ ) {\r |
3580 | if ( checkSet[i] && checkSet[i].nodeType === 1 ) {\r |
3581 | results.push( set[i] );\r |
3582 | }\r |
3583 | }\r |
3584 | }\r |
3585 | } else {\r |
3586 | makeArray( checkSet, results );\r |
3587 | }\r |
3588 | \r |
3589 | if ( extra ) {\r |
3590 | Sizzle( extra, origContext, results, seed );\r |
3591 | Sizzle.uniqueSort( results );\r |
3592 | }\r |
3593 | \r |
3594 | return results;\r |
3595 | };\r |
3596 | \r |
3597 | Sizzle.uniqueSort = function(results){\r |
3598 | if ( sortOrder ) {\r |
3599 | hasDuplicate = false;\r |
3600 | results.sort(sortOrder);\r |
3601 | \r |
3602 | if ( hasDuplicate ) {\r |
3603 | for ( var i = 1; i < results.length; i++ ) {\r |
3604 | if ( results[i] === results[i-1] ) {\r |
3605 | results.splice(i--, 1);\r |
3606 | }\r |
3607 | }\r |
3608 | }\r |
3609 | }\r |
3610 | };\r |
3611 | \r |
3612 | Sizzle.matches = function(expr, set){\r |
3613 | return Sizzle(expr, null, null, set);\r |
3614 | };\r |
3615 | \r |
3616 | Sizzle.find = function(expr, context, isXML){\r |
3617 | var set, match;\r |
3618 | \r |
3619 | if ( !expr ) {\r |
3620 | return [];\r |
3621 | }\r |
3622 | \r |
3623 | for ( var i = 0, l = Expr.order.length; i < l; i++ ) {\r |
3624 | var type = Expr.order[i], match;\r |
3625 | \r |
3626 | if ( (match = Expr.match[ type ].exec( expr )) ) {\r |
3627 | var left = RegExp.leftContext;\r |
3628 | \r |
3629 | if ( left.substr( left.length - 1 ) !== "\\" ) {\r |
3630 | match[1] = (match[1] || "").replace(/\\/g, "");\r |
3631 | set = Expr.find[ type ]( match, context, isXML );\r |
3632 | if ( set != null ) {\r |
3633 | expr = expr.replace( Expr.match[ type ], "" );\r |
3634 | break;\r |
3635 | }\r |
3636 | }\r |
3637 | }\r |
3638 | }\r |
3639 | \r |
3640 | if ( !set ) {\r |
3641 | set = context.getElementsByTagName("*");\r |
3642 | }\r |
3643 | \r |
3644 | return {set: set, expr: expr};\r |
3645 | };\r |
3646 | \r |
3647 | Sizzle.filter = function(expr, set, inplace, not){\r |
3648 | var old = expr, result = [], curLoop = set, match, anyFound,\r |
3649 | isXMLFilter = set && set[0] && isXML(set[0]);\r |
3650 | \r |
3651 | while ( expr && set.length ) {\r |
3652 | for ( var type in Expr.filter ) {\r |
3653 | if ( (match = Expr.match[ type ].exec( expr )) != null ) {\r |
3654 | var filter = Expr.filter[ type ], found, item;\r |
3655 | anyFound = false;\r |
3656 | \r |
3657 | if ( curLoop == result ) {\r |
3658 | result = [];\r |
3659 | }\r |
3660 | \r |
3661 | if ( Expr.preFilter[ type ] ) {\r |
3662 | match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\r |
3663 | \r |
3664 | if ( !match ) {\r |
3665 | anyFound = found = true;\r |
3666 | } else if ( match === true ) {\r |
3667 | continue;\r |
3668 | }\r |
3669 | }\r |
3670 | \r |
3671 | if ( match ) {\r |
3672 | for ( var i = 0; (item = curLoop[i]) != null; i++ ) {\r |
3673 | if ( item ) {\r |
3674 | found = filter( item, match, i, curLoop );\r |
3675 | var pass = not ^ !!found;\r |
3676 | \r |
3677 | if ( inplace && found != null ) {\r |
3678 | if ( pass ) {\r |
3679 | anyFound = true;\r |
3680 | } else {\r |
3681 | curLoop[i] = false;\r |
3682 | }\r |
3683 | } else if ( pass ) {\r |
3684 | result.push( item );\r |
3685 | anyFound = true;\r |
3686 | }\r |
3687 | }\r |
3688 | }\r |
3689 | }\r |
3690 | \r |
3691 | if ( found !== undefined ) {\r |
3692 | if ( !inplace ) {\r |
3693 | curLoop = result;\r |
3694 | }\r |
3695 | \r |
3696 | expr = expr.replace( Expr.match[ type ], "" );\r |
3697 | \r |
3698 | if ( !anyFound ) {\r |
3699 | return [];\r |
3700 | }\r |
3701 | \r |
3702 | break;\r |
3703 | }\r |
3704 | }\r |
3705 | }\r |
3706 | \r |
3707 | // Improper expression\r |
3708 | if ( expr == old ) {\r |
3709 | if ( anyFound == null ) {\r |
3710 | throw "Syntax error, unrecognized expression: " + expr;\r |
3711 | } else {\r |
3712 | break;\r |
3713 | }\r |
3714 | }\r |
3715 | \r |
3716 | old = expr;\r |
3717 | }\r |
3718 | \r |
3719 | return curLoop;\r |
3720 | };\r |
3721 | \r |
3722 | var Expr = Sizzle.selectors = {\r |
3723 | order: [ "ID", "NAME", "TAG" ],\r |
3724 | match: {\r |
3725 | ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,\r |
3726 | CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,\r |
3727 | NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,\r |
3728 | ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,\r |
3729 | TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,\r |
3730 | CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,\r |
3731 | POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,\r |
3732 | PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/\r |
3733 | },\r |
3734 | attrMap: {\r |
3735 | "class": "className",\r |
3736 | "for": "htmlFor"\r |
3737 | },\r |
3738 | attrHandle: {\r |
3739 | href: function(elem){\r |
3740 | return elem.getAttribute("href");\r |
3741 | }\r |
3742 | },\r |
3743 | relative: {\r |
3744 | "+": function(checkSet, part, isXML){\r |
3745 | var isPartStr = typeof part === "string",\r |
3746 | isTag = isPartStr && !/\W/.test(part),\r |
3747 | isPartStrNotTag = isPartStr && !isTag;\r |
3748 | \r |
3749 | if ( isTag && !isXML ) {\r |
3750 | part = part.toUpperCase();\r |
3751 | }\r |
3752 | \r |
3753 | for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\r |
3754 | if ( (elem = checkSet[i]) ) {\r |
3755 | while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\r |
3756 | \r |
3757 | checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?\r |
3758 | elem || false :\r |
3759 | elem === part;\r |
3760 | }\r |
3761 | }\r |
3762 | \r |
3763 | if ( isPartStrNotTag ) {\r |
3764 | Sizzle.filter( part, checkSet, true );\r |
3765 | }\r |
3766 | },\r |
3767 | ">": function(checkSet, part, isXML){\r |
3768 | var isPartStr = typeof part === "string";\r |
3769 | \r |
3770 | if ( isPartStr && !/\W/.test(part) ) {\r |
3771 | part = isXML ? part : part.toUpperCase();\r |
3772 | \r |
3773 | for ( var i = 0, l = checkSet.length; i < l; i++ ) {\r |
3774 | var elem = checkSet[i];\r |
3775 | if ( elem ) {\r |
3776 | var parent = elem.parentNode;\r |
3777 | checkSet[i] = parent.nodeName === part ? parent : false;\r |
3778 | }\r |
3779 | }\r |
3780 | } else {\r |
3781 | for ( var i = 0, l = checkSet.length; i < l; i++ ) {\r |
3782 | var elem = checkSet[i];\r |
3783 | if ( elem ) {\r |
3784 | checkSet[i] = isPartStr ?\r |
3785 | elem.parentNode :\r |
3786 | elem.parentNode === part;\r |
3787 | }\r |
3788 | }\r |
3789 | \r |
3790 | if ( isPartStr ) {\r |
3791 | Sizzle.filter( part, checkSet, true );\r |
3792 | }\r |
3793 | }\r |
3794 | },\r |
3795 | "": function(checkSet, part, isXML){\r |
3796 | var doneName = done++, checkFn = dirCheck;\r |
3797 | \r |
3798 | if ( !part.match(/\W/) ) {\r |
3799 | var nodeCheck = part = isXML ? part : part.toUpperCase();\r |
3800 | checkFn = dirNodeCheck;\r |
3801 | }\r |
3802 | \r |
3803 | checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);\r |
3804 | },\r |
3805 | "~": function(checkSet, part, isXML){\r |
3806 | var doneName = done++, checkFn = dirCheck;\r |
3807 | \r |
3808 | if ( typeof part === "string" && !part.match(/\W/) ) {\r |
3809 | var nodeCheck = part = isXML ? part : part.toUpperCase();\r |
3810 | checkFn = dirNodeCheck;\r |
3811 | }\r |
3812 | \r |
3813 | checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);\r |
3814 | }\r |
3815 | },\r |
3816 | find: {\r |
3817 | ID: function(match, context, isXML){\r |
3818 | if ( typeof context.getElementById !== "undefined" && !isXML ) {\r |
3819 | var m = context.getElementById(match[1]);\r |
3820 | return m ? [m] : [];\r |
3821 | }\r |
3822 | },\r |
3823 | NAME: function(match, context, isXML){\r |
3824 | if ( typeof context.getElementsByName !== "undefined" ) {\r |
3825 | var ret = [], results = context.getElementsByName(match[1]);\r |
3826 | \r |
3827 | for ( var i = 0, l = results.length; i < l; i++ ) {\r |
3828 | if ( results[i].getAttribute("name") === match[1] ) {\r |
3829 | ret.push( results[i] );\r |
3830 | }\r |
3831 | }\r |
3832 | \r |
3833 | return ret.length === 0 ? null : ret;\r |
3834 | }\r |
3835 | },\r |
3836 | TAG: function(match, context){\r |
3837 | return context.getElementsByTagName(match[1]);\r |
3838 | }\r |
3839 | },\r |
3840 | preFilter: {\r |
3841 | CLASS: function(match, curLoop, inplace, result, not, isXML){\r |
3842 | match = " " + match[1].replace(/\\/g, "") + " ";\r |
3843 | \r |
3844 | if ( isXML ) {\r |
3845 | return match;\r |
3846 | }\r |
3847 | \r |
3848 | for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\r |
3849 | if ( elem ) {\r |
3850 | if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {\r |
3851 | if ( !inplace )\r |
3852 | result.push( elem );\r |
3853 | } else if ( inplace ) {\r |
3854 | curLoop[i] = false;\r |
3855 | }\r |
3856 | }\r |
3857 | }\r |
3858 | \r |
3859 | return false;\r |
3860 | },\r |
3861 | ID: function(match){\r |
3862 | return match[1].replace(/\\/g, "");\r |
3863 | },\r |
3864 | TAG: function(match, curLoop){\r |
3865 | for ( var i = 0; curLoop[i] === false; i++ ){}\r |
3866 | return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();\r |
3867 | },\r |
3868 | CHILD: function(match){\r |
3869 | if ( match[1] == "nth" ) {\r |
3870 | // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\r |
3871 | var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(\r |
3872 | match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||\r |
3873 | !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);\r |
3874 | \r |
3875 | // calculate the numbers (first)n+(last) including if they are negative\r |
3876 | match[2] = (test[1] + (test[2] || 1)) - 0;\r |
3877 | match[3] = test[3] - 0;\r |
3878 | }\r |
3879 | \r |
3880 | // TODO: Move to normal caching system\r |
3881 | match[0] = done++;\r |
3882 | \r |
3883 | return match;\r |
3884 | },\r |
3885 | ATTR: function(match, curLoop, inplace, result, not, isXML){\r |
3886 | var name = match[1].replace(/\\/g, "");\r |
3887 | \r |
3888 | if ( !isXML && Expr.attrMap[name] ) {\r |
3889 | match[1] = Expr.attrMap[name];\r |
3890 | }\r |
3891 | \r |
3892 | if ( match[2] === "~=" ) {\r |
3893 | match[4] = " " + match[4] + " ";\r |
3894 | }\r |
3895 | \r |
3896 | return match;\r |
3897 | },\r |
3898 | PSEUDO: function(match, curLoop, inplace, result, not){\r |
3899 | if ( match[1] === "not" ) {\r |
3900 | // If we're dealing with a complex expression, or a simple one\r |
3901 | if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) {\r |
3902 | match[3] = Sizzle(match[3], null, null, curLoop);\r |
3903 | } else {\r |
3904 | var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\r |
3905 | if ( !inplace ) {\r |
3906 | result.push.apply( result, ret );\r |
3907 | }\r |
3908 | return false;\r |
3909 | }\r |
3910 | } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\r |
3911 | return true;\r |
3912 | }\r |
3913 | \r |
3914 | return match;\r |
3915 | },\r |
3916 | POS: function(match){\r |
3917 | match.unshift( true );\r |
3918 | return match;\r |
3919 | }\r |
3920 | },\r |
3921 | filters: {\r |
3922 | enabled: function(elem){\r |
3923 | return elem.disabled === false && elem.type !== "hidden";\r |
3924 | },\r |
3925 | disabled: function(elem){\r |
3926 | return elem.disabled === true;\r |
3927 | },\r |
3928 | checked: function(elem){\r |
3929 | return elem.checked === true;\r |
3930 | },\r |
3931 | selected: function(elem){\r |
3932 | // Accessing this property makes selected-by-default\r |
3933 | // options in Safari work properly\r |
3934 | elem.parentNode.selectedIndex;\r |
3935 | return elem.selected === true;\r |
3936 | },\r |
3937 | parent: function(elem){\r |
3938 | return !!elem.firstChild;\r |
3939 | },\r |
3940 | empty: function(elem){\r |
3941 | return !elem.firstChild;\r |
3942 | },\r |
3943 | has: function(elem, i, match){\r |
3944 | return !!Sizzle( match[3], elem ).length;\r |
3945 | },\r |
3946 | header: function(elem){\r |
3947 | return /h\d/i.test( elem.nodeName );\r |
3948 | },\r |
3949 | text: function(elem){\r |
3950 | return "text" === elem.type;\r |
3951 | },\r |
3952 | radio: function(elem){\r |
3953 | return "radio" === elem.type;\r |
3954 | },\r |
3955 | checkbox: function(elem){\r |
3956 | return "checkbox" === elem.type;\r |
3957 | },\r |
3958 | file: function(elem){\r |
3959 | return "file" === elem.type;\r |
3960 | },\r |
3961 | password: function(elem){\r |
3962 | return "password" === elem.type;\r |
3963 | },\r |
3964 | submit: function(elem){\r |
3965 | return "submit" === elem.type;\r |
3966 | },\r |
3967 | image: function(elem){\r |
3968 | return "image" === elem.type;\r |
3969 | },\r |
3970 | reset: function(elem){\r |
3971 | return "reset" === elem.type;\r |
3972 | },\r |
3973 | button: function(elem){\r |
3974 | return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";\r |
3975 | },\r |
3976 | input: function(elem){\r |
3977 | return /input|select|textarea|button/i.test(elem.nodeName);\r |
3978 | }\r |
3979 | },\r |
3980 | setFilters: {\r |
3981 | first: function(elem, i){\r |
3982 | return i === 0;\r |
3983 | },\r |
3984 | last: function(elem, i, match, array){\r |
3985 | return i === array.length - 1;\r |
3986 | },\r |
3987 | even: function(elem, i){\r |
3988 | return i % 2 === 0;\r |
3989 | },\r |
3990 | odd: function(elem, i){\r |
3991 | return i % 2 === 1;\r |
3992 | },\r |
3993 | lt: function(elem, i, match){\r |
3994 | return i < match[3] - 0;\r |
3995 | },\r |
3996 | gt: function(elem, i, match){\r |
3997 | return i > match[3] - 0;\r |
3998 | },\r |
3999 | nth: function(elem, i, match){\r |
4000 | return match[3] - 0 == i;\r |
4001 | },\r |
4002 | eq: function(elem, i, match){\r |
4003 | return match[3] - 0 == i;\r |
4004 | }\r |
4005 | },\r |
4006 | filter: {\r |
4007 | PSEUDO: function(elem, match, i, array){\r |
4008 | var name = match[1], filter = Expr.filters[ name ];\r |
4009 | \r |
4010 | if ( filter ) {\r |
4011 | return filter( elem, i, match, array );\r |
4012 | } else if ( name === "contains" ) {\r |
4013 | return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;\r |
4014 | } else if ( name === "not" ) {\r |
4015 | var not = match[3];\r |
4016 | \r |
4017 | for ( var i = 0, l = not.length; i < l; i++ ) {\r |
4018 | if ( not[i] === elem ) {\r |
4019 | return false;\r |
4020 | }\r |
4021 | }\r |
4022 | \r |
4023 | return true;\r |
4024 | }\r |
4025 | },\r |
4026 | CHILD: function(elem, match){\r |
4027 | var type = match[1], node = elem;\r |
4028 | switch (type) {\r |
4029 | case 'only':\r |
4030 | case 'first':\r |
4031 | while (node = node.previousSibling) {\r |
4032 | if ( node.nodeType === 1 ) return false;\r |
4033 | }\r |
4034 | if ( type == 'first') return true;\r |
4035 | node = elem;\r |
4036 | case 'last':\r |
4037 | while (node = node.nextSibling) {\r |
4038 | if ( node.nodeType === 1 ) return false;\r |
4039 | }\r |
4040 | return true;\r |
4041 | case 'nth':\r |
4042 | var first = match[2], last = match[3];\r |
4043 | \r |
4044 | if ( first == 1 && last == 0 ) {\r |
4045 | return true;\r |
4046 | }\r |
4047 | \r |
4048 | var doneName = match[0],\r |
4049 | parent = elem.parentNode;\r |
4050 | \r |
4051 | if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {\r |
4052 | var count = 0;\r |
4053 | for ( node = parent.firstChild; node; node = node.nextSibling ) {\r |
4054 | if ( node.nodeType === 1 ) {\r |
4055 | node.nodeIndex = ++count;\r |
4056 | }\r |
4057 | } \r |
4058 | parent.sizcache = doneName;\r |
4059 | }\r |
4060 | \r |
4061 | var diff = elem.nodeIndex - last;\r |
4062 | if ( first == 0 ) {\r |
4063 | return diff == 0;\r |
4064 | } else {\r |
4065 | return ( diff % first == 0 && diff / first >= 0 );\r |
4066 | }\r |
4067 | }\r |
4068 | },\r |
4069 | ID: function(elem, match){\r |
4070 | return elem.nodeType === 1 && elem.getAttribute("id") === match;\r |
4071 | },\r |
4072 | TAG: function(elem, match){\r |
4073 | return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;\r |
4074 | },\r |
4075 | CLASS: function(elem, match){\r |
4076 | return (" " + (elem.className || elem.getAttribute("class")) + " ")\r |
4077 | .indexOf( match ) > -1;\r |
4078 | },\r |
4079 | ATTR: function(elem, match){\r |
4080 | var name = match[1],\r |
4081 | result = Expr.attrHandle[ name ] ?\r |
4082 | Expr.attrHandle[ name ]( elem ) :\r |
4083 | elem[ name ] != null ?\r |
4084 | elem[ name ] :\r |
4085 | elem.getAttribute( name ),\r |
4086 | value = result + "",\r |
4087 | type = match[2],\r |
4088 | check = match[4];\r |
4089 | \r |
4090 | return result == null ?\r |
4091 | type === "!=" :\r |
4092 | type === "=" ?\r |
4093 | value === check :\r |
4094 | type === "*=" ?\r |
4095 | value.indexOf(check) >= 0 :\r |
4096 | type === "~=" ?\r |
4097 | (" " + value + " ").indexOf(check) >= 0 :\r |
4098 | !check ?\r |
4099 | value && result !== false :\r |
4100 | type === "!=" ?\r |
4101 | value != check :\r |
4102 | type === "^=" ?\r |
4103 | value.indexOf(check) === 0 :\r |
4104 | type === "$=" ?\r |
4105 | value.substr(value.length - check.length) === check :\r |
4106 | type === "|=" ?\r |
4107 | value === check || value.substr(0, check.length + 1) === check + "-" :\r |
4108 | false;\r |
4109 | },\r |
4110 | POS: function(elem, match, i, array){\r |
4111 | var name = match[2], filter = Expr.setFilters[ name ];\r |
4112 | \r |
4113 | if ( filter ) {\r |
4114 | return filter( elem, i, match, array );\r |
4115 | }\r |
4116 | }\r |
4117 | }\r |
4118 | };\r |
4119 | \r |
4120 | var origPOS = Expr.match.POS;\r |
4121 | \r |
4122 | for ( var type in Expr.match ) {\r |
4123 | Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );\r |
4124 | }\r |
4125 | \r |
4126 | var makeArray = function(array, results) {\r |
4127 | array = Array.prototype.slice.call( array );\r |
4128 | \r |
4129 | if ( results ) {\r |
4130 | results.push.apply( results, array );\r |
4131 | return results;\r |
4132 | }\r |
4133 | \r |
4134 | return array;\r |
4135 | };\r |
4136 | \r |
4137 | // Perform a simple check to determine if the browser is capable of\r |
4138 | // converting a NodeList to an array using builtin methods.\r |
4139 | try {\r |
4140 | Array.prototype.slice.call( document.documentElement.childNodes );\r |
4141 | \r |
4142 | // Provide a fallback method if it does not work\r |
4143 | } catch(e){\r |
4144 | makeArray = function(array, results) {\r |
4145 | var ret = results || [];\r |
4146 | \r |
4147 | if ( toString.call(array) === "[object Array]" ) {\r |
4148 | Array.prototype.push.apply( ret, array );\r |
4149 | } else {\r |
4150 | if ( typeof array.length === "number" ) {\r |
4151 | for ( var i = 0, l = array.length; i < l; i++ ) {\r |
4152 | ret.push( array[i] );\r |
4153 | }\r |
4154 | } else {\r |
4155 | for ( var i = 0; array[i]; i++ ) {\r |
4156 | ret.push( array[i] );\r |
4157 | }\r |
4158 | }\r |
4159 | }\r |
4160 | \r |
4161 | return ret;\r |
4162 | };\r |
4163 | }\r |
4164 | \r |
4165 | var sortOrder;\r |
4166 | \r |
4167 | if ( document.documentElement.compareDocumentPosition ) {\r |
4168 | sortOrder = function( a, b ) {\r |
4169 | var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;\r |
4170 | if ( ret === 0 ) {\r |
4171 | hasDuplicate = true;\r |
4172 | }\r |
4173 | return ret;\r |
4174 | };\r |
4175 | } else if ( "sourceIndex" in document.documentElement ) {\r |
4176 | sortOrder = function( a, b ) {\r |
4177 | var ret = a.sourceIndex - b.sourceIndex;\r |
4178 | if ( ret === 0 ) {\r |
4179 | hasDuplicate = true;\r |
4180 | }\r |
4181 | return ret;\r |
4182 | };\r |
4183 | } else if ( document.createRange ) {\r |
4184 | sortOrder = function( a, b ) {\r |
4185 | var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();\r |
4186 | aRange.setStart(a, 0);\r |
4187 | aRange.setEnd(a, 0);\r |
4188 | bRange.setStart(b, 0);\r |
4189 | bRange.setEnd(b, 0);\r |
4190 | var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);\r |
4191 | if ( ret === 0 ) {\r |
4192 | hasDuplicate = true;\r |
4193 | }\r |
4194 | return ret;\r |
4195 | };\r |
4196 | }\r |
4197 | \r |
4198 | // Check to see if the browser returns elements by name when\r |
4199 | // querying by getElementById (and provide a workaround)\r |
4200 | (function(){\r |
4201 | // We're going to inject a fake input element with a specified name\r |
4202 | var form = document.createElement("div"),\r |
4203 | id = "script" + (new Date).getTime();\r |
4204 | form.innerHTML = "<a name='" + id + "'/>";\r |
4205 | \r |
4206 | // Inject it into the root element, check its status, and remove it quickly\r |
4207 | var root = document.documentElement;\r |
4208 | root.insertBefore( form, root.firstChild );\r |
4209 | \r |
4210 | // The workaround has to do additional checks after a getElementById\r |
4211 | // Which slows things down for other browsers (hence the branching)\r |
4212 | if ( !!document.getElementById( id ) ) {\r |
4213 | Expr.find.ID = function(match, context, isXML){\r |
4214 | if ( typeof context.getElementById !== "undefined" && !isXML ) {\r |
4215 | var m = context.getElementById(match[1]);\r |
4216 | return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];\r |
4217 | }\r |
4218 | };\r |
4219 | \r |
4220 | Expr.filter.ID = function(elem, match){\r |
4221 | var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");\r |
4222 | return elem.nodeType === 1 && node && node.nodeValue === match;\r |
4223 | };\r |
4224 | }\r |
4225 | \r |
4226 | root.removeChild( form );\r |
4227 | })();\r |
4228 | \r |
4229 | (function(){\r |
4230 | // Check to see if the browser returns only elements\r |
4231 | // when doing getElementsByTagName("*")\r |
4232 | \r |
4233 | // Create a fake element\r |
4234 | var div = document.createElement("div");\r |
4235 | div.appendChild( document.createComment("") );\r |
4236 | \r |
4237 | // Make sure no comments are found\r |
4238 | if ( div.getElementsByTagName("*").length > 0 ) {\r |
4239 | Expr.find.TAG = function(match, context){\r |
4240 | var results = context.getElementsByTagName(match[1]);\r |
4241 | \r |
4242 | // Filter out possible comments\r |
4243 | if ( match[1] === "*" ) {\r |
4244 | var tmp = [];\r |
4245 | \r |
4246 | for ( var i = 0; results[i]; i++ ) {\r |
4247 | if ( results[i].nodeType === 1 ) {\r |
4248 | tmp.push( results[i] );\r |
4249 | }\r |
4250 | }\r |
4251 | \r |
4252 | results = tmp;\r |
4253 | }\r |
4254 | \r |
4255 | return results;\r |
4256 | };\r |
4257 | }\r |
4258 | \r |
4259 | // Check to see if an attribute returns normalized href attributes\r |
4260 | div.innerHTML = "<a href='#'></a>";\r |
4261 | if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&\r |
4262 | div.firstChild.getAttribute("href") !== "#" ) {\r |
4263 | Expr.attrHandle.href = function(elem){\r |
4264 | return elem.getAttribute("href", 2);\r |
4265 | };\r |
4266 | }\r |
4267 | })();\r |
4268 | \r |
4269 | if ( document.querySelectorAll ) (function(){\r |
4270 | var oldSizzle = Sizzle, div = document.createElement("div");\r |
4271 | div.innerHTML = "<p class='TEST'></p>";\r |
4272 | \r |
4273 | // Safari can't handle uppercase or unicode characters when\r |
4274 | // in quirks mode.\r |
4275 | if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {\r |
4276 | return;\r |
4277 | }\r |
4278 | \r |
4279 | Sizzle = function(query, context, extra, seed){\r |
4280 | context = context || document;\r |
4281 | \r |
4282 | // Only use querySelectorAll on non-XML documents\r |
4283 | // (ID selectors don't work in non-HTML documents)\r |
4284 | if ( !seed && context.nodeType === 9 && !isXML(context) ) {\r |
4285 | try {\r |
4286 | return makeArray( context.querySelectorAll(query), extra );\r |
4287 | } catch(e){}\r |
4288 | }\r |
4289 | \r |
4290 | return oldSizzle(query, context, extra, seed);\r |
4291 | };\r |
4292 | \r |
4293 | for ( var prop in oldSizzle ) {\r |
4294 | Sizzle[ prop ] = oldSizzle[ prop ];\r |
4295 | }\r |
4296 | })();\r |
4297 | \r |
4298 | if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){\r |
4299 | var div = document.createElement("div");\r |
4300 | div.innerHTML = "<div class='test e'></div><div class='test'></div>";\r |
4301 | \r |
4302 | // Opera can't find a second classname (in 9.6)\r |
4303 | if ( div.getElementsByClassName("e").length === 0 )\r |
4304 | return;\r |
4305 | \r |
4306 | // Safari caches class attributes, doesn't catch changes (in 3.2)\r |
4307 | div.lastChild.className = "e";\r |
4308 | \r |
4309 | if ( div.getElementsByClassName("e").length === 1 )\r |
4310 | return;\r |
4311 | \r |
4312 | Expr.order.splice(1, 0, "CLASS");\r |
4313 | Expr.find.CLASS = function(match, context, isXML) {\r |
4314 | if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {\r |
4315 | return context.getElementsByClassName(match[1]);\r |
4316 | }\r |
4317 | };\r |
4318 | })();\r |
4319 | \r |
4320 | function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\r |
4321 | var sibDir = dir == "previousSibling" && !isXML;\r |
4322 | for ( var i = 0, l = checkSet.length; i < l; i++ ) {\r |
4323 | var elem = checkSet[i];\r |
4324 | if ( elem ) {\r |
4325 | if ( sibDir && elem.nodeType === 1 ){\r |
4326 | elem.sizcache = doneName;\r |
4327 | elem.sizset = i;\r |
4328 | }\r |
4329 | elem = elem[dir];\r |
4330 | var match = false;\r |
4331 | \r |
4332 | while ( elem ) {\r |
4333 | if ( elem.sizcache === doneName ) {\r |
4334 | match = checkSet[elem.sizset];\r |
4335 | break;\r |
4336 | }\r |
4337 | \r |
4338 | if ( elem.nodeType === 1 && !isXML ){\r |
4339 | elem.sizcache = doneName;\r |
4340 | elem.sizset = i;\r |
4341 | }\r |
4342 | \r |
4343 | if ( elem.nodeName === cur ) {\r |
4344 | match = elem;\r |
4345 | break;\r |
4346 | }\r |
4347 | \r |
4348 | elem = elem[dir];\r |
4349 | }\r |
4350 | \r |
4351 | checkSet[i] = match;\r |
4352 | }\r |
4353 | }\r |
4354 | }\r |
4355 | \r |
4356 | function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\r |
4357 | var sibDir = dir == "previousSibling" && !isXML;\r |
4358 | for ( var i = 0, l = checkSet.length; i < l; i++ ) {\r |
4359 | var elem = checkSet[i];\r |
4360 | if ( elem ) {\r |
4361 | if ( sibDir && elem.nodeType === 1 ) {\r |
4362 | elem.sizcache = doneName;\r |
4363 | elem.sizset = i;\r |
4364 | }\r |
4365 | elem = elem[dir];\r |
4366 | var match = false;\r |
4367 | \r |
4368 | while ( elem ) {\r |
4369 | if ( elem.sizcache === doneName ) {\r |
4370 | match = checkSet[elem.sizset];\r |
4371 | break;\r |
4372 | }\r |
4373 | \r |
4374 | if ( elem.nodeType === 1 ) {\r |
4375 | if ( !isXML ) {\r |
4376 | elem.sizcache = doneName;\r |
4377 | elem.sizset = i;\r |
4378 | }\r |
4379 | if ( typeof cur !== "string" ) {\r |
4380 | if ( elem === cur ) {\r |
4381 | match = true;\r |
4382 | break;\r |
4383 | }\r |
4384 | \r |
4385 | } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\r |
4386 | match = elem;\r |
4387 | break;\r |
4388 | }\r |
4389 | }\r |
4390 | \r |
4391 | elem = elem[dir];\r |
4392 | }\r |
4393 | \r |
4394 | checkSet[i] = match;\r |
4395 | }\r |
4396 | }\r |
4397 | }\r |
4398 | \r |
4399 | var contains = document.compareDocumentPosition ? function(a, b){\r |
4400 | return a.compareDocumentPosition(b) & 16;\r |
4401 | } : function(a, b){\r |
4402 | return a !== b && (a.contains ? a.contains(b) : true);\r |
4403 | };\r |
4404 | \r |
4405 | var isXML = function(elem){\r |
4406 | return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||\r |
4407 | !!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML";\r |
4408 | };\r |
4409 | \r |
4410 | var posProcess = function(selector, context){\r |
4411 | var tmpSet = [], later = "", match,\r |
4412 | root = context.nodeType ? [context] : context;\r |
4413 | \r |
4414 | // Position selectors must be done after the filter\r |
4415 | // And so must :not(positional) so we move all PSEUDOs to the end\r |
4416 | while ( (match = Expr.match.PSEUDO.exec( selector )) ) {\r |
4417 | later += match[0];\r |
4418 | selector = selector.replace( Expr.match.PSEUDO, "" );\r |
4419 | }\r |
4420 | \r |
4421 | selector = Expr.relative[selector] ? selector + "*" : selector;\r |
4422 | \r |
4423 | for ( var i = 0, l = root.length; i < l; i++ ) {\r |
4424 | Sizzle( selector, root[i], tmpSet );\r |
4425 | }\r |
4426 | \r |
4427 | return Sizzle.filter( later, tmpSet );\r |
4428 | };\r |
4429 | \r |
4430 | // EXPOSE\r |
4431 | \r |
4432 | window.tinymce.dom.Sizzle = Sizzle;\r |
4433 | \r |
4434 | })();\r |
4435 | \r |
4436 | (function(tinymce) {\r |
4437 | // Shorten names\r |
4438 | var each = tinymce.each, DOM = tinymce.DOM, isIE = tinymce.isIE, isWebKit = tinymce.isWebKit, Event;\r |
4439 | \r |
4440 | tinymce.create('tinymce.dom.EventUtils', {\r |
4441 | EventUtils : function() {\r |
4442 | this.inits = [];\r |
4443 | this.events = [];\r |
4444 | },\r |
4445 | \r |
4446 | add : function(o, n, f, s) {\r |
4447 | var cb, t = this, el = t.events, r;\r |
4448 | \r |
4449 | if (n instanceof Array) {\r |
4450 | r = [];\r |
4451 | \r |
4452 | each(n, function(n) {\r |
4453 | r.push(t.add(o, n, f, s));\r |
4454 | });\r |
4455 | \r |
4456 | return r;\r |
4457 | }\r |
4458 | \r |
4459 | // Handle array\r |
4460 | if (o && o.hasOwnProperty && o instanceof Array) {\r |
4461 | r = [];\r |
4462 | \r |
4463 | each(o, function(o) {\r |
4464 | o = DOM.get(o);\r |
4465 | r.push(t.add(o, n, f, s));\r |
4466 | });\r |
4467 | \r |
4468 | return r;\r |
4469 | }\r |
4470 | \r |
4471 | o = DOM.get(o);\r |
4472 | \r |
4473 | if (!o)\r |
4474 | return;\r |
4475 | \r |
4476 | // Setup event callback\r |
4477 | cb = function(e) {\r |
4478 | // Is all events disabled\r |
4479 | if (t.disabled)\r |
4480 | return;\r |
4481 | \r |
4482 | e = e || window.event;\r |
4483 | \r |
4484 | // Patch in target, preventDefault and stopPropagation in IE it's W3C valid\r |
4485 | if (e && isIE) {\r |
4486 | if (!e.target)\r |
4487 | e.target = e.srcElement;\r |
4488 | \r |
4489 | // Patch in preventDefault, stopPropagation methods for W3C compatibility\r |
4490 | tinymce.extend(e, t._stoppers);\r |
4491 | }\r |
4492 | \r |
4493 | if (!s)\r |
4494 | return f(e);\r |
4495 | \r |
4496 | return f.call(s, e);\r |
4497 | };\r |
4498 | \r |
4499 | if (n == 'unload') {\r |
4500 | tinymce.unloads.unshift({func : cb});\r |
4501 | return cb;\r |
4502 | }\r |
4503 | \r |
4504 | if (n == 'init') {\r |
4505 | if (t.domLoaded)\r |
4506 | cb();\r |
4507 | else\r |
4508 | t.inits.push(cb);\r |
4509 | \r |
4510 | return cb;\r |
4511 | }\r |
4512 | \r |
4513 | // Store away listener reference\r |
4514 | el.push({\r |
4515 | obj : o,\r |
4516 | name : n,\r |
4517 | func : f,\r |
4518 | cfunc : cb,\r |
4519 | scope : s\r |
4520 | });\r |
4521 | \r |
4522 | t._add(o, n, cb);\r |
4523 | \r |
4524 | return f;\r |
4525 | },\r |
4526 | \r |
4527 | remove : function(o, n, f) {\r |
4528 | var t = this, a = t.events, s = false, r;\r |
4529 | \r |
4530 | // Handle array\r |
4531 | if (o && o.hasOwnProperty && o instanceof Array) {\r |
4532 | r = [];\r |
4533 | \r |
4534 | each(o, function(o) {\r |
4535 | o = DOM.get(o);\r |
4536 | r.push(t.remove(o, n, f));\r |
4537 | });\r |
4538 | \r |
4539 | return r;\r |
4540 | }\r |
4541 | \r |
4542 | o = DOM.get(o);\r |
4543 | \r |
4544 | each(a, function(e, i) {\r |
4545 | if (e.obj == o && e.name == n && (!f || (e.func == f || e.cfunc == f))) {\r |
4546 | a.splice(i, 1);\r |
4547 | t._remove(o, n, e.cfunc);\r |
4548 | s = true;\r |
4549 | return false;\r |
4550 | }\r |
4551 | });\r |
4552 | \r |
4553 | return s;\r |
4554 | },\r |
4555 | \r |
4556 | clear : function(o) {\r |
4557 | var t = this, a = t.events, i, e;\r |
4558 | \r |
4559 | if (o) {\r |
4560 | o = DOM.get(o);\r |
4561 | \r |
4562 | for (i = a.length - 1; i >= 0; i--) {\r |
4563 | e = a[i];\r |
4564 | \r |
4565 | if (e.obj === o) {\r |
4566 | t._remove(e.obj, e.name, e.cfunc);\r |
4567 | e.obj = e.cfunc = null;\r |
4568 | a.splice(i, 1);\r |
4569 | }\r |
4570 | }\r |
4571 | }\r |
4572 | },\r |
4573 | \r |
4574 | cancel : function(e) {\r |
4575 | if (!e)\r |
4576 | return false;\r |
4577 | \r |
4578 | this.stop(e);\r |
4579 | \r |
4580 | return this.prevent(e);\r |
4581 | },\r |
4582 | \r |
4583 | stop : function(e) {\r |
4584 | if (e.stopPropagation)\r |
4585 | e.stopPropagation();\r |
4586 | else\r |
4587 | e.cancelBubble = true;\r |
4588 | \r |
4589 | return false;\r |
4590 | },\r |
4591 | \r |
4592 | prevent : function(e) {\r |
4593 | if (e.preventDefault)\r |
4594 | e.preventDefault();\r |
4595 | else\r |
4596 | e.returnValue = false;\r |
4597 | \r |
4598 | return false;\r |
4599 | },\r |
4600 | \r |
4601 | destroy : function() {\r |
4602 | var t = this;\r |
4603 | \r |
4604 | each(t.events, function(e, i) {\r |
4605 | t._remove(e.obj, e.name, e.cfunc);\r |
4606 | e.obj = e.cfunc = null;\r |
4607 | });\r |
4608 | \r |
4609 | t.events = [];\r |
4610 | t = null;\r |
4611 | },\r |
4612 | \r |
4613 | _add : function(o, n, f) {\r |
4614 | if (o.attachEvent)\r |
4615 | o.attachEvent('on' + n, f);\r |
4616 | else if (o.addEventListener)\r |
4617 | o.addEventListener(n, f, false);\r |
4618 | else\r |
4619 | o['on' + n] = f;\r |
4620 | },\r |
4621 | \r |
4622 | _remove : function(o, n, f) {\r |
4623 | if (o) {\r |
4624 | try {\r |
4625 | if (o.detachEvent)\r |
4626 | o.detachEvent('on' + n, f);\r |
4627 | else if (o.removeEventListener)\r |
4628 | o.removeEventListener(n, f, false);\r |
4629 | else\r |
4630 | o['on' + n] = null;\r |
4631 | } catch (ex) {\r |
4632 | // Might fail with permission denined on IE so we just ignore that\r |
4633 | }\r |
4634 | }\r |
4635 | },\r |
4636 | \r |
4637 | _pageInit : function(win) {\r |
4638 | var t = this;\r |
4639 | \r |
4640 | // Keep it from running more than once\r |
4641 | if (t.domLoaded)\r |
4642 | return;\r |
4643 | \r |
4644 | t.domLoaded = true;\r |
4645 | \r |
4646 | each(t.inits, function(c) {\r |
4647 | c();\r |
4648 | });\r |
4649 | \r |
4650 | t.inits = [];\r |
4651 | },\r |
4652 | \r |
4653 | _wait : function(win) {\r |
4654 | var t = this, doc = win.document;\r |
4655 | \r |
4656 | // No need since the document is already loaded\r |
4657 | if (win.tinyMCE_GZ && tinyMCE_GZ.loaded) {\r |
4658 | t.domLoaded = 1;\r |
4659 | return;\r |
4660 | }\r |
4661 | \r |
4662 | // Use IE method\r |
4663 | if (doc.attachEvent) {\r |
4664 | doc.attachEvent("onreadystatechange", function() {\r |
4665 | if (doc.readyState === "complete") {\r |
4666 | doc.detachEvent("onreadystatechange", arguments.callee);\r |
4667 | t._pageInit(win);\r |
4668 | }\r |
4669 | });\r |
4670 | \r |
4671 | if (doc.documentElement.doScroll && win == win.top) {\r |
4672 | (function() {\r |
4673 | if (t.domLoaded)\r |
4674 | return;\r |
4675 | \r |
4676 | try {\r |
4677 | // If IE is used, use the trick by Diego Perini\r |
4678 | // http://javascript.nwbox.com/IEContentLoaded/\r |
4679 | doc.documentElement.doScroll("left");\r |
4680 | } catch (ex) {\r |
4681 | setTimeout(arguments.callee, 0);\r |
4682 | return;\r |
4683 | }\r |
4684 | \r |
4685 | t._pageInit(win);\r |
4686 | })();\r |
4687 | }\r |
4688 | } else if (doc.addEventListener) {\r |
4689 | t._add(win, 'DOMContentLoaded', function() {\r |
4690 | t._pageInit(win);\r |
4691 | });\r |
4692 | }\r |
4693 | \r |
4694 | t._add(win, 'load', function() {\r |
4695 | t._pageInit(win);\r |
4696 | });\r |
4697 | },\r |
4698 | \r |
4699 | _stoppers : {\r |
4700 | preventDefault : function() {\r |
4701 | this.returnValue = false;\r |
4702 | },\r |
4703 | \r |
4704 | stopPropagation : function() {\r |
4705 | this.cancelBubble = true;\r |
4706 | }\r |
4707 | }\r |
4708 | });\r |
4709 | \r |
4710 | Event = tinymce.dom.Event = new tinymce.dom.EventUtils();\r |
4711 | \r |
4712 | // Dispatch DOM content loaded event for IE and Safari\r |
4713 | Event._wait(window);\r |
4714 | \r |
4715 | tinymce.addUnload(function() {\r |
4716 | Event.destroy();\r |
4717 | });\r |
4718 | })(tinymce);\r |
4719 | (function(tinymce) {\r |
4720 | var each = tinymce.each;\r |
4721 | \r |
4722 | tinymce.create('tinymce.dom.Element', {\r |
4723 | Element : function(id, s) {\r |
4724 | var t = this, dom, el;\r |
4725 | \r |
4726 | s = s || {};\r |
4727 | t.id = id;\r |
4728 | t.dom = dom = s.dom || tinymce.DOM;\r |
4729 | t.settings = s;\r |
4730 | \r |
4731 | // Only IE leaks DOM references, this is a lot faster\r |
4732 | if (!tinymce.isIE)\r |
4733 | el = t.dom.get(t.id);\r |
4734 | \r |
4735 | each([\r |
4736 | 'getPos',\r |
4737 | 'getRect',\r |
4738 | 'getParent',\r |
4739 | 'add',\r |
4740 | 'setStyle',\r |
4741 | 'getStyle',\r |
4742 | 'setStyles',\r |
4743 | 'setAttrib',\r |
4744 | 'setAttribs',\r |
4745 | 'getAttrib',\r |
4746 | 'addClass',\r |
4747 | 'removeClass',\r |
4748 | 'hasClass',\r |
4749 | 'getOuterHTML',\r |
4750 | 'setOuterHTML',\r |
4751 | 'remove',\r |
4752 | 'show',\r |
4753 | 'hide',\r |
4754 | 'isHidden',\r |
4755 | 'setHTML',\r |
4756 | 'get'\r |
4757 | ], function(k) {\r |
4758 | t[k] = function() {\r |
4759 | var a = [id], i;\r |
4760 | \r |
4761 | for (i = 0; i < arguments.length; i++)\r |
4762 | a.push(arguments[i]);\r |
4763 | \r |
4764 | a = dom[k].apply(dom, a);\r |
4765 | t.update(k);\r |
4766 | \r |
4767 | return a;\r |
4768 | };\r |
4769 | });\r |
4770 | },\r |
4771 | \r |
4772 | on : function(n, f, s) {\r |
4773 | return tinymce.dom.Event.add(this.id, n, f, s);\r |
4774 | },\r |
4775 | \r |
4776 | getXY : function() {\r |
4777 | return {\r |
4778 | x : parseInt(this.getStyle('left')),\r |
4779 | y : parseInt(this.getStyle('top'))\r |
4780 | };\r |
4781 | },\r |
4782 | \r |
4783 | getSize : function() {\r |
4784 | var n = this.dom.get(this.id);\r |
4785 | \r |
4786 | return {\r |
4787 | w : parseInt(this.getStyle('width') || n.clientWidth),\r |
4788 | h : parseInt(this.getStyle('height') || n.clientHeight)\r |
4789 | };\r |
4790 | },\r |
4791 | \r |
4792 | moveTo : function(x, y) {\r |
4793 | this.setStyles({left : x, top : y});\r |
4794 | },\r |
4795 | \r |
4796 | moveBy : function(x, y) {\r |
4797 | var p = this.getXY();\r |
4798 | \r |
4799 | this.moveTo(p.x + x, p.y + y);\r |
4800 | },\r |
4801 | \r |
4802 | resizeTo : function(w, h) {\r |
4803 | this.setStyles({width : w, height : h});\r |
4804 | },\r |
4805 | \r |
4806 | resizeBy : function(w, h) {\r |
4807 | var s = this.getSize();\r |
4808 | \r |
4809 | this.resizeTo(s.w + w, s.h + h);\r |
4810 | },\r |
4811 | \r |
4812 | update : function(k) {\r |
4813 | var t = this, b, dom = t.dom;\r |
4814 | \r |
4815 | if (tinymce.isIE6 && t.settings.blocker) {\r |
4816 | k = k || '';\r |
4817 | \r |
4818 | // Ignore getters\r |
4819 | if (k.indexOf('get') === 0 || k.indexOf('has') === 0 || k.indexOf('is') === 0)\r |
4820 | return;\r |
4821 | \r |
4822 | // Remove blocker on remove\r |
4823 | if (k == 'remove') {\r |
4824 | dom.remove(t.blocker);\r |
4825 | return;\r |
4826 | }\r |
4827 | \r |
4828 | if (!t.blocker) {\r |
4829 | t.blocker = dom.uniqueId();\r |
4830 | b = dom.add(t.settings.container || dom.getRoot(), 'iframe', {id : t.blocker, style : 'position:absolute;', frameBorder : 0, src : 'javascript:""'});\r |
4831 | dom.setStyle(b, 'opacity', 0);\r |
4832 | } else\r |
4833 | b = dom.get(t.blocker);\r |
4834 | \r |
4835 | dom.setStyle(b, 'left', t.getStyle('left', 1));\r |
4836 | dom.setStyle(b, 'top', t.getStyle('top', 1));\r |
4837 | dom.setStyle(b, 'width', t.getStyle('width', 1));\r |
4838 | dom.setStyle(b, 'height', t.getStyle('height', 1));\r |
4839 | dom.setStyle(b, 'display', t.getStyle('display', 1));\r |
4840 | dom.setStyle(b, 'zIndex', parseInt(t.getStyle('zIndex', 1) || 0) - 1);\r |
4841 | }\r |
4842 | }\r |
4843 | });\r |
4844 | })(tinymce);\r |
4845 | (function(tinymce) {\r |
4846 | function trimNl(s) {\r |
4847 | return s.replace(/[\n\r]+/g, '');\r |
4848 | };\r |
4849 | \r |
4850 | // Shorten names\r |
4851 | var is = tinymce.is, isIE = tinymce.isIE, each = tinymce.each;\r |
4852 | \r |
4853 | tinymce.create('tinymce.dom.Selection', {\r |
4854 | Selection : function(dom, win, serializer) {\r |
4855 | var t = this;\r |
4856 | \r |
4857 | t.dom = dom;\r |
4858 | t.win = win;\r |
4859 | t.serializer = serializer;\r |
4860 | \r |
4861 | // Add events\r |
4862 | each([\r |
4863 | 'onBeforeSetContent',\r |
4864 | 'onBeforeGetContent',\r |
4865 | 'onSetContent',\r |
4866 | 'onGetContent'\r |
4867 | ], function(e) {\r |
4868 | t[e] = new tinymce.util.Dispatcher(t);\r |
4869 | });\r |
4870 | \r |
4871 | // No W3C Range support\r |
4872 | if (!t.win.getSelection)\r |
4873 | t.tridentSel = new tinymce.dom.TridentSelection(t);\r |
4874 | \r |
4875 | // Prevent leaks\r |
4876 | tinymce.addUnload(t.destroy, t);\r |
4877 | },\r |
4878 | \r |
4879 | getContent : function(s) {\r |
4880 | var t = this, r = t.getRng(), e = t.dom.create("body"), se = t.getSel(), wb, wa, n;\r |
4881 | \r |
4882 | s = s || {};\r |
4883 | wb = wa = '';\r |
4884 | s.get = true;\r |
4885 | s.format = s.format || 'html';\r |
4886 | t.onBeforeGetContent.dispatch(t, s);\r |
4887 | \r |
4888 | if (s.format == 'text')\r |
4889 | return t.isCollapsed() ? '' : (r.text || (se.toString ? se.toString() : ''));\r |
4890 | \r |
4891 | if (r.cloneContents) {\r |
4892 | n = r.cloneContents();\r |
4893 | \r |
4894 | if (n)\r |
4895 | e.appendChild(n);\r |
4896 | } else if (is(r.item) || is(r.htmlText))\r |
4897 | e.innerHTML = r.item ? r.item(0).outerHTML : r.htmlText;\r |
4898 | else\r |
4899 | e.innerHTML = r.toString();\r |
4900 | \r |
4901 | // Keep whitespace before and after\r |
4902 | if (/^\s/.test(e.innerHTML))\r |
4903 | wb = ' ';\r |
4904 | \r |
4905 | if (/\s+$/.test(e.innerHTML))\r |
4906 | wa = ' ';\r |
4907 | \r |
4908 | s.getInner = true;\r |
4909 | \r |
4910 | s.content = t.isCollapsed() ? '' : wb + t.serializer.serialize(e, s) + wa;\r |
4911 | t.onGetContent.dispatch(t, s);\r |
4912 | \r |
4913 | return s.content;\r |
4914 | },\r |
4915 | \r |
4916 | setContent : function(h, s) {\r |
4917 | var t = this, r = t.getRng(), c, d = t.win.document;\r |
4918 | \r |
4919 | s = s || {format : 'html'};\r |
4920 | s.set = true;\r |
4921 | h = s.content = t.dom.processHTML(h);\r |
4922 | \r |
4923 | // Dispatch before set content event\r |
4924 | t.onBeforeSetContent.dispatch(t, s);\r |
4925 | h = s.content;\r |
4926 | \r |
4927 | if (r.insertNode) {\r |
4928 | // Make caret marker since insertNode places the caret in the beginning of text after insert\r |
4929 | h += '<span id="__caret">_</span>';\r |
4930 | \r |
4931 | // Delete and insert new node\r |
4932 | r.deleteContents();\r |
4933 | r.insertNode(t.getRng().createContextualFragment(h));\r |
4934 | \r |
4935 | // Move to caret marker\r |
4936 | c = t.dom.get('__caret');\r |
4937 | \r |
4938 | // Make sure we wrap it compleatly, Opera fails with a simple select call\r |
4939 | r = d.createRange();\r |
4940 | r.setStartBefore(c);\r |
4941 | r.setEndAfter(c);\r |
4942 | t.setRng(r);\r |
4943 | \r |
4944 | // Delete the marker, and hopefully the caret gets placed in the right location\r |
4945 | // Removed this since it seems to remove in FF and simply deleting it\r |
4946 | // doesn't seem to affect the caret position in any browser\r |
4947 | //d.execCommand('Delete', false, null);\r |
4948 | \r |
4949 | // Remove the caret position\r |
4950 | t.dom.remove('__caret');\r |
4951 | } else {\r |
4952 | if (r.item) {\r |
4953 | // Delete content and get caret text selection\r |
4954 | d.execCommand('Delete', false, null);\r |
4955 | r = t.getRng();\r |
4956 | }\r |
4957 | \r |
4958 | r.pasteHTML(h);\r |
4959 | }\r |
4960 | \r |
4961 | // Dispatch set content event\r |
4962 | t.onSetContent.dispatch(t, s);\r |
4963 | },\r |
4964 | \r |
4965 | getStart : function() {\r |
4966 | var t = this, r = t.getRng(), e;\r |
4967 | \r |
4968 | if (isIE) {\r |
4969 | if (r.item)\r |
4970 | return r.item(0);\r |
4971 | \r |
4972 | r = r.duplicate();\r |
4973 | r.collapse(1);\r |
4974 | e = r.parentElement();\r |
4975 | \r |
4976 | if (e && e.nodeName == 'BODY')\r |
4977 | return e.firstChild;\r |
4978 | \r |
4979 | return e;\r |
4980 | } else {\r |
4981 | e = r.startContainer;\r |
4982 | \r |
4983 | if (e.nodeName == 'BODY')\r |
4984 | return e.firstChild;\r |
4985 | \r |
4986 | return t.dom.getParent(e, '*');\r |
4987 | }\r |
4988 | },\r |
4989 | \r |
4990 | getEnd : function() {\r |
4991 | var t = this, r = t.getRng(), e;\r |
4992 | \r |
4993 | if (isIE) {\r |
4994 | if (r.item)\r |
4995 | return r.item(0);\r |
4996 | \r |
4997 | r = r.duplicate();\r |
4998 | r.collapse(0);\r |
4999 | e = r.parentElement();\r |
5000 | \r |
5001 | if (e && e.nodeName == 'BODY')\r |
5002 | return e.lastChild;\r |
5003 | \r |
5004 | return e;\r |
5005 | } else {\r |
5006 | e = r.endContainer;\r |
5007 | \r |
5008 | if (e.nodeName == 'BODY')\r |
5009 | return e.lastChild;\r |
5010 | \r |
5011 | return t.dom.getParent(e, '*');\r |
5012 | }\r |
5013 | },\r |
5014 | \r |
5015 | getBookmark : function(si) {\r |
5016 | var t = this, r = t.getRng(), tr, sx, sy, vp = t.dom.getViewPort(t.win), e, sp, bp, le, c = -0xFFFFFF, s, ro = t.dom.getRoot(), wb = 0, wa = 0, nv;\r |
5017 | sx = vp.x;\r |
5018 | sy = vp.y;\r |
5019 | \r |
5020 | // Simple bookmark fast but not as persistent\r |
5021 | if (si)\r |
5022 | return {rng : r, scrollX : sx, scrollY : sy};\r |
5023 | \r |
5024 | // Handle IE\r |
5025 | if (isIE) {\r |
5026 | // Control selection\r |
5027 | if (r.item) {\r |
5028 | e = r.item(0);\r |
5029 | \r |
5030 | each(t.dom.select(e.nodeName), function(n, i) {\r |
5031 | if (e == n) {\r |
5032 | sp = i;\r |
5033 | return false;\r |
5034 | }\r |
5035 | });\r |
5036 | \r |
5037 | return {\r |
5038 | tag : e.nodeName,\r |
5039 | index : sp,\r |
5040 | scrollX : sx,\r |
5041 | scrollY : sy\r |
5042 | };\r |
5043 | }\r |
5044 | \r |
5045 | // Text selection\r |
5046 | tr = t.dom.doc.body.createTextRange();\r |
5047 | tr.moveToElementText(ro);\r |
5048 | tr.collapse(true);\r |
5049 | bp = Math.abs(tr.move('character', c));\r |
5050 | \r |
5051 | tr = r.duplicate();\r |
5052 | tr.collapse(true);\r |
5053 | sp = Math.abs(tr.move('character', c));\r |
5054 | \r |
5055 | tr = r.duplicate();\r |
5056 | tr.collapse(false);\r |
5057 | le = Math.abs(tr.move('character', c)) - sp;\r |
5058 | \r |
5059 | return {\r |
5060 | start : sp - bp,\r |
5061 | length : le,\r |
5062 | scrollX : sx,\r |
5063 | scrollY : sy\r |
5064 | };\r |
5065 | }\r |
5066 | \r |
5067 | // Handle W3C\r |
5068 | e = t.getNode();\r |
5069 | s = t.getSel();\r |
5070 | \r |
5071 | if (!s)\r |
5072 | return null;\r |
5073 | \r |
5074 | // Image selection\r |
5075 | if (e && e.nodeName == 'IMG') {\r |
5076 | return {\r |
5077 | scrollX : sx,\r |
5078 | scrollY : sy\r |
5079 | };\r |
5080 | }\r |
5081 | \r |
5082 | // Text selection\r |
5083 | \r |
5084 | function getPos(r, sn, en) {\r |
5085 | var w = t.dom.doc.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {};\r |
5086 | \r |
5087 | while ((n = w.nextNode()) != null) {\r |
5088 | if (n == sn)\r |
5089 | d.start = p;\r |
5090 | \r |
5091 | if (n == en) {\r |
5092 | d.end = p;\r |
5093 | return d;\r |
5094 | }\r |
5095 | \r |
5096 | p += trimNl(n.nodeValue || '').length;\r |
5097 | }\r |
5098 | \r |
5099 | return null;\r |
5100 | };\r |
5101 | \r |
5102 | // Caret or selection\r |
5103 | if (s.anchorNode == s.focusNode && s.anchorOffset == s.focusOffset) {\r |
5104 | e = getPos(ro, s.anchorNode, s.focusNode);\r |
5105 | \r |
5106 | if (!e)\r |
5107 | return {scrollX : sx, scrollY : sy};\r |
5108 | \r |
5109 | // Count whitespace before\r |
5110 | trimNl(s.anchorNode.nodeValue || '').replace(/^\s+/, function(a) {wb = a.length;});\r |
5111 | \r |
5112 | return {\r |
5113 | start : Math.max(e.start + s.anchorOffset - wb, 0),\r |
5114 | end : Math.max(e.end + s.focusOffset - wb, 0),\r |
5115 | scrollX : sx,\r |
5116 | scrollY : sy,\r |
5117 | beg : s.anchorOffset - wb == 0\r |
5118 | };\r |
5119 | } else {\r |
5120 | e = getPos(ro, r.startContainer, r.endContainer);\r |
5121 | \r |
5122 | // Count whitespace before start and end container\r |
5123 | //(r.startContainer.nodeValue || '').replace(/^\s+/, function(a) {wb = a.length;});\r |
5124 | //(r.endContainer.nodeValue || '').replace(/^\s+/, function(a) {wa = a.length;});\r |
5125 | \r |
5126 | if (!e)\r |
5127 | return {scrollX : sx, scrollY : sy};\r |
5128 | \r |
5129 | return {\r |
5130 | start : Math.max(e.start + r.startOffset - wb, 0),\r |
5131 | end : Math.max(e.end + r.endOffset - wa, 0),\r |
5132 | scrollX : sx,\r |
5133 | scrollY : sy,\r |
5134 | beg : r.startOffset - wb == 0\r |
5135 | };\r |
5136 | }\r |
5137 | },\r |
5138 | \r |
5139 | moveToBookmark : function(b) {\r |
5140 | var t = this, r = t.getRng(), s = t.getSel(), ro = t.dom.getRoot(), sd, nvl, nv;\r |
5141 | \r |
5142 | function getPos(r, sp, ep) {\r |
5143 | var w = t.dom.doc.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {}, o, v, wa, wb;\r |
5144 | \r |
5145 | while ((n = w.nextNode()) != null) {\r |
5146 | wa = wb = 0;\r |
5147 | \r |
5148 | nv = n.nodeValue || '';\r |
5149 | //nv.replace(/^\s+[^\s]/, function(a) {wb = a.length - 1;});\r |
5150 | //nv.replace(/[^\s]\s+$/, function(a) {wa = a.length - 1;});\r |
5151 | \r |
5152 | nvl = trimNl(nv).length;\r |
5153 | p += nvl;\r |
5154 | \r |
5155 | if (p >= sp && !d.startNode) {\r |
5156 | o = sp - (p - nvl);\r |
5157 | \r |
5158 | // Fix for odd quirk in FF\r |
5159 | if (b.beg && o >= nvl)\r |
5160 | continue;\r |
5161 | \r |
5162 | d.startNode = n;\r |
5163 | d.startOffset = o + wb;\r |
5164 | }\r |
5165 | \r |
5166 | if (p >= ep) {\r |
5167 | d.endNode = n;\r |
5168 | d.endOffset = ep - (p - nvl) + wb;\r |
5169 | return d;\r |
5170 | }\r |
5171 | }\r |
5172 | \r |
5173 | return null;\r |
5174 | };\r |
5175 | \r |
5176 | if (!b)\r |
5177 | return false;\r |
5178 | \r |
5179 | t.win.scrollTo(b.scrollX, b.scrollY);\r |
5180 | \r |
5181 | // Handle explorer\r |
5182 | if (isIE) {\r |
5183 | t.tridentSel.destroy();\r |
5184 | \r |
5185 | // Handle simple\r |
5186 | if (r = b.rng) {\r |
5187 | try {\r |
5188 | r.select();\r |
5189 | } catch (ex) {\r |
5190 | // Ignore\r |
5191 | }\r |
5192 | \r |
5193 | return true;\r |
5194 | }\r |
5195 | \r |
5196 | t.win.focus();\r |
5197 | \r |
5198 | // Handle control bookmark\r |
5199 | if (b.tag) {\r |
5200 | r = ro.createControlRange();\r |
5201 | \r |
5202 | each(t.dom.select(b.tag), function(n, i) {\r |
5203 | if (i == b.index)\r |
5204 | r.addElement(n);\r |
5205 | });\r |
5206 | } else {\r |
5207 | // Try/catch needed since this operation breaks when TinyMCE is placed in hidden divs/tabs\r |
5208 | try {\r |
5209 | // Incorrect bookmark\r |
5210 | if (b.start < 0)\r |
5211 | return true;\r |
5212 | \r |
5213 | r = s.createRange();\r |
5214 | r.moveToElementText(ro);\r |
5215 | r.collapse(true);\r |
5216 | r.moveStart('character', b.start);\r |
5217 | r.moveEnd('character', b.length);\r |
5218 | } catch (ex2) {\r |
5219 | return true;\r |
5220 | }\r |
5221 | }\r |
5222 | \r |
5223 | try {\r |
5224 | r.select();\r |
5225 | } catch (ex) {\r |
5226 | // Needed for some odd IE bug #1843306\r |
5227 | }\r |
5228 | \r |
5229 | return true;\r |
5230 | }\r |
5231 | \r |
5232 | // Handle W3C\r |
5233 | if (!s)\r |
5234 | return false;\r |
5235 | \r |
5236 | // Handle simple\r |
5237 | if (b.rng) {\r |
5238 | s.removeAllRanges();\r |
5239 | s.addRange(b.rng);\r |
5240 | } else {\r |
5241 | if (is(b.start) && is(b.end)) {\r |
5242 | try {\r |
5243 | sd = getPos(ro, b.start, b.end);\r |
5244 | \r |
5245 | if (sd) {\r |
5246 | r = t.dom.doc.createRange();\r |
5247 | r.setStart(sd.startNode, sd.startOffset);\r |
5248 | r.setEnd(sd.endNode, sd.endOffset);\r |
5249 | s.removeAllRanges();\r |
5250 | s.addRange(r);\r |
5251 | }\r |
5252 | \r |
5253 | if (!tinymce.isOpera)\r |
5254 | t.win.focus();\r |
5255 | } catch (ex) {\r |
5256 | // Ignore\r |
5257 | }\r |
5258 | }\r |
5259 | }\r |
5260 | },\r |
5261 | \r |
5262 | select : function(n, c) {\r |
5263 | var t = this, r = t.getRng(), s = t.getSel(), b, fn, ln, d = t.win.document;\r |
5264 | \r |
5265 | function find(n, start) {\r |
5266 | var walker, o;\r |
5267 | \r |
5268 | if (n) {\r |
5269 | walker = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);\r |
5270 | \r |
5271 | // Find first/last non empty text node\r |
5272 | while (n = walker.nextNode()) {\r |
5273 | o = n;\r |
5274 | \r |
5275 | if (tinymce.trim(n.nodeValue).length != 0) {\r |
5276 | if (start)\r |
5277 | return n;\r |
5278 | else\r |
5279 | o = n;\r |
5280 | }\r |
5281 | }\r |
5282 | }\r |
5283 | \r |
5284 | return o;\r |
5285 | };\r |
5286 | \r |
5287 | if (isIE) {\r |
5288 | try {\r |
5289 | b = d.body;\r |
5290 | \r |
5291 | if (/^(IMG|TABLE)$/.test(n.nodeName)) {\r |
5292 | r = b.createControlRange();\r |
5293 | r.addElement(n);\r |
5294 | } else {\r |
5295 | r = b.createTextRange();\r |
5296 | r.moveToElementText(n);\r |
5297 | }\r |
5298 | \r |
5299 | r.select();\r |
5300 | } catch (ex) {\r |
5301 | // Throws illigal agrument in IE some times\r |
5302 | }\r |
5303 | } else {\r |
5304 | if (c) {\r |
5305 | fn = find(n, 1) || t.dom.select('br:first', n)[0];\r |
5306 | ln = find(n, 0) || t.dom.select('br:last', n)[0];\r |
5307 | \r |
5308 | if (fn && ln) {\r |
5309 | r = d.createRange();\r |
5310 | \r |
5311 | if (fn.nodeName == 'BR')\r |
5312 | r.setStartBefore(fn);\r |
5313 | else\r |
5314 | r.setStart(fn, 0);\r |
5315 | \r |
5316 | if (ln.nodeName == 'BR')\r |
5317 | r.setEndBefore(ln);\r |
5318 | else\r |
5319 | r.setEnd(ln, ln.nodeValue.length);\r |
5320 | } else\r |
5321 | r.selectNode(n);\r |
5322 | } else\r |
5323 | r.selectNode(n);\r |
5324 | \r |
5325 | t.setRng(r);\r |
5326 | }\r |
5327 | \r |
5328 | \r |
5329 | return n;\r |
5330 | },\r |
5331 | \r |
5332 | isCollapsed : function() {\r |
5333 | var t = this, r = t.getRng(), s = t.getSel();\r |
5334 | \r |
5335 | if (!r || r.item)\r |
5336 | return false;\r |
5337 | \r |
5338 | return !s || r.boundingWidth == 0 || r.collapsed;\r |
5339 | },\r |
5340 | \r |
5341 | collapse : function(b) {\r |
5342 | var t = this, r = t.getRng(), n;\r |
5343 | \r |
5344 | // Control range on IE\r |
5345 | if (r.item) {\r |
5346 | n = r.item(0);\r |
5347 | r = this.win.document.body.createTextRange();\r |
5348 | r.moveToElementText(n);\r |
5349 | }\r |
5350 | \r |
5351 | r.collapse(!!b);\r |
5352 | t.setRng(r);\r |
5353 | },\r |
5354 | \r |
5355 | getSel : function() {\r |
5356 | var t = this, w = this.win;\r |
5357 | \r |
5358 | return w.getSelection ? w.getSelection() : w.document.selection;\r |
5359 | },\r |
5360 | \r |
5361 | getRng : function(w3c) {\r |
5362 | var t = this, s, r;\r |
5363 | \r |
5364 | // Found tridentSel object then we need to use that one\r |
5365 | if (w3c && t.tridentSel)\r |
5366 | return t.tridentSel.getRangeAt(0);\r |
5367 | \r |
5368 | try {\r |
5369 | if (s = t.getSel())\r |
5370 | r = s.rangeCount > 0 ? s.getRangeAt(0) : (s.createRange ? s.createRange() : t.win.document.createRange());\r |
5371 | } catch (ex) {\r |
5372 | // IE throws unspecified error here if TinyMCE is placed in a frame/iframe\r |
5373 | }\r |
5374 | \r |
5375 | // No range found then create an empty one\r |
5376 | // This can occur when the editor is placed in a hidden container element on Gecko\r |
5377 | // Or on IE when there was an exception\r |
5378 | if (!r)\r |
5379 | r = isIE ? t.win.document.body.createTextRange() : t.win.document.createRange();\r |
5380 | \r |
5381 | return r;\r |
5382 | },\r |
5383 | \r |
5384 | setRng : function(r) {\r |
5385 | var s, t = this;\r |
5386 | \r |
5387 | if (!t.tridentSel) {\r |
5388 | s = t.getSel();\r |
5389 | \r |
5390 | if (s) {\r |
5391 | s.removeAllRanges();\r |
5392 | s.addRange(r);\r |
5393 | }\r |
5394 | } else {\r |
5395 | // Is W3C Range\r |
5396 | if (r.cloneRange) {\r |
5397 | t.tridentSel.addRange(r);\r |
5398 | return;\r |
5399 | }\r |
5400 | \r |
5401 | // Is IE specific range\r |
5402 | try {\r |
5403 | r.select();\r |
5404 | } catch (ex) {\r |
5405 | // Needed for some odd IE bug #1843306\r |
5406 | }\r |
5407 | }\r |
5408 | },\r |
5409 | \r |
5410 | setNode : function(n) {\r |
5411 | var t = this;\r |
5412 | \r |
5413 | t.setContent(t.dom.getOuterHTML(n));\r |
5414 | \r |
5415 | return n;\r |
5416 | },\r |
5417 | \r |
5418 | getNode : function() {\r |
5419 | var t = this, r = t.getRng(), s = t.getSel(), e;\r |
5420 | \r |
5421 | if (!isIE) {\r |
5422 | // Range maybe lost after the editor is made visible again\r |
5423 | if (!r)\r |
5424 | return t.dom.getRoot();\r |
5425 | \r |
5426 | e = r.commonAncestorContainer;\r |
5427 | \r |
5428 | // Handle selection a image or other control like element such as anchors\r |
5429 | if (!r.collapsed) {\r |
5430 | // If the anchor node is a element instead of a text node then return this element\r |
5431 | if (tinymce.isWebKit && s.anchorNode && s.anchorNode.nodeType == 1) \r |
5432 | return s.anchorNode.childNodes[s.anchorOffset]; \r |
5433 | \r |
5434 | if (r.startContainer == r.endContainer) {\r |
5435 | if (r.startOffset - r.endOffset < 2) {\r |
5436 | if (r.startContainer.hasChildNodes())\r |
5437 | e = r.startContainer.childNodes[r.startOffset];\r |
5438 | }\r |
5439 | }\r |
5440 | }\r |
5441 | \r |
5442 | return t.dom.getParent(e, '*');\r |
5443 | }\r |
5444 | \r |
5445 | return r.item ? r.item(0) : r.parentElement();\r |
5446 | },\r |
5447 | \r |
5448 | getSelectedBlocks : function(st, en) {\r |
5449 | var t = this, dom = t.dom, sb, eb, n, bl = [];\r |
5450 | \r |
5451 | sb = dom.getParent(st || t.getStart(), dom.isBlock);\r |
5452 | eb = dom.getParent(en || t.getEnd(), dom.isBlock);\r |
5453 | \r |
5454 | if (sb)\r |
5455 | bl.push(sb);\r |
5456 | \r |
5457 | if (sb && eb && sb != eb) {\r |
5458 | n = sb;\r |
5459 | \r |
5460 | while ((n = n.nextSibling) && n != eb) {\r |
5461 | if (dom.isBlock(n))\r |
5462 | bl.push(n);\r |
5463 | }\r |
5464 | }\r |
5465 | \r |
5466 | if (eb && sb != eb)\r |
5467 | bl.push(eb);\r |
5468 | \r |
5469 | return bl;\r |
5470 | },\r |
5471 | \r |
5472 | destroy : function(s) {\r |
5473 | var t = this;\r |
5474 | \r |
5475 | t.win = null;\r |
5476 | \r |
5477 | if (t.tridentSel)\r |
5478 | t.tridentSel.destroy();\r |
5479 | \r |
5480 | // Manual destroy then remove unload handler\r |
5481 | if (!s)\r |
5482 | tinymce.removeUnload(t.destroy);\r |
5483 | }\r |
5484 | });\r |
5485 | })(tinymce);\r |
5486 | (function(tinymce) {\r |
5487 | tinymce.create('tinymce.dom.XMLWriter', {\r |
5488 | node : null,\r |
5489 | \r |
5490 | XMLWriter : function(s) {\r |
5491 | // Get XML document\r |
5492 | function getXML() {\r |
5493 | var i = document.implementation;\r |
5494 | \r |
5495 | if (!i || !i.createDocument) {\r |
5496 | // Try IE objects\r |
5497 | try {return new ActiveXObject('MSXML2.DOMDocument');} catch (ex) {}\r |
5498 | try {return new ActiveXObject('Microsoft.XmlDom');} catch (ex) {}\r |
5499 | } else\r |
5500 | return i.createDocument('', '', null);\r |
5501 | };\r |
5502 | \r |
5503 | this.doc = getXML();\r |
5504 | \r |
5505 | // Since Opera and WebKit doesn't escape > into > we need to do it our self to normalize the output for all browsers\r |
5506 | this.valid = tinymce.isOpera || tinymce.isWebKit;\r |
5507 | \r |
5508 | this.reset();\r |
5509 | },\r |
5510 | \r |
5511 | reset : function() {\r |
5512 | var t = this, d = t.doc;\r |
5513 | \r |
5514 | if (d.firstChild)\r |
5515 | d.removeChild(d.firstChild);\r |
5516 | \r |
5517 | t.node = d.appendChild(d.createElement("html"));\r |
5518 | },\r |
5519 | \r |
5520 | writeStartElement : function(n) {\r |
5521 | var t = this;\r |
5522 | \r |
5523 | t.node = t.node.appendChild(t.doc.createElement(n));\r |
5524 | },\r |
5525 | \r |
5526 | writeAttribute : function(n, v) {\r |
5527 | if (this.valid)\r |
5528 | v = v.replace(/>/g, '%MCGT%');\r |
5529 | \r |
5530 | this.node.setAttribute(n, v);\r |
5531 | },\r |
5532 | \r |
5533 | writeEndElement : function() {\r |
5534 | this.node = this.node.parentNode;\r |
5535 | },\r |
5536 | \r |
5537 | writeFullEndElement : function() {\r |
5538 | var t = this, n = t.node;\r |
5539 | \r |
5540 | n.appendChild(t.doc.createTextNode(""));\r |
5541 | t.node = n.parentNode;\r |
5542 | },\r |
5543 | \r |
5544 | writeText : function(v) {\r |
5545 | if (this.valid)\r |
5546 | v = v.replace(/>/g, '%MCGT%');\r |
5547 | \r |
5548 | this.node.appendChild(this.doc.createTextNode(v));\r |
5549 | },\r |
5550 | \r |
5551 | writeCDATA : function(v) {\r |
5552 | this.node.appendChild(this.doc.createCDATASection(v));\r |
5553 | },\r |
5554 | \r |
5555 | writeComment : function(v) {\r |
5556 | // Fix for bug #2035694\r |
5557 | if (tinymce.isIE)\r |
5558 | v = v.replace(/^\-|\-$/g, ' ');\r |
5559 | \r |
5560 | this.node.appendChild(this.doc.createComment(v.replace(/\-\-/g, ' ')));\r |
5561 | },\r |
5562 | \r |
5563 | getContent : function() {\r |
5564 | var h;\r |
5565 | \r |
5566 | h = this.doc.xml || new XMLSerializer().serializeToString(this.doc);\r |
5567 | h = h.replace(/<\?[^?]+\?>|<html>|<\/html>|<html\/>|<!DOCTYPE[^>]+>/g, '');\r |
5568 | h = h.replace(/ ?\/>/g, ' />');\r |
5569 | \r |
5570 | if (this.valid)\r |
5571 | h = h.replace(/\%MCGT%/g, '>');\r |
5572 | \r |
5573 | return h;\r |
5574 | }\r |
5575 | });\r |
5576 | })(tinymce);\r |
5577 | (function(tinymce) {\r |
5578 | tinymce.create('tinymce.dom.StringWriter', {\r |
5579 | str : null,\r |
5580 | tags : null,\r |
5581 | count : 0,\r |
5582 | settings : null,\r |
5583 | indent : null,\r |
5584 | \r |
5585 | StringWriter : function(s) {\r |
5586 | this.settings = tinymce.extend({\r |
5587 | indent_char : ' ',\r |
5588 | indentation : 0\r |
5589 | }, s);\r |
5590 | \r |
5591 | this.reset();\r |
5592 | },\r |
5593 | \r |
5594 | reset : function() {\r |
5595 | this.indent = '';\r |
5596 | this.str = "";\r |
5597 | this.tags = [];\r |
5598 | this.count = 0;\r |
5599 | },\r |
5600 | \r |
5601 | writeStartElement : function(n) {\r |
5602 | this._writeAttributesEnd();\r |
5603 | this.writeRaw('<' + n);\r |
5604 | this.tags.push(n);\r |
5605 | this.inAttr = true;\r |
5606 | this.count++;\r |
5607 | this.elementCount = this.count;\r |
5608 | },\r |
5609 | \r |
5610 | writeAttribute : function(n, v) {\r |
5611 | var t = this;\r |
5612 | \r |
5613 | t.writeRaw(" " + t.encode(n) + '="' + t.encode(v) + '"');\r |
5614 | },\r |
5615 | \r |
5616 | writeEndElement : function() {\r |
5617 | var n;\r |
5618 | \r |
5619 | if (this.tags.length > 0) {\r |
5620 | n = this.tags.pop();\r |
5621 | \r |
5622 | if (this._writeAttributesEnd(1))\r |
5623 | this.writeRaw('</' + n + '>');\r |
5624 | \r |
5625 | if (this.settings.indentation > 0)\r |
5626 | this.writeRaw('\n');\r |
5627 | }\r |
5628 | },\r |
5629 | \r |
5630 | writeFullEndElement : function() {\r |
5631 | if (this.tags.length > 0) {\r |
5632 | this._writeAttributesEnd();\r |
5633 | this.writeRaw('</' + this.tags.pop() + '>');\r |
5634 | \r |
5635 | if (this.settings.indentation > 0)\r |
5636 | this.writeRaw('\n');\r |
5637 | }\r |
5638 | },\r |
5639 | \r |
5640 | writeText : function(v) {\r |
5641 | this._writeAttributesEnd();\r |
5642 | this.writeRaw(this.encode(v));\r |
5643 | this.count++;\r |
5644 | },\r |
5645 | \r |
5646 | writeCDATA : function(v) {\r |
5647 | this._writeAttributesEnd();\r |
5648 | this.writeRaw('<![CDATA[' + v + ']]>');\r |
5649 | this.count++;\r |
5650 | },\r |
5651 | \r |
5652 | writeComment : function(v) {\r |
5653 | this._writeAttributesEnd();\r |
5654 | this.writeRaw('<!-- ' + v + '-->');\r |
5655 | this.count++;\r |
5656 | },\r |
5657 | \r |
5658 | writeRaw : function(v) {\r |
5659 | this.str += v;\r |
5660 | },\r |
5661 | \r |
5662 | encode : function(s) {\r |
5663 | return s.replace(/[<>&"]/g, function(v) {\r |
5664 | switch (v) {\r |
5665 | case '<':\r |
5666 | return '<';\r |
5667 | \r |
5668 | case '>':\r |
5669 | return '>';\r |
5670 | \r |
5671 | case '&':\r |
5672 | return '&';\r |
5673 | \r |
5674 | case '"':\r |
5675 | return '"';\r |
5676 | }\r |
5677 | \r |
5678 | return v;\r |
5679 | });\r |
5680 | },\r |
5681 | \r |
5682 | getContent : function() {\r |
5683 | return this.str;\r |
5684 | },\r |
5685 | \r |
5686 | _writeAttributesEnd : function(s) {\r |
5687 | if (!this.inAttr)\r |
5688 | return;\r |
5689 | \r |
5690 | this.inAttr = false;\r |
5691 | \r |
5692 | if (s && this.elementCount == this.count) {\r |
5693 | this.writeRaw(' />');\r |
5694 | return false;\r |
5695 | }\r |
5696 | \r |
5697 | this.writeRaw('>');\r |
5698 | \r |
5699 | return true;\r |
5700 | }\r |
5701 | });\r |
5702 | })(tinymce);\r |
5703 | (function(tinymce) {\r |
5704 | // Shorten names\r |
5705 | var extend = tinymce.extend, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher, isIE = tinymce.isIE, isGecko = tinymce.isGecko;\r |
5706 | \r |
5707 | function wildcardToRE(s) {\r |
5708 | return s.replace(/([?+*])/g, '.$1');\r |
5709 | };\r |
5710 | \r |
5711 | tinymce.create('tinymce.dom.Serializer', {\r |
5712 | Serializer : function(s) {\r |
5713 | var t = this;\r |
5714 | \r |
5715 | t.key = 0;\r |
5716 | t.onPreProcess = new Dispatcher(t);\r |
5717 | t.onPostProcess = new Dispatcher(t);\r |
5718 | \r |
5719 | try {\r |
5720 | t.writer = new tinymce.dom.XMLWriter();\r |
5721 | } catch (ex) {\r |
5722 | // IE might throw exception if ActiveX is disabled so we then switch to the slightly slower StringWriter\r |
5723 | t.writer = new tinymce.dom.StringWriter();\r |
5724 | }\r |
5725 | \r |
5726 | // Default settings\r |
5727 | t.settings = s = extend({\r |
5728 | dom : tinymce.DOM,\r |
5729 | valid_nodes : 0,\r |
5730 | node_filter : 0,\r |
5731 | attr_filter : 0,\r |
5732 | invalid_attrs : /^(mce_|_moz_|sizset|sizcache)/,\r |
5733 | closed : /(br|hr|input|meta|img|link|param|area)/,\r |
5734 | entity_encoding : 'named',\r |
5735 | entities : '160,nbsp,161,iexcl,162,cent,163,pound,164,curren,165,yen,166,brvbar,167,sect,168,uml,169,copy,170,ordf,171,laquo,172,not,173,shy,174,reg,175,macr,176,deg,177,plusmn,178,sup2,179,sup3,180,acute,181,micro,182,para,183,middot,184,cedil,185,sup1,186,ordm,187,raquo,188,frac14,189,frac12,190,frac34,191,iquest,192,Agrave,193,Aacute,194,Acirc,195,Atilde,196,Auml,197,Aring,198,AElig,199,Ccedil,200,Egrave,201,Eacute,202,Ecirc,203,Euml,204,Igrave,205,Iacute,206,Icirc,207,Iuml,208,ETH,209,Ntilde,210,Ograve,211,Oacute,212,Ocirc,213,Otilde,214,Ouml,215,times,216,Oslash,217,Ugrave,218,Uacute,219,Ucirc,220,Uuml,221,Yacute,222,THORN,223,szlig,224,agrave,225,aacute,226,acirc,227,atilde,228,auml,229,aring,230,aelig,231,ccedil,232,egrave,233,eacute,234,ecirc,235,euml,236,igrave,237,iacute,238,icirc,239,iuml,240,eth,241,ntilde,242,ograve,243,oacute,244,ocirc,245,otilde,246,ouml,247,divide,248,oslash,249,ugrave,250,uacute,251,ucirc,252,uuml,253,yacute,254,thorn,255,yuml,402,fnof,913,Alpha,914,Beta,915,Gamma,916,Delta,917,Epsilon,918,Zeta,919,Eta,920,Theta,921,Iota,922,Kappa,923,Lambda,924,Mu,925,Nu,926,Xi,927,Omicron,928,Pi,929,Rho,931,Sigma,932,Tau,933,Upsilon,934,Phi,935,Chi,936,Psi,937,Omega,945,alpha,946,beta,947,gamma,948,delta,949,epsilon,950,zeta,951,eta,952,theta,953,iota,954,kappa,955,lambda,956,mu,957,nu,958,xi,959,omicron,960,pi,961,rho,962,sigmaf,963,sigma,964,tau,965,upsilon,966,phi,967,chi,968,psi,969,omega,977,thetasym,978,upsih,982,piv,8226,bull,8230,hellip,8242,prime,8243,Prime,8254,oline,8260,frasl,8472,weierp,8465,image,8476,real,8482,trade,8501,alefsym,8592,larr,8593,uarr,8594,rarr,8595,darr,8596,harr,8629,crarr,8656,lArr,8657,uArr,8658,rArr,8659,dArr,8660,hArr,8704,forall,8706,part,8707,exist,8709,empty,8711,nabla,8712,isin,8713,notin,8715,ni,8719,prod,8721,sum,8722,minus,8727,lowast,8730,radic,8733,prop,8734,infin,8736,ang,8743,and,8744,or,8745,cap,8746,cup,8747,int,8756,there4,8764,sim,8773,cong,8776,asymp,8800,ne,8801,equiv,8804,le,8805,ge,8834,sub,8835,sup,8836,nsub,8838,sube,8839,supe,8853,oplus,8855,otimes,8869,perp,8901,sdot,8968,lceil,8969,rceil,8970,lfloor,8971,rfloor,9001,lang,9002,rang,9674,loz,9824,spades,9827,clubs,9829,hearts,9830,diams,338,OElig,339,oelig,352,Scaron,353,scaron,376,Yuml,710,circ,732,tilde,8194,ensp,8195,emsp,8201,thinsp,8204,zwnj,8205,zwj,8206,lrm,8207,rlm,8211,ndash,8212,mdash,8216,lsquo,8217,rsquo,8218,sbquo,8220,ldquo,8221,rdquo,8222,bdquo,8224,dagger,8225,Dagger,8240,permil,8249,lsaquo,8250,rsaquo,8364,euro',\r |
5736 | valid_elements : '*[*]',\r |
5737 | extended_valid_elements : 0,\r |
5738 | valid_child_elements : 0,\r |
5739 | invalid_elements : 0,\r |
5740 | fix_table_elements : 1,\r |
5741 | fix_list_elements : true,\r |
5742 | fix_content_duplication : true,\r |
5743 | convert_fonts_to_spans : false,\r |
5744 | font_size_classes : 0,\r |
5745 | font_size_style_values : 0,\r |
5746 | apply_source_formatting : 0,\r |
5747 | indent_mode : 'simple',\r |
5748 | indent_char : '\t',\r |
5749 | indent_levels : 1,\r |
5750 | remove_linebreaks : 1,\r |
5751 | remove_redundant_brs : 1,\r |
5752 | element_format : 'xhtml'\r |
5753 | }, s);\r |
5754 | \r |
5755 | t.dom = s.dom;\r |
5756 | \r |
5757 | if (s.remove_redundant_brs) {\r |
5758 | t.onPostProcess.add(function(se, o) {\r |
5759 | // Remove single BR at end of block elements since they get rendered\r |
5760 | o.content = o.content.replace(/(<br \/>\s*)+<\/(p|h[1-6]|div|li)>/gi, function(a, b, c) {\r |
5761 | // Check if it's a single element\r |
5762 | if (/^<br \/>\s*<\//.test(a))\r |
5763 | return '</' + c + '>';\r |
5764 | \r |
5765 | return a;\r |
5766 | });\r |
5767 | });\r |
5768 | }\r |
5769 | \r |
5770 | // Remove XHTML element endings i.e. produce crap :) XHTML is better\r |
5771 | if (s.element_format == 'html') {\r |
5772 | t.onPostProcess.add(function(se, o) {\r |
5773 | o.content = o.content.replace(/<([^>]+) \/>/g, '<$1>');\r |
5774 | });\r |
5775 | }\r |
5776 | \r |
5777 | if (s.fix_list_elements) {\r |
5778 | t.onPreProcess.add(function(se, o) {\r |
5779 | var nl, x, a = ['ol', 'ul'], i, n, p, r = /^(OL|UL)$/, np;\r |
5780 | \r |
5781 | function prevNode(e, n) {\r |
5782 | var a = n.split(','), i;\r |
5783 | \r |
5784 | while ((e = e.previousSibling) != null) {\r |
5785 | for (i=0; i<a.length; i++) {\r |
5786 | if (e.nodeName == a[i])\r |
5787 | return e;\r |
5788 | }\r |
5789 | }\r |
5790 | \r |
5791 | return null;\r |
5792 | };\r |
5793 | \r |
5794 | for (x=0; x<a.length; x++) {\r |
5795 | nl = t.dom.select(a[x], o.node);\r |
5796 | \r |
5797 | for (i=0; i<nl.length; i++) {\r |
5798 | n = nl[i];\r |
5799 | p = n.parentNode;\r |
5800 | \r |
5801 | if (r.test(p.nodeName)) {\r |
5802 | np = prevNode(n, 'LI');\r |
5803 | \r |
5804 | if (!np) {\r |
5805 | np = t.dom.create('li');\r |
5806 | np.innerHTML = ' ';\r |
5807 | np.appendChild(n);\r |
5808 | p.insertBefore(np, p.firstChild);\r |
5809 | } else\r |
5810 | np.appendChild(n);\r |
5811 | }\r |
5812 | }\r |
5813 | }\r |
5814 | });\r |
5815 | }\r |
5816 | \r |
5817 | if (s.fix_table_elements) {\r |
5818 | t.onPreProcess.add(function(se, o) {\r |
5819 | // Since Opera will crash if you attach the node to a dynamic document we need to brrowser sniff a specific build\r |
5820 | // so Opera users with an older version will have to live with less compaible output not much we can do here\r |
5821 | if (!tinymce.isOpera || opera.buildNumber() >= 1767) {\r |
5822 | each(t.dom.select('p table', o.node).reverse(), function(n) {\r |
5823 | var parent = t.dom.getParent(n.parentNode, 'table,p');\r |
5824 | \r |
5825 | if (parent.nodeName != 'TABLE') {\r |
5826 | try {\r |
5827 | t.dom.split(parent, n);\r |
5828 | } catch (ex) {\r |
5829 | // IE can sometimes fire an unknown runtime error so we just ignore it\r |
5830 | }\r |
5831 | }\r |
5832 | });\r |
5833 | }\r |
5834 | });\r |
5835 | }\r |
5836 | },\r |
5837 | \r |
5838 | setEntities : function(s) {\r |
5839 | var t = this, a, i, l = {}, re = '', v;\r |
5840 | \r |
5841 | // No need to setup more than once\r |
5842 | if (t.entityLookup)\r |
5843 | return;\r |
5844 | \r |
5845 | // Build regex and lookup array\r |
5846 | a = s.split(',');\r |
5847 | for (i = 0; i < a.length; i += 2) {\r |
5848 | v = a[i];\r |
5849 | \r |
5850 | // Don't add default & " etc.\r |
5851 | if (v == 34 || v == 38 || v == 60 || v == 62)\r |
5852 | continue;\r |
5853 | \r |
5854 | l[String.fromCharCode(a[i])] = a[i + 1];\r |
5855 | \r |
5856 | v = parseInt(a[i]).toString(16);\r |
5857 | re += '\\u' + '0000'.substring(v.length) + v;\r |
5858 | }\r |
5859 | \r |
5860 | if (!re) {\r |
5861 | t.settings.entity_encoding = 'raw';\r |
5862 | return;\r |
5863 | }\r |
5864 | \r |
5865 | t.entitiesRE = new RegExp('[' + re + ']', 'g');\r |
5866 | t.entityLookup = l;\r |
5867 | },\r |
5868 | \r |
5869 | setValidChildRules : function(s) {\r |
5870 | this.childRules = null;\r |
5871 | this.addValidChildRules(s);\r |
5872 | },\r |
5873 | \r |
5874 | addValidChildRules : function(s) {\r |
5875 | var t = this, inst, intr, bloc;\r |
5876 | \r |
5877 | if (!s)\r |
5878 | return;\r |
5879 | \r |
5880 | inst = 'A|BR|SPAN|BDO|MAP|OBJECT|IMG|TT|I|B|BIG|SMALL|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|#text|#comment';\r |
5881 | intr = 'A|BR|SPAN|BDO|OBJECT|APPLET|IMG|MAP|IFRAME|TT|I|B|U|S|STRIKE|BIG|SMALL|FONT|BASEFONT|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|INPUT|SELECT|TEXTAREA|LABEL|BUTTON|#text|#comment';\r |
5882 | bloc = 'H[1-6]|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|FORM|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP';\r |
5883 | \r |
5884 | each(s.split(','), function(s) {\r |
5885 | var p = s.split(/\[|\]/), re;\r |
5886 | \r |
5887 | s = '';\r |
5888 | each(p[1].split('|'), function(v) {\r |
5889 | if (s)\r |
5890 | s += '|';\r |
5891 | \r |
5892 | switch (v) {\r |
5893 | case '%itrans':\r |
5894 | v = intr;\r |
5895 | break;\r |
5896 | \r |
5897 | case '%itrans_na':\r |
5898 | v = intr.substring(2);\r |
5899 | break;\r |
5900 | \r |
5901 | case '%istrict':\r |
5902 | v = inst;\r |
5903 | break;\r |
5904 | \r |
5905 | case '%istrict_na':\r |
5906 | v = inst.substring(2);\r |
5907 | break;\r |
5908 | \r |
5909 | case '%btrans':\r |
5910 | v = bloc;\r |
5911 | break;\r |
5912 | \r |
5913 | case '%bstrict':\r |
5914 | v = bloc;\r |
5915 | break;\r |
5916 | }\r |
5917 | \r |
5918 | s += v;\r |
5919 | });\r |
5920 | re = new RegExp('^(' + s.toLowerCase() + ')$', 'i');\r |
5921 | \r |
5922 | each(p[0].split('/'), function(s) {\r |
5923 | t.childRules = t.childRules || {};\r |
5924 | t.childRules[s] = re;\r |
5925 | });\r |
5926 | });\r |
5927 | \r |
5928 | // Build regex\r |
5929 | s = '';\r |
5930 | each(t.childRules, function(v, k) {\r |
5931 | if (s)\r |
5932 | s += '|';\r |
5933 | \r |
5934 | s += k;\r |
5935 | });\r |
5936 | \r |
5937 | t.parentElementsRE = new RegExp('^(' + s.toLowerCase() + ')$', 'i');\r |
5938 | \r |
5939 | /*console.debug(t.parentElementsRE.toString());\r |
5940 | each(t.childRules, function(v) {\r |
5941 | console.debug(v.toString());\r |
5942 | });*/\r |
5943 | },\r |
5944 | \r |
5945 | setRules : function(s) {\r |
5946 | var t = this;\r |
5947 | \r |
5948 | t._setup();\r |
5949 | t.rules = {};\r |
5950 | t.wildRules = [];\r |
5951 | t.validElements = {};\r |
5952 | \r |
5953 | return t.addRules(s);\r |
5954 | },\r |
5955 | \r |
5956 | addRules : function(s) {\r |
5957 | var t = this, dr;\r |
5958 | \r |
5959 | if (!s)\r |
5960 | return;\r |
5961 | \r |
5962 | t._setup();\r |
5963 | \r |
5964 | each(s.split(','), function(s) {\r |
5965 | var p = s.split(/\[|\]/), tn = p[0].split('/'), ra, at, wat, va = [];\r |
5966 | \r |
5967 | // Extend with default rules\r |
5968 | if (dr)\r |
5969 | at = tinymce.extend([], dr.attribs);\r |
5970 | \r |
5971 | // Parse attributes\r |
5972 | if (p.length > 1) {\r |
5973 | each(p[1].split('|'), function(s) {\r |
5974 | var ar = {}, i;\r |
5975 | \r |
5976 | at = at || [];\r |
5977 | \r |
5978 | // Parse attribute rule\r |
5979 | s = s.replace(/::/g, '~');\r |
5980 | s = /^([!\-])?([\w*.?~_\-]+|)([=:<])?(.+)?$/.exec(s);\r |
5981 | s[2] = s[2].replace(/~/g, ':');\r |
5982 | \r |
5983 | // Add required attributes\r |
5984 | if (s[1] == '!') {\r |
5985 | ra = ra || [];\r |
5986 | ra.push(s[2]);\r |
5987 | }\r |
5988 | \r |
5989 | // Remove inherited attributes\r |
5990 | if (s[1] == '-') {\r |
5991 | for (i = 0; i <at.length; i++) {\r |
5992 | if (at[i].name == s[2]) {\r |
5993 | at.splice(i, 1);\r |
5994 | return;\r |
5995 | }\r |
5996 | }\r |
5997 | }\r |
5998 | \r |
5999 | switch (s[3]) {\r |
6000 | // Add default attrib values\r |
6001 | case '=':\r |
6002 | ar.defaultVal = s[4] || '';\r |
6003 | break;\r |
6004 | \r |
6005 | // Add forced attrib values\r |
6006 | case ':':\r |
6007 | ar.forcedVal = s[4];\r |
6008 | break;\r |
6009 | \r |
6010 | // Add validation values\r |
6011 | case '<':\r |
6012 | ar.validVals = s[4].split('?');\r |
6013 | break;\r |
6014 | }\r |
6015 | \r |
6016 | if (/[*.?]/.test(s[2])) {\r |
6017 | wat = wat || [];\r |
6018 | ar.nameRE = new RegExp('^' + wildcardToRE(s[2]) + '$');\r |
6019 | wat.push(ar);\r |
6020 | } else {\r |
6021 | ar.name = s[2];\r |
6022 | at.push(ar);\r |
6023 | }\r |
6024 | \r |
6025 | va.push(s[2]);\r |
6026 | });\r |
6027 | }\r |
6028 | \r |
6029 | // Handle element names\r |
6030 | each(tn, function(s, i) {\r |
6031 | var pr = s.charAt(0), x = 1, ru = {};\r |
6032 | \r |
6033 | // Extend with default rule data\r |
6034 | if (dr) {\r |
6035 | if (dr.noEmpty)\r |
6036 | ru.noEmpty = dr.noEmpty;\r |
6037 | \r |
6038 | if (dr.fullEnd)\r |
6039 | ru.fullEnd = dr.fullEnd;\r |
6040 | \r |
6041 | if (dr.padd)\r |
6042 | ru.padd = dr.padd;\r |
6043 | }\r |
6044 | \r |
6045 | // Handle prefixes\r |
6046 | switch (pr) {\r |
6047 | case '-':\r |
6048 | ru.noEmpty = true;\r |
6049 | break;\r |
6050 | \r |
6051 | case '+':\r |
6052 | ru.fullEnd = true;\r |
6053 | break;\r |
6054 | \r |
6055 | case '#':\r |
6056 | ru.padd = true;\r |
6057 | break;\r |
6058 | \r |
6059 | default:\r |
6060 | x = 0;\r |
6061 | }\r |
6062 | \r |
6063 | tn[i] = s = s.substring(x);\r |
6064 | t.validElements[s] = 1;\r |
6065 | \r |
6066 | // Add element name or element regex\r |
6067 | if (/[*.?]/.test(tn[0])) {\r |
6068 | ru.nameRE = new RegExp('^' + wildcardToRE(tn[0]) + '$');\r |
6069 | t.wildRules = t.wildRules || {};\r |
6070 | t.wildRules.push(ru);\r |
6071 | } else {\r |
6072 | ru.name = tn[0];\r |
6073 | \r |
6074 | // Store away default rule\r |
6075 | if (tn[0] == '@')\r |
6076 | dr = ru;\r |
6077 | \r |
6078 | t.rules[s] = ru;\r |
6079 | }\r |
6080 | \r |
6081 | ru.attribs = at;\r |
6082 | \r |
6083 | if (ra)\r |
6084 | ru.requiredAttribs = ra;\r |
6085 | \r |
6086 | if (wat) {\r |
6087 | // Build valid attributes regexp\r |
6088 | s = '';\r |
6089 | each(va, function(v) {\r |
6090 | if (s)\r |
6091 | s += '|';\r |
6092 | \r |
6093 | s += '(' + wildcardToRE(v) + ')';\r |
6094 | });\r |
6095 | ru.validAttribsRE = new RegExp('^' + s.toLowerCase() + '$');\r |
6096 | ru.wildAttribs = wat;\r |
6097 | }\r |
6098 | });\r |
6099 | });\r |
6100 | \r |
6101 | // Build valid elements regexp\r |
6102 | s = '';\r |
6103 | each(t.validElements, function(v, k) {\r |
6104 | if (s)\r |
6105 | s += '|';\r |
6106 | \r |
6107 | if (k != '@')\r |
6108 | s += k;\r |
6109 | });\r |
6110 | t.validElementsRE = new RegExp('^(' + wildcardToRE(s.toLowerCase()) + ')$');\r |
6111 | \r |
6112 | //console.debug(t.validElementsRE.toString());\r |
6113 | //console.dir(t.rules);\r |
6114 | //console.dir(t.wildRules);\r |
6115 | },\r |
6116 | \r |
6117 | findRule : function(n) {\r |
6118 | var t = this, rl = t.rules, i, r;\r |
6119 | \r |
6120 | t._setup();\r |
6121 | \r |
6122 | // Exact match\r |
6123 | r = rl[n];\r |
6124 | if (r)\r |
6125 | return r;\r |
6126 | \r |
6127 | // Try wildcards\r |
6128 | rl = t.wildRules;\r |
6129 | for (i = 0; i < rl.length; i++) {\r |
6130 | if (rl[i].nameRE.test(n))\r |
6131 | return rl[i];\r |
6132 | }\r |
6133 | \r |
6134 | return null;\r |
6135 | },\r |
6136 | \r |
6137 | findAttribRule : function(ru, n) {\r |
6138 | var i, wa = ru.wildAttribs;\r |
6139 | \r |
6140 | for (i = 0; i < wa.length; i++) {\r |
6141 | if (wa[i].nameRE.test(n))\r |
6142 | return wa[i];\r |
6143 | }\r |
6144 | \r |
6145 | return null;\r |
6146 | },\r |
6147 | \r |
6148 | serialize : function(n, o) {\r |
6149 | var h, t = this, doc, oldDoc, impl, selected;\r |
6150 | \r |
6151 | t._setup();\r |
6152 | o = o || {};\r |
6153 | o.format = o.format || 'html';\r |
6154 | t.processObj = o;\r |
6155 | \r |
6156 | // IE looses the selected attribute on option elements so we need to store it\r |
6157 | // See: http://support.microsoft.com/kb/829907\r |
6158 | if (isIE) {\r |
6159 | selected = [];\r |
6160 | each(n.getElementsByTagName('option'), function(n) {\r |
6161 | var v = t.dom.getAttrib(n, 'selected');\r |
6162 | \r |
6163 | selected.push(v ? v : null);\r |
6164 | });\r |
6165 | }\r |
6166 | \r |
6167 | n = n.cloneNode(true);\r |
6168 | \r |
6169 | // IE looses the selected attribute on option elements so we need to restore it\r |
6170 | if (isIE) {\r |
6171 | each(n.getElementsByTagName('option'), function(n, i) {\r |
6172 | t.dom.setAttrib(n, 'selected', selected[i]);\r |
6173 | });\r |
6174 | }\r |
6175 | \r |
6176 | // Nodes needs to be attached to something in WebKit/Opera\r |
6177 | // Older builds of Opera crashes if you attach the node to an document created dynamically\r |
6178 | // and since we can't feature detect a crash we need to sniff the acutal build number\r |
6179 | // This fix will make DOM ranges and make Sizzle happy!\r |
6180 | impl = n.ownerDocument.implementation;\r |
6181 | if (impl.createHTMLDocument && (tinymce.isOpera && opera.buildNumber() >= 1767)) {\r |
6182 | // Create an empty HTML document\r |
6183 | doc = impl.createHTMLDocument("");\r |
6184 | \r |
6185 | // Add the element or it's children if it's a body element to the new document\r |
6186 | each(n.nodeName == 'BODY' ? n.childNodes : [n], function(node) {\r |
6187 | doc.body.appendChild(doc.importNode(node, true));\r |
6188 | });\r |
6189 | \r |
6190 | // Grab first child or body element for serialization\r |
6191 | if (n.nodeName != 'BODY')\r |
6192 | n = doc.body.firstChild;\r |
6193 | else\r |
6194 | n = doc.body;\r |
6195 | \r |
6196 | // set the new document in DOMUtils so createElement etc works\r |
6197 | oldDoc = t.dom.doc;\r |
6198 | t.dom.doc = doc;\r |
6199 | }\r |
6200 | \r |
6201 | t.key = '' + (parseInt(t.key) + 1);\r |
6202 | \r |
6203 | // Pre process\r |
6204 | if (!o.no_events) {\r |
6205 | o.node = n;\r |
6206 | t.onPreProcess.dispatch(t, o);\r |
6207 | }\r |
6208 | \r |
6209 | // Serialize HTML DOM into a string\r |
6210 | t.writer.reset();\r |
6211 | t._serializeNode(n, o.getInner);\r |
6212 | \r |
6213 | // Post process\r |
6214 | o.content = t.writer.getContent();\r |
6215 | \r |
6216 | // Restore the old document if it was changed\r |
6217 | if (oldDoc)\r |
6218 | t.dom.doc = oldDoc;\r |
6219 | \r |
6220 | if (!o.no_events)\r |
6221 | t.onPostProcess.dispatch(t, o);\r |
6222 | \r |
6223 | t._postProcess(o);\r |
6224 | o.node = null;\r |
6225 | \r |
6226 | return tinymce.trim(o.content);\r |
6227 | },\r |
6228 | \r |
6229 | // Internal functions\r |
6230 | \r |
6231 | _postProcess : function(o) {\r |
6232 | var t = this, s = t.settings, h = o.content, sc = [], p;\r |
6233 | \r |
6234 | if (o.format == 'html') {\r |
6235 | // Protect some elements\r |
6236 | p = t._protect({\r |
6237 | content : h,\r |
6238 | patterns : [\r |
6239 | {pattern : /(<script[^>]*>)(.*?)(<\/script>)/g},\r |
6240 | {pattern : /(<noscript[^>]*>)(.*?)(<\/noscript>)/g},\r |
6241 | {pattern : /(<style[^>]*>)(.*?)(<\/style>)/g},\r |
6242 | {pattern : /(<pre[^>]*>)(.*?)(<\/pre>)/g, encode : 1},\r |
6243 | {pattern : /(<!--\[CDATA\[)(.*?)(\]\]-->)/g}\r |
6244 | ]\r |
6245 | });\r |
6246 | \r |
6247 | h = p.content;\r |
6248 | \r |
6249 | // Entity encode\r |
6250 | if (s.entity_encoding !== 'raw')\r |
6251 | h = t._encode(h);\r |
6252 | \r |
6253 | // Use BR instead of padded P elements inside editor and use <p> </p> outside editor\r |
6254 | /* if (o.set)\r |
6255 | h = h.replace(/<p>\s+( | |\u00a0|<br \/>)\s+<\/p>/g, '<p><br /></p>');\r |
6256 | else\r |
6257 | h = h.replace(/<p>\s+( | |\u00a0|<br \/>)\s+<\/p>/g, '<p>$1</p>');*/\r |
6258 | \r |
6259 | // Since Gecko and Safari keeps whitespace in the DOM we need to\r |
6260 | // remove it inorder to match other browsers. But I think Gecko and Safari is right.\r |
6261 | // This process is only done when getting contents out from the editor.\r |
6262 | if (!o.set) {\r |
6263 | // We need to replace paragraph whitespace with an nbsp before indentation to keep the \u00a0 char\r |
6264 | h = h.replace(/<p>\s+<\/p>|<p([^>]+)>\s+<\/p>/g, s.entity_encoding == 'numeric' ? '<p$1> </p>' : '<p$1> </p>');\r |
6265 | \r |
6266 | if (s.remove_linebreaks) {\r |
6267 | h = h.replace(/\r?\n|\r/g, ' ');\r |
6268 | h = h.replace(/(<[^>]+>)\s+/g, '$1 ');\r |
6269 | h = h.replace(/\s+(<\/[^>]+>)/g, ' $1');\r |
6270 | h = h.replace(/<(p|h[1-6]|blockquote|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object) ([^>]+)>\s+/g, '<$1 $2>'); // Trim block start\r |
6271 | h = h.replace(/<(p|h[1-6]|blockquote|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object)>\s+/g, '<$1>'); // Trim block start\r |
6272 | h = h.replace(/\s+<\/(p|h[1-6]|blockquote|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object)>/g, '</$1>'); // Trim block end\r |
6273 | }\r |
6274 | \r |
6275 | // Simple indentation\r |
6276 | if (s.apply_source_formatting && s.indent_mode == 'simple') {\r |
6277 | // Add line breaks before and after block elements\r |
6278 | h = h.replace(/<(\/?)(ul|hr|table|meta|link|tbody|tr|object|body|head|html|map)(|[^>]+)>\s*/g, '\n<$1$2$3>\n');\r |
6279 | h = h.replace(/\s*<(p|h[1-6]|blockquote|div|title|style|pre|script|td|li|area)(|[^>]+)>/g, '\n<$1$2>');\r |
6280 | h = h.replace(/<\/(p|h[1-6]|blockquote|div|title|style|pre|script|td|li)>\s*/g, '</$1>\n');\r |
6281 | h = h.replace(/\n\n/g, '\n');\r |
6282 | }\r |
6283 | }\r |
6284 | \r |
6285 | h = t._unprotect(h, p);\r |
6286 | \r |
6287 | // Restore CDATA sections\r |
6288 | h = h.replace(/<!--\[CDATA\[([\s\S]+)\]\]-->/g, '<![CDATA[$1]]>');\r |
6289 | \r |
6290 | // Restore the \u00a0 character if raw mode is enabled\r |
6291 | if (s.entity_encoding == 'raw')\r |
6292 | h = h.replace(/<p> <\/p>|<p([^>]+)> <\/p>/g, '<p$1>\u00a0</p>');\r |
6293 | \r |
6294 | // Restore noscript elements\r |
6295 | h = h.replace(/<noscript([^>]+|)>([\s\S]*?)<\/noscript>/g, function(v, attribs, text) {\r |
6296 | return '<noscript' + attribs + '>' + t.dom.decode(text.replace(/<!--|-->/g, '')) + '</noscript>';\r |
6297 | });\r |
6298 | }\r |
6299 | \r |
6300 | o.content = h;\r |
6301 | },\r |
6302 | \r |
6303 | _serializeNode : function(n, inn) {\r |
6304 | var t = this, s = t.settings, w = t.writer, hc, el, cn, i, l, a, at, no, v, nn, ru, ar, iv, closed;\r |
6305 | \r |
6306 | if (!s.node_filter || s.node_filter(n)) {\r |
6307 | switch (n.nodeType) {\r |
6308 | case 1: // Element\r |
6309 | if (n.hasAttribute ? n.hasAttribute('mce_bogus') : n.getAttribute('mce_bogus'))\r |
6310 | return;\r |
6311 | \r |
6312 | iv = false;\r |
6313 | hc = n.hasChildNodes();\r |
6314 | nn = n.getAttribute('mce_name') || n.nodeName.toLowerCase();\r |
6315 | \r |
6316 | // Add correct prefix on IE\r |
6317 | if (isIE) {\r |
6318 | if (n.scopeName !== 'HTML' && n.scopeName !== 'html')\r |
6319 | nn = n.scopeName + ':' + nn;\r |
6320 | }\r |
6321 | \r |
6322 | // Remove mce prefix on IE needed for the abbr element\r |
6323 | if (nn.indexOf('mce:') === 0)\r |
6324 | nn = nn.substring(4);\r |
6325 | \r |
6326 | // Check if valid\r |
6327 | if (!t.validElementsRE || !t.validElementsRE.test(nn) || (t.invalidElementsRE && t.invalidElementsRE.test(nn)) || inn) {\r |
6328 | iv = true;\r |
6329 | break;\r |
6330 | }\r |
6331 | \r |
6332 | if (isIE) {\r |
6333 | // Fix IE content duplication (DOM can have multiple copies of the same node)\r |
6334 | if (s.fix_content_duplication) {\r |
6335 | if (n.mce_serialized == t.key)\r |
6336 | return;\r |
6337 | \r |
6338 | n.mce_serialized = t.key;\r |
6339 | }\r |
6340 | \r |
6341 | // IE sometimes adds a / infront of the node name\r |
6342 | if (nn.charAt(0) == '/')\r |
6343 | nn = nn.substring(1);\r |
6344 | } else if (isGecko) {\r |
6345 | // Ignore br elements\r |
6346 | if (n.nodeName === 'BR' && n.getAttribute('type') == '_moz')\r |
6347 | return;\r |
6348 | }\r |
6349 | \r |
6350 | // Check if valid child\r |
6351 | if (t.childRules) {\r |
6352 | if (t.parentElementsRE.test(t.elementName)) {\r |
6353 | if (!t.childRules[t.elementName].test(nn)) {\r |
6354 | iv = true;\r |
6355 | break;\r |
6356 | }\r |
6357 | }\r |
6358 | \r |
6359 | t.elementName = nn;\r |
6360 | }\r |
6361 | \r |
6362 | ru = t.findRule(nn);\r |
6363 | nn = ru.name || nn;\r |
6364 | closed = s.closed.test(nn);\r |
6365 | \r |
6366 | // Skip empty nodes or empty node name in IE\r |
6367 | if ((!hc && ru.noEmpty) || (isIE && !nn)) {\r |
6368 | iv = true;\r |
6369 | break;\r |
6370 | }\r |
6371 | \r |
6372 | // Check required\r |
6373 | if (ru.requiredAttribs) {\r |
6374 | a = ru.requiredAttribs;\r |
6375 | \r |
6376 | for (i = a.length - 1; i >= 0; i--) {\r |
6377 | if (this.dom.getAttrib(n, a[i]) !== '')\r |
6378 | break;\r |
6379 | }\r |
6380 | \r |
6381 | // None of the required was there\r |
6382 | if (i == -1) {\r |
6383 | iv = true;\r |
6384 | break;\r |
6385 | }\r |
6386 | }\r |
6387 | \r |
6388 | w.writeStartElement(nn);\r |
6389 | \r |
6390 | // Add ordered attributes\r |
6391 | if (ru.attribs) {\r |
6392 | for (i=0, at = ru.attribs, l = at.length; i<l; i++) {\r |
6393 | a = at[i];\r |
6394 | v = t._getAttrib(n, a);\r |
6395 | \r |
6396 | if (v !== null)\r |
6397 | w.writeAttribute(a.name, v);\r |
6398 | }\r |
6399 | }\r |
6400 | \r |
6401 | // Add wild attributes\r |
6402 | if (ru.validAttribsRE) {\r |
6403 | at = t.dom.getAttribs(n);\r |
6404 | for (i=at.length-1; i>-1; i--) {\r |
6405 | no = at[i];\r |
6406 | \r |
6407 | if (no.specified) {\r |
6408 | a = no.nodeName.toLowerCase();\r |
6409 | \r |
6410 | if (s.invalid_attrs.test(a) || !ru.validAttribsRE.test(a))\r |
6411 | continue;\r |
6412 | \r |
6413 | ar = t.findAttribRule(ru, a);\r |
6414 | v = t._getAttrib(n, ar, a);\r |
6415 | \r |
6416 | if (v !== null)\r |
6417 | w.writeAttribute(a, v);\r |
6418 | }\r |
6419 | }\r |
6420 | }\r |
6421 | \r |
6422 | // Write text from script\r |
6423 | if (nn === 'script' && tinymce.trim(n.innerHTML)) {\r |
6424 | w.writeText('// '); // Padd it with a comment so it will parse on older browsers\r |
6425 | w.writeCDATA(n.innerHTML.replace(/<!--|-->|<\[CDATA\[|\]\]>/g, '')); // Remove comments and cdata stuctures\r |
6426 | hc = false;\r |
6427 | break;\r |
6428 | }\r |
6429 | \r |
6430 | // Padd empty nodes with a \r |
6431 | if (ru.padd) {\r |
6432 | // If it has only one bogus child, padd it anyway workaround for <td><br /></td> bug\r |
6433 | if (hc && (cn = n.firstChild) && cn.nodeType === 1 && n.childNodes.length === 1) {\r |
6434 | if (cn.hasAttribute ? cn.hasAttribute('mce_bogus') : cn.getAttribute('mce_bogus'))\r |
6435 | w.writeText('\u00a0');\r |
6436 | } else if (!hc)\r |
6437 | w.writeText('\u00a0'); // No children then padd it\r |
6438 | }\r |
6439 | \r |
6440 | break;\r |
6441 | \r |
6442 | case 3: // Text\r |
6443 | // Check if valid child\r |
6444 | if (t.childRules && t.parentElementsRE.test(t.elementName)) {\r |
6445 | if (!t.childRules[t.elementName].test(n.nodeName))\r |
6446 | return;\r |
6447 | }\r |
6448 | \r |
6449 | return w.writeText(n.nodeValue);\r |
6450 | \r |
6451 | case 4: // CDATA\r |
6452 | return w.writeCDATA(n.nodeValue);\r |
6453 | \r |
6454 | case 8: // Comment\r |
6455 | return w.writeComment(n.nodeValue);\r |
6456 | }\r |
6457 | } else if (n.nodeType == 1)\r |
6458 | hc = n.hasChildNodes();\r |
6459 | \r |
6460 | if (hc && !closed) {\r |
6461 | cn = n.firstChild;\r |
6462 | \r |
6463 | while (cn) {\r |
6464 | t._serializeNode(cn);\r |
6465 | t.elementName = nn;\r |
6466 | cn = cn.nextSibling;\r |
6467 | }\r |
6468 | }\r |
6469 | \r |
6470 | // Write element end\r |
6471 | if (!iv) {\r |
6472 | if (!closed)\r |
6473 | w.writeFullEndElement();\r |
6474 | else\r |
6475 | w.writeEndElement();\r |
6476 | }\r |
6477 | },\r |
6478 | \r |
6479 | _protect : function(o) {\r |
6480 | var t = this;\r |
6481 | \r |
6482 | o.items = o.items || [];\r |
6483 | \r |
6484 | function enc(s) {\r |
6485 | return s.replace(/[\r\n\\]/g, function(c) {\r |
6486 | if (c === '\n')\r |
6487 | return '\\n';\r |
6488 | else if (c === '\\')\r |
6489 | return '\\\\';\r |
6490 | \r |
6491 | return '\\r';\r |
6492 | });\r |
6493 | };\r |
6494 | \r |
6495 | function dec(s) {\r |
6496 | return s.replace(/\\[\\rn]/g, function(c) {\r |
6497 | if (c === '\\n')\r |
6498 | return '\n';\r |
6499 | else if (c === '\\\\')\r |
6500 | return '\\';\r |
6501 | \r |
6502 | return '\r';\r |
6503 | });\r |
6504 | };\r |
6505 | \r |
6506 | each(o.patterns, function(p) {\r |
6507 | o.content = dec(enc(o.content).replace(p.pattern, function(x, a, b, c) {\r |
6508 | b = dec(b);\r |
6509 | \r |
6510 | if (p.encode)\r |
6511 | b = t._encode(b);\r |
6512 | \r |
6513 | o.items.push(b);\r |
6514 | return a + '<!--mce:' + (o.items.length - 1) + '-->' + c;\r |
6515 | }));\r |
6516 | });\r |
6517 | \r |
6518 | return o;\r |
6519 | },\r |
6520 | \r |
6521 | _unprotect : function(h, o) {\r |
6522 | h = h.replace(/\<!--mce:([0-9]+)--\>/g, function(a, b) {\r |
6523 | return o.items[parseInt(b)];\r |
6524 | });\r |
6525 | \r |
6526 | o.items = [];\r |
6527 | \r |
6528 | return h;\r |
6529 | },\r |
6530 | \r |
6531 | _encode : function(h) {\r |
6532 | var t = this, s = t.settings, l;\r |
6533 | \r |
6534 | // Entity encode\r |
6535 | if (s.entity_encoding !== 'raw') {\r |
6536 | if (s.entity_encoding.indexOf('named') != -1) {\r |
6537 | t.setEntities(s.entities);\r |
6538 | l = t.entityLookup;\r |
6539 | \r |
6540 | h = h.replace(t.entitiesRE, function(a) {\r |
6541 | var v;\r |
6542 | \r |
6543 | if (v = l[a])\r |
6544 | a = '&' + v + ';';\r |
6545 | \r |
6546 | return a;\r |
6547 | });\r |
6548 | }\r |
6549 | \r |
6550 | if (s.entity_encoding.indexOf('numeric') != -1) {\r |
6551 | h = h.replace(/[\u007E-\uFFFF]/g, function(a) {\r |
6552 | return '&#' + a.charCodeAt(0) + ';';\r |
6553 | });\r |
6554 | }\r |
6555 | }\r |
6556 | \r |
6557 | return h;\r |
6558 | },\r |
6559 | \r |
6560 | _setup : function() {\r |
6561 | var t = this, s = this.settings;\r |
6562 | \r |
6563 | if (t.done)\r |
6564 | return;\r |
6565 | \r |
6566 | t.done = 1;\r |
6567 | \r |
6568 | t.setRules(s.valid_elements);\r |
6569 | t.addRules(s.extended_valid_elements);\r |
6570 | t.addValidChildRules(s.valid_child_elements);\r |
6571 | \r |
6572 | if (s.invalid_elements)\r |
6573 | t.invalidElementsRE = new RegExp('^(' + wildcardToRE(s.invalid_elements.replace(/,/g, '|').toLowerCase()) + ')$');\r |
6574 | \r |
6575 | if (s.attrib_value_filter)\r |
6576 | t.attribValueFilter = s.attribValueFilter;\r |
6577 | },\r |
6578 | \r |
6579 | _getAttrib : function(n, a, na) {\r |
6580 | var i, v;\r |
6581 | \r |
6582 | na = na || a.name;\r |
6583 | \r |
6584 | if (a.forcedVal && (v = a.forcedVal)) {\r |
6585 | if (v === '{$uid}')\r |
6586 | return this.dom.uniqueId();\r |
6587 | \r |
6588 | return v;\r |
6589 | }\r |
6590 | \r |
6591 | v = this.dom.getAttrib(n, na);\r |
6592 | \r |
6593 | switch (na) {\r |
6594 | case 'rowspan':\r |
6595 | case 'colspan':\r |
6596 | // Whats the point? Remove usless attribute value\r |
6597 | if (v == '1')\r |
6598 | v = '';\r |
6599 | \r |
6600 | break;\r |
6601 | }\r |
6602 | \r |
6603 | if (this.attribValueFilter)\r |
6604 | v = this.attribValueFilter(na, v, n);\r |
6605 | \r |
6606 | if (a.validVals) {\r |
6607 | for (i = a.validVals.length - 1; i >= 0; i--) {\r |
6608 | if (v == a.validVals[i])\r |
6609 | break;\r |
6610 | }\r |
6611 | \r |
6612 | if (i == -1)\r |
6613 | return null;\r |
6614 | }\r |
6615 | \r |
6616 | if (v === '' && typeof(a.defaultVal) != 'undefined') {\r |
6617 | v = a.defaultVal;\r |
6618 | \r |
6619 | if (v === '{$uid}')\r |
6620 | return this.dom.uniqueId();\r |
6621 | \r |
6622 | return v;\r |
6623 | } else {\r |
6624 | // Remove internal mceItemXX classes when content is extracted from editor\r |
6625 | if (na == 'class' && this.processObj.get)\r |
6626 | v = v.replace(/\s?mceItem\w+\s?/g, '');\r |
6627 | }\r |
6628 | \r |
6629 | if (v === '')\r |
6630 | return null;\r |
6631 | \r |
6632 | \r |
6633 | return v;\r |
6634 | }\r |
6635 | });\r |
6636 | })(tinymce);\r |
6637 | (function(tinymce) {\r |
6638 | var each = tinymce.each, Event = tinymce.dom.Event;\r |
6639 | \r |
6640 | tinymce.create('tinymce.dom.ScriptLoader', {\r |
6641 | ScriptLoader : function(s) {\r |
6642 | this.settings = s || {};\r |
6643 | this.queue = [];\r |
6644 | this.lookup = {};\r |
6645 | },\r |
6646 | \r |
6647 | isDone : function(u) {\r |
6648 | return this.lookup[u] ? this.lookup[u].state == 2 : 0;\r |
6649 | },\r |
6650 | \r |
6651 | markDone : function(u) {\r |
6652 | this.lookup[u] = {state : 2, url : u};\r |
6653 | },\r |
6654 | \r |
6655 | add : function(u, cb, s, pr) {\r |
6656 | var t = this, lo = t.lookup, o;\r |
6657 | \r |
6658 | if (o = lo[u]) {\r |
6659 | // Is loaded fire callback\r |
6660 | if (cb && o.state == 2)\r |
6661 | cb.call(s || this);\r |
6662 | \r |
6663 | return o;\r |
6664 | }\r |
6665 | \r |
6666 | o = {state : 0, url : u, func : cb, scope : s || this};\r |
6667 | \r |
6668 | if (pr)\r |
6669 | t.queue.unshift(o);\r |
6670 | else\r |
6671 | t.queue.push(o);\r |
6672 | \r |
6673 | lo[u] = o;\r |
6674 | \r |
6675 | return o;\r |
6676 | },\r |
6677 | \r |
6678 | load : function(u, cb, s) {\r |
6679 | var t = this, o;\r |
6680 | \r |
6681 | if (o = t.lookup[u]) {\r |
6682 | // Is loaded fire callback\r |
6683 | if (cb && o.state == 2)\r |
6684 | cb.call(s || t);\r |
6685 | \r |
6686 | return o;\r |
6687 | }\r |
6688 | \r |
6689 | function loadScript(u) {\r |
6690 | if (Event.domLoaded || t.settings.strict_mode) {\r |
6691 | tinymce.util.XHR.send({\r |
6692 | url : tinymce._addVer(u),\r |
6693 | error : t.settings.error,\r |
6694 | async : false,\r |
6695 | success : function(co) {\r |
6696 | t.eval(co);\r |
6697 | }\r |
6698 | });\r |
6699 | } else\r |
6700 | document.write('<script type="text/javascript" src="' + tinymce._addVer(u) + '"></script>');\r |
6701 | };\r |
6702 | \r |
6703 | if (!tinymce.is(u, 'string')) {\r |
6704 | each(u, function(u) {\r |
6705 | loadScript(u);\r |
6706 | });\r |
6707 | \r |
6708 | if (cb)\r |
6709 | cb.call(s || t);\r |
6710 | } else {\r |
6711 | loadScript(u);\r |
6712 | \r |
6713 | if (cb)\r |
6714 | cb.call(s || t);\r |
6715 | }\r |
6716 | },\r |
6717 | \r |
6718 | loadQueue : function(cb, s) {\r |
6719 | var t = this;\r |
6720 | \r |
6721 | if (!t.queueLoading) {\r |
6722 | t.queueLoading = 1;\r |
6723 | t.queueCallbacks = [];\r |
6724 | \r |
6725 | t.loadScripts(t.queue, function() {\r |
6726 | t.queueLoading = 0;\r |
6727 | \r |
6728 | if (cb)\r |
6729 | cb.call(s || t);\r |
6730 | \r |
6731 | each(t.queueCallbacks, function(o) {\r |
6732 | o.func.call(o.scope);\r |
6733 | });\r |
6734 | });\r |
6735 | } else if (cb)\r |
6736 | t.queueCallbacks.push({func : cb, scope : s || t});\r |
6737 | },\r |
6738 | \r |
6739 | eval : function(co) {\r |
6740 | var w = window;\r |
6741 | \r |
6742 | // Evaluate script\r |
6743 | if (!w.execScript) {\r |
6744 | try {\r |
6745 | eval.call(w, co);\r |
6746 | } catch (ex) {\r |
6747 | eval(co, w); // Firefox 3.0a8\r |
6748 | }\r |
6749 | } else\r |
6750 | w.execScript(co); // IE\r |
6751 | },\r |
6752 | \r |
6753 | loadScripts : function(sc, cb, s) {\r |
6754 | var t = this, lo = t.lookup;\r |
6755 | \r |
6756 | function done(o) {\r |
6757 | o.state = 2; // Has been loaded\r |
6758 | \r |
6759 | // Run callback\r |
6760 | if (o.func)\r |
6761 | o.func.call(o.scope || t);\r |
6762 | };\r |
6763 | \r |
6764 | function allDone() {\r |
6765 | var l;\r |
6766 | \r |
6767 | // Check if all files are loaded\r |
6768 | l = sc.length;\r |
6769 | each(sc, function(o) {\r |
6770 | o = lo[o.url];\r |
6771 | \r |
6772 | if (o.state === 2) {// It has finished loading\r |
6773 | done(o);\r |
6774 | l--;\r |
6775 | } else\r |
6776 | load(o);\r |
6777 | });\r |
6778 | \r |
6779 | // They are all loaded\r |
6780 | if (l === 0 && cb) {\r |
6781 | cb.call(s || t);\r |
6782 | cb = 0;\r |
6783 | }\r |
6784 | };\r |
6785 | \r |
6786 | function load(o) {\r |
6787 | if (o.state > 0)\r |
6788 | return;\r |
6789 | \r |
6790 | o.state = 1; // Is loading\r |
6791 | \r |
6792 | tinymce.dom.ScriptLoader.loadScript(o.url, function() {\r |
6793 | done(o);\r |
6794 | allDone();\r |
6795 | });\r |
6796 | \r |
6797 | /*\r |
6798 | tinymce.util.XHR.send({\r |
6799 | url : o.url,\r |
6800 | error : t.settings.error,\r |
6801 | success : function(co) {\r |
6802 | t.eval(co);\r |
6803 | done(o);\r |
6804 | allDone();\r |
6805 | }\r |
6806 | });\r |
6807 | */\r |
6808 | };\r |
6809 | \r |
6810 | each(sc, function(o) {\r |
6811 | var u = o.url;\r |
6812 | \r |
6813 | // Add to queue if needed\r |
6814 | if (!lo[u]) {\r |
6815 | lo[u] = o;\r |
6816 | t.queue.push(o);\r |
6817 | } else\r |
6818 | o = lo[u];\r |
6819 | \r |
6820 | // Is already loading or has been loaded\r |
6821 | if (o.state > 0)\r |
6822 | return;\r |
6823 | \r |
6824 | if (!Event.domLoaded && !t.settings.strict_mode) {\r |
6825 | var ix, ol = '';\r |
6826 | \r |
6827 | // Add onload events\r |
6828 | if (cb || o.func) {\r |
6829 | o.state = 1; // Is loading\r |
6830 | \r |
6831 | ix = tinymce.dom.ScriptLoader._addOnLoad(function() {\r |
6832 | done(o);\r |
6833 | allDone();\r |
6834 | });\r |
6835 | \r |
6836 | if (tinymce.isIE)\r |
6837 | ol = ' onreadystatechange="';\r |
6838 | else\r |
6839 | ol = ' onload="';\r |
6840 | \r |
6841 | ol += 'tinymce.dom.ScriptLoader._onLoad(this,\'' + u + '\',' + ix + ');"';\r |
6842 | }\r |
6843 | \r |
6844 | document.write('<script type="text/javascript" src="' + tinymce._addVer(u) + '"' + ol + '></script>');\r |
6845 | \r |
6846 | if (!o.func)\r |
6847 | done(o);\r |
6848 | } else\r |
6849 | load(o);\r |
6850 | });\r |
6851 | \r |
6852 | allDone();\r |
6853 | },\r |
6854 | \r |
6855 | // Static methods\r |
6856 | 'static' : {\r |
6857 | _addOnLoad : function(f) {\r |
6858 | var t = this;\r |
6859 | \r |
6860 | t._funcs = t._funcs || [];\r |
6861 | t._funcs.push(f);\r |
6862 | \r |
6863 | return t._funcs.length - 1;\r |
6864 | },\r |
6865 | \r |
6866 | _onLoad : function(e, u, ix) {\r |
6867 | if (!tinymce.isIE || e.readyState == 'complete')\r |
6868 | this._funcs[ix].call(this);\r |
6869 | },\r |
6870 | \r |
6871 | loadScript : function(u, cb) {\r |
6872 | var id = tinymce.DOM.uniqueId(), e;\r |
6873 | \r |
6874 | function done() {\r |
6875 | Event.clear(id);\r |
6876 | tinymce.DOM.remove(id);\r |
6877 | \r |
6878 | if (cb) {\r |
6879 | cb.call(document, u);\r |
6880 | cb = 0;\r |
6881 | }\r |
6882 | };\r |
6883 | \r |
6884 | if (tinymce.isIE) {\r |
6885 | /* Event.add(e, 'readystatechange', function(e) {\r |
6886 | if (e.target && e.target.readyState == 'complete')\r |
6887 | done();\r |
6888 | });*/\r |
6889 | \r |
6890 | tinymce.util.XHR.send({\r |
6891 | url : tinymce._addVer(u),\r |
6892 | async : false,\r |
6893 | success : function(co) {\r |
6894 | window.execScript(co);\r |
6895 | done();\r |
6896 | }\r |
6897 | });\r |
6898 | } else {\r |
6899 | e = tinymce.DOM.create('script', {id : id, type : 'text/javascript', src : tinymce._addVer(u)});\r |
6900 | Event.add(e, 'load', done);\r |
6901 | \r |
6902 | // Check for head or body\r |
6903 | (document.getElementsByTagName('head')[0] || document.body).appendChild(e);\r |
6904 | }\r |
6905 | }\r |
6906 | }\r |
6907 | });\r |
6908 | \r |
6909 | // Global script loader\r |
6910 | tinymce.ScriptLoader = new tinymce.dom.ScriptLoader();\r |
6911 | })(tinymce);\r |
6912 | (function(tinymce) {\r |
6913 | // Shorten class names\r |
6914 | var DOM = tinymce.DOM, is = tinymce.is;\r |
6915 | \r |
6916 | tinymce.create('tinymce.ui.Control', {\r |
6917 | Control : function(id, s) {\r |
6918 | this.id = id;\r |
6919 | this.settings = s = s || {};\r |
6920 | this.rendered = false;\r |
6921 | this.onRender = new tinymce.util.Dispatcher(this);\r |
6922 | this.classPrefix = '';\r |
6923 | this.scope = s.scope || this;\r |
6924 | this.disabled = 0;\r |
6925 | this.active = 0;\r |
6926 | },\r |
6927 | \r |
6928 | setDisabled : function(s) {\r |
6929 | var e;\r |
6930 | \r |
6931 | if (s != this.disabled) {\r |
6932 | e = DOM.get(this.id);\r |
6933 | \r |
6934 | // Add accessibility title for unavailable actions\r |
6935 | if (e && this.settings.unavailable_prefix) {\r |
6936 | if (s) {\r |
6937 | this.prevTitle = e.title;\r |
6938 | e.title = this.settings.unavailable_prefix + ": " + e.title;\r |
6939 | } else\r |
6940 | e.title = this.prevTitle;\r |
6941 | }\r |
6942 | \r |
6943 | this.setState('Disabled', s);\r |
6944 | this.setState('Enabled', !s);\r |
6945 | this.disabled = s;\r |
6946 | }\r |
6947 | },\r |
6948 | \r |
6949 | isDisabled : function() {\r |
6950 | return this.disabled;\r |
6951 | },\r |
6952 | \r |
6953 | setActive : function(s) {\r |
6954 | if (s != this.active) {\r |
6955 | this.setState('Active', s);\r |
6956 | this.active = s;\r |
6957 | }\r |
6958 | },\r |
6959 | \r |
6960 | isActive : function() {\r |
6961 | return this.active;\r |
6962 | },\r |
6963 | \r |
6964 | setState : function(c, s) {\r |
6965 | var n = DOM.get(this.id);\r |
6966 | \r |
6967 | c = this.classPrefix + c;\r |
6968 | \r |
6969 | if (s)\r |
6970 | DOM.addClass(n, c);\r |
6971 | else\r |
6972 | DOM.removeClass(n, c);\r |
6973 | },\r |
6974 | \r |
6975 | isRendered : function() {\r |
6976 | return this.rendered;\r |
6977 | },\r |
6978 | \r |
6979 | renderHTML : function() {\r |
6980 | },\r |
6981 | \r |
6982 | renderTo : function(n) {\r |
6983 | DOM.setHTML(n, this.renderHTML());\r |
6984 | },\r |
6985 | \r |
6986 | postRender : function() {\r |
6987 | var t = this, b;\r |
6988 | \r |
6989 | // Set pending states\r |
6990 | if (is(t.disabled)) {\r |
6991 | b = t.disabled;\r |
6992 | t.disabled = -1;\r |
6993 | t.setDisabled(b);\r |
6994 | }\r |
6995 | \r |
6996 | if (is(t.active)) {\r |
6997 | b = t.active;\r |
6998 | t.active = -1;\r |
6999 | t.setActive(b);\r |
7000 | }\r |
7001 | },\r |
7002 | \r |
7003 | remove : function() {\r |
7004 | DOM.remove(this.id);\r |
7005 | this.destroy();\r |
7006 | },\r |
7007 | \r |
7008 | destroy : function() {\r |
7009 | tinymce.dom.Event.clear(this.id);\r |
7010 | }\r |
7011 | });\r |
7012 | })(tinymce);tinymce.create('tinymce.ui.Container:tinymce.ui.Control', {\r |
7013 | Container : function(id, s) {\r |
7014 | this.parent(id, s);\r |
7015 | \r |
7016 | this.controls = [];\r |
7017 | \r |
7018 | this.lookup = {};\r |
7019 | },\r |
7020 | \r |
7021 | add : function(c) {\r |
7022 | this.lookup[c.id] = c;\r |
7023 | this.controls.push(c);\r |
7024 | \r |
7025 | return c;\r |
7026 | },\r |
7027 | \r |
7028 | get : function(n) {\r |
7029 | return this.lookup[n];\r |
7030 | }\r |
7031 | });\r |
7032 | \r |
7033 | tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {\r |
7034 | Separator : function(id, s) {\r |
7035 | this.parent(id, s);\r |
7036 | this.classPrefix = 'mceSeparator';\r |
7037 | },\r |
7038 | \r |
7039 | renderHTML : function() {\r |
7040 | return tinymce.DOM.createHTML('span', {'class' : this.classPrefix});\r |
7041 | }\r |
7042 | });\r |
7043 | (function(tinymce) {\r |
7044 | var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk;\r |
7045 | \r |
7046 | tinymce.create('tinymce.ui.MenuItem:tinymce.ui.Control', {\r |
7047 | MenuItem : function(id, s) {\r |
7048 | this.parent(id, s);\r |
7049 | this.classPrefix = 'mceMenuItem';\r |
7050 | },\r |
7051 | \r |
7052 | setSelected : function(s) {\r |
7053 | this.setState('Selected', s);\r |
7054 | this.selected = s;\r |
7055 | },\r |
7056 | \r |
7057 | isSelected : function() {\r |
7058 | return this.selected;\r |
7059 | },\r |
7060 | \r |
7061 | postRender : function() {\r |
7062 | var t = this;\r |
7063 | \r |
7064 | t.parent();\r |
7065 | \r |
7066 | // Set pending state\r |
7067 | if (is(t.selected))\r |
7068 | t.setSelected(t.selected);\r |
7069 | }\r |
7070 | });\r |
7071 | })(tinymce);\r |
7072 | (function(tinymce) {\r |
7073 | var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk;\r |
7074 | \r |
7075 | tinymce.create('tinymce.ui.Menu:tinymce.ui.MenuItem', {\r |
7076 | Menu : function(id, s) {\r |
7077 | var t = this;\r |
7078 | \r |
7079 | t.parent(id, s);\r |
7080 | t.items = {};\r |
7081 | t.collapsed = false;\r |
7082 | t.menuCount = 0;\r |
7083 | t.onAddItem = new tinymce.util.Dispatcher(this);\r |
7084 | },\r |
7085 | \r |
7086 | expand : function(d) {\r |
7087 | var t = this;\r |
7088 | \r |
7089 | if (d) {\r |
7090 | walk(t, function(o) {\r |
7091 | if (o.expand)\r |
7092 | o.expand();\r |
7093 | }, 'items', t);\r |
7094 | }\r |
7095 | \r |
7096 | t.collapsed = false;\r |
7097 | },\r |
7098 | \r |
7099 | collapse : function(d) {\r |
7100 | var t = this;\r |
7101 | \r |
7102 | if (d) {\r |
7103 | walk(t, function(o) {\r |
7104 | if (o.collapse)\r |
7105 | o.collapse();\r |
7106 | }, 'items', t);\r |
7107 | }\r |
7108 | \r |
7109 | t.collapsed = true;\r |
7110 | },\r |
7111 | \r |
7112 | isCollapsed : function() {\r |
7113 | return this.collapsed;\r |
7114 | },\r |
7115 | \r |
7116 | add : function(o) {\r |
7117 | if (!o.settings)\r |
7118 | o = new tinymce.ui.MenuItem(o.id || DOM.uniqueId(), o);\r |
7119 | \r |
7120 | this.onAddItem.dispatch(this, o);\r |
7121 | \r |
7122 | return this.items[o.id] = o;\r |
7123 | },\r |
7124 | \r |
7125 | addSeparator : function() {\r |
7126 | return this.add({separator : true});\r |
7127 | },\r |
7128 | \r |
7129 | addMenu : function(o) {\r |
7130 | if (!o.collapse)\r |
7131 | o = this.createMenu(o);\r |
7132 | \r |
7133 | this.menuCount++;\r |
7134 | \r |
7135 | return this.add(o);\r |
7136 | },\r |
7137 | \r |
7138 | hasMenus : function() {\r |
7139 | return this.menuCount !== 0;\r |
7140 | },\r |
7141 | \r |
7142 | remove : function(o) {\r |
7143 | delete this.items[o.id];\r |
7144 | },\r |
7145 | \r |
7146 | removeAll : function() {\r |
7147 | var t = this;\r |
7148 | \r |
7149 | walk(t, function(o) {\r |
7150 | if (o.removeAll)\r |
7151 | o.removeAll();\r |
7152 | else\r |
7153 | o.remove();\r |
7154 | \r |
7155 | o.destroy();\r |
7156 | }, 'items', t);\r |
7157 | \r |
7158 | t.items = {};\r |
7159 | },\r |
7160 | \r |
7161 | createMenu : function(o) {\r |
7162 | var m = new tinymce.ui.Menu(o.id || DOM.uniqueId(), o);\r |
7163 | \r |
7164 | m.onAddItem.add(this.onAddItem.dispatch, this.onAddItem);\r |
7165 | \r |
7166 | return m;\r |
7167 | }\r |
7168 | });\r |
7169 | })(tinymce);(function(tinymce) {\r |
7170 | var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, Event = tinymce.dom.Event, Element = tinymce.dom.Element;\r |
7171 | \r |
7172 | tinymce.create('tinymce.ui.DropMenu:tinymce.ui.Menu', {\r |
7173 | DropMenu : function(id, s) {\r |
7174 | s = s || {};\r |
7175 | s.container = s.container || DOM.doc.body;\r |
7176 | s.offset_x = s.offset_x || 0;\r |
7177 | s.offset_y = s.offset_y || 0;\r |
7178 | s.vp_offset_x = s.vp_offset_x || 0;\r |
7179 | s.vp_offset_y = s.vp_offset_y || 0;\r |
7180 | \r |
7181 | if (is(s.icons) && !s.icons)\r |
7182 | s['class'] += ' mceNoIcons';\r |
7183 | \r |
7184 | this.parent(id, s);\r |
7185 | this.onShowMenu = new tinymce.util.Dispatcher(this);\r |
7186 | this.onHideMenu = new tinymce.util.Dispatcher(this);\r |
7187 | this.classPrefix = 'mceMenu';\r |
7188 | },\r |
7189 | \r |
7190 | createMenu : function(s) {\r |
7191 | var t = this, cs = t.settings, m;\r |
7192 | \r |
7193 | s.container = s.container || cs.container;\r |
7194 | s.parent = t;\r |
7195 | s.constrain = s.constrain || cs.constrain;\r |
7196 | s['class'] = s['class'] || cs['class'];\r |
7197 | s.vp_offset_x = s.vp_offset_x || cs.vp_offset_x;\r |
7198 | s.vp_offset_y = s.vp_offset_y || cs.vp_offset_y;\r |
7199 | m = new tinymce.ui.DropMenu(s.id || DOM.uniqueId(), s);\r |
7200 | \r |
7201 | m.onAddItem.add(t.onAddItem.dispatch, t.onAddItem);\r |
7202 | \r |
7203 | return m;\r |
7204 | },\r |
7205 | \r |
7206 | update : function() {\r |
7207 | var t = this, s = t.settings, tb = DOM.get('menu_' + t.id + '_tbl'), co = DOM.get('menu_' + t.id + '_co'), tw, th;\r |
7208 | \r |
7209 | tw = s.max_width ? Math.min(tb.clientWidth, s.max_width) : tb.clientWidth;\r |
7210 | th = s.max_height ? Math.min(tb.clientHeight, s.max_height) : tb.clientHeight;\r |
7211 | \r |
7212 | if (!DOM.boxModel)\r |
7213 | t.element.setStyles({width : tw + 2, height : th + 2});\r |
7214 | else\r |
7215 | t.element.setStyles({width : tw, height : th});\r |
7216 | \r |
7217 | if (s.max_width)\r |
7218 | DOM.setStyle(co, 'width', tw);\r |
7219 | \r |
7220 | if (s.max_height) {\r |
7221 | DOM.setStyle(co, 'height', th);\r |
7222 | \r |
7223 | if (tb.clientHeight < s.max_height)\r |
7224 | DOM.setStyle(co, 'overflow', 'hidden');\r |
7225 | }\r |
7226 | },\r |
7227 | \r |
7228 | showMenu : function(x, y, px) {\r |
7229 | var t = this, s = t.settings, co, vp = DOM.getViewPort(), w, h, mx, my, ot = 2, dm, tb, cp = t.classPrefix;\r |
7230 | \r |
7231 | t.collapse(1);\r |
7232 | \r |
7233 | if (t.isMenuVisible)\r |
7234 | return;\r |
7235 | \r |
7236 | if (!t.rendered) {\r |
7237 | co = DOM.add(t.settings.container, t.renderNode());\r |
7238 | \r |
7239 | each(t.items, function(o) {\r |
7240 | o.postRender();\r |
7241 | });\r |
7242 | \r |
7243 | t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container});\r |
7244 | } else\r |
7245 | co = DOM.get('menu_' + t.id);\r |
7246 | \r |
7247 | // Move layer out of sight unless it's Opera since it scrolls to top of page due to an bug\r |
7248 | if (!tinymce.isOpera)\r |
7249 | DOM.setStyles(co, {left : -0xFFFF , top : -0xFFFF});\r |
7250 | \r |
7251 | DOM.show(co);\r |
7252 | t.update();\r |
7253 | \r |
7254 | x += s.offset_x || 0;\r |
7255 | y += s.offset_y || 0;\r |
7256 | vp.w -= 4;\r |
7257 | vp.h -= 4;\r |
7258 | \r |
7259 | // Move inside viewport if not submenu\r |
7260 | if (s.constrain) {\r |
7261 | w = co.clientWidth - ot;\r |
7262 | h = co.clientHeight - ot;\r |
7263 | mx = vp.x + vp.w;\r |
7264 | my = vp.y + vp.h;\r |
7265 | \r |
7266 | if ((x + s.vp_offset_x + w) > mx)\r |
7267 | x = px ? px - w : Math.max(0, (mx - s.vp_offset_x) - w);\r |
7268 | \r |
7269 | if ((y + s.vp_offset_y + h) > my)\r |
7270 | y = Math.max(0, (my - s.vp_offset_y) - h);\r |
7271 | }\r |
7272 | \r |
7273 | DOM.setStyles(co, {left : x , top : y});\r |
7274 | \r |
7275 | t.element.update();\r |
7276 | \r |
7277 | t.isMenuVisible = 1;\r |
7278 | t.mouseClickFunc = Event.add(co, 'click', function(e) {\r |
7279 | var m;\r |
7280 | \r |
7281 | e = e.target;\r |
7282 | \r |
7283 | if (e && (e = DOM.getParent(e, 'tr')) && !DOM.hasClass(e, cp + 'ItemSub')) {\r |
7284 | m = t.items[e.id];\r |
7285 | \r |
7286 | if (m.isDisabled())\r |
7287 | return;\r |
7288 | \r |
7289 | dm = t;\r |
7290 | \r |
7291 | while (dm) {\r |
7292 | if (dm.hideMenu)\r |
7293 | dm.hideMenu();\r |
7294 | \r |
7295 | dm = dm.settings.parent;\r |
7296 | }\r |
7297 | \r |
7298 | if (m.settings.onclick)\r |
7299 | m.settings.onclick(e);\r |
7300 | \r |
7301 | return Event.cancel(e); // Cancel to fix onbeforeunload problem\r |
7302 | }\r |
7303 | });\r |
7304 | \r |
7305 | if (t.hasMenus()) {\r |
7306 | t.mouseOverFunc = Event.add(co, 'mouseover', function(e) {\r |
7307 | var m, r, mi;\r |
7308 | \r |
7309 | e = e.target;\r |
7310 | if (e && (e = DOM.getParent(e, 'tr'))) {\r |
7311 | m = t.items[e.id];\r |
7312 | \r |
7313 | if (t.lastMenu)\r |
7314 | t.lastMenu.collapse(1);\r |
7315 | \r |
7316 | if (m.isDisabled())\r |
7317 | return;\r |
7318 | \r |
7319 | if (e && DOM.hasClass(e, cp + 'ItemSub')) {\r |
7320 | //p = DOM.getPos(s.container);\r |
7321 | r = DOM.getRect(e);\r |
7322 | m.showMenu((r.x + r.w - ot), r.y - ot, r.x);\r |
7323 | t.lastMenu = m;\r |
7324 | DOM.addClass(DOM.get(m.id).firstChild, cp + 'ItemActive');\r |
7325 | }\r |
7326 | }\r |
7327 | });\r |
7328 | }\r |
7329 | \r |
7330 | t.onShowMenu.dispatch(t);\r |
7331 | \r |
7332 | if (s.keyboard_focus) {\r |
7333 | Event.add(co, 'keydown', t._keyHandler, t);\r |
7334 | DOM.select('a', 'menu_' + t.id)[0].focus(); // Select first link\r |
7335 | t._focusIdx = 0;\r |
7336 | }\r |
7337 | },\r |
7338 | \r |
7339 | hideMenu : function(c) {\r |
7340 | var t = this, co = DOM.get('menu_' + t.id), e;\r |
7341 | \r |
7342 | if (!t.isMenuVisible)\r |
7343 | return;\r |
7344 | \r |
7345 | Event.remove(co, 'mouseover', t.mouseOverFunc);\r |
7346 | Event.remove(co, 'click', t.mouseClickFunc);\r |
7347 | Event.remove(co, 'keydown', t._keyHandler);\r |
7348 | DOM.hide(co);\r |
7349 | t.isMenuVisible = 0;\r |
7350 | \r |
7351 | if (!c)\r |
7352 | t.collapse(1);\r |
7353 | \r |
7354 | if (t.element)\r |
7355 | t.element.hide();\r |
7356 | \r |
7357 | if (e = DOM.get(t.id))\r |
7358 | DOM.removeClass(e.firstChild, t.classPrefix + 'ItemActive');\r |
7359 | \r |
7360 | t.onHideMenu.dispatch(t);\r |
7361 | },\r |
7362 | \r |
7363 | add : function(o) {\r |
7364 | var t = this, co;\r |
7365 | \r |
7366 | o = t.parent(o);\r |
7367 | \r |
7368 | if (t.isRendered && (co = DOM.get('menu_' + t.id)))\r |
7369 | t._add(DOM.select('tbody', co)[0], o);\r |
7370 | \r |
7371 | return o;\r |
7372 | },\r |
7373 | \r |
7374 | collapse : function(d) {\r |
7375 | this.parent(d);\r |
7376 | this.hideMenu(1);\r |
7377 | },\r |
7378 | \r |
7379 | remove : function(o) {\r |
7380 | DOM.remove(o.id);\r |
7381 | this.destroy();\r |
7382 | \r |
7383 | return this.parent(o);\r |
7384 | },\r |
7385 | \r |
7386 | destroy : function() {\r |
7387 | var t = this, co = DOM.get('menu_' + t.id);\r |
7388 | \r |
7389 | Event.remove(co, 'mouseover', t.mouseOverFunc);\r |
7390 | Event.remove(co, 'click', t.mouseClickFunc);\r |
7391 | \r |
7392 | if (t.element)\r |
7393 | t.element.remove();\r |
7394 | \r |
7395 | DOM.remove(co);\r |
7396 | },\r |
7397 | \r |
7398 | renderNode : function() {\r |
7399 | var t = this, s = t.settings, n, tb, co, w;\r |
7400 | \r |
7401 | if (s['class'].indexOf ('mceListBoxMenu') != -1 && tinymce.EditorManager.settings.theme_advanced_toolbar_location == 'external') {\r |
7402 | w = DOM.create('div', {id : 'menu_' + t.id, 'class' : s['class'], 'style' : 'position:fixed;_position:absolute;left:0;top:0;z-index:200000'});\r |
7403 | } else {\r |
7404 | w = DOM.create('div', {id : 'menu_' + t.id, 'class' : s['class'], 'style' : 'position:absolute;left:0;top:0;z-index:200000'});\r |
7405 | }\r |
7406 | co = DOM.add(w, 'div', {id : 'menu_' + t.id + '_co', 'class' : t.classPrefix + (s['class'] ? ' ' + s['class'] : '')});\r |
7407 | t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container});\r |
7408 | \r |
7409 | if (s.menu_line)\r |
7410 | DOM.add(co, 'span', {'class' : t.classPrefix + 'Line'});\r |
7411 | \r |
7412 | // n = DOM.add(co, 'div', {id : 'menu_' + t.id + '_co', 'class' : 'mceMenuContainer'});\r |
7413 | n = DOM.add(co, 'table', {id : 'menu_' + t.id + '_tbl', border : 0, cellPadding : 0, cellSpacing : 0});\r |
7414 | tb = DOM.add(n, 'tbody');\r |
7415 | \r |
7416 | each(t.items, function(o) {\r |
7417 | t._add(tb, o);\r |
7418 | });\r |
7419 | \r |
7420 | t.rendered = true;\r |
7421 | \r |
7422 | return w;\r |
7423 | },\r |
7424 | \r |
7425 | // Internal functions\r |
7426 | \r |
7427 | _keyHandler : function(e) {\r |
7428 | var t = this, kc = e.keyCode;\r |
7429 | \r |
7430 | function focus(d) {\r |
7431 | var i = t._focusIdx + d, e = DOM.select('a', 'menu_' + t.id)[i];\r |
7432 | \r |
7433 | if (e) {\r |
7434 | t._focusIdx = i;\r |
7435 | e.focus();\r |
7436 | }\r |
7437 | };\r |
7438 | \r |
7439 | switch (kc) {\r |
7440 | case 38:\r |
7441 | focus(-1); // Select first link\r |
7442 | return;\r |
7443 | \r |
7444 | case 40:\r |
7445 | focus(1);\r |
7446 | return;\r |
7447 | \r |
7448 | case 13:\r |
7449 | return;\r |
7450 | \r |
7451 | case 27:\r |
7452 | return this.hideMenu();\r |
7453 | }\r |
7454 | },\r |
7455 | \r |
7456 | _add : function(tb, o) {\r |
7457 | var n, s = o.settings, a, ro, it, cp = this.classPrefix, ic;\r |
7458 | \r |
7459 | if (s.separator) {\r |
7460 | ro = DOM.add(tb, 'tr', {id : o.id, 'class' : cp + 'ItemSeparator'});\r |
7461 | DOM.add(ro, 'td', {'class' : cp + 'ItemSeparator'});\r |
7462 | \r |
7463 | if (n = ro.previousSibling)\r |
7464 | DOM.addClass(n, 'mceLast');\r |
7465 | \r |
7466 | return;\r |
7467 | }\r |
7468 | \r |
7469 | n = ro = DOM.add(tb, 'tr', {id : o.id, 'class' : cp + 'Item ' + cp + 'ItemEnabled'});\r |
7470 | n = it = DOM.add(n, 'td');\r |
7471 | n = a = DOM.add(n, 'a', {href : 'javascript:;', onclick : "return false;", onmousedown : 'return false;'});\r |
7472 | \r |
7473 | DOM.addClass(it, s['class']);\r |
7474 | // n = DOM.add(n, 'span', {'class' : 'item'});\r |
7475 | \r |
7476 | ic = DOM.add(n, 'span', {'class' : 'mceIcon' + (s.icon ? ' mce_' + s.icon : '')});\r |
7477 | \r |
7478 | if (s.icon_src)\r |
7479 | DOM.add(ic, 'img', {src : s.icon_src});\r |
7480 | \r |
7481 | n = DOM.add(n, s.element || 'span', {'class' : 'mceText', title : o.settings.title}, o.settings.title);\r |
7482 | \r |
7483 | if (o.settings.style)\r |
7484 | DOM.setAttrib(n, 'style', o.settings.style);\r |
7485 | \r |
7486 | if (tb.childNodes.length == 1)\r |
7487 | DOM.addClass(ro, 'mceFirst');\r |
7488 | \r |
7489 | if ((n = ro.previousSibling) && DOM.hasClass(n, cp + 'ItemSeparator'))\r |
7490 | DOM.addClass(ro, 'mceFirst');\r |
7491 | \r |
7492 | if (o.collapse)\r |
7493 | DOM.addClass(ro, cp + 'ItemSub');\r |
7494 | \r |
7495 | if (n = ro.previousSibling)\r |
7496 | DOM.removeClass(n, 'mceLast');\r |
7497 | \r |
7498 | DOM.addClass(ro, 'mceLast');\r |
7499 | }\r |
7500 | });\r |
7501 | })(tinymce);(function(tinymce) {\r |
7502 | var DOM = tinymce.DOM;\r |
7503 | \r |
7504 | tinymce.create('tinymce.ui.Button:tinymce.ui.Control', {\r |
7505 | Button : function(id, s) {\r |
7506 | this.parent(id, s);\r |
7507 | this.classPrefix = 'mceButton';\r |
7508 | },\r |
7509 | \r |
7510 | renderHTML : function() {\r |
7511 | var cp = this.classPrefix, s = this.settings, h, l;\r |
7512 | \r |
7513 | l = DOM.encode(s.label || '');\r |
7514 | h = '<a id="' + this.id + '" href="javascript:;" class="' + cp + ' ' + cp + 'Enabled ' + s['class'] + (l ? ' ' + cp + 'Labeled' : '') +'" onmousedown="return false;" onclick="return false;" title="' + DOM.encode(s.title) + '">';\r |
7515 | \r |
7516 | if (s.image)\r |
7517 | h += '<img class="mceIcon" src="' + s.image + '" />' + l + '</a>';\r |
7518 | else\r |
7519 | h += '<span class="mceIcon ' + s['class'] + '"></span>' + (l ? '<span class="' + cp + 'Label">' + l + '</span>' : '') + '</a>';\r |
7520 | \r |
7521 | return h;\r |
7522 | },\r |
7523 | \r |
7524 | postRender : function() {\r |
7525 | var t = this, s = t.settings;\r |
7526 | \r |
7527 | tinymce.dom.Event.add(t.id, 'click', function(e) {\r |
7528 | if (!t.isDisabled())\r |
7529 | return s.onclick.call(s.scope, e);\r |
7530 | });\r |
7531 | }\r |
7532 | });\r |
7533 | })(tinymce);\r |
7534 | (function(tinymce) {\r |
7535 | var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher;\r |
7536 | \r |
7537 | tinymce.create('tinymce.ui.ListBox:tinymce.ui.Control', {\r |
7538 | ListBox : function(id, s) {\r |
7539 | var t = this;\r |
7540 | \r |
7541 | t.parent(id, s);\r |
7542 | \r |
7543 | t.items = [];\r |
7544 | \r |
7545 | t.onChange = new Dispatcher(t);\r |
7546 | \r |
7547 | t.onPostRender = new Dispatcher(t);\r |
7548 | \r |
7549 | t.onAdd = new Dispatcher(t);\r |
7550 | \r |
7551 | t.onRenderMenu = new tinymce.util.Dispatcher(this);\r |
7552 | \r |
7553 | t.classPrefix = 'mceListBox';\r |
7554 | },\r |
7555 | \r |
7556 | select : function(va) {\r |
7557 | var t = this, fv, f;\r |
7558 | \r |
7559 | if (va == undefined)\r |
7560 | return t.selectByIndex(-1);\r |
7561 | \r |
7562 | // Is string or number make function selector\r |
7563 | if (va && va.call)\r |
7564 | f = va;\r |
7565 | else {\r |
7566 | f = function(v) {\r |
7567 | return v == va;\r |
7568 | };\r |
7569 | }\r |
7570 | \r |
7571 | // Do we need to do something?\r |
7572 | if (va != t.selectedValue) {\r |
7573 | // Find item\r |
7574 | each(t.items, function(o, i) {\r |
7575 | if (f(o.value)) {\r |
7576 | fv = 1;\r |
7577 | t.selectByIndex(i);\r |
7578 | return false;\r |
7579 | }\r |
7580 | });\r |
7581 | \r |
7582 | if (!fv)\r |
7583 | t.selectByIndex(-1);\r |
7584 | }\r |
7585 | },\r |
7586 | \r |
7587 | selectByIndex : function(idx) {\r |
7588 | var t = this, e, o;\r |
7589 | \r |
7590 | if (idx != t.selectedIndex) {\r |
7591 | e = DOM.get(t.id + '_text');\r |
7592 | o = t.items[idx];\r |
7593 | \r |
7594 | if (o) {\r |
7595 | t.selectedValue = o.value;\r |
7596 | t.selectedIndex = idx;\r |
7597 | DOM.setHTML(e, DOM.encode(o.title));\r |
7598 | DOM.removeClass(e, 'mceTitle');\r |
7599 | } else {\r |
7600 | DOM.setHTML(e, DOM.encode(t.settings.title));\r |
7601 | DOM.addClass(e, 'mceTitle');\r |
7602 | t.selectedValue = t.selectedIndex = null;\r |
7603 | }\r |
7604 | \r |
7605 | e = 0;\r |
7606 | }\r |
7607 | },\r |
7608 | \r |
7609 | add : function(n, v, o) {\r |
7610 | var t = this;\r |
7611 | \r |
7612 | o = o || {};\r |
7613 | o = tinymce.extend(o, {\r |
7614 | title : n,\r |
7615 | value : v\r |
7616 | });\r |
7617 | \r |
7618 | t.items.push(o);\r |
7619 | t.onAdd.dispatch(t, o);\r |
7620 | },\r |
7621 | \r |
7622 | getLength : function() {\r |
7623 | return this.items.length;\r |
7624 | },\r |
7625 | \r |
7626 | renderHTML : function() {\r |
7627 | var h = '', t = this, s = t.settings, cp = t.classPrefix;\r |
7628 | \r |
7629 | h = '<table id="' + t.id + '" cellpadding="0" cellspacing="0" class="' + cp + ' ' + cp + 'Enabled' + (s['class'] ? (' ' + s['class']) : '') + '"><tbody><tr>';\r |
7630 | h += '<td>' + DOM.createHTML('a', {id : t.id + '_text', href : 'javascript:;', 'class' : 'mceText', onclick : "return false;", onmousedown : 'return false;'}, DOM.encode(t.settings.title)) + '</td>';\r |
7631 | h += '<td>' + DOM.createHTML('a', {id : t.id + '_open', tabindex : -1, href : 'javascript:;', 'class' : 'mceOpen', onclick : "return false;", onmousedown : 'return false;'}, '<span></span>') + '</td>';\r |
7632 | h += '</tr></tbody></table>';\r |
7633 | \r |
7634 | return h;\r |
7635 | },\r |
7636 | \r |
7637 | showMenu : function() {\r |
7638 | var t = this, p1, p2, e = DOM.get(this.id), m;\r |
7639 | \r |
7640 | if (t.isDisabled() || t.items.length == 0)\r |
7641 | return;\r |
7642 | \r |
7643 | if (t.menu && t.menu.isMenuVisible)\r |
7644 | return t.hideMenu();\r |
7645 | \r |
7646 | if (!t.isMenuRendered) {\r |
7647 | t.renderMenu();\r |
7648 | t.isMenuRendered = true;\r |
7649 | }\r |
7650 | \r |
7651 | p1 = DOM.getPos(this.settings.menu_container);\r |
7652 | p2 = DOM.getPos(e);\r |
7653 | \r |
7654 | m = t.menu;\r |
7655 | m.settings.offset_x = p2.x;\r |
7656 | m.settings.offset_y = p2.y;\r |
7657 | m.settings.keyboard_focus = !tinymce.isOpera; // Opera is buggy when it comes to auto focus\r |
7658 | \r |
7659 | // Select in menu\r |
7660 | if (t.oldID)\r |
7661 | m.items[t.oldID].setSelected(0);\r |
7662 | \r |
7663 | each(t.items, function(o) {\r |
7664 | if (o.value === t.selectedValue) {\r |
7665 | m.items[o.id].setSelected(1);\r |
7666 | t.oldID = o.id;\r |
7667 | }\r |
7668 | });\r |
7669 | \r |
7670 | m.showMenu(0, e.clientHeight);\r |
7671 | \r |
7672 | Event.add(DOM.doc, 'mousedown', t.hideMenu, t);\r |
7673 | DOM.addClass(t.id, t.classPrefix + 'Selected');\r |
7674 | \r |
7675 | //DOM.get(t.id + '_text').focus();\r |
7676 | },\r |
7677 | \r |
7678 | hideMenu : function(e) {\r |
7679 | var t = this;\r |
7680 | \r |
7681 | // Prevent double toogles by canceling the mouse click event to the button\r |
7682 | if (e && e.type == "mousedown" && (e.target.id == t.id + '_text' || e.target.id == t.id + '_open'))\r |
7683 | return;\r |
7684 | \r |
7685 | if (!e || !DOM.getParent(e.target, '.mceMenu')) {\r |
7686 | DOM.removeClass(t.id, t.classPrefix + 'Selected');\r |
7687 | Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);\r |
7688 | \r |
7689 | if (t.menu)\r |
7690 | t.menu.hideMenu();\r |
7691 | }\r |
7692 | },\r |
7693 | \r |
7694 | renderMenu : function() {\r |
7695 | var t = this, m;\r |
7696 | \r |
7697 | m = t.settings.control_manager.createDropMenu(t.id + '_menu', {\r |
7698 | menu_line : 1,\r |
7699 | 'class' : t.classPrefix + 'Menu mceNoIcons',\r |
7700 | max_width : 150,\r |
7701 | max_height : 500\r |
7702 | });\r |
7703 | \r |
7704 | m.onHideMenu.add(t.hideMenu, t);\r |
7705 | \r |
7706 | m.add({\r |
7707 | title : t.settings.title,\r |
7708 | 'class' : 'mceMenuItemTitle',\r |
7709 | onclick : function() {\r |
7710 | if (t.settings.onselect('') !== false)\r |
7711 | t.select(''); // Must be runned after\r |
7712 | }\r |
7713 | });\r |
7714 | \r |
7715 | each(t.items, function(o) {\r |
7716 | o.id = DOM.uniqueId();\r |
7717 | o.onclick = function() {\r |
7718 | if (t.settings.onselect(o.value) !== false)\r |
7719 | t.select(o.value); // Must be runned after\r |
7720 | };\r |
7721 | \r |
7722 | m.add(o);\r |
7723 | });\r |
7724 | \r |
7725 | t.onRenderMenu.dispatch(t, m);\r |
7726 | t.menu = m;\r |
7727 | },\r |
7728 | \r |
7729 | postRender : function() {\r |
7730 | var t = this, cp = t.classPrefix;\r |
7731 | \r |
7732 | Event.add(t.id, 'click', t.showMenu, t);\r |
7733 | Event.add(t.id + '_text', 'focus', function(e) {\r |
7734 | if (!t._focused) {\r |
7735 | t.keyDownHandler = Event.add(t.id + '_text', 'keydown', function(e) {\r |
7736 | var idx = -1, v, kc = e.keyCode;\r |
7737 | \r |
7738 | // Find current index\r |
7739 | each(t.items, function(v, i) {\r |
7740 | if (t.selectedValue == v.value)\r |
7741 | idx = i;\r |
7742 | });\r |
7743 | \r |
7744 | // Move up/down\r |
7745 | if (kc == 38)\r |
7746 | v = t.items[idx - 1];\r |
7747 | else if (kc == 40)\r |
7748 | v = t.items[idx + 1];\r |
7749 | else if (kc == 13) {\r |
7750 | // Fake select on enter\r |
7751 | v = t.selectedValue;\r |
7752 | t.selectedValue = null; // Needs to be null to fake change\r |
7753 | t.settings.onselect(v);\r |
7754 | return Event.cancel(e);\r |
7755 | }\r |
7756 | \r |
7757 | if (v) {\r |
7758 | t.hideMenu();\r |
7759 | t.select(v.value);\r |
7760 | }\r |
7761 | });\r |
7762 | }\r |
7763 | \r |
7764 | t._focused = 1;\r |
7765 | });\r |
7766 | Event.add(t.id + '_text', 'blur', function() {Event.remove(t.id + '_text', 'keydown', t.keyDownHandler); t._focused = 0;});\r |
7767 | \r |
7768 | // Old IE doesn't have hover on all elements\r |
7769 | if (tinymce.isIE6 || !DOM.boxModel) {\r |
7770 | Event.add(t.id, 'mouseover', function() {\r |
7771 | if (!DOM.hasClass(t.id, cp + 'Disabled'))\r |
7772 | DOM.addClass(t.id, cp + 'Hover');\r |
7773 | });\r |
7774 | \r |
7775 | Event.add(t.id, 'mouseout', function() {\r |
7776 | if (!DOM.hasClass(t.id, cp + 'Disabled'))\r |
7777 | DOM.removeClass(t.id, cp + 'Hover');\r |
7778 | });\r |
7779 | }\r |
7780 | \r |
7781 | t.onPostRender.dispatch(t, DOM.get(t.id));\r |
7782 | },\r |
7783 | \r |
7784 | destroy : function() {\r |
7785 | this.parent();\r |
7786 | \r |
7787 | Event.clear(this.id + '_text');\r |
7788 | Event.clear(this.id + '_open');\r |
7789 | }\r |
7790 | });\r |
7791 | })(tinymce);(function(tinymce) {\r |
7792 | var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher;\r |
7793 | \r |
7794 | tinymce.create('tinymce.ui.NativeListBox:tinymce.ui.ListBox', {\r |
7795 | NativeListBox : function(id, s) {\r |
7796 | this.parent(id, s);\r |
7797 | this.classPrefix = 'mceNativeListBox';\r |
7798 | },\r |
7799 | \r |
7800 | setDisabled : function(s) {\r |
7801 | DOM.get(this.id).disabled = s;\r |
7802 | },\r |
7803 | \r |
7804 | isDisabled : function() {\r |
7805 | return DOM.get(this.id).disabled;\r |
7806 | },\r |
7807 | \r |
7808 | select : function(va) {\r |
7809 | var t = this, fv, f;\r |
7810 | \r |
7811 | if (va == undefined)\r |
7812 | return t.selectByIndex(-1);\r |
7813 | \r |
7814 | // Is string or number make function selector\r |
7815 | if (va && va.call)\r |
7816 | f = va;\r |
7817 | else {\r |
7818 | f = function(v) {\r |
7819 | return v == va;\r |
7820 | };\r |
7821 | }\r |
7822 | \r |
7823 | // Do we need to do something?\r |
7824 | if (va != t.selectedValue) {\r |
7825 | // Find item\r |
7826 | each(t.items, function(o, i) {\r |
7827 | if (f(o.value)) {\r |
7828 | fv = 1;\r |
7829 | t.selectByIndex(i);\r |
7830 | return false;\r |
7831 | }\r |
7832 | });\r |
7833 | \r |
7834 | if (!fv)\r |
7835 | t.selectByIndex(-1);\r |
7836 | }\r |
7837 | },\r |
7838 | \r |
7839 | selectByIndex : function(idx) {\r |
7840 | DOM.get(this.id).selectedIndex = idx + 1;\r |
7841 | this.selectedValue = this.items[idx] ? this.items[idx].value : null;\r |
7842 | },\r |
7843 | \r |
7844 | add : function(n, v, a) {\r |
7845 | var o, t = this;\r |
7846 | \r |
7847 | a = a || {};\r |
7848 | a.value = v;\r |
7849 | \r |
7850 | if (t.isRendered())\r |
7851 | DOM.add(DOM.get(this.id), 'option', a, n);\r |
7852 | \r |
7853 | o = {\r |
7854 | title : n,\r |
7855 | value : v,\r |
7856 | attribs : a\r |
7857 | };\r |
7858 | \r |
7859 | t.items.push(o);\r |
7860 | t.onAdd.dispatch(t, o);\r |
7861 | },\r |
7862 | \r |
7863 | getLength : function() {\r |
7864 | return DOM.get(this.id).options.length - 1;\r |
7865 | },\r |
7866 | \r |
7867 | renderHTML : function() {\r |
7868 | var h, t = this;\r |
7869 | \r |
7870 | h = DOM.createHTML('option', {value : ''}, '-- ' + t.settings.title + ' --');\r |
7871 | \r |
7872 | each(t.items, function(it) {\r |
7873 | h += DOM.createHTML('option', {value : it.value}, it.title);\r |
7874 | });\r |
7875 | \r |
7876 | h = DOM.createHTML('select', {id : t.id, 'class' : 'mceNativeListBox'}, h);\r |
7877 | \r |
7878 | return h;\r |
7879 | },\r |
7880 | \r |
7881 | postRender : function() {\r |
7882 | var t = this, ch;\r |
7883 | \r |
7884 | t.rendered = true;\r |
7885 | \r |
7886 | function onChange(e) {\r |
7887 | var v = t.items[e.target.selectedIndex - 1];\r |
7888 | \r |
7889 | if (v && (v = v.value)) {\r |
7890 | t.onChange.dispatch(t, v);\r |
7891 | \r |
7892 | if (t.settings.onselect)\r |
7893 | t.settings.onselect(v);\r |
7894 | }\r |
7895 | };\r |
7896 | \r |
7897 | Event.add(t.id, 'change', onChange);\r |
7898 | \r |
7899 | // Accessibility keyhandler\r |
7900 | Event.add(t.id, 'keydown', function(e) {\r |
7901 | var bf;\r |
7902 | \r |
7903 | Event.remove(t.id, 'change', ch);\r |
7904 | \r |
7905 | bf = Event.add(t.id, 'blur', function() {\r |
7906 | Event.add(t.id, 'change', onChange);\r |
7907 | Event.remove(t.id, 'blur', bf);\r |
7908 | });\r |
7909 | \r |
7910 | if (e.keyCode == 13 || e.keyCode == 32) {\r |
7911 | onChange(e);\r |
7912 | return Event.cancel(e);\r |
7913 | }\r |
7914 | });\r |
7915 | \r |
7916 | t.onPostRender.dispatch(t, DOM.get(t.id));\r |
7917 | }\r |
7918 | });\r |
7919 | })(tinymce);(function(tinymce) {\r |
7920 | var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each;\r |
7921 | \r |
7922 | tinymce.create('tinymce.ui.MenuButton:tinymce.ui.Button', {\r |
7923 | MenuButton : function(id, s) {\r |
7924 | this.parent(id, s);\r |
7925 | \r |
7926 | this.onRenderMenu = new tinymce.util.Dispatcher(this);\r |
7927 | \r |
7928 | s.menu_container = s.menu_container || DOM.doc.body;\r |
7929 | },\r |
7930 | \r |
7931 | showMenu : function() {\r |
7932 | var t = this, p1, p2, e = DOM.get(t.id), m;\r |
7933 | \r |
7934 | if (t.isDisabled())\r |
7935 | return;\r |
7936 | \r |
7937 | if (!t.isMenuRendered) {\r |
7938 | t.renderMenu();\r |
7939 | t.isMenuRendered = true;\r |
7940 | }\r |
7941 | \r |
7942 | if (t.isMenuVisible)\r |
7943 | return t.hideMenu();\r |
7944 | \r |
7945 | p1 = DOM.getPos(t.settings.menu_container);\r |
7946 | p2 = DOM.getPos(e);\r |
7947 | \r |
7948 | m = t.menu;\r |
7949 | m.settings.offset_x = p2.x;\r |
7950 | m.settings.offset_y = p2.y;\r |
7951 | m.settings.vp_offset_x = p2.x;\r |
7952 | m.settings.vp_offset_y = p2.y;\r |
7953 | m.settings.keyboard_focus = t._focused;\r |
7954 | m.showMenu(0, e.clientHeight);\r |
7955 | \r |
7956 | Event.add(DOM.doc, 'mousedown', t.hideMenu, t);\r |
7957 | t.setState('Selected', 1);\r |
7958 | \r |
7959 | t.isMenuVisible = 1;\r |
7960 | },\r |
7961 | \r |
7962 | renderMenu : function() {\r |
7963 | var t = this, m;\r |
7964 | \r |
7965 | m = t.settings.control_manager.createDropMenu(t.id + '_menu', {\r |
7966 | menu_line : 1,\r |
7967 | 'class' : this.classPrefix + 'Menu',\r |
7968 | icons : t.settings.icons\r |
7969 | });\r |
7970 | \r |
7971 | m.onHideMenu.add(t.hideMenu, t);\r |
7972 | \r |
7973 | t.onRenderMenu.dispatch(t, m);\r |
7974 | t.menu = m;\r |
7975 | },\r |
7976 | \r |
7977 | hideMenu : function(e) {\r |
7978 | var t = this;\r |
7979 | \r |
7980 | // Prevent double toogles by canceling the mouse click event to the button\r |
7981 | if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id || e.id === t.id + '_open';}))\r |
7982 | return;\r |
7983 | \r |
7984 | if (!e || !DOM.getParent(e.target, '.mceMenu')) {\r |
7985 | t.setState('Selected', 0);\r |
7986 | Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);\r |
7987 | if (t.menu)\r |
7988 | t.menu.hideMenu();\r |
7989 | }\r |
7990 | \r |
7991 | t.isMenuVisible = 0;\r |
7992 | },\r |
7993 | \r |
7994 | postRender : function() {\r |
7995 | var t = this, s = t.settings;\r |
7996 | \r |
7997 | Event.add(t.id, 'click', function() {\r |
7998 | if (!t.isDisabled()) {\r |
7999 | if (s.onclick)\r |
8000 | s.onclick(t.value);\r |
8001 | \r |
8002 | t.showMenu();\r |
8003 | }\r |
8004 | });\r |
8005 | }\r |
8006 | });\r |
8007 | })(tinymce);(function(tinymce) {\r |
8008 | var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each;\r |
8009 | \r |
8010 | tinymce.create('tinymce.ui.SplitButton:tinymce.ui.MenuButton', {\r |
8011 | SplitButton : function(id, s) {\r |
8012 | this.parent(id, s);\r |
8013 | this.classPrefix = 'mceSplitButton';\r |
8014 | },\r |
8015 | \r |
8016 | renderHTML : function() {\r |
8017 | var h, t = this, s = t.settings, h1;\r |
8018 | \r |
8019 | h = '<tbody><tr>';\r |
8020 | \r |
8021 | if (s.image)\r |
8022 | h1 = DOM.createHTML('img ', {src : s.image, 'class' : 'mceAction ' + s['class']});\r |
8023 | else\r |
8024 | h1 = DOM.createHTML('span', {'class' : 'mceAction ' + s['class']}, '');\r |
8025 | \r |
8026 | h += '<td>' + DOM.createHTML('a', {id : t.id + '_action', href : 'javascript:;', 'class' : 'mceAction ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + '</td>';\r |
8027 | \r |
8028 | h1 = DOM.createHTML('span', {'class' : 'mceOpen ' + s['class']});\r |
8029 | h += '<td>' + DOM.createHTML('a', {id : t.id + '_open', href : 'javascript:;', 'class' : 'mceOpen ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + '</td>';\r |
8030 | \r |
8031 | h += '</tr></tbody>';\r |
8032 | \r |
8033 | return DOM.createHTML('table', {id : t.id, 'class' : 'mceSplitButton mceSplitButtonEnabled ' + s['class'], cellpadding : '0', cellspacing : '0', onmousedown : 'return false;', title : s.title}, h);\r |
8034 | },\r |
8035 | \r |
8036 | postRender : function() {\r |
8037 | var t = this, s = t.settings;\r |
8038 | \r |
8039 | if (s.onclick) {\r |
8040 | Event.add(t.id + '_action', 'click', function() {\r |
8041 | if (!t.isDisabled())\r |
8042 | s.onclick(t.value);\r |
8043 | });\r |
8044 | }\r |
8045 | \r |
8046 | Event.add(t.id + '_open', 'click', t.showMenu, t);\r |
8047 | Event.add(t.id + '_open', 'focus', function() {t._focused = 1;});\r |
8048 | Event.add(t.id + '_open', 'blur', function() {t._focused = 0;});\r |
8049 | \r |
8050 | // Old IE doesn't have hover on all elements\r |
8051 | if (tinymce.isIE6 || !DOM.boxModel) {\r |
8052 | Event.add(t.id, 'mouseover', function() {\r |
8053 | if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled'))\r |
8054 | DOM.addClass(t.id, 'mceSplitButtonHover');\r |
8055 | });\r |
8056 | \r |
8057 | Event.add(t.id, 'mouseout', function() {\r |
8058 | if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled'))\r |
8059 | DOM.removeClass(t.id, 'mceSplitButtonHover');\r |
8060 | });\r |
8061 | }\r |
8062 | },\r |
8063 | \r |
8064 | destroy : function() {\r |
8065 | this.parent();\r |
8066 | \r |
8067 | Event.clear(this.id + '_action');\r |
8068 | Event.clear(this.id + '_open');\r |
8069 | }\r |
8070 | });\r |
8071 | })(tinymce);\r |
8072 | (function(tinymce) {\r |
8073 | var DOM = tinymce.DOM, Event = tinymce.dom.Event, is = tinymce.is, each = tinymce.each;\r |
8074 | \r |
8075 | tinymce.create('tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton', {\r |
8076 | ColorSplitButton : function(id, s) {\r |
8077 | var t = this;\r |
8078 | \r |
8079 | t.parent(id, s);\r |
8080 | \r |
8081 | t.settings = s = tinymce.extend({\r |
8082 | colors : '000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF',\r |
8083 | grid_width : 8,\r |
8084 | default_color : '#888888'\r |
8085 | }, t.settings);\r |
8086 | \r |
8087 | t.onShowMenu = new tinymce.util.Dispatcher(t);\r |
8088 | \r |
8089 | t.onHideMenu = new tinymce.util.Dispatcher(t);\r |
8090 | \r |
8091 | t.value = s.default_color;\r |
8092 | },\r |
8093 | \r |
8094 | showMenu : function() {\r |
8095 | var t = this, r, p, e, p2;\r |
8096 | \r |
8097 | if (t.isDisabled())\r |
8098 | return;\r |
8099 | \r |
8100 | if (!t.isMenuRendered) {\r |
8101 | t.renderMenu();\r |
8102 | t.isMenuRendered = true;\r |
8103 | }\r |
8104 | \r |
8105 | if (t.isMenuVisible)\r |
8106 | return t.hideMenu();\r |
8107 | \r |
8108 | e = DOM.get(t.id);\r |
8109 | DOM.show(t.id + '_menu');\r |
8110 | DOM.addClass(e, 'mceSplitButtonSelected');\r |
8111 | p2 = DOM.getPos(e);\r |
8112 | DOM.setStyles(t.id + '_menu', {\r |
8113 | left : p2.x,\r |
8114 | top : p2.y + e.clientHeight,\r |
8115 | zIndex : 200000\r |
8116 | });\r |
8117 | e = 0;\r |
8118 | \r |
8119 | Event.add(DOM.doc, 'mousedown', t.hideMenu, t);\r |
8120 | t.onShowMenu.dispatch(t);\r |
8121 | \r |
8122 | if (t._focused) {\r |
8123 | t._keyHandler = Event.add(t.id + '_menu', 'keydown', function(e) {\r |
8124 | if (e.keyCode == 27)\r |
8125 | t.hideMenu();\r |
8126 | });\r |
8127 | \r |
8128 | DOM.select('a', t.id + '_menu')[0].focus(); // Select first link\r |
8129 | }\r |
8130 | \r |
8131 | t.isMenuVisible = 1;\r |
8132 | },\r |
8133 | \r |
8134 | hideMenu : function(e) {\r |
8135 | var t = this;\r |
8136 | \r |
8137 | // Prevent double toogles by canceling the mouse click event to the button\r |
8138 | if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id + '_open';}))\r |
8139 | return;\r |
8140 | \r |
8141 | if (!e || !DOM.getParent(e.target, '.mceSplitButtonMenu')) {\r |
8142 | DOM.removeClass(t.id, 'mceSplitButtonSelected');\r |
8143 | Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);\r |
8144 | Event.remove(t.id + '_menu', 'keydown', t._keyHandler);\r |
8145 | DOM.hide(t.id + '_menu');\r |
8146 | }\r |
8147 | \r |
8148 | t.onHideMenu.dispatch(t);\r |
8149 | \r |
8150 | t.isMenuVisible = 0;\r |
8151 | },\r |
8152 | \r |
8153 | renderMenu : function() {\r |
8154 | var t = this, m, i = 0, s = t.settings, n, tb, tr, w;\r |
8155 | \r |
8156 | w = DOM.add(s.menu_container, 'div', {id : t.id + '_menu', 'class' : s['menu_class'] + ' ' + s['class'], style : 'position:absolute;left:0;top:-1000px;'});\r |
8157 | m = DOM.add(w, 'div', {'class' : s['class'] + ' mceSplitButtonMenu'});\r |
8158 | DOM.add(m, 'span', {'class' : 'mceMenuLine'});\r |
8159 | \r |
8160 | n = DOM.add(m, 'table', {'class' : 'mceColorSplitMenu'});\r |
8161 | tb = DOM.add(n, 'tbody');\r |
8162 | \r |
8163 | // Generate color grid\r |
8164 | i = 0;\r |
8165 | each(is(s.colors, 'array') ? s.colors : s.colors.split(','), function(c) {\r |
8166 | c = c.replace(/^#/, '');\r |
8167 | \r |
8168 | if (!i--) {\r |
8169 | tr = DOM.add(tb, 'tr');\r |
8170 | i = s.grid_width - 1;\r |
8171 | }\r |
8172 | \r |
8173 | n = DOM.add(tr, 'td');\r |
8174 | \r |
8175 | n = DOM.add(n, 'a', {\r |
8176 | href : 'javascript:;',\r |
8177 | style : {\r |
8178 | backgroundColor : '#' + c\r |
8179 | },\r |
8180 | mce_color : '#' + c\r |
8181 | });\r |
8182 | });\r |
8183 | \r |
8184 | if (s.more_colors_func) {\r |
8185 | n = DOM.add(tb, 'tr');\r |
8186 | n = DOM.add(n, 'td', {colspan : s.grid_width, 'class' : 'mceMoreColors'});\r |
8187 | n = DOM.add(n, 'a', {id : t.id + '_more', href : 'javascript:;', onclick : 'return false;', 'class' : 'mceMoreColors'}, s.more_colors_title);\r |
8188 | \r |
8189 | Event.add(n, 'click', function(e) {\r |
8190 | s.more_colors_func.call(s.more_colors_scope || this);\r |
8191 | return Event.cancel(e); // Cancel to fix onbeforeunload problem\r |
8192 | });\r |
8193 | }\r |
8194 | \r |
8195 | DOM.addClass(m, 'mceColorSplitMenu');\r |
8196 | \r |
8197 | Event.add(t.id + '_menu', 'click', function(e) {\r |
8198 | var c;\r |
8199 | \r |
8200 | e = e.target;\r |
8201 | \r |
8202 | if (e.nodeName == 'A' && (c = e.getAttribute('mce_color')))\r |
8203 | t.setColor(c);\r |
8204 | \r |
8205 | return Event.cancel(e); // Prevent IE auto save warning\r |
8206 | });\r |
8207 | \r |
8208 | return w;\r |
8209 | },\r |
8210 | \r |
8211 | setColor : function(c) {\r |
8212 | var t = this;\r |
8213 | \r |
8214 | DOM.setStyle(t.id + '_preview', 'backgroundColor', c);\r |
8215 | \r |
8216 | t.value = c;\r |
8217 | t.hideMenu();\r |
8218 | t.settings.onselect(c);\r |
8219 | },\r |
8220 | \r |
8221 | postRender : function() {\r |
8222 | var t = this, id = t.id;\r |
8223 | \r |
8224 | t.parent();\r |
8225 | DOM.add(id + '_action', 'div', {id : id + '_preview', 'class' : 'mceColorPreview'});\r |
8226 | DOM.setStyle(t.id + '_preview', 'backgroundColor', t.value);\r |
8227 | },\r |
8228 | \r |
8229 | destroy : function() {\r |
8230 | this.parent();\r |
8231 | \r |
8232 | Event.clear(this.id + '_menu');\r |
8233 | Event.clear(this.id + '_more');\r |
8234 | DOM.remove(this.id + '_menu');\r |
8235 | }\r |
8236 | });\r |
8237 | })(tinymce);\r |
8238 | tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {\r |
8239 | renderHTML : function() {\r |
8240 | var t = this, h = '', c, co, dom = tinymce.DOM, s = t.settings, i, pr, nx, cl;\r |
8241 | \r |
8242 | cl = t.controls;\r |
8243 | for (i=0; i<cl.length; i++) {\r |
8244 | // Get current control, prev control, next control and if the control is a list box or not\r |
8245 | co = cl[i];\r |
8246 | pr = cl[i - 1];\r |
8247 | nx = cl[i + 1];\r |
8248 | \r |
8249 | // Add toolbar start\r |
8250 | if (i === 0) {\r |
8251 | c = 'mceToolbarStart';\r |
8252 | \r |
8253 | if (co.Button)\r |
8254 | c += ' mceToolbarStartButton';\r |
8255 | else if (co.SplitButton)\r |
8256 | c += ' mceToolbarStartSplitButton';\r |
8257 | else if (co.ListBox)\r |
8258 | c += ' mceToolbarStartListBox';\r |
8259 | \r |
8260 | h += dom.createHTML('td', {'class' : c}, dom.createHTML('span', null, '<!-- IE -->'));\r |
8261 | }\r |
8262 | \r |
8263 | // Add toolbar end before list box and after the previous button\r |
8264 | // This is to fix the o2k7 editor skins\r |
8265 | if (pr && co.ListBox) {\r |
8266 | if (pr.Button || pr.SplitButton)\r |
8267 | h += dom.createHTML('td', {'class' : 'mceToolbarEnd'}, dom.createHTML('span', null, '<!-- IE -->'));\r |
8268 | }\r |
8269 | \r |
8270 | // Render control HTML\r |
8271 | \r |
8272 | // IE 8 quick fix, needed to propertly generate a hit area for anchors\r |
8273 | if (dom.stdMode)\r |
8274 | h += '<td style="position: relative">' + co.renderHTML() + '</td>';\r |
8275 | else\r |
8276 | h += '<td>' + co.renderHTML() + '</td>';\r |
8277 | \r |
8278 | // Add toolbar start after list box and before the next button\r |
8279 | // This is to fix the o2k7 editor skins\r |
8280 | if (nx && co.ListBox) {\r |
8281 | if (nx.Button || nx.SplitButton)\r |
8282 | h += dom.createHTML('td', {'class' : 'mceToolbarStart'}, dom.createHTML('span', null, '<!-- IE -->'));\r |
8283 | }\r |
8284 | }\r |
8285 | \r |
8286 | c = 'mceToolbarEnd';\r |
8287 | \r |
8288 | if (co.Button)\r |
8289 | c += ' mceToolbarEndButton';\r |
8290 | else if (co.SplitButton)\r |
8291 | c += ' mceToolbarEndSplitButton';\r |
8292 | else if (co.ListBox)\r |
8293 | c += ' mceToolbarEndListBox';\r |
8294 | \r |
8295 | h += dom.createHTML('td', {'class' : c}, dom.createHTML('span', null, '<!-- IE -->'));\r |
8296 | \r |
8297 | return dom.createHTML('table', {id : t.id, 'class' : 'mceToolbar' + (s['class'] ? ' ' + s['class'] : ''), cellpadding : '0', cellspacing : '0', align : t.settings.align || ''}, '<tbody><tr>' + h + '</tr></tbody>');\r |
8298 | }\r |
8299 | });\r |
8300 | (function(tinymce) {\r |
8301 | var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each;\r |
8302 | \r |
8303 | tinymce.create('tinymce.AddOnManager', {\r |
8304 | items : [],\r |
8305 | urls : {},\r |
8306 | lookup : {},\r |
8307 | \r |
8308 | onAdd : new Dispatcher(this),\r |
8309 | \r |
8310 | get : function(n) {\r |
8311 | return this.lookup[n];\r |
8312 | },\r |
8313 | \r |
8314 | requireLangPack : function(n) {\r |
8315 | var u, s = tinymce.EditorManager.settings;\r |
8316 | \r |
8317 | if (s && s.language) {\r |
8318 | u = this.urls[n] + '/langs/' + s.language + '.js';\r |
8319 | \r |
8320 | if (!tinymce.dom.Event.domLoaded && !s.strict_mode)\r |
8321 | tinymce.ScriptLoader.load(u);\r |
8322 | else\r |
8323 | tinymce.ScriptLoader.add(u);\r |
8324 | }\r |
8325 | },\r |
8326 | \r |
8327 | add : function(id, o) {\r |
8328 | this.items.push(o);\r |
8329 | this.lookup[id] = o;\r |
8330 | this.onAdd.dispatch(this, id, o);\r |
8331 | \r |
8332 | return o;\r |
8333 | },\r |
8334 | \r |
8335 | load : function(n, u, cb, s) {\r |
8336 | var t = this;\r |
8337 | \r |
8338 | if (t.urls[n])\r |
8339 | return;\r |
8340 | \r |
8341 | if (u.indexOf('/') != 0 && u.indexOf('://') == -1)\r |
8342 | u = tinymce.baseURL + '/' + u;\r |
8343 | \r |
8344 | t.urls[n] = u.substring(0, u.lastIndexOf('/'));\r |
8345 | tinymce.ScriptLoader.add(u, cb, s);\r |
8346 | }\r |
8347 | });\r |
8348 | \r |
8349 | // Create plugin and theme managers\r |
8350 | tinymce.PluginManager = new tinymce.AddOnManager();\r |
8351 | tinymce.ThemeManager = new tinymce.AddOnManager();\r |
8352 | }(tinymce));\r |
8353 | \r |
8354 | (function(tinymce) {\r |
8355 | // Shorten names\r |
8356 | var each = tinymce.each, extend = tinymce.extend, DOM = tinymce.DOM, Event = tinymce.dom.Event, ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, explode = tinymce.explode;\r |
8357 | \r |
8358 | tinymce.create('static tinymce.EditorManager', {\r |
8359 | editors : {},\r |
8360 | \r |
8361 | i18n : {},\r |
8362 | \r |
8363 | activeEditor : null,\r |
8364 | \r |
8365 | preInit : function() {\r |
8366 | var t = this, lo = window.location;\r |
8367 | \r |
8368 | // Plone fix\r |
8369 | var lo_array = lo.href.split('/');\r |
8370 | if (lo.href.indexOf('portal_factory') != -1) {\r |
8371 | while (lo_array[lo_array.length-1] != 'portal_factory') {\r |
8372 | lo_array.pop();\r |
8373 | }\r |
8374 | lo_array.pop();\r |
8375 | } else {\r |
8376 | if (lo_array.length > 4) {\r |
8377 | lo_array.pop();\r |
8378 | }\r |
8379 | if (lo_array.length > 4) {\r |
8380 | lo_array.pop();\r |
8381 | }\r |
8382 | }\r |
8383 | tinymce.documentBaseURL = lo_array.join('/') + '/';\r |
8384 | \r |
8385 | // Plone fix when editing contextual portlets\r |
8386 | if (lo.href.indexOf('++contextportlets++') != -1) {\r |
8387 | tinymce.documentBaseURL = tinymce.documentBaseURL.substr(0, lo.href.indexOf('++contextportlets++'));\r |
8388 | }\r |
8389 | \r |
8390 | // Setup some URLs where the editor API is located and where the document is\r |
8391 | /*\r |
8392 | tinymce.documentBaseURL = lo.href.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');\r |
8393 | if (!/[\/\\]$/.test(tinymce.documentBaseURL))\r |
8394 | tinymce.documentBaseURL += '/';\r |
8395 | */\r |
8396 | \r |
8397 | tinymce.baseURL = new tinymce.util.URI(tinymce.documentBaseURL).toAbsolute(tinymce.baseURL);\r |
8398 | tinymce.EditorManager.baseURI = new tinymce.util.URI(tinymce.baseURL);\r |
8399 | \r |
8400 | // Add before unload listener\r |
8401 | // This was required since IE was leaking memory if you added and removed beforeunload listeners\r |
8402 | // with attachEvent/detatchEvent so this only adds one listener and instances can the attach to the onBeforeUnload event\r |
8403 | t.onBeforeUnload = new tinymce.util.Dispatcher(t);\r |
8404 | \r |
8405 | // Must be on window or IE will leak if the editor is placed in frame or iframe\r |
8406 | Event.add(window, 'beforeunload', function(e) {\r |
8407 | t.onBeforeUnload.dispatch(t, e);\r |
8408 | });\r |
8409 | },\r |
8410 | \r |
8411 | init : function(s) {\r |
8412 | var t = this, pl, sl = tinymce.ScriptLoader, c, e, el = [], ed;\r |
8413 | \r |
8414 | function execCallback(se, n, s) {\r |
8415 | var f = se[n];\r |
8416 | \r |
8417 | if (!f)\r |
8418 | return;\r |
8419 | \r |
8420 | if (tinymce.is(f, 'string')) {\r |
8421 | s = f.replace(/\.\w+$/, '');\r |
8422 | s = s ? tinymce.resolve(s) : 0;\r |
8423 | f = tinymce.resolve(f);\r |
8424 | }\r |
8425 | \r |
8426 | return f.apply(s || this, Array.prototype.slice.call(arguments, 2));\r |
8427 | };\r |
8428 | \r |
8429 | s = extend({\r |
8430 | theme : "simple",\r |
8431 | language : "en",\r |
8432 | strict_loading_mode : document.contentType == 'application/xhtml+xml'\r |
8433 | }, s);\r |
8434 | \r |
8435 | t.settings = s;\r |
8436 | \r |
8437 | // If page not loaded and strict mode isn't enabled then load them\r |
8438 | if (!Event.domLoaded && !s.strict_loading_mode) {\r |
8439 | // Load language\r |
8440 | if (s.language)\r |
8441 | sl.add(tinymce.baseURL + '/langs/' + s.language + '.js');\r |
8442 | \r |
8443 | // Load theme\r |
8444 | if (s.theme && s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme])\r |
8445 | ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js');\r |
8446 | \r |
8447 | // Load plugins\r |
8448 | if (s.plugins) {\r |
8449 | pl = explode(s.plugins);\r |
8450 | \r |
8451 | // Load rest if plugins\r |
8452 | each(pl, function(v) {\r |
8453 | if (v && v.charAt(0) != '-' && !PluginManager.urls[v]) {\r |
8454 | // Skip safari plugin for other browsers\r |
8455 | if (!tinymce.isWebKit && v == 'safari')\r |
8456 | return;\r |
8457 | \r |
8458 | PluginManager.load(v, 'plugins/' + v + '/editor_plugin' + tinymce.suffix + '.js');\r |
8459 | }\r |
8460 | });\r |
8461 | }\r |
8462 | \r |
8463 | sl.loadQueue();\r |
8464 | }\r |
8465 | \r |
8466 | // Legacy call\r |
8467 | Event.add(document, 'init', function() {\r |
8468 | var l, co;\r |
8469 | \r |
8470 | execCallback(s, 'onpageload');\r |
8471 | \r |
8472 | // Verify that it's a valid browser\r |
8473 | if (s.browsers) {\r |
8474 | l = false;\r |
8475 | \r |
8476 | each(explode(s.browsers), function(v) {\r |
8477 | switch (v) {\r |
8478 | case 'ie':\r |
8479 | case 'msie':\r |
8480 | if (tinymce.isIE)\r |
8481 | l = true;\r |
8482 | break;\r |
8483 | \r |
8484 | case 'gecko':\r |
8485 | if (tinymce.isGecko)\r |
8486 | l = true;\r |
8487 | break;\r |
8488 | \r |
8489 | case 'safari':\r |
8490 | case 'webkit':\r |
8491 | if (tinymce.isWebKit)\r |
8492 | l = true;\r |
8493 | break;\r |
8494 | \r |
8495 | case 'opera':\r |
8496 | if (tinymce.isOpera)\r |
8497 | l = true;\r |
8498 | \r |
8499 | break;\r |
8500 | }\r |
8501 | });\r |
8502 | \r |
8503 | // Not a valid one\r |
8504 | if (!l)\r |
8505 | return;\r |
8506 | }\r |
8507 | \r |
8508 | switch (s.mode) {\r |
8509 | case "exact":\r |
8510 | l = s.elements || '';\r |
8511 | \r |
8512 | if(l.length > 0) {\r |
8513 | each(explode(l), function(v) {\r |
8514 | if (DOM.get(v)) {\r |
8515 | ed = new tinymce.Editor(v, s);\r |
8516 | el.push(ed);\r |
8517 | ed.render(1);\r |
8518 | } else {\r |
8519 | c = 0;\r |
8520 | \r |
8521 | each(document.forms, function(f) {\r |
8522 | each(f.elements, function(e) {\r |
8523 | if (e.name === v) {\r |
8524 | v = 'mce_editor_' + c;\r |
8525 | DOM.setAttrib(e, 'id', v);\r |
8526 | \r |
8527 | ed = new tinymce.Editor(v, s);\r |
8528 | el.push(ed);\r |
8529 | ed.render(1);\r |
8530 | }\r |
8531 | });\r |
8532 | });\r |
8533 | }\r |
8534 | });\r |
8535 | }\r |
8536 | break;\r |
8537 | \r |
8538 | case "textareas":\r |
8539 | case "specific_textareas":\r |
8540 | function hasClass(n, c) {\r |
8541 | return c.constructor === RegExp ? c.test(n.className) : DOM.hasClass(n, c);\r |
8542 | };\r |
8543 | \r |
8544 | each(DOM.select('textarea'), function(v) {\r |
8545 | if (s.editor_deselector && hasClass(v, s.editor_deselector))\r |
8546 | return;\r |
8547 | \r |
8548 | if (!s.editor_selector || hasClass(v, s.editor_selector)) {\r |
8549 | // Can we use the name\r |
8550 | e = DOM.get(v.name);\r |
8551 | if (!v.id && !e)\r |
8552 | v.id = v.name;\r |
8553 | \r |
8554 | // Generate unique name if missing or already exists\r |
8555 | if (!v.id || t.get(v.id))\r |
8556 | v.id = DOM.uniqueId();\r |
8557 | \r |
8558 | ed = new tinymce.Editor(v.id, s);\r |
8559 | el.push(ed);\r |
8560 | ed.render(1);\r |
8561 | }\r |
8562 | });\r |
8563 | break;\r |
8564 | }\r |
8565 | \r |
8566 | // Call onInit when all editors are initialized\r |
8567 | if (s.oninit) {\r |
8568 | l = co = 0;\r |
8569 | \r |
8570 | each (el, function(ed) {\r |
8571 | co++;\r |
8572 | \r |
8573 | if (!ed.initialized) {\r |
8574 | // Wait for it\r |
8575 | ed.onInit.add(function() {\r |
8576 | l++;\r |
8577 | \r |
8578 | // All done\r |
8579 | if (l == co)\r |
8580 | execCallback(s, 'oninit');\r |
8581 | });\r |
8582 | } else\r |
8583 | l++;\r |
8584 | \r |
8585 | // All done\r |
8586 | if (l == co)\r |
8587 | execCallback(s, 'oninit'); \r |
8588 | });\r |
8589 | }\r |
8590 | });\r |
8591 | },\r |
8592 | \r |
8593 | get : function(id) {\r |
8594 | return this.editors[id];\r |
8595 | },\r |
8596 | \r |
8597 | getInstanceById : function(id) {\r |
8598 | return this.get(id);\r |
8599 | },\r |
8600 | \r |
8601 | add : function(e) {\r |
8602 | this.editors[e.id] = e;\r |
8603 | this._setActive(e);\r |
8604 | \r |
8605 | return e;\r |
8606 | },\r |
8607 | \r |
8608 | remove : function(e) {\r |
8609 | var t = this;\r |
8610 | \r |
8611 | // Not in the collection\r |
8612 | if (!t.editors[e.id])\r |
8613 | return null;\r |
8614 | \r |
8615 | delete t.editors[e.id];\r |
8616 | \r |
8617 | // Select another editor since the active one was removed\r |
8618 | if (t.activeEditor == e) {\r |
8619 | t._setActive(null);\r |
8620 | \r |
8621 | each(t.editors, function(e) {\r |
8622 | t._setActive(e);\r |
8623 | return false; // Break\r |
8624 | });\r |
8625 | }\r |
8626 | \r |
8627 | e.destroy();\r |
8628 | \r |
8629 | return e;\r |
8630 | },\r |
8631 | \r |
8632 | execCommand : function(c, u, v) {\r |
8633 | var t = this, ed = t.get(v), w;\r |
8634 | \r |
8635 | // Manager commands\r |
8636 | switch (c) {\r |
8637 | case "mceFocus":\r |
8638 | ed.focus();\r |
8639 | return true;\r |
8640 | \r |
8641 | case "mceAddEditor":\r |
8642 | case "mceAddControl":\r |
8643 | if (!t.get(v))\r |
8644 | new tinymce.Editor(v, t.settings).render();\r |
8645 | \r |
8646 | return true;\r |
8647 | \r |
8648 | case "mceAddFrameControl":\r |
8649 | w = v.window;\r |
8650 | \r |
8651 | // Add tinyMCE global instance and tinymce namespace to specified window\r |
8652 | w.tinyMCE = tinyMCE;\r |
8653 | w.tinymce = tinymce;\r |
8654 | \r |
8655 | tinymce.DOM.doc = w.document;\r |
8656 | tinymce.DOM.win = w;\r |
8657 | \r |
8658 | ed = new tinymce.Editor(v.element_id, v);\r |
8659 | ed.render();\r |
8660 | \r |
8661 | // Fix IE memory leaks\r |
8662 | if (tinymce.isIE) {\r |
8663 | function clr() {\r |
8664 | ed.destroy();\r |
8665 | w.detachEvent('onunload', clr);\r |
8666 | w = w.tinyMCE = w.tinymce = null; // IE leak\r |
8667 | };\r |
8668 | \r |
8669 | w.attachEvent('onunload', clr);\r |
8670 | }\r |
8671 | \r |
8672 | v.page_window = null;\r |
8673 | \r |
8674 | return true;\r |
8675 | \r |
8676 | case "mceRemoveEditor":\r |
8677 | case "mceRemoveControl":\r |
8678 | if (ed)\r |
8679 | ed.remove();\r |
8680 | \r |
8681 | return true;\r |
8682 | \r |
8683 | case 'mceToggleEditor':\r |
8684 | if (!ed) {\r |
8685 | t.execCommand('mceAddControl', 0, v);\r |
8686 | return true;\r |
8687 | }\r |
8688 | \r |
8689 | if (ed.isHidden())\r |
8690 | ed.show();\r |
8691 | else\r |
8692 | ed.hide();\r |
8693 | \r |
8694 | return true;\r |
8695 | }\r |
8696 | \r |
8697 | // Run command on active editor\r |
8698 | if (t.activeEditor)\r |
8699 | return t.activeEditor.execCommand(c, u, v);\r |
8700 | \r |
8701 | return false;\r |
8702 | },\r |
8703 | \r |
8704 | execInstanceCommand : function(id, c, u, v) {\r |
8705 | var ed = this.get(id);\r |
8706 | \r |
8707 | if (ed)\r |
8708 | return ed.execCommand(c, u, v);\r |
8709 | \r |
8710 | return false;\r |
8711 | },\r |
8712 | \r |
8713 | triggerSave : function() {\r |
8714 | each(this.editors, function(e) {\r |
8715 | e.save();\r |
8716 | });\r |
8717 | },\r |
8718 | \r |
8719 | addI18n : function(p, o) {\r |
8720 | var lo, i18n = this.i18n;\r |
8721 | \r |
8722 | if (!tinymce.is(p, 'string')) {\r |
8723 | each(p, function(o, lc) {\r |
8724 | each(o, function(o, g) {\r |
8725 | each(o, function(o, k) {\r |
8726 | if (g === 'common')\r |
8727 | i18n[lc + '.' + k] = o;\r |
8728 | else\r |
8729 | i18n[lc + '.' + g + '.' + k] = o;\r |
8730 | });\r |
8731 | });\r |
8732 | });\r |
8733 | } else {\r |
8734 | each(o, function(o, k) {\r |
8735 | i18n[p + '.' + k] = o;\r |
8736 | });\r |
8737 | }\r |
8738 | },\r |
8739 | \r |
8740 | // Private methods\r |
8741 | \r |
8742 | _setActive : function(e) {\r |
8743 | this.selectedInstance = this.activeEditor = e;\r |
8744 | }\r |
8745 | });\r |
8746 | \r |
8747 | tinymce.EditorManager.preInit();\r |
8748 | })(tinymce);\r |
8749 | \r |
8750 | var tinyMCE = window.tinyMCE = tinymce.EditorManager;\r |
8751 | \r |
8752 | (function(tinymce) {\r |
8753 | var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, Dispatcher = tinymce.util.Dispatcher;\r |
8754 | var each = tinymce.each, isGecko = tinymce.isGecko, isIE = tinymce.isIE, isWebKit = tinymce.isWebKit;\r |
8755 | var is = tinymce.is, ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, EditorManager = tinymce.EditorManager;\r |
8756 | var inArray = tinymce.inArray, grep = tinymce.grep, explode = tinymce.explode;\r |
8757 | \r |
8758 | tinymce.create('tinymce.Editor', {\r |
8759 | Editor : function(id, s) {\r |
8760 | var t = this;\r |
8761 | \r |
8762 | t.id = t.editorId = id;\r |
8763 | \r |
8764 | t.execCommands = {};\r |
8765 | t.queryStateCommands = {};\r |
8766 | t.queryValueCommands = {};\r |
8767 | \r |
8768 | t.isNotDirty = false;\r |
8769 | \r |
8770 | t.plugins = {};\r |
8771 | \r |
8772 | // Add events to the editor\r |
8773 | each([\r |
8774 | 'onPreInit',\r |
8775 | \r |
8776 | 'onBeforeRenderUI',\r |
8777 | \r |
8778 | 'onPostRender',\r |
8779 | \r |
8780 | 'onInit',\r |
8781 | \r |
8782 | 'onRemove',\r |
8783 | \r |
8784 | 'onActivate',\r |
8785 | \r |
8786 | 'onDeactivate',\r |
8787 | \r |
8788 | 'onClick',\r |
8789 | \r |
8790 | 'onEvent',\r |
8791 | \r |
8792 | 'onMouseUp',\r |
8793 | \r |
8794 | 'onMouseDown',\r |
8795 | \r |
8796 | 'onDblClick',\r |
8797 | \r |
8798 | 'onKeyDown',\r |
8799 | \r |
8800 | 'onKeyUp',\r |
8801 | \r |
8802 | 'onKeyPress',\r |
8803 | \r |
8804 | 'onContextMenu',\r |
8805 | \r |
8806 | 'onSubmit',\r |
8807 | \r |
8808 | 'onReset',\r |
8809 | \r |
8810 | 'onPaste',\r |
8811 | \r |
8812 | 'onPreProcess',\r |
8813 | \r |
8814 | 'onPostProcess',\r |
8815 | \r |
8816 | 'onBeforeSetContent',\r |
8817 | \r |
8818 | 'onBeforeGetContent',\r |
8819 | \r |
8820 | 'onSetContent',\r |
8821 | \r |
8822 | 'onGetContent',\r |
8823 | \r |
8824 | 'onLoadContent',\r |
8825 | \r |
8826 | 'onSaveContent',\r |
8827 | \r |
8828 | 'onNodeChange',\r |
8829 | \r |
8830 | 'onChange',\r |
8831 | \r |
8832 | 'onBeforeExecCommand',\r |
8833 | \r |
8834 | 'onExecCommand',\r |
8835 | \r |
8836 | 'onUndo',\r |
8837 | \r |
8838 | 'onRedo',\r |
8839 | \r |
8840 | 'onVisualAid',\r |
8841 | \r |
8842 | 'onSetProgressState'\r |
8843 | ], function(e) {\r |
8844 | t[e] = new Dispatcher(t);\r |
8845 | });\r |
8846 | \r |
8847 | t.settings = s = extend({\r |
8848 | id : id,\r |
8849 | language : 'en',\r |
8850 | docs_language : 'en',\r |
8851 | theme : 'simple',\r |
8852 | skin : 'default',\r |
8853 | delta_width : 0,\r |
8854 | delta_height : 0,\r |
8855 | popup_css : '',\r |
8856 | plugins : '',\r |
8857 | document_base_url : tinymce.documentBaseURL,\r |
8858 | add_form_submit_trigger : 1,\r |
8859 | submit_patch : 1,\r |
8860 | add_unload_trigger : 1,\r |
8861 | convert_urls : 1,\r |
8862 | relative_urls : 1,\r |
8863 | remove_script_host : 1,\r |
8864 | table_inline_editing : 0,\r |
8865 | object_resizing : 1,\r |
8866 | cleanup : 1,\r |
8867 | accessibility_focus : 1,\r |
8868 | custom_shortcuts : 1,\r |
8869 | custom_undo_redo_keyboard_shortcuts : 1,\r |
8870 | custom_undo_redo_restore_selection : 1,\r |
8871 | custom_undo_redo : 1,\r |
8872 | doctype : '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">',\r |
8873 | visual_table_class : 'mceItemTable',\r |
8874 | visual : 1,\r |
8875 | inline_styles : true,\r |
8876 | convert_fonts_to_spans : true,\r |
8877 | font_size_style_values : 'xx-small,x-small,small,medium,large,x-large,xx-large',\r |
8878 | apply_source_formatting : 1,\r |
8879 | directionality : 'ltr',\r |
8880 | forced_root_block : 'p',\r |
8881 | valid_elements : '@[id|class|style|title|dir<ltr?rtl|lang|xml::lang|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],a[rel|rev|charset|hreflang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur],strong/b,em/i,strike,u,#p,-ol[type|compact],-ul[type|compact],-li,br,img[longdesc|usemap|src|border|alt=|title|hspace|vspace|width|height|align],-sub,-sup,-blockquote[cite],-table[border|cellspacing|cellpadding|width|frame|rules|height|align|summary|bgcolor|background|bordercolor],-tr[rowspan|width|height|align|valign|bgcolor|background|bordercolor],tbody,thead,tfoot,#td[colspan|rowspan|width|height|align|valign|bgcolor|background|bordercolor|scope],#th[colspan|rowspan|width|height|align|valign|scope],caption,-div,-span,-code,-pre,address,-h1,-h2,-h3,-h4,-h5,-h6,hr[size|noshade],-font[face|size|color],dd,dl,dt,cite,abbr,acronym,del[datetime|cite],ins[datetime|cite],object[classid|width|height|codebase|*],param[name|value],embed[type|width|height|src|*],script[src|type],map[name],area[shape|coords|href|alt|target],bdo,button,col[align|char|charoff|span|valign|width],colgroup[align|char|charoff|span|valign|width],dfn,fieldset,form[action|accept|accept-charset|enctype|method],input[accept|alt|checked|disabled|maxlength|name|readonly|size|src|type|value|tabindex|accesskey],kbd,label[for],legend,noscript,optgroup[label|disabled],option[disabled|label|selected|value],q[cite],samp,select[disabled|multiple|name|size],small,textarea[cols|rows|disabled|name|readonly],tt,var,big',\r |
8882 | hidden_input : 1,\r |
8883 | padd_empty_editor : 1,\r |
8884 | render_ui : 1,\r |
8885 | init_theme : 1,\r |
8886 | force_p_newlines : 1,\r |
8887 | indentation : '30px',\r |
8888 | keep_styles : 1,\r |
8889 | fix_table_elements : 1,\r |
8890 | removeformat_selector : 'span,b,strong,em,i,font,u,strike'\r |
8891 | }, s);\r |
8892 | \r |
8893 | t.documentBaseURI = new tinymce.util.URI(s.document_base_url || tinymce.documentBaseURL, {\r |
8894 | base_uri : tinyMCE.baseURI\r |
8895 | });\r |
8896 | \r |
8897 | t.baseURI = EditorManager.baseURI;\r |
8898 | \r |
8899 | // Call setup\r |
8900 | t.execCallback('setup', t);\r |
8901 | },\r |
8902 | \r |
8903 | render : function(nst) {\r |
8904 | var t = this, s = t.settings, id = t.id, sl = tinymce.ScriptLoader;\r |
8905 | \r |
8906 | // Page is not loaded yet, wait for it\r |
8907 | if (!Event.domLoaded) {\r |
8908 | Event.add(document, 'init', function() {\r |
8909 | t.render();\r |
8910 | });\r |
8911 | return;\r |
8912 | }\r |
8913 | \r |
8914 | // Force strict loading mode if render us called by user and not internally\r |
8915 | if (!nst) {\r |
8916 | s.strict_loading_mode = 1;\r |
8917 | tinyMCE.settings = s;\r |
8918 | }\r |
8919 | \r |
8920 | // Element not found, then skip initialization\r |
8921 | if (!t.getElement())\r |
8922 | return;\r |
8923 | \r |
8924 | if (s.strict_loading_mode) {\r |
8925 | sl.settings.strict_mode = s.strict_loading_mode;\r |
8926 | tinymce.DOM.settings.strict = 1;\r |
8927 | }\r |
8928 | \r |
8929 | // Add hidden input for non input elements inside form elements\r |
8930 | if (!/TEXTAREA|INPUT/i.test(t.getElement().nodeName) && s.hidden_input && DOM.getParent(id, 'form'))\r |
8931 | DOM.insertAfter(DOM.create('input', {type : 'hidden', name : id}), id);\r |
8932 | \r |
8933 | if (tinymce.WindowManager)\r |
8934 | t.windowManager = new tinymce.WindowManager(t);\r |
8935 | \r |
8936 | if (s.encoding == 'xml') {\r |
8937 | t.onGetContent.add(function(ed, o) {\r |
8938 | if (o.save)\r |
8939 | o.content = DOM.encode(o.content);\r |
8940 | });\r |
8941 | }\r |
8942 | \r |
8943 | if (s.add_form_submit_trigger) {\r |
8944 | t.onSubmit.addToTop(function() {\r |
8945 | if (t.initialized) {\r |
8946 | t.save();\r |
8947 | t.isNotDirty = 1;\r |
8948 | }\r |
8949 | });\r |
8950 | }\r |
8951 | \r |
8952 | if (s.add_unload_trigger) {\r |
8953 | t._beforeUnload = tinyMCE.onBeforeUnload.add(function() {\r |
8954 | if (t.initialized && !t.destroyed && !t.isHidden())\r |
8955 | t.save({format : 'raw', no_events : true});\r |
8956 | });\r |
8957 | }\r |
8958 | \r |
8959 | tinymce.addUnload(t.destroy, t);\r |
8960 | \r |
8961 | if (s.submit_patch) {\r |
8962 | t.onBeforeRenderUI.add(function() {\r |
8963 | var n = t.getElement().form;\r |
8964 | \r |
8965 | if (!n)\r |
8966 | return;\r |
8967 | \r |
8968 | // Already patched\r |
8969 | if (n._mceOldSubmit)\r |
8970 | return;\r |
8971 | \r |
8972 | // Check page uses id="submit" or name="submit" for it's submit button\r |
8973 | if (!n.submit.nodeType && !n.submit.length) {\r |
8974 | t.formElement = n;\r |
8975 | n._mceOldSubmit = n.submit;\r |
8976 | n.submit = function() {\r |
8977 | // Save all instances\r |
8978 | EditorManager.triggerSave();\r |
8979 | t.isNotDirty = 1;\r |
8980 | \r |
8981 | return t.formElement._mceOldSubmit(t.formElement);\r |
8982 | };\r |
8983 | }\r |
8984 | \r |
8985 | n = null;\r |
8986 | });\r |
8987 | }\r |
8988 | \r |
8989 | // Load scripts\r |
8990 | function loadScripts() {\r |
8991 | if (s.language)\r |
8992 | sl.add(tinymce.baseURL + '/langs/' + s.language + '.js');\r |
8993 | \r |
8994 | if (s.theme && s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme])\r |
8995 | ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js');\r |
8996 | \r |
8997 | each(explode(s.plugins), function(p) {\r |
8998 | if (p && p.charAt(0) != '-' && !PluginManager.urls[p]) {\r |
8999 | // Skip safari plugin for other browsers\r |
9000 | if (!isWebKit && p == 'safari')\r |
9001 | return;\r |
9002 | \r |
9003 | PluginManager.load(p, 'plugins/' + p + '/editor_plugin' + tinymce.suffix + '.js');\r |
9004 | }\r |
9005 | });\r |
9006 | \r |
9007 | // Init when que is loaded\r |
9008 | sl.loadQueue(function() {\r |
9009 | if (!t.removed)\r |
9010 | t.init();\r |
9011 | });\r |
9012 | };\r |
9013 | \r |
9014 | loadScripts();\r |
9015 | },\r |
9016 | \r |
9017 | init : function() {\r |
9018 | var n, t = this, s = t.settings, w, h, e = t.getElement(), o, ti, u, bi, bc, re;\r |
9019 | \r |
9020 | EditorManager.add(t);\r |
9021 | \r |
9022 | if (s.theme) {\r |
9023 | s.theme = s.theme.replace(/-/, '');\r |
9024 | o = ThemeManager.get(s.theme);\r |
9025 | t.theme = new o();\r |
9026 | \r |
9027 | if (t.theme.init && s.init_theme)\r |
9028 | t.theme.init(t, ThemeManager.urls[s.theme] || tinymce.documentBaseURL.replace(/\/$/, ''));\r |
9029 | }\r |
9030 | \r |
9031 | // Create all plugins\r |
9032 | each(explode(s.plugins.replace(/\-/g, '')), function(p) {\r |
9033 | var c = PluginManager.get(p), u = PluginManager.urls[p] || tinymce.documentBaseURL.replace(/\/$/, ''), po;\r |
9034 | \r |
9035 | if (c) {\r |
9036 | po = new c(t, u);\r |
9037 | \r |
9038 | t.plugins[p] = po;\r |
9039 | \r |
9040 | if (po.init)\r |
9041 | po.init(t, u);\r |
9042 | }\r |
9043 | });\r |
9044 | \r |
9045 | // Setup popup CSS path(s)\r |
9046 | if (s.popup_css !== false) {\r |
9047 | if (s.popup_css)\r |
9048 | s.popup_css = t.documentBaseURI.toAbsolute(s.popup_css);\r |
9049 | else\r |
9050 | s.popup_css = t.baseURI.toAbsolute("themes/" + s.theme + "/skins/" + s.skin + "/dialog.css");\r |
9051 | }\r |
9052 | \r |
9053 | if (s.popup_css_add)\r |
9054 | s.popup_css += ',' + t.documentBaseURI.toAbsolute(s.popup_css_add);\r |
9055 | \r |
9056 | t.controlManager = new tinymce.ControlManager(t);\r |
9057 | \r |
9058 | t.undoManager = new tinymce.UndoManager(t);\r |
9059 | \r |
9060 | // Pass through\r |
9061 | t.undoManager.onAdd.add(function(um, l) {\r |
9062 | if (!l.initial)\r |
9063 | return t.onChange.dispatch(t, l, um);\r |
9064 | });\r |
9065 | \r |
9066 | t.undoManager.onUndo.add(function(um, l) {\r |
9067 | return t.onUndo.dispatch(t, l, um);\r |
9068 | });\r |
9069 | \r |
9070 | t.undoManager.onRedo.add(function(um, l) {\r |
9071 | return t.onRedo.dispatch(t, l, um);\r |
9072 | });\r |
9073 | \r |
9074 | if (s.custom_undo_redo) {\r |
9075 | t.onExecCommand.add(function(ed, cmd, ui, val, a) {\r |
9076 | if (cmd != 'Undo' && cmd != 'Redo' && cmd != 'mceRepaint' && (!a || !a.skip_undo))\r |
9077 | t.undoManager.add();\r |
9078 | });\r |
9079 | }\r |
9080 | \r |
9081 | t.onExecCommand.add(function(ed, c) {\r |
9082 | // Don't refresh the select lists until caret move\r |
9083 | if (!/^(FontName|FontSize)$/.test(c))\r |
9084 | t.nodeChanged();\r |
9085 | });\r |
9086 | \r |
9087 | // Remove ghost selections on images and tables in Gecko\r |
9088 | if (isGecko) {\r |
9089 | function repaint(a, o) {\r |
9090 | if (!o || !o.initial)\r |
9091 | t.execCommand('mceRepaint');\r |
9092 | };\r |
9093 | \r |
9094 | t.onUndo.add(repaint);\r |
9095 | t.onRedo.add(repaint);\r |
9096 | t.onSetContent.add(repaint);\r |
9097 | }\r |
9098 | \r |
9099 | // Enables users to override the control factory\r |
9100 | t.onBeforeRenderUI.dispatch(t, t.controlManager);\r |
9101 | \r |
9102 | // Measure box\r |
9103 | if (s.render_ui) {\r |
9104 | w = s.width || e.style.width || e.offsetWidth;\r |
9105 | h = s.height || e.style.height || e.offsetHeight;\r |
9106 | t.orgDisplay = e.style.display;\r |
9107 | re = /^[0-9\.]+(|px)$/i;\r |
9108 | \r |
9109 | if (re.test('' + w))\r |
9110 | w = Math.max(parseInt(w) + (o.deltaWidth || 0), 100);\r |
9111 | \r |
9112 | if (re.test('' + h))\r |
9113 | h = Math.max(parseInt(h) + (o.deltaHeight || 0), 100);\r |
9114 | \r |
9115 | // Render UI\r |
9116 | o = t.theme.renderUI({\r |
9117 | targetNode : e,\r |
9118 | width : w,\r |
9119 | height : h,\r |
9120 | deltaWidth : s.delta_width,\r |
9121 | deltaHeight : s.delta_height\r |
9122 | });\r |
9123 | \r |
9124 | t.editorContainer = o.editorContainer;\r |
9125 | }\r |
9126 | \r |
9127 | // User specified a document.domain value\r |
9128 | if (document.domain && location.hostname != document.domain)\r |
9129 | tinymce.relaxedDomain = document.domain;\r |
9130 | \r |
9131 | // Resize editor\r |
9132 | if (s.theme_advanced_toolbar_location != 'external') {\r |
9133 | DOM.setStyles(o.sizeContainer || o.editorContainer, {\r |
9134 | width : w,\r |
9135 | height : h\r |
9136 | });\r |
9137 | }\r |
9138 | \r |
9139 | h = (o.iframeHeight || h) + (typeof(h) == 'number' ? (o.deltaHeight || 0) : '');\r |
9140 | if (h < 100)\r |
9141 | h = 100;\r |
9142 | \r |
9143 | t.iframeHTML = s.doctype + '<html><head xmlns="http://www.w3.org/1999/xhtml">';\r |
9144 | \r |
9145 | // We only need to override paths if we have to\r |
9146 | // IE has a bug where it remove site absolute urls to relative ones if this is specified\r |
9147 | //if (s.document_base_url != tinymce.documentBaseURL)\r |
9148 | t.iframeHTML += '<base href="' + t.documentBaseURI.getURI() + '" />';\r |
9149 | \r |
9150 | t.iframeHTML += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';\r |
9151 | \r |
9152 | if (tinymce.relaxedDomain)\r |
9153 | t.iframeHTML += '<script type="text/javascript">document.domain = "' + tinymce.relaxedDomain + '";</script>';\r |
9154 | \r |
9155 | bi = s.body_id || 'tinymce';\r |
9156 | if (bi.indexOf('=') != -1) {\r |
9157 | bi = t.getParam('body_id', '', 'hash');\r |
9158 | bi = bi[t.id] || bi;\r |
9159 | }\r |
9160 | \r |
9161 | bc = s.body_class || '';\r |
9162 | if (bc.indexOf('=') != -1) {\r |
9163 | bc = t.getParam('body_class', '', 'hash');\r |
9164 | bc = bc[t.id] || '';\r |
9165 | }\r |
9166 | \r |
9167 | t.iframeHTML += '</head><body id="' + bi + '" class="mceContentBody ' + bc + '"></body></html>';\r |
9168 | \r |
9169 | // Domain relaxing enabled, then set document domain\r |
9170 | if (tinymce.relaxedDomain) {\r |
9171 | // We need to write the contents here in IE since multiple writes messes up refresh button and back button\r |
9172 | if (isIE || (tinymce.isOpera && parseFloat(opera.version()) >= 9.5))\r |
9173 | u = 'javascript:(function(){document.open();document.domain="' + document.domain + '";var ed = window.parent.tinyMCE.get("' + t.id + '");document.write(ed.iframeHTML);document.close();ed.setupIframe();})()';\r |
9174 | else if (tinymce.isOpera)\r |
9175 | u = 'javascript:(function(){document.open();document.domain="' + document.domain + '";document.close();ed.setupIframe();})()'; \r |
9176 | }\r |
9177 | \r |
9178 | // Create iframe\r |
9179 | n = DOM.add(o.iframeContainer, 'iframe', {\r |
9180 | id : t.id + "_ifr",\r |
9181 | src : u || 'javascript:""', // Workaround for HTTPS warning in IE6/7\r |
9182 | frameBorder : '0',\r |
9183 | style : {\r |
9184 | width : '100%',\r |
9185 | height : h\r |
9186 | }\r |
9187 | });\r |
9188 | \r |
9189 | t.contentAreaContainer = o.iframeContainer;\r |
9190 | DOM.get(o.editorContainer).style.display = t.orgDisplay;\r |
9191 | DOM.get(t.id).style.display = 'none';\r |
9192 | \r |
9193 | if (!isIE || !tinymce.relaxedDomain)\r |
9194 | t.setupIframe();\r |
9195 | \r |
9196 | e = n = o = null; // Cleanup\r |
9197 | },\r |
9198 | \r |
9199 | setupIframe : function() {\r |
9200 | var t = this, s = t.settings, e = DOM.get(t.id), d = t.getDoc(), h, b;\r |
9201 | \r |
9202 | // Setup iframe body\r |
9203 | if (!isIE || !tinymce.relaxedDomain) {\r |
9204 | d.open();\r |
9205 | d.write(t.iframeHTML);\r |
9206 | d.close();\r |
9207 | }\r |
9208 | \r |
9209 | // Design mode needs to be added here Ctrl+A will fail otherwise\r |
9210 | if (!isIE) {\r |
9211 | try {\r |
9212 | if (!s.readonly)\r |
9213 | d.designMode = 'On';\r |
9214 | } catch (ex) {\r |
9215 | // Will fail on Gecko if the editor is placed in an hidden container element\r |
9216 | // The design mode will be set ones the editor is focused\r |
9217 | }\r |
9218 | }\r |
9219 | \r |
9220 | // IE needs to use contentEditable or it will display non secure items for HTTPS\r |
9221 | if (isIE) {\r |
9222 | // It will not steal focus if we hide it while setting contentEditable\r |
9223 | b = t.getBody();\r |
9224 | DOM.hide(b);\r |
9225 | \r |
9226 | if (!s.readonly)\r |
9227 | b.contentEditable = true;\r |
9228 | \r |
9229 | DOM.show(b);\r |
9230 | }\r |
9231 | \r |
9232 | t.dom = new tinymce.dom.DOMUtils(t.getDoc(), {\r |
9233 | keep_values : true,\r |
9234 | url_converter : t.convertURL,\r |
9235 | url_converter_scope : t,\r |
9236 | hex_colors : s.force_hex_style_colors,\r |
9237 | class_filter : s.class_filter,\r |
9238 | update_styles : 1,\r |
9239 | fix_ie_paragraphs : 1\r |
9240 | });\r |
9241 | \r |
9242 | t.serializer = new tinymce.dom.Serializer(extend(s, {\r |
9243 | valid_elements : s.verify_html === false ? '*[*]' : s.valid_elements,\r |
9244 | dom : t.dom\r |
9245 | }));\r |
9246 | \r |
9247 | t.selection = new tinymce.dom.Selection(t.dom, t.getWin(), t.serializer);\r |
9248 | \r |
9249 | t.forceBlocks = new tinymce.ForceBlocks(t, {\r |
9250 | forced_root_block : s.forced_root_block\r |
9251 | });\r |
9252 | t.editorCommands = new tinymce.EditorCommands(t);\r |
9253 | \r |
9254 | // Pass through\r |
9255 | t.serializer.onPreProcess.add(function(se, o) {\r |
9256 | return t.onPreProcess.dispatch(t, o, se);\r |
9257 | });\r |
9258 | \r |
9259 | t.serializer.onPostProcess.add(function(se, o) {\r |
9260 | return t.onPostProcess.dispatch(t, o, se);\r |
9261 | });\r |
9262 | \r |
9263 | t.onPreInit.dispatch(t);\r |
9264 | \r |
9265 | if (!s.gecko_spellcheck)\r |
9266 | t.getBody().spellcheck = 0;\r |
9267 | \r |
9268 | if (!s.readonly)\r |
9269 | t._addEvents();\r |
9270 | \r |
9271 | t.controlManager.onPostRender.dispatch(t, t.controlManager);\r |
9272 | t.onPostRender.dispatch(t);\r |
9273 | \r |
9274 | if (s.directionality)\r |
9275 | t.getBody().dir = s.directionality;\r |
9276 | \r |
9277 | if (s.nowrap)\r |
9278 | t.getBody().style.whiteSpace = "nowrap";\r |
9279 | \r |
9280 | if (s.custom_elements) {\r |
9281 | function handleCustom(ed, o) {\r |
9282 | each(explode(s.custom_elements), function(v) {\r |
9283 | var n;\r |
9284 | \r |
9285 | if (v.indexOf('~') === 0) {\r |
9286 | v = v.substring(1);\r |
9287 | n = 'span';\r |
9288 | } else\r |
9289 | n = 'div';\r |
9290 | \r |
9291 | o.content = o.content.replace(new RegExp('<(' + v + ')([^>]*)>', 'g'), '<' + n + ' mce_name="$1"$2>');\r |
9292 | o.content = o.content.replace(new RegExp('</(' + v + ')>', 'g'), '</' + n + '>');\r |
9293 | });\r |
9294 | };\r |
9295 | \r |
9296 | t.onBeforeSetContent.add(handleCustom);\r |
9297 | t.onPostProcess.add(function(ed, o) {\r |
9298 | if (o.set)\r |
9299 | handleCustom(ed, o);\r |
9300 | });\r |
9301 | }\r |
9302 | \r |
9303 | if (s.handle_node_change_callback) {\r |
9304 | t.onNodeChange.add(function(ed, cm, n) {\r |
9305 | t.execCallback('handle_node_change_callback', t.id, n, -1, -1, true, t.selection.isCollapsed());\r |
9306 | });\r |
9307 | }\r |
9308 | \r |
9309 | if (s.save_callback) {\r |
9310 | t.onSaveContent.add(function(ed, o) {\r |
9311 | var h = t.execCallback('save_callback', t.id, o.content, t.getBody());\r |
9312 | \r |
9313 | if (h)\r |
9314 | o.content = h;\r |
9315 | });\r |
9316 | }\r |
9317 | \r |
9318 | if (s.onchange_callback) {\r |
9319 | t.onChange.add(function(ed, l) {\r |
9320 | t.execCallback('onchange_callback', t, l);\r |
9321 | });\r |
9322 | }\r |
9323 | \r |
9324 | if (s.convert_newlines_to_brs) {\r |
9325 | t.onBeforeSetContent.add(function(ed, o) {\r |
9326 | if (o.initial)\r |
9327 | o.content = o.content.replace(/\r?\n/g, '<br />');\r |
9328 | });\r |
9329 | }\r |
9330 | \r |
9331 | if (s.fix_nesting && isIE) {\r |
9332 | t.onBeforeSetContent.add(function(ed, o) {\r |
9333 | o.content = t._fixNesting(o.content);\r |
9334 | });\r |
9335 | }\r |
9336 | \r |
9337 | if (s.preformatted) {\r |
9338 | t.onPostProcess.add(function(ed, o) {\r |
9339 | o.content = o.content.replace(/^\s*<pre.*?>/, '');\r |
9340 | o.content = o.content.replace(/<\/pre>\s*$/, '');\r |
9341 | \r |
9342 | if (o.set)\r |
9343 | o.content = '<pre class="mceItemHidden">' + o.content + '</pre>';\r |
9344 | });\r |
9345 | }\r |
9346 | \r |
9347 | if (s.verify_css_classes) {\r |
9348 | t.serializer.attribValueFilter = function(n, v) {\r |
9349 | var s, cl;\r |
9350 | \r |
9351 | if (n == 'class') {\r |
9352 | // Build regexp for classes\r |
9353 | if (!t.classesRE) {\r |
9354 | cl = t.dom.getClasses();\r |
9355 | \r |
9356 | if (cl.length > 0) {\r |
9357 | s = '';\r |
9358 | \r |
9359 | each (cl, function(o) {\r |
9360 | s += (s ? '|' : '') + o['class'];\r |
9361 | });\r |
9362 | \r |
9363 | t.classesRE = new RegExp('(' + s + ')', 'gi');\r |
9364 | }\r |
9365 | }\r |
9366 | \r |
9367 | return !t.classesRE || /(\bmceItem\w+\b|\bmceTemp\w+\b)/g.test(v) || t.classesRE.test(v) ? v : '';\r |
9368 | }\r |
9369 | \r |
9370 | return v;\r |
9371 | };\r |
9372 | }\r |
9373 | \r |
9374 | if (s.convert_fonts_to_spans)\r |
9375 | t._convertFonts();\r |
9376 | \r |
9377 | if (s.inline_styles)\r |
9378 | t._convertInlineElements();\r |
9379 | \r |
9380 | if (s.cleanup_callback) {\r |
9381 | t.onBeforeSetContent.add(function(ed, o) {\r |
9382 | o.content = t.execCallback('cleanup_callback', 'insert_to_editor', o.content, o);\r |
9383 | });\r |
9384 | \r |
9385 | t.onPreProcess.add(function(ed, o) {\r |
9386 | if (o.set)\r |
9387 | t.execCallback('cleanup_callback', 'insert_to_editor_dom', o.node, o);\r |
9388 | \r |
9389 | if (o.get)\r |
9390 | t.execCallback('cleanup_callback', 'get_from_editor_dom', o.node, o);\r |
9391 | });\r |
9392 | \r |
9393 | t.onPostProcess.add(function(ed, o) {\r |
9394 | if (o.set)\r |
9395 | o.content = t.execCallback('cleanup_callback', 'insert_to_editor', o.content, o);\r |
9396 | \r |
9397 | if (o.get) \r |
9398 | o.content = t.execCallback('cleanup_callback', 'get_from_editor', o.content, o);\r |
9399 | });\r |
9400 | }\r |
9401 | \r |
9402 | if (s.save_callback) {\r |
9403 | t.onGetContent.add(function(ed, o) {\r |
9404 | if (o.save)\r |
9405 | o.content = t.execCallback('save_callback', t.id, o.content, t.getBody());\r |
9406 | });\r |
9407 | }\r |
9408 | \r |
9409 | if (s.handle_event_callback) {\r |
9410 | t.onEvent.add(function(ed, e, o) {\r |
9411 | if (t.execCallback('handle_event_callback', e, ed, o) === false)\r |
9412 | Event.cancel(e);\r |
9413 | });\r |
9414 | }\r |
9415 | \r |
9416 | // Add visual aids when new contents is added\r |
9417 | t.onSetContent.add(function() {\r |
9418 | t.addVisual(t.getBody());\r |
9419 | });\r |
9420 | \r |
9421 | // Remove empty contents\r |
9422 | if (s.padd_empty_editor) {\r |
9423 | t.onPostProcess.add(function(ed, o) {\r |
9424 | o.content = o.content.replace(/^(<p[^>]*>( | |\s|\u00a0|)<\/p>[\r\n]*|<br \/>[\r\n]*)$/, '');\r |
9425 | });\r |
9426 | }\r |
9427 | \r |
9428 | if (isGecko) {\r |
9429 | // Fix gecko link bug, when a link is placed at the end of block elements there is\r |
9430 | // no way to move the caret behind the link. This fix adds a bogus br element after the link\r |
9431 | function fixLinks(ed, o) {\r |
9432 | each(ed.dom.select('a'), function(n) {\r |
9433 | var pn = n.parentNode;\r |
9434 | \r |
9435 | if (ed.dom.isBlock(pn) && pn.lastChild === n)\r |
9436 | ed.dom.add(pn, 'br', {'mce_bogus' : 1});\r |
9437 | });\r |
9438 | };\r |
9439 | \r |
9440 | t.onExecCommand.add(function(ed, cmd) {\r |
9441 | if (cmd === 'CreateLink')\r |
9442 | fixLinks(ed);\r |
9443 | });\r |
9444 | \r |
9445 | t.onSetContent.add(t.selection.onSetContent.add(fixLinks));\r |
9446 | \r |
9447 | if (!s.readonly) {\r |
9448 | try {\r |
9449 | // Design mode must be set here once again to fix a bug where\r |
9450 | // Ctrl+A/Delete/Backspace didn't work if the editor was added using mceAddControl then removed then added again\r |
9451 | d.designMode = 'Off';\r |
9452 | d.designMode = 'On';\r |
9453 | } catch (ex) {\r |
9454 | // Will fail on Gecko if the editor is placed in an hidden container element\r |
9455 | // The design mode will be set ones the editor is focused\r |
9456 | }\r |
9457 | }\r |
9458 | }\r |
9459 | \r |
9460 | // A small timeout was needed since firefox will remove. Bug: #1838304\r |
9461 | setTimeout(function () {\r |
9462 | if (t.removed)\r |
9463 | return;\r |
9464 | \r |
9465 | t.load({initial : true, format : (s.cleanup_on_startup ? 'html' : 'raw')});\r |
9466 | t.startContent = t.getContent({format : 'raw'});\r |
9467 | t.undoManager.add({initial : true});\r |
9468 | t.initialized = true;\r |
9469 | \r |
9470 | t.onInit.dispatch(t);\r |
9471 | t.execCallback('setupcontent_callback', t.id, t.getBody(), t.getDoc());\r |
9472 | t.execCallback('init_instance_callback', t);\r |
9473 | t.focus(true);\r |
9474 | t.nodeChanged({initial : 1});\r |
9475 | \r |
9476 | // Load specified content CSS last\r |
9477 | if (s.content_css) {\r |
9478 | tinymce.each(explode(s.content_css), function(u) {\r |
9479 | t.dom.loadCSS(t.documentBaseURI.toAbsolute(u));\r |
9480 | });\r |
9481 | }\r |
9482 | \r |
9483 | // Handle auto focus\r |
9484 | if (s.auto_focus) {\r |
9485 | setTimeout(function () {\r |
9486 | var ed = EditorManager.get(s.auto_focus);\r |
9487 | \r |
9488 | ed.selection.select(ed.getBody(), 1);\r |
9489 | ed.selection.collapse(1);\r |
9490 | ed.getWin().focus();\r |
9491 | }, 100);\r |
9492 | }\r |
9493 | }, 1);\r |
9494 | \r |
9495 | // Changed behavior of the blur and focus event so it matches the api docs :XXX doesn't fully work yet\r |
9496 | Event.add(!isGecko ? t.getWin() : t.getDoc(), 'blur', function(e) {\r |
9497 | t.onDeactivate.dispatch(t, e);\r |
9498 | });\r |
9499 | Event.add(!isGecko ? t.getWin() : t.getDoc(), 'focus', function(e) {\r |
9500 | t.onActivate.dispatch(t, e);\r |
9501 | });\r |
9502 | \r |
9503 | e = null;\r |
9504 | },\r |
9505 | \r |
9506 | focus : function(sf) {\r |
9507 | var oed, t = this, ce = t.settings.content_editable;\r |
9508 | \r |
9509 | if (!sf) {\r |
9510 | // Is not content editable or the selection is outside the area in IE\r |
9511 | // the IE statement is needed to avoid bluring if element selections inside layers since\r |
9512 | // the layer is like it's own document in IE\r |
9513 | if (!ce && (!isIE || t.selection.getNode().ownerDocument != t.getDoc()))\r |
9514 | t.getWin().focus();\r |
9515 | \r |
9516 | }\r |
9517 | \r |
9518 | // Changed behavior of the blur and focus event so it matches the api docs\r |
9519 | /*\r |
9520 | if (EditorManager.activeEditor != t) {\r |
9521 | if ((oed = EditorManager.activeEditor) != null)\r |
9522 | oed.onDeactivate.dispatch(oed, t);\r |
9523 | \r |
9524 | t.onActivate.dispatch(t, oed);\r |
9525 | }\r |
9526 | */\r |
9527 | \r |
9528 | EditorManager._setActive(t);\r |
9529 | },\r |
9530 | \r |
9531 | execCallback : function(n) {\r |
9532 | var t = this, f = t.settings[n], s;\r |
9533 | \r |
9534 | if (!f)\r |
9535 | return;\r |
9536 | \r |
9537 | // Look through lookup\r |
9538 | if (t.callbackLookup && (s = t.callbackLookup[n])) {\r |
9539 | f = s.func;\r |
9540 | s = s.scope;\r |
9541 | }\r |
9542 | \r |
9543 | if (is(f, 'string')) {\r |
9544 | s = f.replace(/\.\w+$/, '');\r |
9545 | s = s ? tinymce.resolve(s) : 0;\r |
9546 | f = tinymce.resolve(f);\r |
9547 | t.callbackLookup = t.callbackLookup || {};\r |
9548 | t.callbackLookup[n] = {func : f, scope : s};\r |
9549 | }\r |
9550 | \r |
9551 | return f.apply(s || t, Array.prototype.slice.call(arguments, 1));\r |
9552 | },\r |
9553 | \r |
9554 | translate : function(s) {\r |
9555 | var c = this.settings.language || 'en', i18n = EditorManager.i18n;\r |
9556 | \r |
9557 | if (!s)\r |
9558 | return '';\r |
9559 | \r |
9560 | return i18n[c + '.' + s] || s.replace(/{\#([^}]+)\}/g, function(a, b) {\r |
9561 | return i18n[c + '.' + b] || '{#' + b + '}';\r |
9562 | });\r |
9563 | },\r |
9564 | \r |
9565 | getLang : function(n, dv) {\r |
9566 | return EditorManager.i18n[(this.settings.language || 'en') + '.' + n] || (is(dv) ? dv : '{#' + n + '}');\r |
9567 | },\r |
9568 | \r |
9569 | getParam : function(n, dv, ty) {\r |
9570 | var tr = tinymce.trim, v = is(this.settings[n]) ? this.settings[n] : dv, o;\r |
9571 | \r |
9572 | if (ty === 'hash') {\r |
9573 | o = {};\r |
9574 | \r |
9575 | if (is(v, 'string')) {\r |
9576 | each(v.indexOf('=') > 0 ? v.split(/[;,](?![^=;,]*(?:[;,]|$))/) : v.split(','), function(v) {\r |
9577 | v = v.split('=');\r |
9578 | \r |
9579 | if (v.length > 1)\r |
9580 | o[tr(v[0])] = tr(v[1]);\r |
9581 | else\r |
9582 | o[tr(v[0])] = tr(v);\r |
9583 | });\r |
9584 | } else\r |
9585 | o = v;\r |
9586 | \r |
9587 | return o;\r |
9588 | }\r |
9589 | \r |
9590 | return v;\r |
9591 | },\r |
9592 | \r |
9593 | nodeChanged : function(o) {\r |
9594 | var t = this, s = t.selection, n = s.getNode() || t.getBody();\r |
9595 | \r |
9596 | // Fix for bug #1896577 it seems that this can not be fired while the editor is loading\r |
9597 | if (t.initialized) {\r |
9598 | t.onNodeChange.dispatch(\r |
9599 | t,\r |
9600 | o ? o.controlManager || t.controlManager : t.controlManager,\r |
9601 | isIE && n.ownerDocument != t.getDoc() ? t.getBody() : n, // Fix for IE initial state\r |
9602 | s.isCollapsed(),\r |
9603 | o\r |
9604 | );\r |
9605 | }\r |
9606 | },\r |
9607 | \r |
9608 | addButton : function(n, s) {\r |
9609 | var t = this;\r |
9610 | \r |
9611 | t.buttons = t.buttons || {};\r |
9612 | t.buttons[n] = s;\r |
9613 | },\r |
9614 | \r |
9615 | addCommand : function(n, f, s) {\r |
9616 | this.execCommands[n] = {func : f, scope : s || this};\r |
9617 | },\r |
9618 | \r |
9619 | addQueryStateHandler : function(n, f, s) {\r |
9620 | this.queryStateCommands[n] = {func : f, scope : s || this};\r |
9621 | },\r |
9622 | \r |
9623 | addQueryValueHandler : function(n, f, s) {\r |
9624 | this.queryValueCommands[n] = {func : f, scope : s || this};\r |
9625 | },\r |
9626 | \r |
9627 | addShortcut : function(pa, desc, cmd_func, sc) {\r |
9628 | var t = this, c;\r |
9629 | \r |
9630 | if (!t.settings.custom_shortcuts)\r |
9631 | return false;\r |
9632 | \r |
9633 | t.shortcuts = t.shortcuts || {};\r |
9634 | \r |
9635 | if (is(cmd_func, 'string')) {\r |
9636 | c = cmd_func;\r |
9637 | \r |
9638 | cmd_func = function() {\r |
9639 | t.execCommand(c, false, null);\r |
9640 | };\r |
9641 | }\r |
9642 | \r |
9643 | if (is(cmd_func, 'object')) {\r |
9644 | c = cmd_func;\r |
9645 | \r |
9646 | cmd_func = function() {\r |
9647 | t.execCommand(c[0], c[1], c[2]);\r |
9648 | };\r |
9649 | }\r |
9650 | \r |
9651 | each(explode(pa), function(pa) {\r |
9652 | var o = {\r |
9653 | func : cmd_func,\r |
9654 | scope : sc || this,\r |
9655 | desc : desc,\r |
9656 | alt : false,\r |
9657 | ctrl : false,\r |
9658 | shift : false\r |
9659 | };\r |
9660 | \r |
9661 | each(explode(pa, '+'), function(v) {\r |
9662 | switch (v) {\r |
9663 | case 'alt':\r |
9664 | case 'ctrl':\r |
9665 | case 'shift':\r |
9666 | o[v] = true;\r |
9667 | break;\r |
9668 | \r |
9669 | default:\r |
9670 | o.charCode = v.charCodeAt(0);\r |
9671 | o.keyCode = v.toUpperCase().charCodeAt(0);\r |
9672 | }\r |
9673 | });\r |
9674 | \r |
9675 | t.shortcuts[(o.ctrl ? 'ctrl' : '') + ',' + (o.alt ? 'alt' : '') + ',' + (o.shift ? 'shift' : '') + ',' + o.keyCode] = o;\r |
9676 | });\r |
9677 | \r |
9678 | return true;\r |
9679 | },\r |
9680 | \r |
9681 | execCommand : function(cmd, ui, val, a) {\r |
9682 | var t = this, s = 0, o, st;\r |
9683 | \r |
9684 | if (!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(cmd) && (!a || !a.skip_focus))\r |
9685 | t.focus();\r |
9686 | \r |
9687 | o = {};\r |
9688 | t.onBeforeExecCommand.dispatch(t, cmd, ui, val, o);\r |
9689 | if (o.terminate)\r |
9690 | return false;\r |
9691 | \r |
9692 | // Command callback\r |
9693 | if (t.execCallback('execcommand_callback', t.id, t.selection.getNode(), cmd, ui, val)) {\r |
9694 | t.onExecCommand.dispatch(t, cmd, ui, val, a);\r |
9695 | return true;\r |
9696 | }\r |
9697 | \r |
9698 | // Registred commands\r |
9699 | if (o = t.execCommands[cmd]) {\r |
9700 | st = o.func.call(o.scope, ui, val);\r |
9701 | \r |
9702 | // Fall through on true\r |
9703 | if (st !== true) {\r |
9704 | t.onExecCommand.dispatch(t, cmd, ui, val, a);\r |
9705 | return st;\r |
9706 | }\r |
9707 | }\r |
9708 | \r |
9709 | // Plugin commands\r |
9710 | each(t.plugins, function(p) {\r |
9711 | if (p.execCommand && p.execCommand(cmd, ui, val)) {\r |
9712 | t.onExecCommand.dispatch(t, cmd, ui, val, a);\r |
9713 | s = 1;\r |
9714 | return false;\r |
9715 | }\r |
9716 | });\r |
9717 | \r |
9718 | if (s)\r |
9719 | return true;\r |
9720 | \r |
9721 | // Theme commands\r |
9722 | if (t.theme && t.theme.execCommand && t.theme.execCommand(cmd, ui, val)) {\r |
9723 | t.onExecCommand.dispatch(t, cmd, ui, val, a);\r |
9724 | return true;\r |
9725 | }\r |
9726 | \r |
9727 | // Execute global commands\r |
9728 | if (tinymce.GlobalCommands.execCommand(t, cmd, ui, val)) {\r |
9729 | t.onExecCommand.dispatch(t, cmd, ui, val, a);\r |
9730 | return true;\r |
9731 | }\r |
9732 | \r |
9733 | // Editor commands\r |
9734 | if (t.editorCommands.execCommand(cmd, ui, val)) {\r |
9735 | t.onExecCommand.dispatch(t, cmd, ui, val, a);\r |
9736 | return true;\r |
9737 | }\r |
9738 | \r |
9739 | // Browser commands\r |
9740 | t.getDoc().execCommand(cmd, ui, val);\r |
9741 | t.onExecCommand.dispatch(t, cmd, ui, val, a);\r |
9742 | },\r |
9743 | \r |
9744 | queryCommandState : function(c) {\r |
9745 | var t = this, o, s;\r |
9746 | \r |
9747 | // Is hidden then return undefined\r |
9748 | if (t._isHidden())\r |
9749 | return;\r |
9750 | \r |
9751 | // Registred commands\r |
9752 | if (o = t.queryStateCommands[c]) {\r |
9753 | s = o.func.call(o.scope);\r |
9754 | \r |
9755 | // Fall though on true\r |
9756 | if (s !== true)\r |
9757 | return s;\r |
9758 | }\r |
9759 | \r |
9760 | // Registred commands\r |
9761 | o = t.editorCommands.queryCommandState(c);\r |
9762 | if (o !== -1)\r |
9763 | return o;\r |
9764 | \r |
9765 | // Browser commands\r |
9766 | try {\r |
9767 | return this.getDoc().queryCommandState(c);\r |
9768 | } catch (ex) {\r |
9769 | // Fails sometimes see bug: 1896577\r |
9770 | }\r |
9771 | },\r |
9772 | \r |
9773 | queryCommandValue : function(c) {\r |
9774 | var t = this, o, s;\r |
9775 | \r |
9776 | // Is hidden then return undefined\r |
9777 | if (t._isHidden())\r |
9778 | return;\r |
9779 | \r |
9780 | // Registred commands\r |
9781 | if (o = t.queryValueCommands[c]) {\r |
9782 | s = o.func.call(o.scope);\r |
9783 | \r |
9784 | // Fall though on true\r |
9785 | if (s !== true)\r |
9786 | return s;\r |
9787 | }\r |
9788 | \r |
9789 | // Registred commands\r |
9790 | o = t.editorCommands.queryCommandValue(c);\r |
9791 | if (is(o))\r |
9792 | return o;\r |
9793 | \r |
9794 | // Browser commands\r |
9795 | try {\r |
9796 | return this.getDoc().queryCommandValue(c);\r |
9797 | } catch (ex) {\r |
9798 | // Fails sometimes see bug: 1896577\r |
9799 | }\r |
9800 | },\r |
9801 | \r |
9802 | show : function() {\r |
9803 | var t = this;\r |
9804 | \r |
9805 | DOM.show(t.getContainer());\r |
9806 | DOM.hide(t.id);\r |
9807 | t.load();\r |
9808 | },\r |
9809 | \r |
9810 | hide : function() {\r |
9811 | var t = this, d = t.getDoc();\r |
9812 | \r |
9813 | // Fixed bug where IE has a blinking cursor left from the editor\r |
9814 | if (isIE && d)\r |
9815 | d.execCommand('SelectAll');\r |
9816 | \r |
9817 | // We must save before we hide so Safari doesn't crash\r |
9818 | t.save();\r |
9819 | DOM.hide(t.getContainer());\r |
9820 | DOM.setStyle(t.id, 'display', t.orgDisplay);\r |
9821 | },\r |
9822 | \r |
9823 | isHidden : function() {\r |
9824 | return !DOM.isHidden(this.id);\r |
9825 | },\r |
9826 | \r |
9827 | setProgressState : function(b, ti, o) {\r |
9828 | this.onSetProgressState.dispatch(this, b, ti, o);\r |
9829 | \r |
9830 | return b;\r |
9831 | },\r |
9832 | \r |
9833 | load : function(o) {\r |
9834 | var t = this, e = t.getElement(), h;\r |
9835 | \r |
9836 | if (e) {\r |
9837 | o = o || {};\r |
9838 | o.load = true;\r |
9839 | \r |
9840 | // Double encode existing entities in the value\r |
9841 | h = t.setContent(is(e.value) ? e.value : e.innerHTML, o);\r |
9842 | o.element = e;\r |
9843 | \r |
9844 | if (!o.no_events)\r |
9845 | t.onLoadContent.dispatch(t, o);\r |
9846 | \r |
9847 | o.element = e = null;\r |
9848 | \r |
9849 | return h;\r |
9850 | }\r |
9851 | },\r |
9852 | \r |
9853 | save : function(o) {\r |
9854 | var t = this, e = t.getElement(), h, f;\r |
9855 | \r |
9856 | if (!e || !t.initialized)\r |
9857 | return;\r |
9858 | \r |
9859 | o = o || {};\r |
9860 | o.save = true;\r |
9861 | \r |
9862 | // Add undo level will trigger onchange event\r |
9863 | if (!o.no_events) {\r |
9864 | t.undoManager.typing = 0;\r |
9865 | t.undoManager.add();\r |
9866 | }\r |
9867 | \r |
9868 | o.element = e;\r |
9869 | h = o.content = t.getContent(o);\r |
9870 | \r |
9871 | if (!o.no_events)\r |
9872 | t.onSaveContent.dispatch(t, o);\r |
9873 | \r |
9874 | h = o.content;\r |
9875 | \r |
9876 | if (!/TEXTAREA|INPUT/i.test(e.nodeName)) {\r |
9877 | e.innerHTML = h;\r |
9878 | \r |
9879 | // Update hidden form element\r |
9880 | if (f = DOM.getParent(t.id, 'form')) {\r |
9881 | each(f.elements, function(e) {\r |
9882 | if (e.name == t.id) {\r |
9883 | e.value = h;\r |
9884 | return false;\r |
9885 | }\r |
9886 | });\r |
9887 | }\r |
9888 | } else\r |
9889 | e.value = h;\r |
9890 | \r |
9891 | o.element = e = null;\r |
9892 | \r |
9893 | return h;\r |
9894 | },\r |
9895 | \r |
9896 | setContent : function(h, o) {\r |
9897 | var t = this;\r |
9898 | \r |
9899 | o = o || {};\r |
9900 | o.format = o.format || 'html';\r |
9901 | o.set = true;\r |
9902 | o.content = h;\r |
9903 | \r |
9904 | if (!o.no_events)\r |
9905 | t.onBeforeSetContent.dispatch(t, o);\r |
9906 | \r |
9907 | // Padd empty content in Gecko and Safari. Commands will otherwise fail on the content\r |
9908 | // It will also be impossible to place the caret in the editor unless there is a BR element present\r |
9909 | if (!tinymce.isIE && (h.length === 0 || /^\s+$/.test(h))) {\r |
9910 | o.content = t.dom.setHTML(t.getBody(), '<br mce_bogus="1" />');\r |
9911 | o.format = 'raw';\r |
9912 | }\r |
9913 | \r |
9914 | o.content = t.dom.setHTML(t.getBody(), tinymce.trim(o.content));\r |
9915 | \r |
9916 | if (o.format != 'raw' && t.settings.cleanup) {\r |
9917 | o.getInner = true;\r |
9918 | o.content = t.dom.setHTML(t.getBody(), t.serializer.serialize(t.getBody(), o));\r |
9919 | }\r |
9920 | \r |
9921 | if (!o.no_events)\r |
9922 | t.onSetContent.dispatch(t, o);\r |
9923 | \r |
9924 | return o.content;\r |
9925 | },\r |
9926 | \r |
9927 | getContent : function(o) {\r |
9928 | var t = this, h;\r |
9929 | \r |
9930 | o = o || {};\r |
9931 | o.format = o.format || 'html';\r |
9932 | o.get = true;\r |
9933 | \r |
9934 | if (!o.no_events)\r |
9935 | t.onBeforeGetContent.dispatch(t, o);\r |
9936 | \r |
9937 | if (o.format != 'raw' && t.settings.cleanup) {\r |
9938 | o.getInner = true;\r |
9939 | h = t.serializer.serialize(t.getBody(), o);\r |
9940 | } else\r |
9941 | h = t.getBody().innerHTML;\r |
9942 | \r |
9943 | h = h.replace(/^\s*|\s*$/g, '');\r |
9944 | o.content = h;\r |
9945 | \r |
9946 | if (!o.no_events)\r |
9947 | t.onGetContent.dispatch(t, o);\r |
9948 | \r |
9949 | return o.content;\r |
9950 | },\r |
9951 | \r |
9952 | isDirty : function() {\r |
9953 | var t = this;\r |
9954 | \r |
9955 | return tinymce.trim(t.startContent) != tinymce.trim(t.getContent({format : 'raw', no_events : 1})) && !t.isNotDirty;\r |
9956 | },\r |
9957 | \r |
9958 | getContainer : function() {\r |
9959 | var t = this;\r |
9960 | \r |
9961 | if (!t.container)\r |
9962 | t.container = DOM.get(t.editorContainer || t.id + '_parent');\r |
9963 | \r |
9964 | return t.container;\r |
9965 | },\r |
9966 | \r |
9967 | getContentAreaContainer : function() {\r |
9968 | return this.contentAreaContainer;\r |
9969 | },\r |
9970 | \r |
9971 | getElement : function() {\r |
9972 | return DOM.get(this.settings.content_element || this.id);\r |
9973 | },\r |
9974 | \r |
9975 | getWin : function() {\r |
9976 | var t = this, e;\r |
9977 | \r |
9978 | if (!t.contentWindow) {\r |
9979 | e = DOM.get(t.id + "_ifr");\r |
9980 | \r |
9981 | if (e)\r |
9982 | t.contentWindow = e.contentWindow;\r |
9983 | }\r |
9984 | \r |
9985 | return t.contentWindow;\r |
9986 | },\r |
9987 | \r |
9988 | getDoc : function() {\r |
9989 | var t = this, w;\r |
9990 | \r |
9991 | if (!t.contentDocument) {\r |
9992 | w = t.getWin();\r |
9993 | \r |
9994 | if (w)\r |
9995 | t.contentDocument = w.document;\r |
9996 | }\r |
9997 | \r |
9998 | return t.contentDocument;\r |
9999 | },\r |
10000 | \r |
10001 | getBody : function() {\r |
10002 | return this.bodyElement || this.getDoc().body;\r |
10003 | },\r |
10004 | \r |
10005 | convertURL : function(u, n, e) {\r |
10006 | var t = this, s = t.settings;\r |
10007 | \r |
10008 | // Use callback instead\r |
10009 | if (s.urlconverter_callback)\r |
10010 | return t.execCallback('urlconverter_callback', u, e, true, n);\r |
10011 | \r |
10012 | // Don't convert link href since thats the CSS files that gets loaded into the editor also skip local file URLs\r |
10013 | if (!s.convert_urls || (e && e.nodeName == 'LINK') || u.indexOf('file:') === 0)\r |
10014 | return u;\r |
10015 | \r |
10016 | // Convert to relative\r |
10017 | if (s.relative_urls)\r |
10018 | return t.documentBaseURI.toRelative(u);\r |
10019 | \r |
10020 | // Convert to absolute\r |
10021 | u = t.documentBaseURI.toAbsolute(u, s.remove_script_host);\r |
10022 | \r |
10023 | return u;\r |
10024 | },\r |
10025 | \r |
10026 | addVisual : function(e) {\r |
10027 | var t = this, s = t.settings;\r |
10028 | \r |
10029 | e = e || t.getBody();\r |
10030 | \r |
10031 | if (!is(t.hasVisual))\r |
10032 | t.hasVisual = s.visual;\r |
10033 | \r |
10034 | each(t.dom.select('table,a', e), function(e) {\r |
10035 | var v;\r |
10036 | \r |
10037 | switch (e.nodeName) {\r |
10038 | case 'TABLE':\r |
10039 | v = t.dom.getAttrib(e, 'border');\r |
10040 | \r |
10041 | if (!v || v == '0') {\r |
10042 | if (t.hasVisual)\r |
10043 | t.dom.addClass(e, s.visual_table_class);\r |
10044 | else\r |
10045 | t.dom.removeClass(e, s.visual_table_class);\r |
10046 | }\r |
10047 | \r |
10048 | return;\r |
10049 | \r |
10050 | case 'A':\r |
10051 | v = t.dom.getAttrib(e, 'name');\r |
10052 | \r |
10053 | if (v) {\r |
10054 | if (t.hasVisual)\r |
10055 | t.dom.addClass(e, 'mceItemAnchor');\r |
10056 | else\r |
10057 | t.dom.removeClass(e, 'mceItemAnchor');\r |
10058 | }\r |
10059 | \r |
10060 | return;\r |
10061 | }\r |
10062 | });\r |
10063 | \r |
10064 | t.onVisualAid.dispatch(t, e, t.hasVisual);\r |
10065 | },\r |
10066 | \r |
10067 | remove : function() {\r |
10068 | var t = this, e = t.getContainer();\r |
10069 | \r |
10070 | t.removed = 1; // Cancels post remove event execution\r |
10071 | t.hide();\r |
10072 | \r |
10073 | t.execCallback('remove_instance_callback', t);\r |
10074 | t.onRemove.dispatch(t);\r |
10075 | \r |
10076 | // Clear all execCommand listeners this is required to avoid errors if the editor was removed inside another command\r |
10077 | t.onExecCommand.listeners = [];\r |
10078 | \r |
10079 | EditorManager.remove(t);\r |
10080 | DOM.remove(e);\r |
10081 | },\r |
10082 | \r |
10083 | destroy : function(s) {\r |
10084 | var t = this;\r |
10085 | \r |
10086 | // One time is enough\r |
10087 | if (t.destroyed)\r |
10088 | return;\r |
10089 | \r |
10090 | if (!s) {\r |
10091 | tinymce.removeUnload(t.destroy);\r |
10092 | tinyMCE.onBeforeUnload.remove(t._beforeUnload);\r |
10093 | \r |
10094 | // Manual destroy\r |
10095 | if (t.theme && t.theme.destroy)\r |
10096 | t.theme.destroy();\r |
10097 | \r |
10098 | // Destroy controls, selection and dom\r |
10099 | t.controlManager.destroy();\r |
10100 | t.selection.destroy();\r |
10101 | t.dom.destroy();\r |
10102 | \r |
10103 | // Remove all events\r |
10104 | \r |
10105 | // Don't clear the window or document if content editable\r |
10106 | // is enabled since other instances might still be present\r |
10107 | if (!t.settings.content_editable) {\r |
10108 | Event.clear(t.getWin());\r |
10109 | Event.clear(t.getDoc());\r |
10110 | }\r |
10111 | \r |
10112 | Event.clear(t.getBody());\r |
10113 | Event.clear(t.formElement);\r |
10114 | }\r |
10115 | \r |
10116 | if (t.formElement) {\r |
10117 | t.formElement.submit = t.formElement._mceOldSubmit;\r |
10118 | t.formElement._mceOldSubmit = null;\r |
10119 | }\r |
10120 | \r |
10121 | t.contentAreaContainer = t.formElement = t.container = t.settings.content_element = t.bodyElement = t.contentDocument = t.contentWindow = null;\r |
10122 | \r |
10123 | if (t.selection)\r |
10124 | t.selection = t.selection.win = t.selection.dom = t.selection.dom.doc = null;\r |
10125 | \r |
10126 | t.destroyed = 1;\r |
10127 | },\r |
10128 | \r |
10129 | // Internal functions\r |
10130 | \r |
10131 | _addEvents : function() {\r |
10132 | // 'focus', 'blur', 'dblclick', 'beforedeactivate', submit, reset\r |
10133 | var t = this, i, s = t.settings, lo = {\r |
10134 | mouseup : 'onMouseUp',\r |
10135 | mousedown : 'onMouseDown',\r |
10136 | click : 'onClick',\r |
10137 | keyup : 'onKeyUp',\r |
10138 | keydown : 'onKeyDown',\r |
10139 | keypress : 'onKeyPress',\r |
10140 | submit : 'onSubmit',\r |
10141 | reset : 'onReset',\r |
10142 | contextmenu : 'onContextMenu',\r |
10143 | dblclick : 'onDblClick',\r |
10144 | paste : 'onPaste' // Doesn't work in all browsers yet\r |
10145 | };\r |
10146 | \r |
10147 | function eventHandler(e, o) {\r |
10148 | var ty = e.type;\r |
10149 | \r |
10150 | // Don't fire events when it's removed\r |
10151 | if (t.removed)\r |
10152 | return;\r |
10153 | \r |
10154 | // Generic event handler\r |
10155 | if (t.onEvent.dispatch(t, e, o) !== false) {\r |
10156 | // Specific event handler\r |
10157 | t[lo[e.fakeType || e.type]].dispatch(t, e, o);\r |
10158 | }\r |
10159 | };\r |
10160 | \r |
10161 | // Add DOM events\r |
10162 | each(lo, function(v, k) {\r |
10163 | switch (k) {\r |
10164 | case 'contextmenu':\r |
10165 | if (tinymce.isOpera) {\r |
10166 | // Fake contextmenu on Opera\r |
10167 | t.dom.bind(t.getBody(), 'mousedown', function(e) {\r |
10168 | if (e.ctrlKey) {\r |
10169 | e.fakeType = 'contextmenu';\r |
10170 | eventHandler(e);\r |
10171 | }\r |
10172 | });\r |
10173 | } else\r |
10174 | t.dom.bind(t.getBody(), k, eventHandler);\r |
10175 | break;\r |
10176 | \r |
10177 | case 'paste':\r |
10178 | t.dom.bind(t.getBody(), k, function(e) {\r |
10179 | eventHandler(e);\r |
10180 | });\r |
10181 | break;\r |
10182 | \r |
10183 | case 'submit':\r |
10184 | case 'reset':\r |
10185 | t.dom.bind(t.getElement().form || DOM.getParent(t.id, 'form'), k, eventHandler);\r |
10186 | break;\r |
10187 | \r |
10188 | default:\r |
10189 | t.dom.bind(s.content_editable ? t.getBody() : t.getDoc(), k, eventHandler);\r |
10190 | }\r |
10191 | });\r |
10192 | \r |
10193 | t.dom.bind(s.content_editable ? t.getBody() : (isGecko ? t.getDoc() : t.getWin()), 'focus', function(e) {\r |
10194 | t.focus(true);\r |
10195 | });\r |
10196 | \r |
10197 | // Fixes bug where a specified document_base_uri could result in broken images\r |
10198 | // This will also fix drag drop of images in Gecko\r |
10199 | if (tinymce.isGecko) {\r |
10200 | // Convert all images to absolute URLs\r |
10201 | /* t.onSetContent.add(function(ed, o) {\r |
10202 | each(ed.dom.select('img'), function(e) {\r |
10203 | var v;\r |
10204 | \r |
10205 | if (v = e.getAttribute('mce_src'))\r |
10206 | e.src = t.documentBaseURI.toAbsolute(v);\r |
10207 | })\r |
10208 | });*/\r |
10209 | \r |
10210 | t.dom.bind(t.getDoc(), 'DOMNodeInserted', function(e) {\r |
10211 | var v;\r |
10212 | \r |
10213 | e = e.target;\r |
10214 | \r |
10215 | if (e.nodeType === 1 && e.nodeName === 'IMG' && (v = e.getAttribute('mce_src')))\r |
10216 | e.src = t.documentBaseURI.toAbsolute(v);\r |
10217 | });\r |
10218 | }\r |
10219 | \r |
10220 | // Set various midas options in Gecko\r |
10221 | if (isGecko) {\r |
10222 | function setOpts() {\r |
10223 | var t = this, d = t.getDoc(), s = t.settings;\r |
10224 | \r |
10225 | if (isGecko && !s.readonly) {\r |
10226 | if (t._isHidden()) {\r |
10227 | try {\r |
10228 | if (!s.content_editable)\r |
10229 | d.designMode = 'On';\r |
10230 | } catch (ex) {\r |
10231 | // Fails if it's hidden\r |
10232 | }\r |
10233 | }\r |
10234 | \r |
10235 | try {\r |
10236 | // Try new Gecko method\r |
10237 | d.execCommand("styleWithCSS", 0, false);\r |
10238 | } catch (ex) {\r |
10239 | // Use old method\r |
10240 | if (!t._isHidden())\r |
10241 | try {d.execCommand("useCSS", 0, true);} catch (ex) {}\r |
10242 | }\r |
10243 | \r |
10244 | if (!s.table_inline_editing)\r |
10245 | try {d.execCommand('enableInlineTableEditing', false, false);} catch (ex) {}\r |
10246 | \r |
10247 | if (!s.object_resizing)\r |
10248 | try {d.execCommand('enableObjectResizing', false, false);} catch (ex) {}\r |
10249 | }\r |
10250 | };\r |
10251 | \r |
10252 | t.onBeforeExecCommand.add(setOpts);\r |
10253 | t.onMouseDown.add(setOpts);\r |
10254 | }\r |
10255 | \r |
10256 | // Add node change handlers\r |
10257 | t.onMouseUp.add(t.nodeChanged);\r |
10258 | t.onClick.add(t.nodeChanged);\r |
10259 | t.onKeyUp.add(function(ed, e) {\r |
10260 | var c = e.keyCode;\r |
10261 | \r |
10262 | if ((c >= 33 && c <= 36) || (c >= 37 && c <= 40) || c == 13 || c == 45 || c == 46 || c == 8 || (tinymce.isMac && (c == 91 || c == 93)) || e.ctrlKey)\r |
10263 | t.nodeChanged();\r |
10264 | });\r |
10265 | \r |
10266 | // Add reset handler\r |
10267 | t.onReset.add(function() {\r |
10268 | t.setContent(t.startContent, {format : 'raw'});\r |
10269 | });\r |
10270 | \r |
10271 | // Add shortcuts\r |
10272 | if (s.custom_shortcuts) {\r |
10273 | if (s.custom_undo_redo_keyboard_shortcuts) {\r |
10274 | t.addShortcut('ctrl+z', t.getLang('undo_desc'), 'Undo');\r |
10275 | t.addShortcut('ctrl+y', t.getLang('redo_desc'), 'Redo');\r |
10276 | }\r |
10277 | \r |
10278 | // Add default shortcuts for gecko\r |
10279 | if (isGecko) {\r |
10280 | t.addShortcut('ctrl+b', t.getLang('bold_desc'), 'Bold');\r |
10281 | t.addShortcut('ctrl+i', t.getLang('italic_desc'), 'Italic');\r |
10282 | t.addShortcut('ctrl+u', t.getLang('underline_desc'), 'Underline');\r |
10283 | }\r |
10284 | \r |
10285 | // BlockFormat shortcuts keys\r |
10286 | for (i=1; i<=6; i++)\r |
10287 | t.addShortcut('ctrl+' + i, '', ['FormatBlock', false, '<h' + i + '>']);\r |
10288 | \r |
10289 | t.addShortcut('ctrl+7', '', ['FormatBlock', false, '<p>']);\r |
10290 | t.addShortcut('ctrl+8', '', ['FormatBlock', false, '<div>']);\r |
10291 | t.addShortcut('ctrl+9', '', ['FormatBlock', false, '<address>']);\r |
10292 | \r |
10293 | function find(e) {\r |
10294 | var v = null;\r |
10295 | \r |
10296 | if (!e.altKey && !e.ctrlKey && !e.metaKey)\r |
10297 | return v;\r |
10298 | \r |
10299 | each(t.shortcuts, function(o) {\r |
10300 | if (tinymce.isMac && o.ctrl != e.metaKey)\r |
10301 | return;\r |
10302 | else if (!tinymce.isMac && o.ctrl != e.ctrlKey)\r |
10303 | return;\r |
10304 | \r |
10305 | if (o.alt != e.altKey)\r |
10306 | return;\r |
10307 | \r |
10308 | if (o.shift != e.shiftKey)\r |
10309 | return;\r |
10310 | \r |
10311 | if (e.keyCode == o.keyCode || (e.charCode && e.charCode == o.charCode)) {\r |
10312 | v = o;\r |
10313 | return false;\r |
10314 | }\r |
10315 | });\r |
10316 | \r |
10317 | return v;\r |
10318 | };\r |
10319 | \r |
10320 | t.onKeyUp.add(function(ed, e) {\r |
10321 | var o = find(e);\r |
10322 | \r |
10323 | if (o)\r |
10324 | return Event.cancel(e);\r |
10325 | });\r |
10326 | \r |
10327 | t.onKeyPress.add(function(ed, e) {\r |
10328 | var o = find(e);\r |
10329 | \r |
10330 | if (o)\r |
10331 | return Event.cancel(e);\r |
10332 | });\r |
10333 | \r |
10334 | t.onKeyDown.add(function(ed, e) {\r |
10335 | var o = find(e);\r |
10336 | \r |
10337 | if (o) {\r |
10338 | o.func.call(o.scope);\r |
10339 | return Event.cancel(e);\r |
10340 | }\r |
10341 | });\r |
10342 | }\r |
10343 | \r |
10344 | if (tinymce.isIE) {\r |
10345 | // Fix so resize will only update the width and height attributes not the styles of an image\r |
10346 | // It will also block mceItemNoResize items\r |
10347 | t.dom.bind(t.getDoc(), 'controlselect', function(e) {\r |
10348 | var re = t.resizeInfo, cb;\r |
10349 | \r |
10350 | e = e.target;\r |
10351 | \r |
10352 | // Don't do this action for non image elements\r |
10353 | if (e.nodeName !== 'IMG')\r |
10354 | return;\r |
10355 | \r |
10356 | if (re)\r |
10357 | t.dom.unbind(re.node, re.ev, re.cb);\r |
10358 | \r |
10359 | if (!t.dom.hasClass(e, 'mceItemNoResize')) {\r |
10360 | ev = 'resizeend';\r |
10361 | cb = t.dom.bind(e, ev, function(e) {\r |
10362 | var v;\r |
10363 | \r |
10364 | e = e.target;\r |
10365 | \r |
10366 | if (v = t.dom.getStyle(e, 'width')) {\r |
10367 | t.dom.setAttrib(e, 'width', v.replace(/[^0-9%]+/g, ''));\r |
10368 | t.dom.setStyle(e, 'width', '');\r |
10369 | }\r |
10370 | \r |
10371 | if (v = t.dom.getStyle(e, 'height')) {\r |
10372 | t.dom.setAttrib(e, 'height', v.replace(/[^0-9%]+/g, ''));\r |
10373 | t.dom.setStyle(e, 'height', '');\r |
10374 | }\r |
10375 | });\r |
10376 | } else {\r |
10377 | ev = 'resizestart';\r |
10378 | cb = t.dom.bind(e, 'resizestart', Event.cancel, Event);\r |
10379 | }\r |
10380 | \r |
10381 | re = t.resizeInfo = {\r |
10382 | node : e,\r |
10383 | ev : ev,\r |
10384 | cb : cb\r |
10385 | };\r |
10386 | });\r |
10387 | \r |
10388 | t.onKeyDown.add(function(ed, e) {\r |
10389 | switch (e.keyCode) {\r |
10390 | case 8:\r |
10391 | // Fix IE control + backspace browser bug\r |
10392 | if (t.selection.getRng().item) {\r |
10393 | t.selection.getRng().item(0).removeNode();\r |
10394 | return Event.cancel(e);\r |
10395 | }\r |
10396 | }\r |
10397 | });\r |
10398 | \r |
10399 | /*if (t.dom.boxModel) {\r |
10400 | t.getBody().style.height = '100%';\r |
10401 | \r |
10402 | Event.add(t.getWin(), 'resize', function(e) {\r |
10403 | var docElm = t.getDoc().documentElement;\r |
10404 | \r |
10405 | docElm.style.height = (docElm.offsetHeight - 10) + 'px';\r |
10406 | });\r |
10407 | }*/\r |
10408 | }\r |
10409 | \r |
10410 | if (tinymce.isOpera) {\r |
10411 | t.onClick.add(function(ed, e) {\r |
10412 | Event.prevent(e);\r |
10413 | });\r |
10414 | }\r |
10415 | \r |
10416 | // Add custom undo/redo handlers\r |
10417 | if (s.custom_undo_redo) {\r |
10418 | function addUndo() {\r |
10419 | t.undoManager.typing = 0;\r |
10420 | t.undoManager.add();\r |
10421 | };\r |
10422 | \r |
10423 | // Add undo level on editor blur\r |
10424 | if (tinymce.isIE) {\r |
10425 | t.dom.bind(t.getWin(), 'blur', function(e) {\r |
10426 | var n;\r |
10427 | \r |
10428 | // Check added for fullscreen bug\r |
10429 | if (t.selection) {\r |
10430 | n = t.selection.getNode();\r |
10431 | \r |
10432 | // Add undo level is selection was lost to another document\r |
10433 | if (!t.removed && n.ownerDocument && n.ownerDocument != t.getDoc())\r |
10434 | addUndo();\r |
10435 | }\r |
10436 | });\r |
10437 | } else {\r |
10438 | t.dom.bind(t.getDoc(), 'blur', function() {\r |
10439 | if (t.selection && !t.removed)\r |
10440 | addUndo();\r |
10441 | });\r |
10442 | }\r |
10443 | \r |
10444 | t.onMouseDown.add(addUndo);\r |
10445 | \r |
10446 | t.onKeyUp.add(function(ed, e) {\r |
10447 | if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45 || e.ctrlKey) {\r |
10448 | t.undoManager.typing = 0;\r |
10449 | t.undoManager.add();\r |
10450 | }\r |
10451 | });\r |
10452 | \r |
10453 | t.onKeyDown.add(function(ed, e) {\r |
10454 | // Is caracter positon keys\r |
10455 | if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45) {\r |
10456 | if (t.undoManager.typing) {\r |
10457 | t.undoManager.add();\r |
10458 | t.undoManager.typing = 0;\r |
10459 | }\r |
10460 | \r |
10461 | return;\r |
10462 | }\r |
10463 | \r |
10464 | if (!t.undoManager.typing) {\r |
10465 | t.undoManager.add();\r |
10466 | t.undoManager.typing = 1;\r |
10467 | }\r |
10468 | });\r |
10469 | }\r |
10470 | },\r |
10471 | \r |
10472 | _convertInlineElements : function() {\r |
10473 | var t = this, s = t.settings, dom = t.dom, v, e, na, st, sp;\r |
10474 | \r |
10475 | function convert(ed, o) {\r |
10476 | if (!s.inline_styles)\r |
10477 | return;\r |
10478 | \r |
10479 | if (o.get) {\r |
10480 | each(t.dom.select('table,u,strike', o.node), function(n) {\r |
10481 | switch (n.nodeName) {\r |
10482 | case 'TABLE':\r |
10483 | if (v = dom.getAttrib(n, 'height')) {\r |
10484 | dom.setStyle(n, 'height', v);\r |
10485 | dom.setAttrib(n, 'height', '');\r |
10486 | }\r |
10487 | break;\r |
10488 | \r |
10489 | case 'U':\r |
10490 | case 'STRIKE':\r |
10491 | //sp = dom.create('span', {style : dom.getAttrib(n, 'style')});\r |
10492 | n.style.textDecoration = n.nodeName == 'U' ? 'underline' : 'line-through';\r |
10493 | dom.setAttrib(n, 'mce_style', '');\r |
10494 | dom.setAttrib(n, 'mce_name', 'span');\r |
10495 | break;\r |
10496 | }\r |
10497 | });\r |
10498 | } else if (o.set) {\r |
10499 | each(t.dom.select('table,span', o.node).reverse(), function(n) {\r |
10500 | if (n.nodeName == 'TABLE') {\r |
10501 | if (v = dom.getStyle(n, 'height'))\r |
10502 | dom.setAttrib(n, 'height', v.replace(/[^0-9%]+/g, ''));\r |
10503 | } else {\r |
10504 | // Convert spans to elements\r |
10505 | if (n.style.textDecoration == 'underline')\r |
10506 | na = 'u';\r |
10507 | else if (n.style.textDecoration == 'line-through')\r |
10508 | na = 'strike';\r |
10509 | else\r |
10510 | na = '';\r |
10511 | \r |
10512 | if (na) {\r |
10513 | n.style.textDecoration = '';\r |
10514 | dom.setAttrib(n, 'mce_style', '');\r |
10515 | \r |
10516 | e = dom.create(na, {\r |
10517 | style : dom.getAttrib(n, 'style')\r |
10518 | });\r |
10519 | \r |
10520 | dom.replace(e, n, 1);\r |
10521 | }\r |
10522 | }\r |
10523 | });\r |
10524 | }\r |
10525 | };\r |
10526 | \r |
10527 | t.onPreProcess.add(convert);\r |
10528 | \r |
10529 | if (!s.cleanup_on_startup) {\r |
10530 | t.onSetContent.add(function(ed, o) {\r |
10531 | if (o.initial)\r |
10532 | convert(t, {node : t.getBody(), set : 1});\r |
10533 | });\r |
10534 | }\r |
10535 | },\r |
10536 | \r |
10537 | _convertFonts : function() {\r |
10538 | var t = this, s = t.settings, dom = t.dom, fz, fzn, sl, cl;\r |
10539 | \r |
10540 | // No need\r |
10541 | if (!s.inline_styles)\r |
10542 | return;\r |
10543 | \r |
10544 | // Font pt values and font size names\r |
10545 | fz = [8, 10, 12, 14, 18, 24, 36];\r |
10546 | fzn = ['xx-small', 'x-small','small','medium','large','x-large', 'xx-large'];\r |
10547 | \r |
10548 | if (sl = s.font_size_style_values)\r |
10549 | sl = explode(sl);\r |
10550 | \r |
10551 | if (cl = s.font_size_classes)\r |
10552 | cl = explode(cl);\r |
10553 | \r |
10554 | function process(no) {\r |
10555 | var n, sp, nl, x;\r |
10556 | \r |
10557 | // Keep unit tests happy\r |
10558 | if (!s.inline_styles)\r |
10559 | return;\r |
10560 | \r |
10561 | nl = t.dom.select('font', no);\r |
10562 | for (x = nl.length - 1; x >= 0; x--) {\r |
10563 | n = nl[x];\r |
10564 | \r |
10565 | sp = dom.create('span', {\r |
10566 | style : dom.getAttrib(n, 'style'),\r |
10567 | 'class' : dom.getAttrib(n, 'class')\r |
10568 | });\r |
10569 | \r |
10570 | dom.setStyles(sp, {\r |
10571 | fontFamily : dom.getAttrib(n, 'face'),\r |
10572 | color : dom.getAttrib(n, 'color'),\r |
10573 | backgroundColor : n.style.backgroundColor\r |
10574 | });\r |
10575 | \r |
10576 | if (n.size) {\r |
10577 | if (sl)\r |
10578 | dom.setStyle(sp, 'fontSize', sl[parseInt(n.size) - 1]);\r |
10579 | else\r |
10580 | dom.setAttrib(sp, 'class', cl[parseInt(n.size) - 1]);\r |
10581 | }\r |
10582 | \r |
10583 | dom.setAttrib(sp, 'mce_style', '');\r |
10584 | dom.replace(sp, n, 1);\r |
10585 | }\r |
10586 | };\r |
10587 | \r |
10588 | // Run on cleanup\r |
10589 | t.onPreProcess.add(function(ed, o) {\r |
10590 | if (o.get)\r |
10591 | process(o.node);\r |
10592 | });\r |
10593 | \r |
10594 | t.onSetContent.add(function(ed, o) {\r |
10595 | if (o.initial)\r |
10596 | process(o.node);\r |
10597 | });\r |
10598 | },\r |
10599 | \r |
10600 | _isHidden : function() {\r |
10601 | var s;\r |
10602 | \r |
10603 | if (!isGecko)\r |
10604 | return 0;\r |
10605 | \r |
10606 | // Weird, wheres that cursor selection?\r |
10607 | s = this.selection.getSel();\r |
10608 | return (!s || !s.rangeCount || s.rangeCount == 0);\r |
10609 | },\r |
10610 | \r |
10611 | // Fix for bug #1867292\r |
10612 | _fixNesting : function(s) {\r |
10613 | var d = [], i;\r |
10614 | \r |
10615 | s = s.replace(/<(\/)?([^\s>]+)[^>]*?>/g, function(a, b, c) {\r |
10616 | var e;\r |
10617 | \r |
10618 | // Handle end element\r |
10619 | if (b === '/') {\r |
10620 | if (!d.length)\r |
10621 | return '';\r |
10622 | \r |
10623 | if (c !== d[d.length - 1].tag) {\r |
10624 | for (i=d.length - 1; i>=0; i--) {\r |
10625 | if (d[i].tag === c) {\r |
10626 | d[i].close = 1;\r |
10627 | break;\r |
10628 | }\r |
10629 | }\r |
10630 | \r |
10631 | return '';\r |
10632 | } else {\r |
10633 | d.pop();\r |
10634 | \r |
10635 | if (d.length && d[d.length - 1].close) {\r |
10636 | a = a + '</' + d[d.length - 1].tag + '>';\r |
10637 | d.pop();\r |
10638 | }\r |
10639 | }\r |
10640 | } else {\r |
10641 | // Ignore these\r |
10642 | if (/^(br|hr|input|meta|img|link|param)$/i.test(c))\r |
10643 | return a;\r |
10644 | \r |
10645 | // Ignore closed ones\r |
10646 | if (/\/>$/.test(a))\r |
10647 | return a;\r |
10648 | \r |
10649 | d.push({tag : c}); // Push start element\r |
10650 | }\r |
10651 | \r |
10652 | return a;\r |
10653 | });\r |
10654 | \r |
10655 | // End all open tags\r |
10656 | for (i=d.length - 1; i>=0; i--)\r |
10657 | s += '</' + d[i].tag + '>';\r |
10658 | \r |
10659 | return s;\r |
10660 | }\r |
10661 | });\r |
10662 | })(tinymce);\r |
10663 | (function(tinymce) {\r |
10664 | var each = tinymce.each, isIE = tinymce.isIE, isGecko = tinymce.isGecko, isOpera = tinymce.isOpera, isWebKit = tinymce.isWebKit;\r |
10665 | \r |
10666 | tinymce.create('tinymce.EditorCommands', {\r |
10667 | EditorCommands : function(ed) {\r |
10668 | this.editor = ed;\r |
10669 | },\r |
10670 | \r |
10671 | execCommand : function(cmd, ui, val) {\r |
10672 | var t = this, ed = t.editor, f;\r |
10673 | \r |
10674 | switch (cmd) {\r |
10675 | // Ignore these\r |
10676 | case 'mceResetDesignMode':\r |
10677 | case 'mceBeginUndoLevel':\r |
10678 | return true;\r |
10679 | \r |
10680 | // Ignore these\r |
10681 | case 'unlink':\r |
10682 | t.UnLink();\r |
10683 | return true;\r |
10684 | \r |
10685 | // Bundle these together\r |
10686 | case 'JustifyLeft':\r |
10687 | case 'JustifyCenter':\r |
10688 | case 'JustifyRight':\r |
10689 | case 'JustifyFull':\r |
10690 | t.mceJustify(cmd, cmd.substring(7).toLowerCase());\r |
10691 | return true;\r |
10692 | \r |
10693 | default:\r |
10694 | f = this[cmd];\r |
10695 | \r |
10696 | if (f) {\r |
10697 | f.call(this, ui, val);\r |
10698 | return true;\r |
10699 | }\r |
10700 | }\r |
10701 | \r |
10702 | return false;\r |
10703 | },\r |
10704 | \r |
10705 | Indent : function() {\r |
10706 | var ed = this.editor, d = ed.dom, s = ed.selection, e, iv, iu;\r |
10707 | \r |
10708 | // Setup indent level\r |
10709 | iv = ed.settings.indentation;\r |
10710 | iu = /[a-z%]+$/i.exec(iv);\r |
10711 | iv = parseInt(iv);\r |
10712 | \r |
10713 | if (ed.settings.inline_styles && (!this.queryStateInsertUnorderedList() && !this.queryStateInsertOrderedList())) {\r |
10714 | each(s.getSelectedBlocks(), function(e) {\r |
10715 | d.setStyle(e, 'paddingLeft', (parseInt(e.style.paddingLeft || 0) + iv) + iu);\r |
10716 | });\r |
10717 | \r |
10718 | return;\r |
10719 | }\r |
10720 | \r |
10721 | ed.getDoc().execCommand('Indent', false, null);\r |
10722 | \r |
10723 | if (isIE) {\r |
10724 | d.getParent(s.getNode(), function(n) {\r |
10725 | if (n.nodeName == 'BLOCKQUOTE') {\r |
10726 | n.dir = n.style.cssText = '';\r |
10727 | }\r |
10728 | });\r |
10729 | }\r |
10730 | },\r |
10731 | \r |
10732 | Outdent : function() {\r |
10733 | var ed = this.editor, d = ed.dom, s = ed.selection, e, v, iv, iu;\r |
10734 | \r |
10735 | // Setup indent level\r |
10736 | iv = ed.settings.indentation;\r |
10737 | iu = /[a-z%]+$/i.exec(iv);\r |
10738 | iv = parseInt(iv);\r |
10739 | \r |
10740 | if (ed.settings.inline_styles && (!this.queryStateInsertUnorderedList() && !this.queryStateInsertOrderedList())) {\r |
10741 | each(s.getSelectedBlocks(), function(e) {\r |
10742 | v = Math.max(0, parseInt(e.style.paddingLeft || 0) - iv);\r |
10743 | d.setStyle(e, 'paddingLeft', v ? v + iu : '');\r |
10744 | });\r |
10745 | \r |
10746 | return;\r |
10747 | }\r |
10748 | \r |
10749 | ed.getDoc().execCommand('Outdent', false, null);\r |
10750 | },\r |
10751 | \r |
10752 | /*\r |
10753 | mceSetAttribute : function(u, v) {\r |
10754 | var ed = this.editor, d = ed.dom, e;\r |
10755 | \r |
10756 | if (e = d.getParent(ed.selection.getNode(), d.isBlock))\r |
10757 | d.setAttrib(e, v.name, v.value);\r |
10758 | },\r |
10759 | */\r |
10760 | mceSetContent : function(u, v) {\r |
10761 | this.editor.setContent(v);\r |
10762 | },\r |
10763 | \r |
10764 | mceToggleVisualAid : function() {\r |
10765 | var ed = this.editor;\r |
10766 | \r |
10767 | ed.hasVisual = !ed.hasVisual;\r |
10768 | ed.addVisual();\r |
10769 | },\r |
10770 | \r |
10771 | mceReplaceContent : function(u, v) {\r |
10772 | var s = this.editor.selection;\r |
10773 | \r |
10774 | s.setContent(v.replace(/\{\$selection\}/g, s.getContent({format : 'text'})));\r |
10775 | },\r |
10776 | \r |
10777 | mceInsertLink : function(u, v) {\r |
10778 | var ed = this.editor, s = ed.selection, e = ed.dom.getParent(s.getNode(), 'a');\r |
10779 | \r |
10780 | if (tinymce.is(v, 'string'))\r |
10781 | v = {href : v};\r |
10782 | \r |
10783 | function set(e) {\r |
10784 | each(v, function(v, k) {\r |
10785 | ed.dom.setAttrib(e, k, v);\r |
10786 | });\r |
10787 | };\r |
10788 | \r |
10789 | if (!e) {\r |
10790 | ed.execCommand('CreateLink', false, 'javascript:mctmp(0);');\r |
10791 | each(ed.dom.select('a[href=javascript:mctmp(0);]'), function(e) {\r |
10792 | set(e);\r |
10793 | });\r |
10794 | } else {\r |
10795 | if (v.href)\r |
10796 | set(e);\r |
10797 | else\r |
10798 | ed.dom.remove(e, 1);\r |
10799 | }\r |
10800 | },\r |
10801 | \r |
10802 | UnLink : function() {\r |
10803 | var ed = this.editor, s = ed.selection;\r |
10804 | \r |
10805 | if (s.isCollapsed())\r |
10806 | s.select(s.getNode());\r |
10807 | \r |
10808 | ed.getDoc().execCommand('unlink', false, null);\r |
10809 | s.collapse(0);\r |
10810 | },\r |
10811 | \r |
10812 | FontName : function(u, v) {\r |
10813 | var t = this, ed = t.editor, s = ed.selection, e;\r |
10814 | \r |
10815 | if (!v) {\r |
10816 | if (s.isCollapsed())\r |
10817 | s.select(s.getNode());\r |
10818 | } else {\r |
10819 | if (ed.settings.convert_fonts_to_spans)\r |
10820 | t._applyInlineStyle('span', {style : {fontFamily : v}});\r |
10821 | else\r |
10822 | ed.getDoc().execCommand('FontName', false, v);\r |
10823 | }\r |
10824 | },\r |
10825 | \r |
10826 | FontSize : function(u, v) {\r |
10827 | var ed = this.editor, s = ed.settings, fc, fs;\r |
10828 | \r |
10829 | // Use style options instead\r |
10830 | if (s.convert_fonts_to_spans && v >= 1 && v <= 7) {\r |
10831 | fs = tinymce.explode(s.font_size_style_values);\r |
10832 | fc = tinymce.explode(s.font_size_classes);\r |
10833 | \r |
10834 | if (fc)\r |
10835 | v = fc[v - 1] || v;\r |
10836 | else\r |
10837 | v = fs[v - 1] || v;\r |
10838 | }\r |
10839 | \r |
10840 | if (v >= 1 && v <= 7)\r |
10841 | ed.getDoc().execCommand('FontSize', false, v);\r |
10842 | else\r |
10843 | this._applyInlineStyle('span', {style : {fontSize : v}});\r |
10844 | },\r |
10845 | \r |
10846 | queryCommandValue : function(c) {\r |
10847 | var f = this['queryValue' + c];\r |
10848 | \r |
10849 | if (f)\r |
10850 | return f.call(this, c);\r |
10851 | \r |
10852 | return false;\r |
10853 | },\r |
10854 | \r |
10855 | queryCommandState : function(cmd) {\r |
10856 | var f;\r |
10857 | \r |
10858 | switch (cmd) {\r |
10859 | // Bundle these together\r |
10860 | case 'JustifyLeft':\r |
10861 | case 'JustifyCenter':\r |
10862 | case 'JustifyRight':\r |
10863 | case 'JustifyFull':\r |
10864 | return this.queryStateJustify(cmd, cmd.substring(7).toLowerCase());\r |
10865 | \r |
10866 | default:\r |
10867 | if (f = this['queryState' + cmd])\r |
10868 | return f.call(this, cmd);\r |
10869 | }\r |
10870 | \r |
10871 | return -1;\r |
10872 | },\r |
10873 | \r |
10874 | _queryState : function(c) {\r |
10875 | try {\r |
10876 | return this.editor.getDoc().queryCommandState(c);\r |
10877 | } catch (ex) {\r |
10878 | // Ignore exception\r |
10879 | }\r |
10880 | },\r |
10881 | \r |
10882 | _queryVal : function(c) {\r |
10883 | try {\r |
10884 | return this.editor.getDoc().queryCommandValue(c);\r |
10885 | } catch (ex) {\r |
10886 | // Ignore exception\r |
10887 | }\r |
10888 | },\r |
10889 | \r |
10890 | queryValueFontSize : function() {\r |
10891 | var ed = this.editor, v = 0, p;\r |
10892 | \r |
10893 | if (p = ed.dom.getParent(ed.selection.getNode(), 'span'))\r |
10894 | v = p.style.fontSize;\r |
10895 | \r |
10896 | if (!v && (isOpera || isWebKit)) {\r |
10897 | if (p = ed.dom.getParent(ed.selection.getNode(), 'font'))\r |
10898 | v = p.size;\r |
10899 | \r |
10900 | return v;\r |
10901 | }\r |
10902 | \r |
10903 | return v || this._queryVal('FontSize');\r |
10904 | },\r |
10905 | \r |
10906 | queryValueFontName : function() {\r |
10907 | var ed = this.editor, v = 0, p;\r |
10908 | \r |
10909 | if (p = ed.dom.getParent(ed.selection.getNode(), 'font'))\r |
10910 | v = p.face;\r |
10911 | \r |
10912 | if (p = ed.dom.getParent(ed.selection.getNode(), 'span'))\r |
10913 | v = p.style.fontFamily.replace(/, /g, ',').replace(/[\'\"]/g, '').toLowerCase();\r |
10914 | \r |
10915 | if (!v)\r |
10916 | v = this._queryVal('FontName');\r |
10917 | \r |
10918 | return v;\r |
10919 | },\r |
10920 | \r |
10921 | mceJustify : function(c, v) {\r |
10922 | var ed = this.editor, se = ed.selection, n = se.getNode(), nn = n.nodeName, bl, nb, dom = ed.dom, rm;\r |
10923 | \r |
10924 | if (ed.settings.inline_styles && this.queryStateJustify(c, v))\r |
10925 | rm = 1;\r |
10926 | \r |
10927 | bl = dom.getParent(n, ed.dom.isBlock);\r |
10928 | \r |
10929 | if (nn == 'IMG') {\r |
10930 | if (v == 'full')\r |
10931 | return;\r |
10932 | \r |
10933 | if (rm) {\r |
10934 | if (v == 'center')\r |
10935 | dom.setStyle(bl || n.parentNode, 'textAlign', '');\r |
10936 | \r |
10937 | dom.setStyle(n, 'float', '');\r |
10938 | this.mceRepaint();\r |
10939 | return;\r |
10940 | }\r |
10941 | \r |
10942 | if (v == 'center') {\r |
10943 | // Do not change table elements\r |
10944 | if (bl && /^(TD|TH)$/.test(bl.nodeName))\r |
10945 | bl = 0;\r |
10946 | \r |
10947 | if (!bl || bl.childNodes.length > 1) {\r |
10948 | nb = dom.create('p');\r |
10949 | nb.appendChild(n.cloneNode(false));\r |
10950 | \r |
10951 | if (bl)\r |
10952 | dom.insertAfter(nb, bl);\r |
10953 | else\r |
10954 | dom.insertAfter(nb, n);\r |
10955 | \r |
10956 | dom.remove(n);\r |
10957 | n = nb.firstChild;\r |
10958 | bl = nb;\r |
10959 | }\r |
10960 | \r |
10961 | dom.setStyle(bl, 'textAlign', v);\r |
10962 | dom.setStyle(n, 'float', '');\r |
10963 | } else {\r |
10964 | dom.setStyle(n, 'float', v);\r |
10965 | dom.setStyle(bl || n.parentNode, 'textAlign', '');\r |
10966 | }\r |
10967 | \r |
10968 | this.mceRepaint();\r |
10969 | return;\r |
10970 | }\r |
10971 | \r |
10972 | // Handle the alignment outselfs, less quirks in all browsers\r |
10973 | if (ed.settings.inline_styles && ed.settings.forced_root_block) {\r |
10974 | if (rm)\r |
10975 | v = '';\r |
10976 | \r |
10977 | each(se.getSelectedBlocks(dom.getParent(se.getStart(), dom.isBlock), dom.getParent(se.getEnd(), dom.isBlock)), function(e) {\r |
10978 | dom.setAttrib(e, 'align', '');\r |
10979 | dom.setStyle(e, 'textAlign', v == 'full' ? 'justify' : v);\r |
10980 | });\r |
10981 | \r |
10982 | return;\r |
10983 | } else if (!rm)\r |
10984 | ed.getDoc().execCommand(c, false, null);\r |
10985 | \r |
10986 | if (ed.settings.inline_styles) {\r |
10987 | if (rm) {\r |
10988 | dom.getParent(ed.selection.getNode(), function(n) {\r |
10989 | if (n.style && n.style.textAlign)\r |
10990 | dom.setStyle(n, 'textAlign', '');\r |
10991 | });\r |
10992 | \r |
10993 | return;\r |
10994 | }\r |
10995 | \r |
10996 | each(dom.select('*'), function(n) {\r |
10997 | var v = n.align;\r |
10998 | \r |
10999 | if (v) {\r |
11000 | if (v == 'full')\r |
11001 | v = 'justify';\r |
11002 | \r |
11003 | dom.setStyle(n, 'textAlign', v);\r |
11004 | dom.setAttrib(n, 'align', '');\r |
11005 | }\r |
11006 | });\r |
11007 | }\r |
11008 | },\r |
11009 | \r |
11010 | mceSetCSSClass : function(u, v) {\r |
11011 | this.mceSetStyleInfo(0, {command : 'setattrib', name : 'class', value : v});\r |
11012 | },\r |
11013 | \r |
11014 | getSelectedElement : function() {\r |
11015 | var t = this, ed = t.editor, dom = ed.dom, se = ed.selection, r = se.getRng(), r1, r2, sc, ec, so, eo, e, sp, ep, re;\r |
11016 | \r |
11017 | if (se.isCollapsed() || r.item)\r |
11018 | return se.getNode();\r |
11019 | \r |
11020 | // Setup regexp\r |
11021 | re = ed.settings.merge_styles_invalid_parents;\r |
11022 | if (tinymce.is(re, 'string'))\r |
11023 | re = new RegExp(re, 'i');\r |
11024 | \r |
11025 | if (isIE) {\r |
11026 | r1 = r.duplicate();\r |
11027 | r1.collapse(true);\r |
11028 | sc = r1.parentElement();\r |
11029 | \r |
11030 | r2 = r.duplicate();\r |
11031 | r2.collapse(false);\r |
11032 | ec = r2.parentElement();\r |
11033 | \r |
11034 | if (sc != ec) {\r |
11035 | r1.move('character', 1);\r |
11036 | sc = r1.parentElement();\r |
11037 | }\r |
11038 | \r |
11039 | if (sc == ec) {\r |
11040 | r1 = r.duplicate();\r |
11041 | r1.moveToElementText(sc);\r |
11042 | \r |
11043 | if (r1.compareEndPoints('StartToStart', r) == 0 && r1.compareEndPoints('EndToEnd', r) == 0)\r |
11044 | return re && re.test(sc.nodeName) ? null : sc;\r |
11045 | }\r |
11046 | } else {\r |
11047 | function getParent(n) {\r |
11048 | return dom.getParent(n, '*');\r |
11049 | };\r |
11050 | \r |
11051 | sc = r.startContainer;\r |
11052 | ec = r.endContainer;\r |
11053 | so = r.startOffset;\r |
11054 | eo = r.endOffset;\r |
11055 | \r |
11056 | if (!r.collapsed) {\r |
11057 | if (sc == ec) {\r |
11058 | if (so - eo < 2) {\r |
11059 | if (sc.hasChildNodes()) {\r |
11060 | sp = sc.childNodes[so];\r |
11061 | return re && re.test(sp.nodeName) ? null : sp;\r |
11062 | }\r |
11063 | }\r |
11064 | }\r |
11065 | }\r |
11066 | \r |
11067 | if (sc.nodeType != 3 || ec.nodeType != 3)\r |
11068 | return null;\r |
11069 | \r |
11070 | if (so == 0) {\r |
11071 | sp = getParent(sc);\r |
11072 | \r |
11073 | if (sp && sp.firstChild != sc)\r |
11074 | sp = null;\r |
11075 | }\r |
11076 | \r |
11077 | if (so == sc.nodeValue.length) {\r |
11078 | e = sc.nextSibling;\r |
11079 | \r |
11080 | if (e && e.nodeType == 1)\r |
11081 | sp = sc.nextSibling;\r |
11082 | }\r |
11083 | \r |
11084 | if (eo == 0) {\r |
11085 | e = ec.previousSibling;\r |
11086 | \r |
11087 | if (e && e.nodeType == 1)\r |
11088 | ep = e;\r |
11089 | }\r |
11090 | \r |
11091 | if (eo == ec.nodeValue.length) {\r |
11092 | ep = getParent(ec);\r |
11093 | \r |
11094 | if (ep && ep.lastChild != ec)\r |
11095 | ep = null;\r |
11096 | }\r |
11097 | \r |
11098 | // Same element\r |
11099 | if (sp == ep)\r |
11100 | return re && sp && re.test(sp.nodeName) ? null : sp;\r |
11101 | }\r |
11102 | \r |
11103 | return null;\r |
11104 | },\r |
11105 | \r |
11106 | mceSetStyleInfo : function(u, v) {\r |
11107 | var t = this, ed = t.editor, d = ed.getDoc(), dom = ed.dom, e, b, s = ed.selection, nn = v.wrapper || 'span', b = s.getBookmark(), re;\r |
11108 | \r |
11109 | function set(n, e) {\r |
11110 | if (n.nodeType == 1) {\r |
11111 | switch (v.command) {\r |
11112 | case 'setattrib':\r |
11113 | return dom.setAttrib(n, v.name, v.value);\r |
11114 | \r |
11115 | case 'setstyle':\r |
11116 | return dom.setStyle(n, v.name, v.value);\r |
11117 | \r |
11118 | case 'removeformat':\r |
11119 | return dom.setAttrib(n, 'class', '');\r |
11120 | }\r |
11121 | }\r |
11122 | };\r |
11123 | \r |
11124 | // Setup regexp\r |
11125 | re = ed.settings.merge_styles_invalid_parents;\r |
11126 | if (tinymce.is(re, 'string'))\r |
11127 | re = new RegExp(re, 'i');\r |
11128 | \r |
11129 | // Set style info on selected element\r |
11130 | if ((e = t.getSelectedElement()) && !ed.settings.force_span_wrappers)\r |
11131 | set(e, 1);\r |
11132 | else {\r |
11133 | // Generate wrappers and set styles on them\r |
11134 | d.execCommand('FontName', false, '__');\r |
11135 | each(dom.select('span,font'), function(n) {\r |
11136 | var sp, e;\r |
11137 | \r |
11138 | if (dom.getAttrib(n, 'face') == '__' || n.style.fontFamily === '__') {\r |
11139 | sp = dom.create(nn, {mce_new : '1'});\r |
11140 | \r |
11141 | set(sp);\r |
11142 | \r |
11143 | each (n.childNodes, function(n) {\r |
11144 | sp.appendChild(n.cloneNode(true));\r |
11145 | });\r |
11146 | \r |
11147 | dom.replace(sp, n);\r |
11148 | }\r |
11149 | });\r |
11150 | }\r |
11151 | \r |
11152 | // Remove wrappers inside new ones\r |
11153 | each(dom.select(nn).reverse(), function(n) {\r |
11154 | var p = n.parentNode;\r |
11155 | \r |
11156 | // Check if it's an old span in a new wrapper\r |
11157 | if (!dom.getAttrib(n, 'mce_new')) {\r |
11158 | // Find new wrapper\r |
11159 | p = dom.getParent(n, '*[mce_new]');\r |
11160 | \r |
11161 | if (p)\r |
11162 | dom.remove(n, 1);\r |
11163 | }\r |
11164 | });\r |
11165 | \r |
11166 | // Merge wrappers with parent wrappers\r |
11167 | each(dom.select(nn).reverse(), function(n) {\r |
11168 | var p = n.parentNode;\r |
11169 | \r |
11170 | if (!p || !dom.getAttrib(n, 'mce_new'))\r |
11171 | return;\r |
11172 | \r |
11173 | if (ed.settings.force_span_wrappers && p.nodeName != 'SPAN')\r |
11174 | return;\r |
11175 | \r |
11176 | // Has parent of the same type and only child\r |
11177 | if (p.nodeName == nn.toUpperCase() && p.childNodes.length == 1)\r |
11178 | return dom.remove(p, 1);\r |
11179 | \r |
11180 | // Has parent that is more suitable to have the class and only child\r |
11181 | if (n.nodeType == 1 && (!re || !re.test(p.nodeName)) && p.childNodes.length == 1) {\r |
11182 | set(p); // Set style info on parent instead\r |
11183 | dom.setAttrib(n, 'class', '');\r |
11184 | }\r |
11185 | });\r |
11186 | \r |
11187 | // Remove empty wrappers\r |
11188 | each(dom.select(nn).reverse(), function(n) {\r |
11189 | if (dom.getAttrib(n, 'mce_new') || (dom.getAttribs(n).length <= 1 && n.className === '')) {\r |
11190 | if (!dom.getAttrib(n, 'class') && !dom.getAttrib(n, 'style'))\r |
11191 | return dom.remove(n, 1);\r |
11192 | \r |
11193 | dom.setAttrib(n, 'mce_new', ''); // Remove mce_new marker\r |
11194 | }\r |
11195 | });\r |
11196 | \r |
11197 | s.moveToBookmark(b);\r |
11198 | },\r |
11199 | \r |
11200 | queryStateJustify : function(c, v) {\r |
11201 | var ed = this.editor, n = ed.selection.getNode(), dom = ed.dom;\r |
11202 | \r |
11203 | if (n && n.nodeName == 'IMG') {\r |
11204 | if (dom.getStyle(n, 'float') == v)\r |
11205 | return 1;\r |
11206 | \r |
11207 | return n.parentNode.style.textAlign == v;\r |
11208 | }\r |
11209 | \r |
11210 | n = dom.getParent(ed.selection.getStart(), function(n) {\r |
11211 | return n.nodeType == 1 && n.style.textAlign;\r |
11212 | });\r |
11213 | \r |
11214 | if (v == 'full')\r |
11215 | v = 'justify';\r |
11216 | \r |
11217 | if (ed.settings.inline_styles)\r |
11218 | return (n && n.style.textAlign == v);\r |
11219 | \r |
11220 | return this._queryState(c);\r |
11221 | },\r |
11222 | \r |
11223 | ForeColor : function(ui, v) {\r |
11224 | var ed = this.editor;\r |
11225 | \r |
11226 | if (ed.settings.convert_fonts_to_spans) {\r |
11227 | this._applyInlineStyle('span', {style : {color : v}});\r |
11228 | return;\r |
11229 | } else\r |
11230 | ed.getDoc().execCommand('ForeColor', false, v);\r |
11231 | },\r |
11232 | \r |
11233 | HiliteColor : function(ui, val) {\r |
11234 | var t = this, ed = t.editor, d = ed.getDoc();\r |
11235 | \r |
11236 | if (ed.settings.convert_fonts_to_spans) {\r |
11237 | this._applyInlineStyle('span', {style : {backgroundColor : val}});\r |
11238 | return;\r |
11239 | }\r |
11240 | \r |
11241 | function set(s) {\r |
11242 | if (!isGecko)\r |
11243 | return;\r |
11244 | \r |
11245 | try {\r |
11246 | // Try new Gecko method\r |
11247 | d.execCommand("styleWithCSS", 0, s);\r |
11248 | } catch (ex) {\r |
11249 | // Use old\r |
11250 | d.execCommand("useCSS", 0, !s);\r |
11251 | }\r |
11252 | };\r |
11253 | \r |
11254 | if (isGecko || isOpera) {\r |
11255 | set(true);\r |
11256 | d.execCommand('hilitecolor', false, val);\r |
11257 | set(false);\r |
11258 | } else\r |
11259 | d.execCommand('BackColor', false, val);\r |
11260 | },\r |
11261 | \r |
11262 | FormatBlock : function(ui, val) {\r |
11263 | var t = this, ed = t.editor, s = ed.selection, dom = ed.dom, bl, nb, b;\r |
11264 | \r |
11265 | function isBlock(n) {\r |
11266 | return /^(P|DIV|H[1-6]|ADDRESS|BLOCKQUOTE|PRE)$/.test(n.nodeName);\r |
11267 | };\r |
11268 | \r |
11269 | bl = dom.getParent(s.getNode(), function(n) {\r |
11270 | return isBlock(n);\r |
11271 | });\r |
11272 | \r |
11273 | // IE has an issue where it removes the parent div if you change format on the paragrah in <div><p>Content</p></div>\r |
11274 | // FF and Opera doesn't change parent DIV elements if you switch format\r |
11275 | if (bl) {\r |
11276 | if ((isIE && isBlock(bl.parentNode)) || bl.nodeName == 'DIV') {\r |
11277 | // Rename block element\r |
11278 | nb = ed.dom.create(val);\r |
11279 | \r |
11280 | each(dom.getAttribs(bl), function(v) {\r |
11281 | dom.setAttrib(nb, v.nodeName, dom.getAttrib(bl, v.nodeName));\r |
11282 | });\r |
11283 | \r |
11284 | b = s.getBookmark();\r |
11285 | dom.replace(nb, bl, 1);\r |
11286 | s.moveToBookmark(b);\r |
11287 | ed.nodeChanged();\r |
11288 | return;\r |
11289 | }\r |
11290 | }\r |
11291 | \r |
11292 | val = ed.settings.forced_root_block ? (val || '<p>') : val;\r |
11293 | \r |
11294 | if (val.indexOf('<') == -1)\r |
11295 | val = '<' + val + '>';\r |
11296 | \r |
11297 | if (tinymce.isGecko)\r |
11298 | val = val.replace(/<(div|blockquote|code|dt|dd|dl|samp)>/gi, '$1');\r |
11299 | \r |
11300 | ed.getDoc().execCommand('FormatBlock', false, val);\r |
11301 | },\r |
11302 | \r |
11303 | mceCleanup : function() {\r |
11304 | var ed = this.editor, s = ed.selection, b = s.getBookmark();\r |
11305 | ed.setContent(ed.getContent());\r |
11306 | s.moveToBookmark(b);\r |
11307 | },\r |
11308 | \r |
11309 | mceRemoveNode : function(ui, val) {\r |
11310 | var ed = this.editor, s = ed.selection, b, n = val || s.getNode();\r |
11311 | \r |
11312 | // Make sure that the body node isn't removed\r |
11313 | if (n == ed.getBody())\r |
11314 | return;\r |
11315 | \r |
11316 | b = s.getBookmark();\r |
11317 | ed.dom.remove(n, 1);\r |
11318 | s.moveToBookmark(b);\r |
11319 | ed.nodeChanged();\r |
11320 | },\r |
11321 | \r |
11322 | mceSelectNodeDepth : function(ui, val) {\r |
11323 | var ed = this.editor, s = ed.selection, c = 0;\r |
11324 | \r |
11325 | ed.dom.getParent(s.getNode(), function(n) {\r |
11326 | if (n.nodeType == 1 && c++ == val) {\r |
11327 | s.select(n);\r |
11328 | ed.nodeChanged();\r |
11329 | return false;\r |
11330 | }\r |
11331 | }, ed.getBody());\r |
11332 | },\r |
11333 | \r |
11334 | mceSelectNode : function(u, v) {\r |
11335 | this.editor.selection.select(v);\r |
11336 | },\r |
11337 | \r |
11338 | mceInsertContent : function(ui, val) {\r |
11339 | this.editor.selection.setContent(val);\r |
11340 | },\r |
11341 | \r |
11342 | mceInsertRawHTML : function(ui, val) {\r |
11343 | var ed = this.editor;\r |
11344 | \r |
11345 | ed.selection.setContent('tiny_mce_marker');\r |
11346 | ed.setContent(ed.getContent().replace(/tiny_mce_marker/g, val));\r |
11347 | },\r |
11348 | \r |
11349 | mceRepaint : function() {\r |
11350 | var s, b, e = this.editor;\r |
11351 | \r |
11352 | if (tinymce.isGecko) {\r |
11353 | try {\r |
11354 | s = e.selection;\r |
11355 | b = s.getBookmark(true);\r |
11356 | \r |
11357 | if (s.getSel())\r |
11358 | s.getSel().selectAllChildren(e.getBody());\r |
11359 | \r |
11360 | s.collapse(true);\r |
11361 | s.moveToBookmark(b);\r |
11362 | } catch (ex) {\r |
11363 | // Ignore\r |
11364 | }\r |
11365 | }\r |
11366 | },\r |
11367 | \r |
11368 | queryStateUnderline : function() {\r |
11369 | var ed = this.editor, n = ed.selection.getNode();\r |
11370 | \r |
11371 | if (n && n.nodeName == 'A')\r |
11372 | return false;\r |
11373 | \r |
11374 | return this._queryState('Underline');\r |
11375 | },\r |
11376 | \r |
11377 | queryStateOutdent : function() {\r |
11378 | var ed = this.editor, n;\r |
11379 | \r |
11380 | if (ed.settings.inline_styles) {\r |
11381 | if ((n = ed.dom.getParent(ed.selection.getStart(), ed.dom.isBlock)) && parseInt(n.style.paddingLeft) > 0)\r |
11382 | return true;\r |
11383 | \r |
11384 | if ((n = ed.dom.getParent(ed.selection.getEnd(), ed.dom.isBlock)) && parseInt(n.style.paddingLeft) > 0)\r |
11385 | return true;\r |
11386 | }\r |
11387 | \r |
11388 | return this.queryStateInsertUnorderedList() || this.queryStateInsertOrderedList() || (!ed.settings.inline_styles && !!ed.dom.getParent(ed.selection.getNode(), 'BLOCKQUOTE'));\r |
11389 | },\r |
11390 | \r |
11391 | queryStateInsertUnorderedList : function() {\r |
11392 | return this.editor.dom.getParent(this.editor.selection.getNode(), 'UL');\r |
11393 | },\r |
11394 | \r |
11395 | queryStateInsertOrderedList : function() {\r |
11396 | return this.editor.dom.getParent(this.editor.selection.getNode(), 'OL');\r |
11397 | },\r |
11398 | \r |
11399 | queryStatemceBlockQuote : function() {\r |
11400 | return !!this.editor.dom.getParent(this.editor.selection.getStart(), function(n) {return n.nodeName === 'BLOCKQUOTE';});\r |
11401 | },\r |
11402 | \r |
11403 | _applyInlineStyle : function(na, at, op) {\r |
11404 | var t = this, ed = t.editor, dom = ed.dom, bm, lo = {}, kh, found;\r |
11405 | \r |
11406 | na = na.toUpperCase();\r |
11407 | \r |
11408 | if (op && op.check_classes && at['class'])\r |
11409 | op.check_classes.push(at['class']);\r |
11410 | \r |
11411 | function removeEmpty() {\r |
11412 | each(dom.select(na).reverse(), function(n) {\r |
11413 | var c = 0;\r |
11414 | \r |
11415 | // Check if there is any attributes\r |
11416 | each(dom.getAttribs(n), function(an) {\r |
11417 | if (an.nodeName.substring(0, 1) != '_' && dom.getAttrib(n, an.nodeName) != '') {\r |
11418 | //console.log(dom.getOuterHTML(n), dom.getAttrib(n, an.nodeName));\r |
11419 | c++;\r |
11420 | }\r |
11421 | });\r |
11422 | \r |
11423 | // No attributes then remove the element and keep the children\r |
11424 | if (c == 0)\r |
11425 | dom.remove(n, 1);\r |
11426 | });\r |
11427 | };\r |
11428 | \r |
11429 | function replaceFonts() {\r |
11430 | var bm;\r |
11431 | \r |
11432 | each(dom.select('span,font'), function(n) {\r |
11433 | if (n.style.fontFamily == 'mceinline' || n.face == 'mceinline') {\r |
11434 | if (!bm)\r |
11435 | bm = ed.selection.getBookmark();\r |
11436 | \r |
11437 | at._mce_new = '1';\r |
11438 | dom.replace(dom.create(na, at), n, 1);\r |
11439 | }\r |
11440 | });\r |
11441 | \r |
11442 | // Remove redundant elements\r |
11443 | each(dom.select(na + '[_mce_new]'), function(n) {\r |
11444 | function removeStyle(n) {\r |
11445 | if (n.nodeType == 1) {\r |
11446 | each(at.style, function(v, k) {\r |
11447 | dom.setStyle(n, k, '');\r |
11448 | });\r |
11449 | \r |
11450 | // Remove spans with the same class or marked classes\r |
11451 | if (at['class'] && n.className && op) {\r |
11452 | each(op.check_classes, function(c) {\r |
11453 | if (dom.hasClass(n, c))\r |
11454 | dom.removeClass(n, c);\r |
11455 | });\r |
11456 | }\r |
11457 | }\r |
11458 | };\r |
11459 | \r |
11460 | // Remove specified style information from child elements\r |
11461 | each(dom.select(na, n), removeStyle);\r |
11462 | \r |
11463 | // Remove the specified style information on parent if current node is only child (IE)\r |
11464 | if (n.parentNode && n.parentNode.nodeType == 1 && n.parentNode.childNodes.length == 1)\r |
11465 | removeStyle(n.parentNode);\r |
11466 | \r |
11467 | // Remove the child elements style info if a parent already has it\r |
11468 | dom.getParent(n.parentNode, function(pn) {\r |
11469 | if (pn.nodeType == 1) {\r |
11470 | if (at.style) {\r |
11471 | each(at.style, function(v, k) {\r |
11472 | var sv;\r |
11473 | \r |
11474 | if (!lo[k] && (sv = dom.getStyle(pn, k))) {\r |
11475 | if (sv === v)\r |
11476 | dom.setStyle(n, k, '');\r |
11477 | \r |
11478 | lo[k] = 1;\r |
11479 | }\r |
11480 | });\r |
11481 | }\r |
11482 | \r |
11483 | // Remove spans with the same class or marked classes\r |
11484 | if (at['class'] && pn.className && op) {\r |
11485 | each(op.check_classes, function(c) {\r |
11486 | if (dom.hasClass(pn, c))\r |
11487 | dom.removeClass(n, c);\r |
11488 | });\r |
11489 | }\r |
11490 | }\r |
11491 | \r |
11492 | return false;\r |
11493 | });\r |
11494 | \r |
11495 | n.removeAttribute('_mce_new');\r |
11496 | });\r |
11497 | \r |
11498 | removeEmpty();\r |
11499 | ed.selection.moveToBookmark(bm);\r |
11500 | \r |
11501 | return !!bm;\r |
11502 | };\r |
11503 | \r |
11504 | // Create inline elements\r |
11505 | ed.focus();\r |
11506 | ed.getDoc().execCommand('FontName', false, 'mceinline');\r |
11507 | replaceFonts();\r |
11508 | \r |
11509 | if (kh = t._applyInlineStyle.keyhandler) {\r |
11510 | ed.onKeyUp.remove(kh);\r |
11511 | ed.onKeyPress.remove(kh);\r |
11512 | ed.onKeyDown.remove(kh);\r |
11513 | ed.onSetContent.remove(t._applyInlineStyle.chandler);\r |
11514 | }\r |
11515 | \r |
11516 | if (ed.selection.isCollapsed()) {\r |
11517 | // IE will format the current word so this code can't be executed on that browser\r |
11518 | if (!isIE) {\r |
11519 | each(dom.getParents(ed.selection.getNode(), 'span'), function(n) {\r |
11520 | each(at.style, function(v, k) {\r |
11521 | var kv;\r |
11522 | \r |
11523 | if (kv = dom.getStyle(n, k)) {\r |
11524 | if (kv == v) {\r |
11525 | dom.setStyle(n, k, '');\r |
11526 | found = 2;\r |
11527 | return false;\r |
11528 | }\r |
11529 | \r |
11530 | found = 1;\r |
11531 | return false;\r |
11532 | }\r |
11533 | });\r |
11534 | \r |
11535 | if (found)\r |
11536 | return false;\r |
11537 | });\r |
11538 | \r |
11539 | if (found == 2) {\r |
11540 | bm = ed.selection.getBookmark();\r |
11541 | \r |
11542 | removeEmpty();\r |
11543 | \r |
11544 | ed.selection.moveToBookmark(bm);\r |
11545 | \r |
11546 | // Node change needs to be detached since the onselect event\r |
11547 | // for the select box will run the onclick handler after onselect call. Todo: Add a nicer fix!\r |
11548 | window.setTimeout(function() {\r |
11549 | ed.nodeChanged();\r |
11550 | }, 1);\r |
11551 | \r |
11552 | return;\r |
11553 | }\r |
11554 | }\r |
11555 | \r |
11556 | // Start collecting styles\r |
11557 | t._pendingStyles = tinymce.extend(t._pendingStyles || {}, at.style);\r |
11558 | \r |
11559 | t._applyInlineStyle.chandler = ed.onSetContent.add(function() {\r |
11560 | delete t._pendingStyles;\r |
11561 | });\r |
11562 | \r |
11563 | t._applyInlineStyle.keyhandler = kh = function(e) {\r |
11564 | // Use pending styles\r |
11565 | if (t._pendingStyles) {\r |
11566 | at.style = t._pendingStyles;\r |
11567 | delete t._pendingStyles;\r |
11568 | }\r |
11569 | \r |
11570 | if (replaceFonts()) {\r |
11571 | ed.onKeyDown.remove(t._applyInlineStyle.keyhandler);\r |
11572 | ed.onKeyPress.remove(t._applyInlineStyle.keyhandler);\r |
11573 | }\r |
11574 | \r |
11575 | if (e.type == 'keyup')\r |
11576 | ed.onKeyUp.remove(t._applyInlineStyle.keyhandler);\r |
11577 | };\r |
11578 | \r |
11579 | ed.onKeyDown.add(kh);\r |
11580 | ed.onKeyPress.add(kh);\r |
11581 | ed.onKeyUp.add(kh);\r |
11582 | } else\r |
11583 | t._pendingStyles = 0;\r |
11584 | }\r |
11585 | });\r |
11586 | })(tinymce);(function(tinymce) {\r |
11587 | tinymce.create('tinymce.UndoManager', {\r |
11588 | index : 0,\r |
11589 | data : null,\r |
11590 | typing : 0,\r |
11591 | \r |
11592 | UndoManager : function(ed) {\r |
11593 | var t = this, Dispatcher = tinymce.util.Dispatcher;\r |
11594 | \r |
11595 | t.editor = ed;\r |
11596 | t.data = [];\r |
11597 | t.onAdd = new Dispatcher(this);\r |
11598 | t.onUndo = new Dispatcher(this);\r |
11599 | t.onRedo = new Dispatcher(this);\r |
11600 | },\r |
11601 | \r |
11602 | add : function(l) {\r |
11603 | var t = this, i, ed = t.editor, b, s = ed.settings, la;\r |
11604 | \r |
11605 | l = l || {};\r |
11606 | l.content = l.content || ed.getContent({format : 'raw', no_events : 1});\r |
11607 | \r |
11608 | // Add undo level if needed\r |
11609 | l.content = l.content.replace(/^\s*|\s*$/g, '');\r |
11610 | la = t.data[t.index > 0 && (t.index == 0 || t.index == t.data.length) ? t.index - 1 : t.index];\r |
11611 | if (!l.initial && la && l.content == la.content)\r |
11612 | return null;\r |
11613 | \r |
11614 | // Time to compress\r |
11615 | if (s.custom_undo_redo_levels) {\r |
11616 | if (t.data.length > s.custom_undo_redo_levels) {\r |
11617 | for (i = 0; i < t.data.length - 1; i++)\r |
11618 | t.data[i] = t.data[i + 1];\r |
11619 | \r |
11620 | t.data.length--;\r |
11621 | t.index = t.data.length;\r |
11622 | }\r |
11623 | }\r |
11624 | \r |
11625 | if (s.custom_undo_redo_restore_selection && !l.initial)\r |
11626 | l.bookmark = b = l.bookmark || ed.selection.getBookmark();\r |
11627 | \r |
11628 | if (t.index < t.data.length)\r |
11629 | t.index++;\r |
11630 | \r |
11631 | // Only initial marked undo levels should be allowed as first item\r |
11632 | // This to workaround a bug with Firefox and the blur event\r |
11633 | if (t.data.length === 0 && !l.initial)\r |
11634 | return null;\r |
11635 | \r |
11636 | // Add level\r |
11637 | t.data.length = t.index + 1;\r |
11638 | t.data[t.index++] = l;\r |
11639 | \r |
11640 | if (l.initial)\r |
11641 | t.index = 0;\r |
11642 | \r |
11643 | // Set initial bookmark use first real undo level\r |
11644 | if (t.data.length == 2 && t.data[0].initial)\r |
11645 | t.data[0].bookmark = b;\r |
11646 | \r |
11647 | t.onAdd.dispatch(t, l);\r |
11648 | ed.isNotDirty = 0;\r |
11649 | \r |
11650 | //console.dir(t.data);\r |
11651 | \r |
11652 | return l;\r |
11653 | },\r |
11654 | \r |
11655 | undo : function() {\r |
11656 | var t = this, ed = t.editor, l = l, i;\r |
11657 | \r |
11658 | if (t.typing) {\r |
11659 | t.add();\r |
11660 | t.typing = 0;\r |
11661 | }\r |
11662 | \r |
11663 | if (t.index > 0) {\r |
11664 | // If undo on last index then take snapshot\r |
11665 | if (t.index == t.data.length && t.index > 1) {\r |
11666 | i = t.index;\r |
11667 | t.typing = 0;\r |
11668 | \r |
11669 | if (!t.add())\r |
11670 | t.index = i;\r |
11671 | \r |
11672 | --t.index;\r |
11673 | }\r |
11674 | \r |
11675 | l = t.data[--t.index];\r |
11676 | ed.setContent(l.content, {format : 'raw'});\r |
11677 | ed.selection.moveToBookmark(l.bookmark);\r |
11678 | \r |
11679 | t.onUndo.dispatch(t, l);\r |
11680 | }\r |
11681 | \r |
11682 | return l;\r |
11683 | },\r |
11684 | \r |
11685 | redo : function() {\r |
11686 | var t = this, ed = t.editor, l = null;\r |
11687 | \r |
11688 | if (t.index < t.data.length - 1) {\r |
11689 | l = t.data[++t.index];\r |
11690 | ed.setContent(l.content, {format : 'raw'});\r |
11691 | ed.selection.moveToBookmark(l.bookmark);\r |
11692 | \r |
11693 | t.onRedo.dispatch(t, l);\r |
11694 | }\r |
11695 | \r |
11696 | return l;\r |
11697 | },\r |
11698 | \r |
11699 | clear : function() {\r |
11700 | var t = this;\r |
11701 | \r |
11702 | t.data = [];\r |
11703 | t.index = 0;\r |
11704 | t.typing = 0;\r |
11705 | t.add({initial : true});\r |
11706 | },\r |
11707 | \r |
11708 | hasUndo : function() {\r |
11709 | return this.index != 0 || this.typing;\r |
11710 | },\r |
11711 | \r |
11712 | hasRedo : function() {\r |
11713 | return this.index < this.data.length - 1;\r |
11714 | }\r |
11715 | });\r |
11716 | })(tinymce);\r |
11717 | (function(tinymce) {\r |
11718 | // Shorten names\r |
11719 | var Event, isIE, isGecko, isOpera, each, extend;\r |
11720 | \r |
11721 | Event = tinymce.dom.Event;\r |
11722 | isIE = tinymce.isIE;\r |
11723 | isGecko = tinymce.isGecko;\r |
11724 | isOpera = tinymce.isOpera;\r |
11725 | each = tinymce.each;\r |
11726 | extend = tinymce.extend;\r |
11727 | \r |
11728 | // Checks if the selection/caret is at the end of the specified block element\r |
11729 | function isAtEnd(rng, par) {\r |
11730 | var rng2 = par.ownerDocument.createRange();\r |
11731 | \r |
11732 | rng2.setStart(rng.endContainer, rng.endOffset);\r |
11733 | rng2.setEndAfter(par);\r |
11734 | \r |
11735 | // Get number of characters to the right of the cursor if it's zero then we are at the end and need to merge the next block element\r |
11736 | return rng2.cloneContents().textContent.length == 0;\r |
11737 | };\r |
11738 | \r |
11739 | function isEmpty(n) {\r |
11740 | n = n.innerHTML;\r |
11741 | \r |
11742 | n = n.replace(/<(img|hr|table|input|select|textarea)[ \>]/gi, '-'); // Keep these convert them to - chars\r |
11743 | n = n.replace(/<[^>]+>/g, ''); // Remove all tags\r |
11744 | \r |
11745 | return n.replace(/[ \t\r\n]+/g, '') == '';\r |
11746 | };\r |
11747 | \r |
11748 | tinymce.create('tinymce.ForceBlocks', {\r |
11749 | ForceBlocks : function(ed) {\r |
11750 | var t = this, s = ed.settings, elm;\r |
11751 | \r |
11752 | t.editor = ed;\r |
11753 | t.dom = ed.dom;\r |
11754 | elm = (s.forced_root_block || 'p').toLowerCase();\r |
11755 | s.element = elm.toUpperCase();\r |
11756 | \r |
11757 | ed.onPreInit.add(t.setup, t);\r |
11758 | \r |
11759 | t.reOpera = new RegExp('(\\u00a0| | )<\/' + elm + '>', 'gi');\r |
11760 | t.rePadd = new RegExp('<p( )([^>]+)><\\\/p>|<p( )([^>]+)\\\/>|<p( )([^>]+)>\\s+<\\\/p>|<p><\\\/p>|<p\\\/>|<p>\\s+<\\\/p>'.replace(/p/g, elm), 'gi');\r |
11761 | t.reNbsp2BR1 = new RegExp('<p( )([^>]+)>[\\s\\u00a0]+<\\\/p>|<p>[\\s\\u00a0]+<\\\/p>'.replace(/p/g, elm), 'gi');\r |
11762 | t.reNbsp2BR2 = new RegExp('<%p()([^>]+)>( | )<\\\/%p>|<%p>( | )<\\\/%p>'.replace(/%p/g, elm), 'gi');\r |
11763 | t.reBR2Nbsp = new RegExp('<p( )([^>]+)>\\s*<br \\\/>\\s*<\\\/p>|<p>\\s*<br \\\/>\\s*<\\\/p>'.replace(/p/g, elm), 'gi');\r |
11764 | \r |
11765 | function padd(ed, o) {\r |
11766 | if (isOpera)\r |
11767 | o.content = o.content.replace(t.reOpera, '</' + elm + '>');\r |
11768 | \r |
11769 | o.content = o.content.replace(t.rePadd, '<' + elm + '$1$2$3$4$5$6>\u00a0</' + elm + '>');\r |
11770 | \r |
11771 | if (!isIE && !isOpera && o.set) {\r |
11772 | // Use instead of BR in padded paragraphs\r |
11773 | o.content = o.content.replace(t.reNbsp2BR1, '<' + elm + '$1$2><br /></' + elm + '>');\r |
11774 | o.content = o.content.replace(t.reNbsp2BR2, '<' + elm + '$1$2><br /></' + elm + '>');\r |
11775 | } else\r |
11776 | o.content = o.content.replace(t.reBR2Nbsp, '<' + elm + '$1$2>\u00a0</' + elm + '>');\r |
11777 | };\r |
11778 | \r |
11779 | ed.onBeforeSetContent.add(padd);\r |
11780 | ed.onPostProcess.add(padd);\r |
11781 | \r |
11782 | if (s.forced_root_block) {\r |
11783 | ed.onInit.add(t.forceRoots, t);\r |
11784 | ed.onSetContent.add(t.forceRoots, t);\r |
11785 | ed.onBeforeGetContent.add(t.forceRoots, t);\r |
11786 | }\r |
11787 | },\r |
11788 | \r |
11789 | setup : function() {\r |
11790 | var t = this, ed = t.editor, s = ed.settings;\r |
11791 | \r |
11792 | // Force root blocks when typing and when getting output\r |
11793 | if (s.forced_root_block) {\r |
11794 | ed.onKeyUp.add(t.forceRoots, t);\r |
11795 | ed.onPreProcess.add(t.forceRoots, t);\r |
11796 | }\r |
11797 | \r |
11798 | if (s.force_br_newlines) {\r |
11799 | // Force IE to produce BRs on enter\r |
11800 | if (isIE) {\r |
11801 | ed.onKeyPress.add(function(ed, e) {\r |
11802 | var n, s = ed.selection;\r |
11803 | \r |
11804 | if (e.keyCode == 13 && s.getNode().nodeName != 'LI') {\r |
11805 | s.setContent('<br id="__" /> ', {format : 'raw'});\r |
11806 | n = ed.dom.get('__');\r |
11807 | n.removeAttribute('id');\r |
11808 | s.select(n);\r |
11809 | s.collapse();\r |
11810 | return Event.cancel(e);\r |
11811 | }\r |
11812 | });\r |
11813 | }\r |
11814 | \r |
11815 | return;\r |
11816 | }\r |
11817 | \r |
11818 | if (!isIE && s.force_p_newlines) {\r |
11819 | /* ed.onPreProcess.add(function(ed, o) {\r |
11820 | each(ed.dom.select('br', o.node), function(n) {\r |
11821 | var p = n.parentNode;\r |
11822 | \r |
11823 | // Replace <p><br /></p> with <p> </p>\r |
11824 | if (p && p.nodeName == 'p' && (p.childNodes.length == 1 || p.lastChild == n)) {\r |
11825 | p.replaceChild(ed.getDoc().createTextNode('\u00a0'), n);\r |
11826 | }\r |
11827 | });\r |
11828 | });*/\r |
11829 | \r |
11830 | ed.onKeyPress.add(function(ed, e) {\r |
11831 | if (e.keyCode == 13 && !e.shiftKey) {\r |
11832 | if (!t.insertPara(e))\r |
11833 | Event.cancel(e);\r |
11834 | }\r |
11835 | });\r |
11836 | \r |
11837 | if (isGecko) {\r |
11838 | ed.onKeyDown.add(function(ed, e) {\r |
11839 | if ((e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey)\r |
11840 | t.backspaceDelete(e, e.keyCode == 8);\r |
11841 | });\r |
11842 | }\r |
11843 | }\r |
11844 | \r |
11845 | function ren(rn, na) {\r |
11846 | var ne = ed.dom.create(na);\r |
11847 | \r |
11848 | each(rn.attributes, function(a) {\r |
11849 | if (a.specified && a.nodeValue)\r |
11850 | ne.setAttribute(a.nodeName.toLowerCase(), a.nodeValue);\r |
11851 | });\r |
11852 | \r |
11853 | each(rn.childNodes, function(n) {\r |
11854 | ne.appendChild(n.cloneNode(true));\r |
11855 | });\r |
11856 | \r |
11857 | rn.parentNode.replaceChild(ne, rn);\r |
11858 | \r |
11859 | return ne;\r |
11860 | };\r |
11861 | \r |
11862 | // Padd empty inline elements within block elements\r |
11863 | // For example: <p><strong><em></em></strong></p> becomes <p><strong><em> </em></strong></p>\r |
11864 | ed.onPreProcess.add(function(ed, o) {\r |
11865 | each(ed.dom.select('p,h1,h2,h3,h4,h5,h6,div', o.node), function(p) {\r |
11866 | if (isEmpty(p)) {\r |
11867 | each(ed.dom.select('span,em,strong,b,i', o.node), function(n) {\r |
11868 | if (!n.hasChildNodes()) {\r |
11869 | n.appendChild(ed.getDoc().createTextNode('\u00a0'));\r |
11870 | return false; // Break the loop one padding is enough\r |
11871 | }\r |
11872 | });\r |
11873 | }\r |
11874 | });\r |
11875 | });\r |
11876 | \r |
11877 | // IE specific fixes\r |
11878 | if (isIE) {\r |
11879 | // Replaces IE:s auto generated paragraphs with the specified element name\r |
11880 | if (s.element != 'P') {\r |
11881 | ed.onKeyPress.add(function(ed, e) {\r |
11882 | t.lastElm = ed.selection.getNode().nodeName;\r |
11883 | });\r |
11884 | \r |
11885 | ed.onKeyUp.add(function(ed, e) {\r |
11886 | var bl, sel = ed.selection, n = sel.getNode(), b = ed.getBody();\r |
11887 | \r |
11888 | if (b.childNodes.length === 1 && n.nodeName == 'P') {\r |
11889 | n = ren(n, s.element);\r |
11890 | sel.select(n);\r |
11891 | sel.collapse();\r |
11892 | ed.nodeChanged();\r |
11893 | } else if (e.keyCode == 13 && !e.shiftKey && t.lastElm != 'P') {\r |
11894 | bl = ed.dom.getParent(n, 'p');\r |
11895 | \r |
11896 | if (bl) {\r |
11897 | ren(bl, s.element);\r |
11898 | ed.nodeChanged();\r |
11899 | }\r |
11900 | }\r |
11901 | });\r |
11902 | }\r |
11903 | }\r |
11904 | },\r |
11905 | \r |
11906 | find : function(n, t, s) {\r |
11907 | var ed = this.editor, w = ed.getDoc().createTreeWalker(n, 4, null, false), c = -1;\r |
11908 | \r |
11909 | while (n = w.nextNode()) {\r |
11910 | c++;\r |
11911 | \r |
11912 | // Index by node\r |
11913 | if (t == 0 && n == s)\r |
11914 | return c;\r |
11915 | \r |
11916 | // Node by index\r |
11917 | if (t == 1 && c == s)\r |
11918 | return n;\r |
11919 | }\r |
11920 | \r |
11921 | return -1;\r |
11922 | },\r |
11923 | \r |
11924 | forceRoots : function(ed, e) {\r |
11925 | var t = this, ed = t.editor, b = ed.getBody(), d = ed.getDoc(), se = ed.selection, s = se.getSel(), r = se.getRng(), si = -2, ei, so, eo, tr, c = -0xFFFFFF;\r |
11926 | var nx, bl, bp, sp, le, nl = b.childNodes, i, n, eid;\r |
11927 | \r |
11928 | // Fix for bug #1863847\r |
11929 | //if (e && e.keyCode == 13)\r |
11930 | // return true;\r |
11931 | \r |
11932 | // Wrap non blocks into blocks\r |
11933 | for (i = nl.length - 1; i >= 0; i--) {\r |
11934 | nx = nl[i];\r |
11935 | \r |
11936 | // Is text or non block element\r |
11937 | if (nx.nodeType === 3 || (!t.dom.isBlock(nx) && nx.nodeType !== 8 && !/^(script|mce:script|style|mce:style)$/i.test(nx.nodeName))) {\r |
11938 | if (!bl) {\r |
11939 | // Create new block but ignore whitespace\r |
11940 | if (nx.nodeType != 3 || /[^\s]/g.test(nx.nodeValue)) {\r |
11941 | // Store selection\r |
11942 | if (si == -2 && r) {\r |
11943 | if (!isIE) {\r |
11944 | // If selection is element then mark it\r |
11945 | if (r.startContainer.nodeType == 1 && (n = r.startContainer.childNodes[r.startOffset]) && n.nodeType == 1) {\r |
11946 | // Save the id of the selected element\r |
11947 | eid = n.getAttribute("id");\r |
11948 | n.setAttribute("id", "__mce");\r |
11949 | } else {\r |
11950 | // If element is inside body, might not be the case in contentEdiable mode\r |
11951 | if (ed.dom.getParent(r.startContainer, function(e) {return e === b;})) {\r |
11952 | so = r.startOffset;\r |
11953 | eo = r.endOffset;\r |
11954 | si = t.find(b, 0, r.startContainer);\r |
11955 | ei = t.find(b, 0, r.endContainer);\r |
11956 | }\r |
11957 | }\r |
11958 | } else {\r |
11959 | tr = d.body.createTextRange();\r |
11960 | tr.moveToElementText(b);\r |
11961 | tr.collapse(1);\r |
11962 | bp = tr.move('character', c) * -1;\r |
11963 | \r |
11964 | tr = r.duplicate();\r |
11965 | tr.collapse(1);\r |
11966 | sp = tr.move('character', c) * -1;\r |
11967 | \r |
11968 | tr = r.duplicate();\r |
11969 | tr.collapse(0);\r |
11970 | le = (tr.move('character', c) * -1) - sp;\r |
11971 | \r |
11972 | si = sp - bp;\r |
11973 | ei = le;\r |
11974 | }\r |
11975 | }\r |
11976 | \r |
11977 | // Uses replaceChild instead of cloneNode since it removes selected attribute from option elements on IE\r |
11978 | // See: http://support.microsoft.com/kb/829907\r |
11979 | bl = ed.dom.create(ed.settings.forced_root_block);\r |
11980 | nx.parentNode.replaceChild(bl, nx);\r |
11981 | bl.appendChild(nx);\r |
11982 | }\r |
11983 | } else {\r |
11984 | if (bl.hasChildNodes())\r |
11985 | bl.insertBefore(nx, bl.firstChild);\r |
11986 | else\r |
11987 | bl.appendChild(nx);\r |
11988 | }\r |
11989 | } else\r |
11990 | bl = null; // Time to create new block\r |
11991 | }\r |
11992 | \r |
11993 | // Restore selection\r |
11994 | if (si != -2) {\r |
11995 | if (!isIE) {\r |
11996 | bl = b.getElementsByTagName(ed.settings.element)[0];\r |
11997 | r = d.createRange();\r |
11998 | \r |
11999 | // Select last location or generated block\r |
12000 | if (si != -1)\r |
12001 | r.setStart(t.find(b, 1, si), so);\r |
12002 | else\r |
12003 | r.setStart(bl, 0);\r |
12004 | \r |
12005 | // Select last location or generated block\r |
12006 | if (ei != -1)\r |
12007 | r.setEnd(t.find(b, 1, ei), eo);\r |
12008 | else\r |
12009 | r.setEnd(bl, 0);\r |
12010 | \r |
12011 | if (s) {\r |
12012 | s.removeAllRanges();\r |
12013 | s.addRange(r);\r |
12014 | }\r |
12015 | } else {\r |
12016 | try {\r |
12017 | r = s.createRange();\r |
12018 | r.moveToElementText(b);\r |
12019 | r.collapse(1);\r |
12020 | r.moveStart('character', si);\r |
12021 | r.moveEnd('character', ei);\r |
12022 | r.select();\r |
12023 | } catch (ex) {\r |
12024 | // Ignore\r |
12025 | }\r |
12026 | }\r |
12027 | } else if (!isIE && (n = ed.dom.get('__mce'))) {\r |
12028 | // Restore the id of the selected element\r |
12029 | if (eid)\r |
12030 | n.setAttribute('id', eid);\r |
12031 | else\r |
12032 | n.removeAttribute('id');\r |
12033 | \r |
12034 | // Move caret before selected element\r |
12035 | r = d.createRange();\r |
12036 | r.setStartBefore(n);\r |
12037 | r.setEndBefore(n);\r |
12038 | se.setRng(r);\r |
12039 | }\r |
12040 | },\r |
12041 | \r |
12042 | getParentBlock : function(n) {\r |
12043 | var d = this.dom;\r |
12044 | \r |
12045 | return d.getParent(n, d.isBlock);\r |
12046 | },\r |
12047 | \r |
12048 | insertPara : function(e) {\r |
12049 | var t = this, ed = t.editor, dom = ed.dom, d = ed.getDoc(), se = ed.settings, s = ed.selection.getSel(), r = s.getRangeAt(0), b = d.body;\r |
12050 | var rb, ra, dir, sn, so, en, eo, sb, eb, bn, bef, aft, sc, ec, n, vp = dom.getViewPort(ed.getWin()), y, ch, car;\r |
12051 | \r |
12052 | // If root blocks are forced then use Operas default behavior since it's really good\r |
12053 | // Removed due to bug: #1853816\r |
12054 | // if (se.forced_root_block && isOpera)\r |
12055 | // return true;\r |
12056 | \r |
12057 | // Setup before range\r |
12058 | rb = d.createRange();\r |
12059 | \r |
12060 | // If is before the first block element and in body, then move it into first block element\r |
12061 | rb.setStart(s.anchorNode, s.anchorOffset);\r |
12062 | rb.collapse(true);\r |
12063 | \r |
12064 | // Setup after range\r |
12065 | ra = d.createRange();\r |
12066 | \r |
12067 | // If is before the first block element and in body, then move it into first block element\r |
12068 | ra.setStart(s.focusNode, s.focusOffset);\r |
12069 | ra.collapse(true);\r |
12070 | \r |
12071 | // Setup start/end points\r |
12072 | dir = rb.compareBoundaryPoints(rb.START_TO_END, ra) < 0;\r |
12073 | sn = dir ? s.anchorNode : s.focusNode;\r |
12074 | so = dir ? s.anchorOffset : s.focusOffset;\r |
12075 | en = dir ? s.focusNode : s.anchorNode;\r |
12076 | eo = dir ? s.focusOffset : s.anchorOffset;\r |
12077 | \r |
12078 | // If selection is in empty table cell\r |
12079 | if (sn === en && /^(TD|TH)$/.test(sn.nodeName)) {\r |
12080 | if (sn.firstChild.nodeName == 'BR')\r |
12081 | dom.remove(sn.firstChild); // Remove BR\r |
12082 | \r |
12083 | // Create two new block elements\r |
12084 | if (sn.childNodes.length == 0) {\r |
12085 | ed.dom.add(sn, se.element, null, '<br />');\r |
12086 | aft = ed.dom.add(sn, se.element, null, '<br />');\r |
12087 | } else {\r |
12088 | n = sn.innerHTML;\r |
12089 | sn.innerHTML = '';\r |
12090 | ed.dom.add(sn, se.element, null, n);\r |
12091 | aft = ed.dom.add(sn, se.element, null, '<br />');\r |
12092 | }\r |
12093 | \r |
12094 | // Move caret into the last one\r |
12095 | r = d.createRange();\r |
12096 | r.selectNodeContents(aft);\r |
12097 | r.collapse(1);\r |
12098 | ed.selection.setRng(r);\r |
12099 | \r |
12100 | return false;\r |
12101 | }\r |
12102 | \r |
12103 | // If the caret is in an invalid location in FF we need to move it into the first block\r |
12104 | if (sn == b && en == b && b.firstChild && ed.dom.isBlock(b.firstChild)) {\r |
12105 | sn = en = sn.firstChild;\r |
12106 | so = eo = 0;\r |
12107 | rb = d.createRange();\r |
12108 | rb.setStart(sn, 0);\r |
12109 | ra = d.createRange();\r |
12110 | ra.setStart(en, 0);\r |
12111 | }\r |
12112 | \r |
12113 | // Never use body as start or end node\r |
12114 | sn = sn.nodeName == "HTML" ? d.body : sn; // Fix for Opera bug: https://bugs.opera.com/show_bug.cgi?id=273224&comments=yes\r |
12115 | sn = sn.nodeName == "BODY" ? sn.firstChild : sn;\r |
12116 | en = en.nodeName == "HTML" ? d.body : en; // Fix for Opera bug: https://bugs.opera.com/show_bug.cgi?id=273224&comments=yes\r |
12117 | en = en.nodeName == "BODY" ? en.firstChild : en;\r |
12118 | \r |
12119 | // Get start and end blocks\r |
12120 | sb = t.getParentBlock(sn);\r |
12121 | eb = t.getParentBlock(en);\r |
12122 | bn = sb ? sb.nodeName : se.element; // Get block name to create\r |
12123 | \r |
12124 | // Return inside list use default browser behavior\r |
12125 | if (t.dom.getParent(sb, 'ol,ul,pre'))\r |
12126 | return true;\r |
12127 | \r |
12128 | // If caption or absolute layers then always generate new blocks within\r |
12129 | if (sb && (sb.nodeName == 'CAPTION' || /absolute|relative|fixed/gi.test(dom.getStyle(sb, 'position', 1)))) {\r |
12130 | bn = se.element;\r |
12131 | sb = null;\r |
12132 | }\r |
12133 | \r |
12134 | // If caption or absolute layers then always generate new blocks within\r |
12135 | if (eb && (eb.nodeName == 'CAPTION' || /absolute|relative|fixed/gi.test(dom.getStyle(sb, 'position', 1)))) {\r |
12136 | bn = se.element;\r |
12137 | eb = null;\r |
12138 | }\r |
12139 | \r |
12140 | // Use P instead\r |
12141 | if (/(TD|TABLE|TH|CAPTION)/.test(bn) || (sb && bn == "DIV" && /left|right/gi.test(dom.getStyle(sb, 'float', 1)))) {\r |
12142 | bn = se.element;\r |
12143 | sb = eb = null;\r |
12144 | }\r |
12145 | \r |
12146 | // Setup new before and after blocks\r |
12147 | bef = (sb && sb.nodeName == bn) ? sb.cloneNode(0) : ed.dom.create(bn);\r |
12148 | aft = (eb && eb.nodeName == bn) ? eb.cloneNode(0) : ed.dom.create(bn);\r |
12149 | \r |
12150 | // Remove id from after clone\r |
12151 | aft.removeAttribute('id');\r |
12152 | \r |
12153 | // Is header and cursor is at the end, then force paragraph under\r |
12154 | if (/^(H[1-6])$/.test(bn) && isAtEnd(r, sb))\r |
12155 | aft = ed.dom.create(se.element);\r |
12156 | \r |
12157 | // Find start chop node\r |
12158 | n = sc = sn;\r |
12159 | do {\r |
12160 | if (n == b || n.nodeType == 9 || t.dom.isBlock(n) || /(TD|TABLE|TH|CAPTION)/.test(n.nodeName))\r |
12161 | break;\r |
12162 | \r |
12163 | sc = n;\r |
12164 | } while ((n = n.previousSibling ? n.previousSibling : n.parentNode));\r |
12165 | \r |
12166 | // Find end chop node\r |
12167 | n = ec = en;\r |
12168 | do {\r |
12169 | if (n == b || n.nodeType == 9 || t.dom.isBlock(n) || /(TD|TABLE|TH|CAPTION)/.test(n.nodeName))\r |
12170 | break;\r |
12171 | \r |
12172 | ec = n;\r |
12173 | } while ((n = n.nextSibling ? n.nextSibling : n.parentNode));\r |
12174 | \r |
12175 | // Place first chop part into before block element\r |
12176 | if (sc.nodeName == bn)\r |
12177 | rb.setStart(sc, 0);\r |
12178 | else\r |
12179 | rb.setStartBefore(sc);\r |
12180 | \r |
12181 | rb.setEnd(sn, so);\r |
12182 | bef.appendChild(rb.cloneContents() || d.createTextNode('')); // Empty text node needed for Safari\r |
12183 | \r |
12184 | // Place secnd chop part within new block element\r |
12185 | try {\r |
12186 | ra.setEndAfter(ec);\r |
12187 | } catch(ex) {\r |
12188 | //console.debug(s.focusNode, s.focusOffset);\r |
12189 | }\r |
12190 | \r |
12191 | ra.setStart(en, eo);\r |
12192 | aft.appendChild(ra.cloneContents() || d.createTextNode('')); // Empty text node needed for Safari\r |
12193 | \r |
12194 | // Create range around everything\r |
12195 | r = d.createRange();\r |
12196 | if (!sc.previousSibling && sc.parentNode.nodeName == bn) {\r |
12197 | r.setStartBefore(sc.parentNode);\r |
12198 | } else {\r |
12199 | if (rb.startContainer.nodeName == bn && rb.startOffset == 0)\r |
12200 | r.setStartBefore(rb.startContainer);\r |
12201 | else\r |
12202 | r.setStart(rb.startContainer, rb.startOffset);\r |
12203 | }\r |
12204 | \r |
12205 | if (!ec.nextSibling && ec.parentNode.nodeName == bn)\r |
12206 | r.setEndAfter(ec.parentNode);\r |
12207 | else\r |
12208 | r.setEnd(ra.endContainer, ra.endOffset);\r |
12209 | \r |
12210 | // Delete and replace it with new block elements\r |
12211 | r.deleteContents();\r |
12212 | \r |
12213 | if (isOpera)\r |
12214 | ed.getWin().scrollTo(0, vp.y);\r |
12215 | \r |
12216 | // Never wrap blocks in blocks\r |
12217 | if (bef.firstChild && bef.firstChild.nodeName == bn)\r |
12218 | bef.innerHTML = bef.firstChild.innerHTML;\r |
12219 | \r |
12220 | if (aft.firstChild && aft.firstChild.nodeName == bn)\r |
12221 | aft.innerHTML = aft.firstChild.innerHTML;\r |
12222 | \r |
12223 | // Padd empty blocks\r |
12224 | if (isEmpty(bef))\r |
12225 | bef.innerHTML = '<br />';\r |
12226 | \r |
12227 | function appendStyles(e, en) {\r |
12228 | var nl = [], nn, n, i;\r |
12229 | \r |
12230 | e.innerHTML = '';\r |
12231 | \r |
12232 | // Make clones of style elements\r |
12233 | if (se.keep_styles) {\r |
12234 | n = en;\r |
12235 | do {\r |
12236 | // We only want style specific elements\r |
12237 | if (/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(n.nodeName)) {\r |
12238 | nn = n.cloneNode(false);\r |
12239 | dom.setAttrib(nn, 'id', ''); // Remove ID since it needs to be unique\r |
12240 | nl.push(nn);\r |
12241 | }\r |
12242 | } while (n = n.parentNode);\r |
12243 | }\r |
12244 | \r |
12245 | // Append style elements to aft\r |
12246 | if (nl.length > 0) {\r |
12247 | for (i = nl.length - 1, nn = e; i >= 0; i--)\r |
12248 | nn = nn.appendChild(nl[i]);\r |
12249 | \r |
12250 | // Padd most inner style element\r |
12251 | nl[0].innerHTML = isOpera ? ' ' : '<br />'; // Extra space for Opera so that the caret can move there\r |
12252 | return nl[0]; // Move caret to most inner element\r |
12253 | } else\r |
12254 | e.innerHTML = isOpera ? ' ' : '<br />'; // Extra space for Opera so that the caret can move there\r |
12255 | };\r |
12256 | \r |
12257 | // Fill empty afterblook with current style\r |
12258 | if (isEmpty(aft))\r |
12259 | car = appendStyles(aft, en);\r |
12260 | \r |
12261 | // Opera needs this one backwards for older versions\r |
12262 | if (isOpera && parseFloat(opera.version()) < 9.5) {\r |
12263 | r.insertNode(bef);\r |
12264 | r.insertNode(aft);\r |
12265 | } else {\r |
12266 | r.insertNode(aft);\r |
12267 | r.insertNode(bef);\r |
12268 | }\r |
12269 | \r |
12270 | // Normalize\r |
12271 | aft.normalize();\r |
12272 | bef.normalize();\r |
12273 | \r |
12274 | function first(n) {\r |
12275 | return d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false).nextNode() || n;\r |
12276 | };\r |
12277 | \r |
12278 | // Move cursor and scroll into view\r |
12279 | r = d.createRange();\r |
12280 | r.selectNodeContents(isGecko ? first(car || aft) : car || aft);\r |
12281 | r.collapse(1);\r |
12282 | s.removeAllRanges();\r |
12283 | s.addRange(r);\r |
12284 | \r |
12285 | // scrollIntoView seems to scroll the parent window in most browsers now including FF 3.0b4 so it's time to stop using it and do it our selfs\r |
12286 | y = ed.dom.getPos(aft).y;\r |
12287 | ch = aft.clientHeight;\r |
12288 | \r |
12289 | // Is element within viewport\r |
12290 | if (y < vp.y || y + ch > vp.y + vp.h) {\r |
12291 | ed.getWin().scrollTo(0, y < vp.y ? y : y - vp.h + 25); // Needs to be hardcoded to roughly one line of text if a huge text block is broken into two blocks\r |
12292 | //console.debug('SCROLL!', 'vp.y: ' + vp.y, 'y' + y, 'vp.h' + vp.h, 'clientHeight' + aft.clientHeight, 'yyy: ' + (y < vp.y ? y : y - vp.h + aft.clientHeight));\r |
12293 | }\r |
12294 | \r |
12295 | return false;\r |
12296 | },\r |
12297 | \r |
12298 | backspaceDelete : function(e, bs) {\r |
12299 | var t = this, ed = t.editor, b = ed.getBody(), dom = ed.dom, n, se = ed.selection, r = se.getRng(), sc = r.startContainer, n, w, tn;\r |
12300 | \r |
12301 | /*\r |
12302 | var par, rng, nextBlock;\r |
12303 | \r |
12304 | // Delete key will not merge paragraphs on Gecko so we need to do this manually\r |
12305 | // Hitting the delete key at the following caret position doesn't merge the elements <p>A|</p><p>B</p>\r |
12306 | // This logic will merge them into this: <p>A|B</p>\r |
12307 | if (e.keyCode == 46) {\r |
12308 | if (r.collapsed) {\r |
12309 | par = dom.getParent(sc, 'p,h1,h2,h3,h4,h5,h6,div');\r |
12310 | \r |
12311 | if (par) {\r |
12312 | rng = dom.createRng();\r |
12313 | \r |
12314 | rng.setStart(sc, r.startOffset);\r |
12315 | rng.setEndAfter(par);\r |
12316 | \r |
12317 | // Get number of characters to the right of the cursor if it's zero then we are at the end and need to merge the next block element\r |
12318 | if (dom.getOuterHTML(rng.cloneContents()).replace(/<[^>]+>/g, '').length == 0) {\r |
12319 | nextBlock = dom.getNext(par, 'p,h1,h2,h3,h4,h5,h6,div');\r |
12320 | \r |
12321 | // Copy all children from next sibling block and remove it\r |
12322 | if (nextBlock) {\r |
12323 | each(nextBlock.childNodes, function(node) {\r |
12324 | par.appendChild(node.cloneNode(true));\r |
12325 | });\r |
12326 | \r |
12327 | dom.remove(nextBlock);\r |
12328 | }\r |
12329 | \r |
12330 | // Block the default even since the Gecko team might eventually fix this\r |
12331 | // We will remove this logic once they do we can't feature detect this one\r |
12332 | e.preventDefault();\r |
12333 | return;\r |
12334 | }\r |
12335 | }\r |
12336 | }\r |
12337 | }\r |
12338 | */\r |
12339 | \r |
12340 | // The caret sometimes gets stuck in Gecko if you delete empty paragraphs\r |
12341 | // This workaround removes the element by hand and moves the caret to the previous element\r |
12342 | if (sc && ed.dom.isBlock(sc) && !/^(TD|TH)$/.test(sc.nodeName) && bs) {\r |
12343 | if (sc.childNodes.length == 0 || (sc.childNodes.length == 1 && sc.firstChild.nodeName == 'BR')) {\r |
12344 | // Find previous block element\r |
12345 | n = sc;\r |
12346 | while ((n = n.previousSibling) && !ed.dom.isBlock(n)) ;\r |
12347 | \r |
12348 | if (n) {\r |
12349 | if (sc != b.firstChild) {\r |
12350 | // Find last text node\r |
12351 | w = ed.dom.doc.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);\r |
12352 | while (tn = w.nextNode())\r |
12353 | n = tn;\r |
12354 | \r |
12355 | // Place caret at the end of last text node\r |
12356 | r = ed.getDoc().createRange();\r |
12357 | r.setStart(n, n.nodeValue ? n.nodeValue.length : 0);\r |
12358 | r.setEnd(n, n.nodeValue ? n.nodeValue.length : 0);\r |
12359 | se.setRng(r);\r |
12360 | \r |
12361 | // Remove the target container\r |
12362 | ed.dom.remove(sc);\r |
12363 | }\r |
12364 | \r |
12365 | return Event.cancel(e);\r |
12366 | }\r |
12367 | }\r |
12368 | }\r |
12369 | \r |
12370 | // Gecko generates BR elements here and there, we don't like those so lets remove them\r |
12371 | function handler(e) {\r |
12372 | var pr;\r |
12373 | \r |
12374 | e = e.target;\r |
12375 | \r |
12376 | // A new BR was created in a block element, remove it\r |
12377 | if (e && e.parentNode && e.nodeName == 'BR' && (n = t.getParentBlock(e))) {\r |
12378 | pr = e.previousSibling;\r |
12379 | \r |
12380 | Event.remove(b, 'DOMNodeInserted', handler);\r |
12381 | \r |
12382 | // Is there whitespace at the end of the node before then we might need the pesky BR\r |
12383 | // to place the caret at a correct location see bug: #2013943\r |
12384 | if (pr && pr.nodeType == 3 && /\s+$/.test(pr.nodeValue))\r |
12385 | return;\r |
12386 | \r |
12387 | // Only remove BR elements that got inserted in the middle of the text\r |
12388 | if (e.previousSibling || e.nextSibling)\r |
12389 | ed.dom.remove(e);\r |
12390 | }\r |
12391 | };\r |
12392 | \r |
12393 | // Listen for new nodes\r |
12394 | Event._add(b, 'DOMNodeInserted', handler);\r |
12395 | \r |
12396 | // Remove listener\r |
12397 | window.setTimeout(function() {\r |
12398 | Event._remove(b, 'DOMNodeInserted', handler);\r |
12399 | }, 1);\r |
12400 | }\r |
12401 | });\r |
12402 | })(tinymce);\r |
12403 | (function(tinymce) {\r |
12404 | // Shorten names\r |
12405 | var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, extend = tinymce.extend;\r |
12406 | \r |
12407 | tinymce.create('tinymce.ControlManager', {\r |
12408 | ControlManager : function(ed, s) {\r |
12409 | var t = this, i;\r |
12410 | \r |
12411 | s = s || {};\r |
12412 | t.editor = ed;\r |
12413 | t.controls = {};\r |
12414 | t.onAdd = new tinymce.util.Dispatcher(t);\r |
12415 | t.onPostRender = new tinymce.util.Dispatcher(t);\r |
12416 | t.prefix = s.prefix || ed.id + '_';\r |
12417 | t._cls = {};\r |
12418 | \r |
12419 | t.onPostRender.add(function() {\r |
12420 | each(t.controls, function(c) {\r |
12421 | c.postRender();\r |
12422 | });\r |
12423 | });\r |
12424 | },\r |
12425 | \r |
12426 | get : function(id) {\r |
12427 | return this.controls[this.prefix + id] || this.controls[id];\r |
12428 | },\r |
12429 | \r |
12430 | setActive : function(id, s) {\r |
12431 | var c = null;\r |
12432 | \r |
12433 | if (c = this.get(id))\r |
12434 | c.setActive(s);\r |
12435 | \r |
12436 | return c;\r |
12437 | },\r |
12438 | \r |
12439 | setDisabled : function(id, s) {\r |
12440 | var c = null;\r |
12441 | \r |
12442 | if (c = this.get(id))\r |
12443 | c.setDisabled(s);\r |
12444 | \r |
12445 | return c;\r |
12446 | },\r |
12447 | \r |
12448 | add : function(c) {\r |
12449 | var t = this;\r |
12450 | \r |
12451 | if (c) {\r |
12452 | t.controls[c.id] = c;\r |
12453 | t.onAdd.dispatch(c, t);\r |
12454 | }\r |
12455 | \r |
12456 | return c;\r |
12457 | },\r |
12458 | \r |
12459 | createControl : function(n) {\r |
12460 | var c, t = this, ed = t.editor;\r |
12461 | \r |
12462 | each(ed.plugins, function(p) {\r |
12463 | if (p.createControl) {\r |
12464 | c = p.createControl(n, t);\r |
12465 | \r |
12466 | if (c)\r |
12467 | return false;\r |
12468 | }\r |
12469 | });\r |
12470 | \r |
12471 | switch (n) {\r |
12472 | case "|":\r |
12473 | case "separator":\r |
12474 | return t.createSeparator();\r |
12475 | }\r |
12476 | \r |
12477 | if (!c && ed.buttons && (c = ed.buttons[n]))\r |
12478 | return t.createButton(n, c);\r |
12479 | \r |
12480 | return t.add(c);\r |
12481 | },\r |
12482 | \r |
12483 | createDropMenu : function(id, s, cc) {\r |
12484 | var t = this, ed = t.editor, c, bm, v, cls;\r |
12485 | \r |
12486 | s = extend({\r |
12487 | 'class' : 'mceDropDown',\r |
12488 | constrain : ed.settings.constrain_menus\r |
12489 | }, s);\r |
12490 | \r |
12491 | s['class'] = s['class'] + ' ' + ed.getParam('skin') + 'Skin';\r |
12492 | if (v = ed.getParam('skin_variant'))\r |
12493 | s['class'] += ' ' + ed.getParam('skin') + 'Skin' + v.substring(0, 1).toUpperCase() + v.substring(1);\r |
12494 | \r |
12495 | id = t.prefix + id;\r |
12496 | cls = cc || t._cls.dropmenu || tinymce.ui.DropMenu;\r |
12497 | c = t.controls[id] = new cls(id, s);\r |
12498 | c.onAddItem.add(function(c, o) {\r |
12499 | var s = o.settings;\r |
12500 | \r |
12501 | s.title = ed.getLang(s.title, s.title);\r |
12502 | \r |
12503 | if (!s.onclick) {\r |
12504 | s.onclick = function(v) {\r |
12505 | ed.execCommand(s.cmd, s.ui || false, s.value);\r |
12506 | };\r |
12507 | }\r |
12508 | });\r |
12509 | \r |
12510 | ed.onRemove.add(function() {\r |
12511 | c.destroy();\r |
12512 | });\r |
12513 | \r |
12514 | // Fix for bug #1897785, #1898007\r |
12515 | if (tinymce.isIE) {\r |
12516 | c.onShowMenu.add(function() {\r |
12517 | // IE 8 needs focus in order to store away a range with the current collapsed caret location\r |
12518 | ed.focus();\r |
12519 | \r |
12520 | bm = ed.selection.getBookmark(1);\r |
12521 | });\r |
12522 | \r |
12523 | c.onHideMenu.add(function() {\r |
12524 | if (bm) {\r |
12525 | ed.selection.moveToBookmark(bm);\r |
12526 | bm = 0;\r |
12527 | }\r |
12528 | });\r |
12529 | }\r |
12530 | \r |
12531 | return t.add(c);\r |
12532 | },\r |
12533 | \r |
12534 | createListBox : function(id, s, cc) {\r |
12535 | var t = this, ed = t.editor, cmd, c, cls;\r |
12536 | \r |
12537 | if (t.get(id))\r |
12538 | return null;\r |
12539 | \r |
12540 | s.title = ed.translate(s.title);\r |
12541 | s.scope = s.scope || ed;\r |
12542 | \r |
12543 | if (!s.onselect) {\r |
12544 | s.onselect = function(v) {\r |
12545 | ed.execCommand(s.cmd, s.ui || false, v || s.value);\r |
12546 | };\r |
12547 | }\r |
12548 | \r |
12549 | s = extend({\r |
12550 | title : s.title,\r |
12551 | 'class' : 'mce_' + id,\r |
12552 | scope : s.scope,\r |
12553 | control_manager : t\r |
12554 | }, s);\r |
12555 | \r |
12556 | id = t.prefix + id;\r |
12557 | \r |
12558 | if (ed.settings.use_native_selects)\r |
12559 | c = new tinymce.ui.NativeListBox(id, s);\r |
12560 | else {\r |
12561 | cls = cc || t._cls.listbox || tinymce.ui.ListBox;\r |
12562 | c = new cls(id, s);\r |
12563 | }\r |
12564 | \r |
12565 | t.controls[id] = c;\r |
12566 | \r |
12567 | // Fix focus problem in Safari\r |
12568 | if (tinymce.isWebKit) {\r |
12569 | c.onPostRender.add(function(c, n) {\r |
12570 | // Store bookmark on mousedown\r |
12571 | Event.add(n, 'mousedown', function() {\r |
12572 | ed.bookmark = ed.selection.getBookmark(1);\r |
12573 | });\r |
12574 | \r |
12575 | // Restore on focus, since it might be lost\r |
12576 | Event.add(n, 'focus', function() {\r |
12577 | ed.selection.moveToBookmark(ed.bookmark);\r |
12578 | ed.bookmark = null;\r |
12579 | });\r |
12580 | });\r |
12581 | }\r |
12582 | \r |
12583 | if (c.hideMenu)\r |
12584 | ed.onMouseDown.add(c.hideMenu, c);\r |
12585 | \r |
12586 | return t.add(c);\r |
12587 | },\r |
12588 | \r |
12589 | createButton : function(id, s, cc) {\r |
12590 | var t = this, ed = t.editor, o, c, cls;\r |
12591 | \r |
12592 | if (t.get(id))\r |
12593 | return null;\r |
12594 | \r |
12595 | s.title = ed.translate(s.title);\r |
12596 | s.label = ed.translate(s.label);\r |
12597 | s.scope = s.scope || ed;\r |
12598 | \r |
12599 | if (!s.onclick && !s.menu_button) {\r |
12600 | s.onclick = function() {\r |
12601 | ed.execCommand(s.cmd, s.ui || false, s.value);\r |
12602 | };\r |
12603 | }\r |
12604 | \r |
12605 | s = extend({\r |
12606 | title : s.title,\r |
12607 | 'class' : 'mce_' + id,\r |
12608 | unavailable_prefix : ed.getLang('unavailable', ''),\r |
12609 | scope : s.scope,\r |
12610 | control_manager : t\r |
12611 | }, s);\r |
12612 | \r |
12613 | id = t.prefix + id;\r |
12614 | \r |
12615 | if (s.menu_button) {\r |
12616 | cls = cc || t._cls.menubutton || tinymce.ui.MenuButton;\r |
12617 | c = new cls(id, s);\r |
12618 | ed.onMouseDown.add(c.hideMenu, c);\r |
12619 | } else {\r |
12620 | cls = t._cls.button || tinymce.ui.Button;\r |
12621 | c = new cls(id, s);\r |
12622 | }\r |
12623 | \r |
12624 | return t.add(c);\r |
12625 | },\r |
12626 | \r |
12627 | createMenuButton : function(id, s, cc) {\r |
12628 | s = s || {};\r |
12629 | s.menu_button = 1;\r |
12630 | \r |
12631 | return this.createButton(id, s, cc);\r |
12632 | },\r |
12633 | \r |
12634 | createSplitButton : function(id, s, cc) {\r |
12635 | var t = this, ed = t.editor, cmd, c, cls;\r |
12636 | \r |
12637 | if (t.get(id))\r |
12638 | return null;\r |
12639 | \r |
12640 | s.title = ed.translate(s.title);\r |
12641 | s.scope = s.scope || ed;\r |
12642 | \r |
12643 | if (!s.onclick) {\r |
12644 | s.onclick = function(v) {\r |
12645 | ed.execCommand(s.cmd, s.ui || false, v || s.value);\r |
12646 | };\r |
12647 | }\r |
12648 | \r |
12649 | if (!s.onselect) {\r |
12650 | s.onselect = function(v) {\r |
12651 | ed.execCommand(s.cmd, s.ui || false, v || s.value);\r |
12652 | };\r |
12653 | }\r |
12654 | \r |
12655 | s = extend({\r |
12656 | title : s.title,\r |
12657 | 'class' : 'mce_' + id,\r |
12658 | scope : s.scope,\r |
12659 | control_manager : t\r |
12660 | }, s);\r |
12661 | \r |
12662 | id = t.prefix + id;\r |
12663 | cls = cc || t._cls.splitbutton || tinymce.ui.SplitButton;\r |
12664 | c = t.add(new cls(id, s));\r |
12665 | ed.onMouseDown.add(c.hideMenu, c);\r |
12666 | \r |
12667 | return c;\r |
12668 | },\r |
12669 | \r |
12670 | createColorSplitButton : function(id, s, cc) {\r |
12671 | var t = this, ed = t.editor, cmd, c, cls, bm;\r |
12672 | \r |
12673 | if (t.get(id))\r |
12674 | return null;\r |
12675 | \r |
12676 | s.title = ed.translate(s.title);\r |
12677 | s.scope = s.scope || ed;\r |
12678 | \r |
12679 | if (!s.onclick) {\r |
12680 | s.onclick = function(v) {\r |
12681 | if (tinymce.isIE)\r |
12682 | bm = ed.selection.getBookmark(1);\r |
12683 | \r |
12684 | ed.execCommand(s.cmd, s.ui || false, v || s.value);\r |
12685 | };\r |
12686 | }\r |
12687 | \r |
12688 | if (!s.onselect) {\r |
12689 | s.onselect = function(v) {\r |
12690 | ed.execCommand(s.cmd, s.ui || false, v || s.value);\r |
12691 | };\r |
12692 | }\r |
12693 | \r |
12694 | s = extend({\r |
12695 | title : s.title,\r |
12696 | 'class' : 'mce_' + id,\r |
12697 | 'menu_class' : ed.getParam('skin') + 'Skin',\r |
12698 | scope : s.scope,\r |
12699 | more_colors_title : ed.getLang('more_colors')\r |
12700 | }, s);\r |
12701 | \r |
12702 | id = t.prefix + id;\r |
12703 | cls = cc || t._cls.colorsplitbutton || tinymce.ui.ColorSplitButton;\r |
12704 | c = new cls(id, s);\r |
12705 | ed.onMouseDown.add(c.hideMenu, c);\r |
12706 | \r |
12707 | // Remove the menu element when the editor is removed\r |
12708 | ed.onRemove.add(function() {\r |
12709 | c.destroy();\r |
12710 | });\r |
12711 | \r |
12712 | // Fix for bug #1897785, #1898007\r |
12713 | if (tinymce.isIE) {\r |
12714 | c.onShowMenu.add(function() {\r |
12715 | // IE 8 needs focus in order to store away a range with the current collapsed caret location\r |
12716 | ed.focus();\r |
12717 | bm = ed.selection.getBookmark(1);\r |
12718 | });\r |
12719 | \r |
12720 | c.onHideMenu.add(function() {\r |
12721 | if (bm) {\r |
12722 | ed.selection.moveToBookmark(bm);\r |
12723 | bm = 0;\r |
12724 | }\r |
12725 | });\r |
12726 | }\r |
12727 | \r |
12728 | return t.add(c);\r |
12729 | },\r |
12730 | \r |
12731 | createToolbar : function(id, s, cc) {\r |
12732 | var c, t = this, cls;\r |
12733 | \r |
12734 | id = t.prefix + id;\r |
12735 | cls = cc || t._cls.toolbar || tinymce.ui.Toolbar;\r |
12736 | c = new cls(id, s);\r |
12737 | \r |
12738 | if (t.get(id))\r |
12739 | return null;\r |
12740 | \r |
12741 | return t.add(c);\r |
12742 | },\r |
12743 | \r |
12744 | createSeparator : function(cc) {\r |
12745 | var cls = cc || this._cls.separator || tinymce.ui.Separator;\r |
12746 | \r |
12747 | return new cls();\r |
12748 | },\r |
12749 | \r |
12750 | setControlType : function(n, c) {\r |
12751 | return this._cls[n.toLowerCase()] = c;\r |
12752 | },\r |
12753 | \r |
12754 | destroy : function() {\r |
12755 | each(this.controls, function(c) {\r |
12756 | c.destroy();\r |
12757 | });\r |
12758 | \r |
12759 | this.controls = null;\r |
12760 | }\r |
12761 | });\r |
12762 | })(tinymce);\r |
12763 | (function(tinymce) {\r |
12764 | var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each, isIE = tinymce.isIE, isOpera = tinymce.isOpera;\r |
12765 | \r |
12766 | tinymce.create('tinymce.WindowManager', {\r |
12767 | WindowManager : function(ed) {\r |
12768 | var t = this;\r |
12769 | \r |
12770 | t.editor = ed;\r |
12771 | t.onOpen = new Dispatcher(t);\r |
12772 | t.onClose = new Dispatcher(t);\r |
12773 | t.params = {};\r |
12774 | t.features = {};\r |
12775 | },\r |
12776 | \r |
12777 | open : function(s, p) {\r |
12778 | var t = this, f = '', x, y, mo = t.editor.settings.dialog_type == 'modal', w, sw, sh, vp = tinymce.DOM.getViewPort(), u;\r |
12779 | \r |
12780 | // Default some options\r |
12781 | s = s || {};\r |
12782 | p = p || {};\r |
12783 | sw = isOpera ? vp.w : screen.width; // Opera uses windows inside the Opera window\r |
12784 | sh = isOpera ? vp.h : screen.height;\r |
12785 | s.name = s.name || 'mc_' + new Date().getTime();\r |
12786 | s.width = parseInt(s.width || 320);\r |
12787 | s.height = parseInt(s.height || 240);\r |
12788 | s.resizable = true;\r |
12789 | s.left = s.left || parseInt(sw / 2.0) - (s.width / 2.0);\r |
12790 | s.top = s.top || parseInt(sh / 2.0) - (s.height / 2.0);\r |
12791 | p.inline = false;\r |
12792 | p.mce_width = s.width;\r |
12793 | p.mce_height = s.height;\r |
12794 | p.mce_auto_focus = s.auto_focus;\r |
12795 | \r |
12796 | if (mo) {\r |
12797 | if (isIE) {\r |
12798 | s.center = true;\r |
12799 | s.help = false;\r |
12800 | s.dialogWidth = s.width + 'px';\r |
12801 | s.dialogHeight = s.height + 'px';\r |
12802 | s.scroll = s.scrollbars || false;\r |
12803 | }\r |
12804 | }\r |
12805 | \r |
12806 | // Build features string\r |
12807 | each(s, function(v, k) {\r |
12808 | if (tinymce.is(v, 'boolean'))\r |
12809 | v = v ? 'yes' : 'no';\r |
12810 | \r |
12811 | if (!/^(name|url)$/.test(k)) {\r |
12812 | if (isIE && mo)\r |
12813 | f += (f ? ';' : '') + k + ':' + v;\r |
12814 | else\r |
12815 | f += (f ? ',' : '') + k + '=' + v;\r |
12816 | }\r |
12817 | });\r |
12818 | \r |
12819 | t.features = s;\r |
12820 | t.params = p;\r |
12821 | t.onOpen.dispatch(t, s, p);\r |
12822 | \r |
12823 | u = s.url || s.file;\r |
12824 | u = tinymce._addVer(u);\r |
12825 | \r |
12826 | try {\r |
12827 | if (isIE && mo) {\r |
12828 | w = 1;\r |
12829 | window.showModalDialog(u, window, f);\r |
12830 | } else\r |
12831 | w = window.open(u, s.name, f);\r |
12832 | } catch (ex) {\r |
12833 | // Ignore\r |
12834 | }\r |
12835 | \r |
12836 | if (!w)\r |
12837 | alert(t.editor.getLang('popup_blocked'));\r |
12838 | },\r |
12839 | \r |
12840 | close : function(w) {\r |
12841 | w.close();\r |
12842 | this.onClose.dispatch(this);\r |
12843 | },\r |
12844 | \r |
12845 | createInstance : function(cl, a, b, c, d, e) {\r |
12846 | var f = tinymce.resolve(cl);\r |
12847 | \r |
12848 | return new f(a, b, c, d, e);\r |
12849 | },\r |
12850 | \r |
12851 | confirm : function(t, cb, s, w) {\r |
12852 | w = w || window;\r |
12853 | \r |
12854 | cb.call(s || this, w.confirm(this._decode(this.editor.getLang(t, t))));\r |
12855 | },\r |
12856 | \r |
12857 | alert : function(tx, cb, s, w) {\r |
12858 | var t = this;\r |
12859 | \r |
12860 | w = w || window;\r |
12861 | w.alert(t._decode(t.editor.getLang(tx, tx)));\r |
12862 | \r |
12863 | if (cb)\r |
12864 | cb.call(s || t);\r |
12865 | },\r |
12866 | \r |
12867 | // Internal functions\r |
12868 | \r |
12869 | _decode : function(s) {\r |
12870 | return tinymce.DOM.decode(s).replace(/\\n/g, '\n');\r |
12871 | }\r |
12872 | });\r |
12873 | }(tinymce));(function(tinymce) {\r |
12874 | tinymce.CommandManager = function() {\r |
12875 | var execCommands = {}, queryStateCommands = {}, queryValueCommands = {};\r |
12876 | \r |
12877 | function add(collection, cmd, func, scope) {\r |
12878 | if (typeof(cmd) == 'string')\r |
12879 | cmd = [cmd];\r |
12880 | \r |
12881 | tinymce.each(cmd, function(cmd) {\r |
12882 | collection[cmd.toLowerCase()] = {func : func, scope : scope};\r |
12883 | });\r |
12884 | };\r |
12885 | \r |
12886 | tinymce.extend(this, {\r |
12887 | add : function(cmd, func, scope) {\r |
12888 | add(execCommands, cmd, func, scope);\r |
12889 | },\r |
12890 | \r |
12891 | addQueryStateHandler : function(cmd, func, scope) {\r |
12892 | add(queryStateCommands, cmd, func, scope);\r |
12893 | },\r |
12894 | \r |
12895 | addQueryValueHandler : function(cmd, func, scope) {\r |
12896 | add(queryValueCommands, cmd, func, scope);\r |
12897 | },\r |
12898 | \r |
12899 | execCommand : function(scope, cmd, ui, value, args) {\r |
12900 | if (cmd = execCommands[cmd.toLowerCase()]) {\r |
12901 | if (cmd.func.call(scope || cmd.scope, ui, value, args) !== false)\r |
12902 | return true;\r |
12903 | }\r |
12904 | },\r |
12905 | \r |
12906 | queryCommandValue : function() {\r |
12907 | if (cmd = queryValueCommands[cmd.toLowerCase()])\r |
12908 | return cmd.func.call(scope || cmd.scope, ui, value, args);\r |
12909 | },\r |
12910 | \r |
12911 | queryCommandState : function() {\r |
12912 | if (cmd = queryStateCommands[cmd.toLowerCase()])\r |
12913 | return cmd.func.call(scope || cmd.scope, ui, value, args);\r |
12914 | }\r |
12915 | });\r |
12916 | };\r |
12917 | \r |
12918 | tinymce.GlobalCommands = new tinymce.CommandManager();\r |
12919 | })(tinymce);(function(tinymce) {\r |
12920 | function processRange(dom, start, end, callback) {\r |
12921 | var ancestor, n, startPoint, endPoint, sib;\r |
12922 | \r |
12923 | function findEndPoint(n, c) {\r |
12924 | do {\r |
12925 | if (n.parentNode == c)\r |
12926 | return n;\r |
12927 | \r |
12928 | n = n.parentNode;\r |
12929 | } while(n);\r |
12930 | };\r |
12931 | \r |
12932 | function process(n) {\r |
12933 | callback(n);\r |
12934 | tinymce.walk(n, callback, 'childNodes');\r |
12935 | };\r |
12936 | \r |
12937 | // Find common ancestor and end points\r |
12938 | ancestor = dom.findCommonAncestor(start, end);\r |
12939 | startPoint = findEndPoint(start, ancestor) || start;\r |
12940 | endPoint = findEndPoint(end, ancestor) || end;\r |
12941 | \r |
12942 | // Process left leaf\r |
12943 | for (n = start; n && n != startPoint; n = n.parentNode) {\r |
12944 | for (sib = n.nextSibling; sib; sib = sib.nextSibling)\r |
12945 | process(sib);\r |
12946 | }\r |
12947 | \r |
12948 | // Process middle from start to end point\r |
12949 | if (startPoint != endPoint) {\r |
12950 | for (n = startPoint.nextSibling; n && n != endPoint; n = n.nextSibling)\r |
12951 | process(n);\r |
12952 | } else\r |
12953 | process(startPoint);\r |
12954 | \r |
12955 | // Process right leaf\r |
12956 | for (n = end; n && n != endPoint; n = n.parentNode) {\r |
12957 | for (sib = n.previousSibling; sib; sib = sib.previousSibling)\r |
12958 | process(sib);\r |
12959 | }\r |
12960 | };\r |
12961 | \r |
12962 | tinymce.GlobalCommands.add('RemoveFormat', function() {\r |
12963 | var ed = this, dom = ed.dom, s = ed.selection, r = s.getRng(1), nodes = [], bm, start, end, sc, so, ec, eo, n;\r |
12964 | \r |
12965 | function findFormatRoot(n) {\r |
12966 | var sp;\r |
12967 | \r |
12968 | dom.getParent(n, function(n) {\r |
12969 | if (dom.is(n, ed.getParam('removeformat_selector')))\r |
12970 | sp = n;\r |
12971 | \r |
12972 | return dom.isBlock(n);\r |
12973 | }, ed.getBody());\r |
12974 | \r |
12975 | return sp;\r |
12976 | };\r |
12977 | \r |
12978 | function collect(n) {\r |
12979 | if (dom.is(n, ed.getParam('removeformat_selector')))\r |
12980 | nodes.push(n);\r |
12981 | };\r |
12982 | \r |
12983 | function walk(n) {\r |
12984 | collect(n);\r |
12985 | tinymce.walk(n, collect, 'childNodes');\r |
12986 | };\r |
12987 | \r |
12988 | bm = s.getBookmark();\r |
12989 | sc = r.startContainer;\r |
12990 | ec = r.endContainer;\r |
12991 | so = r.startOffset;\r |
12992 | eo = r.endOffset;\r |
12993 | sc = sc.nodeType == 1 ? sc.childNodes[Math.min(so, sc.childNodes.length - 1)] : sc;\r |
12994 | ec = ec.nodeType == 1 ? ec.childNodes[Math.min(so == eo ? eo : eo - 1, ec.childNodes.length - 1)] : ec;\r |
12995 | \r |
12996 | // Same container\r |
12997 | if (sc == ec) { // TEXT_NODE\r |
12998 | start = findFormatRoot(sc);\r |
12999 | \r |
13000 | // Handle single text node\r |
13001 | if (sc.nodeType == 3) {\r |
13002 | if (start && start.nodeType == 1) { // ELEMENT\r |
13003 | n = sc.splitText(so);\r |
13004 | n.splitText(eo - so);\r |
13005 | dom.split(start, n);\r |
13006 | \r |
13007 | s.moveToBookmark(bm);\r |
13008 | }\r |
13009 | \r |
13010 | return;\r |
13011 | }\r |
13012 | \r |
13013 | // Handle single element\r |
13014 | walk(dom.split(start, sc) || sc);\r |
13015 | } else {\r |
13016 | // Find start/end format root\r |
13017 | start = findFormatRoot(sc);\r |
13018 | end = findFormatRoot(ec);\r |
13019 | \r |
13020 | // Split start text node\r |
13021 | if (start) {\r |
13022 | if (sc.nodeType == 3) { // TEXT\r |
13023 | // Since IE doesn't support white space nodes in the DOM we need to\r |
13024 | // add this invisible character so that the splitText function can split the contents\r |
13025 | if (so == sc.nodeValue.length)\r |
13026 | sc.nodeValue += '\uFEFF'; // Yet another pesky IE fix\r |
13027 | \r |
13028 | sc = sc.splitText(so);\r |
13029 | }\r |
13030 | }\r |
13031 | \r |
13032 | // Split end text node\r |
13033 | if (end) {\r |
13034 | if (ec.nodeType == 3) // TEXT\r |
13035 | ec.splitText(eo);\r |
13036 | }\r |
13037 | \r |
13038 | // If the start and end format root is the same then we need to wrap\r |
13039 | // the end node in a span since the split calls might change the reference\r |
13040 | // Example: <p><b><em>x[yz<span>---</span>12]3</em></b></p>\r |
13041 | if (start && start == end)\r |
13042 | dom.replace(dom.create('span', {id : '__end'}, ec.cloneNode(true)), ec);\r |
13043 | \r |
13044 | // Split all start containers down to the format root\r |
13045 | if (start)\r |
13046 | start = dom.split(start, sc);\r |
13047 | else\r |
13048 | start = sc;\r |
13049 | \r |
13050 | // If there is a span wrapper use that one instead\r |
13051 | if (n = dom.get('__end')) {\r |
13052 | ec = n;\r |
13053 | end = findFormatRoot(ec);\r |
13054 | }\r |
13055 | \r |
13056 | // Split all end containers down to the format root\r |
13057 | if (end)\r |
13058 | end = dom.split(end, ec);\r |
13059 | else\r |
13060 | end = ec;\r |
13061 | \r |
13062 | // Collect nodes in between\r |
13063 | processRange(dom, start, end, collect);\r |
13064 | \r |
13065 | // Remove invisible character for IE workaround if we find it\r |
13066 | if (sc.nodeValue == '\uFEFF')\r |
13067 | sc.nodeValue = '';\r |
13068 | \r |
13069 | // Process start/end container elements\r |
13070 | walk(ec);\r |
13071 | walk(sc);\r |
13072 | }\r |
13073 | \r |
13074 | // Remove all collected nodes\r |
13075 | tinymce.each(nodes, function(n) {\r |
13076 | dom.remove(n, 1);\r |
13077 | });\r |
13078 | \r |
13079 | // Remove leftover wrapper\r |
13080 | dom.remove('__end', 1);\r |
13081 | \r |
13082 | s.moveToBookmark(bm);\r |
13083 | });\r |
13084 | })(tinymce);\r |
13085 | (function(tinymce) {\r |
13086 | tinymce.GlobalCommands.add('mceBlockQuote', function() {\r |
13087 | var ed = this, s = ed.selection, dom = ed.dom, sb, eb, n, bm, bq, r, bq2, i, nl;\r |
13088 | \r |
13089 | function getBQ(e) {\r |
13090 | return dom.getParent(e, function(n) {return n.nodeName === 'BLOCKQUOTE';});\r |
13091 | };\r |
13092 | \r |
13093 | // Get start/end block\r |
13094 | sb = dom.getParent(s.getStart(), dom.isBlock);\r |
13095 | eb = dom.getParent(s.getEnd(), dom.isBlock);\r |
13096 | \r |
13097 | // Remove blockquote(s)\r |
13098 | if (bq = getBQ(sb)) {\r |
13099 | if (sb != eb || sb.childNodes.length > 1 || (sb.childNodes.length == 1 && sb.firstChild.nodeName != 'BR'))\r |
13100 | bm = s.getBookmark();\r |
13101 | \r |
13102 | // Move all elements after the end block into new bq\r |
13103 | if (getBQ(eb)) {\r |
13104 | bq2 = bq.cloneNode(false);\r |
13105 | \r |
13106 | while (n = eb.nextSibling)\r |
13107 | bq2.appendChild(n.parentNode.removeChild(n));\r |
13108 | }\r |
13109 | \r |
13110 | // Add new bq after\r |
13111 | if (bq2)\r |
13112 | dom.insertAfter(bq2, bq);\r |
13113 | \r |
13114 | // Move all selected blocks after the current bq\r |
13115 | nl = s.getSelectedBlocks(sb, eb);\r |
13116 | for (i = nl.length - 1; i >= 0; i--) {\r |
13117 | dom.insertAfter(nl[i], bq);\r |
13118 | }\r |
13119 | \r |
13120 | // Empty bq, then remove it\r |
13121 | if (/^\s*$/.test(bq.innerHTML))\r |
13122 | dom.remove(bq, 1); // Keep children so boomark restoration works correctly\r |
13123 | \r |
13124 | // Empty bq, then remote it\r |
13125 | if (bq2 && /^\s*$/.test(bq2.innerHTML))\r |
13126 | dom.remove(bq2, 1); // Keep children so boomark restoration works correctly\r |
13127 | \r |
13128 | if (!bm) {\r |
13129 | // Move caret inside empty block element\r |
13130 | if (!tinymce.isIE) {\r |
13131 | r = ed.getDoc().createRange();\r |
13132 | r.setStart(sb, 0);\r |
13133 | r.setEnd(sb, 0);\r |
13134 | s.setRng(r);\r |
13135 | } else {\r |
13136 | s.select(sb);\r |
13137 | s.collapse(0);\r |
13138 | \r |
13139 | // IE misses the empty block some times element so we must move back the caret\r |
13140 | if (dom.getParent(s.getStart(), dom.isBlock) != sb) {\r |
13141 | r = s.getRng();\r |
13142 | r.move('character', -1);\r |
13143 | r.select();\r |
13144 | }\r |
13145 | }\r |
13146 | } else\r |
13147 | ed.selection.moveToBookmark(bm);\r |
13148 | \r |
13149 | return;\r |
13150 | }\r |
13151 | \r |
13152 | // Since IE can start with a totally empty document we need to add the first bq and paragraph\r |
13153 | if (tinymce.isIE && !sb && !eb) {\r |
13154 | ed.getDoc().execCommand('Indent');\r |
13155 | n = getBQ(s.getNode());\r |
13156 | n.style.margin = n.dir = ''; // IE adds margin and dir to bq\r |
13157 | return;\r |
13158 | }\r |
13159 | \r |
13160 | if (!sb || !eb)\r |
13161 | return;\r |
13162 | \r |
13163 | // If empty paragraph node then do not use bookmark\r |
13164 | if (sb != eb || sb.childNodes.length > 1 || (sb.childNodes.length == 1 && sb.firstChild.nodeName != 'BR'))\r |
13165 | bm = s.getBookmark();\r |
13166 | \r |
13167 | // Move selected block elements into a bq\r |
13168 | tinymce.each(s.getSelectedBlocks(getBQ(s.getStart()), getBQ(s.getEnd())), function(e) {\r |
13169 | // Found existing BQ add to this one\r |
13170 | if (e.nodeName == 'BLOCKQUOTE' && !bq) {\r |
13171 | bq = e;\r |
13172 | return;\r |
13173 | }\r |
13174 | \r |
13175 | // No BQ found, create one\r |
13176 | if (!bq) {\r |
13177 | bq = dom.create('blockquote');\r |
13178 | e.parentNode.insertBefore(bq, e);\r |
13179 | }\r |
13180 | \r |
13181 | // Add children from existing BQ\r |
13182 | if (e.nodeName == 'BLOCKQUOTE' && bq) {\r |
13183 | n = e.firstChild;\r |
13184 | \r |
13185 | while (n) {\r |
13186 | bq.appendChild(n.cloneNode(true));\r |
13187 | n = n.nextSibling;\r |
13188 | }\r |
13189 | \r |
13190 | dom.remove(e);\r |
13191 | return;\r |
13192 | }\r |
13193 | \r |
13194 | // Add non BQ element to BQ\r |
13195 | bq.appendChild(dom.remove(e));\r |
13196 | });\r |
13197 | \r |
13198 | if (!bm) {\r |
13199 | // Move caret inside empty block element\r |
13200 | if (!tinymce.isIE) {\r |
13201 | r = ed.getDoc().createRange();\r |
13202 | r.setStart(sb, 0);\r |
13203 | r.setEnd(sb, 0);\r |
13204 | s.setRng(r);\r |
13205 | } else {\r |
13206 | s.select(sb);\r |
13207 | s.collapse(1);\r |
13208 | }\r |
13209 | } else\r |
13210 | s.moveToBookmark(bm);\r |
13211 | });\r |
13212 | })(tinymce);\r |
13213 | (function(tinymce) {\r |
13214 | tinymce.each(['Cut', 'Copy', 'Paste'], function(cmd) {\r |
13215 | tinymce.GlobalCommands.add(cmd, function() {\r |
13216 | var ed = this, doc = ed.getDoc();\r |
13217 | \r |
13218 | try {\r |
13219 | doc.execCommand(cmd, false, null);\r |
13220 | \r |
13221 | // On WebKit the command will just be ignored if it's not enabled\r |
13222 | if (!doc.queryCommandEnabled(cmd))\r |
13223 | throw 'Error';\r |
13224 | } catch (ex) {\r |
13225 | if (tinymce.isGecko) {\r |
13226 | ed.windowManager.confirm(ed.getLang('clipboard_msg'), function(s) {\r |
13227 | if (s)\r |
13228 | open('http://www.mozilla.org/editor/midasdemo/securityprefs.html', '_blank');\r |
13229 | });\r |
13230 | } else\r |
13231 | ed.windowManager.alert(ed.getLang('clipboard_no_support'));\r |
13232 | }\r |
13233 | });\r |
13234 | });\r |
13235 | })(tinymce);\r |
13236 | (function(tinymce) {\r |
13237 | tinymce.GlobalCommands.add('InsertHorizontalRule', function() {\r |
13238 | if (tinymce.isOpera)\r |
13239 | return this.getDoc().execCommand('InsertHorizontalRule', false, '');\r |
13240 | \r |
13241 | this.selection.setContent('<hr />');\r |
13242 | });\r |
13243 | })(tinymce);\r |
13244 | (function() {\r |
13245 | var cmds = tinymce.GlobalCommands;\r |
13246 | \r |
13247 | cmds.add(['mceEndUndoLevel', 'mceAddUndoLevel'], function() {\r |
13248 | this.undoManager.add();\r |
13249 | });\r |
13250 | \r |
13251 | cmds.add('Undo', function() {\r |
13252 | var ed = this;\r |
13253 | \r |
13254 | if (ed.settings.custom_undo_redo) {\r |
13255 | ed.undoManager.undo();\r |
13256 | ed.nodeChanged();\r |
13257 | return true;\r |
13258 | }\r |
13259 | \r |
13260 | return false; // Run browser command\r |
13261 | });\r |
13262 | \r |
13263 | cmds.add('Redo', function() {\r |
13264 | var ed = this;\r |
13265 | \r |
13266 | if (ed.settings.custom_undo_redo) {\r |
13267 | ed.undoManager.redo();\r |
13268 | ed.nodeChanged();\r |
13269 | return true;\r |
13270 | }\r |
13271 | \r |
13272 | return false; // Run browser command\r |
13273 | });\r |
13274 | })();\r |