* upgraded new version of tiny_mce
[citadel.git] / webcit / tiny_mce / tiny_mce_src.js
1 \r
2 /* file:jscripts/tiny_mce/classes/tinymce.js */\r
3 \r
4 var tinymce = {\r
5         majorVersion : '3',\r
6         minorVersion : '2.1.1',\r
7         releaseDate : '2008-11-27',\r
8 \r
9         _init : function() {\r
10                 var t = this, d = document, w = window, na = navigator, ua = na.userAgent, i, nl, n, base, p, v;\r
11 \r
12                 // Browser checks\r
13                 t.isOpera = w.opera && opera.buildNumber;\r
14                 t.isWebKit = /WebKit/.test(ua);\r
15                 t.isOldWebKit = t.isWebKit && !w.getSelection().getRangeAt;\r
16                 t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(na.appName);\r
17                 t.isIE6 = t.isIE && /MSIE [56]/.test(ua);\r
18                 t.isGecko = !t.isWebKit && /Gecko/.test(ua);\r
19                 t.isMac = ua.indexOf('Mac') != -1;\r
20                 t.isAir = /adobeair/i.test(ua);\r
21 \r
22                 // TinyMCE .NET webcontrol might be setting the values for TinyMCE\r
23                 if (w.tinyMCEPreInit) {\r
24                         t.suffix = tinyMCEPreInit.suffix;\r
25                         t.baseURL = tinyMCEPreInit.base;\r
26                         t.query = tinyMCEPreInit.query;\r
27                         return;\r
28                 }\r
29 \r
30                 // Get suffix and base\r
31                 t.suffix = '';\r
32 \r
33                 // If base element found, add that infront of baseURL\r
34                 nl = d.getElementsByTagName('base');\r
35                 for (i=0; i<nl.length; i++) {\r
36                         if (v = nl[i].href) {\r
37                                 // Host only value like http://site.com or http://site.com:8008\r
38                                 if (/^https?:\/\/[^\/]+$/.test(v))\r
39                                         v += '/';\r
40 \r
41                                 base = v ? v.match(/.*\//)[0] : ''; // Get only directory\r
42                         }\r
43                 }\r
44 \r
45                 function getBase(n) {\r
46                         if (n.src && /tiny_mce(|_dev|_src|_gzip|_jquery|_prototype).js/.test(n.src)) {\r
47                                 if (/_(src|dev)\.js/g.test(n.src))\r
48                                         t.suffix = '_src';\r
49 \r
50                                 if ((p = n.src.indexOf('?')) != -1)\r
51                                         t.query = n.src.substring(p + 1);\r
52 \r
53                                 t.baseURL = n.src.substring(0, n.src.lastIndexOf('/'));\r
54 \r
55                                 // If path to script is relative and a base href was found add that one infront\r
56                                 if (base && t.baseURL.indexOf('://') == -1)\r
57                                         t.baseURL = base + t.baseURL;\r
58 \r
59                                 return t.baseURL;\r
60                         }\r
61 \r
62                         return null;\r
63                 };\r
64 \r
65                 // Check document\r
66                 nl = d.getElementsByTagName('script');\r
67                 for (i=0; i<nl.length; i++) {\r
68                         if (getBase(nl[i]))\r
69                                 return;\r
70                 }\r
71 \r
72                 // Check head\r
73                 n = d.getElementsByTagName('head')[0];\r
74                 if (n) {\r
75                         nl = n.getElementsByTagName('script');\r
76                         for (i=0; i<nl.length; i++) {\r
77                                 if (getBase(nl[i]))\r
78                                         return;\r
79                         }\r
80                 }\r
81 \r
82                 return;\r
83         },\r
84 \r
85         is : function(o, t) {\r
86                 var n = typeof(o);\r
87 \r
88                 if (!t)\r
89                         return n != 'undefined';\r
90 \r
91                 if (t == 'array' && (o instanceof Array))\r
92                         return true;\r
93 \r
94                 return n == t;\r
95         },\r
96 \r
97         // #if !jquery\r
98 \r
99         each : function(o, cb, s) {\r
100                 var n, l;\r
101 \r
102                 if (!o)\r
103                         return 0;\r
104 \r
105                 s = s || o;\r
106 \r
107                 if (typeof(o.length) != 'undefined') {\r
108                         // Indexed arrays, needed for Safari\r
109                         for (n=0, l = o.length; n<l; n++) {\r
110                                 if (cb.call(s, o[n], n, o) === false)\r
111                                         return 0;\r
112                         }\r
113                 } else {\r
114                         // Hashtables\r
115                         for (n in o) {\r
116                                 if (o.hasOwnProperty(n)) {\r
117                                         if (cb.call(s, o[n], n, o) === false)\r
118                                                 return 0;\r
119                                 }\r
120                         }\r
121                 }\r
122 \r
123                 return 1;\r
124         },\r
125 \r
126         map : function(a, f) {\r
127                 var o = [];\r
128 \r
129                 tinymce.each(a, function(v) {\r
130                         o.push(f(v));\r
131                 });\r
132 \r
133                 return o;\r
134         },\r
135 \r
136         grep : function(a, f) {\r
137                 var o = [];\r
138 \r
139                 tinymce.each(a, function(v) {\r
140                         if (!f || f(v))\r
141                                 o.push(v);\r
142                 });\r
143 \r
144                 return o;\r
145         },\r
146 \r
147         inArray : function(a, v) {\r
148                 var i, l;\r
149 \r
150                 if (a) {\r
151                         for (i = 0, l = a.length; i < l; i++) {\r
152                                 if (a[i] === v)\r
153                                         return i;\r
154                         }\r
155                 }\r
156 \r
157                 return -1;\r
158         },\r
159 \r
160         extend : function(o, e) {\r
161                 var i, a = arguments;\r
162 \r
163                 for (i=1; i<a.length; i++) {\r
164                         e = a[i];\r
165 \r
166                         tinymce.each(e, function(v, n) {\r
167                                 if (typeof(v) !== 'undefined')\r
168                                         o[n] = v;\r
169                         });\r
170                 }\r
171 \r
172                 return o;\r
173         },\r
174 \r
175         trim : function(s) {\r
176                 return (s ? '' + s : '').replace(/^\s*|\s*$/g, '');\r
177         },\r
178 \r
179         // #endif\r
180 \r
181         create : function(s, p) {\r
182                 var t = this, sp, ns, cn, scn, c, de = 0;\r
183 \r
184                 // Parse : <prefix> <class>:<super class>\r
185                 s = /^((static) )?([\w.]+)(:([\w.]+))?/.exec(s);\r
186                 cn = s[3].match(/(^|\.)(\w+)$/i)[2]; // Class name\r
187 \r
188                 // Create namespace for new class\r
189                 ns = t.createNS(s[3].replace(/\.\w+$/, ''));\r
190 \r
191                 // Class already exists\r
192                 if (ns[cn])\r
193                         return;\r
194 \r
195                 // Make pure static class\r
196                 if (s[2] == 'static') {\r
197                         ns[cn] = p;\r
198 \r
199                         if (this.onCreate)\r
200                                 this.onCreate(s[2], s[3], ns[cn]);\r
201 \r
202                         return;\r
203                 }\r
204 \r
205                 // Create default constructor\r
206                 if (!p[cn]) {\r
207                         p[cn] = function() {};\r
208                         de = 1;\r
209                 }\r
210 \r
211                 // Add constructor and methods\r
212                 ns[cn] = p[cn];\r
213                 t.extend(ns[cn].prototype, p);\r
214 \r
215                 // Extend\r
216                 if (s[5]) {\r
217                         sp = t.resolve(s[5]).prototype;\r
218                         scn = s[5].match(/\.(\w+)$/i)[1]; // Class name\r
219 \r
220                         // Extend constructor\r
221                         c = ns[cn];\r
222                         if (de) {\r
223                                 // Add passthrough constructor\r
224                                 ns[cn] = function() {\r
225                                         return sp[scn].apply(this, arguments);\r
226                                 };\r
227                         } else {\r
228                                 // Add inherit constructor\r
229                                 ns[cn] = function() {\r
230                                         this.parent = sp[scn];\r
231                                         return c.apply(this, arguments);\r
232                                 };\r
233                         }\r
234                         ns[cn].prototype[cn] = ns[cn];\r
235 \r
236                         // Add super methods\r
237                         t.each(sp, function(f, n) {\r
238                                 ns[cn].prototype[n] = sp[n];\r
239                         });\r
240 \r
241                         // Add overridden methods\r
242                         t.each(p, function(f, n) {\r
243                                 // Extend methods if needed\r
244                                 if (sp[n]) {\r
245                                         ns[cn].prototype[n] = function() {\r
246                                                 this.parent = sp[n];\r
247                                                 return f.apply(this, arguments);\r
248                                         };\r
249                                 } else {\r
250                                         if (n != cn)\r
251                                                 ns[cn].prototype[n] = f;\r
252                                 }\r
253                         });\r
254                 }\r
255 \r
256                 // Add static methods\r
257                 t.each(p['static'], function(f, n) {\r
258                         ns[cn][n] = f;\r
259                 });\r
260 \r
261                 if (this.onCreate)\r
262                         this.onCreate(s[2], s[3], ns[cn].prototype);\r
263         },\r
264 \r
265         walk : function(o, f, n, s) {\r
266                 s = s || this;\r
267 \r
268                 if (o) {\r
269                         if (n)\r
270                                 o = o[n];\r
271 \r
272                         tinymce.each(o, function(o, i) {\r
273                                 if (f.call(s, o, i, n) === false)\r
274                                         return false;\r
275 \r
276                                 tinymce.walk(o, f, n, s);\r
277                         });\r
278                 }\r
279         },\r
280 \r
281         createNS : function(n, o) {\r
282                 var i, v;\r
283 \r
284                 o = o || window;\r
285 \r
286                 n = n.split('.');\r
287                 for (i=0; i<n.length; i++) {\r
288                         v = n[i];\r
289 \r
290                         if (!o[v])\r
291                                 o[v] = {};\r
292 \r
293                         o = o[v];\r
294                 }\r
295 \r
296                 return o;\r
297         },\r
298 \r
299         resolve : function(n, o) {\r
300                 var i, l;\r
301 \r
302                 o = o || window;\r
303 \r
304                 n = n.split('.');\r
305                 for (i=0, l = n.length; i<l; i++) {\r
306                         o = o[n[i]];\r
307 \r
308                         if (!o)\r
309                                 break;\r
310                 }\r
311 \r
312                 return o;\r
313         },\r
314 \r
315         addUnload : function(f, s) {\r
316                 var t = this, w = window;\r
317 \r
318                 f = {func : f, scope : s || this};\r
319 \r
320                 if (!t.unloads) {\r
321                         function unload() {\r
322                                 var li = t.unloads, o, n;\r
323 \r
324                                 if (li) {\r
325                                         // Call unload handlers\r
326                                         for (n in li) {\r
327                                                 o = li[n];\r
328 \r
329                                                 if (o && o.func)\r
330                                                         o.func.call(o.scope, 1); // Send in one arg to distinct unload and user destroy\r
331                                         }\r
332 \r
333                                         // Detach unload function\r
334                                         if (w.detachEvent) {\r
335                                                 w.detachEvent('onbeforeunload', fakeUnload);\r
336                                                 w.detachEvent('onunload', unload);\r
337                                         } else if (w.removeEventListener)\r
338                                                 w.removeEventListener('unload', unload, false);\r
339 \r
340                                         // Destroy references\r
341                                         t.unloads = o = li = w = unload = null;\r
342 \r
343                                         // Run garbarge collector on IE\r
344                                         if (window.CollectGarbage)\r
345                                                 window.CollectGarbage();\r
346                                 }\r
347                         };\r
348 \r
349                         function fakeUnload() {\r
350                                 var d = document;\r
351 \r
352                                 // Is there things still loading, then do some magic\r
353                                 if (d.readyState == 'interactive') {\r
354                                         function stop() {\r
355                                                 // Prevent memory leak\r
356                                                 d.detachEvent('onstop', stop);\r
357 \r
358                                                 // Call unload handler\r
359                                                 unload();\r
360 \r
361                                                 d = null;\r
362                                         };\r
363 \r
364                                         // Fire unload when the currently loading page is stopped\r
365                                         d.attachEvent('onstop', stop);\r
366 \r
367                                         // Remove onstop listener after a while to prevent the unload function\r
368                                         // to execute if the user presses cancel in an onbeforeunload\r
369                                         // confirm dialog and then presses the browser stop button\r
370                                         window.setTimeout(function() {\r
371                                                 d.detachEvent('onstop', stop);\r
372                                         }, 0);\r
373                                 }\r
374                         };\r
375 \r
376                         // Attach unload handler\r
377                         if (w.attachEvent) {\r
378                                 w.attachEvent('onunload', unload);\r
379                                 w.attachEvent('onbeforeunload', fakeUnload);\r
380                         } else if (w.addEventListener)\r
381                                 w.addEventListener('unload', unload, false);\r
382 \r
383                         // Setup initial unload handler array\r
384                         t.unloads = [f];\r
385                 } else\r
386                         t.unloads.push(f);\r
387 \r
388                 return f;\r
389         },\r
390 \r
391         removeUnload : function(f) {\r
392                 var u = this.unloads, r = null;\r
393 \r
394                 tinymce.each(u, function(o, i) {\r
395                         if (o && o.func == f) {\r
396                                 u.splice(i, 1);\r
397                                 r = f;\r
398                                 return false;\r
399                         }\r
400                 });\r
401 \r
402                 return r;\r
403         },\r
404 \r
405         explode : function(s, d) {\r
406                 return s ? tinymce.map(s.split(d || ','), tinymce.trim) : s;\r
407         },\r
408 \r
409         _addVer : function(u) {\r
410                 var v;\r
411 \r
412                 if (!this.query)\r
413                         return u;\r
414 \r
415                 v = (u.indexOf('?') == -1 ? '?' : '&') + this.query;\r
416 \r
417                 if (u.indexOf('#') == -1)\r
418                         return u + v;\r
419 \r
420                 return u.replace('#', v + '#');\r
421         }\r
422 \r
423         };\r
424 \r
425 // Required for GZip AJAX loading\r
426 window.tinymce = tinymce;\r
427 \r
428 // Initialize the API\r
429 tinymce._init();\r
430 \r
431 /* file:jscripts/tiny_mce/classes/adapter/jquery/adapter.js */\r
432 \r
433 \r
434 /* file:jscripts/tiny_mce/classes/adapter/prototype/adapter.js */\r
435 \r
436 \r
437 /* file:jscripts/tiny_mce/classes/util/Dispatcher.js */\r
438 \r
439 tinymce.create('tinymce.util.Dispatcher', {\r
440         scope : null,\r
441         listeners : null,\r
442 \r
443         Dispatcher : function(s) {\r
444                 this.scope = s || this;\r
445                 this.listeners = [];\r
446         },\r
447 \r
448         add : function(cb, s) {\r
449                 this.listeners.push({cb : cb, scope : s || this.scope});\r
450 \r
451                 return cb;\r
452         },\r
453 \r
454         addToTop : function(cb, s) {\r
455                 this.listeners.unshift({cb : cb, scope : s || this.scope});\r
456 \r
457                 return cb;\r
458         },\r
459 \r
460         remove : function(cb) {\r
461                 var l = this.listeners, o = null;\r
462 \r
463                 tinymce.each(l, function(c, i) {\r
464                         if (cb == c.cb) {\r
465                                 o = cb;\r
466                                 l.splice(i, 1);\r
467                                 return false;\r
468                         }\r
469                 });\r
470 \r
471                 return o;\r
472         },\r
473 \r
474         dispatch : function() {\r
475                 var s, a = arguments, i, li = this.listeners, c;\r
476 \r
477                 // Needs to be a real loop since the listener count might change while looping\r
478                 // And this is also more efficient\r
479                 for (i = 0; i<li.length; i++) {\r
480                         c = li[i];\r
481                         s = c.cb.apply(c.scope, a);\r
482 \r
483                         if (s === false)\r
484                                 break;\r
485                 }\r
486 \r
487                 return s;\r
488         }\r
489 \r
490         });\r
491 \r
492 /* file:jscripts/tiny_mce/classes/util/URI.js */\r
493 \r
494 (function() {\r
495         var each = tinymce.each;\r
496 \r
497         tinymce.create('tinymce.util.URI', {\r
498                 URI : function(u, s) {\r
499                         var t = this, o, a, b;\r
500 \r
501                         // Default settings\r
502                         s = t.settings = s || {};\r
503 \r
504                         // Strange app protocol or local anchor\r
505                         if (/^(mailto|news|javascript|about):/i.test(u) || /^\s*#/.test(u)) {\r
506                                 t.source = u;\r
507                                 return;\r
508                         }\r
509 \r
510                         // Absolute path with no host, fake host and protocol\r
511                         if (u.indexOf('/') === 0 && u.indexOf('//') !== 0)\r
512                                 u = (s.base_uri ? s.base_uri.protocol || 'http' : 'http') + '://mce_host' + u;\r
513 \r
514                         // Relative path\r
515                         if (u.indexOf(':/') === -1 && u.indexOf('//') !== 0)\r
516                                 u = (s.base_uri.protocol || 'http') + '://mce_host' + t.toAbsPath(s.base_uri.path, u);\r
517 \r
518                         // Parse URL (Credits goes to Steave, http://blog.stevenlevithan.com/archives/parseuri)\r
519                         u = u.replace(/@@/g, '(mce_at)'); // Zope 3 workaround, they use @@something\r
520                         u = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(u);\r
521                         each(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], function(v, i) {\r
522                                 var s = u[i];\r
523 \r
524                                 // Zope 3 workaround, they use @@something\r
525                                 if (s)\r
526                                         s = s.replace(/\(mce_at\)/g, '@@');\r
527 \r
528                                 t[v] = s;\r
529                         });\r
530 \r
531                         if (b = s.base_uri) {\r
532                                 if (!t.protocol)\r
533                                         t.protocol = b.protocol;\r
534 \r
535                                 if (!t.userInfo)\r
536                                         t.userInfo = b.userInfo;\r
537 \r
538                                 if (!t.port && t.host == 'mce_host')\r
539                                         t.port = b.port;\r
540 \r
541                                 if (!t.host || t.host == 'mce_host')\r
542                                         t.host = b.host;\r
543 \r
544                                 t.source = '';\r
545                         }\r
546 \r
547                         //t.path = t.path || '/';\r
548                 },\r
549 \r
550                 setPath : function(p) {\r
551                         var t = this;\r
552 \r
553                         p = /^(.*?)\/?(\w+)?$/.exec(p);\r
554 \r
555                         // Update path parts\r
556                         t.path = p[0];\r
557                         t.directory = p[1];\r
558                         t.file = p[2];\r
559 \r
560                         // Rebuild source\r
561                         t.source = '';\r
562                         t.getURI();\r
563                 },\r
564 \r
565                 toRelative : function(u) {\r
566                         var t = this, o;\r
567 \r
568                         if (u === "./")\r
569                                 return u;\r
570 \r
571                         u = new tinymce.util.URI(u, {base_uri : t});\r
572 \r
573                         // Not on same domain/port or protocol\r
574                         if ((u.host != 'mce_host' && t.host != u.host && u.host) || t.port != u.port || t.protocol != u.protocol)\r
575                                 return u.getURI();\r
576 \r
577                         o = t.toRelPath(t.path, u.path);\r
578 \r
579                         // Add query\r
580                         if (u.query)\r
581                                 o += '?' + u.query;\r
582 \r
583                         // Add anchor\r
584                         if (u.anchor)\r
585                                 o += '#' + u.anchor;\r
586 \r
587                         return o;\r
588                 },\r
589         \r
590                 toAbsolute : function(u, nh) {\r
591                         var u = new tinymce.util.URI(u, {base_uri : this});\r
592 \r
593                         return u.getURI(this.host == u.host ? nh : 0);\r
594                 },\r
595 \r
596                 toRelPath : function(base, path) {\r
597                         var items, bp = 0, out = '', i, l;\r
598 \r
599                         // Split the paths\r
600                         base = base.substring(0, base.lastIndexOf('/'));\r
601                         base = base.split('/');\r
602                         items = path.split('/');\r
603 \r
604                         if (base.length >= items.length) {\r
605                                 for (i = 0, l = base.length; i < l; i++) {\r
606                                         if (i >= items.length || base[i] != items[i]) {\r
607                                                 bp = i + 1;\r
608                                                 break;\r
609                                         }\r
610                                 }\r
611                         }\r
612 \r
613                         if (base.length < items.length) {\r
614                                 for (i = 0, l = items.length; i < l; i++) {\r
615                                         if (i >= base.length || base[i] != items[i]) {\r
616                                                 bp = i + 1;\r
617                                                 break;\r
618                                         }\r
619                                 }\r
620                         }\r
621 \r
622                         if (bp == 1)\r
623                                 return path;\r
624 \r
625                         for (i = 0, l = base.length - (bp - 1); i < l; i++)\r
626                                 out += "../";\r
627 \r
628                         for (i = bp - 1, l = items.length; i < l; i++) {\r
629                                 if (i != bp - 1)\r
630                                         out += "/" + items[i];\r
631                                 else\r
632                                         out += items[i];\r
633                         }\r
634 \r
635                         return out;\r
636                 },\r
637 \r
638                 toAbsPath : function(base, path) {\r
639                         var i, nb = 0, o = [];\r
640 \r
641                         // Split paths\r
642                         base = base.split('/');\r
643                         path = path.split('/');\r
644 \r
645                         // Remove empty chunks\r
646                         each(base, function(k) {\r
647                                 if (k)\r
648                                         o.push(k);\r
649                         });\r
650 \r
651                         base = o;\r
652 \r
653                         // Merge relURLParts chunks\r
654                         for (i = path.length - 1, o = []; i >= 0; i--) {\r
655                                 // Ignore empty or .\r
656                                 if (path[i].length == 0 || path[i] == ".")\r
657                                         continue;\r
658 \r
659                                 // Is parent\r
660                                 if (path[i] == '..') {\r
661                                         nb++;\r
662                                         continue;\r
663                                 }\r
664 \r
665                                 // Move up\r
666                                 if (nb > 0) {\r
667                                         nb--;\r
668                                         continue;\r
669                                 }\r
670 \r
671                                 o.push(path[i]);\r
672                         }\r
673 \r
674                         i = base.length - nb;\r
675 \r
676                         // If /a/b/c or /\r
677                         if (i <= 0)\r
678                                 return '/' + o.reverse().join('/');\r
679 \r
680                         return '/' + base.slice(0, i).join('/') + '/' + o.reverse().join('/');\r
681                 },\r
682 \r
683                 getURI : function(nh) {\r
684                         var s, t = this;\r
685 \r
686                         // Rebuild source\r
687                         if (!t.source || nh) {\r
688                                 s = '';\r
689 \r
690                                 if (!nh) {\r
691                                         if (t.protocol)\r
692                                                 s += t.protocol + '://';\r
693 \r
694                                         if (t.userInfo)\r
695                                                 s += t.userInfo + '@';\r
696 \r
697                                         if (t.host)\r
698                                                 s += t.host;\r
699 \r
700                                         if (t.port)\r
701                                                 s += ':' + t.port;\r
702                                 }\r
703 \r
704                                 if (t.path)\r
705                                         s += t.path;\r
706 \r
707                                 if (t.query)\r
708                                         s += '?' + t.query;\r
709 \r
710                                 if (t.anchor)\r
711                                         s += '#' + t.anchor;\r
712 \r
713                                 t.source = s;\r
714                         }\r
715 \r
716                         return t.source;\r
717                 }\r
718 \r
719                 });\r
720 })();\r
721 \r
722 /* file:jscripts/tiny_mce/classes/util/Cookie.js */\r
723 \r
724 (function() {\r
725         var each = tinymce.each;\r
726 \r
727         tinymce.create('static tinymce.util.Cookie', {\r
728                 getHash : function(n) {\r
729                         var v = this.get(n), h;\r
730 \r
731                         if (v) {\r
732                                 each(v.split('&'), function(v) {\r
733                                         v = v.split('=');\r
734                                         h = h || {};\r
735                                         h[unescape(v[0])] = unescape(v[1]);\r
736                                 });\r
737                         }\r
738 \r
739                         return h;\r
740                 },\r
741 \r
742                 setHash : function(n, v, e, p, d, s) {\r
743                         var o = '';\r
744 \r
745                         each(v, function(v, k) {\r
746                                 o += (!o ? '' : '&') + escape(k) + '=' + escape(v);\r
747                         });\r
748 \r
749                         this.set(n, o, e, p, d, s);\r
750                 },\r
751 \r
752                 get : function(n) {\r
753                         var c = document.cookie, e, p = n + "=", b;\r
754 \r
755                         // Strict mode\r
756                         if (!c)\r
757                                 return;\r
758 \r
759                         b = c.indexOf("; " + p);\r
760 \r
761                         if (b == -1) {\r
762                                 b = c.indexOf(p);\r
763 \r
764                                 if (b != 0)\r
765                                         return null;\r
766                         } else\r
767                                 b += 2;\r
768 \r
769                         e = c.indexOf(";", b);\r
770 \r
771                         if (e == -1)\r
772                                 e = c.length;\r
773 \r
774                         return unescape(c.substring(b + p.length, e));\r
775                 },\r
776 \r
777                 set : function(n, v, e, p, d, s) {\r
778                         document.cookie = n + "=" + escape(v) +\r
779                                 ((e) ? "; expires=" + e.toGMTString() : "") +\r
780                                 ((p) ? "; path=" + escape(p) : "") +\r
781                                 ((d) ? "; domain=" + d : "") +\r
782                                 ((s) ? "; secure" : "");\r
783                 },\r
784 \r
785                 remove : function(n, p) {\r
786                         var d = new Date();\r
787 \r
788                         d.setTime(d.getTime() - 1000);\r
789 \r
790                         this.set(n, '', d, p, d);\r
791                 }\r
792 \r
793                 });\r
794 })();\r
795 \r
796 /* file:jscripts/tiny_mce/classes/util/JSON.js */\r
797 \r
798 tinymce.create('static tinymce.util.JSON', {\r
799         serialize : function(o) {\r
800                 var i, v, s = tinymce.util.JSON.serialize, t;\r
801 \r
802                 if (o == null)\r
803                         return 'null';\r
804 \r
805                 t = typeof o;\r
806 \r
807                 if (t == 'string') {\r
808                         v = '\bb\tt\nn\ff\rr\""\'\'\\\\';\r
809 \r
810                         return '"' + o.replace(/([\u0080-\uFFFF\x00-\x1f\"])/g, function(a, b) {\r
811                                 i = v.indexOf(b);\r
812 \r
813                                 if (i + 1)\r
814                                         return '\\' + v.charAt(i + 1);\r
815 \r
816                                 a = b.charCodeAt().toString(16);\r
817 \r
818                                 return '\\u' + '0000'.substring(a.length) + a;\r
819                         }) + '"';\r
820                 }\r
821 \r
822                 if (t == 'object') {\r
823                         if (o instanceof Array) {\r
824                                         for (i=0, v = '['; i<o.length; i++)\r
825                                                 v += (i > 0 ? ',' : '') + s(o[i]);\r
826 \r
827                                         return v + ']';\r
828                                 }\r
829 \r
830                                 v = '{';\r
831 \r
832                                 for (i in o)\r
833                                         v += typeof o[i] != 'function' ? (v.length > 1 ? ',"' : '"') + i + '":' + s(o[i]) : '';\r
834 \r
835                                 return v + '}';\r
836                 }\r
837 \r
838                 return '' + o;\r
839         },\r
840 \r
841         parse : function(s) {\r
842                 try {\r
843                         return eval('(' + s + ')');\r
844                 } catch (ex) {\r
845                         // Ignore\r
846                 }\r
847         }\r
848 \r
849         });\r
850 \r
851 /* file:jscripts/tiny_mce/classes/util/XHR.js */\r
852 \r
853 tinymce.create('static tinymce.util.XHR', {\r
854         send : function(o) {\r
855                 var x, t, w = window, c = 0;\r
856 \r
857                 // Default settings\r
858                 o.scope = o.scope || this;\r
859                 o.success_scope = o.success_scope || o.scope;\r
860                 o.error_scope = o.error_scope || o.scope;\r
861                 o.async = o.async === false ? false : true;\r
862                 o.data = o.data || '';\r
863 \r
864                 function get(s) {\r
865                         x = 0;\r
866 \r
867                         try {\r
868                                 x = new ActiveXObject(s);\r
869                         } catch (ex) {\r
870                         }\r
871 \r
872                         return x;\r
873                 };\r
874 \r
875                 x = w.XMLHttpRequest ? new XMLHttpRequest() : get('Microsoft.XMLHTTP') || get('Msxml2.XMLHTTP');\r
876 \r
877                 if (x) {\r
878                         if (x.overrideMimeType)\r
879                                 x.overrideMimeType(o.content_type);\r
880 \r
881                         x.open(o.type || (o.data ? 'POST' : 'GET'), o.url, o.async);\r
882 \r
883                         if (o.content_type)\r
884                                 x.setRequestHeader('Content-Type', o.content_type);\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 });\r
910 \r
911 /* file:jscripts/tiny_mce/classes/util/JSONRequest.js */\r
912 \r
913 (function() {\r
914         var extend = tinymce.extend, JSON = tinymce.util.JSON, XHR = tinymce.util.XHR;\r
915 \r
916         tinymce.create('tinymce.util.JSONRequest', {\r
917                 JSONRequest : function(s) {\r
918                         this.settings = extend({\r
919                         }, s);\r
920                         this.count = 0;\r
921                 },\r
922 \r
923                 send : function(o) {\r
924                         var ecb = o.error, scb = o.success;\r
925 \r
926                         o = extend(this.settings, o);\r
927 \r
928                         o.success = function(c, x) {\r
929                                 c = JSON.parse(c);\r
930 \r
931                                 if (typeof(c) == 'undefined') {\r
932                                         c = {\r
933                                                 error : 'JSON Parse error.'\r
934                                         };\r
935                                 }\r
936 \r
937                                 if (c.error)\r
938                                         ecb.call(o.error_scope || o.scope, c.error, x);\r
939                                 else\r
940                                         scb.call(o.success_scope || o.scope, c.result);\r
941                         };\r
942 \r
943                         o.error = function(ty, x) {\r
944                                 ecb.call(o.error_scope || o.scope, ty, x);\r
945                         };\r
946 \r
947                         o.data = JSON.serialize({\r
948                                 id : o.id || 'c' + (this.count++),\r
949                                 method : o.method,\r
950                                 params : o.params\r
951                         });\r
952 \r
953                         // JSON content type for Ruby on rails. Bug: #1883287\r
954                         o.content_type = 'application/json';\r
955 \r
956                         XHR.send(o);\r
957                 },\r
958 \r
959                 'static' : {\r
960                         sendRPC : function(o) {\r
961                                 return new tinymce.util.JSONRequest().send(o);\r
962                         }\r
963                 }\r
964 \r
965                 });\r
966 }());\r
967 /* file:jscripts/tiny_mce/classes/dom/DOMUtils.js */\r
968 \r
969 (function() {\r
970         // Shorten names\r
971         var each = tinymce.each, is = tinymce.is;\r
972         var isWebKit = tinymce.isWebKit, isIE = tinymce.isIE;\r
973 \r
974         tinymce.create('tinymce.dom.DOMUtils', {\r
975                 doc : null,\r
976                 root : null,\r
977                 files : null,\r
978                 listeners : {},\r
979                 pixelStyles : /^(top|left|bottom|right|width|height|borderWidth)$/,\r
980                 cache : {},\r
981                 idPattern : /^#[\w]+$/,\r
982                 elmPattern : /^[\w_*]+$/,\r
983                 elmClassPattern : /^([\w_]*)\.([\w_]+)$/,\r
984                 props : {\r
985                         "for" : "htmlFor",\r
986                         "class" : "className",\r
987                         className : "className",\r
988                         checked : "checked",\r
989                         disabled : "disabled",\r
990                         maxlength : "maxLength",\r
991                         readonly : "readOnly",\r
992                         selected : "selected",\r
993                         value : "value",\r
994                         id : "id",\r
995                         name : "name",\r
996                         type : "type"\r
997                 },\r
998 \r
999                 DOMUtils : function(d, s) {\r
1000                         var t = this;\r
1001 \r
1002                         t.doc = d;\r
1003                         t.win = window;\r
1004                         t.files = {};\r
1005                         t.cssFlicker = false;\r
1006                         t.counter = 0;\r
1007                         t.boxModel = !tinymce.isIE || d.compatMode == "CSS1Compat"; \r
1008                         t.stdMode = d.documentMode === 8;\r
1009 \r
1010                         this.settings = s = tinymce.extend({\r
1011                                 keep_values : false,\r
1012                                 hex_colors : 1,\r
1013                                 process_html : 1\r
1014                         }, s);\r
1015 \r
1016                         // Fix IE6SP2 flicker and check it failed for pre SP2\r
1017                         if (tinymce.isIE6) {\r
1018                                 try {\r
1019                                         d.execCommand('BackgroundImageCache', false, true);\r
1020                                 } catch (e) {\r
1021                                         t.cssFlicker = true;\r
1022                                 }\r
1023                         }\r
1024 \r
1025                         tinymce.addUnload(t.destroy, t);\r
1026                 },\r
1027 \r
1028                 getRoot : function() {\r
1029                         var t = this, s = t.settings;\r
1030 \r
1031                         return (s && t.get(s.root_element)) || t.doc.body;\r
1032                 },\r
1033 \r
1034                 getViewPort : function(w) {\r
1035                         var d, b;\r
1036 \r
1037                         w = !w ? this.win : w;\r
1038                         d = w.document;\r
1039                         b = this.boxModel ? d.documentElement : d.body;\r
1040 \r
1041                         // Returns viewport size excluding scrollbars\r
1042                         return {\r
1043                                 x : w.pageXOffset || b.scrollLeft,\r
1044                                 y : w.pageYOffset || b.scrollTop,\r
1045                                 w : w.innerWidth || b.clientWidth,\r
1046                                 h : w.innerHeight || b.clientHeight\r
1047                         };\r
1048                 },\r
1049 \r
1050                 getRect : function(e) {\r
1051                         var p, t = this, sr;\r
1052 \r
1053                         e = t.get(e);\r
1054                         p = t.getPos(e);\r
1055                         sr = t.getSize(e);\r
1056 \r
1057                         return {\r
1058                                 x : p.x,\r
1059                                 y : p.y,\r
1060                                 w : sr.w,\r
1061                                 h : sr.h\r
1062                         };\r
1063                 },\r
1064 \r
1065                 getSize : function(e) {\r
1066                         var t = this, w, h;\r
1067 \r
1068                         e = t.get(e);\r
1069                         w = t.getStyle(e, 'width');\r
1070                         h = t.getStyle(e, 'height');\r
1071 \r
1072                         // Non pixel value, then force offset/clientWidth\r
1073                         if (w.indexOf('px') === -1)\r
1074                                 w = 0;\r
1075 \r
1076                         // Non pixel value, then force offset/clientWidth\r
1077                         if (h.indexOf('px') === -1)\r
1078                                 h = 0;\r
1079 \r
1080                         return {\r
1081                                 w : parseInt(w) || e.offsetWidth || e.clientWidth,\r
1082                                 h : parseInt(h) || e.offsetHeight || e.clientHeight\r
1083                         };\r
1084                 },\r
1085 \r
1086                 getParent : function(n, f, r) {\r
1087                         var na, se = this.settings;\r
1088 \r
1089                         n = this.get(n);\r
1090 \r
1091                         if (se.strict_root)\r
1092                                 r = r || this.getRoot();\r
1093 \r
1094                         // Wrap node name as func\r
1095                         if (is(f, 'string')) {\r
1096                                 na = f.toUpperCase();\r
1097 \r
1098                                 f = function(n) {\r
1099                                         var s = false;\r
1100 \r
1101                                         // Any element\r
1102                                         if (n.nodeType == 1 && na === '*') {\r
1103                                                 s = true;\r
1104                                                 return false;\r
1105                                         }\r
1106 \r
1107                                         each(na.split(','), function(v) {\r
1108                                                 if (n.nodeType == 1 && ((se.strict && n.nodeName.toUpperCase() == v) || n.nodeName.toUpperCase() == v)) {\r
1109                                                         s = true;\r
1110                                                         return false; // Break loop\r
1111                                                 }\r
1112                                         });\r
1113 \r
1114                                         return s;\r
1115                                 };\r
1116                         }\r
1117 \r
1118                         while (n) {\r
1119                                 if (n == r)\r
1120                                         return null;\r
1121 \r
1122                                 if (f(n))\r
1123                                         return n;\r
1124 \r
1125                                 n = n.parentNode;\r
1126                         }\r
1127 \r
1128                         return null;\r
1129                 },\r
1130 \r
1131                 get : function(e) {\r
1132                         var n;\r
1133 \r
1134                         if (e && this.doc && typeof(e) == 'string') {\r
1135                                 n = e;\r
1136                                 e = this.doc.getElementById(e);\r
1137 \r
1138                                 // IE and Opera returns meta elements when they match the specified input ID, but getElementsByName seems to do the trick\r
1139                                 if (e && e.id !== n)\r
1140                                         return this.doc.getElementsByName(n)[1];\r
1141                         }\r
1142 \r
1143                         return e;\r
1144                 },\r
1145 \r
1146                 \r
1147                 // #if !jquery\r
1148 \r
1149                 select : function(pa, s) {\r
1150                         var t = this, cs, c, pl, o = [], x, i, l, n, xp;\r
1151 \r
1152                         s = t.get(s) || t.doc;\r
1153 \r
1154                         // Look for native support and use that if it's found\r
1155                         if (s.querySelectorAll) {\r
1156                                 // Element scope then use temp id\r
1157                                 // We need to do this to be compatible with other implementations\r
1158                                 // See bug report: http://bugs.webkit.org/show_bug.cgi?id=17461\r
1159                                 if (s != t.doc) {\r
1160                                         i = s.id;\r
1161                                         s.id = '_mc_tmp';\r
1162                                         pa = '#_mc_tmp ' + pa;\r
1163                                 }\r
1164 \r
1165                                 // Select elements\r
1166                                 l = tinymce.grep(s.querySelectorAll(pa));\r
1167 \r
1168                                 // Restore old id\r
1169                                 s.id = i;\r
1170 \r
1171                                 return l;\r
1172                         }\r
1173 \r
1174                         if (!t.selectorRe)\r
1175                                 t.selectorRe = /^([\w\\*]+)?(?:#([\w\\]+))?(?:\.([\w\\\.]+))?(?:\[\@([\w\\]+)([\^\$\*!]?=)([\w\\]+)\])?(?:\:([\w\\]+))?/i;;\r
1176 \r
1177                         // Air doesn't support eval due to security sandboxing and querySelectorAll isn't supported yet\r
1178                         if (tinymce.isAir) {\r
1179                                 each(tinymce.explode(pa), function(v) {\r
1180                                         if (!(xp = t.cache[v])) {\r
1181                                                 xp = '';\r
1182 \r
1183                                                 each(v.split(' '), function(v) {\r
1184                                                         v = t.selectorRe.exec(v);\r
1185 \r
1186                                                         xp += v[1] ? '//' + v[1] : '//*';\r
1187 \r
1188                                                         // Id\r
1189                                                         if (v[2])\r
1190                                                                 xp += "[@id='" + v[2] + "']";\r
1191 \r
1192                                                         // Class\r
1193                                                         if (v[3]) {\r
1194                                                                 each(v[3].split('.'), function(n) {\r
1195                                                                         xp += "[@class = '" + n + "' or contains(concat(' ', @class, ' '), ' " + n + " ')]";\r
1196                                                                 });\r
1197                                                         }\r
1198                                                 });\r
1199 \r
1200                                                 t.cache[v] = xp;\r
1201                                         }\r
1202 \r
1203                                         xp = t.doc.evaluate(xp, s, null, 4, null);\r
1204 \r
1205                                         while (n = xp.iterateNext())\r
1206                                                 o.push(n);\r
1207                                 });\r
1208 \r
1209                                 return o;\r
1210                         }\r
1211 \r
1212                         if (t.settings.strict) {\r
1213                                 function get(s, n) {\r
1214                                         return s.getElementsByTagName(n.toLowerCase());\r
1215                                 };\r
1216                         } else {\r
1217                                 function get(s, n) {\r
1218                                         return s.getElementsByTagName(n);\r
1219                                 };\r
1220                         }\r
1221 \r
1222                         // Simple element pattern. For example: "p" or "*"\r
1223                         if (t.elmPattern.test(pa)) {\r
1224                                 x = get(s, pa);\r
1225 \r
1226                                 for (i = 0, l = x.length; i<l; i++)\r
1227                                         o.push(x[i]);\r
1228 \r
1229                                 return o;\r
1230                         }\r
1231 \r
1232                         // Simple class pattern. For example: "p.class" or ".class"\r
1233                         if (t.elmClassPattern.test(pa)) {\r
1234                                 pl = t.elmClassPattern.exec(pa);\r
1235                                 x = get(s, pl[1] || '*');\r
1236                                 c = ' ' + pl[2] + ' ';\r
1237 \r
1238                                 for (i = 0, l = x.length; i<l; i++) {\r
1239                                         n = x[i];\r
1240 \r
1241                                         if (n.className && (' ' + n.className + ' ').indexOf(c) !== -1)\r
1242                                                 o.push(n);\r
1243                                 }\r
1244 \r
1245                                 return o;\r
1246                         }\r
1247 \r
1248                         function collect(n) {\r
1249                                 if (!n.mce_save) {\r
1250                                         n.mce_save = 1;\r
1251                                         o.push(n);\r
1252                                 }\r
1253                         };\r
1254 \r
1255                         function collectIE(n) {\r
1256                                 if (!n.getAttribute('mce_save')) {\r
1257                                         n.setAttribute('mce_save', '1');\r
1258                                         o.push(n);\r
1259                                 }\r
1260                         };\r
1261 \r
1262                         function find(n, f, r) {\r
1263                                 var i, l, nl = get(r, n);\r
1264 \r
1265                                 for (i = 0, l = nl.length; i < l; i++)\r
1266                                         f(nl[i]);\r
1267                         };\r
1268 \r
1269                         each(pa.split(','), function(v, i) {\r
1270                                 v = tinymce.trim(v);\r
1271 \r
1272                                 // Simple element pattern, most common in TinyMCE\r
1273                                 if (t.elmPattern.test(v)) {\r
1274                                         each(get(s, v), function(n) {\r
1275                                                 collect(n);\r
1276                                         });\r
1277 \r
1278                                         return;\r
1279                                 }\r
1280 \r
1281                                 // Simple element pattern with class, fairly common in TinyMCE\r
1282                                 if (t.elmClassPattern.test(v)) {\r
1283                                         x = t.elmClassPattern.exec(v);\r
1284 \r
1285                                         each(get(s, x[1]), function(n) {\r
1286                                                 if (t.hasClass(n, x[2]))\r
1287                                                         collect(n);\r
1288                                         });\r
1289 \r
1290                                         return;\r
1291                                 }\r
1292 \r
1293                                 if (!(cs = t.cache[pa])) {\r
1294                                         cs = 'x=(function(cf, s) {';\r
1295                                         pl = v.split(' ');\r
1296 \r
1297                                         each(pl, function(v) {\r
1298                                                 var p = t.selectorRe.exec(v);\r
1299 \r
1300                                                 // Find elements\r
1301                                                 p[1] = p[1] || '*';\r
1302                                                 cs += 'find("' + p[1] + '", function(n) {';\r
1303 \r
1304                                                 // Check id\r
1305                                                 if (p[2])\r
1306                                                         cs += 'if (n.id !== "' + p[2] + '") return;';\r
1307 \r
1308                                                 // Check classes\r
1309                                                 if (p[3]) {\r
1310                                                         cs += 'var c = " " + n.className + " ";';\r
1311                                                         cs += 'if (';\r
1312                                                         c = '';\r
1313                                                         each(p[3].split('.'), function(v) {\r
1314                                                                 if (v)\r
1315                                                                         c += (c ? '||' : '') + 'c.indexOf(" ' + v + ' ") === -1';\r
1316                                                         });\r
1317                                                         cs += c + ') return;';\r
1318                                                 }\r
1319                                         });\r
1320 \r
1321                                         cs += 'cf(n);';\r
1322 \r
1323                                         for (i = pl.length - 1; i >= 0; i--)\r
1324                                                 cs += '}, ' + (i ? 'n' : 's') + ');';\r
1325 \r
1326                                         cs += '})';\r
1327 \r
1328                                         // Compile CSS pattern function\r
1329                                         t.cache[pa] = cs = eval(cs);\r
1330                                 }\r
1331 \r
1332                                 // Run selector function\r
1333                                 cs(isIE ? collectIE : collect, s);\r
1334                         });\r
1335 \r
1336                         // Cleanup\r
1337                         each(o, function(n) {\r
1338                                 if (isIE)\r
1339                                         n.removeAttribute('mce_save');\r
1340                                 else\r
1341                                         delete n.mce_save;\r
1342                         });\r
1343 \r
1344                         return o;\r
1345                 },\r
1346 \r
1347                 // #endif\r
1348 \r
1349                 add : function(p, n, a, h, c) {\r
1350                         var t = this;\r
1351 \r
1352                         return this.run(p, function(p) {\r
1353                                 var e, k;\r
1354 \r
1355                                 e = is(n, 'string') ? t.doc.createElement(n) : n;\r
1356                                 t.setAttribs(e, a);\r
1357 \r
1358                                 if (h) {\r
1359                                         if (h.nodeType)\r
1360                                                 e.appendChild(h);\r
1361                                         else\r
1362                                                 t.setHTML(e, h);\r
1363                                 }\r
1364 \r
1365                                 return !c ? p.appendChild(e) : e;\r
1366                         });\r
1367                 },\r
1368 \r
1369                 create : function(n, a, h) {\r
1370                         return this.add(this.doc.createElement(n), n, a, h, 1);\r
1371                 },\r
1372 \r
1373                 createHTML : function(n, a, h) {\r
1374                         var o = '', t = this, k;\r
1375 \r
1376                         o += '<' + n;\r
1377 \r
1378                         for (k in a) {\r
1379                                 if (a.hasOwnProperty(k))\r
1380                                         o += ' ' + k + '="' + t.encode(a[k]) + '"';\r
1381                         }\r
1382 \r
1383                         if (tinymce.is(h))\r
1384                                 return o + '>' + h + '</' + n + '>';\r
1385 \r
1386                         return o + ' />';\r
1387                 },\r
1388 \r
1389                 remove : function(n, k) {\r
1390                         return this.run(n, function(n) {\r
1391                                 var p, g;\r
1392 \r
1393                                 p = n.parentNode;\r
1394 \r
1395                                 if (!p)\r
1396                                         return null;\r
1397 \r
1398                                 if (k) {\r
1399                                         each (n.childNodes, function(c) {\r
1400                                                 p.insertBefore(c.cloneNode(true), n);\r
1401                                         });\r
1402                                 }\r
1403 \r
1404                                 // Fix IE psuedo leak\r
1405                 /*              if (isIE) {\r
1406                                         p = n.cloneNode(true);\r
1407                                         n.outerHTML = '';\r
1408 \r
1409                                         return p;\r
1410                                 }*/\r
1411 \r
1412                                 return p.removeChild(n);\r
1413                         });\r
1414                 },\r
1415 \r
1416                 // #if !jquery\r
1417 \r
1418                 setStyle : function(n, na, v) {\r
1419                         var t = this;\r
1420 \r
1421                         return t.run(n, function(e) {\r
1422                                 var s, i;\r
1423 \r
1424                                 s = e.style;\r
1425 \r
1426                                 // Camelcase it, if needed\r
1427                                 na = na.replace(/-(\D)/g, function(a, b){\r
1428                                         return b.toUpperCase();\r
1429                                 });\r
1430 \r
1431                                 // Default px suffix on these\r
1432                                 if (t.pixelStyles.test(na) && (tinymce.is(v, 'number') || /^[\-0-9\.]+$/.test(v)))\r
1433                                         v += 'px';\r
1434 \r
1435                                 switch (na) {\r
1436                                         case 'opacity':\r
1437                                                 // IE specific opacity\r
1438                                                 if (isIE) {\r
1439                                                         s.filter = v === '' ? '' : "alpha(opacity=" + (v * 100) + ")";\r
1440 \r
1441                                                         if (!n.currentStyle || !n.currentStyle.hasLayout)\r
1442                                                                 s.display = 'inline-block';\r
1443                                                 }\r
1444 \r
1445                                                 // Fix for older browsers\r
1446                                                 s[na] = s['-moz-opacity'] = s['-khtml-opacity'] = v || '';\r
1447                                                 break;\r
1448 \r
1449                                         case 'float':\r
1450                                                 isIE ? s.styleFloat = v : s.cssFloat = v;\r
1451                                                 break;\r
1452                                         \r
1453                                         default:\r
1454                                                 s[na] = v || '';\r
1455                                 }\r
1456 \r
1457                                 // Force update of the style data\r
1458                                 if (t.settings.update_styles)\r
1459                                         t.setAttrib(e, 'mce_style');\r
1460                         });\r
1461                 },\r
1462 \r
1463                 getStyle : function(n, na, c) {\r
1464                         n = this.get(n);\r
1465 \r
1466                         if (!n)\r
1467                                 return false;\r
1468 \r
1469                         // Gecko\r
1470                         if (this.doc.defaultView && c) {\r
1471                                 // Remove camelcase\r
1472                                 na = na.replace(/[A-Z]/g, function(a){\r
1473                                         return '-' + a;\r
1474                                 });\r
1475 \r
1476                                 try {\r
1477                                         return this.doc.defaultView.getComputedStyle(n, null).getPropertyValue(na);\r
1478                                 } catch (ex) {\r
1479                                         // Old safari might fail\r
1480                                         return null;\r
1481                                 }\r
1482                         }\r
1483 \r
1484                         // Camelcase it, if needed\r
1485                         na = na.replace(/-(\D)/g, function(a, b){\r
1486                                 return b.toUpperCase();\r
1487                         });\r
1488 \r
1489                         if (na == 'float')\r
1490                                 na = isIE ? 'styleFloat' : 'cssFloat';\r
1491 \r
1492                         // IE & Opera\r
1493                         if (n.currentStyle && c)\r
1494                                 return n.currentStyle[na];\r
1495 \r
1496                         return n.style[na];\r
1497                 },\r
1498 \r
1499                 setStyles : function(e, o) {\r
1500                         var t = this, s = t.settings, ol;\r
1501 \r
1502                         ol = s.update_styles;\r
1503                         s.update_styles = 0;\r
1504 \r
1505                         each(o, function(v, n) {\r
1506                                 t.setStyle(e, n, v);\r
1507                         });\r
1508 \r
1509                         // Update style info\r
1510                         s.update_styles = ol;\r
1511                         if (s.update_styles)\r
1512                                 t.setAttrib(e, s.cssText);\r
1513                 },\r
1514 \r
1515                 setAttrib : function(e, n, v) {\r
1516                         var t = this;\r
1517 \r
1518                         // Whats the point\r
1519                         if (!e || !n)\r
1520                                 return;\r
1521 \r
1522                         // Strict XML mode\r
1523                         if (t.settings.strict)\r
1524                                 n = n.toLowerCase();\r
1525 \r
1526                         return this.run(e, function(e) {\r
1527                                 var s = t.settings;\r
1528 \r
1529                                 switch (n) {\r
1530                                         case "style":\r
1531                                                 if (!is(v, 'string')) {\r
1532                                                         each(v, function(v, n) {\r
1533                                                                 t.setStyle(e, n, v);\r
1534                                                         });\r
1535 \r
1536                                                         return;\r
1537                                                 }\r
1538 \r
1539                                                 // No mce_style for elements with these since they might get resized by the user\r
1540                                                 if (s.keep_values) {\r
1541                                                         if (v && !t._isRes(v))\r
1542                                                                 e.setAttribute('mce_style', v, 2);\r
1543                                                         else\r
1544                                                                 e.removeAttribute('mce_style', 2);\r
1545                                                 }\r
1546 \r
1547                                                 e.style.cssText = v;\r
1548                                                 break;\r
1549 \r
1550                                         case "class":\r
1551                                                 e.className = v || ''; // Fix IE null bug\r
1552                                                 break;\r
1553 \r
1554                                         case "src":\r
1555                                         case "href":\r
1556                                                 if (s.keep_values) {\r
1557                                                         if (s.url_converter)\r
1558                                                                 v = s.url_converter.call(s.url_converter_scope || t, v, n, e);\r
1559 \r
1560                                                         t.setAttrib(e, 'mce_' + n, v, 2);\r
1561                                                 }\r
1562 \r
1563                                                 break;\r
1564                                         \r
1565                                         case "shape":\r
1566                                                 e.setAttribute('mce_style', v);\r
1567                                                 break;\r
1568                                 }\r
1569 \r
1570                                 if (is(v) && v !== null && v.length !== 0)\r
1571                                         e.setAttribute(n, '' + v, 2);\r
1572                                 else\r
1573                                         e.removeAttribute(n, 2);\r
1574                         });\r
1575                 },\r
1576 \r
1577                 setAttribs : function(e, o) {\r
1578                         var t = this;\r
1579 \r
1580                         return this.run(e, function(e) {\r
1581                                 each(o, function(v, n) {\r
1582                                         t.setAttrib(e, n, v);\r
1583                                 });\r
1584                         });\r
1585                 },\r
1586 \r
1587                 // #endif\r
1588 \r
1589                 getAttrib : function(e, n, dv) {\r
1590                         var v, t = this;\r
1591 \r
1592                         e = t.get(e);\r
1593 \r
1594                         if (!e || e.nodeType !== 1)\r
1595                                 return false;\r
1596 \r
1597                         if (!is(dv))\r
1598                                 dv = '';\r
1599 \r
1600                         // Try the mce variant for these\r
1601                         if (/^(src|href|style|coords|shape)$/.test(n)) {\r
1602                                 v = e.getAttribute("mce_" + n);\r
1603 \r
1604                                 if (v)\r
1605                                         return v;\r
1606                         }\r
1607 \r
1608                         if (isIE && t.props[n]) {\r
1609                                 v = e[t.props[n]];\r
1610                                 v = v && v.nodeValue ? v.nodeValue : v;\r
1611                         }\r
1612 \r
1613                         if (!v)\r
1614                                 v = e.getAttribute(n, 2);\r
1615 \r
1616                         if (n === 'style') {\r
1617                                 v = v || e.style.cssText;\r
1618 \r
1619                                 if (v) {\r
1620                                         v = t.serializeStyle(t.parseStyle(v));\r
1621 \r
1622                                         if (t.settings.keep_values && !t._isRes(v))\r
1623                                                 e.setAttribute('mce_style', v);\r
1624                                 }\r
1625                         }\r
1626 \r
1627                         // Remove Apple and WebKit stuff\r
1628                         if (isWebKit && n === "class" && v)\r
1629                                 v = v.replace(/(apple|webkit)\-[a-z\-]+/gi, '');\r
1630 \r
1631                         // Handle IE issues\r
1632                         if (isIE) {\r
1633                                 switch (n) {\r
1634                                         case 'rowspan':\r
1635                                         case 'colspan':\r
1636                                                 // IE returns 1 as default value\r
1637                                                 if (v === 1)\r
1638                                                         v = '';\r
1639 \r
1640                                                 break;\r
1641 \r
1642                                         case 'size':\r
1643                                                 // IE returns +0 as default value for size\r
1644                                                 if (v === '+0' || v === 20)\r
1645                                                         v = '';\r
1646 \r
1647                                                 break;\r
1648 \r
1649                                         case 'width':\r
1650                                         case 'height':\r
1651                                         case 'vspace':\r
1652                                         case 'checked':\r
1653                                         case 'disabled':\r
1654                                         case 'readonly':\r
1655                                                 if (v === 0)\r
1656                                                         v = '';\r
1657 \r
1658                                                 break;\r
1659 \r
1660                                         case 'hspace':\r
1661                                                 // IE returns -1 as default value\r
1662                                                 if (v === -1)\r
1663                                                         v = '';\r
1664 \r
1665                                                 break;\r
1666 \r
1667                                         case 'maxlength':\r
1668                                         case 'tabindex':\r
1669                                                 // IE returns default value\r
1670                                                 if (v === 32768 || v === 2147483647 || v === '32768')\r
1671                                                         v = '';\r
1672 \r
1673                                                 break;\r
1674 \r
1675                                         case 'compact':\r
1676                                         case 'noshade':\r
1677                                         case 'nowrap':\r
1678                                                 if (v === 65535)\r
1679                                                         return n;\r
1680 \r
1681                                                 return dv;\r
1682 \r
1683                                         case 'shape':\r
1684                                                 v = v.toLowerCase();\r
1685                                                 break;\r
1686 \r
1687                                         default:\r
1688                                                 // IE has odd anonymous function for event attributes\r
1689                                                 if (n.indexOf('on') === 0 && v)\r
1690                                                         v = ('' + v).replace(/^function\s+anonymous\(\)\s+\{\s+(.*)\s+\}$/, '$1');\r
1691                                 }\r
1692                         }\r
1693 \r
1694                         return (v !== undefined && v !== null && v !== '') ? '' + v : dv;\r
1695                 },\r
1696 \r
1697                 getPos : function(n) {\r
1698                         var t = this, x = 0, y = 0, e, d = t.doc, r;\r
1699 \r
1700                         n = t.get(n);\r
1701 \r
1702                         // Use getBoundingClientRect on IE, Opera has it but it's not perfect\r
1703                         if (n && isIE) {\r
1704                                 n = n.getBoundingClientRect();\r
1705                                 e = t.boxModel ? d.documentElement : d.body;\r
1706                                 x = t.getStyle(t.select('html')[0], 'borderWidth'); // Remove border\r
1707                                 x = (x == 'medium' || t.boxModel && !t.isIE6) && 2 || x;\r
1708                                 n.top += t.win.self != t.win.top ? 2 : 0; // IE adds some strange extra cord if used in a frameset\r
1709 \r
1710                                 return {x : n.left + e.scrollLeft - x, y : n.top + e.scrollTop - x};\r
1711                         }\r
1712 \r
1713                         r = n;\r
1714                         while (r) {\r
1715                                 x += r.offsetLeft || 0;\r
1716                                 y += r.offsetTop || 0;\r
1717                                 r = r.offsetParent;\r
1718                         }\r
1719 \r
1720                         r = n;\r
1721                         while (r) {\r
1722                                 // Opera 9.25 bug fix, fixed in 9.50\r
1723                                 if (!/^table-row|inline.*/i.test(t.getStyle(r, "display", 1))) {\r
1724                                         x -= r.scrollLeft || 0;\r
1725                                         y -= r.scrollTop || 0;\r
1726                                 }\r
1727 \r
1728                                 r = r.parentNode;\r
1729 \r
1730                                 if (r == d.body)\r
1731                                         break;\r
1732                         }\r
1733 \r
1734                         return {x : x, y : y};\r
1735                 },\r
1736 \r
1737                 parseStyle : function(st) {\r
1738                         var t = this, s = t.settings, o = {};\r
1739 \r
1740                         if (!st)\r
1741                                 return o;\r
1742 \r
1743                         function compress(p, s, ot) {\r
1744                                 var t, r, b, l;\r
1745 \r
1746                                 // Get values and check it it needs compressing\r
1747                                 t = o[p + '-top' + s];\r
1748                                 if (!t)\r
1749                                         return;\r
1750 \r
1751                                 r = o[p + '-right' + s];\r
1752                                 if (t != r)\r
1753                                         return;\r
1754 \r
1755                                 b = o[p + '-bottom' + s];\r
1756                                 if (r != b)\r
1757                                         return;\r
1758 \r
1759                                 l = o[p + '-left' + s];\r
1760                                 if (b != l)\r
1761                                         return;\r
1762 \r
1763                                 // Compress\r
1764                                 o[ot] = l;\r
1765                                 delete o[p + '-top' + s];\r
1766                                 delete o[p + '-right' + s];\r
1767                                 delete o[p + '-bottom' + s];\r
1768                                 delete o[p + '-left' + s];\r
1769                         };\r
1770 \r
1771                         function compress2(ta, a, b, c) {\r
1772                                 var t;\r
1773 \r
1774                                 t = o[a];\r
1775                                 if (!t)\r
1776                                         return;\r
1777 \r
1778                                 t = o[b];\r
1779                                 if (!t)\r
1780                                         return;\r
1781 \r
1782                                 t = o[c];\r
1783                                 if (!t)\r
1784                                         return;\r
1785 \r
1786                                 // Compress\r
1787                                 o[ta] = o[a] + ' ' + o[b] + ' ' + o[c];\r
1788                                 delete o[a];\r
1789                                 delete o[b];\r
1790                                 delete o[c];\r
1791                         };\r
1792 \r
1793                         st = st.replace(/&(#?[a-z0-9]+);/g, '&$1_MCE_SEMI_'); // Protect entities\r
1794 \r
1795                         each(st.split(';'), function(v) {\r
1796                                 var sv, ur = [];\r
1797 \r
1798                                 if (v) {\r
1799                                         v = v.replace(/_MCE_SEMI_/g, ';'); // Restore entities\r
1800                                         v = v.replace(/url\([^\)]+\)/g, function(v) {ur.push(v);return 'url(' + ur.length + ')';});\r
1801                                         v = v.split(':');\r
1802                                         sv = tinymce.trim(v[1]);\r
1803                                         sv = sv.replace(/url\(([^\)]+)\)/g, function(a, b) {return ur[parseInt(b) - 1];});\r
1804 \r
1805                                         sv = sv.replace(/rgb\([^\)]+\)/g, function(v) {\r
1806                                                 return t.toHex(v);\r
1807                                         });\r
1808 \r
1809                                         if (s.url_converter) {\r
1810                                                 sv = sv.replace(/url\([\'\"]?([^\)\'\"]+)[\'\"]?\)/g, function(x, c) {\r
1811                                                         return 'url(' + s.url_converter.call(s.url_converter_scope || t, t.decode(c), 'style', null) + ')';\r
1812                                                 });\r
1813                                         }\r
1814 \r
1815                                         o[tinymce.trim(v[0]).toLowerCase()] = sv;\r
1816                                 }\r
1817                         });\r
1818 \r
1819                         compress("border", "", "border");\r
1820                         compress("border", "-width", "border-width");\r
1821                         compress("border", "-color", "border-color");\r
1822                         compress("border", "-style", "border-style");\r
1823                         compress("padding", "", "padding");\r
1824                         compress("margin", "", "margin");\r
1825                         compress2('border', 'border-width', 'border-style', 'border-color');\r
1826 \r
1827                         if (isIE) {\r
1828                                 // Remove pointless border\r
1829                                 if (o.border == 'medium none')\r
1830                                         o.border = '';\r
1831                         }\r
1832 \r
1833                         return o;\r
1834                 },\r
1835 \r
1836                 serializeStyle : function(o) {\r
1837                         var s = '';\r
1838 \r
1839                         each(o, function(v, k) {\r
1840                                 if (k && v) {\r
1841                                         if (tinymce.isGecko && k.indexOf('-moz-') === 0)\r
1842                                                 return;\r
1843 \r
1844                                         switch (k) {\r
1845                                                 case 'color':\r
1846                                                 case 'background-color':\r
1847                                                         v = v.toLowerCase();\r
1848                                                         break;\r
1849                                         }\r
1850 \r
1851                                         s += (s ? ' ' : '') + k + ': ' + v + ';';\r
1852                                 }\r
1853                         });\r
1854 \r
1855                         return s;\r
1856                 },\r
1857 \r
1858                 loadCSS : function(u) {\r
1859                         var t = this, d = t.doc;\r
1860 \r
1861                         if (!u)\r
1862                                 u = '';\r
1863 \r
1864                         each(u.split(','), function(u) {\r
1865                                 if (t.files[u])\r
1866                                         return;\r
1867 \r
1868                                 t.files[u] = true;\r
1869                                 t.add(t.select('head')[0], 'link', {rel : 'stylesheet', href : tinymce._addVer(u)});\r
1870                         });\r
1871                 },\r
1872 \r
1873                 // #if !jquery\r
1874 \r
1875                 addClass : function(e, c) {\r
1876                         return this.run(e, function(e) {\r
1877                                 var o;\r
1878 \r
1879                                 if (!c)\r
1880                                         return 0;\r
1881 \r
1882                                 if (this.hasClass(e, c))\r
1883                                         return e.className;\r
1884 \r
1885                                 o = this.removeClass(e, c);\r
1886 \r
1887                                 return e.className = (o != '' ? (o + ' ') : '') + c;\r
1888                         });\r
1889                 },\r
1890 \r
1891                 removeClass : function(e, c) {\r
1892                         var t = this, re;\r
1893 \r
1894                         return t.run(e, function(e) {\r
1895                                 var v;\r
1896 \r
1897                                 if (t.hasClass(e, c)) {\r
1898                                         if (!re)\r
1899                                                 re = new RegExp("(^|\\s+)" + c + "(\\s+|$)", "g");\r
1900 \r
1901                                         v = e.className.replace(re, ' ');\r
1902 \r
1903                                         return e.className = tinymce.trim(v != ' ' ? v : '');\r
1904                                 }\r
1905 \r
1906                                 return e.className;\r
1907                         });\r
1908                 },\r
1909 \r
1910                 hasClass : function(n, c) {\r
1911                         n = this.get(n);\r
1912 \r
1913                         if (!n || !c)\r
1914                                 return false;\r
1915 \r
1916                         return (' ' + n.className + ' ').indexOf(' ' + c + ' ') !== -1;\r
1917                 },\r
1918 \r
1919                 show : function(e) {\r
1920                         return this.setStyle(e, 'display', 'block');\r
1921                 },\r
1922 \r
1923                 hide : function(e) {\r
1924                         return this.setStyle(e, 'display', 'none');\r
1925                 },\r
1926 \r
1927                 isHidden : function(e) {\r
1928                         e = this.get(e);\r
1929 \r
1930                         return !e || e.style.display == 'none' || this.getStyle(e, 'display') == 'none';\r
1931                 },\r
1932 \r
1933                 // #endif\r
1934 \r
1935                 uniqueId : function(p) {\r
1936                         return (!p ? 'mce_' : p) + (this.counter++);\r
1937                 },\r
1938 \r
1939                 setHTML : function(e, h) {\r
1940                         var t = this;\r
1941 \r
1942                         return this.run(e, function(e) {\r
1943                                 var x, i, nl, n, p, x;\r
1944 \r
1945                                 h = t.processHTML(h);\r
1946 \r
1947                                 if (isIE) {\r
1948                                         function set() {\r
1949                                                 try {\r
1950                                                         // IE will remove comments from the beginning\r
1951                                                         // unless you padd the contents with something\r
1952                                                         e.innerHTML = '<br />' + h;\r
1953                                                         e.removeChild(e.firstChild);\r
1954                                                 } catch (ex) {\r
1955                                                         // 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
1956                                                         // This seems to fix this problem\r
1957 \r
1958                                                         // Remove all child nodes\r
1959                                                         while (e.firstChild)\r
1960                                                                 e.firstChild.removeNode();\r
1961 \r
1962                                                         // Create new div with HTML contents and a BR infront to keep comments\r
1963                                                         x = t.create('div');\r
1964                                                         x.innerHTML = '<br />' + h;\r
1965 \r
1966                                                         // Add all children from div to target\r
1967                                                         each (x.childNodes, function(n, i) {\r
1968                                                                 // Skip br element\r
1969                                                                 if (i)\r
1970                                                                         e.appendChild(n);\r
1971                                                         });\r
1972                                                 }\r
1973                                         };\r
1974 \r
1975                                         // IE has a serious bug when it comes to paragraphs it can produce an invalid\r
1976                                         // DOM tree if contents like this <p><ul><li>Item 1</li></ul></p> is inserted\r
1977                                         // It seems to be that IE doesn't like a root block element placed inside another root block element\r
1978                                         if (t.settings.fix_ie_paragraphs)\r
1979                                                 h = h.replace(/<p><\/p>|<p([^>]+)><\/p>|<p[^\/+]\/>/gi, '<p$1 mce_keep="true">&nbsp;</p>');\r
1980 \r
1981                                         set();\r
1982 \r
1983                                         if (t.settings.fix_ie_paragraphs) {\r
1984                                                 // Check for odd paragraphs this is a sign of a broken DOM\r
1985                                                 nl = e.getElementsByTagName("p");\r
1986                                                 for (i = nl.length - 1, x = 0; i >= 0; i--) {\r
1987                                                         n = nl[i];\r
1988 \r
1989                                                         if (!n.hasChildNodes()) {\r
1990                                                                 if (!n.mce_keep) {\r
1991                                                                         x = 1; // Is broken\r
1992                                                                         break;\r
1993                                                                 }\r
1994 \r
1995                                                                 n.removeAttribute('mce_keep');\r
1996                                                         }\r
1997                                                 }\r
1998                                         }\r
1999 \r
2000                                         // Time to fix the madness IE left us\r
2001                                         if (x) {\r
2002                                                 // So if we replace the p elements with divs and mark them and then replace them back to paragraphs\r
2003                                                 // after we use innerHTML we can fix the DOM tree\r
2004                                                 h = h.replace(/<p ([^>]+)>|<p>/g, '<div $1 mce_tmp="1">');\r
2005                                                 h = h.replace(/<\/p>/g, '</div>');\r
2006 \r
2007                                                 // Set the new HTML with DIVs\r
2008                                                 set();\r
2009 \r
2010                                                 // Replace all DIV elements with he mce_tmp attibute back to paragraphs\r
2011                                                 // This is needed since IE has a annoying bug see above for details\r
2012                                                 // This is a slow process but it has to be done. :(\r
2013                                                 if (t.settings.fix_ie_paragraphs) {\r
2014                                                         nl = e.getElementsByTagName("DIV");\r
2015                                                         for (i = nl.length - 1; i >= 0; i--) {\r
2016                                                                 n = nl[i];\r
2017 \r
2018                                                                 // Is it a temp div\r
2019                                                                 if (n.mce_tmp) {\r
2020                                                                         // Create new paragraph\r
2021                                                                         p = t.doc.createElement('p');\r
2022 \r
2023                                                                         // Copy all attributes\r
2024                                                                         n.cloneNode(false).outerHTML.replace(/([a-z0-9\-_]+)=/gi, function(a, b) {\r
2025                                                                                 var v;\r
2026 \r
2027                                                                                 if (b !== 'mce_tmp') {\r
2028                                                                                         v = n.getAttribute(b);\r
2029 \r
2030                                                                                         if (!v && b === 'class')\r
2031                                                                                                 v = n.className;\r
2032 \r
2033                                                                                         p.setAttribute(b, v);\r
2034                                                                                 }\r
2035                                                                         });\r
2036 \r
2037                                                                         // Append all children to new paragraph\r
2038                                                                         for (x = 0; x<n.childNodes.length; x++)\r
2039                                                                                 p.appendChild(n.childNodes[x].cloneNode(true));\r
2040 \r
2041                                                                         // Replace div with new paragraph\r
2042                                                                         n.swapNode(p);\r
2043                                                                 }\r
2044                                                         }\r
2045                                                 }\r
2046                                         }\r
2047                                 } else\r
2048                                         e.innerHTML = h;\r
2049 \r
2050                                 return h;\r
2051                         });\r
2052                 },\r
2053 \r
2054                 processHTML : function(h) {\r
2055                         var t = this, s = t.settings;\r
2056 \r
2057                         if (!s.process_html)\r
2058                                 return h;\r
2059 \r
2060                         // Convert strong and em to b and i in FF since it can't handle them\r
2061                         if (tinymce.isGecko) {\r
2062                                 h = h.replace(/<(\/?)strong>|<strong( [^>]+)>/gi, '<$1b$2>');\r
2063                                 h = h.replace(/<(\/?)em>|<em( [^>]+)>/gi, '<$1i$2>');\r
2064                         } else if (isIE) {\r
2065                                 h = h.replace(/&apos;/g, '&#39;'); // IE can't handle apos\r
2066                                 h = h.replace(/\s+(disabled|checked|readonly|selected)\s*=\s*[\"\']?(false|0)[\"\']?/gi, ''); // IE doesn't handle default values correct\r
2067                         }\r
2068 \r
2069                         // Fix some issues\r
2070                         h = h.replace(/<a( )([^>]+)\/>|<a\/>/gi, '<a$1$2></a>'); // Force open\r
2071 \r
2072                         // Store away src and href in mce_src and mce_href since browsers mess them up\r
2073                         if (s.keep_values) {\r
2074                                 // Wrap scripts and styles in comments for serialization purposes\r
2075                                 if (/<script|style/.test(h)) {\r
2076                                         function trim(s) {\r
2077                                                 // Remove prefix and suffix code for element\r
2078                                                 s = s.replace(/(<!--\[CDATA\[|\]\]-->)/g, '\n');\r
2079                                                 s = s.replace(/^[\r\n]*|[\r\n]*$/g, '');\r
2080                                                 s = s.replace(/^\s*(\/\/\s*<!--|\/\/\s*<!\[CDATA\[|<!--|<!\[CDATA\[)[\r\n]*/g, '');\r
2081                                                 s = s.replace(/\s*(\/\/\s*\]\]>|\/\/\s*-->|\]\]>|-->|\]\]-->)\s*$/g, '');\r
2082 \r
2083                                                 return s;\r
2084                                         };\r
2085 \r
2086                                         // Preserve script elements\r
2087                                         h = h.replace(/<script([^>]+|)>([\s\S]*?)<\/script>/g, function(v, a, b) {\r
2088                                                 // Remove prefix and suffix code for script element\r
2089                                                 b = trim(b);\r
2090 \r
2091                                                 // Force type attribute\r
2092                                                 if (!a)\r
2093                                                         a = ' type="text/javascript"';\r
2094 \r
2095                                                 // Wrap contents in a comment\r
2096                                                 if (b)\r
2097                                                         b = '<!--\n' + b + '\n// -->';\r
2098 \r
2099                                                 // Output fake element\r
2100                                                 return '<mce:script' + a + '>' + b + '</mce:script>';\r
2101                                         });\r
2102 \r
2103                                         // Preserve style elements\r
2104                                         h = h.replace(/<style([^>]+|)>([\s\S]*?)<\/style>/g, function(v, a, b) {\r
2105                                                 b = trim(b);\r
2106                                                 return '<mce:style' + a + '><!--\n' + b + '\n--></mce:style><style' + a + ' mce_bogus="1">' + b + '</style>';\r
2107                                         });\r
2108                                 }\r
2109 \r
2110                                 h = h.replace(/<!\[CDATA\[([\s\S]+)\]\]>/g, '<!--[CDATA[$1]]-->');\r
2111 \r
2112                                 // Process all tags with src, href or style\r
2113                                 h = h.replace(/<([\w:]+) [^>]*(src|href|style|shape|coords)[^>]*>/gi, function(a, n) {\r
2114                                         function handle(m, b, c) {\r
2115                                                 var u = c;\r
2116 \r
2117                                                 // Tag already got a mce_ version\r
2118                                                 if (a.indexOf('mce_' + b) != -1)\r
2119                                                         return m;\r
2120 \r
2121                                                 if (b == 'style') {\r
2122                                                         // Why did I need this one?\r
2123                                                         //if (isIE)\r
2124                                                         //      u = t.serializeStyle(t.parseStyle(u));\r
2125 \r
2126                                                         // No mce_style for elements with these since they might get resized by the user\r
2127                                                         if (t._isRes(c))\r
2128                                                                 return m;\r
2129 \r
2130                                                         if (s.hex_colors) {\r
2131                                                                 u = u.replace(/rgb\([^\)]+\)/g, function(v) {\r
2132                                                                         return t.toHex(v);\r
2133                                                                 });\r
2134                                                         }\r
2135 \r
2136                                                         if (s.url_converter) {\r
2137                                                                 u = u.replace(/url\([\'\"]?([^\)\'\"]+)\)/g, function(x, c) {\r
2138                                                                         return 'url(' + t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), b, n)) + ')';\r
2139                                                                 });\r
2140                                                         }\r
2141                                                 } else if (b != 'coords' && b != 'shape') {\r
2142                                                         if (s.url_converter)\r
2143                                                                 u = t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), b, n));\r
2144                                                 }\r
2145 \r
2146                                                 return ' ' + b + '="' + c + '" mce_' + b + '="' + u + '"';\r
2147                                         };\r
2148 \r
2149                                         a = a.replace(/ (src|href|style|coords|shape)=[\"]([^\"]+)[\"]/gi, handle); // W3C\r
2150                                         a = a.replace(/ (src|href|style|coords|shape)=[\']([^\']+)[\']/gi, handle); // W3C\r
2151 \r
2152                                         return a.replace(/ (src|href|style|coords|shape)=([^\s\"\'>]+)/gi, handle); // IE\r
2153                                 });\r
2154                         }\r
2155 \r
2156                         return h;\r
2157                 },\r
2158 \r
2159                 getOuterHTML : function(e) {\r
2160                         var d;\r
2161 \r
2162                         e = this.get(e);\r
2163 \r
2164                         if (!e)\r
2165                                 return null;\r
2166 \r
2167                         if (isIE)\r
2168                                 return e.outerHTML;\r
2169 \r
2170                         d = (e.ownerDocument || this.doc).createElement("body");\r
2171                         d.appendChild(e.cloneNode(true));\r
2172 \r
2173                         return d.innerHTML;\r
2174                 },\r
2175 \r
2176                 setOuterHTML : function(e, h, d) {\r
2177                         var t = this;\r
2178 \r
2179                         return this.run(e, function(e) {\r
2180                                 var n, tp;\r
2181 \r
2182                                 e = t.get(e);\r
2183                                 d = d || e.ownerDocument || t.doc;\r
2184 \r
2185                                 if (isIE && e.nodeType == 1)\r
2186                                         e.outerHTML = h;\r
2187                                 else {\r
2188                                         tp = d.createElement("body");\r
2189                                         tp.innerHTML = h;\r
2190 \r
2191                                         n = tp.lastChild;\r
2192                                         while (n) {\r
2193                                                 t.insertAfter(n.cloneNode(true), e);\r
2194                                                 n = n.previousSibling;\r
2195                                         }\r
2196 \r
2197                                         t.remove(e);\r
2198                                 }\r
2199                         });\r
2200                 },\r
2201 \r
2202                 decode : function(s) {\r
2203                         var e, n, v;\r
2204 \r
2205                         // Look for entities to decode\r
2206                         if (/&[^;]+;/.test(s)) {\r
2207                                 // Decode the entities using a div element not super efficient but less code\r
2208                                 e = this.doc.createElement("div");\r
2209                                 e.innerHTML = s;\r
2210                                 n = e.firstChild;\r
2211                                 v = '';\r
2212 \r
2213                                 if (n) {\r
2214                                         do {\r
2215                                                 v += n.nodeValue;\r
2216                                         } while (n.nextSibling);\r
2217                                 }\r
2218 \r
2219                                 return v || s;\r
2220                         }\r
2221 \r
2222                         return s;\r
2223                 },\r
2224 \r
2225                 encode : function(s) {\r
2226                         return s ? ('' + s).replace(/[<>&\"]/g, function (c, b) {\r
2227                                 switch (c) {\r
2228                                         case '&':\r
2229                                                 return '&amp;';\r
2230 \r
2231                                         case '"':\r
2232                                                 return '&quot;';\r
2233 \r
2234                                         case '<':\r
2235                                                 return '&lt;';\r
2236 \r
2237                                         case '>':\r
2238                                                 return '&gt;';\r
2239                                 }\r
2240 \r
2241                                 return c;\r
2242                         }) : s;\r
2243                 },\r
2244 \r
2245                 // #if !jquery\r
2246 \r
2247                 insertAfter : function(n, r) {\r
2248                         var t = this;\r
2249 \r
2250                         r = t.get(r);\r
2251 \r
2252                         return this.run(n, function(n) {\r
2253                                 var p, ns;\r
2254 \r
2255                                 p = r.parentNode;\r
2256                                 ns = r.nextSibling;\r
2257 \r
2258                                 if (ns)\r
2259                                         p.insertBefore(n, ns);\r
2260                                 else\r
2261                                         p.appendChild(n);\r
2262 \r
2263                                 return n;\r
2264                         });\r
2265                 },\r
2266 \r
2267                 // #endif\r
2268 \r
2269                 isBlock : function(n) {\r
2270                         if (n.nodeType && n.nodeType !== 1)\r
2271                                 return false;\r
2272 \r
2273                         n = n.nodeName || n;\r
2274 \r
2275                         return /^(H[1-6]|HR|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP)$/.test(n);\r
2276                 },\r
2277 \r
2278                 // #if !jquery\r
2279 \r
2280                 replace : function(n, o, k) {\r
2281                         if (is(o, 'array'))\r
2282                                 n = n.cloneNode(true);\r
2283 \r
2284                         return this.run(o, function(o) {\r
2285                                 if (k) {\r
2286                                         each(o.childNodes, function(c) {\r
2287                                                 n.appendChild(c.cloneNode(true));\r
2288                                         });\r
2289                                 }\r
2290 \r
2291                                 // Fix IE psuedo leak for elements since replacing elements if fairly common\r
2292                                 // Will break parentNode for some unknown reason\r
2293         /*                      if (isIE && o.nodeType === 1) {\r
2294                                         o.parentNode.insertBefore(n, o);\r
2295                                         o.outerHTML = '';\r
2296                                         return n;\r
2297                                 }*/\r
2298 \r
2299                                 return o.parentNode.replaceChild(n, o);\r
2300                         });\r
2301                 },\r
2302 \r
2303                 // #endif\r
2304 \r
2305                 toHex : function(s) {\r
2306                         var c = /^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(s);\r
2307 \r
2308                         function hex(s) {\r
2309                                 s = parseInt(s).toString(16);\r
2310 \r
2311                                 return s.length > 1 ? s : '0' + s; // 0 -> 00\r
2312                         };\r
2313 \r
2314                         if (c) {\r
2315                                 s = '#' + hex(c[1]) + hex(c[2]) + hex(c[3]);\r
2316 \r
2317                                 return s;\r
2318                         }\r
2319 \r
2320                         return s;\r
2321                 },\r
2322 \r
2323                 getClasses : function() {\r
2324                         var t = this, cl = [], i, lo = {}, f = t.settings.class_filter, ov;\r
2325 \r
2326                         if (t.classes)\r
2327                                 return t.classes;\r
2328 \r
2329                         function addClasses(s) {\r
2330                                 // IE style imports\r
2331                                 each(s.imports, function(r) {\r
2332                                         addClasses(r);\r
2333                                 });\r
2334 \r
2335                                 each(s.cssRules || s.rules, function(r) {\r
2336                                         // Real type or fake it on IE\r
2337                                         switch (r.type || 1) {\r
2338                                                 // Rule\r
2339                                                 case 1:\r
2340                                                         if (r.selectorText) {\r
2341                                                                 each(r.selectorText.split(','), function(v) {\r
2342                                                                         v = v.replace(/^\s*|\s*$|^\s\./g, "");\r
2343 \r
2344                                                                         // Is internal or it doesn't contain a class\r
2345                                                                         if (/\.mce/.test(v) || !/\.[\w\-]+$/.test(v))\r
2346                                                                                 return;\r
2347 \r
2348                                                                         // Remove everything but class name\r
2349                                                                         ov = v;\r
2350                                                                         v = v.replace(/.*\.([a-z0-9_\-]+).*/i, '$1');\r
2351 \r
2352                                                                         // Filter classes\r
2353                                                                         if (f && !(v = f(v, ov)))\r
2354                                                                                 return;\r
2355 \r
2356                                                                         if (!lo[v]) {\r
2357                                                                                 cl.push({'class' : v});\r
2358                                                                                 lo[v] = 1;\r
2359                                                                         }\r
2360                                                                 });\r
2361                                                         }\r
2362                                                         break;\r
2363 \r
2364                                                 // Import\r
2365                                                 case 3:\r
2366                                                         addClasses(r.styleSheet);\r
2367                                                         break;\r
2368                                         }\r
2369                                 });\r
2370                         };\r
2371 \r
2372                         try {\r
2373                                 each(t.doc.styleSheets, addClasses);\r
2374                         } catch (ex) {\r
2375                                 // Ignore\r
2376                         }\r
2377 \r
2378                         if (cl.length > 0)\r
2379                                 t.classes = cl;\r
2380 \r
2381                         return cl;\r
2382                 },\r
2383 \r
2384                 run : function(e, f, s) {\r
2385                         var t = this, o;\r
2386 \r
2387                         if (t.doc && typeof(e) === 'string')\r
2388                                 e = t.get(e);\r
2389 \r
2390                         if (!e)\r
2391                                 return false;\r
2392 \r
2393                         s = s || this;\r
2394                         if (!e.nodeType && (e.length || e.length === 0)) {\r
2395                                 o = [];\r
2396 \r
2397                                 each(e, function(e, i) {\r
2398                                         if (e) {\r
2399                                                 if (typeof(e) == 'string')\r
2400                                                         e = t.doc.getElementById(e);\r
2401 \r
2402                                                 o.push(f.call(s, e, i));\r
2403                                         }\r
2404                                 });\r
2405 \r
2406                                 return o;\r
2407                         }\r
2408 \r
2409                         return f.call(s, e);\r
2410                 },\r
2411 \r
2412                 getAttribs : function(n) {\r
2413                         var o;\r
2414 \r
2415                         n = this.get(n);\r
2416 \r
2417                         if (!n)\r
2418                                 return [];\r
2419 \r
2420                         if (isIE) {\r
2421                                 o = [];\r
2422 \r
2423                                 // Object will throw exception in IE\r
2424                                 if (n.nodeName == 'OBJECT')\r
2425                                         return n.attributes;\r
2426 \r
2427                                 // It's crazy that this is faster in IE but it's because it returns all attributes all the time\r
2428                                 n.cloneNode(false).outerHTML.replace(/([a-z0-9\:\-_]+)=/gi, function(a, b) {\r
2429                                         o.push({specified : 1, nodeName : b});\r
2430                                 });\r
2431 \r
2432                                 return o;\r
2433                         }\r
2434 \r
2435                         return n.attributes;\r
2436                 },\r
2437 \r
2438                 destroy : function(s) {\r
2439                         var t = this;\r
2440 \r
2441                         t.win = t.doc = t.root = null;\r
2442 \r
2443                         // Manual destroy then remove unload handler\r
2444                         if (!s)\r
2445                                 tinymce.removeUnload(t.destroy);\r
2446                 },\r
2447 \r
2448                 _isRes : function(c) {\r
2449                         // Is live resizble element\r
2450                         return /^(top|left|bottom|right|width|height)/i.test(c) || /;\s*(top|left|bottom|right|width|height)/i.test(c);\r
2451                 }\r
2452 \r
2453                 /*\r
2454                 walk : function(n, f, s) {\r
2455                         var d = this.doc, w;\r
2456 \r
2457                         if (d.createTreeWalker) {\r
2458                                 w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);\r
2459 \r
2460                                 while ((n = w.nextNode()) != null)\r
2461                                         f.call(s || this, n);\r
2462                         } else\r
2463                                 tinymce.walk(n, f, 'childNodes', s);\r
2464                 }\r
2465                 */\r
2466 \r
2467                 /*\r
2468                 toRGB : function(s) {\r
2469                         var c = /^\s*?#([0-9A-F]{2})([0-9A-F]{1,2})([0-9A-F]{2})?\s*?$/.exec(s);\r
2470 \r
2471                         if (c) {\r
2472                                 // #FFF -> #FFFFFF\r
2473                                 if (!is(c[3]))\r
2474                                         c[3] = c[2] = c[1];\r
2475 \r
2476                                 return "rgb(" + parseInt(c[1], 16) + "," + parseInt(c[2], 16) + "," + parseInt(c[3], 16) + ")";\r
2477                         }\r
2478 \r
2479                         return s;\r
2480                 }\r
2481                 */\r
2482 \r
2483                 });\r
2484 \r
2485         // Setup page DOM\r
2486         tinymce.DOM = new tinymce.dom.DOMUtils(document, {process_html : 0});\r
2487 })();\r
2488 \r
2489 /* file:jscripts/tiny_mce/classes/dom/Event.js */\r
2490 \r
2491 (function() {\r
2492         // Shorten names\r
2493         var each = tinymce.each, DOM = tinymce.DOM, isIE = tinymce.isIE, isWebKit = tinymce.isWebKit, Event;\r
2494 \r
2495         tinymce.create('static tinymce.dom.Event', {\r
2496                 inits : [],\r
2497                 events : [],\r
2498 \r
2499                 // #if !jquery\r
2500 \r
2501                 add : function(o, n, f, s) {\r
2502                         var cb, t = this, el = t.events, r;\r
2503 \r
2504                         // Handle array\r
2505                         if (o && o instanceof Array) {\r
2506                                 r = [];\r
2507 \r
2508                                 each(o, function(o) {\r
2509                                         o = DOM.get(o);\r
2510                                         r.push(t.add(o, n, f, s));\r
2511                                 });\r
2512 \r
2513                                 return r;\r
2514                         }\r
2515 \r
2516                         o = DOM.get(o);\r
2517 \r
2518                         if (!o)\r
2519                                 return;\r
2520 \r
2521                         // Setup event callback\r
2522                         cb = function(e) {\r
2523                                 e = e || window.event;\r
2524 \r
2525                                 // Patch in target in IE it's W3C valid\r
2526                                 if (e && !e.target && isIE)\r
2527                                         e.target = e.srcElement;\r
2528 \r
2529                                 if (!s)\r
2530                                         return f(e);\r
2531 \r
2532                                 return f.call(s, e);\r
2533                         };\r
2534 \r
2535                         if (n == 'unload') {\r
2536                                 tinymce.unloads.unshift({func : cb});\r
2537                                 return cb;\r
2538                         }\r
2539 \r
2540                         if (n == 'init') {\r
2541                                 if (t.domLoaded)\r
2542                                         cb();\r
2543                                 else\r
2544                                         t.inits.push(cb);\r
2545 \r
2546                                 return cb;\r
2547                         }\r
2548 \r
2549                         // Store away listener reference\r
2550                         el.push({\r
2551                                 obj : o,\r
2552                                 name : n,\r
2553                                 func : f,\r
2554                                 cfunc : cb,\r
2555                                 scope : s\r
2556                         });\r
2557 \r
2558                         t._add(o, n, cb);\r
2559 \r
2560                         return f;\r
2561                 },\r
2562 \r
2563                 remove : function(o, n, f) {\r
2564                         var t = this, a = t.events, s = false, r;\r
2565 \r
2566                         // Handle array\r
2567                         if (o && o instanceof Array) {\r
2568                                 r = [];\r
2569 \r
2570                                 each(o, function(o) {\r
2571                                         o = DOM.get(o);\r
2572                                         r.push(t.remove(o, n, f));\r
2573                                 });\r
2574 \r
2575                                 return r;\r
2576                         }\r
2577 \r
2578                         o = DOM.get(o);\r
2579 \r
2580                         each(a, function(e, i) {\r
2581                                 if (e.obj == o && e.name == n && (!f || (e.func == f || e.cfunc == f))) {\r
2582                                         a.splice(i, 1);\r
2583                                         t._remove(o, n, e.cfunc);\r
2584                                         s = true;\r
2585                                         return false;\r
2586                                 }\r
2587                         });\r
2588 \r
2589                         return s;\r
2590                 },\r
2591 \r
2592                 clear : function(o) {\r
2593                         var t = this, a = t.events, i, e;\r
2594 \r
2595                         if (o) {\r
2596                                 o = DOM.get(o);\r
2597 \r
2598                                 for (i = a.length - 1; i >= 0; i--) {\r
2599                                         e = a[i];\r
2600 \r
2601                                         if (e.obj === o) {\r
2602                                                 t._remove(e.obj, e.name, e.cfunc);\r
2603                                                 e.obj = e.cfunc = null;\r
2604                                                 a.splice(i, 1);\r
2605                                         }\r
2606                                 }\r
2607                         }\r
2608                 },\r
2609 \r
2610                 // #endif\r
2611 \r
2612                 cancel : function(e) {\r
2613                         if (!e)\r
2614                                 return false;\r
2615 \r
2616                         this.stop(e);\r
2617                         return this.prevent(e);\r
2618                 },\r
2619 \r
2620                 stop : function(e) {\r
2621                         if (e.stopPropagation)\r
2622                                 e.stopPropagation();\r
2623                         else\r
2624                                 e.cancelBubble = true;\r
2625 \r
2626                         return false;\r
2627                 },\r
2628 \r
2629                 prevent : function(e) {\r
2630                         if (e.preventDefault)\r
2631                                 e.preventDefault();\r
2632                         else\r
2633                                 e.returnValue = false;\r
2634 \r
2635                         return false;\r
2636                 },\r
2637 \r
2638                 _unload : function() {\r
2639                         var t = Event;\r
2640 \r
2641                         each(t.events, function(e, i) {\r
2642                                 t._remove(e.obj, e.name, e.cfunc);\r
2643                                 e.obj = e.cfunc = null;\r
2644                         });\r
2645 \r
2646                         t.events = [];\r
2647                         t = null;\r
2648                 },\r
2649 \r
2650                 _add : function(o, n, f) {\r
2651                         if (o.attachEvent)\r
2652                                 o.attachEvent('on' + n, f);\r
2653                         else if (o.addEventListener)\r
2654                                 o.addEventListener(n, f, false);\r
2655                         else\r
2656                                 o['on' + n] = f;\r
2657                 },\r
2658 \r
2659                 _remove : function(o, n, f) {\r
2660                         if (o) {\r
2661                                 try {\r
2662                                         if (o.detachEvent)\r
2663                                                 o.detachEvent('on' + n, f);\r
2664                                         else if (o.removeEventListener)\r
2665                                                 o.removeEventListener(n, f, false);\r
2666                                         else\r
2667                                                 o['on' + n] = null;\r
2668                                 } catch (ex) {\r
2669                                         // Might fail with permission denined on IE so we just ignore that\r
2670                                 }\r
2671                         }\r
2672                 },\r
2673 \r
2674                 _pageInit : function() {\r
2675                         var e = Event;\r
2676 \r
2677                         // Safari on Mac fires this twice\r
2678                         if (e.domLoaded)\r
2679                                 return;\r
2680 \r
2681                         e._remove(window, 'DOMContentLoaded', e._pageInit);\r
2682                         e.domLoaded = true;\r
2683 \r
2684                         each(e.inits, function(c) {\r
2685                                 c();\r
2686                         });\r
2687 \r
2688                         e.inits = [];\r
2689                 },\r
2690 \r
2691                 _wait : function() {\r
2692                         var t;\r
2693 \r
2694                         // No need since the document is already loaded\r
2695                         if (window.tinyMCE_GZ && tinyMCE_GZ.loaded) {\r
2696                                 Event.domLoaded = 1;\r
2697                                 return;\r
2698                         }\r
2699 \r
2700                         if (isIE && document.location.protocol != 'https:') {\r
2701                                 // Fake DOMContentLoaded on IE\r
2702                                 document.write('<script id=__ie_onload defer src=\'javascript:""\';><\/script>');\r
2703                                 DOM.get("__ie_onload").onreadystatechange = function() {\r
2704                                         if (this.readyState == "complete") {\r
2705                                                 Event._pageInit();\r
2706                                                 DOM.get("__ie_onload").onreadystatechange = null; // Prevent leak\r
2707                                         }\r
2708                                 };\r
2709                         } else {\r
2710                                 Event._add(window, 'DOMContentLoaded', Event._pageInit, Event);\r
2711 \r
2712                                 if (isIE || isWebKit) {\r
2713                                         t = setInterval(function() {\r
2714                                                 if (/loaded|complete/.test(document.readyState)) {\r
2715                                                         clearInterval(t);\r
2716                                                         Event._pageInit();\r
2717                                                 }\r
2718                                         }, 10);\r
2719                                 }\r
2720                         }\r
2721                 }\r
2722 \r
2723                 });\r
2724 \r
2725         // Shorten name\r
2726         Event = tinymce.dom.Event;\r
2727 \r
2728         // Dispatch DOM content loaded event for IE and Safari\r
2729         Event._wait();\r
2730         tinymce.addUnload(Event._unload);\r
2731 })();\r
2732 \r
2733 /* file:jscripts/tiny_mce/classes/dom/Element.js */\r
2734 \r
2735 (function() {\r
2736         var each = tinymce.each;\r
2737 \r
2738         tinymce.create('tinymce.dom.Element', {\r
2739                 Element : function(id, s) {\r
2740                         var t = this, dom, el;\r
2741 \r
2742                         s = s || {};\r
2743                         t.id = id;\r
2744                         t.dom = dom = s.dom || tinymce.DOM;\r
2745                         t.settings = s;\r
2746 \r
2747                         // Only IE leaks DOM references, this is a lot faster\r
2748                         if (!tinymce.isIE)\r
2749                                 el = t.dom.get(t.id);\r
2750 \r
2751                         each([\r
2752                                 'getPos',\r
2753                                 'getRect',\r
2754                                 'getParent',\r
2755                                 'add',\r
2756                                 'setStyle',\r
2757                                 'getStyle',\r
2758                                 'setStyles',\r
2759                                 'setAttrib',\r
2760                                 'setAttribs',\r
2761                                 'getAttrib',\r
2762                                 'addClass',\r
2763                                 'removeClass',\r
2764                                 'hasClass',\r
2765                                 'getOuterHTML',\r
2766                                 'setOuterHTML',\r
2767                                 'remove',\r
2768                                 'show',\r
2769                                 'hide',\r
2770                                 'isHidden',\r
2771                                 'setHTML',\r
2772                                 'get'\r
2773                         ], function(k) {\r
2774                                 t[k] = function() {\r
2775                                         var a = arguments, o;\r
2776 \r
2777                                         // Opera fails\r
2778                                         if (tinymce.isOpera) {\r
2779                                                 a = [id];\r
2780 \r
2781                                                 each(arguments, function(v) {\r
2782                                                         a.push(v);\r
2783                                                 });\r
2784                                         } else\r
2785                                                 Array.prototype.unshift.call(a, el || id);\r
2786 \r
2787                                         o = dom[k].apply(dom, a);\r
2788                                         t.update(k);\r
2789 \r
2790                                         return o;\r
2791                                 };\r
2792                         });\r
2793                 },\r
2794 \r
2795                 on : function(n, f, s) {\r
2796                         return tinymce.dom.Event.add(this.id, n, f, s);\r
2797                 },\r
2798 \r
2799                 getXY : function() {\r
2800                         return {\r
2801                                 x : parseInt(this.getStyle('left')),\r
2802                                 y : parseInt(this.getStyle('top'))\r
2803                         };\r
2804                 },\r
2805 \r
2806                 getSize : function() {\r
2807                         var n = this.dom.get(this.id);\r
2808 \r
2809                         return {\r
2810                                 w : parseInt(this.getStyle('width') || n.clientWidth),\r
2811                                 h : parseInt(this.getStyle('height') || n.clientHeight)\r
2812                         };\r
2813                 },\r
2814 \r
2815                 moveTo : function(x, y) {\r
2816                         this.setStyles({left : x, top : y});\r
2817                 },\r
2818 \r
2819                 moveBy : function(x, y) {\r
2820                         var p = this.getXY();\r
2821 \r
2822                         this.moveTo(p.x + x, p.y + y);\r
2823                 },\r
2824 \r
2825                 resizeTo : function(w, h) {\r
2826                         this.setStyles({width : w, height : h});\r
2827                 },\r
2828 \r
2829                 resizeBy : function(w, h) {\r
2830                         var s = this.getSize();\r
2831 \r
2832                         this.resizeTo(s.w + w, s.h + h);\r
2833                 },\r
2834 \r
2835                 update : function(k) {\r
2836                         var t = this, b, dom = t.dom;\r
2837 \r
2838                         if (tinymce.isIE6 && t.settings.blocker) {\r
2839                                 k = k || '';\r
2840 \r
2841                                 // Ignore getters\r
2842                                 if (k.indexOf('get') === 0 || k.indexOf('has') === 0 || k.indexOf('is') === 0)\r
2843                                         return;\r
2844 \r
2845                                 // Remove blocker on remove\r
2846                                 if (k == 'remove') {\r
2847                                         dom.remove(t.blocker);\r
2848                                         return;\r
2849                                 }\r
2850 \r
2851                                 if (!t.blocker) {\r
2852                                         t.blocker = dom.uniqueId();\r
2853                                         b = dom.add(t.settings.container || dom.getRoot(), 'iframe', {id : t.blocker, style : 'position:absolute;', frameBorder : 0, src : 'javascript:""'});\r
2854                                         dom.setStyle(b, 'opacity', 0);\r
2855                                 } else\r
2856                                         b = dom.get(t.blocker);\r
2857 \r
2858                                 dom.setStyle(b, 'left', t.getStyle('left', 1));\r
2859                                 dom.setStyle(b, 'top', t.getStyle('top', 1));\r
2860                                 dom.setStyle(b, 'width', t.getStyle('width', 1));\r
2861                                 dom.setStyle(b, 'height', t.getStyle('height', 1));\r
2862                                 dom.setStyle(b, 'display', t.getStyle('display', 1));\r
2863                                 dom.setStyle(b, 'zIndex', parseInt(t.getStyle('zIndex', 1) || 0) - 1);\r
2864                         }\r
2865                 }\r
2866 \r
2867                 });\r
2868 })();\r
2869 \r
2870 /* file:jscripts/tiny_mce/classes/dom/Selection.js */\r
2871 \r
2872 (function() {\r
2873         function trimNl(s) {\r
2874                 return s.replace(/[\n\r]+/g, '');\r
2875         };\r
2876 \r
2877         // Shorten names\r
2878         var is = tinymce.is, isIE = tinymce.isIE, each = tinymce.each;\r
2879 \r
2880         tinymce.create('tinymce.dom.Selection', {\r
2881                 Selection : function(dom, win, serializer) {\r
2882                         var t = this;\r
2883 \r
2884                         t.dom = dom;\r
2885                         t.win = win;\r
2886                         t.serializer = serializer;\r
2887 \r
2888                         // Add events\r
2889                         each([\r
2890                                 'onBeforeSetContent',\r
2891                                 'onBeforeGetContent',\r
2892                                 'onSetContent',\r
2893                                 'onGetContent'\r
2894                         ], function(e) {\r
2895                                 t[e] = new tinymce.util.Dispatcher(t);\r
2896                         });\r
2897 \r
2898                         // Prevent leaks\r
2899                         tinymce.addUnload(t.destroy, t);\r
2900                 },\r
2901 \r
2902                 getContent : function(s) {\r
2903                         var t = this, r = t.getRng(), e = t.dom.create("body"), se = t.getSel(), wb, wa, n;\r
2904 \r
2905                         s = s || {};\r
2906                         wb = wa = '';\r
2907                         s.get = true;\r
2908                         s.format = s.format || 'html';\r
2909                         t.onBeforeGetContent.dispatch(t, s);\r
2910 \r
2911                         if (s.format == 'text')\r
2912                                 return t.isCollapsed() ? '' : (r.text || (se.toString ? se.toString() : ''));\r
2913 \r
2914                         if (r.cloneContents) {\r
2915                                 n = r.cloneContents();\r
2916 \r
2917                                 if (n)\r
2918                                         e.appendChild(n);\r
2919                         } else if (is(r.item) || is(r.htmlText))\r
2920                                 e.innerHTML = r.item ? r.item(0).outerHTML : r.htmlText;\r
2921                         else\r
2922                                 e.innerHTML = r.toString();\r
2923 \r
2924                         // Keep whitespace before and after\r
2925                         if (/^\s/.test(e.innerHTML))\r
2926                                 wb = ' ';\r
2927 \r
2928                         if (/\s+$/.test(e.innerHTML))\r
2929                                 wa = ' ';\r
2930 \r
2931                         s.getInner = true;\r
2932 \r
2933                         s.content = t.isCollapsed() ? '' : wb + t.serializer.serialize(e, s) + wa;\r
2934                         t.onGetContent.dispatch(t, s);\r
2935 \r
2936                         return s.content;\r
2937                 },\r
2938 \r
2939                 setContent : function(h, s) {\r
2940                         var t = this, r = t.getRng(), c, d = t.win.document;\r
2941 \r
2942                         s = s || {format : 'html'};\r
2943                         s.set = true;\r
2944                         h = s.content = t.dom.processHTML(h);\r
2945 \r
2946                         // Dispatch before set content event\r
2947                         t.onBeforeSetContent.dispatch(t, s);\r
2948                         h = s.content;\r
2949 \r
2950                         if (r.insertNode) {\r
2951                                 // Make caret marker since insertNode places the caret in the beginning of text after insert\r
2952                                 h += '<span id="__caret">_</span>';\r
2953 \r
2954                                 // Delete and insert new node\r
2955                                 r.deleteContents();\r
2956                                 r.insertNode(t.getRng().createContextualFragment(h));\r
2957 \r
2958                                 // Move to caret marker\r
2959                                 c = t.dom.get('__caret');\r
2960 \r
2961                                 // Make sure we wrap it compleatly, Opera fails with a simple select call\r
2962                                 r = d.createRange();\r
2963                                 r.setStartBefore(c);\r
2964                                 r.setEndAfter(c);\r
2965                                 t.setRng(r);\r
2966 \r
2967                                 // Delete the marker, and hopefully the caret gets placed in the right location\r
2968                                 d.execCommand('Delete', false, null);\r
2969 \r
2970                                 // In case it's still there\r
2971                                 t.dom.remove('__caret');\r
2972                         } else {\r
2973                                 if (r.item) {\r
2974                                         // Delete content and get caret text selection\r
2975                                         d.execCommand('Delete', false, null);\r
2976                                         r = t.getRng();\r
2977                                 }\r
2978 \r
2979                                 r.pasteHTML(h);\r
2980                         }\r
2981 \r
2982                         // Dispatch set content event\r
2983                         t.onSetContent.dispatch(t, s);\r
2984                 },\r
2985 \r
2986                 getStart : function() {\r
2987                         var t = this, r = t.getRng(), e;\r
2988 \r
2989                         if (isIE) {\r
2990                                 if (r.item)\r
2991                                         return r.item(0);\r
2992 \r
2993                                 r = r.duplicate();\r
2994                                 r.collapse(1);\r
2995                                 e = r.parentElement();\r
2996 \r
2997                                 if (e && e.nodeName == 'BODY')\r
2998                                         return e.firstChild;\r
2999 \r
3000                                 return e;\r
3001                         } else {\r
3002                                 e = r.startContainer;\r
3003 \r
3004                                 if (e.nodeName == 'BODY')\r
3005                                         return e.firstChild;\r
3006 \r
3007                                 return t.dom.getParent(e, function(n) {return n.nodeType == 1;});\r
3008                         }\r
3009                 },\r
3010 \r
3011                 getEnd : function() {\r
3012                         var t = this, r = t.getRng(), e;\r
3013 \r
3014                         if (isIE) {\r
3015                                 if (r.item)\r
3016                                         return r.item(0);\r
3017 \r
3018                                 r = r.duplicate();\r
3019                                 r.collapse(0);\r
3020                                 e = r.parentElement();\r
3021 \r
3022                                 if (e && e.nodeName == 'BODY')\r
3023                                         return e.lastChild;\r
3024 \r
3025                                 return e;\r
3026                         } else {\r
3027                                 e = r.endContainer;\r
3028 \r
3029                                 if (e.nodeName == 'BODY')\r
3030                                         return e.lastChild;\r
3031 \r
3032                                 return t.dom.getParent(e, function(n) {return n.nodeType == 1;});\r
3033                         }\r
3034                 },\r
3035 \r
3036                 getBookmark : function(si) {\r
3037                         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
3038                         sx = vp.x;\r
3039                         sy = vp.y;\r
3040 \r
3041                         // Simple bookmark fast but not as persistent\r
3042                         if (si == 'simple')\r
3043                                 return {rng : r, scrollX : sx, scrollY : sy};\r
3044 \r
3045                         // Handle IE\r
3046                         if (isIE) {\r
3047                                 // Control selection\r
3048                                 if (r.item) {\r
3049                                         e = r.item(0);\r
3050 \r
3051                                         each(t.dom.select(e.nodeName), function(n, i) {\r
3052                                                 if (e == n) {\r
3053                                                         sp = i;\r
3054                                                         return false;\r
3055                                                 }\r
3056                                         });\r
3057 \r
3058                                         return {\r
3059                                                 tag : e.nodeName,\r
3060                                                 index : sp,\r
3061                                                 scrollX : sx,\r
3062                                                 scrollY : sy\r
3063                                         };\r
3064                                 }\r
3065 \r
3066                                 // Text selection\r
3067                                 tr = t.dom.doc.body.createTextRange();\r
3068                                 tr.moveToElementText(ro);\r
3069                                 tr.collapse(true);\r
3070                                 bp = Math.abs(tr.move('character', c));\r
3071 \r
3072                                 tr = r.duplicate();\r
3073                                 tr.collapse(true);\r
3074                                 sp = Math.abs(tr.move('character', c));\r
3075 \r
3076                                 tr = r.duplicate();\r
3077                                 tr.collapse(false);\r
3078                                 le = Math.abs(tr.move('character', c)) - sp;\r
3079 \r
3080                                 return {\r
3081                                         start : sp - bp,\r
3082                                         length : le,\r
3083                                         scrollX : sx,\r
3084                                         scrollY : sy\r
3085                                 };\r
3086                         }\r
3087 \r
3088                         // Handle W3C\r
3089                         e = t.getNode();\r
3090                         s = t.getSel();\r
3091 \r
3092                         if (!s)\r
3093                                 return null;\r
3094 \r
3095                         // Image selection\r
3096                         if (e && e.nodeName == 'IMG') {\r
3097                                 return {\r
3098                                         scrollX : sx,\r
3099                                         scrollY : sy\r
3100                                 };\r
3101                         }\r
3102 \r
3103                         // Text selection\r
3104 \r
3105                         function getPos(r, sn, en) {\r
3106                                 var w = t.dom.doc.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {};\r
3107 \r
3108                                 while ((n = w.nextNode()) != null) {\r
3109                                         if (n == sn)\r
3110                                                 d.start = p;\r
3111 \r
3112                                         if (n == en) {\r
3113                                                 d.end = p;\r
3114                                                 return d;\r
3115                                         }\r
3116 \r
3117                                         p += trimNl(n.nodeValue || '').length;\r
3118                                 }\r
3119 \r
3120                                 return null;\r
3121                         };\r
3122 \r
3123                         // Caret or selection\r
3124                         if (s.anchorNode == s.focusNode && s.anchorOffset == s.focusOffset) {\r
3125                                 e = getPos(ro, s.anchorNode, s.focusNode);\r
3126 \r
3127                                 if (!e)\r
3128                                         return {scrollX : sx, scrollY : sy};\r
3129 \r
3130                                 // Count whitespace before\r
3131                                 trimNl(s.anchorNode.nodeValue || '').replace(/^\s+/, function(a) {wb = a.length;});\r
3132 \r
3133                                 return {\r
3134                                         start : Math.max(e.start + s.anchorOffset - wb, 0),\r
3135                                         end : Math.max(e.end + s.focusOffset - wb, 0),\r
3136                                         scrollX : sx,\r
3137                                         scrollY : sy,\r
3138                                         beg : s.anchorOffset - wb == 0\r
3139                                 };\r
3140                         } else {\r
3141                                 e = getPos(ro, r.startContainer, r.endContainer);\r
3142 \r
3143                                 // Count whitespace before start and end container\r
3144                                 //(r.startContainer.nodeValue || '').replace(/^\s+/, function(a) {wb = a.length;});\r
3145                                 //(r.endContainer.nodeValue || '').replace(/^\s+/, function(a) {wa = a.length;});\r
3146 \r
3147                                 if (!e)\r
3148                                         return {scrollX : sx, scrollY : sy};\r
3149 \r
3150                                 return {\r
3151                                         start : Math.max(e.start + r.startOffset - wb, 0),\r
3152                                         end : Math.max(e.end + r.endOffset - wa, 0),\r
3153                                         scrollX : sx,\r
3154                                         scrollY : sy,\r
3155                                         beg : r.startOffset - wb == 0\r
3156                                 };\r
3157                         }\r
3158                 },\r
3159 \r
3160                 moveToBookmark : function(b) {\r
3161                         var t = this, r = t.getRng(), s = t.getSel(), ro = t.dom.getRoot(), sd, nvl, nv;\r
3162 \r
3163                         function getPos(r, sp, ep) {\r
3164                                 var w = t.dom.doc.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {}, o, v, wa, wb;\r
3165 \r
3166                                 while ((n = w.nextNode()) != null) {\r
3167                                         wa = wb = 0;\r
3168 \r
3169                                         nv = n.nodeValue || '';\r
3170                                         //nv.replace(/^\s+[^\s]/, function(a) {wb = a.length - 1;});\r
3171                                         //nv.replace(/[^\s]\s+$/, function(a) {wa = a.length - 1;});\r
3172 \r
3173                                         nvl = trimNl(nv).length;\r
3174                                         p += nvl;\r
3175 \r
3176                                         if (p >= sp && !d.startNode) {\r
3177                                                 o = sp - (p - nvl);\r
3178 \r
3179                                                 // Fix for odd quirk in FF\r
3180                                                 if (b.beg && o >= nvl)\r
3181                                                         continue;\r
3182 \r
3183                                                 d.startNode = n;\r
3184                                                 d.startOffset = o + wb;\r
3185                                         }\r
3186 \r
3187                                         if (p >= ep) {\r
3188                                                 d.endNode = n;\r
3189                                                 d.endOffset = ep - (p - nvl) + wb;\r
3190                                                 return d;\r
3191                                         }\r
3192                                 }\r
3193 \r
3194                                 return null;\r
3195                         };\r
3196 \r
3197                         if (!b)\r
3198                                 return false;\r
3199 \r
3200                         t.win.scrollTo(b.scrollX, b.scrollY);\r
3201 \r
3202                         // Handle explorer\r
3203                         if (isIE) {\r
3204                                 // Handle simple\r
3205                                 if (r = b.rng) {\r
3206                                         try {\r
3207                                                 r.select();\r
3208                                         } catch (ex) {\r
3209                                                 // Ignore\r
3210                                         }\r
3211 \r
3212                                         return true;\r
3213                                 }\r
3214 \r
3215                                 t.win.focus();\r
3216 \r
3217                                 // Handle control bookmark\r
3218                                 if (b.tag) {\r
3219                                         r = ro.createControlRange();\r
3220 \r
3221                                         each(t.dom.select(b.tag), function(n, i) {\r
3222                                                 if (i == b.index)\r
3223                                                         r.addElement(n);\r
3224                                         });\r
3225                                 } else {\r
3226                                         // Try/catch needed since this operation breaks when TinyMCE is placed in hidden divs/tabs\r
3227                                         try {\r
3228                                                 // Incorrect bookmark\r
3229                                                 if (b.start < 0)\r
3230                                                         return true;\r
3231 \r
3232                                                 r = s.createRange();\r
3233                                                 r.moveToElementText(ro);\r
3234                                                 r.collapse(true);\r
3235                                                 r.moveStart('character', b.start);\r
3236                                                 r.moveEnd('character', b.length);\r
3237                                         } catch (ex2) {\r
3238                                                 return true;\r
3239                                         }\r
3240                                 }\r
3241 \r
3242                                 try {\r
3243                                         r.select();\r
3244                                 } catch (ex) {\r
3245                                         // Needed for some odd IE bug #1843306\r
3246                                 }\r
3247 \r
3248                                 return true;\r
3249                         }\r
3250 \r
3251                         // Handle W3C\r
3252                         if (!s)\r
3253                                 return false;\r
3254 \r
3255                         // Handle simple\r
3256                         if (b.rng) {\r
3257                                 s.removeAllRanges();\r
3258                                 s.addRange(b.rng);\r
3259                         } else {\r
3260                                 if (is(b.start) && is(b.end)) {\r
3261                                         try {\r
3262                                                 sd = getPos(ro, b.start, b.end);\r
3263 \r
3264                                                 if (sd) {\r
3265                                                         r = t.dom.doc.createRange();\r
3266                                                         r.setStart(sd.startNode, sd.startOffset);\r
3267                                                         r.setEnd(sd.endNode, sd.endOffset);\r
3268                                                         s.removeAllRanges();\r
3269                                                         s.addRange(r);\r
3270                                                 }\r
3271 \r
3272                                                 if (!tinymce.isOpera)\r
3273                                                         t.win.focus();\r
3274                                         } catch (ex) {\r
3275                                                 // Ignore\r
3276                                         }\r
3277                                 }\r
3278                         }\r
3279                 },\r
3280 \r
3281                 select : function(n, c) {\r
3282                         var t = this, r = t.getRng(), s = t.getSel(), b, fn, ln, d = t.win.document;\r
3283 \r
3284                         function first(n) {\r
3285                                 return n ? d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false).nextNode() : null;\r
3286                         };\r
3287 \r
3288                         function last(n) {\r
3289                                 var c, o, w;\r
3290 \r
3291                                 if (!n)\r
3292                                         return null;\r
3293 \r
3294                                 w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);\r
3295                                 while (c = w.nextNode())\r
3296                                         o = c;\r
3297 \r
3298                                 return o;\r
3299                         };\r
3300 \r
3301                         if (isIE) {\r
3302                                 try {\r
3303                                         b = d.body;\r
3304 \r
3305                                         if (/^(IMG|TABLE)$/.test(n.nodeName)) {\r
3306                                                 r = b.createControlRange();\r
3307                                                 r.addElement(n);\r
3308                                         } else {\r
3309                                                 r = b.createTextRange();\r
3310                                                 r.moveToElementText(n);\r
3311                                         }\r
3312 \r
3313                                         r.select();\r
3314                                 } catch (ex) {\r
3315                                         // Throws illigal agrument in IE some times\r
3316                                 }\r
3317                         } else {\r
3318                                 if (c) {\r
3319                                         fn = first(n);\r
3320                                         ln = last(n);\r
3321 \r
3322                                         if (fn && ln) {\r
3323                                                 //console.debug(fn, ln);\r
3324                                                 r = d.createRange();\r
3325                                                 r.setStart(fn, 0);\r
3326                                                 r.setEnd(ln, ln.nodeValue.length);\r
3327                                         } else\r
3328                                                 r.selectNode(n);\r
3329                                 } else\r
3330                                         r.selectNode(n);\r
3331 \r
3332                                 t.setRng(r);\r
3333                         }\r
3334 \r
3335                         return n;\r
3336                 },\r
3337 \r
3338                 isCollapsed : function() {\r
3339                         var t = this, r = t.getRng(), s = t.getSel();\r
3340 \r
3341                         if (!r || r.item)\r
3342                                 return false;\r
3343 \r
3344                         return !s || r.boundingWidth == 0 || r.collapsed;\r
3345                 },\r
3346 \r
3347                 collapse : function(b) {\r
3348                         var t = this, r = t.getRng(), n;\r
3349 \r
3350                         // Control range on IE\r
3351                         if (r.item) {\r
3352                                 n = r.item(0);\r
3353                                 r = this.win.document.body.createTextRange();\r
3354                                 r.moveToElementText(n);\r
3355                         }\r
3356 \r
3357                         r.collapse(!!b);\r
3358                         t.setRng(r);\r
3359                 },\r
3360 \r
3361                 getSel : function() {\r
3362                         var t = this, w = this.win;\r
3363 \r
3364                         return w.getSelection ? w.getSelection() : w.document.selection;\r
3365                 },\r
3366 \r
3367                 getRng : function() {\r
3368                         var t = this, s = t.getSel(), r;\r
3369 \r
3370                         try {\r
3371                                 if (s)\r
3372                                         r = s.rangeCount > 0 ? s.getRangeAt(0) : (s.createRange ? s.createRange() : t.win.document.createRange());\r
3373                         } catch (ex) {\r
3374                                 // IE throws unspecified error here if TinyMCE is placed in a frame/iframe\r
3375                         }\r
3376 \r
3377                         // No range found then create an empty one\r
3378                         // This can occur when the editor is placed in a hidden container element on Gecko\r
3379                         // Or on IE when there was an exception\r
3380                         if (!r)\r
3381                                 r = isIE ? t.win.document.body.createTextRange() : t.win.document.createRange();\r
3382 \r
3383                         return r;\r
3384                 },\r
3385 \r
3386                 setRng : function(r) {\r
3387                         var s;\r
3388 \r
3389                         if (!isIE) {\r
3390                                 s = this.getSel();\r
3391 \r
3392                                 if (s) {\r
3393                                         s.removeAllRanges();\r
3394                                         s.addRange(r);\r
3395                                 }\r
3396                         } else {\r
3397                                 try {\r
3398                                         r.select();\r
3399                                 } catch (ex) {\r
3400                                         // Needed for some odd IE bug #1843306\r
3401                                 }\r
3402                         }\r
3403                 },\r
3404 \r
3405                 setNode : function(n) {\r
3406                         var t = this;\r
3407 \r
3408                         t.setContent(t.dom.getOuterHTML(n));\r
3409 \r
3410                         return n;\r
3411                 },\r
3412 \r
3413                 getNode : function() {\r
3414                         var t = this, r = t.getRng(), s = t.getSel(), e;\r
3415 \r
3416                         if (!isIE) {\r
3417                                 // Range maybe lost after the editor is made visible again\r
3418                                 if (!r)\r
3419                                         return t.dom.getRoot();\r
3420 \r
3421                                 e = r.commonAncestorContainer;\r
3422 \r
3423                                 // Handle selection a image or other control like element such as anchors\r
3424                                 if (!r.collapsed) {\r
3425                                         // If the anchor node is a element instead of a text node then return this element\r
3426                                         if (tinymce.isWebKit && s.anchorNode && s.anchorNode.nodeType == 1) \r
3427                                                 return s.anchorNode.childNodes[s.anchorOffset]; \r
3428 \r
3429                                         if (r.startContainer == r.endContainer) {\r
3430                                                 if (r.startOffset - r.endOffset < 2) {\r
3431                                                         if (r.startContainer.hasChildNodes())\r
3432                                                                 e = r.startContainer.childNodes[r.startOffset];\r
3433                                                 }\r
3434                                         }\r
3435                                 }\r
3436 \r
3437                                 return t.dom.getParent(e, function(n) {\r
3438                                         return n.nodeType == 1;\r
3439                                 });\r
3440                         }\r
3441 \r
3442                         return r.item ? r.item(0) : r.parentElement();\r
3443                 },\r
3444 \r
3445                 destroy : function(s) {\r
3446                         var t = this;\r
3447 \r
3448                         t.win = null;\r
3449 \r
3450                         // Manual destroy then remove unload handler\r
3451                         if (!s)\r
3452                                 tinymce.removeUnload(t.destroy);\r
3453                 }\r
3454 \r
3455                 });\r
3456 })();\r
3457 \r
3458 /* file:jscripts/tiny_mce/classes/dom/XMLWriter.js */\r
3459 \r
3460 (function() {\r
3461         tinymce.create('tinymce.dom.XMLWriter', {\r
3462                 node : null,\r
3463 \r
3464                 XMLWriter : function(s) {\r
3465                         // Get XML document\r
3466                         function getXML() {\r
3467                                 var i = document.implementation;\r
3468 \r
3469                                 if (!i || !i.createDocument) {\r
3470                                         // Try IE objects\r
3471                                         try {return new ActiveXObject('MSXML2.DOMDocument');} catch (ex) {}\r
3472                                         try {return new ActiveXObject('Microsoft.XmlDom');} catch (ex) {}\r
3473                                 } else\r
3474                                         return i.createDocument('', '', null);\r
3475                         };\r
3476 \r
3477                         this.doc = getXML();\r
3478                         \r
3479                         // Since Opera and WebKit doesn't escape > into &gt; we need to do it our self to normalize the output for all browsers\r
3480                         this.valid = tinymce.isOpera || tinymce.isWebKit;\r
3481 \r
3482                         this.reset();\r
3483                 },\r
3484 \r
3485                 reset : function() {\r
3486                         var t = this, d = t.doc;\r
3487 \r
3488                         if (d.firstChild)\r
3489                                 d.removeChild(d.firstChild);\r
3490 \r
3491                         t.node = d.appendChild(d.createElement("html"));\r
3492                 },\r
3493 \r
3494                 writeStartElement : function(n) {\r
3495                         var t = this;\r
3496 \r
3497                         t.node = t.node.appendChild(t.doc.createElement(n));\r
3498                 },\r
3499 \r
3500                 writeAttribute : function(n, v) {\r
3501                         if (this.valid)\r
3502                                 v = v.replace(/>/g, '%MCGT%');\r
3503 \r
3504                         this.node.setAttribute(n, v);\r
3505                 },\r
3506 \r
3507                 writeEndElement : function() {\r
3508                         this.node = this.node.parentNode;\r
3509                 },\r
3510 \r
3511                 writeFullEndElement : function() {\r
3512                         var t = this, n = t.node;\r
3513 \r
3514                         n.appendChild(t.doc.createTextNode(""));\r
3515                         t.node = n.parentNode;\r
3516                 },\r
3517 \r
3518                 writeText : function(v) {\r
3519                         if (this.valid)\r
3520                                 v = v.replace(/>/g, '%MCGT%');\r
3521 \r
3522                         this.node.appendChild(this.doc.createTextNode(v));\r
3523                 },\r
3524 \r
3525                 writeCDATA : function(v) {\r
3526                         this.node.appendChild(this.doc.createCDATA(v));\r
3527                 },\r
3528 \r
3529                 writeComment : function(v) {\r
3530                         // Fix for bug #2035694\r
3531                         if (tinymce.isIE)\r
3532                                 v = v.replace(/^\-|\-$/g, ' ');\r
3533 \r
3534                         this.node.appendChild(this.doc.createComment(v.replace(/\-\-/g, ' ')));\r
3535                 },\r
3536 \r
3537                 getContent : function() {\r
3538                         var h;\r
3539 \r
3540                         h = this.doc.xml || new XMLSerializer().serializeToString(this.doc);\r
3541                         h = h.replace(/<\?[^?]+\?>|<html>|<\/html>|<html\/>|<!DOCTYPE[^>]+>/g, '');\r
3542                         h = h.replace(/ ?\/>/g, ' />');\r
3543 \r
3544                         if (this.valid)\r
3545                                 h = h.replace(/\%MCGT%/g, '&gt;');\r
3546 \r
3547                         return h;\r
3548                 }\r
3549 \r
3550                 });\r
3551 })();\r
3552 \r
3553 /* file:jscripts/tiny_mce/classes/dom/StringWriter.js */\r
3554 \r
3555 (function() {\r
3556         tinymce.create('tinymce.dom.StringWriter', {\r
3557                 str : null,\r
3558                 tags : null,\r
3559                 count : 0,\r
3560                 settings : null,\r
3561                 indent : null,\r
3562 \r
3563                 StringWriter : function(s) {\r
3564                         this.settings = tinymce.extend({\r
3565                                 indent_char : ' ',\r
3566                                 indentation : 1\r
3567                         }, s);\r
3568 \r
3569                         this.reset();\r
3570                 },\r
3571 \r
3572                 reset : function() {\r
3573                         this.indent = '';\r
3574                         this.str = "";\r
3575                         this.tags = [];\r
3576                         this.count = 0;\r
3577                 },\r
3578 \r
3579                 writeStartElement : function(n) {\r
3580                         this._writeAttributesEnd();\r
3581                         this.writeRaw('<' + n);\r
3582                         this.tags.push(n);\r
3583                         this.inAttr = true;\r
3584                         this.count++;\r
3585                         this.elementCount = this.count;\r
3586                 },\r
3587 \r
3588                 writeAttribute : function(n, v) {\r
3589                         var t = this;\r
3590 \r
3591                         t.writeRaw(" " + t.encode(n) + '="' + t.encode(v) + '"');\r
3592                 },\r
3593 \r
3594                 writeEndElement : function() {\r
3595                         var n;\r
3596 \r
3597                         if (this.tags.length > 0) {\r
3598                                 n = this.tags.pop();\r
3599 \r
3600                                 if (this._writeAttributesEnd(1))\r
3601                                         this.writeRaw('</' + n + '>');\r
3602 \r
3603                                 if (this.settings.indentation > 0)\r
3604                                         this.writeRaw('\n');\r
3605                         }\r
3606                 },\r
3607 \r
3608                 writeFullEndElement : function() {\r
3609                         if (this.tags.length > 0) {\r
3610                                 this._writeAttributesEnd();\r
3611                                 this.writeRaw('</' + this.tags.pop() + '>');\r
3612 \r
3613                                 if (this.settings.indentation > 0)\r
3614                                         this.writeRaw('\n');\r
3615                         }\r
3616                 },\r
3617 \r
3618                 writeText : function(v) {\r
3619                         this._writeAttributesEnd();\r
3620                         this.writeRaw(this.encode(v));\r
3621                         this.count++;\r
3622                 },\r
3623 \r
3624                 writeCDATA : function(v) {\r
3625                         this._writeAttributesEnd();\r
3626                         this.writeRaw('<![CDATA[' + v + ']]>');\r
3627                         this.count++;\r
3628                 },\r
3629 \r
3630                 writeComment : function(v) {\r
3631                         this._writeAttributesEnd();\r
3632                         this.writeRaw('<!-- ' + v + '-->');\r
3633                         this.count++;\r
3634                 },\r
3635 \r
3636                 writeRaw : function(v) {\r
3637                         this.str += v;\r
3638                 },\r
3639 \r
3640                 encode : function(s) {\r
3641                         return s.replace(/[<>&"]/g, function(v) {\r
3642                                 switch (v) {\r
3643                                         case '<':\r
3644                                                 return '&lt;';\r
3645 \r
3646                                         case '>':\r
3647                                                 return '&gt;';\r
3648 \r
3649                                         case '&':\r
3650                                                 return '&amp;';\r
3651 \r
3652                                         case '"':\r
3653                                                 return '&quot;';\r
3654                                 }\r
3655 \r
3656                                 return v;\r
3657                         });\r
3658                 },\r
3659 \r
3660                 getContent : function() {\r
3661                         return this.str;\r
3662                 },\r
3663 \r
3664                 _writeAttributesEnd : function(s) {\r
3665                         if (!this.inAttr)\r
3666                                 return;\r
3667 \r
3668                         this.inAttr = false;\r
3669 \r
3670                         if (s && this.elementCount == this.count) {\r
3671                                 this.writeRaw(' />');\r
3672                                 return false;\r
3673                         }\r
3674 \r
3675                         this.writeRaw('>');\r
3676 \r
3677                         return true;\r
3678                 }\r
3679 \r
3680                 });\r
3681 })();\r
3682 \r
3683 /* file:jscripts/tiny_mce/classes/dom/Serializer.js */\r
3684 \r
3685 (function() {\r
3686         // Shorten names\r
3687         var extend = tinymce.extend, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher, isIE = tinymce.isIE, isGecko = tinymce.isGecko;\r
3688 \r
3689         // Returns only attribites that have values not all attributes in IE\r
3690         function getIEAtts(n) {\r
3691                 var o = [];\r
3692 \r
3693                 // Object will throw exception in IE\r
3694                 if (n.nodeName == 'OBJECT')\r
3695                         return n.attributes;\r
3696 \r
3697                 n.cloneNode(false).outerHTML.replace(/([a-z0-9\:\-_]+)=/gi, function(a, b) {\r
3698                         o.push({specified : 1, nodeName : b});\r
3699                 });\r
3700 \r
3701                 return o;\r
3702         };\r
3703 \r
3704         function wildcardToRE(s) {\r
3705                 return s.replace(/([?+*])/g, '.$1');\r
3706         };\r
3707 \r
3708         tinymce.create('tinymce.dom.Serializer', {\r
3709                 Serializer : function(s) {\r
3710                         var t = this;\r
3711 \r
3712                         t.key = 0;\r
3713                         t.onPreProcess = new Dispatcher(t);\r
3714                         t.onPostProcess = new Dispatcher(t);\r
3715 \r
3716                         if (tinymce.relaxedDomain && tinymce.isGecko) {\r
3717                                 // Gecko has a bug where we can't create a new XML document if domain relaxing is used\r
3718                                 t.writer = new tinymce.dom.StringWriter();\r
3719                         } else {\r
3720                                 try {\r
3721                                         t.writer = new tinymce.dom.XMLWriter();\r
3722                                 } catch (ex) {\r
3723                                         // IE might throw exception if ActiveX is disabled so we then switch to the slightly slower StringWriter\r
3724                                         t.writer = new tinymce.dom.StringWriter();\r
3725                                 }\r
3726                         }\r
3727 \r
3728                         // Default settings\r
3729                         t.settings = s = extend({\r
3730                                 dom : tinymce.DOM,\r
3731                                 valid_nodes : 0,\r
3732                                 node_filter : 0,\r
3733                                 attr_filter : 0,\r
3734                                 invalid_attrs : /^(mce_|_moz_)/,\r
3735                                 closed : /(br|hr|input|meta|img|link|param)/,\r
3736                                 entity_encoding : 'named',\r
3737                                 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
3738                                 bool_attrs : /(checked|disabled|readonly|selected|nowrap)/,\r
3739                                 valid_elements : '*[*]',\r
3740                                 extended_valid_elements : 0,\r
3741                                 valid_child_elements : 0,\r
3742                                 invalid_elements : 0,\r
3743                                 fix_table_elements : 0,\r
3744                                 fix_list_elements : true,\r
3745                                 fix_content_duplication : true,\r
3746                                 convert_fonts_to_spans : false,\r
3747                                 font_size_classes : 0,\r
3748                                 font_size_style_values : 0,\r
3749                                 apply_source_formatting : 0,\r
3750                                 indent_mode : 'simple',\r
3751                                 indent_char : '\t',\r
3752                                 indent_levels : 1,\r
3753                                 remove_linebreaks : 1,\r
3754                                 remove_redundant_brs : 1,\r
3755                                 element_format : 'xhtml'\r
3756                         }, s);\r
3757 \r
3758                         t.dom = s.dom;\r
3759 \r
3760                         if (s.remove_redundant_brs) {\r
3761                                 t.onPostProcess.add(function(se, o) {\r
3762                                         // Remove BR elements at end of list elements since they get rendered in IE\r
3763                                         o.content = o.content.replace(/<br \/>(\s*<\/li>)/g, '$1');\r
3764                                 });\r
3765                         }\r
3766 \r
3767                         // Remove XHTML element endings i.e. produce crap :) XHTML is better\r
3768                         if (s.element_format == 'html') {\r
3769                                 t.onPostProcess.add(function(se, o) {\r
3770                                         o.content = o.content.replace(/<([^>]+) \/>/g, '<$1>');\r
3771                                 });\r
3772                         }\r
3773 \r
3774                         if (s.fix_list_elements) {\r
3775                                 t.onPreProcess.add(function(se, o) {\r
3776                                         var nl, x, a = ['ol', 'ul'], i, n, p, r = /^(OL|UL)$/, np;\r
3777 \r
3778                                         function prevNode(e, n) {\r
3779                                                 var a = n.split(','), i;\r
3780 \r
3781                                                 while ((e = e.previousSibling) != null) {\r
3782                                                         for (i=0; i<a.length; i++) {\r
3783                                                                 if (e.nodeName == a[i])\r
3784                                                                         return e;\r
3785                                                         }\r
3786                                                 }\r
3787 \r
3788                                                 return null;\r
3789                                         };\r
3790 \r
3791                                         for (x=0; x<a.length; x++) {\r
3792                                                 nl = t.dom.select(a[x], o.node);\r
3793 \r
3794                                                 for (i=0; i<nl.length; i++) {\r
3795                                                         n = nl[i];\r
3796                                                         p = n.parentNode;\r
3797 \r
3798                                                         if (r.test(p.nodeName)) {\r
3799                                                                 np = prevNode(n, 'LI');\r
3800 \r
3801                                                                 if (!np) {\r
3802                                                                         np = t.dom.create('li');\r
3803                                                                         np.innerHTML = '&nbsp;';\r
3804                                                                         np.appendChild(n);\r
3805                                                                         p.insertBefore(np, p.firstChild);\r
3806                                                                 } else\r
3807                                                                         np.appendChild(n);\r
3808                                                         }\r
3809                                                 }\r
3810                                         }\r
3811                                 });\r
3812                         }\r
3813 \r
3814                         if (s.fix_table_elements) {\r
3815                                 t.onPreProcess.add(function(se, o) {\r
3816                                         each(t.dom.select('table', o.node), function(e) {\r
3817                                                 var pa = t.dom.getParent(e, 'H1,H2,H3,H4,H5,H6,P'), pa2, n, tm, pl = [], i, ns;\r
3818 \r
3819                                                 if (pa) {\r
3820                                                         pa2 = pa.cloneNode(false);\r
3821 \r
3822                                                         pl.push(e);\r
3823                                                         for (n = e; n = n.parentNode;) {\r
3824                                                                 pl.push(n);\r
3825 \r
3826                                                                 if (n == pa)\r
3827                                                                         break;\r
3828                                                         }\r
3829 \r
3830                                                         tm = pa2;\r
3831                                                         for (i = pl.length - 1; i >= 0; i--) {\r
3832                                                                 if (i == pl.length - 1) {\r
3833                                                                         while (ns = pl[i - 1].nextSibling)\r
3834                                                                                 tm.appendChild(ns.parentNode.removeChild(ns));\r
3835                                                                 } else {\r
3836                                                                         n = pl[i].cloneNode(false);\r
3837 \r
3838                                                                         if (i != 0) {\r
3839                                                                                 while (ns = pl[i - 1].nextSibling)\r
3840                                                                                         n.appendChild(ns.parentNode.removeChild(ns));\r
3841                                                                         }\r
3842 \r
3843                                                                         tm = tm.appendChild(n);\r
3844                                                                 }\r
3845                                                         }\r
3846 \r
3847                                                         e = t.dom.insertAfter(e.parentNode.removeChild(e), pa);\r
3848                                                         t.dom.insertAfter(e, pa);\r
3849                                                         t.dom.insertAfter(pa2, e);\r
3850                                                 }\r
3851                                         });\r
3852                                 });\r
3853                         }\r
3854                 },\r
3855 \r
3856                 setEntities : function(s) {\r
3857                         var t = this, a, i, l = {}, re = '', v;\r
3858 \r
3859                         // No need to setup more than once\r
3860                         if (t.entityLookup)\r
3861                                 return;\r
3862 \r
3863                         // Build regex and lookup array\r
3864                         a = s.split(',');\r
3865                         for (i = 0; i < a.length; i += 2) {\r
3866                                 v = a[i];\r
3867 \r
3868                                 // Don't add default &amp; &quot; etc.\r
3869                                 if (v == 34 || v == 38 || v == 60 || v == 62)\r
3870                                         continue;\r
3871 \r
3872                                 l[String.fromCharCode(a[i])] = a[i + 1];\r
3873 \r
3874                                 v = parseInt(a[i]).toString(16);\r
3875                                 re += '\\u' + '0000'.substring(v.length) + v;\r
3876                         }\r
3877 \r
3878                         if (!re) {\r
3879                                 t.settings.entity_encoding = 'raw';\r
3880                                 return;\r
3881                         }\r
3882 \r
3883                         t.entitiesRE = new RegExp('[' + re + ']', 'g');\r
3884                         t.entityLookup = l;\r
3885                 },\r
3886 \r
3887                 setValidChildRules : function(s) {\r
3888                         this.childRules = null;\r
3889                         this.addValidChildRules(s);\r
3890                 },\r
3891 \r
3892                 addValidChildRules : function(s) {\r
3893                         var t = this, inst, intr, bloc;\r
3894 \r
3895                         if (!s)\r
3896                                 return;\r
3897 \r
3898                         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
3899                         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
3900                         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
3901 \r
3902                         each(s.split(','), function(s) {\r
3903                                 var p = s.split(/\[|\]/), re;\r
3904 \r
3905                                 s = '';\r
3906                                 each(p[1].split('|'), function(v) {\r
3907                                         if (s)\r
3908                                                 s += '|';\r
3909 \r
3910                                         switch (v) {\r
3911                                                 case '%itrans':\r
3912                                                         v = intr;\r
3913                                                         break;\r
3914 \r
3915                                                 case '%itrans_na':\r
3916                                                         v = intr.substring(2);\r
3917                                                         break;\r
3918 \r
3919                                                 case '%istrict':\r
3920                                                         v = inst;\r
3921                                                         break;\r
3922 \r
3923                                                 case '%istrict_na':\r
3924                                                         v = inst.substring(2);\r
3925                                                         break;\r
3926 \r
3927                                                 case '%btrans':\r
3928                                                         v = bloc;\r
3929                                                         break;\r
3930 \r
3931                                                 case '%bstrict':\r
3932                                                         v = bloc;\r
3933                                                         break;\r
3934                                         }\r
3935 \r
3936                                         s += v;\r
3937                                 });\r
3938                                 re = new RegExp('^(' + s.toLowerCase() + ')$', 'i');\r
3939 \r
3940                                 each(p[0].split('/'), function(s) {\r
3941                                         t.childRules = t.childRules || {};\r
3942                                         t.childRules[s] = re;\r
3943                                 });\r
3944                         });\r
3945 \r
3946                         // Build regex\r
3947                         s = '';\r
3948                         each(t.childRules, function(v, k) {\r
3949                                 if (s)\r
3950                                         s += '|';\r
3951 \r
3952                                 s += k;\r
3953                         });\r
3954 \r
3955                         t.parentElementsRE = new RegExp('^(' + s.toLowerCase() + ')$', 'i');\r
3956 \r
3957                         /*console.debug(t.parentElementsRE.toString());\r
3958                         each(t.childRules, function(v) {\r
3959                                 console.debug(v.toString());\r
3960                         });*/\r
3961                 },\r
3962 \r
3963                 setRules : function(s) {\r
3964                         var t = this;\r
3965 \r
3966                         t._setup();\r
3967                         t.rules = {};\r
3968                         t.wildRules = [];\r
3969                         t.validElements = {};\r
3970 \r
3971                         return t.addRules(s);\r
3972                 },\r
3973 \r
3974                 addRules : function(s) {\r
3975                         var t = this, dr;\r
3976 \r
3977                         if (!s)\r
3978                                 return;\r
3979 \r
3980                         t._setup();\r
3981 \r
3982                         each(s.split(','), function(s) {\r
3983                                 var p = s.split(/\[|\]/), tn = p[0].split('/'), ra, at, wat, va = [];\r
3984 \r
3985                                 // Extend with default rules\r
3986                                 if (dr)\r
3987                                         at = tinymce.extend([], dr.attribs);\r
3988 \r
3989                                 // Parse attributes\r
3990                                 if (p.length > 1) {\r
3991                                         each(p[1].split('|'), function(s) {\r
3992                                                 var ar = {}, i;\r
3993 \r
3994                                                 at = at || [];\r
3995 \r
3996                                                 // Parse attribute rule\r
3997                                                 s = s.replace(/::/g, '~');\r
3998                                                 s = /^([!\-])?([\w*.?~_\-]+|)([=:<])?(.+)?$/.exec(s);\r
3999                                                 s[2] = s[2].replace(/~/g, ':');\r
4000 \r
4001                                                 // Add required attributes\r
4002                                                 if (s[1] == '!') {\r
4003                                                         ra = ra || [];\r
4004                                                         ra.push(s[2]);\r
4005                                                 }\r
4006 \r
4007                                                 // Remove inherited attributes\r
4008                                                 if (s[1] == '-') {\r
4009                                                         for (i = 0; i <at.length; i++) {\r
4010                                                                 if (at[i].name == s[2]) {\r
4011                                                                         at.splice(i, 1);\r
4012                                                                         return;\r
4013                                                                 }\r
4014                                                         }\r
4015                                                 }\r
4016 \r
4017                                                 switch (s[3]) {\r
4018                                                         // Add default attrib values\r
4019                                                         case '=':\r
4020                                                                 ar.defaultVal = s[4] || '';\r
4021                                                                 break;\r
4022 \r
4023                                                         // Add forced attrib values\r
4024                                                         case ':':\r
4025                                                                 ar.forcedVal = s[4];\r
4026                                                                 break;\r
4027 \r
4028                                                         // Add validation values\r
4029                                                         case '<':\r
4030                                                                 ar.validVals = s[4].split('?');\r
4031                                                                 break;\r
4032                                                 }\r
4033 \r
4034                                                 if (/[*.?]/.test(s[2])) {\r
4035                                                         wat = wat || [];\r
4036                                                         ar.nameRE = new RegExp('^' + wildcardToRE(s[2]) + '$');\r
4037                                                         wat.push(ar);\r
4038                                                 } else {\r
4039                                                         ar.name = s[2];\r
4040                                                         at.push(ar);\r
4041                                                 }\r
4042 \r
4043                                                 va.push(s[2]);\r
4044                                         });\r
4045                                 }\r
4046 \r
4047                                 // Handle element names\r
4048                                 each(tn, function(s, i) {\r
4049                                         var pr = s.charAt(0), x = 1, ru = {};\r
4050 \r
4051                                         // Extend with default rule data\r
4052                                         if (dr) {\r
4053                                                 if (dr.noEmpty)\r
4054                                                         ru.noEmpty = dr.noEmpty;\r
4055 \r
4056                                                 if (dr.fullEnd)\r
4057                                                         ru.fullEnd = dr.fullEnd;\r
4058 \r
4059                                                 if (dr.padd)\r
4060                                                         ru.padd = dr.padd;\r
4061                                         }\r
4062 \r
4063                                         // Handle prefixes\r
4064                                         switch (pr) {\r
4065                                                 case '-':\r
4066                                                         ru.noEmpty = true;\r
4067                                                         break;\r
4068 \r
4069                                                 case '+':\r
4070                                                         ru.fullEnd = true;\r
4071                                                         break;\r
4072 \r
4073                                                 case '#':\r
4074                                                         ru.padd = true;\r
4075                                                         break;\r
4076 \r
4077                                                 default:\r
4078                                                         x = 0;\r
4079                                         }\r
4080 \r
4081                                         tn[i] = s = s.substring(x);\r
4082                                         t.validElements[s] = 1;\r
4083 \r
4084                                         // Add element name or element regex\r
4085                                         if (/[*.?]/.test(tn[0])) {\r
4086                                                 ru.nameRE = new RegExp('^' + wildcardToRE(tn[0]) + '$');\r
4087                                                 t.wildRules = t.wildRules || {};\r
4088                                                 t.wildRules.push(ru);\r
4089                                         } else {\r
4090                                                 ru.name = tn[0];\r
4091 \r
4092                                                 // Store away default rule\r
4093                                                 if (tn[0] == '@')\r
4094                                                         dr = ru;\r
4095 \r
4096                                                 t.rules[s] = ru;\r
4097                                         }\r
4098 \r
4099                                         ru.attribs = at;\r
4100 \r
4101                                         if (ra)\r
4102                                                 ru.requiredAttribs = ra;\r
4103 \r
4104                                         if (wat) {\r
4105                                                 // Build valid attributes regexp\r
4106                                                 s = '';\r
4107                                                 each(va, function(v) {\r
4108                                                         if (s)\r
4109                                                                 s += '|';\r
4110 \r
4111                                                         s += '(' + wildcardToRE(v) + ')';\r
4112                                                 });\r
4113                                                 ru.validAttribsRE = new RegExp('^' + s.toLowerCase() + '$');\r
4114                                                 ru.wildAttribs = wat;\r
4115                                         }\r
4116                                 });\r
4117                         });\r
4118 \r
4119                         // Build valid elements regexp\r
4120                         s = '';\r
4121                         each(t.validElements, function(v, k) {\r
4122                                 if (s)\r
4123                                         s += '|';\r
4124 \r
4125                                 if (k != '@')\r
4126                                         s += k;\r
4127                         });\r
4128                         t.validElementsRE = new RegExp('^(' + wildcardToRE(s.toLowerCase()) + ')$');\r
4129 \r
4130                         //console.debug(t.validElementsRE.toString());\r
4131                         //console.dir(t.rules);\r
4132                         //console.dir(t.wildRules);\r
4133                 },\r
4134 \r
4135                 findRule : function(n) {\r
4136                         var t = this, rl = t.rules, i, r;\r
4137 \r
4138                         t._setup();\r
4139 \r
4140                         // Exact match\r
4141                         r = rl[n];\r
4142                         if (r)\r
4143                                 return r;\r
4144 \r
4145                         // Try wildcards\r
4146                         rl = t.wildRules;\r
4147                         for (i = 0; i < rl.length; i++) {\r
4148                                 if (rl[i].nameRE.test(n))\r
4149                                         return rl[i];\r
4150                         }\r
4151 \r
4152                         return null;\r
4153                 },\r
4154 \r
4155                 findAttribRule : function(ru, n) {\r
4156                         var i, wa = ru.wildAttribs;\r
4157 \r
4158                         for (i = 0; i < wa.length; i++) {\r
4159                                 if (wa[i].nameRE.test(n))\r
4160                                         return wa[i];\r
4161                         }\r
4162 \r
4163                         return null;\r
4164                 },\r
4165 \r
4166                 serialize : function(n, o) {\r
4167                         var h, t = this;\r
4168 \r
4169                         t._setup();\r
4170                         o = o || {};\r
4171                         o.format = o.format || 'html';\r
4172                         t.processObj = o;\r
4173                         n = n.cloneNode(true);\r
4174                         t.key = '' + (parseInt(t.key) + 1);\r
4175 \r
4176                         // Pre process\r
4177                         if (!o.no_events) {\r
4178                                 o.node = n;\r
4179                                 t.onPreProcess.dispatch(t, o);\r
4180                         }\r
4181 \r
4182                         // Serialize HTML DOM into a string\r
4183                         t.writer.reset();\r
4184                         t._serializeNode(n, o.getInner);\r
4185 \r
4186                         // Post process\r
4187                         o.content = t.writer.getContent();\r
4188 \r
4189                         if (!o.no_events)\r
4190                                 t.onPostProcess.dispatch(t, o);\r
4191 \r
4192                         t._postProcess(o);\r
4193                         o.node = null;\r
4194 \r
4195                         return tinymce.trim(o.content);\r
4196                 },\r
4197 \r
4198                 // Internal functions\r
4199 \r
4200                 _postProcess : function(o) {\r
4201                         var t = this, s = t.settings, h = o.content, sc = [], p;\r
4202 \r
4203                         if (o.format == 'html') {\r
4204                                 // Protect some elements\r
4205                                 p = t._protect({\r
4206                                         content : h,\r
4207                                         patterns : [\r
4208                                                 {pattern : /(<script[^>]*>)(.*?)(<\/script>)/g},\r
4209                                                 {pattern : /(<style[^>]*>)(.*?)(<\/style>)/g},\r
4210                                                 {pattern : /(<pre[^>]*>)(.*?)(<\/pre>)/g, encode : 1},\r
4211                                                 {pattern : /(<!--\[CDATA\[)(.*?)(\]\]-->)/g}\r
4212                                         ]\r
4213                                 });\r
4214 \r
4215                                 h = p.content;\r
4216 \r
4217                                 // Entity encode\r
4218                                 if (s.entity_encoding !== 'raw')\r
4219                                         h = t._encode(h);\r
4220 \r
4221                                 // Use BR instead of &nbsp; padded P elements inside editor and use <p>&nbsp;</p> outside editor\r
4222 /*                              if (o.set)\r
4223                                         h = h.replace(/<p>\s+(&nbsp;|&#160;|\u00a0|<br \/>)\s+<\/p>/g, '<p><br /></p>');\r
4224                                 else\r
4225                                         h = h.replace(/<p>\s+(&nbsp;|&#160;|\u00a0|<br \/>)\s+<\/p>/g, '<p>$1</p>');*/\r
4226 \r
4227                                 // Since Gecko and Safari keeps whitespace in the DOM we need to\r
4228                                 // remove it inorder to match other browsers. But I think Gecko and Safari is right.\r
4229                                 // This process is only done when getting contents out from the editor.\r
4230                                 if (!o.set) {\r
4231                                         // We need to replace paragraph whitespace with an nbsp before indentation to keep the \u00a0 char\r
4232                                         h = h.replace(/<p>\s+<\/p>|<p([^>]+)>\s+<\/p>/g, s.entity_encoding == 'numeric' ? '<p$1>&#160;</p>' : '<p$1>&nbsp;</p>');\r
4233 \r
4234                                         if (s.remove_linebreaks) {\r
4235                                                 h = h.replace(/\r?\n|\r/g, ' ');\r
4236                                                 h = h.replace(/(<[^>]+>)\s+/g, '$1 ');\r
4237                                                 h = h.replace(/\s+(<\/[^>]+>)/g, ' $1');\r
4238                                                 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
4239                                                 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
4240                                                 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
4241                                         }\r
4242 \r
4243                                         // Simple indentation\r
4244                                         if (s.apply_source_formatting && s.indent_mode == 'simple') {\r
4245                                                 // Add line breaks before and after block elements\r
4246                                                 h = h.replace(/<(\/?)(ul|hr|table|meta|link|tbody|tr|object|body|head|html|map)(|[^>]+)>\s*/g, '\n<$1$2$3>\n');\r
4247                                                 h = h.replace(/\s*<(p|h[1-6]|blockquote|div|title|style|pre|script|td|li|area)(|[^>]+)>/g, '\n<$1$2>');\r
4248                                                 h = h.replace(/<\/(p|h[1-6]|blockquote|div|title|style|pre|script|td|li)>\s*/g, '</$1>\n');\r
4249                                                 h = h.replace(/\n\n/g, '\n');\r
4250                                         }\r
4251                                 }\r
4252 \r
4253                                 h = t._unprotect(h, p);\r
4254 \r
4255                                 // Restore CDATA sections\r
4256                                 h = h.replace(/<!--\[CDATA\[([\s\S]+)\]\]-->/g, '<![CDATA[$1]]>');\r
4257 \r
4258                                 // Restore the \u00a0 character if raw mode is enabled\r
4259                                 if (s.entity_encoding == 'raw')\r
4260                                         h = h.replace(/<p>&nbsp;<\/p>|<p([^>]+)>&nbsp;<\/p>/g, '<p$1>\u00a0</p>');\r
4261                         }\r
4262 \r
4263                         o.content = h;\r
4264                 },\r
4265 \r
4266                 _serializeNode : function(n, inn) {\r
4267                         var t = this, s = t.settings, w = t.writer, hc, el, cn, i, l, a, at, no, v, nn, ru, ar, iv;\r
4268 \r
4269                         if (!s.node_filter || s.node_filter(n)) {\r
4270                                 switch (n.nodeType) {\r
4271                                         case 1: // Element\r
4272                                                 if (n.hasAttribute ? n.hasAttribute('mce_bogus') : n.getAttribute('mce_bogus'))\r
4273                                                         return;\r
4274 \r
4275                                                 iv = false;\r
4276                                                 hc = n.hasChildNodes();\r
4277                                                 nn = n.getAttribute('mce_name') || n.nodeName.toLowerCase();\r
4278 \r
4279                                                 // Add correct prefix on IE\r
4280                                                 if (isIE) {\r
4281                                                         if (n.scopeName !== 'HTML' && n.scopeName !== 'html')\r
4282                                                                 nn = n.scopeName + ':' + nn;\r
4283                                                 }\r
4284 \r
4285                                                 // Remove mce prefix on IE needed for the abbr element\r
4286                                                 if (nn.indexOf('mce:') === 0)\r
4287                                                         nn = nn.substring(4);\r
4288 \r
4289                                                 // Check if valid\r
4290                                                 if (!t.validElementsRE.test(nn) || (t.invalidElementsRE && t.invalidElementsRE.test(nn)) || inn) {\r
4291                                                         iv = true;\r
4292                                                         break;\r
4293                                                 }\r
4294 \r
4295                                                 if (isIE) {\r
4296                                                         // Fix IE content duplication (DOM can have multiple copies of the same node)\r
4297                                                         if (s.fix_content_duplication) {\r
4298                                                                 if (n.mce_serialized == t.key)\r
4299                                                                         return;\r
4300 \r
4301                                                                 n.mce_serialized = t.key;\r
4302                                                         }\r
4303 \r
4304                                                         // IE sometimes adds a / infront of the node name\r
4305                                                         if (nn.charAt(0) == '/')\r
4306                                                                 nn = nn.substring(1);\r
4307                                                 } else if (isGecko) {\r
4308                                                         // Ignore br elements\r
4309                                                         if (n.nodeName === 'BR' && n.getAttribute('type') == '_moz')\r
4310                                                                 return;\r
4311                                                 }\r
4312 \r
4313                                                 // Check if valid child\r
4314                                                 if (t.childRules) {\r
4315                                                         if (t.parentElementsRE.test(t.elementName)) {\r
4316                                                                 if (!t.childRules[t.elementName].test(nn)) {\r
4317                                                                         iv = true;\r
4318                                                                         break;\r
4319                                                                 }\r
4320                                                         }\r
4321 \r
4322                                                         t.elementName = nn;\r
4323                                                 }\r
4324 \r
4325                                                 ru = t.findRule(nn);\r
4326                                                 nn = ru.name || nn;\r
4327 \r
4328                                                 // Skip empty nodes or empty node name in IE\r
4329                                                 if ((!hc && ru.noEmpty) || (isIE && !nn)) {\r
4330                                                         iv = true;\r
4331                                                         break;\r
4332                                                 }\r
4333 \r
4334                                                 // Check required\r
4335                                                 if (ru.requiredAttribs) {\r
4336                                                         a = ru.requiredAttribs;\r
4337 \r
4338                                                         for (i = a.length - 1; i >= 0; i--) {\r
4339                                                                 if (this.dom.getAttrib(n, a[i]) !== '')\r
4340                                                                         break;\r
4341                                                         }\r
4342 \r
4343                                                         // None of the required was there\r
4344                                                         if (i == -1) {\r
4345                                                                 iv = true;\r
4346                                                                 break;\r
4347                                                         }\r
4348                                                 }\r
4349 \r
4350                                                 w.writeStartElement(nn);\r
4351 \r
4352                                                 // Add ordered attributes\r
4353                                                 if (ru.attribs) {\r
4354                                                         for (i=0, at = ru.attribs, l = at.length; i<l; i++) {\r
4355                                                                 a = at[i];\r
4356                                                                 v = t._getAttrib(n, a);\r
4357 \r
4358                                                                 if (v !== null)\r
4359                                                                         w.writeAttribute(a.name, v);\r
4360                                                         }\r
4361                                                 }\r
4362 \r
4363                                                 // Add wild attributes\r
4364                                                 if (ru.validAttribsRE) {\r
4365                                                         at = isIE ? getIEAtts(n) : n.attributes;\r
4366                                                         for (i=at.length-1; i>-1; i--) {\r
4367                                                                 no = at[i];\r
4368 \r
4369                                                                 if (no.specified) {\r
4370                                                                         a = no.nodeName.toLowerCase();\r
4371 \r
4372                                                                         if (s.invalid_attrs.test(a) || !ru.validAttribsRE.test(a))\r
4373                                                                                 continue;\r
4374 \r
4375                                                                         ar = t.findAttribRule(ru, a);\r
4376                                                                         v = t._getAttrib(n, ar, a);\r
4377 \r
4378                                                                         if (v !== null)\r
4379                                                                                 w.writeAttribute(a, v);\r
4380                                                                 }\r
4381                                                         }\r
4382                                                 }\r
4383 \r
4384                                                 // Padd empty nodes with a &nbsp;\r
4385                                                 if (ru.padd) {\r
4386                                                         // If it has only one bogus child, padd it anyway workaround for <td><br /></td> bug\r
4387                                                         if (hc && (cn = n.firstChild) && cn.nodeType === 1 && n.childNodes.length === 1) {\r
4388                                                                 if (cn.hasAttribute ? cn.hasAttribute('mce_bogus') : cn.getAttribute('mce_bogus'))\r
4389                                                                         w.writeText('\u00a0');\r
4390                                                         } else if (!hc)\r
4391                                                                 w.writeText('\u00a0'); // No children then padd it\r
4392                                                 }\r
4393 \r
4394                                                 break;\r
4395 \r
4396                                         case 3: // Text\r
4397                                                 // Check if valid child\r
4398                                                 if (t.childRules && t.parentElementsRE.test(t.elementName)) {\r
4399                                                         if (!t.childRules[t.elementName].test(n.nodeName))\r
4400                                                                 return;\r
4401                                                 }\r
4402 \r
4403                                                 return w.writeText(n.nodeValue);\r
4404 \r
4405                                         case 4: // CDATA\r
4406                                                 return w.writeCDATA(n.nodeValue);\r
4407 \r
4408                                         case 8: // Comment\r
4409                                                 return w.writeComment(n.nodeValue);\r
4410                                 }\r
4411                         } else if (n.nodeType == 1)\r
4412                                 hc = n.hasChildNodes();\r
4413 \r
4414                         if (hc) {\r
4415                                 cn = n.firstChild;\r
4416 \r
4417                                 while (cn) {\r
4418                                         t._serializeNode(cn);\r
4419                                         t.elementName = nn;\r
4420                                         cn = cn.nextSibling;\r
4421                                 }\r
4422                         }\r
4423 \r
4424                         // Write element end\r
4425                         if (!iv) {\r
4426                                 if (hc || !s.closed.test(nn))\r
4427                                         w.writeFullEndElement();\r
4428                                 else\r
4429                                         w.writeEndElement();\r
4430                         }\r
4431                 },\r
4432 \r
4433                 _protect : function(o) {\r
4434                         var t = this;\r
4435 \r
4436                         o.items = o.items || [];\r
4437 \r
4438                         function enc(s) {\r
4439                                 return s.replace(/[\r\n\\]/g, function(c) {\r
4440                                         if (c === '\n')\r
4441                                                 return '\\n';\r
4442                                         else if (c === '\\')\r
4443                                                 return '\\\\';\r
4444 \r
4445                                         return '\\r';\r
4446                                 });\r
4447                         };\r
4448 \r
4449                         function dec(s) {\r
4450                                 return s.replace(/\\[\\rn]/g, function(c) {\r
4451                                         if (c === '\\n')\r
4452                                                 return '\n';\r
4453                                         else if (c === '\\\\')\r
4454                                                 return '\\';\r
4455 \r
4456                                         return '\r';\r
4457                                 });\r
4458                         };\r
4459 \r
4460                         each(o.patterns, function(p) {\r
4461                                 o.content = dec(enc(o.content).replace(p.pattern, function(x, a, b, c) {\r
4462                                         b = dec(b);\r
4463 \r
4464                                         if (p.encode)\r
4465                                                 b = t._encode(b);\r
4466 \r
4467                                         o.items.push(b);\r
4468                                         return a + '<!--mce:' + (o.items.length - 1) + '-->' + c;\r
4469                                 }));\r
4470                         });\r
4471 \r
4472                         return o;\r
4473                 },\r
4474 \r
4475                 _unprotect : function(h, o) {\r
4476                         h = h.replace(/\<!--mce:([0-9]+)--\>/g, function(a, b) {\r
4477                                 return o.items[parseInt(b)];\r
4478                         });\r
4479 \r
4480                         o.items = [];\r
4481 \r
4482                         return h;\r
4483                 },\r
4484 \r
4485                 _encode : function(h) {\r
4486                         var t = this, s = t.settings, l;\r
4487 \r
4488                         // Entity encode\r
4489                         if (s.entity_encoding !== 'raw') {\r
4490                                 if (s.entity_encoding.indexOf('named') != -1) {\r
4491                                         t.setEntities(s.entities);\r
4492                                         l = t.entityLookup;\r
4493 \r
4494                                         h = h.replace(t.entitiesRE, function(a) {\r
4495                                                 var v;\r
4496 \r
4497                                                 if (v = l[a])\r
4498                                                         a = '&' + v + ';';\r
4499 \r
4500                                                 return a;\r
4501                                         });\r
4502                                 }\r
4503 \r
4504                                 if (s.entity_encoding.indexOf('numeric') != -1) {\r
4505                                         h = h.replace(/[\u007E-\uFFFF]/g, function(a) {\r
4506                                                 return '&#' + a.charCodeAt(0) + ';';\r
4507                                         });\r
4508                                 }\r
4509                         }\r
4510 \r
4511                         return h;\r
4512                 },\r
4513 \r
4514                 _setup : function() {\r
4515                         var t = this, s = this.settings;\r
4516 \r
4517                         if (t.done)\r
4518                                 return;\r
4519 \r
4520                         t.done = 1;\r
4521 \r
4522                         t.setRules(s.valid_elements);\r
4523                         t.addRules(s.extended_valid_elements);\r
4524                         t.addValidChildRules(s.valid_child_elements);\r
4525 \r
4526                         if (s.invalid_elements)\r
4527                                 t.invalidElementsRE = new RegExp('^(' + wildcardToRE(s.invalid_elements.replace(/,/g, '|').toLowerCase()) + ')$');\r
4528 \r
4529                         if (s.attrib_value_filter)\r
4530                                 t.attribValueFilter = s.attribValueFilter;\r
4531                 },\r
4532 \r
4533                 _getAttrib : function(n, a, na) {\r
4534                         var i, v;\r
4535 \r
4536                         na = na || a.name;\r
4537 \r
4538                         if (a.forcedVal && (v = a.forcedVal)) {\r
4539                                 if (v === '{$uid}')\r
4540                                         return this.dom.uniqueId();\r
4541 \r
4542                                 return v;\r
4543                         }\r
4544 \r
4545                         v = this.dom.getAttrib(n, na);\r
4546 \r
4547                         // Bool attr\r
4548                         if (this.settings.bool_attrs.test(na) && v) {\r
4549                                 v = ('' + v).toLowerCase();\r
4550 \r
4551                                 if (v === 'false' || v === '0')\r
4552                                         return null;\r
4553 \r
4554                                 v = na;\r
4555                         }\r
4556 \r
4557                         switch (na) {\r
4558                                 case 'rowspan':\r
4559                                 case 'colspan':\r
4560                                         // Whats the point? Remove usless attribute value\r
4561                                         if (v == '1')\r
4562                                                 v = '';\r
4563 \r
4564                                         break;\r
4565                         }\r
4566 \r
4567                         if (this.attribValueFilter)\r
4568                                 v = this.attribValueFilter(na, v, n);\r
4569 \r
4570                         if (a.validVals) {\r
4571                                 for (i = a.validVals.length - 1; i >= 0; i--) {\r
4572                                         if (v == a.validVals[i])\r
4573                                                 break;\r
4574                                 }\r
4575 \r
4576                                 if (i == -1)\r
4577                                         return null;\r
4578                         }\r
4579 \r
4580                         if (v === '' && typeof(a.defaultVal) != 'undefined') {\r
4581                                 v = a.defaultVal;\r
4582 \r
4583                                 if (v === '{$uid}')\r
4584                                         return this.dom.uniqueId();\r
4585 \r
4586                                 return v;\r
4587                         } else {\r
4588                                 // Remove internal mceItemXX classes when content is extracted from editor\r
4589                                 if (na == 'class' && this.processObj.get)\r
4590                                         v = v.replace(/\s?mceItem\w+\s?/g, '');\r
4591                         }\r
4592 \r
4593                         if (v === '')\r
4594                                 return null;\r
4595 \r
4596 \r
4597                         return v;\r
4598                 }\r
4599 \r
4600                 });\r
4601 })();\r
4602 \r
4603 /* file:jscripts/tiny_mce/classes/dom/ScriptLoader.js */\r
4604 \r
4605 (function() {\r
4606         var each = tinymce.each, Event = tinymce.dom.Event;\r
4607 \r
4608         tinymce.create('tinymce.dom.ScriptLoader', {\r
4609                 ScriptLoader : function(s) {\r
4610                         this.settings = s || {};\r
4611                         this.queue = [];\r
4612                         this.lookup = {};\r
4613                 },\r
4614 \r
4615                 isDone : function(u) {\r
4616                         return this.lookup[u] ? this.lookup[u].state == 2 : 0;\r
4617                 },\r
4618 \r
4619                 markDone : function(u) {\r
4620                         this.lookup[u] = {state : 2, url : u};\r
4621                 },\r
4622 \r
4623                 add : function(u, cb, s, pr) {\r
4624                         var t = this, lo = t.lookup, o;\r
4625 \r
4626                         if (o = lo[u]) {\r
4627                                 // Is loaded fire callback\r
4628                                 if (cb && o.state == 2)\r
4629                                         cb.call(s || this);\r
4630 \r
4631                                 return o;\r
4632                         }\r
4633 \r
4634                         o = {state : 0, url : u, func : cb, scope : s || this};\r
4635 \r
4636                         if (pr)\r
4637                                 t.queue.unshift(o);\r
4638                         else\r
4639                                 t.queue.push(o);\r
4640 \r
4641                         lo[u] = o;\r
4642 \r
4643                         return o;\r
4644                 },\r
4645 \r
4646                 load : function(u, cb, s) {\r
4647                         var t = this, o;\r
4648 \r
4649                         if (o = t.lookup[u]) {\r
4650                                 // Is loaded fire callback\r
4651                                 if (cb && o.state == 2)\r
4652                                         cb.call(s || t);\r
4653 \r
4654                                 return o;\r
4655                         }\r
4656 \r
4657                         function loadScript(u) {\r
4658                                 if (Event.domLoaded || t.settings.strict_mode) {\r
4659                                         tinymce.util.XHR.send({\r
4660                                                 url : tinymce._addVer(u),\r
4661                                                 error : t.settings.error,\r
4662                                                 async : false,\r
4663                                                 success : function(co) {\r
4664                                                         t.eval(co);\r
4665                                                 }\r
4666                                         });\r
4667                                 } else\r
4668                                         document.write('<script type="text/javascript" src="' + tinymce._addVer(u) + '"></script>');\r
4669                         };\r
4670 \r
4671                         if (!tinymce.is(u, 'string')) {\r
4672                                 each(u, function(u) {\r
4673                                         loadScript(u);\r
4674                                 });\r
4675 \r
4676                                 if (cb)\r
4677                                         cb.call(s || t);\r
4678                         } else {\r
4679                                 loadScript(u);\r
4680 \r
4681                                 if (cb)\r
4682                                         cb.call(s || t);\r
4683                         }\r
4684                 },\r
4685 \r
4686                 loadQueue : function(cb, s) {\r
4687                         var t = this;\r
4688 \r
4689                         if (!t.queueLoading) {\r
4690                                 t.queueLoading = 1;\r
4691                                 t.queueCallbacks = [];\r
4692 \r
4693                                 t.loadScripts(t.queue, function() {\r
4694                                         t.queueLoading = 0;\r
4695 \r
4696                                         if (cb)\r
4697                                                 cb.call(s || t);\r
4698 \r
4699                                         each(t.queueCallbacks, function(o) {\r
4700                                                 o.func.call(o.scope);\r
4701                                         });\r
4702                                 });\r
4703                         } else if (cb)\r
4704                                 t.queueCallbacks.push({func : cb, scope : s || t});\r
4705                 },\r
4706 \r
4707                 eval : function(co) {\r
4708                         var w = window;\r
4709 \r
4710                         // Evaluate script\r
4711                         if (!w.execScript) {\r
4712                                 try {\r
4713                                         eval.call(w, co);\r
4714                                 } catch (ex) {\r
4715                                         eval(co, w); // Firefox 3.0a8\r
4716                                 }\r
4717                         } else\r
4718                                 w.execScript(co); // IE\r
4719                 },\r
4720 \r
4721                 loadScripts : function(sc, cb, s) {\r
4722                         var t = this, lo = t.lookup;\r
4723 \r
4724                         function done(o) {\r
4725                                 o.state = 2; // Has been loaded\r
4726 \r
4727                                 // Run callback\r
4728                                 if (o.func)\r
4729                                         o.func.call(o.scope || t);\r
4730                         };\r
4731 \r
4732                         function allDone() {\r
4733                                 var l;\r
4734 \r
4735                                 // Check if all files are loaded\r
4736                                 l = sc.length;\r
4737                                 each(sc, function(o) {\r
4738                                         o = lo[o.url];\r
4739 \r
4740                                         if (o.state === 2) {// It has finished loading\r
4741                                                 done(o);\r
4742                                                 l--;\r
4743                                         } else\r
4744                                                 load(o);\r
4745                                 });\r
4746 \r
4747                                 // They are all loaded\r
4748                                 if (l === 0 && cb) {\r
4749                                         cb.call(s || t);\r
4750                                         cb = 0;\r
4751                                 }\r
4752                         };\r
4753 \r
4754                         function load(o) {\r
4755                                 if (o.state > 0)\r
4756                                         return;\r
4757 \r
4758                                 o.state = 1; // Is loading\r
4759 \r
4760                                 tinymce.dom.ScriptLoader.loadScript(o.url, function() {\r
4761                                         done(o);\r
4762                                         allDone();\r
4763                                 });\r
4764 \r
4765                                 /*\r
4766                                 tinymce.util.XHR.send({\r
4767                                         url : o.url,\r
4768                                         error : t.settings.error,\r
4769                                         success : function(co) {\r
4770                                                 t.eval(co);\r
4771                                                 done(o);\r
4772                                                 allDone();\r
4773                                         }\r
4774                                 });\r
4775                                 */\r
4776                         };\r
4777 \r
4778                         each(sc, function(o) {\r
4779                                 var u = o.url;\r
4780 \r
4781                                 // Add to queue if needed\r
4782                                 if (!lo[u]) {\r
4783                                         lo[u] = o;\r
4784                                         t.queue.push(o);\r
4785                                 } else\r
4786                                         o = lo[u];\r
4787 \r
4788                                 // Is already loading or has been loaded\r
4789                                 if (o.state > 0)\r
4790                                         return;\r
4791 \r
4792                                 if (!Event.domLoaded && !t.settings.strict_mode) {\r
4793                                         var ix, ol = '';\r
4794 \r
4795                                         // Add onload events\r
4796                                         if (cb || o.func) {\r
4797                                                 o.state = 1; // Is loading\r
4798 \r
4799                                                 ix = tinymce.dom.ScriptLoader._addOnLoad(function() {\r
4800                                                         done(o);\r
4801                                                         allDone();\r
4802                                                 });\r
4803 \r
4804                                                 if (tinymce.isIE)\r
4805                                                         ol = ' onreadystatechange="';\r
4806                                                 else\r
4807                                                         ol = ' onload="';\r
4808 \r
4809                                                 ol += 'tinymce.dom.ScriptLoader._onLoad(this,\'' + u + '\',' + ix + ');"';\r
4810                                         }\r
4811 \r
4812                                         document.write('<script type="text/javascript" src="' + tinymce._addVer(u) + '"' + ol + '></script>');\r
4813 \r
4814                                         if (!o.func)\r
4815                                                 done(o);\r
4816                                 } else\r
4817                                         load(o);\r
4818                         });\r
4819 \r
4820                         allDone();\r
4821                 },\r
4822 \r
4823                 // Static methods\r
4824                 'static' : {\r
4825                         _addOnLoad : function(f) {\r
4826                                 var t = this;\r
4827 \r
4828                                 t._funcs = t._funcs || [];\r
4829                                 t._funcs.push(f);\r
4830 \r
4831                                 return t._funcs.length - 1;\r
4832                         },\r
4833 \r
4834                         _onLoad : function(e, u, ix) {\r
4835                                 if (!tinymce.isIE || e.readyState == 'complete')\r
4836                                         this._funcs[ix].call(this);\r
4837                         },\r
4838 \r
4839                         loadScript : function(u, cb) {\r
4840                                 var id = tinymce.DOM.uniqueId(), e;\r
4841 \r
4842                                 function done() {\r
4843                                         Event.clear(id);\r
4844                                         tinymce.DOM.remove(id);\r
4845 \r
4846                                         if (cb) {\r
4847                                                 cb.call(document, u);\r
4848                                                 cb = 0;\r
4849                                         }\r
4850                                 };\r
4851 \r
4852                                 if (tinymce.isIE) {\r
4853 /*                                      Event.add(e, 'readystatechange', function(e) {\r
4854                                                 if (e.target && e.target.readyState == 'complete')\r
4855                                                         done();\r
4856                                         });*/\r
4857 \r
4858                                         tinymce.util.XHR.send({\r
4859                                                 url : tinymce._addVer(u),\r
4860                                                 async : false,\r
4861                                                 success : function(co) {\r
4862                                                         window.execScript(co);\r
4863                                                         done();\r
4864                                                 }\r
4865                                         });\r
4866                                 } else {\r
4867                                         e = tinymce.DOM.create('script', {id : id, type : 'text/javascript', src : tinymce._addVer(u)});\r
4868                                         Event.add(e, 'load', done);\r
4869 \r
4870                                         // Check for head or body\r
4871                                         (document.getElementsByTagName('head')[0] || document.body).appendChild(e);\r
4872                                 }\r
4873                         }\r
4874                 }\r
4875 \r
4876                 });\r
4877 \r
4878         // Global script loader\r
4879         tinymce.ScriptLoader = new tinymce.dom.ScriptLoader();\r
4880 })();\r
4881 \r
4882 /* file:jscripts/tiny_mce/classes/ui/Control.js */\r
4883 \r
4884 (function() {\r
4885         // Shorten class names\r
4886         var DOM = tinymce.DOM, is = tinymce.is;\r
4887 \r
4888         tinymce.create('tinymce.ui.Control', {\r
4889                 Control : function(id, s) {\r
4890                         this.id = id;\r
4891                         this.settings = s = s || {};\r
4892                         this.rendered = false;\r
4893                         this.onRender = new tinymce.util.Dispatcher(this);\r
4894                         this.classPrefix = '';\r
4895                         this.scope = s.scope || this;\r
4896                         this.disabled = 0;\r
4897                         this.active = 0;\r
4898                 },\r
4899 \r
4900                 setDisabled : function(s) {\r
4901                         var e;\r
4902 \r
4903                         if (s != this.disabled) {\r
4904                                 e = DOM.get(this.id);\r
4905 \r
4906                                 // Add accessibility title for unavailable actions\r
4907                                 if (e && this.settings.unavailable_prefix) {\r
4908                                         if (s) {\r
4909                                                 this.prevTitle = e.title;\r
4910                                                 e.title = this.settings.unavailable_prefix + ": " + e.title;\r
4911                                         } else\r
4912                                                 e.title = this.prevTitle;\r
4913                                 }\r
4914 \r
4915                                 this.setState('Disabled', s);\r
4916                                 this.setState('Enabled', !s);\r
4917                                 this.disabled = s;\r
4918                         }\r
4919                 },\r
4920 \r
4921                 isDisabled : function() {\r
4922                         return this.disabled;\r
4923                 },\r
4924 \r
4925                 setActive : function(s) {\r
4926                         if (s != this.active) {\r
4927                                 this.setState('Active', s);\r
4928                                 this.active = s;\r
4929                         }\r
4930                 },\r
4931 \r
4932                 isActive : function() {\r
4933                         return this.active;\r
4934                 },\r
4935 \r
4936                 setState : function(c, s) {\r
4937                         var n = DOM.get(this.id);\r
4938 \r
4939                         c = this.classPrefix + c;\r
4940 \r
4941                         if (s)\r
4942                                 DOM.addClass(n, c);\r
4943                         else\r
4944                                 DOM.removeClass(n, c);\r
4945                 },\r
4946 \r
4947                 isRendered : function() {\r
4948                         return this.rendered;\r
4949                 },\r
4950 \r
4951                 renderHTML : function() {\r
4952                 },\r
4953 \r
4954                 renderTo : function(n) {\r
4955                         DOM.setHTML(n, this.renderHTML());\r
4956                 },\r
4957 \r
4958                 postRender : function() {\r
4959                         var t = this, b;\r
4960 \r
4961                         // Set pending states\r
4962                         if (is(t.disabled)) {\r
4963                                 b = t.disabled;\r
4964                                 t.disabled = -1;\r
4965                                 t.setDisabled(b);\r
4966                         }\r
4967 \r
4968                         if (is(t.active)) {\r
4969                                 b = t.active;\r
4970                                 t.active = -1;\r
4971                                 t.setActive(b);\r
4972                         }\r
4973                 },\r
4974 \r
4975                 remove : function() {\r
4976                         DOM.remove(this.id);\r
4977                         this.destroy();\r
4978                 },\r
4979 \r
4980                 destroy : function() {\r
4981                         tinymce.dom.Event.clear(this.id);\r
4982                 }\r
4983 \r
4984                 });\r
4985 })();\r
4986 /* file:jscripts/tiny_mce/classes/ui/Container.js */\r
4987 \r
4988 tinymce.create('tinymce.ui.Container:tinymce.ui.Control', {\r
4989         Container : function(id, s) {\r
4990                 this.parent(id, s);\r
4991                 this.controls = [];\r
4992                 this.lookup = {};\r
4993         },\r
4994 \r
4995         add : function(c) {\r
4996                 this.lookup[c.id] = c;\r
4997                 this.controls.push(c);\r
4998 \r
4999                 return c;\r
5000         },\r
5001 \r
5002         get : function(n) {\r
5003                 return this.lookup[n];\r
5004         }\r
5005 \r
5006         });\r
5007 \r
5008 \r
5009 /* file:jscripts/tiny_mce/classes/ui/Separator.js */\r
5010 \r
5011 tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {\r
5012         Separator : function(id, s) {\r
5013                 this.parent(id, s);\r
5014                 this.classPrefix = 'mceSeparator';\r
5015         },\r
5016 \r
5017         renderHTML : function() {\r
5018                 return tinymce.DOM.createHTML('span', {'class' : this.classPrefix});\r
5019         }\r
5020 \r
5021         });\r
5022 \r
5023 /* file:jscripts/tiny_mce/classes/ui/MenuItem.js */\r
5024 \r
5025 (function() {\r
5026         var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk;\r
5027 \r
5028         tinymce.create('tinymce.ui.MenuItem:tinymce.ui.Control', {\r
5029                 MenuItem : function(id, s) {\r
5030                         this.parent(id, s);\r
5031                         this.classPrefix = 'mceMenuItem';\r
5032                 },\r
5033 \r
5034                 setSelected : function(s) {\r
5035                         this.setState('Selected', s);\r
5036                         this.selected = s;\r
5037                 },\r
5038 \r
5039                 isSelected : function() {\r
5040                         return this.selected;\r
5041                 },\r
5042 \r
5043                 postRender : function() {\r
5044                         var t = this;\r
5045                         \r
5046                         t.parent();\r
5047 \r
5048                         // Set pending state\r
5049                         if (is(t.selected))\r
5050                                 t.setSelected(t.selected);\r
5051                 }\r
5052 \r
5053                 });\r
5054 })();\r
5055 \r
5056 /* file:jscripts/tiny_mce/classes/ui/Menu.js */\r
5057 \r
5058 (function() {\r
5059         var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk;\r
5060 \r
5061         tinymce.create('tinymce.ui.Menu:tinymce.ui.MenuItem', {\r
5062                 Menu : function(id, s) {\r
5063                         var t = this;\r
5064 \r
5065                         t.parent(id, s);\r
5066                         t.items = {};\r
5067                         t.collapsed = false;\r
5068                         t.menuCount = 0;\r
5069                         t.onAddItem = new tinymce.util.Dispatcher(this);\r
5070                 },\r
5071 \r
5072                 expand : function(d) {\r
5073                         var t = this;\r
5074 \r
5075                         if (d) {\r
5076                                 walk(t, function(o) {\r
5077                                         if (o.expand)\r
5078                                                 o.expand();\r
5079                                 }, 'items', t);\r
5080                         }\r
5081 \r
5082                         t.collapsed = false;\r
5083                 },\r
5084 \r
5085                 collapse : function(d) {\r
5086                         var t = this;\r
5087 \r
5088                         if (d) {\r
5089                                 walk(t, function(o) {\r
5090                                         if (o.collapse)\r
5091                                                 o.collapse();\r
5092                                 }, 'items', t);\r
5093                         }\r
5094 \r
5095                         t.collapsed = true;\r
5096                 },\r
5097 \r
5098                 isCollapsed : function() {\r
5099                         return this.collapsed;\r
5100                 },\r
5101 \r
5102                 add : function(o) {\r
5103                         if (!o.settings)\r
5104                                 o = new tinymce.ui.MenuItem(o.id || DOM.uniqueId(), o);\r
5105 \r
5106                         this.onAddItem.dispatch(this, o);\r
5107 \r
5108                         return this.items[o.id] = o;\r
5109                 },\r
5110 \r
5111                 addSeparator : function() {\r
5112                         return this.add({separator : true});\r
5113                 },\r
5114 \r
5115                 addMenu : function(o) {\r
5116                         if (!o.collapse)\r
5117                                 o = this.createMenu(o);\r
5118 \r
5119                         this.menuCount++;\r
5120 \r
5121                         return this.add(o);\r
5122                 },\r
5123 \r
5124                 hasMenus : function() {\r
5125                         return this.menuCount !== 0;\r
5126                 },\r
5127 \r
5128                 remove : function(o) {\r
5129                         delete this.items[o.id];\r
5130                 },\r
5131 \r
5132                 removeAll : function() {\r
5133                         var t = this;\r
5134 \r
5135                         walk(t, function(o) {\r
5136                                 if (o.removeAll)\r
5137                                         o.removeAll();\r
5138                                 else\r
5139                                         o.remove();\r
5140 \r
5141                                 o.destroy();\r
5142                         }, 'items', t);\r
5143 \r
5144                         t.items = {};\r
5145                 },\r
5146 \r
5147                 createMenu : function(o) {\r
5148                         var m = new tinymce.ui.Menu(o.id || DOM.uniqueId(), o);\r
5149 \r
5150                         m.onAddItem.add(this.onAddItem.dispatch, this.onAddItem);\r
5151 \r
5152                         return m;\r
5153                 }\r
5154 \r
5155                 });\r
5156 })();\r
5157 /* file:jscripts/tiny_mce/classes/ui/DropMenu.js */\r
5158 \r
5159 (function() {\r
5160         var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, Event = tinymce.dom.Event, Element = tinymce.dom.Element;\r
5161 \r
5162         tinymce.create('tinymce.ui.DropMenu:tinymce.ui.Menu', {\r
5163                 DropMenu : function(id, s) {\r
5164                         s = s || {};\r
5165                         s.container = s.container || DOM.doc.body;\r
5166                         s.offset_x = s.offset_x || 0;\r
5167                         s.offset_y = s.offset_y || 0;\r
5168                         s.vp_offset_x = s.vp_offset_x || 0;\r
5169                         s.vp_offset_y = s.vp_offset_y || 0;\r
5170 \r
5171                         if (is(s.icons) && !s.icons)\r
5172                                 s['class'] += ' mceNoIcons';\r
5173 \r
5174                         this.parent(id, s);\r
5175                         this.onShowMenu = new tinymce.util.Dispatcher(this);\r
5176                         this.onHideMenu = new tinymce.util.Dispatcher(this);\r
5177                         this.classPrefix = 'mceMenu';\r
5178                 },\r
5179 \r
5180                 createMenu : function(s) {\r
5181                         var t = this, cs = t.settings, m;\r
5182 \r
5183                         s.container = s.container || cs.container;\r
5184                         s.parent = t;\r
5185                         s.constrain = s.constrain || cs.constrain;\r
5186                         s['class'] = s['class'] || cs['class'];\r
5187                         s.vp_offset_x = s.vp_offset_x || cs.vp_offset_x;\r
5188                         s.vp_offset_y = s.vp_offset_y || cs.vp_offset_y;\r
5189                         m = new tinymce.ui.DropMenu(s.id || DOM.uniqueId(), s);\r
5190 \r
5191                         m.onAddItem.add(t.onAddItem.dispatch, t.onAddItem);\r
5192 \r
5193                         return m;\r
5194                 },\r
5195 \r
5196                 update : function() {\r
5197                         var t = this, s = t.settings, tb = DOM.get('menu_' + t.id + '_tbl'), co = DOM.get('menu_' + t.id + '_co'), tw, th;\r
5198 \r
5199                         tw = s.max_width ? Math.min(tb.clientWidth, s.max_width) : tb.clientWidth;\r
5200                         th = s.max_height ? Math.min(tb.clientHeight, s.max_height) : tb.clientHeight;\r
5201 \r
5202                         if (!DOM.boxModel)\r
5203                                 t.element.setStyles({width : tw + 2, height : th + 2});\r
5204                         else\r
5205                                 t.element.setStyles({width : tw, height : th});\r
5206 \r
5207                         if (s.max_width)\r
5208                                 DOM.setStyle(co, 'width', tw);\r
5209 \r
5210                         if (s.max_height) {\r
5211                                 DOM.setStyle(co, 'height', th);\r
5212 \r
5213                                 if (tb.clientHeight < s.max_height)\r
5214                                         DOM.setStyle(co, 'overflow', 'hidden');\r
5215                         }\r
5216                 },\r
5217 \r
5218                 showMenu : function(x, y, px) {\r
5219                         var t = this, s = t.settings, co, vp = DOM.getViewPort(), w, h, mx, my, ot = 2, dm, tb, cp = t.classPrefix;\r
5220 \r
5221                         t.collapse(1);\r
5222 \r
5223                         if (t.isMenuVisible)\r
5224                                 return;\r
5225 \r
5226                         if (!t.rendered) {\r
5227                                 co = DOM.add(t.settings.container, t.renderNode());\r
5228 \r
5229                                 each(t.items, function(o) {\r
5230                                         o.postRender();\r
5231                                 });\r
5232 \r
5233                                 t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container});\r
5234                         } else\r
5235                                 co = DOM.get('menu_' + t.id);\r
5236 \r
5237                         // Move layer out of sight unless it's Opera since it scrolls to top of page due to an bug\r
5238                         if (!tinymce.isOpera)\r
5239                                 DOM.setStyles(co, {left : -0xFFFF , top : -0xFFFF});\r
5240 \r
5241                         DOM.show(co);\r
5242                         t.update();\r
5243 \r
5244                         x += s.offset_x || 0;\r
5245                         y += s.offset_y || 0;\r
5246                         vp.w -= 4;\r
5247                         vp.h -= 4;\r
5248 \r
5249                         // Move inside viewport if not submenu\r
5250                         if (s.constrain) {\r
5251                                 w = co.clientWidth - ot;\r
5252                                 h = co.clientHeight - ot;\r
5253                                 mx = vp.x + vp.w;\r
5254                                 my = vp.y + vp.h;\r
5255 \r
5256                                 if ((x + s.vp_offset_x + w) > mx)\r
5257                                         x = px ? px - w : Math.max(0, (mx - s.vp_offset_x) - w);\r
5258 \r
5259                                 if ((y + s.vp_offset_y + h) > my)\r
5260                                         y = Math.max(0, (my - s.vp_offset_y) - h);\r
5261                         }\r
5262 \r
5263                         DOM.setStyles(co, {left : x , top : y});\r
5264                         t.element.update();\r
5265 \r
5266                         t.isMenuVisible = 1;\r
5267                         t.mouseClickFunc = Event.add(co, 'click', function(e) {\r
5268                                 var m;\r
5269 \r
5270                                 e = e.target;\r
5271 \r
5272                                 if (e && (e = DOM.getParent(e, 'TR')) && !DOM.hasClass(e, cp + 'ItemSub')) {\r
5273                                         m = t.items[e.id];\r
5274 \r
5275                                         if (m.isDisabled())\r
5276                                                 return;\r
5277 \r
5278                                         dm = t;\r
5279 \r
5280                                         while (dm) {\r
5281                                                 if (dm.hideMenu)\r
5282                                                         dm.hideMenu();\r
5283 \r
5284                                                 dm = dm.settings.parent;\r
5285                                         }\r
5286 \r
5287                                         if (m.settings.onclick)\r
5288                                                 m.settings.onclick(e);\r
5289 \r
5290                                         return Event.cancel(e); // Cancel to fix onbeforeunload problem\r
5291                                 }\r
5292                         });\r
5293 \r
5294                         if (t.hasMenus()) {\r
5295                                 t.mouseOverFunc = Event.add(co, 'mouseover', function(e) {\r
5296                                         var m, r, mi;\r
5297 \r
5298                                         e = e.target;\r
5299                                         if (e && (e = DOM.getParent(e, 'TR'))) {\r
5300                                                 m = t.items[e.id];\r
5301 \r
5302                                                 if (t.lastMenu)\r
5303                                                         t.lastMenu.collapse(1);\r
5304 \r
5305                                                 if (m.isDisabled())\r
5306                                                         return;\r
5307 \r
5308                                                 if (e && DOM.hasClass(e, cp + 'ItemSub')) {\r
5309                                                         //p = DOM.getPos(s.container);\r
5310                                                         r = DOM.getRect(e);\r
5311                                                         m.showMenu((r.x + r.w - ot), r.y - ot, r.x);\r
5312                                                         t.lastMenu = m;\r
5313                                                         DOM.addClass(DOM.get(m.id).firstChild, cp + 'ItemActive');\r
5314                                                 }\r
5315                                         }\r
5316                                 });\r
5317                         }\r
5318 \r
5319                         t.onShowMenu.dispatch(t);\r
5320 \r
5321                         if (s.keyboard_focus) {\r
5322                                 Event.add(co, 'keydown', t._keyHandler, t);\r
5323                                 DOM.select('a', 'menu_' + t.id)[0].focus(); // Select first link\r
5324                                 t._focusIdx = 0;\r
5325                         }\r
5326                 },\r
5327 \r
5328                 hideMenu : function(c) {\r
5329                         var t = this, co = DOM.get('menu_' + t.id), e;\r
5330 \r
5331                         if (!t.isMenuVisible)\r
5332                                 return;\r
5333 \r
5334                         Event.remove(co, 'mouseover', t.mouseOverFunc);\r
5335                         Event.remove(co, 'click', t.mouseClickFunc);\r
5336                         Event.remove(co, 'keydown', t._keyHandler);\r
5337                         DOM.hide(co);\r
5338                         t.isMenuVisible = 0;\r
5339 \r
5340                         if (!c)\r
5341                                 t.collapse(1);\r
5342 \r
5343                         if (t.element)\r
5344                                 t.element.hide();\r
5345 \r
5346                         if (e = DOM.get(t.id))\r
5347                                 DOM.removeClass(e.firstChild, t.classPrefix + 'ItemActive');\r
5348 \r
5349                         t.onHideMenu.dispatch(t);\r
5350                 },\r
5351 \r
5352                 add : function(o) {\r
5353                         var t = this, co;\r
5354 \r
5355                         o = t.parent(o);\r
5356 \r
5357                         if (t.isRendered && (co = DOM.get('menu_' + t.id)))\r
5358                                 t._add(DOM.select('tbody', co)[0], o);\r
5359 \r
5360                         return o;\r
5361                 },\r
5362 \r
5363                 collapse : function(d) {\r
5364                         this.parent(d);\r
5365                         this.hideMenu(1);\r
5366                 },\r
5367 \r
5368                 remove : function(o) {\r
5369                         DOM.remove(o.id);\r
5370                         this.destroy();\r
5371 \r
5372                         return this.parent(o);\r
5373                 },\r
5374 \r
5375                 destroy : function() {\r
5376                         var t = this, co = DOM.get('menu_' + t.id);\r
5377 \r
5378                         Event.remove(co, 'mouseover', t.mouseOverFunc);\r
5379                         Event.remove(co, 'click', t.mouseClickFunc);\r
5380 \r
5381                         if (t.element)\r
5382                                 t.element.remove();\r
5383 \r
5384                         DOM.remove(co);\r
5385                 },\r
5386 \r
5387                 renderNode : function() {\r
5388                         var t = this, s = t.settings, n, tb, co, w;\r
5389 \r
5390                         w = DOM.create('div', {id : 'menu_' + t.id, 'class' : s['class'], 'style' : 'position:absolute;left:0;top:0;z-index:200000'});\r
5391                         co = DOM.add(w, 'div', {id : 'menu_' + t.id + '_co', 'class' : t.classPrefix + (s['class'] ? ' ' + s['class'] : '')});\r
5392                         t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container});\r
5393 \r
5394                         if (s.menu_line)\r
5395                                 DOM.add(co, 'span', {'class' : t.classPrefix + 'Line'});\r
5396 \r
5397 //                      n = DOM.add(co, 'div', {id : 'menu_' + t.id + '_co', 'class' : 'mceMenuContainer'});\r
5398                         n = DOM.add(co, 'table', {id : 'menu_' + t.id + '_tbl', border : 0, cellPadding : 0, cellSpacing : 0});\r
5399                         tb = DOM.add(n, 'tbody');\r
5400 \r
5401                         each(t.items, function(o) {\r
5402                                 t._add(tb, o);\r
5403                         });\r
5404 \r
5405                         t.rendered = true;\r
5406 \r
5407                         return w;\r
5408                 },\r
5409 \r
5410                 // Internal functions\r
5411 \r
5412                 _keyHandler : function(e) {\r
5413                         var t = this, kc = e.keyCode;\r
5414 \r
5415                         function focus(d) {\r
5416                                 var i = t._focusIdx + d, e = DOM.select('a', 'menu_' + t.id)[i];\r
5417 \r
5418                                 if (e) {\r
5419                                         t._focusIdx = i;\r
5420                                         e.focus();\r
5421                                 }\r
5422                         };\r
5423 \r
5424                         switch (kc) {\r
5425                                 case 38:\r
5426                                         focus(-1); // Select first link\r
5427                                         return;\r
5428 \r
5429                                 case 40:\r
5430                                         focus(1);\r
5431                                         return;\r
5432 \r
5433                                 case 13:\r
5434                                         return;\r
5435 \r
5436                                 case 27:\r
5437                                         return this.hideMenu();\r
5438                         }\r
5439                 },\r
5440 \r
5441                 _add : function(tb, o) {\r
5442                         var n, s = o.settings, a, ro, it, cp = this.classPrefix, ic;\r
5443 \r
5444                         if (s.separator) {\r
5445                                 ro = DOM.add(tb, 'tr', {id : o.id, 'class' : cp + 'ItemSeparator'});\r
5446                                 DOM.add(ro, 'td', {'class' : cp + 'ItemSeparator'});\r
5447 \r
5448                                 if (n = ro.previousSibling)\r
5449                                         DOM.addClass(n, 'mceLast');\r
5450 \r
5451                                 return;\r
5452                         }\r
5453 \r
5454                         n = ro = DOM.add(tb, 'tr', {id : o.id, 'class' : cp + 'Item ' + cp + 'ItemEnabled'});\r
5455                         n = it = DOM.add(n, 'td');\r
5456                         n = a = DOM.add(n, 'a', {href : 'javascript:;', onclick : "return false;", onmousedown : 'return false;'});\r
5457 \r
5458                         DOM.addClass(it, s['class']);\r
5459 //                      n = DOM.add(n, 'span', {'class' : 'item'});\r
5460 \r
5461                         ic = DOM.add(n, 'span', {'class' : 'mceIcon' + (s.icon ? ' mce_' + s.icon : '')});\r
5462 \r
5463                         if (s.icon_src)\r
5464                                 DOM.add(ic, 'img', {src : s.icon_src});\r
5465 \r
5466                         n = DOM.add(n, s.element || 'span', {'class' : 'mceText', title : o.settings.title}, o.settings.title);\r
5467 \r
5468                         if (o.settings.style)\r
5469                                 DOM.setAttrib(n, 'style', o.settings.style);\r
5470 \r
5471                         if (tb.childNodes.length == 1)\r
5472                                 DOM.addClass(ro, 'mceFirst');\r
5473 \r
5474                         if ((n = ro.previousSibling) && DOM.hasClass(n, cp + 'ItemSeparator'))\r
5475                                 DOM.addClass(ro, 'mceFirst');\r
5476 \r
5477                         if (o.collapse)\r
5478                                 DOM.addClass(ro, cp + 'ItemSub');\r
5479 \r
5480                         if (n = ro.previousSibling)\r
5481                                 DOM.removeClass(n, 'mceLast');\r
5482 \r
5483                         DOM.addClass(ro, 'mceLast');\r
5484                 }\r
5485 \r
5486                 });\r
5487 })();\r
5488 /* file:jscripts/tiny_mce/classes/ui/Button.js */\r
5489 \r
5490 (function() {\r
5491         var DOM = tinymce.DOM;\r
5492 \r
5493         tinymce.create('tinymce.ui.Button:tinymce.ui.Control', {\r
5494                 Button : function(id, s) {\r
5495                         this.parent(id, s);\r
5496                         this.classPrefix = 'mceButton';\r
5497                 },\r
5498 \r
5499                 renderHTML : function() {\r
5500                         var cp = this.classPrefix, s = this.settings, h, l;\r
5501 \r
5502                         l = DOM.encode(s.label || '');\r
5503                         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
5504 \r
5505                         if (s.image)\r
5506                                 h += '<img class="mceIcon" src="' + s.image + '" />' + l + '</a>';\r
5507                         else\r
5508                                 h += '<span class="mceIcon ' + s['class'] + '"></span>' + (l ? '<span class="' + cp + 'Label">' + l + '</span>' : '') + '</a>';\r
5509 \r
5510                         return h;\r
5511                 },\r
5512 \r
5513                 postRender : function() {\r
5514                         var t = this, s = t.settings;\r
5515 \r
5516                         tinymce.dom.Event.add(t.id, 'click', function(e) {\r
5517                                 if (!t.isDisabled())\r
5518                                         return s.onclick.call(s.scope, e);\r
5519                         });\r
5520                 }\r
5521 \r
5522                 });\r
5523 })();\r
5524 \r
5525 /* file:jscripts/tiny_mce/classes/ui/ListBox.js */\r
5526 \r
5527 (function() {\r
5528         var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher;\r
5529 \r
5530         tinymce.create('tinymce.ui.ListBox:tinymce.ui.Control', {\r
5531                 ListBox : function(id, s) {\r
5532                         var t = this;\r
5533 \r
5534                         t.parent(id, s);\r
5535                         t.items = [];\r
5536                         t.onChange = new Dispatcher(t);\r
5537                         t.onPostRender = new Dispatcher(t);\r
5538                         t.onAdd = new Dispatcher(t);\r
5539                         t.onRenderMenu = new tinymce.util.Dispatcher(this);\r
5540                         t.classPrefix = 'mceListBox';\r
5541                 },\r
5542 \r
5543                 select : function(va) {\r
5544                         var t = this, fv, f;\r
5545 \r
5546                         if (va == undefined)\r
5547                                 return t.selectByIndex(-1);\r
5548 \r
5549                         // Is string or number make function selector\r
5550                         if (va && va.call)\r
5551                                 f = va;\r
5552                         else {\r
5553                                 f = function(v) {\r
5554                                         return v == va;\r
5555                                 };\r
5556                         }\r
5557 \r
5558                         // Do we need to do something?\r
5559                         if (va != t.selectedValue) {\r
5560                                 // Find item\r
5561                                 each(t.items, function(o, i) {\r
5562                                         if (f(o.value)) {\r
5563                                                 fv = 1;\r
5564                                                 t.selectByIndex(i);\r
5565                                                 return false;\r
5566                                         }\r
5567                                 });\r
5568 \r
5569                                 if (!fv)\r
5570                                         t.selectByIndex(-1);\r
5571                         }\r
5572                 },\r
5573 \r
5574                 selectByIndex : function(idx) {\r
5575                         var t = this, e, o;\r
5576 \r
5577                         if (idx != t.selectedIndex) {\r
5578                                 e = DOM.get(t.id + '_text');\r
5579                                 o = t.items[idx];\r
5580 \r
5581                                 if (o) {\r
5582                                         t.selectedValue = o.value;\r
5583                                         t.selectedIndex = idx;\r
5584                                         DOM.setHTML(e, DOM.encode(o.title));\r
5585                                         DOM.removeClass(e, 'mceTitle');\r
5586                                 } else {\r
5587                                         DOM.setHTML(e, DOM.encode(t.settings.title));\r
5588                                         DOM.addClass(e, 'mceTitle');\r
5589                                         t.selectedValue = t.selectedIndex = null;\r
5590                                 }\r
5591 \r
5592                                 e = 0;\r
5593                         } else\r
5594                                 t.selectedValue = t.selectedIndex = null;\r
5595                 },\r
5596 \r
5597                 add : function(n, v, o) {\r
5598                         var t = this;\r
5599 \r
5600                         o = o || {};\r
5601                         o = tinymce.extend(o, {\r
5602                                 title : n,\r
5603                                 value : v\r
5604                         });\r
5605 \r
5606                         t.items.push(o);\r
5607                         t.onAdd.dispatch(t, o);\r
5608                 },\r
5609 \r
5610                 getLength : function() {\r
5611                         return this.items.length;\r
5612                 },\r
5613 \r
5614                 renderHTML : function() {\r
5615                         var h = '', t = this, s = t.settings, cp = t.classPrefix;\r
5616 \r
5617                         h = '<table id="' + t.id + '" cellpadding="0" cellspacing="0" class="' + cp + ' ' + cp + 'Enabled' + (s['class'] ? (' ' + s['class']) : '') + '"><tbody><tr>';\r
5618                         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
5619                         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
5620                         h += '</tr></tbody></table>';\r
5621 \r
5622                         return h;\r
5623                 },\r
5624 \r
5625                 showMenu : function() {\r
5626                         var t = this, p1, p2, e = DOM.get(this.id), m;\r
5627 \r
5628                         if (t.isDisabled() || t.items.length == 0)\r
5629                                 return;\r
5630 \r
5631                         if (t.menu && t.menu.isMenuVisible)\r
5632                                 return t.hideMenu();\r
5633 \r
5634                         if (!t.isMenuRendered) {\r
5635                                 t.renderMenu();\r
5636                                 t.isMenuRendered = true;\r
5637                         }\r
5638 \r
5639                         p1 = DOM.getPos(this.settings.menu_container);\r
5640                         p2 = DOM.getPos(e);\r
5641 \r
5642                         m = t.menu;\r
5643                         m.settings.offset_x = p2.x;\r
5644                         m.settings.offset_y = p2.y;\r
5645                         m.settings.keyboard_focus = !tinymce.isOpera; // Opera is buggy when it comes to auto focus\r
5646 \r
5647                         // Select in menu\r
5648                         if (t.oldID)\r
5649                                 m.items[t.oldID].setSelected(0);\r
5650 \r
5651                         each(t.items, function(o) {\r
5652                                 if (o.value === t.selectedValue) {\r
5653                                         m.items[o.id].setSelected(1);\r
5654                                         t.oldID = o.id;\r
5655                                 }\r
5656                         });\r
5657 \r
5658                         m.showMenu(0, e.clientHeight);\r
5659 \r
5660                         Event.add(DOM.doc, 'mousedown', t.hideMenu, t);\r
5661                         DOM.addClass(t.id, t.classPrefix + 'Selected');\r
5662 \r
5663                         //DOM.get(t.id + '_text').focus();\r
5664                 },\r
5665 \r
5666                 hideMenu : function(e) {\r
5667                         var t = this;\r
5668 \r
5669                         // Prevent double toogles by canceling the mouse click event to the button\r
5670                         if (e && e.type == "mousedown" && (e.target.id == t.id + '_text' || e.target.id == t.id + '_open'))\r
5671                                 return;\r
5672 \r
5673                         if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceMenu');})) {\r
5674                                 DOM.removeClass(t.id, t.classPrefix + 'Selected');\r
5675                                 Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);\r
5676 \r
5677                                 if (t.menu)\r
5678                                         t.menu.hideMenu();\r
5679                         }\r
5680                 },\r
5681 \r
5682                 renderMenu : function() {\r
5683                         var t = this, m;\r
5684 \r
5685                         m = t.settings.control_manager.createDropMenu(t.id + '_menu', {\r
5686                                 menu_line : 1,\r
5687                                 'class' : t.classPrefix + 'Menu mceNoIcons',\r
5688                                 max_width : 150,\r
5689                                 max_height : 150\r
5690                         });\r
5691 \r
5692                         m.onHideMenu.add(t.hideMenu, t);\r
5693 \r
5694                         m.add({\r
5695                                 title : t.settings.title,\r
5696                                 'class' : 'mceMenuItemTitle',\r
5697                                 onclick : function() {\r
5698                                         if (t.settings.onselect('') !== false)\r
5699                                                 t.select(''); // Must be runned after\r
5700                                 }\r
5701                         });\r
5702 \r
5703                         each(t.items, function(o) {\r
5704                                 o.id = DOM.uniqueId();\r
5705                                 o.onclick = function() {\r
5706                                         if (t.settings.onselect(o.value) !== false)\r
5707                                                 t.select(o.value); // Must be runned after\r
5708                                 };\r
5709 \r
5710                                 m.add(o);\r
5711                         });\r
5712 \r
5713                         t.onRenderMenu.dispatch(t, m);\r
5714                         t.menu = m;\r
5715                 },\r
5716 \r
5717                 postRender : function() {\r
5718                         var t = this, cp = t.classPrefix;\r
5719 \r
5720                         Event.add(t.id, 'click', t.showMenu, t);\r
5721                         Event.add(t.id + '_text', 'focus', function(e) {\r
5722                                 if (!t._focused) {\r
5723                                         t.keyDownHandler = Event.add(t.id + '_text', 'keydown', function(e) {\r
5724                                                 var idx = -1, v, kc = e.keyCode;\r
5725 \r
5726                                                 // Find current index\r
5727                                                 each(t.items, function(v, i) {\r
5728                                                         if (t.selectedValue == v.value)\r
5729                                                                 idx = i;\r
5730                                                 });\r
5731 \r
5732                                                 // Move up/down\r
5733                                                 if (kc == 38)\r
5734                                                         v = t.items[idx - 1];\r
5735                                                 else if (kc == 40)\r
5736                                                         v = t.items[idx + 1];\r
5737                                                 else if (kc == 13) {\r
5738                                                         // Fake select on enter\r
5739                                                         v = t.selectedValue;\r
5740                                                         t.selectedValue = null; // Needs to be null to fake change\r
5741                                                         t.settings.onselect(v);\r
5742                                                         return Event.cancel(e);\r
5743                                                 }\r
5744 \r
5745                                                 if (v) {\r
5746                                                         t.hideMenu();\r
5747                                                         t.select(v.value);\r
5748                                                 }\r
5749                                         });\r
5750                                 }\r
5751 \r
5752                                 t._focused = 1;\r
5753                         });\r
5754                         Event.add(t.id + '_text', 'blur', function() {Event.remove(t.id + '_text', 'keydown', t.keyDownHandler); t._focused = 0;});\r
5755 \r
5756                         // Old IE doesn't have hover on all elements\r
5757                         if (tinymce.isIE6 || !DOM.boxModel) {\r
5758                                 Event.add(t.id, 'mouseover', function() {\r
5759                                         if (!DOM.hasClass(t.id, cp + 'Disabled'))\r
5760                                                 DOM.addClass(t.id, cp + 'Hover');\r
5761                                 });\r
5762 \r
5763                                 Event.add(t.id, 'mouseout', function() {\r
5764                                         if (!DOM.hasClass(t.id, cp + 'Disabled'))\r
5765                                                 DOM.removeClass(t.id, cp + 'Hover');\r
5766                                 });\r
5767                         }\r
5768 \r
5769                         t.onPostRender.dispatch(t, DOM.get(t.id));\r
5770                 },\r
5771 \r
5772                 destroy : function() {\r
5773                         this.parent();\r
5774 \r
5775                         Event.clear(this.id + '_text');\r
5776                 }\r
5777 \r
5778                 });\r
5779 })();\r
5780 /* file:jscripts/tiny_mce/classes/ui/NativeListBox.js */\r
5781 \r
5782 (function() {\r
5783         var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher;\r
5784 \r
5785         tinymce.create('tinymce.ui.NativeListBox:tinymce.ui.ListBox', {\r
5786                 NativeListBox : function(id, s) {\r
5787                         this.parent(id, s);\r
5788                         this.classPrefix = 'mceNativeListBox';\r
5789                 },\r
5790 \r
5791                 setDisabled : function(s) {\r
5792                         DOM.get(this.id).disabled = s;\r
5793                 },\r
5794 \r
5795                 isDisabled : function() {\r
5796                         return DOM.get(this.id).disabled;\r
5797                 },\r
5798 \r
5799                 select : function(va) {\r
5800                         var t = this, fv, f;\r
5801 \r
5802                         if (va == undefined)\r
5803                                 return t.selectByIndex(-1);\r
5804 \r
5805                         // Is string or number make function selector\r
5806                         if (va && va.call)\r
5807                                 f = va;\r
5808                         else {\r
5809                                 f = function(v) {\r
5810                                         return v == va;\r
5811                                 };\r
5812                         }\r
5813 \r
5814                         // Do we need to do something?\r
5815                         if (va != t.selectedValue) {\r
5816                                 // Find item\r
5817                                 each(t.items, function(o, i) {\r
5818                                         if (f(o.value)) {\r
5819                                                 fv = 1;\r
5820                                                 t.selectByIndex(i);\r
5821                                                 return false;\r
5822                                         }\r
5823                                 });\r
5824 \r
5825                                 if (!fv)\r
5826                                         t.selectByIndex(-1);\r
5827                         }\r
5828                 },\r
5829 \r
5830                 selectByIndex : function(idx) {\r
5831                         DOM.get(this.id).selectedIndex = idx + 1;\r
5832                         this.selectedValue = this.items[idx] ? this.items[idx].value : null;\r
5833                 },\r
5834 \r
5835                 add : function(n, v, a) {\r
5836                         var o, t = this;\r
5837 \r
5838                         a = a || {};\r
5839                         a.value = v;\r
5840 \r
5841                         if (t.isRendered())\r
5842                                 DOM.add(DOM.get(this.id), 'option', a, n);\r
5843 \r
5844                         o = {\r
5845                                 title : n,\r
5846                                 value : v,\r
5847                                 attribs : a\r
5848                         };\r
5849 \r
5850                         t.items.push(o);\r
5851                         t.onAdd.dispatch(t, o);\r
5852                 },\r
5853 \r
5854                 getLength : function() {\r
5855                         return DOM.get(this.id).options.length - 1;\r
5856                 },\r
5857 \r
5858                 renderHTML : function() {\r
5859                         var h, t = this;\r
5860 \r
5861                         h = DOM.createHTML('option', {value : ''}, '-- ' + t.settings.title + ' --');\r
5862 \r
5863                         each(t.items, function(it) {\r
5864                                 h += DOM.createHTML('option', {value : it.value}, it.title);\r
5865                         });\r
5866 \r
5867                         h = DOM.createHTML('select', {id : t.id, 'class' : 'mceNativeListBox'}, h);\r
5868 \r
5869                         return h;\r
5870                 },\r
5871 \r
5872                 postRender : function() {\r
5873                         var t = this, ch;\r
5874 \r
5875                         t.rendered = true;\r
5876 \r
5877                         function onChange(e) {\r
5878                                 var v = t.items[e.target.selectedIndex - 1];\r
5879 \r
5880                                 if (v && (v = v.value)) {\r
5881                                         t.onChange.dispatch(t, v);\r
5882 \r
5883                                         if (t.settings.onselect)\r
5884                                                 t.settings.onselect(v);\r
5885                                 }\r
5886                         };\r
5887 \r
5888                         Event.add(t.id, 'change', onChange);\r
5889 \r
5890                         // Accessibility keyhandler\r
5891                         Event.add(t.id, 'keydown', function(e) {\r
5892                                 var bf;\r
5893 \r
5894                                 Event.remove(t.id, 'change', ch);\r
5895 \r
5896                                 bf = Event.add(t.id, 'blur', function() {\r
5897                                         Event.add(t.id, 'change', onChange);\r
5898                                         Event.remove(t.id, 'blur', bf);\r
5899                                 });\r
5900 \r
5901                                 if (e.keyCode == 13 || e.keyCode == 32) {\r
5902                                         onChange(e);\r
5903                                         return Event.cancel(e);\r
5904                                 }\r
5905                         });\r
5906 \r
5907                         t.onPostRender.dispatch(t, DOM.get(t.id));\r
5908                 }\r
5909 \r
5910                 });\r
5911 })();\r
5912 /* file:jscripts/tiny_mce/classes/ui/MenuButton.js */\r
5913 \r
5914 (function() {\r
5915         var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each;\r
5916 \r
5917         tinymce.create('tinymce.ui.MenuButton:tinymce.ui.Button', {\r
5918                 MenuButton : function(id, s) {\r
5919                         this.parent(id, s);\r
5920                         this.onRenderMenu = new tinymce.util.Dispatcher(this);\r
5921                         s.menu_container = s.menu_container || DOM.doc.body;\r
5922                 },\r
5923 \r
5924                 showMenu : function() {\r
5925                         var t = this, p1, p2, e = DOM.get(t.id), m;\r
5926 \r
5927                         if (t.isDisabled())\r
5928                                 return;\r
5929 \r
5930                         if (!t.isMenuRendered) {\r
5931                                 t.renderMenu();\r
5932                                 t.isMenuRendered = true;\r
5933                         }\r
5934 \r
5935                         if (t.isMenuVisible)\r
5936                                 return t.hideMenu();\r
5937 \r
5938                         p1 = DOM.getPos(t.settings.menu_container);\r
5939                         p2 = DOM.getPos(e);\r
5940 \r
5941                         m = t.menu;\r
5942                         m.settings.offset_x = p2.x;\r
5943                         m.settings.offset_y = p2.y;\r
5944                         m.settings.vp_offset_x = p2.x;\r
5945                         m.settings.vp_offset_y = p2.y;\r
5946                         m.settings.keyboard_focus = t._focused;\r
5947                         m.showMenu(0, e.clientHeight);\r
5948 \r
5949                         Event.add(DOM.doc, 'mousedown', t.hideMenu, t);\r
5950                         t.setState('Selected', 1);\r
5951 \r
5952                         t.isMenuVisible = 1;\r
5953                 },\r
5954 \r
5955                 renderMenu : function() {\r
5956                         var t = this, m;\r
5957 \r
5958                         m = t.settings.control_manager.createDropMenu(t.id + '_menu', {\r
5959                                 menu_line : 1,\r
5960                                 'class' : this.classPrefix + 'Menu',\r
5961                                 icons : t.settings.icons\r
5962                         });\r
5963 \r
5964                         m.onHideMenu.add(t.hideMenu, t);\r
5965 \r
5966                         t.onRenderMenu.dispatch(t, m);\r
5967                         t.menu = m;\r
5968                 },\r
5969 \r
5970                 hideMenu : function(e) {\r
5971                         var t = this;\r
5972 \r
5973                         // Prevent double toogles by canceling the mouse click event to the button\r
5974                         if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id || e.id === t.id + '_open';}))\r
5975                                 return;\r
5976 \r
5977                         if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceMenu');})) {\r
5978                                 t.setState('Selected', 0);\r
5979                                 Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);\r
5980                                 if (t.menu)\r
5981                                         t.menu.hideMenu();\r
5982                         }\r
5983 \r
5984                         t.isMenuVisible = 0;\r
5985                 },\r
5986 \r
5987                 postRender : function() {\r
5988                         var t = this, s = t.settings;\r
5989 \r
5990                         Event.add(t.id, 'click', function() {\r
5991                                 if (!t.isDisabled()) {\r
5992                                         if (s.onclick)\r
5993                                                 s.onclick(t.value);\r
5994 \r
5995                                         t.showMenu();\r
5996                                 }\r
5997                         });\r
5998                 }\r
5999 \r
6000                 });\r
6001 })();\r
6002 \r
6003 /* file:jscripts/tiny_mce/classes/ui/SplitButton.js */\r
6004 \r
6005 (function() {\r
6006         var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each;\r
6007 \r
6008         tinymce.create('tinymce.ui.SplitButton:tinymce.ui.MenuButton', {\r
6009                 SplitButton : function(id, s) {\r
6010                         this.parent(id, s);\r
6011                         this.classPrefix = 'mceSplitButton';\r
6012                 },\r
6013 \r
6014                 renderHTML : function() {\r
6015                         var h, t = this, s = t.settings, h1;\r
6016 \r
6017                         h = '<tbody><tr>';\r
6018 \r
6019                         if (s.image)\r
6020                                 h1 = DOM.createHTML('img ', {src : s.image, 'class' : 'mceAction ' + s['class']});\r
6021                         else\r
6022                                 h1 = DOM.createHTML('span', {'class' : 'mceAction ' + s['class']}, '');\r
6023 \r
6024                         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
6025         \r
6026                         h1 = DOM.createHTML('span', {'class' : 'mceOpen ' + s['class']});\r
6027                         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
6028 \r
6029                         h += '</tr></tbody>';\r
6030 \r
6031                         return DOM.createHTML('table', {id : t.id, 'class' : 'mceSplitButton mceSplitButtonEnabled ' + s['class'], cellpadding : '0', cellspacing : '0', onmousedown : 'return false;', title : s.title}, h);\r
6032                 },\r
6033 \r
6034                 postRender : function() {\r
6035                         var t = this, s = t.settings;\r
6036 \r
6037                         if (s.onclick) {\r
6038                                 Event.add(t.id + '_action', 'click', function() {\r
6039                                         if (!t.isDisabled())\r
6040                                                 s.onclick(t.value);\r
6041                                 });\r
6042                         }\r
6043 \r
6044                         Event.add(t.id + '_open', 'click', t.showMenu, t);\r
6045                         Event.add(t.id + '_open', 'focus', function() {t._focused = 1;});\r
6046                         Event.add(t.id + '_open', 'blur', function() {t._focused = 0;});\r
6047 \r
6048                         // Old IE doesn't have hover on all elements\r
6049                         if (tinymce.isIE6 || !DOM.boxModel) {\r
6050                                 Event.add(t.id, 'mouseover', function() {\r
6051                                         if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled'))\r
6052                                                 DOM.addClass(t.id, 'mceSplitButtonHover');\r
6053                                 });\r
6054 \r
6055                                 Event.add(t.id, 'mouseout', function() {\r
6056                                         if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled'))\r
6057                                                 DOM.removeClass(t.id, 'mceSplitButtonHover');\r
6058                                 });\r
6059                         }\r
6060                 },\r
6061 \r
6062                 destroy : function() {\r
6063                         this.parent();\r
6064 \r
6065                         Event.clear(this.id + '_action');\r
6066                         Event.clear(this.id + '_open');\r
6067                 }\r
6068 \r
6069                 });\r
6070 })();\r
6071 \r
6072 /* file:jscripts/tiny_mce/classes/ui/ColorSplitButton.js */\r
6073 \r
6074 (function() {\r
6075         var DOM = tinymce.DOM, Event = tinymce.dom.Event, is = tinymce.is, each = tinymce.each;\r
6076 \r
6077         tinymce.create('tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton', {\r
6078                 ColorSplitButton : function(id, s) {\r
6079                         var t = this;\r
6080 \r
6081                         t.parent(id, s);\r
6082 \r
6083                         t.settings = s = tinymce.extend({\r
6084                                 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
6085                                 grid_width : 8,\r
6086                                 default_color : '#888888'\r
6087                         }, t.settings);\r
6088 \r
6089                         t.onShowMenu = new tinymce.util.Dispatcher(t);\r
6090                         t.onHideMenu = new tinymce.util.Dispatcher(t);\r
6091 \r
6092                         t.value = s.default_color;\r
6093                 },\r
6094 \r
6095                 showMenu : function() {\r
6096                         var t = this, r, p, e, p2;\r
6097 \r
6098                         if (t.isDisabled())\r
6099                                 return;\r
6100 \r
6101                         if (!t.isMenuRendered) {\r
6102                                 t.renderMenu();\r
6103                                 t.isMenuRendered = true;\r
6104                         }\r
6105 \r
6106                         if (t.isMenuVisible)\r
6107                                 return t.hideMenu();\r
6108 \r
6109                         e = DOM.get(t.id);\r
6110                         DOM.show(t.id + '_menu');\r
6111                         DOM.addClass(e, 'mceSplitButtonSelected');\r
6112                         p2 = DOM.getPos(e);\r
6113                         DOM.setStyles(t.id + '_menu', {\r
6114                                 left : p2.x,\r
6115                                 top : p2.y + e.clientHeight,\r
6116                                 zIndex : 200000\r
6117                         });\r
6118                         e = 0;\r
6119 \r
6120                         Event.add(DOM.doc, 'mousedown', t.hideMenu, t);\r
6121 \r
6122                         if (t._focused) {\r
6123                                 t._keyHandler = Event.add(t.id + '_menu', 'keydown', function(e) {\r
6124                                         if (e.keyCode == 27)\r
6125                                                 t.hideMenu();\r
6126                                 });\r
6127 \r
6128                                 DOM.select('a', t.id + '_menu')[0].focus(); // Select first link\r
6129                         }\r
6130 \r
6131                         t.onShowMenu.dispatch(t);\r
6132 \r
6133                         t.isMenuVisible = 1;\r
6134                 },\r
6135 \r
6136                 hideMenu : function(e) {\r
6137                         var t = this;\r
6138 \r
6139                         // Prevent double toogles by canceling the mouse click event to the button\r
6140                         if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id + '_open';}))\r
6141                                 return;\r
6142 \r
6143                         if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceSplitButtonMenu');})) {\r
6144                                 DOM.removeClass(t.id, 'mceSplitButtonSelected');\r
6145                                 Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);\r
6146                                 Event.remove(t.id + '_menu', 'keydown', t._keyHandler);\r
6147                                 DOM.hide(t.id + '_menu');\r
6148                         }\r
6149 \r
6150                         t.onHideMenu.dispatch(t);\r
6151 \r
6152                         t.isMenuVisible = 0;\r
6153                 },\r
6154 \r
6155                 renderMenu : function() {\r
6156                         var t = this, m, i = 0, s = t.settings, n, tb, tr, w;\r
6157 \r
6158                         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
6159                         m = DOM.add(w, 'div', {'class' : s['class'] + ' mceSplitButtonMenu'});\r
6160                         DOM.add(m, 'span', {'class' : 'mceMenuLine'});\r
6161 \r
6162                         n = DOM.add(m, 'table', {'class' : 'mceColorSplitMenu'});\r
6163                         tb = DOM.add(n, 'tbody');\r
6164 \r
6165                         // Generate color grid\r
6166                         i = 0;\r
6167                         each(is(s.colors, 'array') ? s.colors : s.colors.split(','), function(c) {\r
6168                                 c = c.replace(/^#/, '');\r
6169 \r
6170                                 if (!i--) {\r
6171                                         tr = DOM.add(tb, 'tr');\r
6172                                         i = s.grid_width - 1;\r
6173                                 }\r
6174 \r
6175                                 n = DOM.add(tr, 'td');\r
6176 \r
6177                                 n = DOM.add(n, 'a', {\r
6178                                         href : 'javascript:;',\r
6179                                         style : {\r
6180                                                 backgroundColor : '#' + c\r
6181                                         },\r
6182                                         mce_color : '#' + c\r
6183                                 });\r
6184                         });\r
6185 \r
6186                         if (s.more_colors_func) {\r
6187                                 n = DOM.add(tb, 'tr');\r
6188                                 n = DOM.add(n, 'td', {colspan : s.grid_width, 'class' : 'mceMoreColors'});\r
6189                                 n = DOM.add(n, 'a', {id : t.id + '_more', href : 'javascript:;', onclick : 'return false;', 'class' : 'mceMoreColors'}, s.more_colors_title);\r
6190 \r
6191                                 Event.add(n, 'click', function(e) {\r
6192                                         s.more_colors_func.call(s.more_colors_scope || this);\r
6193                                         return Event.cancel(e); // Cancel to fix onbeforeunload problem\r
6194                                 });\r
6195                         }\r
6196 \r
6197                         DOM.addClass(m, 'mceColorSplitMenu');\r
6198 \r
6199                         Event.add(t.id + '_menu', 'click', function(e) {\r
6200                                 var c;\r
6201 \r
6202                                 e = e.target;\r
6203 \r
6204                                 if (e.nodeName == 'A' && (c = e.getAttribute('mce_color')))\r
6205                                         t.setColor(c);\r
6206 \r
6207                                 return Event.cancel(e); // Prevent IE auto save warning\r
6208                         });\r
6209 \r
6210                         return w;\r
6211                 },\r
6212 \r
6213                 setColor : function(c) {\r
6214                         var t = this;\r
6215 \r
6216                         DOM.setStyle(t.id + '_preview', 'backgroundColor', c);\r
6217 \r
6218                         t.value = c;\r
6219                         t.hideMenu();\r
6220                         t.settings.onselect(c);\r
6221                 },\r
6222 \r
6223                 postRender : function() {\r
6224                         var t = this, id = t.id;\r
6225 \r
6226                         t.parent();\r
6227                         DOM.add(id + '_action', 'div', {id : id + '_preview', 'class' : 'mceColorPreview'});\r
6228                         DOM.setStyle(t.id + '_preview', 'backgroundColor', t.value);\r
6229                 },\r
6230 \r
6231                 destroy : function() {\r
6232                         this.parent();\r
6233 \r
6234                         Event.clear(this.id + '_menu');\r
6235                         Event.clear(this.id + '_more');\r
6236                         DOM.remove(this.id + '_menu');\r
6237                 }\r
6238 \r
6239                 });\r
6240 })();\r
6241 \r
6242 /* file:jscripts/tiny_mce/classes/ui/Toolbar.js */\r
6243 \r
6244 tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {\r
6245         renderHTML : function() {\r
6246                 var t = this, h = '', c, co, dom = tinymce.DOM, s = t.settings, i, pr, nx, cl;\r
6247 \r
6248                 cl = t.controls;\r
6249                 for (i=0; i<cl.length; i++) {\r
6250                         // Get current control, prev control, next control and if the control is a list box or not\r
6251                         co = cl[i];\r
6252                         pr = cl[i - 1];\r
6253                         nx = cl[i + 1];\r
6254 \r
6255                         // Add toolbar start\r
6256                         if (i === 0) {\r
6257                                 c = 'mceToolbarStart';\r
6258 \r
6259                                 if (co.Button)\r
6260                                         c += ' mceToolbarStartButton';\r
6261                                 else if (co.SplitButton)\r
6262                                         c += ' mceToolbarStartSplitButton';\r
6263                                 else if (co.ListBox)\r
6264                                         c += ' mceToolbarStartListBox';\r
6265 \r
6266                                 h += dom.createHTML('td', {'class' : c}, dom.createHTML('span', null, '<!-- IE -->'));\r
6267                         }\r
6268 \r
6269                         // Add toolbar end before list box and after the previous button\r
6270                         // This is to fix the o2k7 editor skins\r
6271                         if (pr && co.ListBox) {\r
6272                                 if (pr.Button || pr.SplitButton)\r
6273                                         h += dom.createHTML('td', {'class' : 'mceToolbarEnd'}, dom.createHTML('span', null, '<!-- IE -->'));\r
6274                         }\r
6275 \r
6276                         // Render control HTML\r
6277 \r
6278                         // IE 8 quick fix, needed to propertly generate a hit area for anchors\r
6279                         if (dom.stdMode)\r
6280                                 h += '<td style="position: relative">' + co.renderHTML() + '</td>';\r
6281                         else\r
6282                                 h += '<td>' + co.renderHTML() + '</td>';\r
6283 \r
6284                         // Add toolbar start after list box and before the next button\r
6285                         // This is to fix the o2k7 editor skins\r
6286                         if (nx && co.ListBox) {\r
6287                                 if (nx.Button || nx.SplitButton)\r
6288                                         h += dom.createHTML('td', {'class' : 'mceToolbarStart'}, dom.createHTML('span', null, '<!-- IE -->'));\r
6289                         }\r
6290                 }\r
6291 \r
6292                 c = 'mceToolbarEnd';\r
6293 \r
6294                 if (co.Button)\r
6295                         c += ' mceToolbarEndButton';\r
6296                 else if (co.SplitButton)\r
6297                         c += ' mceToolbarEndSplitButton';\r
6298                 else if (co.ListBox)\r
6299                         c += ' mceToolbarEndListBox';\r
6300 \r
6301                 h += dom.createHTML('td', {'class' : c}, dom.createHTML('span', null, '<!-- IE -->'));\r
6302 \r
6303                 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
6304         }\r
6305 \r
6306         });\r
6307 \r
6308 /* file:jscripts/tiny_mce/classes/AddOnManager.js */\r
6309 \r
6310 (function() {\r
6311         var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each;\r
6312 \r
6313         tinymce.create('tinymce.AddOnManager', {\r
6314                 items : [],\r
6315                 urls : {},\r
6316                 lookup : {},\r
6317                 onAdd : new Dispatcher(this),\r
6318 \r
6319                 get : function(n) {\r
6320                         return this.lookup[n];\r
6321                 },\r
6322 \r
6323                 requireLangPack : function(n) {\r
6324                         var u, s = tinymce.EditorManager.settings;\r
6325 \r
6326                         if (s && s.language) {\r
6327                                 u = this.urls[n] + '/langs/' + s.language + '.js';\r
6328 \r
6329                                 if (!tinymce.dom.Event.domLoaded && !s.strict_mode)\r
6330                                         tinymce.ScriptLoader.load(u);\r
6331                                 else\r
6332                                         tinymce.ScriptLoader.add(u);\r
6333                         }\r
6334                 },\r
6335 \r
6336                 add : function(id, o) {\r
6337                         this.items.push(o);\r
6338                         this.lookup[id] = o;\r
6339                         this.onAdd.dispatch(this, id, o);\r
6340 \r
6341                         return o;\r
6342                 },\r
6343 \r
6344                 load : function(n, u, cb, s) {\r
6345                         var t = this;\r
6346 \r
6347                         if (t.urls[n])\r
6348                                 return;\r
6349 \r
6350                         if (u.indexOf('/') != 0 && u.indexOf('://') == -1)\r
6351                                 u = tinymce.baseURL + '/' +  u;\r
6352 \r
6353                         t.urls[n] = u.substring(0, u.lastIndexOf('/'));\r
6354                         tinymce.ScriptLoader.add(u, cb, s);\r
6355                 }\r
6356 \r
6357                 });\r
6358 \r
6359         // Create plugin and theme managers\r
6360         tinymce.PluginManager = new tinymce.AddOnManager();\r
6361         tinymce.ThemeManager = new tinymce.AddOnManager();\r
6362 }());\r
6363 /* file:jscripts/tiny_mce/classes/EditorManager.js */\r
6364 \r
6365 (function() {\r
6366         // Shorten names\r
6367         var each = tinymce.each, extend = tinymce.extend, DOM = tinymce.DOM, Event = tinymce.dom.Event, ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, explode = tinymce.explode;\r
6368 \r
6369         tinymce.create('static tinymce.EditorManager', {\r
6370                 editors : {},\r
6371                 i18n : {},\r
6372                 activeEditor : null,\r
6373 \r
6374                 preInit : function() {\r
6375                         var t = this, lo = window.location;\r
6376 \r
6377                         // Setup some URLs where the editor API is located and where the document is\r
6378                         tinymce.documentBaseURL = lo.href.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');\r
6379                         if (!/[\/\\]$/.test(tinymce.documentBaseURL))\r
6380                                 tinymce.documentBaseURL += '/';\r
6381 \r
6382                         tinymce.baseURL = new tinymce.util.URI(tinymce.documentBaseURL).toAbsolute(tinymce.baseURL);\r
6383                         tinymce.EditorManager.baseURI = new tinymce.util.URI(tinymce.baseURL);\r
6384 \r
6385                         // User already specified a document.domain value\r
6386                         if (document.domain && lo.hostname != document.domain)\r
6387                                 tinymce.relaxedDomain = document.domain;\r
6388 \r
6389                         // Setup document domain if tinymce is loaded from other domain\r
6390                         if (!tinymce.relaxedDomain && tinymce.EditorManager.baseURI.host != lo.hostname && lo.hostname)\r
6391                                 document.domain = tinymce.relaxedDomain = lo.hostname.replace(/.*\.(.+\..+)$/, '$1');\r
6392 \r
6393                         // Add before unload listener\r
6394                         // This was required since IE was leaking memory if you added and removed beforeunload listeners\r
6395                         // with attachEvent/detatchEvent so this only adds one listener and instances can the attach to the onBeforeUnload event\r
6396                         t.onBeforeUnload = new tinymce.util.Dispatcher(t);\r
6397 \r
6398                         // Must be on window or IE will leak if the editor is placed in frame or iframe\r
6399                         Event.add(window, 'beforeunload', function(e) {\r
6400                                 t.onBeforeUnload.dispatch(t, e);\r
6401                         });\r
6402                 },\r
6403 \r
6404                 init : function(s) {\r
6405                         var t = this, pl, sl = tinymce.ScriptLoader, c, e, el = [], ed;\r
6406 \r
6407                         function execCallback(se, n, s) {\r
6408                                 var f = se[n];\r
6409 \r
6410                                 if (!f)\r
6411                                         return;\r
6412 \r
6413                                 if (tinymce.is(f, 'string')) {\r
6414                                         s = f.replace(/\.\w+$/, '');\r
6415                                         s = s ? tinymce.resolve(s) : 0;\r
6416                                         f = tinymce.resolve(f);\r
6417                                 }\r
6418 \r
6419                                 return f.apply(s || this, Array.prototype.slice.call(arguments, 2));\r
6420                         };\r
6421 \r
6422                         s = extend({\r
6423                                 theme : "simple",\r
6424                                 language : "en",\r
6425                                 strict_loading_mode : document.contentType == 'application/xhtml+xml'\r
6426                         }, s);\r
6427 \r
6428                         t.settings = s;\r
6429 \r
6430                         // If page not loaded and strict mode isn't enabled then load them\r
6431                         if (!Event.domLoaded && !s.strict_loading_mode) {\r
6432                                 // Load language\r
6433                                 if (s.language)\r
6434                                         sl.add(tinymce.baseURL + '/langs/' + s.language + '.js');\r
6435 \r
6436                                 // Load theme\r
6437                                 if (s.theme && s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme])\r
6438                                         ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js');\r
6439 \r
6440                                 // Load plugins\r
6441                                 if (s.plugins) {\r
6442                                         pl = explode(s.plugins);\r
6443 \r
6444                                         // Load compat2x first\r
6445                                         if (tinymce.inArray(pl, 'compat2x') != -1)\r
6446                                                 PluginManager.load('compat2x', 'plugins/compat2x/editor_plugin' + tinymce.suffix + '.js');\r
6447 \r
6448                                         // Load rest if plugins\r
6449                                         each(pl, function(v) {\r
6450                                                 if (v && v.charAt(0) != '-' && !PluginManager.urls[v]) {\r
6451                                                         // Skip safari plugin for other browsers\r
6452                                                         if (!tinymce.isWebKit && v == 'safari')\r
6453                                                                 return;\r
6454 \r
6455                                                         PluginManager.load(v, 'plugins/' + v + '/editor_plugin' + tinymce.suffix + '.js');\r
6456                                                 }\r
6457                                         });\r
6458                                 }\r
6459 \r
6460                                 sl.loadQueue();\r
6461                         }\r
6462 \r
6463                         // Legacy call\r
6464                         Event.add(document, 'init', function() {\r
6465                                 var l, co;\r
6466 \r
6467                                 execCallback(s, 'onpageload');\r
6468 \r
6469                                 // Verify that it's a valid browser\r
6470                                 if (s.browsers) {\r
6471                                         l = false;\r
6472 \r
6473                                         each(explode(s.browsers), function(v) {\r
6474                                                 switch (v) {\r
6475                                                         case 'ie':\r
6476                                                         case 'msie':\r
6477                                                                 if (tinymce.isIE)\r
6478                                                                         l = true;\r
6479                                                                 break;\r
6480 \r
6481                                                         case 'gecko':\r
6482                                                                 if (tinymce.isGecko)\r
6483                                                                         l = true;\r
6484                                                                 break;\r
6485 \r
6486                                                         case 'safari':\r
6487                                                         case 'webkit':\r
6488                                                                 if (tinymce.isWebKit)\r
6489                                                                         l = true;\r
6490                                                                 break;\r
6491 \r
6492                                                         case 'opera':\r
6493                                                                 if (tinymce.isOpera)\r
6494                                                                         l = true;\r
6495 \r
6496                                                                 break;\r
6497                                                 }\r
6498                                         });\r
6499 \r
6500                                         // Not a valid one\r
6501                                         if (!l)\r
6502                                                 return;\r
6503                                 }\r
6504 \r
6505                                 switch (s.mode) {\r
6506                                         case "exact":\r
6507                                                 l = s.elements || '';\r
6508 \r
6509                                                 if(l.length > 0) {\r
6510                                                         each(explode(l), function(v) {\r
6511                                                                 if (DOM.get(v)) {\r
6512                                                                         ed = new tinymce.Editor(v, s);\r
6513                                                                         el.push(ed);\r
6514                                                                         ed.render(1);\r
6515                                                                 } else {\r
6516                                                                         c = 0;\r
6517 \r
6518                                                                         each(document.forms, function(f) {\r
6519                                                                                 each(f.elements, function(e) {\r
6520                                                                                         if (e.name === v) {\r
6521                                                                                                 v = 'mce_editor_' + c;\r
6522                                                                                                 DOM.setAttrib(e, 'id', v);\r
6523 \r
6524                                                                                                 ed = new tinymce.Editor(v, s);\r
6525                                                                                                 el.push(ed);\r
6526                                                                                                 ed.render(1);\r
6527                                                                                         }\r
6528                                                                                 });\r
6529                                                                         });\r
6530                                                                 }\r
6531                                                         });\r
6532                                                 }\r
6533                                                 break;\r
6534 \r
6535                                         case "textareas":\r
6536                                         case "specific_textareas":\r
6537                                                 function hasClass(n, c) {\r
6538                                                         return c.constructor === RegExp ? c.test(n.className) : DOM.hasClass(n, c);\r
6539                                                 };\r
6540 \r
6541                                                 each(DOM.select('textarea'), function(v) {\r
6542                                                         if (s.editor_deselector && hasClass(v, s.editor_deselector))\r
6543                                                                 return;\r
6544 \r
6545                                                         if (!s.editor_selector || hasClass(v, s.editor_selector)) {\r
6546                                                                 // Can we use the name\r
6547                                                                 e = DOM.get(v.name);\r
6548                                                                 if (!v.id && !e)\r
6549                                                                         v.id = v.name;\r
6550 \r
6551                                                                 // Generate unique name if missing or already exists\r
6552                                                                 if (!v.id || t.get(v.id))\r
6553                                                                         v.id = DOM.uniqueId();\r
6554 \r
6555                                                                 ed = new tinymce.Editor(v.id, s);\r
6556                                                                 el.push(ed);\r
6557                                                                 ed.render(1);\r
6558                                                         }\r
6559                                                 });\r
6560                                                 break;\r
6561                                 }\r
6562 \r
6563                                 // Call onInit when all editors are initialized\r
6564                                 if (s.oninit) {\r
6565                                         l = co = 0;\r
6566 \r
6567                                         each (el, function(ed) {\r
6568                                                 co++;\r
6569 \r
6570                                                 if (!ed.initialized) {\r
6571                                                         // Wait for it\r
6572                                                         ed.onInit.add(function() {\r
6573                                                                 l++;\r
6574 \r
6575                                                                 // All done\r
6576                                                                 if (l == co)\r
6577                                                                         execCallback(s, 'oninit');\r
6578                                                         });\r
6579                                                 } else\r
6580                                                         l++;\r
6581 \r
6582                                                 // All done\r
6583                                                 if (l == co)\r
6584                                                         execCallback(s, 'oninit');                                      \r
6585                                         });\r
6586                                 }\r
6587                         });\r
6588                 },\r
6589 \r
6590                 get : function(id) {\r
6591                         return this.editors[id];\r
6592                 },\r
6593 \r
6594                 getInstanceById : function(id) {\r
6595                         return this.get(id);\r
6596                 },\r
6597 \r
6598                 add : function(e) {\r
6599                         this.editors[e.id] = e;\r
6600                         this._setActive(e);\r
6601 \r
6602                         return e;\r
6603                 },\r
6604 \r
6605                 remove : function(e) {\r
6606                         var t = this;\r
6607 \r
6608                         // Not in the collection\r
6609                         if (!t.editors[e.id])\r
6610                                 return null;\r
6611 \r
6612                         delete t.editors[e.id];\r
6613 \r
6614                         // Select another editor since the active one was removed\r
6615                         if (t.activeEditor == e) {\r
6616                                 each(t.editors, function(e) {\r
6617                                         t._setActive(e);\r
6618                                         return false; // Break\r
6619                                 });\r
6620                         }\r
6621 \r
6622                         e.destroy();\r
6623 \r
6624                         return e;\r
6625                 },\r
6626 \r
6627                 execCommand : function(c, u, v) {\r
6628                         var t = this, ed = t.get(v), w;\r
6629 \r
6630                         // Manager commands\r
6631                         switch (c) {\r
6632                                 case "mceFocus":\r
6633                                         ed.focus();\r
6634                                         return true;\r
6635 \r
6636                                 case "mceAddEditor":\r
6637                                 case "mceAddControl":\r
6638                                         if (!t.get(v))\r
6639                                                 new tinymce.Editor(v, t.settings).render();\r
6640 \r
6641                                         return true;\r
6642 \r
6643                                 case "mceAddFrameControl":\r
6644                                         w = v.window;\r
6645 \r
6646                                         // Add tinyMCE global instance and tinymce namespace to specified window\r
6647                                         w.tinyMCE = tinyMCE;\r
6648                                         w.tinymce = tinymce;\r
6649 \r
6650                                         tinymce.DOM.doc = w.document;\r
6651                                         tinymce.DOM.win = w;\r
6652 \r
6653                                         ed = new tinymce.Editor(v.element_id, v);\r
6654                                         ed.render();\r
6655 \r
6656                                         // Fix IE memory leaks\r
6657                                         if (tinymce.isIE) {\r
6658                                                 function clr() {\r
6659                                                         ed.destroy();\r
6660                                                         w.detachEvent('onunload', clr);\r
6661                                                         w = w.tinyMCE = w.tinymce = null; // IE leak\r
6662                                                 };\r
6663 \r
6664                                                 w.attachEvent('onunload', clr);\r
6665                                         }\r
6666 \r
6667                                         v.page_window = null;\r
6668 \r
6669                                         return true;\r
6670 \r
6671                                 case "mceRemoveEditor":\r
6672                                 case "mceRemoveControl":\r
6673                                         if (ed)\r
6674                                                 ed.remove();\r
6675 \r
6676                                         return true;\r
6677 \r
6678                                 case 'mceToggleEditor':\r
6679                                         if (!ed) {\r
6680                                                 t.execCommand('mceAddControl', 0, v);\r
6681                                                 return true;\r
6682                                         }\r
6683 \r
6684                                         if (ed.isHidden())\r
6685                                                 ed.show();\r
6686                                         else\r
6687                                                 ed.hide();\r
6688 \r
6689                                         return true;\r
6690                         }\r
6691 \r
6692                         // Run command on active editor\r
6693                         if (t.activeEditor)\r
6694                                 return t.activeEditor.execCommand(c, u, v);\r
6695 \r
6696                         return false;\r
6697                 },\r
6698 \r
6699                 execInstanceCommand : function(id, c, u, v) {\r
6700                         var ed = this.get(id);\r
6701 \r
6702                         if (ed)\r
6703                                 return ed.execCommand(c, u, v);\r
6704 \r
6705                         return false;\r
6706                 },\r
6707 \r
6708                 triggerSave : function() {\r
6709                         each(this.editors, function(e) {\r
6710                                 e.save();\r
6711                         });\r
6712                 },\r
6713 \r
6714                 addI18n : function(p, o) {\r
6715                         var lo, i18n = this.i18n;\r
6716 \r
6717                         if (!tinymce.is(p, 'string')) {\r
6718                                 each(p, function(o, lc) {\r
6719                                         each(o, function(o, g) {\r
6720                                                 each(o, function(o, k) {\r
6721                                                         if (g === 'common')\r
6722                                                                 i18n[lc + '.' + k] = o;\r
6723                                                         else\r
6724                                                                 i18n[lc + '.' + g + '.' + k] = o;\r
6725                                                 });\r
6726                                         });\r
6727                                 });\r
6728                         } else {\r
6729                                 each(o, function(o, k) {\r
6730                                         i18n[p + '.' + k] = o;\r
6731                                 });\r
6732                         }\r
6733                 },\r
6734 \r
6735                 // Private methods\r
6736 \r
6737                 _setActive : function(e) {\r
6738                         this.selectedInstance = this.activeEditor = e;\r
6739                 }\r
6740 \r
6741                 });\r
6742 \r
6743         tinymce.EditorManager.preInit();\r
6744 })();\r
6745 \r
6746 // Short for editor manager window.tinyMCE is needed when TinyMCE gets loaded though a XHR call\r
6747 var tinyMCE = window.tinyMCE = tinymce.EditorManager;\r
6748 \r
6749 /* file:jscripts/tiny_mce/classes/Editor.js */\r
6750 \r
6751 (function() {\r
6752         var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, Dispatcher = tinymce.util.Dispatcher;\r
6753         var each = tinymce.each, isGecko = tinymce.isGecko, isIE = tinymce.isIE, isWebKit = tinymce.isWebKit;\r
6754         var is = tinymce.is, ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, EditorManager = tinymce.EditorManager;\r
6755         var inArray = tinymce.inArray, grep = tinymce.grep, explode = tinymce.explode;\r
6756 \r
6757         tinymce.create('tinymce.Editor', {\r
6758                 Editor : function(id, s) {\r
6759                         var t = this;\r
6760 \r
6761                         t.id = t.editorId = id;\r
6762                         t.execCommands = {};\r
6763                         t.queryStateCommands = {};\r
6764                         t.queryValueCommands = {};\r
6765                         t.plugins = {};\r
6766 \r
6767                         // Add events to the editor\r
6768                         each([\r
6769                                 'onPreInit',\r
6770                                 'onBeforeRenderUI',\r
6771                                 'onPostRender',\r
6772                                 'onInit',\r
6773                                 'onRemove',\r
6774                                 'onActivate',\r
6775                                 'onDeactivate',\r
6776                                 'onClick',\r
6777                                 'onEvent',\r
6778                                 'onMouseUp',\r
6779                                 'onMouseDown',\r
6780                                 'onDblClick',\r
6781                                 'onKeyDown',\r
6782                                 'onKeyUp',\r
6783                                 'onKeyPress',\r
6784                                 'onContextMenu',\r
6785                                 'onSubmit',\r
6786                                 'onReset',\r
6787                                 'onPaste',\r
6788                                 'onPreProcess',\r
6789                                 'onPostProcess',\r
6790                                 'onBeforeSetContent',\r
6791                                 'onBeforeGetContent',\r
6792                                 'onSetContent',\r
6793                                 'onGetContent',\r
6794                                 'onLoadContent',\r
6795                                 'onSaveContent',\r
6796                                 'onNodeChange',\r
6797                                 'onChange',\r
6798                                 'onBeforeExecCommand',\r
6799                                 'onExecCommand',\r
6800                                 'onUndo',\r
6801                                 'onRedo',\r
6802                                 'onVisualAid',\r
6803                                 'onSetProgressState'\r
6804                         ], function(e) {\r
6805                                 t[e] = new Dispatcher(t);\r
6806                         });\r
6807 \r
6808                         // Default editor config\r
6809                         t.settings = s = extend({\r
6810                                 id : id,\r
6811                                 language : 'en',\r
6812                                 docs_language : 'en',\r
6813                                 theme : 'simple',\r
6814                                 skin : 'default',\r
6815                                 delta_width : 0,\r
6816                                 delta_height : 0,\r
6817                                 popup_css : '',\r
6818                                 plugins : '',\r
6819                                 document_base_url : tinymce.documentBaseURL,\r
6820                                 add_form_submit_trigger : 1,\r
6821                                 submit_patch : 1,\r
6822                                 add_unload_trigger : 1,\r
6823                                 convert_urls : 1,\r
6824                                 relative_urls : 1,\r
6825                                 remove_script_host : 1,\r
6826                                 table_inline_editing : 0,\r
6827                                 object_resizing : 1,\r
6828                                 cleanup : 1,\r
6829                                 accessibility_focus : 1,\r
6830                                 custom_shortcuts : 1,\r
6831                                 custom_undo_redo_keyboard_shortcuts : 1,\r
6832                                 custom_undo_redo_restore_selection : 1,\r
6833                                 custom_undo_redo : 1,\r
6834                                 doctype : '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">',\r
6835                                 visual_table_class : 'mceItemTable',\r
6836                                 visual : 1,\r
6837                                 inline_styles : true,\r
6838                                 convert_fonts_to_spans : true,\r
6839                                 font_size_style_values : 'xx-small,x-small,small,medium,large,x-large,xx-large',\r
6840                                 apply_source_formatting : 1,\r
6841                                 directionality : 'ltr',\r
6842                                 forced_root_block : 'p',\r
6843                                 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[align],-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=0|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
6844                                 hidden_input : 1,\r
6845                                 padd_empty_editor : 1,\r
6846                                 render_ui : 1,\r
6847                                 init_theme : 1,\r
6848                                 force_p_newlines : 1,\r
6849                                 indentation : '30px',\r
6850                                 keep_styles : 1\r
6851                         }, s);\r
6852 \r
6853                         // Setup URIs\r
6854                         t.documentBaseURI = new tinymce.util.URI(s.document_base_url || tinymce.documentBaseURL, {\r
6855                                 base_uri : tinyMCE.baseURI\r
6856                         });\r
6857                         t.baseURI = EditorManager.baseURI;\r
6858 \r
6859                         // Call setup\r
6860                         t.execCallback('setup', t);\r
6861                 },\r
6862 \r
6863                 render : function(nst) {\r
6864                         var t = this, s = t.settings, id = t.id, sl = tinymce.ScriptLoader;\r
6865 \r
6866                         // Page is not loaded yet, wait for it\r
6867                         if (!Event.domLoaded) {\r
6868                                 Event.add(document, 'init', function() {\r
6869                                         t.render();\r
6870                                 });\r
6871                                 return;\r
6872                         }\r
6873 \r
6874                         // Force strict loading mode if render us called by user and not internally\r
6875                         if (!nst) {\r
6876                                 s.strict_loading_mode = 1;\r
6877                                 tinyMCE.settings = s;\r
6878                         }\r
6879 \r
6880                         // Element not found, then skip initialization\r
6881                         if (!t.getElement())\r
6882                                 return;\r
6883 \r
6884                         if (s.strict_loading_mode) {\r
6885                                 sl.settings.strict_mode = s.strict_loading_mode;\r
6886                                 tinymce.DOM.settings.strict = 1;\r
6887                         }\r
6888 \r
6889                         // Add hidden input for non input elements inside form elements\r
6890                         if (!/TEXTAREA|INPUT/i.test(t.getElement().nodeName) && s.hidden_input && DOM.getParent(id, 'form'))\r
6891                                 DOM.insertAfter(DOM.create('input', {type : 'hidden', name : id}), id);\r
6892 \r
6893                         t.windowManager = new tinymce.WindowManager(t);\r
6894 \r
6895                         if (s.encoding == 'xml') {\r
6896                                 t.onGetContent.add(function(ed, o) {\r
6897                                         if (o.save)\r
6898                                                 o.content = DOM.encode(o.content);\r
6899                                 });\r
6900                         }\r
6901 \r
6902                         if (s.add_form_submit_trigger) {\r
6903                                 t.onSubmit.addToTop(function() {\r
6904                                         if (t.initialized) {\r
6905                                                 t.save();\r
6906                                                 t.isNotDirty = 1;\r
6907                                         }\r
6908                                 });\r
6909                         }\r
6910 \r
6911                         if (s.add_unload_trigger && !s.ask) {\r
6912                                 t._beforeUnload = tinyMCE.onBeforeUnload.add(function() {\r
6913                                         if (t.initialized && !t.destroyed && !t.isHidden())\r
6914                                                 t.save({format : 'raw', no_events : true});\r
6915                                 });\r
6916                         }\r
6917 \r
6918                         tinymce.addUnload(t.destroy, t);\r
6919 \r
6920                         if (s.submit_patch) {\r
6921                                 t.onBeforeRenderUI.add(function() {\r
6922                                         var n = t.getElement().form;\r
6923 \r
6924                                         if (!n)\r
6925                                                 return;\r
6926 \r
6927                                         // Already patched\r
6928                                         if (n._mceOldSubmit)\r
6929                                                 return;\r
6930 \r
6931                                         // Check page uses id="submit" or name="submit" for it's submit button\r
6932                                         if (!n.submit.nodeType && !n.submit.length) {\r
6933                                                 t.formElement = n;\r
6934                                                 n._mceOldSubmit = n.submit;\r
6935                                                 n.submit = function() {\r
6936                                                         // Save all instances\r
6937                                                         EditorManager.triggerSave();\r
6938                                                         t.isNotDirty = 1;\r
6939 \r
6940                                                         return this._mceOldSubmit(this);\r
6941                                                 };\r
6942                                         }\r
6943 \r
6944                                         n = null;\r
6945                                 });\r
6946                         }\r
6947 \r
6948                         // Load scripts\r
6949                         function loadScripts() {\r
6950                                 if (s.language)\r
6951                                         sl.add(tinymce.baseURL + '/langs/' + s.language + '.js');\r
6952 \r
6953                                 if (s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme])\r
6954                                         ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js');\r
6955 \r
6956                                 each(explode(s.plugins), function(p) {\r
6957                                         if (p && p.charAt(0) != '-' && !PluginManager.urls[p]) {\r
6958                                                 // Skip safari plugin for other browsers\r
6959                                                 if (!isWebKit && p == 'safari')\r
6960                                                         return;\r
6961 \r
6962                                                 PluginManager.load(p, 'plugins/' + p + '/editor_plugin' + tinymce.suffix + '.js');\r
6963                                         }\r
6964                                 });\r
6965 \r
6966                                 // Init when que is loaded\r
6967                                 sl.loadQueue(function() {\r
6968                                         if (s.ask) {\r
6969                                                 function ask() {\r
6970                                                         // Yield for awhile to avoid focus bug on FF 3 when cancel is pressed\r
6971                                                         window.setTimeout(function() {\r
6972                                                                 Event.remove(t.id, 'focus', ask);\r
6973 \r
6974                                                                 t.windowManager.confirm(t.getLang('edit_confirm'), function(s) {\r
6975                                                                         if (s)\r
6976                                                                                 t.init();\r
6977                                                                 });\r
6978                                                         }, 0);\r
6979                                                 };\r
6980 \r
6981                                                 Event.add(t.id, 'focus', ask);\r
6982                                                 return;\r
6983                                         }\r
6984 \r
6985                                         if (!t.removed)\r
6986                                                 t.init();\r
6987                                 });\r
6988                         };\r
6989 \r
6990                         // Load compat2x first\r
6991                         if (s.plugins.indexOf('compat2x') != -1) {\r
6992                                 PluginManager.load('compat2x', 'plugins/compat2x/editor_plugin' + tinymce.suffix + '.js');\r
6993                                 sl.loadQueue(loadScripts);\r
6994                         } else\r
6995                                 loadScripts();\r
6996                 },\r
6997 \r
6998                 init : function() {\r
6999                         var n, t = this, s = t.settings, w, h, e = t.getElement(), o, ti, u, bi, bc, re;\r
7000 \r
7001                         EditorManager.add(t);\r
7002 \r
7003                         // Create theme\r
7004                         s.theme = s.theme.replace(/-/, '');\r
7005                         o = ThemeManager.get(s.theme);\r
7006                         t.theme = new o();\r
7007 \r
7008                         if (t.theme.init && s.init_theme)\r
7009                                 t.theme.init(t, ThemeManager.urls[s.theme] || tinymce.documentBaseURL.replace(/\/$/, ''));\r
7010 \r
7011                         // Create all plugins\r
7012                         each(explode(s.plugins.replace(/\-/g, '')), function(p) {\r
7013                                 var c = PluginManager.get(p), u = PluginManager.urls[p] || tinymce.documentBaseURL.replace(/\/$/, ''), po;\r
7014 \r
7015                                 if (c) {\r
7016                                         po = new c(t, u);\r
7017 \r
7018                                         t.plugins[p] = po;\r
7019 \r
7020                                         if (po.init)\r
7021                                                 po.init(t, u);\r
7022                                 }\r
7023                         });\r
7024 \r
7025                         // Setup popup CSS path(s)\r
7026                         if (s.popup_css !== false) {\r
7027                                 if (s.popup_css)\r
7028                                         s.popup_css = t.documentBaseURI.toAbsolute(s.popup_css);\r
7029                                 else\r
7030                                         s.popup_css = t.baseURI.toAbsolute("themes/" + s.theme + "/skins/" + s.skin + "/dialog.css");\r
7031                         }\r
7032 \r
7033                         if (s.popup_css_add)\r
7034                                 s.popup_css += ',' + t.documentBaseURI.toAbsolute(s.popup_css_add);\r
7035 \r
7036                         // Setup control factory\r
7037                         t.controlManager = new tinymce.ControlManager(t);\r
7038                         t.undoManager = new tinymce.UndoManager(t);\r
7039 \r
7040                         // Pass through\r
7041                         t.undoManager.onAdd.add(function(um, l) {\r
7042                                 if (!l.initial)\r
7043                                         return t.onChange.dispatch(t, l, um);\r
7044                         });\r
7045 \r
7046                         t.undoManager.onUndo.add(function(um, l) {\r
7047                                 return t.onUndo.dispatch(t, l, um);\r
7048                         });\r
7049 \r
7050                         t.undoManager.onRedo.add(function(um, l) {\r
7051                                 return t.onRedo.dispatch(t, l, um);\r
7052                         });\r
7053 \r
7054                         if (s.custom_undo_redo) {\r
7055                                 t.onExecCommand.add(function(ed, cmd, ui, val, a) {\r
7056                                         if (cmd != 'Undo' && cmd != 'Redo' && cmd != 'mceRepaint' && (!a || !a.skip_undo))\r
7057                                                 t.undoManager.add();\r
7058                                 });\r
7059                         }\r
7060 \r
7061                         t.onExecCommand.add(function(ed, c) {\r
7062                                 // Don't refresh the select lists until caret move\r
7063                                 if (!/^(FontName|FontSize)$/.test(c))\r
7064                                         t.nodeChanged();\r
7065                         });\r
7066 \r
7067                         // Remove ghost selections on images and tables in Gecko\r
7068                         if (isGecko) {\r
7069                                 function repaint(a, o) {\r
7070                                         if (!o || !o.initial)\r
7071                                                 t.execCommand('mceRepaint');\r
7072                                 };\r
7073 \r
7074                                 t.onUndo.add(repaint);\r
7075                                 t.onRedo.add(repaint);\r
7076                                 t.onSetContent.add(repaint);\r
7077                         }\r
7078 \r
7079                         // Enables users to override the control factory\r
7080                         t.onBeforeRenderUI.dispatch(t, t.controlManager);\r
7081 \r
7082                         // Measure box\r
7083                         if (s.render_ui) {\r
7084                                 w = s.width || e.style.width || e.offsetWidth;\r
7085                                 h = s.height || e.style.height || e.offsetHeight;\r
7086                                 t.orgDisplay = e.style.display;\r
7087                                 re = /^[0-9\.]+(|px)$/i;\r
7088 \r
7089                                 if (re.test('' + w))\r
7090                                         w = Math.max(parseInt(w) + (o.deltaWidth || 0), 100);\r
7091 \r
7092                                 if (re.test('' + h))\r
7093                                         h = Math.max(parseInt(h) + (o.deltaHeight || 0), 100);\r
7094 \r
7095                                 // Render UI\r
7096                                 o = t.theme.renderUI({\r
7097                                         targetNode : e,\r
7098                                         width : w,\r
7099                                         height : h,\r
7100                                         deltaWidth : s.delta_width,\r
7101                                         deltaHeight : s.delta_height\r
7102                                 });\r
7103 \r
7104                                 t.editorContainer = o.editorContainer;\r
7105                         }\r
7106 \r
7107                         \r
7108                         // Resize editor\r
7109                         DOM.setStyles(o.sizeContainer || o.editorContainer, {\r
7110                                 width : w,\r
7111                                 height : h\r
7112                         });\r
7113 \r
7114                         h = (o.iframeHeight || h) + (typeof(h) == 'number' ? (o.deltaHeight || 0) : '');\r
7115                         if (h < 100)\r
7116                                 h = 100;\r
7117 \r
7118                         t.iframeHTML = s.doctype + '<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="' + t.documentBaseURI.getURI() + '" />';\r
7119                         t.iframeHTML += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';\r
7120 \r
7121                         if (tinymce.relaxedDomain)\r
7122                                 t.iframeHTML += '<script type="text/javascript">document.domain = "' + tinymce.relaxedDomain + '";</script>';\r
7123 \r
7124                         bi = s.body_id || 'tinymce';\r
7125                         if (bi.indexOf('=') != -1) {\r
7126                                 bi = t.getParam('body_id', '', 'hash');\r
7127                                 bi = bi[t.id] || bi;\r
7128                         }\r
7129 \r
7130                         bc = s.body_class || '';\r
7131                         if (bc.indexOf('=') != -1) {\r
7132                                 bc = t.getParam('body_class', '', 'hash');\r
7133                                 bc = bc[t.id] || '';\r
7134                         }\r
7135 \r
7136                         t.iframeHTML += '</head><body id="' + bi + '" class="mceContentBody ' + bc + '"></body></html>';\r
7137 \r
7138                         // Domain relaxing enabled, then set document domain\r
7139                         if (tinymce.relaxedDomain) {\r
7140                                 // We need to write the contents here in IE since multiple writes messes up refresh button and back button\r
7141                                 if (isIE || (tinymce.isOpera && parseFloat(opera.version()) >= 9.5))\r
7142                                         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
7143                                 else if (tinymce.isOpera)\r
7144                                         u = 'javascript:(function(){document.open();document.domain="' + document.domain + '";document.close();ed.setupIframe();})()';                                  \r
7145                         }\r
7146 \r
7147                         // Create iframe\r
7148                         n = DOM.add(o.iframeContainer, 'iframe', {\r
7149                                 id : t.id + "_ifr",\r
7150                                 src : u || 'javascript:""', // Workaround for HTTPS warning in IE6/7\r
7151                                 frameBorder : '0',\r
7152                                 style : {\r
7153                                         width : '100%',\r
7154                                         height : h\r
7155                                 }\r
7156                         });\r
7157 \r
7158                         t.contentAreaContainer = o.iframeContainer;\r
7159                         DOM.get(o.editorContainer).style.display = t.orgDisplay;\r
7160                         DOM.get(t.id).style.display = 'none';\r
7161 \r
7162                         // Safari 2.x requires us to wait for the load event and load a real HTML doc\r
7163                         if (tinymce.isOldWebKit) {\r
7164                                 Event.add(n, 'load', t.setupIframe, t);\r
7165                                 n.src = tinymce.baseURL + '/plugins/safari/blank.htm';\r
7166                         } else {\r
7167                                 if (!isIE || !tinymce.relaxedDomain)\r
7168                                         t.setupIframe();\r
7169 \r
7170                                 e = n = o = null; // Cleanup\r
7171                         }\r
7172                 },\r
7173 \r
7174                 setupIframe : function() {\r
7175                         var t = this, s = t.settings, e = DOM.get(t.id), d = t.getDoc(), h, b;\r
7176 \r
7177                         // Setup iframe body\r
7178                         if (!isIE || !tinymce.relaxedDomain) {\r
7179                                 d.open();\r
7180                                 d.write(t.iframeHTML);\r
7181                                 d.close();\r
7182                         }\r
7183 \r
7184                         // Design mode needs to be added here Ctrl+A will fail otherwise\r
7185                         if (!isIE) {\r
7186                                 try {\r
7187                                         if (!s.readonly)\r
7188                                                 d.designMode = 'On';\r
7189                                 } catch (ex) {\r
7190                                         // Will fail on Gecko if the editor is placed in an hidden container element\r
7191                                         // The design mode will be set ones the editor is focused\r
7192                                 }\r
7193                         }\r
7194 \r
7195                         // IE needs to use contentEditable or it will display non secure items for HTTPS\r
7196                         if (isIE) {\r
7197                                 // It will not steal focus if we hide it while setting contentEditable\r
7198                                 b = t.getBody();\r
7199                                 DOM.hide(b);\r
7200 \r
7201                                 if (!s.readonly)\r
7202                                         b.contentEditable = true;\r
7203 \r
7204                                 DOM.show(b);\r
7205                         }\r
7206 \r
7207                         // Setup objects\r
7208                         t.dom = new tinymce.DOM.DOMUtils(t.getDoc(), {\r
7209                                 keep_values : true,\r
7210                                 url_converter : t.convertURL,\r
7211                                 url_converter_scope : t,\r
7212                                 hex_colors : s.force_hex_style_colors,\r
7213                                 class_filter : s.class_filter,\r
7214                                 update_styles : 1,\r
7215                                 fix_ie_paragraphs : 1\r
7216                         });\r
7217 \r
7218                         t.serializer = new tinymce.dom.Serializer({\r
7219                                 entity_encoding : s.entity_encoding,\r
7220                                 entities : s.entities,\r
7221                                 valid_elements : s.verify_html === false ? '*[*]' : s.valid_elements,\r
7222                                 extended_valid_elements : s.extended_valid_elements,\r
7223                                 valid_child_elements : s.valid_child_elements,\r
7224                                 invalid_elements : s.invalid_elements,\r
7225                                 fix_table_elements : s.fix_table_elements,\r
7226                                 fix_list_elements : s.fix_list_elements,\r
7227                                 fix_content_duplication : s.fix_content_duplication,\r
7228                                 convert_fonts_to_spans : s.convert_fonts_to_spans,\r
7229                                 font_size_classes  : s.font_size_classes,\r
7230                                 font_size_style_values : s.font_size_style_values,\r
7231                                 apply_source_formatting : s.apply_source_formatting,\r
7232                                 remove_linebreaks : s.remove_linebreaks,\r
7233                                 element_format : s.element_format,\r
7234                                 dom : t.dom\r
7235                         });\r
7236 \r
7237                         t.selection = new tinymce.dom.Selection(t.dom, t.getWin(), t.serializer);\r
7238                         t.forceBlocks = new tinymce.ForceBlocks(t, {\r
7239                                 forced_root_block : s.forced_root_block\r
7240                         });\r
7241                         t.editorCommands = new tinymce.EditorCommands(t);\r
7242 \r
7243                         // Pass through\r
7244                         t.serializer.onPreProcess.add(function(se, o) {\r
7245                                 return t.onPreProcess.dispatch(t, o, se);\r
7246                         });\r
7247 \r
7248                         t.serializer.onPostProcess.add(function(se, o) {\r
7249                                 return t.onPostProcess.dispatch(t, o, se);\r
7250                         });\r
7251 \r
7252                         t.onPreInit.dispatch(t);\r
7253 \r
7254                         if (!s.gecko_spellcheck)\r
7255                                 t.getBody().spellcheck = 0;\r
7256 \r
7257                         if (!s.readonly)\r
7258                                 t._addEvents();\r
7259 \r
7260                         t.controlManager.onPostRender.dispatch(t, t.controlManager);\r
7261                         t.onPostRender.dispatch(t);\r
7262 \r
7263                         if (s.directionality)\r
7264                                 t.getBody().dir = s.directionality;\r
7265 \r
7266                         if (s.nowrap)\r
7267                                 t.getBody().style.whiteSpace = "nowrap";\r
7268 \r
7269                         if (s.auto_resize)\r
7270                                 t.onNodeChange.add(t.resizeToContent, t);\r
7271 \r
7272                         if (s.custom_elements) {\r
7273                                 function handleCustom(ed, o) {\r
7274                                         each(explode(s.custom_elements), function(v) {\r
7275                                                 var n;\r
7276 \r
7277                                                 if (v.indexOf('~') === 0) {\r
7278                                                         v = v.substring(1);\r
7279                                                         n = 'span';\r
7280                                                 } else\r
7281                                                         n = 'div';\r
7282 \r
7283                                                 o.content = o.content.replace(new RegExp('<(' + v + ')([^>]*)>', 'g'), '<' + n + ' mce_name="$1"$2>');\r
7284                                                 o.content = o.content.replace(new RegExp('</(' + v + ')>', 'g'), '</' + n + '>');\r
7285                                         });\r
7286                                 };\r
7287 \r
7288                                 t.onBeforeSetContent.add(handleCustom);\r
7289                                 t.onPostProcess.add(function(ed, o) {\r
7290                                         if (o.set)\r
7291                                                 handleCustom(ed, o)\r
7292                                 });\r
7293                         }\r
7294 \r
7295                         if (s.handle_node_change_callback) {\r
7296                                 t.onNodeChange.add(function(ed, cm, n) {\r
7297                                         t.execCallback('handle_node_change_callback', t.id, n, -1, -1, true, t.selection.isCollapsed());\r
7298                                 });\r
7299                         }\r
7300 \r
7301                         if (s.save_callback) {\r
7302                                 t.onSaveContent.add(function(ed, o) {\r
7303                                         var h = t.execCallback('save_callback', t.id, o.content, t.getBody());\r
7304 \r
7305                                         if (h)\r
7306                                                 o.content = h;\r
7307                                 });\r
7308                         }\r
7309 \r
7310                         if (s.onchange_callback) {\r
7311                                 t.onChange.add(function(ed, l) {\r
7312                                         t.execCallback('onchange_callback', t, l);\r
7313                                 });\r
7314                         }\r
7315 \r
7316                         if (s.convert_newlines_to_brs) {\r
7317                                 t.onBeforeSetContent.add(function(ed, o) {\r
7318                                         if (o.initial)\r
7319                                                 o.content = o.content.replace(/\r?\n/g, '<br />');\r
7320                                 });\r
7321                         }\r
7322 \r
7323                         if (s.fix_nesting && isIE) {\r
7324                                 t.onBeforeSetContent.add(function(ed, o) {\r
7325                                         o.content = t._fixNesting(o.content);\r
7326                                 });\r
7327                         }\r
7328 \r
7329                         if (s.preformatted) {\r
7330                                 t.onPostProcess.add(function(ed, o) {\r
7331                                         o.content = o.content.replace(/^\s*<pre.*?>/, '');\r
7332                                         o.content = o.content.replace(/<\/pre>\s*$/, '');\r
7333 \r
7334                                         if (o.set)\r
7335                                                 o.content = '<pre class="mceItemHidden">' + o.content + '</pre>';\r
7336                                 });\r
7337                         }\r
7338 \r
7339                         if (s.verify_css_classes) {\r
7340                                 t.serializer.attribValueFilter = function(n, v) {\r
7341                                         var s, cl;\r
7342 \r
7343                                         if (n == 'class') {\r
7344                                                 // Build regexp for classes\r
7345                                                 if (!t.classesRE) {\r
7346                                                         cl = t.dom.getClasses();\r
7347 \r
7348                                                         if (cl.length > 0) {\r
7349                                                                 s = '';\r
7350 \r
7351                                                                 each (cl, function(o) {\r
7352                                                                         s += (s ? '|' : '') + o['class'];\r
7353                                                                 });\r
7354 \r
7355                                                                 t.classesRE = new RegExp('(' + s + ')', 'gi');\r
7356                                                         }\r
7357                                                 }\r
7358 \r
7359                                                 return !t.classesRE || /(\bmceItem\w+\b|\bmceTemp\w+\b)/g.test(v) || t.classesRE.test(v) ? v : '';\r
7360                                         }\r
7361 \r
7362                                         return v;\r
7363                                 };\r
7364                         }\r
7365 \r
7366                         if (s.convert_fonts_to_spans)\r
7367                                 t._convertFonts();\r
7368 \r
7369                         if (s.inline_styles)\r
7370                                 t._convertInlineElements();\r
7371 \r
7372                         if (s.cleanup_callback) {\r
7373                                 t.onBeforeSetContent.add(function(ed, o) {\r
7374                                         o.content = t.execCallback('cleanup_callback', 'insert_to_editor', o.content, o);\r
7375                                 });\r
7376 \r
7377                                 t.onPreProcess.add(function(ed, o) {\r
7378                                         if (o.set)\r
7379                                                 t.execCallback('cleanup_callback', 'insert_to_editor_dom', o.node, o);\r
7380 \r
7381                                         if (o.get)\r
7382                                                 t.execCallback('cleanup_callback', 'get_from_editor_dom', o.node, o);\r
7383                                 });\r
7384 \r
7385                                 t.onPostProcess.add(function(ed, o) {\r
7386                                         if (o.set)\r
7387                                                 o.content = t.execCallback('cleanup_callback', 'insert_to_editor', o.content, o);\r
7388 \r
7389                                         if (o.get)                                              \r
7390                                                 o.content = t.execCallback('cleanup_callback', 'get_from_editor', o.content, o);\r
7391                                 });\r
7392                         }\r
7393 \r
7394                         if (s.save_callback) {\r
7395                                 t.onGetContent.add(function(ed, o) {\r
7396                                         if (o.save)\r
7397                                                 o.content = t.execCallback('save_callback', t.id, o.content, t.getBody());\r
7398                                 });\r
7399                         }\r
7400 \r
7401                         if (s.handle_event_callback) {\r
7402                                 t.onEvent.add(function(ed, e, o) {\r
7403                                         if (t.execCallback('handle_event_callback', e, ed, o) === false)\r
7404                                                 Event.cancel(e);\r
7405                                 });\r
7406                         }\r
7407 \r
7408                         t.onSetContent.add(function() {\r
7409                                 // Safari needs some time, it will crash the browser when a link is created otherwise\r
7410                                 // I think this crash issue is resolved in the latest 3.0.4\r
7411                                 //window.setTimeout(function() {\r
7412                                         t.addVisual(t.getBody());\r
7413                                 //}, 1);\r
7414                         });\r
7415 \r
7416                         // Remove empty contents\r
7417                         if (s.padd_empty_editor) {\r
7418                                 t.onPostProcess.add(function(ed, o) {\r
7419                                         o.content = o.content.replace(/^(<p[^>]*>(&nbsp;|&#160;|\s|\u00a0|)<\/p>[\r\n]*|<br \/>[\r\n]*)$/, '');\r
7420                                 });\r
7421                         }\r
7422 \r
7423                         if (isGecko && !s.readonly) {\r
7424                                 try {\r
7425                                         // Design mode must be set here once again to fix a bug where\r
7426                                         // Ctrl+A/Delete/Backspace didn't work if the editor was added using mceAddControl then removed then added again\r
7427                                         d.designMode = 'Off';\r
7428                                         d.designMode = 'On';\r
7429                                 } catch (ex) {\r
7430                                         // Will fail on Gecko if the editor is placed in an hidden container element\r
7431                                         // The design mode will be set ones the editor is focused\r
7432                                 }\r
7433                         }\r
7434 \r
7435                         // A small timeout was needed since firefox will remove. Bug: #1838304\r
7436                         setTimeout(function () {\r
7437                                 if (t.removed)\r
7438                                         return;\r
7439 \r
7440                                 t.load({initial : true, format : (s.cleanup_on_startup ? 'html' : 'raw')});\r
7441                                 t.startContent = t.getContent({format : 'raw'});\r
7442                                 t.undoManager.add({initial : true});\r
7443                                 t.initialized = true;\r
7444 \r
7445                                 t.onInit.dispatch(t);\r
7446                                 t.execCallback('setupcontent_callback', t.id, t.getBody(), t.getDoc());\r
7447                                 t.execCallback('init_instance_callback', t);\r
7448                                 t.focus(true);\r
7449                                 t.nodeChanged({initial : 1});\r
7450 \r
7451                                 // Load specified content CSS last\r
7452                                 if (s.content_css) {\r
7453                                         tinymce.each(explode(s.content_css), function(u) {\r
7454                                                 t.dom.loadCSS(t.documentBaseURI.toAbsolute(u));\r
7455                                         });\r
7456                                 }\r
7457 \r
7458                                 // Handle auto focus\r
7459                                 if (s.auto_focus) {\r
7460                                         setTimeout(function () {\r
7461                                                 var ed = EditorManager.get(s.auto_focus);\r
7462 \r
7463                                                 ed.selection.select(ed.getBody(), 1);\r
7464                                                 ed.selection.collapse(1);\r
7465                                                 ed.getWin().focus();\r
7466                                         }, 100);\r
7467                                 }\r
7468                         }, 1);\r
7469         \r
7470                         e = null;\r
7471                 },\r
7472 \r
7473                 \r
7474                 focus : function(sf) {\r
7475                         var oed, t = this, ce = t.settings.content_editable;\r
7476 \r
7477                         if (!sf) {\r
7478                                 // Is not content editable or the selection is outside the area in IE\r
7479                                 // the IE statement is needed to avoid bluring if element selections inside layers since\r
7480                                 // the layer is like it's own document in IE\r
7481                                 if (!ce && (!isIE || t.selection.getNode().ownerDocument != t.getDoc()))\r
7482                                         t.getWin().focus();\r
7483 \r
7484                                                         }\r
7485 \r
7486                         if (EditorManager.activeEditor != t) {\r
7487                                 if ((oed = EditorManager.activeEditor) != null)\r
7488                                         oed.onDeactivate.dispatch(oed, t);\r
7489 \r
7490                                 t.onActivate.dispatch(t, oed);\r
7491                         }\r
7492 \r
7493                         EditorManager._setActive(t);\r
7494                 },\r
7495 \r
7496                 execCallback : function(n) {\r
7497                         var t = this, f = t.settings[n], s;\r
7498 \r
7499                         if (!f)\r
7500                                 return;\r
7501 \r
7502                         // Look through lookup\r
7503                         if (t.callbackLookup && (s = t.callbackLookup[n])) {\r
7504                                 f = s.func;\r
7505                                 s = s.scope;\r
7506                         }\r
7507 \r
7508                         if (is(f, 'string')) {\r
7509                                 s = f.replace(/\.\w+$/, '');\r
7510                                 s = s ? tinymce.resolve(s) : 0;\r
7511                                 f = tinymce.resolve(f);\r
7512                                 t.callbackLookup = t.callbackLookup || {};\r
7513                                 t.callbackLookup[n] = {func : f, scope : s};\r
7514                         }\r
7515 \r
7516                         return f.apply(s || t, Array.prototype.slice.call(arguments, 1));\r
7517                 },\r
7518 \r
7519                 translate : function(s) {\r
7520                         var c = this.settings.language || 'en', i18n = EditorManager.i18n;\r
7521 \r
7522                         if (!s)\r
7523                                 return '';\r
7524 \r
7525                         return i18n[c + '.' + s] || s.replace(/{\#([^}]+)\}/g, function(a, b) {\r
7526                                 return i18n[c + '.' + b] || '{#' + b + '}';\r
7527                         });\r
7528                 },\r
7529 \r
7530                 getLang : function(n, dv) {\r
7531                         return EditorManager.i18n[(this.settings.language || 'en') + '.' + n] || (is(dv) ? dv : '{#' + n + '}');\r
7532                 },\r
7533 \r
7534                 getParam : function(n, dv, ty) {\r
7535                         var tr = tinymce.trim, v = is(this.settings[n]) ? this.settings[n] : dv, o;\r
7536 \r
7537                         if (ty === 'hash') {\r
7538                                 o = {};\r
7539 \r
7540                                 if (is(v, 'string')) {\r
7541                                         each(v.indexOf('=') > 0 ? v.split(/[;,](?![^=;,]*(?:[;,]|$))/) : v.split(','), function(v) {\r
7542                                                 v = v.split('=');\r
7543 \r
7544                                                 if (v.length > 1)\r
7545                                                         o[tr(v[0])] = tr(v[1]);\r
7546                                                 else\r
7547                                                         o[tr(v[0])] = tr(v);\r
7548                                         });\r
7549                                 } else\r
7550                                         o = v;\r
7551 \r
7552                                 return o;\r
7553                         }\r
7554 \r
7555                         return v;\r
7556                 },\r
7557 \r
7558                 nodeChanged : function(o) {\r
7559                         var t = this, s = t.selection, n = s.getNode() || t.getBody();\r
7560 \r
7561                         // Fix for bug #1896577 it seems that this can not be fired while the editor is loading\r
7562                         if (t.initialized) {\r
7563                                 t.onNodeChange.dispatch(\r
7564                                         t,\r
7565                                         o ? o.controlManager || t.controlManager : t.controlManager,\r
7566                                         isIE && n.ownerDocument != t.getDoc() ? t.getBody() : n, // Fix for IE initial state\r
7567                                         s.isCollapsed(),\r
7568                                         o\r
7569                                 );\r
7570                         }\r
7571                 },\r
7572 \r
7573                 addButton : function(n, s) {\r
7574                         var t = this;\r
7575 \r
7576                         t.buttons = t.buttons || {};\r
7577                         t.buttons[n] = s;\r
7578                 },\r
7579 \r
7580                 addCommand : function(n, f, s) {\r
7581                         this.execCommands[n] = {func : f, scope : s || this};\r
7582                 },\r
7583 \r
7584                 addQueryStateHandler : function(n, f, s) {\r
7585                         this.queryStateCommands[n] = {func : f, scope : s || this};\r
7586                 },\r
7587 \r
7588                 addQueryValueHandler : function(n, f, s) {\r
7589                         this.queryValueCommands[n] = {func : f, scope : s || this};\r
7590                 },\r
7591 \r
7592                 addShortcut : function(pa, desc, cmd_func, sc) {\r
7593                         var t = this, c;\r
7594 \r
7595                         if (!t.settings.custom_shortcuts)\r
7596                                 return false;\r
7597 \r
7598                         t.shortcuts = t.shortcuts || {};\r
7599 \r
7600                         if (is(cmd_func, 'string')) {\r
7601                                 c = cmd_func;\r
7602 \r
7603                                 cmd_func = function() {\r
7604                                         t.execCommand(c, false, null);\r
7605                                 };\r
7606                         }\r
7607 \r
7608                         if (is(cmd_func, 'object')) {\r
7609                                 c = cmd_func;\r
7610 \r
7611                                 cmd_func = function() {\r
7612                                         t.execCommand(c[0], c[1], c[2]);\r
7613                                 };\r
7614                         }\r
7615 \r
7616                         each(explode(pa), function(pa) {\r
7617                                 var o = {\r
7618                                         func : cmd_func,\r
7619                                         scope : sc || this,\r
7620                                         desc : desc,\r
7621                                         alt : false,\r
7622                                         ctrl : false,\r
7623                                         shift : false\r
7624                                 };\r
7625 \r
7626                                 each(explode(pa, '+'), function(v) {\r
7627                                         switch (v) {\r
7628                                                 case 'alt':\r
7629                                                 case 'ctrl':\r
7630                                                 case 'shift':\r
7631                                                         o[v] = true;\r
7632                                                         break;\r
7633 \r
7634                                                 default:\r
7635                                                         o.charCode = v.charCodeAt(0);\r
7636                                                         o.keyCode = v.toUpperCase().charCodeAt(0);\r
7637                                         }\r
7638                                 });\r
7639 \r
7640                                 t.shortcuts[(o.ctrl ? 'ctrl' : '') + ',' + (o.alt ? 'alt' : '') + ',' + (o.shift ? 'shift' : '') + ',' + o.keyCode] = o;\r
7641                         });\r
7642 \r
7643                         return true;\r
7644                 },\r
7645 \r
7646                 execCommand : function(cmd, ui, val, a) {\r
7647                         var t = this, s = 0, o, st;\r
7648 \r
7649                         if (!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(cmd) && (!a || !a.skip_focus))\r
7650                                 t.focus();\r
7651 \r
7652                         o = {};\r
7653                         t.onBeforeExecCommand.dispatch(t, cmd, ui, val, o);\r
7654                         if (o.terminate)\r
7655                                 return false;\r
7656 \r
7657                         // Command callback\r
7658                         if (t.execCallback('execcommand_callback', t.id, t.selection.getNode(), cmd, ui, val)) {\r
7659                                 t.onExecCommand.dispatch(t, cmd, ui, val, a);\r
7660                                 return true;\r
7661                         }\r
7662 \r
7663                         // Registred commands\r
7664                         if (o = t.execCommands[cmd]) {\r
7665                                 st = o.func.call(o.scope, ui, val);\r
7666 \r
7667                                 // Fall through on true\r
7668                                 if (st !== true) {\r
7669                                         t.onExecCommand.dispatch(t, cmd, ui, val, a);\r
7670                                         return st;\r
7671                                 }\r
7672                         }\r
7673 \r
7674                         // Plugin commands\r
7675                         each(t.plugins, function(p) {\r
7676                                 if (p.execCommand && p.execCommand(cmd, ui, val)) {\r
7677                                         t.onExecCommand.dispatch(t, cmd, ui, val, a);\r
7678                                         s = 1;\r
7679                                         return false;\r
7680                                 }\r
7681                         });\r
7682 \r
7683                         if (s)\r
7684                                 return true;\r
7685 \r
7686                         // Theme commands\r
7687                         if (t.theme.execCommand && t.theme.execCommand(cmd, ui, val)) {\r
7688                                 t.onExecCommand.dispatch(t, cmd, ui, val, a);\r
7689                                 return true;\r
7690                         }\r
7691 \r
7692                         // Editor commands\r
7693                         if (t.editorCommands.execCommand(cmd, ui, val)) {\r
7694                                 t.onExecCommand.dispatch(t, cmd, ui, val, a);\r
7695                                 return true;\r
7696                         }\r
7697 \r
7698                         // Browser commands\r
7699                         t.getDoc().execCommand(cmd, ui, val);\r
7700                         t.onExecCommand.dispatch(t, cmd, ui, val, a);\r
7701                 },\r
7702 \r
7703                 queryCommandState : function(c) {\r
7704                         var t = this, o, s;\r
7705 \r
7706                         // Is hidden then return undefined\r
7707                         if (t._isHidden())\r
7708                                 return;\r
7709 \r
7710                         // Registred commands\r
7711                         if (o = t.queryStateCommands[c]) {\r
7712                                 s = o.func.call(o.scope);\r
7713 \r
7714                                 // Fall though on true\r
7715                                 if (s !== true)\r
7716                                         return s;\r
7717                         }\r
7718 \r
7719                         // Registred commands\r
7720                         o = t.editorCommands.queryCommandState(c);\r
7721                         if (o !== -1)\r
7722                                 return o;\r
7723 \r
7724                         // Browser commands\r
7725                         try {\r
7726                                 return this.getDoc().queryCommandState(c);\r
7727                         } catch (ex) {\r
7728                                 // Fails sometimes see bug: 1896577\r
7729                         }\r
7730                 },\r
7731 \r
7732                 queryCommandValue : function(c) {\r
7733                         var t = this, o, s;\r
7734 \r
7735                         // Is hidden then return undefined\r
7736                         if (t._isHidden())\r
7737                                 return;\r
7738 \r
7739                         // Registred commands\r
7740                         if (o = t.queryValueCommands[c]) {\r
7741                                 s = o.func.call(o.scope);\r
7742 \r
7743                                 // Fall though on true\r
7744                                 if (s !== true)\r
7745                                         return s;\r
7746                         }\r
7747 \r
7748                         // Registred commands\r
7749                         o = t.editorCommands.queryCommandValue(c);\r
7750                         if (is(o))\r
7751                                 return o;\r
7752 \r
7753                         // Browser commands\r
7754                         try {\r
7755                                 return this.getDoc().queryCommandValue(c);\r
7756                         } catch (ex) {\r
7757                                 // Fails sometimes see bug: 1896577\r
7758                         }\r
7759                 },\r
7760 \r
7761                 show : function() {\r
7762                         var t = this;\r
7763 \r
7764                         DOM.show(t.getContainer());\r
7765                         DOM.hide(t.id);\r
7766                         t.load();\r
7767                 },\r
7768 \r
7769                 hide : function() {\r
7770                         var t = this, d = t.getDoc();\r
7771 \r
7772                         // Fixed bug where IE has a blinking cursor left from the editor\r
7773                         if (isIE && d)\r
7774                                 d.execCommand('SelectAll');\r
7775 \r
7776                         // We must save before we hide so Safari doesn't crash\r
7777                         t.save();\r
7778                         DOM.hide(t.getContainer());\r
7779                         DOM.setStyle(t.id, 'display', t.orgDisplay);\r
7780                 },\r
7781 \r
7782                 isHidden : function() {\r
7783                         return !DOM.isHidden(this.id);\r
7784                 },\r
7785 \r
7786                 setProgressState : function(b, ti, o) {\r
7787                         this.onSetProgressState.dispatch(this, b, ti, o);\r
7788 \r
7789                         return b;\r
7790                 },\r
7791 \r
7792                 resizeToContent : function() {\r
7793                         var t = this;\r
7794 \r
7795                         DOM.setStyle(t.id + "_ifr", 'height', t.getBody().scrollHeight);\r
7796                 },\r
7797 \r
7798                 load : function(o) {\r
7799                         var t = this, e = t.getElement(), h;\r
7800 \r
7801                         if (e) {\r
7802                                 o = o || {};\r
7803                                 o.load = true;\r
7804 \r
7805                                 h = t.setContent(is(e.value) ? e.value : e.innerHTML, o);\r
7806                                 o.element = e;\r
7807 \r
7808                                 if (!o.no_events)\r
7809                                         t.onLoadContent.dispatch(t, o);\r
7810 \r
7811                                 o.element = e = null;\r
7812 \r
7813                                 return h;\r
7814                         }\r
7815                 },\r
7816 \r
7817                 save : function(o) {\r
7818                         var t = this, e = t.getElement(), h, f;\r
7819 \r
7820                         if (!e || !t.initialized)\r
7821                                 return;\r
7822 \r
7823                         o = o || {};\r
7824                         o.save = true;\r
7825 \r
7826                         // Add undo level will trigger onchange event\r
7827                         if (!o.no_events) {\r
7828                                 t.undoManager.typing = 0;\r
7829                                 t.undoManager.add();\r
7830                         }\r
7831 \r
7832                         o.element = e;\r
7833                         h = o.content = t.getContent(o);\r
7834 \r
7835                         if (!o.no_events)\r
7836                                 t.onSaveContent.dispatch(t, o);\r
7837 \r
7838                         h = o.content;\r
7839 \r
7840                         if (!/TEXTAREA|INPUT/i.test(e.nodeName)) {\r
7841                                 e.innerHTML = h;\r
7842 \r
7843                                 // Update hidden form element\r
7844                                 if (f = DOM.getParent(t.id, 'form')) {\r
7845                                         each(f.elements, function(e) {\r
7846                                                 if (e.name == t.id) {\r
7847                                                         e.value = h;\r
7848                                                         return false;\r
7849                                                 }\r
7850                                         });\r
7851                                 }\r
7852                         } else\r
7853                                 e.value = h;\r
7854 \r
7855                         o.element = e = null;\r
7856 \r
7857                         return h;\r
7858                 },\r
7859 \r
7860                 setContent : function(h, o) {\r
7861                         var t = this;\r
7862 \r
7863                         o = o || {};\r
7864                         o.format = o.format || 'html';\r
7865                         o.set = true;\r
7866                         o.content = h;\r
7867 \r
7868                         if (!o.no_events)\r
7869                                 t.onBeforeSetContent.dispatch(t, o);\r
7870 \r
7871                         // Padd empty content in Gecko and Safari. Commands will otherwise fail on the content\r
7872                         // It will also be impossible to place the caret in the editor unless there is a BR element present\r
7873                         if (!tinymce.isIE && (h.length === 0 || /^\s+$/.test(h))) {\r
7874                                 o.content = t.dom.setHTML(t.getBody(), '<br mce_bogus="1" />');\r
7875                                 o.format = 'raw';\r
7876                         }\r
7877 \r
7878                         o.content = t.dom.setHTML(t.getBody(), tinymce.trim(o.content));\r
7879 \r
7880                         if (o.format != 'raw' && t.settings.cleanup) {\r
7881                                 o.getInner = true;\r
7882                                 o.content = t.dom.setHTML(t.getBody(), t.serializer.serialize(t.getBody(), o));\r
7883                         }\r
7884 \r
7885                         if (!o.no_events)\r
7886                                 t.onSetContent.dispatch(t, o);\r
7887 \r
7888                         return o.content;\r
7889                 },\r
7890 \r
7891                 getContent : function(o) {\r
7892                         var t = this, h;\r
7893 \r
7894                         o = o || {};\r
7895                         o.format = o.format || 'html';\r
7896                         o.get = true;\r
7897 \r
7898                         if (!o.no_events)\r
7899                                 t.onBeforeGetContent.dispatch(t, o);\r
7900 \r
7901                         if (o.format != 'raw' && t.settings.cleanup) {\r
7902                                 o.getInner = true;\r
7903                                 h = t.serializer.serialize(t.getBody(), o);\r
7904                         } else\r
7905                                 h = t.getBody().innerHTML;\r
7906 \r
7907                         h = h.replace(/^\s*|\s*$/g, '');\r
7908                         o.content = h;\r
7909 \r
7910                         if (!o.no_events)\r
7911                                 t.onGetContent.dispatch(t, o);\r
7912 \r
7913                         return o.content;\r
7914                 },\r
7915 \r
7916                 isDirty : function() {\r
7917                         var t = this;\r
7918 \r
7919                         return tinymce.trim(t.startContent) != tinymce.trim(t.getContent({format : 'raw', no_events : 1})) && !t.isNotDirty;\r
7920                 },\r
7921 \r
7922                 getContainer : function() {\r
7923                         var t = this;\r
7924 \r
7925                         if (!t.container)\r
7926                                 t.container = DOM.get(t.editorContainer || t.id + '_parent');\r
7927 \r
7928                         return t.container;\r
7929                 },\r
7930 \r
7931                 getContentAreaContainer : function() {\r
7932                         return this.contentAreaContainer;\r
7933                 },\r
7934 \r
7935                 getElement : function() {\r
7936                         return DOM.get(this.settings.content_element || this.id);\r
7937                 },\r
7938 \r
7939                 getWin : function() {\r
7940                         var t = this, e;\r
7941 \r
7942                         if (!t.contentWindow) {\r
7943                                 e = DOM.get(t.id + "_ifr");\r
7944 \r
7945                                 if (e)\r
7946                                         t.contentWindow = e.contentWindow;\r
7947                         }\r
7948 \r
7949                         return t.contentWindow;\r
7950                 },\r
7951 \r
7952                 getDoc : function() {\r
7953                         var t = this, w;\r
7954 \r
7955                         if (!t.contentDocument) {\r
7956                                 w = t.getWin();\r
7957 \r
7958                                 if (w)\r
7959                                         t.contentDocument = w.document;\r
7960                         }\r
7961 \r
7962                         return t.contentDocument;\r
7963                 },\r
7964 \r
7965                 getBody : function() {\r
7966                         return this.bodyElement || this.getDoc().body;\r
7967                 },\r
7968 \r
7969                 convertURL : function(u, n, e) {\r
7970                         var t = this, s = t.settings;\r
7971 \r
7972                         // Use callback instead\r
7973                         if (s.urlconverter_callback)\r
7974                                 return t.execCallback('urlconverter_callback', u, e, true, n);\r
7975 \r
7976                         // Don't convert link href since thats the CSS files that gets loaded into the editor also skip local file URLs\r
7977                         if (!s.convert_urls || (e && e.nodeName == 'LINK') || u.indexOf('file:') === 0)\r
7978                                 return u;\r
7979 \r
7980                         // Convert to relative\r
7981                         if (s.relative_urls)\r
7982                                 return t.documentBaseURI.toRelative(u);\r
7983 \r
7984                         // Convert to absolute\r
7985                         u = t.documentBaseURI.toAbsolute(u, s.remove_script_host);\r
7986 \r
7987                         return u;\r
7988                 },\r
7989 \r
7990                 addVisual : function(e) {\r
7991                         var t = this, s = t.settings;\r
7992 \r
7993                         e = e || t.getBody();\r
7994 \r
7995                         if (!is(t.hasVisual))\r
7996                                 t.hasVisual = s.visual;\r
7997 \r
7998                         each(t.dom.select('table,a', e), function(e) {\r
7999                                 var v;\r
8000 \r
8001                                 switch (e.nodeName) {\r
8002                                         case 'TABLE':\r
8003                                                 v = t.dom.getAttrib(e, 'border');\r
8004 \r
8005                                                 if (!v || v == '0') {\r
8006                                                         if (t.hasVisual)\r
8007                                                                 t.dom.addClass(e, s.visual_table_class);\r
8008                                                         else\r
8009                                                                 t.dom.removeClass(e, s.visual_table_class);\r
8010                                                 }\r
8011 \r
8012                                                 return;\r
8013 \r
8014                                         case 'A':\r
8015                                                 v = t.dom.getAttrib(e, 'name');\r
8016 \r
8017                                                 if (v) {\r
8018                                                         if (t.hasVisual)\r
8019                                                                 t.dom.addClass(e, 'mceItemAnchor');\r
8020                                                         else\r
8021                                                                 t.dom.removeClass(e, 'mceItemAnchor');\r
8022                                                 }\r
8023 \r
8024                                                 return;\r
8025                                 }\r
8026                         });\r
8027 \r
8028                         t.onVisualAid.dispatch(t, e, t.hasVisual);\r
8029                 },\r
8030 \r
8031                 remove : function() {\r
8032                         var t = this, e = t.getContainer();\r
8033 \r
8034                         t.removed = 1; // Cancels post remove event execution\r
8035                         t.hide();\r
8036 \r
8037                         t.execCallback('remove_instance_callback', t);\r
8038                         t.onRemove.dispatch(t);\r
8039 \r
8040                         // Clear all execCommand listeners this is required to avoid errors if the editor was removed inside another command\r
8041                         t.onExecCommand.listeners = [];\r
8042 \r
8043                         EditorManager.remove(t);\r
8044                         DOM.remove(e);\r
8045                 },\r
8046 \r
8047                 destroy : function(s) {\r
8048                         var t = this;\r
8049 \r
8050                         // One time is enough\r
8051                         if (t.destroyed)\r
8052                                 return;\r
8053 \r
8054                         if (!s) {\r
8055                                 tinymce.removeUnload(t.destroy);\r
8056                                 tinyMCE.onBeforeUnload.remove(t._beforeUnload);\r
8057 \r
8058                                 // Manual destroy\r
8059                                 if (t.theme.destroy)\r
8060                                         t.theme.destroy();\r
8061 \r
8062                                 // Destroy controls, selection and dom\r
8063                                 t.controlManager.destroy();\r
8064                                 t.selection.destroy();\r
8065                                 t.dom.destroy();\r
8066 \r
8067                                 // Remove all events\r
8068 \r
8069                                 // Don't clear the window or document if content editable\r
8070                                 // is enabled since other instances might still be present\r
8071                                 if (!t.settings.content_editable) {\r
8072                                         Event.clear(t.getWin());\r
8073                                         Event.clear(t.getDoc());\r
8074                                 }\r
8075 \r
8076                                 Event.clear(t.getBody());\r
8077                                 Event.clear(t.formElement);\r
8078                         }\r
8079 \r
8080                         if (t.formElement) {\r
8081                                 t.formElement.submit = t.formElement._mceOldSubmit;\r
8082                                 t.formElement._mceOldSubmit = null;\r
8083                         }\r
8084 \r
8085                         t.contentAreaContainer = t.formElement = t.container = t.settings.content_element = t.bodyElement = t.contentDocument = t.contentWindow = null;\r
8086 \r
8087                         if (t.selection)\r
8088                                 t.selection = t.selection.win = t.selection.dom = t.selection.dom.doc = null;\r
8089 \r
8090                         t.destroyed = 1;\r
8091                 },\r
8092 \r
8093                 // Internal functions\r
8094 \r
8095                 _addEvents : function() {\r
8096                         // 'focus', 'blur', 'dblclick', 'beforedeactivate', submit, reset\r
8097                         var t = this, i, s = t.settings, lo = {\r
8098                                 mouseup : 'onMouseUp',\r
8099                                 mousedown : 'onMouseDown',\r
8100                                 click : 'onClick',\r
8101                                 keyup : 'onKeyUp',\r
8102                                 keydown : 'onKeyDown',\r
8103                                 keypress : 'onKeyPress',\r
8104                                 submit : 'onSubmit',\r
8105                                 reset : 'onReset',\r
8106                                 contextmenu : 'onContextMenu',\r
8107                                 dblclick : 'onDblClick',\r
8108                                 paste : 'onPaste' // Doesn't work in all browsers yet\r
8109                         };\r
8110 \r
8111                         function eventHandler(e, o) {\r
8112                                 var ty = e.type;\r
8113 \r
8114                                 // Don't fire events when it's removed\r
8115                                 if (t.removed)\r
8116                                         return;\r
8117 \r
8118                                 // Generic event handler\r
8119                                 if (t.onEvent.dispatch(t, e, o) !== false) {\r
8120                                         // Specific event handler\r
8121                                         t[lo[e.fakeType || e.type]].dispatch(t, e, o);\r
8122                                 }\r
8123                         };\r
8124 \r
8125                         // Add DOM events\r
8126                         each(lo, function(v, k) {\r
8127                                 switch (k) {\r
8128                                         case 'contextmenu':\r
8129                                                 if (tinymce.isOpera) {\r
8130                                                         // Fake contextmenu on Opera\r
8131                                                         Event.add(t.getBody(), 'mousedown', function(e) {\r
8132                                                                 if (e.ctrlKey) {\r
8133                                                                         e.fakeType = 'contextmenu';\r
8134                                                                         eventHandler(e);\r
8135                                                                 }\r
8136                                                         });\r
8137                                                 } else\r
8138                                                         Event.add(t.getBody(), k, eventHandler);\r
8139                                                 break;\r
8140 \r
8141                                         case 'paste':\r
8142                                                 Event.add(t.getBody(), k, function(e) {\r
8143                                                         var tx, h, el, r;\r
8144 \r
8145                                                         // Get plain text data\r
8146                                                         if (e.clipboardData)\r
8147                                                                 tx = e.clipboardData.getData('text/plain');\r
8148                                                         else if (tinymce.isIE)\r
8149                                                                 tx = t.getWin().clipboardData.getData('Text');\r
8150 \r
8151                                                         // Get HTML data\r
8152                                                         /*if (tinymce.isIE) {\r
8153                                                                 el = DOM.add(DOM.doc.body, 'div', {style : 'visibility:hidden;overflow:hidden;position:absolute;width:1px;height:1px'});\r
8154                                                                 r = DOM.doc.body.createTextRange();\r
8155                                                                 r.moveToElementText(el);\r
8156                                                                 r.execCommand('Paste');\r
8157                                                                 h = el.innerHTML;\r
8158                                                                 DOM.remove(el);\r
8159                                                         }*/\r
8160 \r
8161                                                         eventHandler(e, {text : tx, html : h});\r
8162                                                 });\r
8163                                                 break;\r
8164 \r
8165                                         case 'submit':\r
8166                                         case 'reset':\r
8167                                                 Event.add(t.getElement().form || DOM.getParent(t.id, 'form'), k, eventHandler);\r
8168                                                 break;\r
8169 \r
8170                                         default:\r
8171                                                 Event.add(s.content_editable ? t.getBody() : t.getDoc(), k, eventHandler);\r
8172                                 }\r
8173                         });\r
8174 \r
8175                         Event.add(s.content_editable ? t.getBody() : (isGecko ? t.getDoc() : t.getWin()), 'focus', function(e) {\r
8176                                 t.focus(true);\r
8177                         });\r
8178 \r
8179                         \r
8180                         // Fixes bug where a specified document_base_uri could result in broken images\r
8181                         // This will also fix drag drop of images in Gecko\r
8182                         if (tinymce.isGecko) {\r
8183                                 // Convert all images to absolute URLs\r
8184 /*                              t.onSetContent.add(function(ed, o) {\r
8185                                         each(ed.dom.select('img'), function(e) {\r
8186                                                 var v;\r
8187 \r
8188                                                 if (v = e.getAttribute('mce_src'))\r
8189                                                         e.src = t.documentBaseURI.toAbsolute(v);\r
8190                                         })\r
8191                                 });*/\r
8192 \r
8193                                 Event.add(t.getDoc(), 'DOMNodeInserted', function(e) {\r
8194                                         var v;\r
8195 \r
8196                                         e = e.target;\r
8197 \r
8198                                         if (e.nodeType === 1 && e.nodeName === 'IMG' && (v = e.getAttribute('mce_src')))\r
8199                                                 e.src = t.documentBaseURI.toAbsolute(v);\r
8200                                 });\r
8201                         }\r
8202 \r
8203                         // Set various midas options in Gecko\r
8204                         if (isGecko) {\r
8205                                 function setOpts() {\r
8206                                         var t = this, d = t.getDoc(), s = t.settings;\r
8207 \r
8208                                         if (isGecko && !s.readonly) {\r
8209                                                 if (t._isHidden()) {\r
8210                                                         try {\r
8211                                                                 if (!s.content_editable)\r
8212                                                                         d.designMode = 'On';\r
8213                                                         } catch (ex) {\r
8214                                                                 // Fails if it's hidden\r
8215                                                         }\r
8216                                                 }\r
8217 \r
8218                                                 try {\r
8219                                                         // Try new Gecko method\r
8220                                                         d.execCommand("styleWithCSS", 0, false);\r
8221                                                 } catch (ex) {\r
8222                                                         // Use old method\r
8223                                                         if (!t._isHidden())\r
8224                                                                 try {d.execCommand("useCSS", 0, true);} catch (ex) {}\r
8225                                                 }\r
8226 \r
8227                                                 if (!s.table_inline_editing)\r
8228                                                         try {d.execCommand('enableInlineTableEditing', false, false);} catch (ex) {}\r
8229 \r
8230                                                 if (!s.object_resizing)\r
8231                                                         try {d.execCommand('enableObjectResizing', false, false);} catch (ex) {}\r
8232                                         }\r
8233                                 };\r
8234 \r
8235                                 t.onBeforeExecCommand.add(setOpts);\r
8236                                 t.onMouseDown.add(setOpts);\r
8237                         }\r
8238 \r
8239                         // Add node change handlers\r
8240                         t.onMouseUp.add(t.nodeChanged);\r
8241                         t.onClick.add(t.nodeChanged);\r
8242                         t.onKeyUp.add(function(ed, e) {\r
8243                                 var c = e.keyCode;\r
8244 \r
8245                                 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
8246                                         t.nodeChanged();\r
8247                         });\r
8248 \r
8249                         // Add reset handler\r
8250                         t.onReset.add(function() {\r
8251                                 t.setContent(t.startContent, {format : 'raw'});\r
8252                         });\r
8253 \r
8254                         if (t.getParam('tab_focus')) {\r
8255                                 function tabCancel(ed, e) {\r
8256                                         if (e.keyCode === 9)\r
8257                                                 return Event.cancel(e);\r
8258                                 };\r
8259 \r
8260                                 function tabHandler(ed, e) {\r
8261                                         var x, i, f, el, v;\r
8262 \r
8263                                         function find(d) {\r
8264                                                 f = DOM.getParent(ed.id, 'form');\r
8265                                                 el = f.elements;\r
8266 \r
8267                                                 if (f) {\r
8268                                                         each(el, function(e, i) {\r
8269                                                                 if (e.id == ed.id) {\r
8270                                                                         x = i;\r
8271                                                                         return false;\r
8272                                                                 }\r
8273                                                         });\r
8274 \r
8275                                                         if (d > 0) {\r
8276                                                                 for (i = x + 1; i < el.length; i++) {\r
8277                                                                         if (el[i].type != 'hidden')\r
8278                                                                                 return el[i];\r
8279                                                                 }\r
8280                                                         } else {\r
8281                                                                 for (i = x - 1; i >= 0; i--) {\r
8282                                                                         if (el[i].type != 'hidden')\r
8283                                                                                 return el[i];\r
8284                                                                 }\r
8285                                                         }\r
8286                                                 }\r
8287 \r
8288                                                 return null;\r
8289                                         };\r
8290 \r
8291                                         if (e.keyCode === 9) {\r
8292                                                 v = explode(ed.getParam('tab_focus'));\r
8293 \r
8294                                                 if (v.length == 1) {\r
8295                                                         v[1] = v[0];\r
8296                                                         v[0] = ':prev';\r
8297                                                 }\r
8298 \r
8299                                                 // Find element to focus\r
8300                                                 if (e.shiftKey) {\r
8301                                                         if (v[0] == ':prev')\r
8302                                                                 el = find(-1);\r
8303                                                         else\r
8304                                                                 el = DOM.get(v[0]);\r
8305                                                 } else {\r
8306                                                         if (v[1] == ':next')\r
8307                                                                 el = find(1);\r
8308                                                         else\r
8309                                                                 el = DOM.get(v[1]);\r
8310                                                 }\r
8311 \r
8312                                                 if (el) {\r
8313                                                         if (ed = EditorManager.get(el.id || el.name))\r
8314                                                                 ed.focus();\r
8315                                                         else\r
8316                                                                 window.setTimeout(function() {window.focus();el.focus();}, 10);\r
8317 \r
8318                                                         return Event.cancel(e);\r
8319                                                 }\r
8320                                         }\r
8321                                 };\r
8322 \r
8323                                 t.onKeyUp.add(tabCancel);\r
8324 \r
8325                                 if (isGecko) {\r
8326                                         t.onKeyPress.add(tabHandler);\r
8327                                         t.onKeyDown.add(tabCancel);\r
8328                                 } else\r
8329                                         t.onKeyDown.add(tabHandler);\r
8330                         }\r
8331 \r
8332                         // Add shortcuts\r
8333                         if (s.custom_shortcuts) {\r
8334                                 if (s.custom_undo_redo_keyboard_shortcuts) {\r
8335                                         t.addShortcut('ctrl+z', t.getLang('undo_desc'), 'Undo');\r
8336                                         t.addShortcut('ctrl+y', t.getLang('redo_desc'), 'Redo');\r
8337                                 }\r
8338 \r
8339                                 // Add default shortcuts for gecko\r
8340                                 if (isGecko) {\r
8341                                         t.addShortcut('ctrl+b', t.getLang('bold_desc'), 'Bold');\r
8342                                         t.addShortcut('ctrl+i', t.getLang('italic_desc'), 'Italic');\r
8343                                         t.addShortcut('ctrl+u', t.getLang('underline_desc'), 'Underline');\r
8344                                 }\r
8345 \r
8346                                 // BlockFormat shortcuts keys\r
8347                                 for (i=1; i<=6; i++)\r
8348                                         t.addShortcut('ctrl+' + i, '', ['FormatBlock', false, '<h' + i + '>']);\r
8349 \r
8350                                 t.addShortcut('ctrl+7', '', ['FormatBlock', false, '<p>']);\r
8351                                 t.addShortcut('ctrl+8', '', ['FormatBlock', false, '<div>']);\r
8352                                 t.addShortcut('ctrl+9', '', ['FormatBlock', false, '<address>']);\r
8353 \r
8354                                 function find(e) {\r
8355                                         var v = null;\r
8356 \r
8357                                         if (!e.altKey && !e.ctrlKey && !e.metaKey)\r
8358                                                 return v;\r
8359 \r
8360                                         each(t.shortcuts, function(o) {\r
8361                                                 if (tinymce.isMac && o.ctrl != e.metaKey)\r
8362                                                         return;\r
8363                                                 else if (!tinymce.isMac && o.ctrl != e.ctrlKey)\r
8364                                                         return;\r
8365 \r
8366                                                 if (o.alt != e.altKey)\r
8367                                                         return;\r
8368 \r
8369                                                 if (o.shift != e.shiftKey)\r
8370                                                         return;\r
8371 \r
8372                                                 if (e.keyCode == o.keyCode || (e.charCode && e.charCode == o.charCode)) {\r
8373                                                         v = o;\r
8374                                                         return false;\r
8375                                                 }\r
8376                                         });\r
8377 \r
8378                                         return v;\r
8379                                 };\r
8380 \r
8381                                 t.onKeyUp.add(function(ed, e) {\r
8382                                         var o = find(e);\r
8383 \r
8384                                         if (o)\r
8385                                                 return Event.cancel(e);\r
8386                                 });\r
8387 \r
8388                                 t.onKeyPress.add(function(ed, e) {\r
8389                                         var o = find(e);\r
8390 \r
8391                                         if (o)\r
8392                                                 return Event.cancel(e);\r
8393                                 });\r
8394 \r
8395                                 t.onKeyDown.add(function(ed, e) {\r
8396                                         var o = find(e);\r
8397 \r
8398                                         if (o) {\r
8399                                                 o.func.call(o.scope);\r
8400                                                 return Event.cancel(e);\r
8401                                         }\r
8402                                 });\r
8403                         }\r
8404 \r
8405                         if (tinymce.isIE) {\r
8406                                 // Fix so resize will only update the width and height attributes not the styles of an image\r
8407                                 // It will also block mceItemNoResize items\r
8408                                 Event.add(t.getDoc(), 'controlselect', function(e) {\r
8409                                         var re = t.resizeInfo, cb;\r
8410 \r
8411                                         e = e.target;\r
8412 \r
8413                                         // Don't do this action for non image elements\r
8414                                         if (e.nodeName !== 'IMG')\r
8415                                                 return;\r
8416 \r
8417                                         if (re)\r
8418                                                 Event.remove(re.node, re.ev, re.cb);\r
8419 \r
8420                                         if (!t.dom.hasClass(e, 'mceItemNoResize')) {\r
8421                                                 ev = 'resizeend';\r
8422                                                 cb = Event.add(e, ev, function(e) {\r
8423                                                         var v;\r
8424 \r
8425                                                         e = e.target;\r
8426 \r
8427                                                         if (v = t.dom.getStyle(e, 'width')) {\r
8428                                                                 t.dom.setAttrib(e, 'width', v.replace(/[^0-9%]+/g, ''));\r
8429                                                                 t.dom.setStyle(e, 'width', '');\r
8430                                                         }\r
8431 \r
8432                                                         if (v = t.dom.getStyle(e, 'height')) {\r
8433                                                                 t.dom.setAttrib(e, 'height', v.replace(/[^0-9%]+/g, ''));\r
8434                                                                 t.dom.setStyle(e, 'height', '');\r
8435                                                         }\r
8436                                                 });\r
8437                                         } else {\r
8438                                                 ev = 'resizestart';\r
8439                                                 cb = Event.add(e, 'resizestart', Event.cancel, Event);\r
8440                                         }\r
8441 \r
8442                                         re = t.resizeInfo = {\r
8443                                                 node : e,\r
8444                                                 ev : ev,\r
8445                                                 cb : cb\r
8446                                         };\r
8447                                 });\r
8448 \r
8449                                 t.onKeyDown.add(function(ed, e) {\r
8450                                         switch (e.keyCode) {\r
8451                                                 case 8:\r
8452                                                         // Fix IE control + backspace browser bug\r
8453                                                         if (t.selection.getRng().item) {\r
8454                                                                 t.selection.getRng().item(0).removeNode();\r
8455                                                                 return Event.cancel(e);\r
8456                                                         }\r
8457                                         }\r
8458                                 });\r
8459                         }\r
8460 \r
8461                         if (tinymce.isOpera) {\r
8462                                 t.onClick.add(function(ed, e) {\r
8463                                         Event.prevent(e);\r
8464                                 });\r
8465                         }\r
8466 \r
8467                         // Add custom undo/redo handlers\r
8468                         if (s.custom_undo_redo) {\r
8469                                 function addUndo() {\r
8470                                         t.undoManager.typing = 0;\r
8471                                         t.undoManager.add();\r
8472                                 };\r
8473 \r
8474                                 // Add undo level on editor blur\r
8475                                 if (tinymce.isIE) {\r
8476                                         Event.add(t.getWin(), 'blur', function(e) {\r
8477                                                 var n;\r
8478 \r
8479                                                 // Check added for fullscreen bug\r
8480                                                 if (t.selection) {\r
8481                                                         n = t.selection.getNode();\r
8482 \r
8483                                                         // Add undo level is selection was lost to another document\r
8484                                                         if (!t.removed && n.ownerDocument && n.ownerDocument != t.getDoc())\r
8485                                                                 addUndo();\r
8486                                                 }\r
8487                                         });\r
8488                                 } else {\r
8489                                         Event.add(t.getDoc(), 'blur', function() {\r
8490                                                 if (t.selection && !t.removed)\r
8491                                                         addUndo();\r
8492                                         });\r
8493                                 }\r
8494 \r
8495                                 t.onMouseDown.add(addUndo);\r
8496 \r
8497                                 t.onKeyUp.add(function(ed, e) {\r
8498                                         if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45 || e.ctrlKey) {\r
8499                                                 t.undoManager.typing = 0;\r
8500                                                 t.undoManager.add();\r
8501                                         }\r
8502                                 });\r
8503 \r
8504                                 t.onKeyDown.add(function(ed, e) {\r
8505                                         // Is caracter positon keys\r
8506                                         if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45) {\r
8507                                                 if (t.undoManager.typing) {\r
8508                                                         t.undoManager.add();\r
8509                                                         t.undoManager.typing = 0;\r
8510                                                 }\r
8511 \r
8512                                                 return;\r
8513                                         }\r
8514 \r
8515                                         if (!t.undoManager.typing) {\r
8516                                                 t.undoManager.add();\r
8517                                                 t.undoManager.typing = 1;\r
8518                                         }\r
8519                                 });\r
8520                         }\r
8521                 },\r
8522 \r
8523                 _convertInlineElements : function() {\r
8524                         var t = this, s = t.settings, dom = t.dom, v, e, na, st, sp;\r
8525 \r
8526                         function convert(ed, o) {\r
8527                                 if (!s.inline_styles)\r
8528                                         return;\r
8529 \r
8530                                 if (o.get) {\r
8531                                         each(t.dom.select('table,u,strike', o.node), function(n) {\r
8532                                                 switch (n.nodeName) {\r
8533                                                         case 'TABLE':\r
8534                                                                 if (v = dom.getAttrib(n, 'height')) {\r
8535                                                                         dom.setStyle(n, 'height', v);\r
8536                                                                         dom.setAttrib(n, 'height', '');\r
8537                                                                 }\r
8538                                                                 break;\r
8539 \r
8540                                                         case 'U':\r
8541                                                         case 'STRIKE':\r
8542                                                                 //sp = dom.create('span', {style : dom.getAttrib(n, 'style')});\r
8543                                                                 n.style.textDecoration = n.nodeName == 'U' ? 'underline' : 'line-through';\r
8544                                                                 dom.setAttrib(n, 'mce_style', '');\r
8545                                                                 dom.setAttrib(n, 'mce_name', 'span');\r
8546                                                                 break;\r
8547                                                 }\r
8548                                         });\r
8549                                 } else if (o.set) {\r
8550                                         each(t.dom.select('table,span', o.node).reverse(), function(n) {\r
8551                                                 if (n.nodeName == 'TABLE') {\r
8552                                                         if (v = dom.getStyle(n, 'height'))\r
8553                                                                 dom.setAttrib(n, 'height', v.replace(/[^0-9%]+/g, ''));\r
8554                                                 } else {\r
8555                                                         // Convert spans to elements\r
8556                                                         if (n.style.textDecoration == 'underline')\r
8557                                                                 na = 'u';\r
8558                                                         else if (n.style.textDecoration == 'line-through')\r
8559                                                                 na = 'strike';\r
8560                                                         else\r
8561                                                                 na = '';\r
8562 \r
8563                                                         if (na) {\r
8564                                                                 n.style.textDecoration = '';\r
8565                                                                 dom.setAttrib(n, 'mce_style', '');\r
8566 \r
8567                                                                 e = dom.create(na, {\r
8568                                                                         style : dom.getAttrib(n, 'style')\r
8569                                                                 });\r
8570 \r
8571                                                                 dom.replace(e, n, 1);\r
8572                                                         }\r
8573                                                 }\r
8574                                         });\r
8575                                 }\r
8576                         };\r
8577 \r
8578                         t.onPreProcess.add(convert);\r
8579 \r
8580                         if (!s.cleanup_on_startup) {\r
8581                                 t.onSetContent.add(function(ed, o) {\r
8582                                         if (o.initial)\r
8583                                                 convert(t, {node : t.getBody(), set : 1});\r
8584                                 });\r
8585                         }\r
8586                 },\r
8587 \r
8588                 _convertFonts : function() {\r
8589                         var t = this, s = t.settings, dom = t.dom, fz, fzn, sl, cl;\r
8590 \r
8591                         // No need\r
8592                         if (!s.inline_styles)\r
8593                                 return;\r
8594 \r
8595                         // Font pt values and font size names\r
8596                         fz = [8, 10, 12, 14, 18, 24, 36];\r
8597                         fzn = ['xx-small', 'x-small','small','medium','large','x-large', 'xx-large'];\r
8598 \r
8599                         if (sl = s.font_size_style_values)\r
8600                                 sl = explode(sl);\r
8601 \r
8602                         if (cl = s.font_size_classes)\r
8603                                 cl = explode(cl);\r
8604 \r
8605                         function process(no) {\r
8606                                 var n, sp, nl, x;\r
8607 \r
8608                                 // Keep unit tests happy\r
8609                                 if (!s.inline_styles)\r
8610                                         return;\r
8611 \r
8612                                 nl = t.dom.select('font', no);\r
8613                                 for (x = nl.length - 1; x >= 0; x--) {\r
8614                                         n = nl[x];\r
8615 \r
8616                                         sp = dom.create('span', {\r
8617                                                 style : dom.getAttrib(n, 'style'),\r
8618                                                 'class' : dom.getAttrib(n, 'class')\r
8619                                         });\r
8620 \r
8621                                         dom.setStyles(sp, {\r
8622                                                 fontFamily : dom.getAttrib(n, 'face'),\r
8623                                                 color : dom.getAttrib(n, 'color'),\r
8624                                                 backgroundColor : n.style.backgroundColor\r
8625                                         });\r
8626 \r
8627                                         if (n.size) {\r
8628                                                 if (sl)\r
8629                                                         dom.setStyle(sp, 'fontSize', sl[parseInt(n.size) - 1]);\r
8630                                                 else\r
8631                                                         dom.setAttrib(sp, 'class', cl[parseInt(n.size) - 1]);\r
8632                                         }\r
8633 \r
8634                                         dom.setAttrib(sp, 'mce_style', '');\r
8635                                         dom.replace(sp, n, 1);\r
8636                                 }\r
8637                         };\r
8638 \r
8639                         // Run on cleanup\r
8640                         t.onPreProcess.add(function(ed, o) {\r
8641                                 if (o.get)\r
8642                                         process(o.node);\r
8643                         });\r
8644 \r
8645                         t.onSetContent.add(function(ed, o) {\r
8646                                 if (o.initial)\r
8647                                         process(o.node);\r
8648                         });\r
8649                 },\r
8650 \r
8651                 _isHidden : function() {\r
8652                         var s;\r
8653 \r
8654                         if (!isGecko)\r
8655                                 return 0;\r
8656 \r
8657                         // Weird, wheres that cursor selection?\r
8658                         s = this.selection.getSel();\r
8659                         return (!s || !s.rangeCount || s.rangeCount == 0);\r
8660                 },\r
8661 \r
8662                 // Fix for bug #1867292\r
8663                 _fixNesting : function(s) {\r
8664                         var d = [], i;\r
8665 \r
8666                         s = s.replace(/<(\/)?([^\s>]+)[^>]*?>/g, function(a, b, c) {\r
8667                                 var e;\r
8668 \r
8669                                 // Handle end element\r
8670                                 if (b === '/') {\r
8671                                         if (!d.length)\r
8672                                                 return '';\r
8673 \r
8674                                         if (c !== d[d.length - 1].tag) {\r
8675                                                 for (i=d.length - 1; i>=0; i--) {\r
8676                                                         if (d[i].tag === c) {\r
8677                                                                 d[i].close = 1;\r
8678                                                                 break;\r
8679                                                         }\r
8680                                                 }\r
8681 \r
8682                                                 return '';\r
8683                                         } else {\r
8684                                                 d.pop();\r
8685 \r
8686                                                 if (d.length && d[d.length - 1].close) {\r
8687                                                         a = a + '</' + d[d.length - 1].tag + '>';\r
8688                                                         d.pop();\r
8689                                                 }\r
8690                                         }\r
8691                                 } else {\r
8692                                         // Ignore these\r
8693                                         if (/^(br|hr|input|meta|img|link|param)$/i.test(c))\r
8694                                                 return a;\r
8695 \r
8696                                         // Ignore closed ones\r
8697                                         if (/\/>$/.test(a))\r
8698                                                 return a;\r
8699 \r
8700                                         d.push({tag : c}); // Push start element\r
8701                                 }\r
8702 \r
8703                                 return a;\r
8704                         });\r
8705 \r
8706                         // End all open tags\r
8707                         for (i=d.length - 1; i>=0; i--)\r
8708                                 s += '</' + d[i].tag + '>';\r
8709 \r
8710                         return s;\r
8711                 }\r
8712 \r
8713                 });\r
8714 })();\r
8715 \r
8716 /* file:jscripts/tiny_mce/classes/EditorCommands.js */\r
8717 \r
8718 (function() {\r
8719         var each = tinymce.each, isIE = tinymce.isIE, isGecko = tinymce.isGecko, isOpera = tinymce.isOpera, isWebKit = tinymce.isWebKit;\r
8720 \r
8721         function isBlock(n) {\r
8722                 return /^(H[1-6]|HR|P|DIV|ADDRESS|PRE|FORM|TABLE|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP)$/.test(n.nodeName);\r
8723         };\r
8724 \r
8725         tinymce.create('tinymce.EditorCommands', {\r
8726                 EditorCommands : function(ed) {\r
8727                         this.editor = ed;\r
8728                 },\r
8729 \r
8730                 execCommand : function(cmd, ui, val) {\r
8731                         var t = this, ed = t.editor, f;\r
8732 \r
8733                         switch (cmd) {\r
8734                                 case 'Cut':\r
8735                                 case 'Copy':\r
8736                                 case 'Paste':\r
8737                                         try {\r
8738                                                 ed.getDoc().execCommand(cmd, ui, val);\r
8739                                         } catch (ex) {\r
8740                                                 if (isGecko) {\r
8741                                                         ed.windowManager.confirm(ed.getLang('clipboard_msg'), function(s) {\r
8742                                                                 if (s)\r
8743                                                                         window.open('http://www.mozilla.org/editor/midasdemo/securityprefs.html', 'mceExternal');\r
8744                                                         });\r
8745                                                 } else\r
8746                                                         ed.windowManager.alert(ed.getLang('clipboard_no_support'));\r
8747                                         }\r
8748 \r
8749                                         return true;\r
8750 \r
8751                                 // Ignore these\r
8752                                 case 'mceResetDesignMode':\r
8753                                 case 'mceBeginUndoLevel':\r
8754                                         return true;\r
8755 \r
8756                                 // Ignore these\r
8757                                 case 'unlink':\r
8758                                         t.UnLink();\r
8759                                         return true;\r
8760 \r
8761                                 // Bundle these together\r
8762                                 case 'JustifyLeft':\r
8763                                 case 'JustifyCenter':\r
8764                                 case 'JustifyRight':\r
8765                                 case 'JustifyFull':\r
8766                                         t.mceJustify(cmd, cmd.substring(7).toLowerCase());\r
8767                                         return true;\r
8768 \r
8769                                 case 'mceEndUndoLevel':\r
8770                                 case 'mceAddUndoLevel':\r
8771                                         ed.undoManager.add();\r
8772                                         return true;\r
8773 \r
8774                                 default:\r
8775                                         f = this[cmd];\r
8776 \r
8777                                         if (f) {\r
8778                                                 f.call(this, ui, val);\r
8779                                                 return true;\r
8780                                         }\r
8781                         }\r
8782 \r
8783                         return false;\r
8784                 },\r
8785 \r
8786                 Indent : function() {\r
8787                         var ed = this.editor, d = ed.dom, s = ed.selection, e, iv, iu;\r
8788 \r
8789                         // Setup indent level\r
8790                         iv = ed.settings.indentation;\r
8791                         iu = /[a-z%]+$/i.exec(iv);\r
8792                         iv = parseInt(iv);\r
8793 \r
8794                         if (ed.settings.inline_styles && (!this.queryStateInsertUnorderedList() && !this.queryStateInsertOrderedList())) {\r
8795                                 each(this._getSelectedBlocks(), function(e) {\r
8796                                         d.setStyle(e, 'paddingLeft', (parseInt(e.style.paddingLeft || 0) + iv) + iu);\r
8797                                 });\r
8798 \r
8799                                 return;\r
8800                         }\r
8801 \r
8802                         ed.getDoc().execCommand('Indent', false, null);\r
8803 \r
8804                         if (isIE) {\r
8805                                 d.getParent(s.getNode(), function(n) {\r
8806                                         if (n.nodeName == 'BLOCKQUOTE') {\r
8807                                                 n.dir = n.style.cssText = '';\r
8808                                         }\r
8809                                 });\r
8810                         }\r
8811                 },\r
8812 \r
8813                 Outdent : function() {\r
8814                         var ed = this.editor, d = ed.dom, s = ed.selection, e, v, iv, iu;\r
8815 \r
8816                         // Setup indent level\r
8817                         iv = ed.settings.indentation;\r
8818                         iu = /[a-z%]+$/i.exec(iv);\r
8819                         iv = parseInt(iv);\r
8820 \r
8821                         if (ed.settings.inline_styles && (!this.queryStateInsertUnorderedList() && !this.queryStateInsertOrderedList())) {\r
8822                                 each(this._getSelectedBlocks(), function(e) {\r
8823                                         v = Math.max(0, parseInt(e.style.paddingLeft || 0) - iv);\r
8824                                         d.setStyle(e, 'paddingLeft', v ? v + iu : '');\r
8825                                 });\r
8826 \r
8827                                 return;\r
8828                         }\r
8829 \r
8830                         ed.getDoc().execCommand('Outdent', false, null);\r
8831                 },\r
8832 \r
8833                 mceSetAttribute : function(u, v) {\r
8834                         var ed = this.editor, d = ed.dom, e;\r
8835 \r
8836                         if (e = d.getParent(ed.selection.getNode(), d.isBlock))\r
8837                                 d.setAttrib(e, v.name, v.value);\r
8838                 },\r
8839 \r
8840                 mceSetContent : function(u, v) {\r
8841                         this.editor.setContent(v);\r
8842                 },\r
8843 \r
8844                 mceToggleVisualAid : function() {\r
8845                         var ed = this.editor;\r
8846 \r
8847                         ed.hasVisual = !ed.hasVisual;\r
8848                         ed.addVisual();\r
8849                 },\r
8850 \r
8851                 mceReplaceContent : function(u, v) {\r
8852                         var s = this.editor.selection;\r
8853 \r
8854                         s.setContent(v.replace(/\{\$selection\}/g, s.getContent({format : 'text'})));\r
8855                 },\r
8856 \r
8857                 mceInsertLink : function(u, v) {\r
8858                         var ed = this.editor, s = ed.selection, e = ed.dom.getParent(s.getNode(), 'A');\r
8859 \r
8860                         if (tinymce.is(v, 'string'))\r
8861                                 v = {href : v};\r
8862 \r
8863                         function set(e) {\r
8864                                 each(v, function(v, k) {\r
8865                                         ed.dom.setAttrib(e, k, v);\r
8866                                 });\r
8867                         };\r
8868 \r
8869                         if (!e) {\r
8870                                 ed.execCommand('CreateLink', false, 'javascript:mctmp(0);');\r
8871                                 each(ed.dom.select('a'), function(e) {\r
8872                                         if (e.href == 'javascript:mctmp(0);')\r
8873                                                 set(e);\r
8874                                 });\r
8875                         } else {\r
8876                                 if (v.href)\r
8877                                         set(e);\r
8878                                 else\r
8879                                         ed.dom.remove(e, 1);\r
8880                         }\r
8881                 },\r
8882 \r
8883                 UnLink : function() {\r
8884                         var ed = this.editor, s = ed.selection;\r
8885 \r
8886                         if (s.isCollapsed())\r
8887                                 s.select(s.getNode());\r
8888 \r
8889                         ed.getDoc().execCommand('unlink', false, null);\r
8890                         s.collapse(0);\r
8891                 },\r
8892 \r
8893                 FontName : function(u, v) {\r
8894                         var t = this, ed = t.editor, s = ed.selection, e;\r
8895 \r
8896                         if (!v) {\r
8897                                 if (s.isCollapsed())\r
8898                                         s.select(s.getNode());\r
8899 \r
8900                                 t.RemoveFormat();\r
8901                         } else {\r
8902                                 if (ed.settings.convert_fonts_to_spans)\r
8903                                         t._applyInlineStyle('span', {style : {fontFamily : v}});\r
8904                                 else\r
8905                                         ed.getDoc().execCommand('FontName', false, v);\r
8906                         }\r
8907                 },\r
8908 \r
8909                 FontSize : function(u, v) {\r
8910                         var ed = this.editor, s = ed.settings, fc, fs;\r
8911 \r
8912                         // Use style options instead\r
8913                         if (s.convert_fonts_to_spans && v >= 1 && v <= 7) {\r
8914                                 fs = tinymce.explode(s.font_size_style_values);\r
8915                                 fc = tinymce.explode(s.font_size_classes);\r
8916 \r
8917                                 if (fc)\r
8918                                         v = fc[v - 1] || v;\r
8919                                 else\r
8920                                         v = fs[v - 1] || v;\r
8921                         }\r
8922 \r
8923                         if (v >= 1 && v <= 7)\r
8924                                 ed.getDoc().execCommand('FontSize', false, v);\r
8925                         else\r
8926                                 this._applyInlineStyle('span', {style : {fontSize : v}});\r
8927                 },\r
8928 \r
8929                 queryCommandValue : function(c) {\r
8930                         var f = this['queryValue' + c];\r
8931 \r
8932                         if (f)\r
8933                                 return f.call(this, c);\r
8934 \r
8935                         return false;\r
8936                 },\r
8937 \r
8938                 queryCommandState : function(cmd) {\r
8939                         var f;\r
8940 \r
8941                         switch (cmd) {\r
8942                                 // Bundle these together\r
8943                                 case 'JustifyLeft':\r
8944                                 case 'JustifyCenter':\r
8945                                 case 'JustifyRight':\r
8946                                 case 'JustifyFull':\r
8947                                         return this.queryStateJustify(cmd, cmd.substring(7).toLowerCase());\r
8948 \r
8949                                 default:\r
8950                                         if (f = this['queryState' + cmd])\r
8951                                                 return f.call(this, cmd);\r
8952                         }\r
8953 \r
8954                         return -1;\r
8955                 },\r
8956 \r
8957                 _queryState : function(c) {\r
8958                         try {\r
8959                                 return this.editor.getDoc().queryCommandState(c);\r
8960                         } catch (ex) {\r
8961                                 // Ignore exception\r
8962                         }\r
8963                 },\r
8964 \r
8965                 _queryVal : function(c) {\r
8966                         try {\r
8967                                 return this.editor.getDoc().queryCommandValue(c);\r
8968                         } catch (ex) {\r
8969                                 // Ignore exception\r
8970                         }\r
8971                 },\r
8972 \r
8973                 queryValueFontSize : function() {\r
8974                         var ed = this.editor, v = 0, p;\r
8975 \r
8976                         if (p = ed.dom.getParent(ed.selection.getNode(), 'SPAN'))\r
8977                                 v = p.style.fontSize;\r
8978 \r
8979                         if (!v && (isOpera || isWebKit)) {\r
8980                                 if (p = ed.dom.getParent(ed.selection.getNode(), 'FONT'))\r
8981                                         v = p.size;\r
8982 \r
8983                                 return v;\r
8984                         }\r
8985 \r
8986                         return v || this._queryVal('FontSize');\r
8987                 },\r
8988 \r
8989                 queryValueFontName : function() {\r
8990                         var ed = this.editor, v = 0, p;\r
8991 \r
8992                         if (p = ed.dom.getParent(ed.selection.getNode(), 'FONT'))\r
8993                                 v = p.face;\r
8994 \r
8995                         if (p = ed.dom.getParent(ed.selection.getNode(), 'SPAN'))\r
8996                                 v = p.style.fontFamily.replace(/, /g, ',').replace(/[\'\"]/g, '').toLowerCase();\r
8997 \r
8998                         if (!v)\r
8999                                 v = this._queryVal('FontName');\r
9000 \r
9001                         return v;\r
9002                 },\r
9003 \r
9004                 mceJustify : function(c, v) {\r
9005                         var ed = this.editor, se = ed.selection, n = se.getNode(), nn = n.nodeName, bl, nb, dom = ed.dom, rm;\r
9006 \r
9007                         if (ed.settings.inline_styles && this.queryStateJustify(c, v))\r
9008                                 rm = 1;\r
9009 \r
9010                         bl = dom.getParent(n, ed.dom.isBlock);\r
9011 \r
9012                         if (nn == 'IMG') {\r
9013                                 if (v == 'full')\r
9014                                         return;\r
9015 \r
9016                                 if (rm) {\r
9017                                         if (v == 'center')\r
9018                                                 dom.setStyle(bl || n.parentNode, 'textAlign', '');\r
9019 \r
9020                                         dom.setStyle(n, 'float', '');\r
9021                                         this.mceRepaint();\r
9022                                         return;\r
9023                                 }\r
9024 \r
9025                                 if (v == 'center') {\r
9026                                         // Do not change table elements\r
9027                                         if (bl && /^(TD|TH)$/.test(bl.nodeName))\r
9028                                                 bl = 0;\r
9029 \r
9030                                         if (!bl || bl.childNodes.length > 1) {\r
9031                                                 nb = dom.create('p');\r
9032                                                 nb.appendChild(n.cloneNode(false));\r
9033 \r
9034                                                 if (bl)\r
9035                                                         dom.insertAfter(nb, bl);\r
9036                                                 else\r
9037                                                         dom.insertAfter(nb, n);\r
9038 \r
9039                                                 dom.remove(n);\r
9040                                                 n = nb.firstChild;\r
9041                                                 bl = nb;\r
9042                                         }\r
9043 \r
9044                                         dom.setStyle(bl, 'textAlign', v);\r
9045                                         dom.setStyle(n, 'float', '');\r
9046                                 } else {\r
9047                                         dom.setStyle(n, 'float', v);\r
9048                                         dom.setStyle(bl || n.parentNode, 'textAlign', '');\r
9049                                 }\r
9050 \r
9051                                 this.mceRepaint();\r
9052                                 return;\r
9053                         }\r
9054 \r
9055                         // Handle the alignment outselfs, less quirks in all browsers\r
9056                         if (ed.settings.inline_styles && ed.settings.forced_root_block) {\r
9057                                 if (rm)\r
9058                                         v = '';\r
9059 \r
9060                                 each(this._getSelectedBlocks(dom.getParent(se.getStart(), dom.isBlock), dom.getParent(se.getEnd(), dom.isBlock)), function(e) {\r
9061                                         dom.setAttrib(e, 'align', '');\r
9062                                         dom.setStyle(e, 'textAlign', v == 'full' ? 'justify' : v);\r
9063                                 });\r
9064 \r
9065                                 return;\r
9066                         } else if (!rm)\r
9067                                 ed.getDoc().execCommand(c, false, null);\r
9068 \r
9069                         if (ed.settings.inline_styles) {\r
9070                                 if (rm) {\r
9071                                         dom.getParent(ed.selection.getNode(), function(n) {\r
9072                                                 if (n.style && n.style.textAlign)\r
9073                                                         dom.setStyle(n, 'textAlign', '');\r
9074                                         });\r
9075 \r
9076                                         return;\r
9077                                 }\r
9078 \r
9079                                 each(dom.select('*'), function(n) {\r
9080                                         var v = n.align;\r
9081 \r
9082                                         if (v) {\r
9083                                                 if (v == 'full')\r
9084                                                         v = 'justify';\r
9085 \r
9086                                                 dom.setStyle(n, 'textAlign', v);\r
9087                                                 dom.setAttrib(n, 'align', '');\r
9088                                         }\r
9089                                 });\r
9090                         }\r
9091                 },\r
9092 \r
9093                 mceSetCSSClass : function(u, v) {\r
9094                         this.mceSetStyleInfo(0, {command : 'setattrib', name : 'class', value : v});\r
9095                 },\r
9096 \r
9097                 getSelectedElement : function() {\r
9098                         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
9099 \r
9100                         if (se.isCollapsed() || r.item)\r
9101                                 return se.getNode();\r
9102 \r
9103                         // Setup regexp\r
9104                         re = ed.settings.merge_styles_invalid_parents;\r
9105                         if (tinymce.is(re, 'string'))\r
9106                                 re = new RegExp(re, 'i');\r
9107 \r
9108                         if (isIE) {\r
9109                                 r1 = r.duplicate();\r
9110                                 r1.collapse(true);\r
9111                                 sc = r1.parentElement();\r
9112 \r
9113                                 r2 = r.duplicate();\r
9114                                 r2.collapse(false);\r
9115                                 ec = r2.parentElement();\r
9116 \r
9117                                 if (sc != ec) {\r
9118                                         r1.move('character', 1);\r
9119                                         sc = r1.parentElement();\r
9120                                 }\r
9121 \r
9122                                 if (sc == ec) {\r
9123                                         r1 = r.duplicate();\r
9124                                         r1.moveToElementText(sc);\r
9125 \r
9126                                         if (r1.compareEndPoints('StartToStart', r) == 0 && r1.compareEndPoints('EndToEnd', r) == 0)\r
9127                                                 return re && re.test(sc.nodeName) ? null : sc;\r
9128                                 }\r
9129                         } else {\r
9130                                 function getParent(n) {\r
9131                                         return dom.getParent(n, function(n) {return n.nodeType == 1;});\r
9132                                 };\r
9133 \r
9134                                 sc = r.startContainer;\r
9135                                 ec = r.endContainer;\r
9136                                 so = r.startOffset;\r
9137                                 eo = r.endOffset;\r
9138 \r
9139                                 if (!r.collapsed) {\r
9140                                         if (sc == ec) {\r
9141                                                 if (so - eo < 2) {\r
9142                                                         if (sc.hasChildNodes()) {\r
9143                                                                 sp = sc.childNodes[so];\r
9144                                                                 return re && re.test(sp.nodeName) ? null : sp;\r
9145                                                         }\r
9146                                                 }\r
9147                                         }\r
9148                                 }\r
9149 \r
9150                                 if (sc.nodeType != 3 || ec.nodeType != 3)\r
9151                                         return null;\r
9152 \r
9153                                 if (so == 0) {\r
9154                                         sp = getParent(sc);\r
9155 \r
9156                                         if (sp && sp.firstChild != sc)\r
9157                                                 sp = null;\r
9158                                 }\r
9159 \r
9160                                 if (so == sc.nodeValue.length) {\r
9161                                         e = sc.nextSibling;\r
9162 \r
9163                                         if (e && e.nodeType == 1)\r
9164                                                 sp = sc.nextSibling;\r
9165                                 }\r
9166 \r
9167                                 if (eo == 0) {\r
9168                                         e = ec.previousSibling;\r
9169 \r
9170                                         if (e && e.nodeType == 1)\r
9171                                                 ep = e;\r
9172                                 }\r
9173 \r
9174                                 if (eo == ec.nodeValue.length) {\r
9175                                         ep = getParent(ec);\r
9176 \r
9177                                         if (ep && ep.lastChild != ec)\r
9178                                                 ep = null;\r
9179                                 }\r
9180 \r
9181                                 // Same element\r
9182                                 if (sp == ep)\r
9183                                         return re && sp && re.test(sp.nodeName) ? null : sp;\r
9184                         }\r
9185 \r
9186                         return null;\r
9187                 },\r
9188 \r
9189                 InsertHorizontalRule : function() {\r
9190                         // Fix for Gecko <hr size="1" /> issue and IE bug rep(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]");\r
9191                         if (isGecko || isIE)\r
9192                                 this.editor.selection.setContent('<hr />');\r
9193                         else\r
9194                                 this.editor.getDoc().execCommand('InsertHorizontalRule', false, '');\r
9195                 },\r
9196 \r
9197                 RemoveFormat : function() {\r
9198                         var t = this, ed = t.editor, s = ed.selection, b;\r
9199 \r
9200                         // Safari breaks tables\r
9201                         if (isWebKit)\r
9202                                 s.setContent(s.getContent({format : 'raw'}).replace(/(<(span|b|i|strong|em|strike) [^>]+>|<(span|b|i|strong|em|strike)>|<\/(span|b|i|strong|em|strike)>|)/g, ''), {format : 'raw'});\r
9203                         else\r
9204                                 ed.getDoc().execCommand('RemoveFormat', false, null);\r
9205 \r
9206                         t.mceSetStyleInfo(0, {command : 'removeformat'});\r
9207                         ed.addVisual();\r
9208                 },\r
9209 \r
9210                 mceSetStyleInfo : function(u, v) {\r
9211                         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
9212 \r
9213                         function set(n, e) {\r
9214                                 if (n.nodeType == 1) {\r
9215                                         switch (v.command) {\r
9216                                                 case 'setattrib':\r
9217                                                         return dom.setAttrib(n, v.name, v.value);\r
9218 \r
9219                                                 case 'setstyle':\r
9220                                                         return dom.setStyle(n, v.name, v.value);\r
9221 \r
9222                                                 case 'removeformat':\r
9223                                                         return dom.setAttrib(n, 'class', '');\r
9224                                         }\r
9225                                 }\r
9226                         };\r
9227 \r
9228                         // Setup regexp\r
9229                         re = ed.settings.merge_styles_invalid_parents;\r
9230                         if (tinymce.is(re, 'string'))\r
9231                                 re = new RegExp(re, 'i');\r
9232 \r
9233                         // Set style info on selected element\r
9234                         if ((e = t.getSelectedElement()) && !ed.settings.force_span_wrappers)\r
9235                                 set(e, 1);\r
9236                         else {\r
9237                                 // Generate wrappers and set styles on them\r
9238                                 d.execCommand('FontName', false, '__');\r
9239                                 each(isWebKit ? dom.select('span') : dom.select('font'), function(n) {\r
9240                                         var sp, e;\r
9241 \r
9242                                         if (dom.getAttrib(n, 'face') == '__' || n.style.fontFamily === '__') {\r
9243                                                 sp = dom.create(nn, {mce_new : '1'});\r
9244 \r
9245                                                 set(sp);\r
9246 \r
9247                                                 each (n.childNodes, function(n) {\r
9248                                                         sp.appendChild(n.cloneNode(true));\r
9249                                                 });\r
9250 \r
9251                                                 dom.replace(sp, n);\r
9252                                         }\r
9253                                 });\r
9254                         }\r
9255 \r
9256                         // Remove wrappers inside new ones\r
9257                         each(dom.select(nn).reverse(), function(n) {\r
9258                                 var p = n.parentNode;\r
9259 \r
9260                                 // Check if it's an old span in a new wrapper\r
9261                                 if (!dom.getAttrib(n, 'mce_new')) {\r
9262                                         // Find new wrapper\r
9263                                         p = dom.getParent(n, function(n) {\r
9264                                                 return n.nodeType == 1 && dom.getAttrib(n, 'mce_new');\r
9265                                         });\r
9266 \r
9267                                         if (p)\r
9268                                                 dom.remove(n, 1);\r
9269                                 }\r
9270                         });\r
9271 \r
9272                         // Merge wrappers with parent wrappers\r
9273                         each(dom.select(nn).reverse(), function(n) {\r
9274                                 var p = n.parentNode;\r
9275 \r
9276                                 if (!p || !dom.getAttrib(n, 'mce_new'))\r
9277                                         return;\r
9278 \r
9279                                 if (ed.settings.force_span_wrappers && p.nodeName != 'SPAN')\r
9280                                         return;\r
9281 \r
9282                                 // Has parent of the same type and only child\r
9283                                 if (p.nodeName == nn.toUpperCase() && p.childNodes.length == 1)\r
9284                                         return dom.remove(p, 1);\r
9285 \r
9286                                 // Has parent that is more suitable to have the class and only child\r
9287                                 if (n.nodeType == 1 && (!re || !re.test(p.nodeName)) && p.childNodes.length == 1) {\r
9288                                         set(p); // Set style info on parent instead\r
9289                                         dom.setAttrib(n, 'class', '');\r
9290                                 }\r
9291                         });\r
9292 \r
9293                         // Remove empty wrappers\r
9294                         each(dom.select(nn).reverse(), function(n) {\r
9295                                 if (dom.getAttrib(n, 'mce_new') || (dom.getAttribs(n).length <= 1 && n.className === '')) {\r
9296                                         if (!dom.getAttrib(n, 'class') && !dom.getAttrib(n, 'style'))\r
9297                                                 return dom.remove(n, 1);\r
9298 \r
9299                                         dom.setAttrib(n, 'mce_new', ''); // Remove mce_new marker\r
9300                                 }\r
9301                         });\r
9302 \r
9303                         s.moveToBookmark(b);\r
9304                 },\r
9305 \r
9306                 queryStateJustify : function(c, v) {\r
9307                         var ed = this.editor, n = ed.selection.getNode(), dom = ed.dom;\r
9308 \r
9309                         if (n && n.nodeName == 'IMG') {\r
9310                                 if (dom.getStyle(n, 'float') == v)\r
9311                                         return 1;\r
9312 \r
9313                                 return n.parentNode.style.textAlign == v;\r
9314                         }\r
9315 \r
9316                         n = dom.getParent(ed.selection.getStart(), function(n) {\r
9317                                 return n.nodeType == 1 && n.style.textAlign;\r
9318                         });\r
9319 \r
9320                         if (v == 'full')\r
9321                                 v = 'justify';\r
9322 \r
9323                         if (ed.settings.inline_styles)\r
9324                                 return (n && n.style.textAlign == v);\r
9325 \r
9326                         return this._queryState(c);\r
9327                 },\r
9328 \r
9329                 ForeColor : function(ui, v) {\r
9330                         var ed = this.editor;\r
9331 \r
9332                         if (ed.settings.convert_fonts_to_spans) {\r
9333                                 this._applyInlineStyle('span', {style : {color : v}});\r
9334                                 return;\r
9335                         } else\r
9336                                 ed.getDoc().execCommand('ForeColor', false, v);\r
9337                 },\r
9338 \r
9339                 HiliteColor : function(ui, val) {\r
9340                         var t = this, ed = t.editor, d = ed.getDoc();\r
9341 \r
9342                         if (ed.settings.convert_fonts_to_spans) {\r
9343                                 this._applyInlineStyle('span', {style : {backgroundColor : val}});\r
9344                                 return;\r
9345                         }\r
9346 \r
9347                         function set(s) {\r
9348                                 if (!isGecko)\r
9349                                         return;\r
9350 \r
9351                                 try {\r
9352                                         // Try new Gecko method\r
9353                                         d.execCommand("styleWithCSS", 0, s);\r
9354                                 } catch (ex) {\r
9355                                         // Use old\r
9356                                         d.execCommand("useCSS", 0, !s);\r
9357                                 }\r
9358                         };\r
9359 \r
9360                         if (isGecko || isOpera) {\r
9361                                 set(true);\r
9362                                 d.execCommand('hilitecolor', false, val);\r
9363                                 set(false);\r
9364                         } else\r
9365                                 d.execCommand('BackColor', false, val);\r
9366                 },\r
9367 \r
9368                 Undo : function() {\r
9369                         var ed = this.editor;\r
9370 \r
9371                         if (ed.settings.custom_undo_redo) {\r
9372                                 ed.undoManager.undo();\r
9373                                 ed.nodeChanged();\r
9374                         } else\r
9375                                 ed.getDoc().execCommand('Undo', false, null);\r
9376                 },\r
9377 \r
9378                 Redo : function() {\r
9379                         var ed = this.editor;\r
9380 \r
9381                         if (ed.settings.custom_undo_redo) {\r
9382                                 ed.undoManager.redo();\r
9383                                 ed.nodeChanged();\r
9384                         } else\r
9385                                 ed.getDoc().execCommand('Redo', false, null);\r
9386                 },\r
9387 \r
9388                 FormatBlock : function(ui, val) {\r
9389                         var t = this, ed = t.editor, s = ed.selection, dom = ed.dom, bl, nb, b;\r
9390 \r
9391                         function isBlock(n) {\r
9392                                 return /^(P|DIV|H[1-6]|ADDRESS|BLOCKQUOTE|PRE)$/.test(n.nodeName);\r
9393                         };\r
9394 \r
9395                         bl = dom.getParent(s.getNode(), function(n) {\r
9396                                 return isBlock(n);\r
9397                         });\r
9398 \r
9399                         // IE has an issue where it removes the parent div if you change format on the paragrah in <div><p>Content</p></div>\r
9400                         // FF and Opera doesn't change parent DIV elements if you switch format\r
9401                         if (bl) {\r
9402                                 if ((isIE && isBlock(bl.parentNode)) || bl.nodeName == 'DIV') {\r
9403                                         // Rename block element\r
9404                                         nb = ed.dom.create(val);\r
9405 \r
9406                                         each(dom.getAttribs(bl), function(v) {\r
9407                                                 dom.setAttrib(nb, v.nodeName, dom.getAttrib(bl, v.nodeName));\r
9408                                         });\r
9409 \r
9410                                         b = s.getBookmark();\r
9411                                         dom.replace(nb, bl, 1);\r
9412                                         s.moveToBookmark(b);\r
9413                                         ed.nodeChanged();\r
9414                                         return;\r
9415                                 }\r
9416                         }\r
9417 \r
9418                         val = ed.settings.forced_root_block ? (val || '<p>') : val;\r
9419 \r
9420                         if (val.indexOf('<') == -1)\r
9421                                 val = '<' + val + '>';\r
9422 \r
9423                         if (tinymce.isGecko)\r
9424                                 val = val.replace(/<(div|blockquote|code|dt|dd|dl|samp)>/gi, '$1');\r
9425 \r
9426                         ed.getDoc().execCommand('FormatBlock', false, val);\r
9427                 },\r
9428 \r
9429                 mceCleanup : function() {\r
9430                         var ed = this.editor, s = ed.selection, b = s.getBookmark();\r
9431                         ed.setContent(ed.getContent());\r
9432                         s.moveToBookmark(b);\r
9433                 },\r
9434 \r
9435                 mceRemoveNode : function(ui, val) {\r
9436                         var ed = this.editor, s = ed.selection, b, n = val || s.getNode();\r
9437 \r
9438                         // Make sure that the body node isn't removed\r
9439                         if (n == ed.getBody())\r
9440                                 return;\r
9441 \r
9442                         b = s.getBookmark();\r
9443                         ed.dom.remove(n, 1);\r
9444                         s.moveToBookmark(b);\r
9445                         ed.nodeChanged();\r
9446                 },\r
9447 \r
9448                 mceSelectNodeDepth : function(ui, val) {\r
9449                         var ed = this.editor, s = ed.selection, c = 0;\r
9450 \r
9451                         ed.dom.getParent(s.getNode(), function(n) {\r
9452                                 if (n.nodeType == 1 && c++ == val) {\r
9453                                         s.select(n);\r
9454                                         ed.nodeChanged();\r
9455                                         return false;\r
9456                                 }\r
9457                         }, ed.getBody());\r
9458                 },\r
9459 \r
9460                 mceSelectNode : function(u, v) {\r
9461                         this.editor.selection.select(v);\r
9462                 },\r
9463 \r
9464                 mceInsertContent : function(ui, val) {\r
9465                         this.editor.selection.setContent(val);\r
9466                 },\r
9467 \r
9468                 mceInsertRawHTML : function(ui, val) {\r
9469                         var ed = this.editor;\r
9470 \r
9471                         ed.selection.setContent('tiny_mce_marker');\r
9472                         ed.setContent(ed.getContent().replace(/tiny_mce_marker/g, val));\r
9473                 },\r
9474 \r
9475                 mceRepaint : function() {\r
9476                         var s, b, e = this.editor;\r
9477 \r
9478                         if (tinymce.isGecko) {\r
9479                                 try {\r
9480                                         s = e.selection;\r
9481                                         b = s.getBookmark(true);\r
9482 \r
9483                                         if (s.getSel())\r
9484                                                 s.getSel().selectAllChildren(e.getBody());\r
9485 \r
9486                                         s.collapse(true);\r
9487                                         s.moveToBookmark(b);\r
9488                                 } catch (ex) {\r
9489                                         // Ignore\r
9490                                 }\r
9491                         }\r
9492                 },\r
9493 \r
9494                 queryStateUnderline : function() {\r
9495                         var ed = this.editor, n = ed.selection.getNode();\r
9496 \r
9497                         if (n && n.nodeName == 'A')\r
9498                                 return false;\r
9499 \r
9500                         return this._queryState('Underline');\r
9501                 },\r
9502 \r
9503                 queryStateOutdent : function() {\r
9504                         var ed = this.editor, n;\r
9505 \r
9506                         if (ed.settings.inline_styles) {\r
9507                                 if ((n = ed.dom.getParent(ed.selection.getStart(), ed.dom.isBlock)) && parseInt(n.style.paddingLeft) > 0)\r
9508                                         return true;\r
9509 \r
9510                                 if ((n = ed.dom.getParent(ed.selection.getEnd(), ed.dom.isBlock)) && parseInt(n.style.paddingLeft) > 0)\r
9511                                         return true;\r
9512                         }\r
9513 \r
9514                         return this.queryStateInsertUnorderedList() || this.queryStateInsertOrderedList() || (!ed.settings.inline_styles && !!ed.dom.getParent(ed.selection.getNode(), 'BLOCKQUOTE'));\r
9515                 },\r
9516 \r
9517                 queryStateInsertUnorderedList : function() {\r
9518                         return this.editor.dom.getParent(this.editor.selection.getNode(), 'UL');\r
9519                 },\r
9520 \r
9521                 queryStateInsertOrderedList : function() {\r
9522                         return this.editor.dom.getParent(this.editor.selection.getNode(), 'OL');\r
9523                 },\r
9524 \r
9525                 queryStatemceBlockQuote : function() {\r
9526                         return !!this.editor.dom.getParent(this.editor.selection.getStart(), function(n) {return n.nodeName === 'BLOCKQUOTE';});\r
9527                 },\r
9528 \r
9529                 mceBlockQuote : function() {\r
9530                         var t = this, ed = t.editor, s = ed.selection, dom = ed.dom, sb, eb, n, bm, bq, r, bq2, i, nl;\r
9531 \r
9532                         function getBQ(e) {\r
9533                                 return dom.getParent(e, function(n) {return n.nodeName === 'BLOCKQUOTE';});\r
9534                         };\r
9535 \r
9536                         // Get start/end block\r
9537                         sb = dom.getParent(s.getStart(), isBlock);\r
9538                         eb = dom.getParent(s.getEnd(), isBlock);\r
9539 \r
9540                         // Remove blockquote(s)\r
9541                         if (bq = getBQ(sb)) {\r
9542                                 if (sb != eb || sb.childNodes.length > 1 || (sb.childNodes.length == 1 && sb.firstChild.nodeName != 'BR'))\r
9543                                         bm = s.getBookmark();\r
9544 \r
9545                                 // Move all elements after the end block into new bq\r
9546                                 if (getBQ(eb)) {\r
9547                                         bq2 = bq.cloneNode(false);\r
9548 \r
9549                                         while (n = eb.nextSibling)\r
9550                                                 bq2.appendChild(n.parentNode.removeChild(n));\r
9551                                 }\r
9552 \r
9553                                 // Add new bq after\r
9554                                 if (bq2)\r
9555                                         dom.insertAfter(bq2, bq);\r
9556 \r
9557                                 // Move all selected blocks after the current bq\r
9558                                 nl = t._getSelectedBlocks(sb, eb);\r
9559                                 for (i = nl.length - 1; i >= 0; i--) {\r
9560                                         dom.insertAfter(nl[i], bq);\r
9561                                 }\r
9562 \r
9563                                 // Empty bq, then remove it\r
9564                                 if (/^\s*$/.test(bq.innerHTML))\r
9565                                         dom.remove(bq, 1); // Keep children so boomark restoration works correctly\r
9566 \r
9567                                 // Empty bq, then remote it\r
9568                                 if (bq2 && /^\s*$/.test(bq2.innerHTML))\r
9569                                         dom.remove(bq2, 1); // Keep children so boomark restoration works correctly\r
9570 \r
9571                                 if (!bm) {\r
9572                                         // Move caret inside empty block element\r
9573                                         if (!isIE) {\r
9574                                                 r = ed.getDoc().createRange();\r
9575                                                 r.setStart(sb, 0);\r
9576                                                 r.setEnd(sb, 0);\r
9577                                                 s.setRng(r);\r
9578                                         } else {\r
9579                                                 s.select(sb);\r
9580                                                 s.collapse(0);\r
9581 \r
9582                                                 // IE misses the empty block some times element so we must move back the caret\r
9583                                                 if (dom.getParent(s.getStart(), isBlock) != sb) {\r
9584                                                         r = s.getRng();\r
9585                                                         r.move('character', -1);\r
9586                                                         r.select();\r
9587                                                 }\r
9588                                         }\r
9589                                 } else\r
9590                                         t.editor.selection.moveToBookmark(bm);\r
9591 \r
9592                                 return;\r
9593                         }\r
9594 \r
9595                         // Since IE can start with a totally empty document we need to add the first bq and paragraph\r
9596                         if (isIE && !sb && !eb) {\r
9597                                 t.editor.getDoc().execCommand('Indent');\r
9598                                 n = getBQ(s.getNode());\r
9599                                 n.style.margin = n.dir = ''; // IE adds margin and dir to bq\r
9600                                 return;\r
9601                         }\r
9602 \r
9603                         if (!sb || !eb)\r
9604                                 return;\r
9605 \r
9606                         // If empty paragraph node then do not use bookmark\r
9607                         if (sb != eb || sb.childNodes.length > 1 || (sb.childNodes.length == 1 && sb.firstChild.nodeName != 'BR'))\r
9608                                 bm = s.getBookmark();\r
9609 \r
9610                         // Move selected block elements into a bq\r
9611                         each(t._getSelectedBlocks(getBQ(s.getStart()), getBQ(s.getEnd())), function(e) {\r
9612                                 // Found existing BQ add to this one\r
9613                                 if (e.nodeName == 'BLOCKQUOTE' && !bq) {\r
9614                                         bq = e;\r
9615                                         return;\r
9616                                 }\r
9617 \r
9618                                 // No BQ found, create one\r
9619                                 if (!bq) {\r
9620                                         bq = dom.create('blockquote');\r
9621                                         e.parentNode.insertBefore(bq, e);\r
9622                                 }\r
9623 \r
9624                                 // Add children from existing BQ\r
9625                                 if (e.nodeName == 'BLOCKQUOTE' && bq) {\r
9626                                         n = e.firstChild;\r
9627 \r
9628                                         while (n) {\r
9629                                                 bq.appendChild(n.cloneNode(true));\r
9630                                                 n = n.nextSibling;\r
9631                                         }\r
9632 \r
9633                                         dom.remove(e);\r
9634                                         return;\r
9635                                 }\r
9636 \r
9637                                 // Add non BQ element to BQ\r
9638                                 bq.appendChild(dom.remove(e));\r
9639                         });\r
9640 \r
9641                         if (!bm) {\r
9642                                 // Move caret inside empty block element\r
9643                                 if (!isIE) {\r
9644                                         r = ed.getDoc().createRange();\r
9645                                         r.setStart(sb, 0);\r
9646                                         r.setEnd(sb, 0);\r
9647                                         s.setRng(r);\r
9648                                 } else {\r
9649                                         s.select(sb);\r
9650                                         s.collapse(1);\r
9651                                 }\r
9652                         } else\r
9653                                 s.moveToBookmark(bm);\r
9654                 },\r
9655 \r
9656                 _applyInlineStyle : function(na, at, op) {\r
9657                         var t = this, ed = t.editor, dom = ed.dom, bm, lo = {}, kh;\r
9658 \r
9659                         na = na.toUpperCase();\r
9660 \r
9661                         if (op && op.check_classes && at['class'])\r
9662                                 op.check_classes.push(at['class']);\r
9663 \r
9664                         function replaceFonts() {\r
9665                                 var bm;\r
9666 \r
9667                                 each(dom.select(tinymce.isWebKit && !tinymce.isAir ? 'span' : 'font'), function(n) {\r
9668                                         if (n.style.fontFamily == 'mceinline' || n.face == 'mceinline') {\r
9669                                                 if (!bm)\r
9670                                                         bm = ed.selection.getBookmark();\r
9671 \r
9672                                                 at._mce_new = '1';\r
9673                                                 dom.replace(dom.create(na, at), n, 1);\r
9674                                         }\r
9675                                 });\r
9676 \r
9677                                 // Remove redundant elements\r
9678                                 each(dom.select(na), function(n) {\r
9679                                         if (n.getAttribute('_mce_new')) {\r
9680                                                 function removeStyle(n) {\r
9681                                                         if (n.nodeType == 1) {\r
9682                                                                 each(at.style, function(v, k) {\r
9683                                                                         dom.setStyle(n, k, '');\r
9684                                                                 });\r
9685 \r
9686                                                                 // Remove spans with the same class or marked classes\r
9687                                                                 if (at['class'] && n.className && op) {\r
9688                                                                         each(op.check_classes, function(c) {\r
9689                                                                                 if (dom.hasClass(n, c))\r
9690                                                                                         dom.removeClass(n, c);\r
9691                                                                         });\r
9692                                                                 }\r
9693                                                         }\r
9694                                                 };\r
9695 \r
9696                                                 // Remove specified style information from child elements\r
9697                                                 each(dom.select(na, n), removeStyle);\r
9698 \r
9699                                                 // Remove the specified style information on parent if current node is only child (IE)\r
9700                                                 if (n.parentNode && n.parentNode.nodeType == 1 && n.parentNode.childNodes.length == 1)\r
9701                                                         removeStyle(n.parentNode);\r
9702 \r
9703                                                 // Remove the child elements style info if a parent already has it\r
9704                                                 dom.getParent(n.parentNode, function(pn) {\r
9705                                                         if (pn.nodeType == 1) {\r
9706                                                                 if (at.style) {\r
9707                                                                         each(at.style, function(v, k) {\r
9708                                                                                 var sv;\r
9709 \r
9710                                                                                 if (!lo[k] && (sv = dom.getStyle(pn, k))) {\r
9711                                                                                         if (sv === v)\r
9712                                                                                                 dom.setStyle(n, k, '');\r
9713 \r
9714                                                                                         lo[k] = 1;\r
9715                                                                                 }\r
9716                                                                         });\r
9717                                                                 }\r
9718 \r
9719                                                                 // Remove spans with the same class or marked classes\r
9720                                                                 if (at['class'] && pn.className && op) {\r
9721                                                                         each(op.check_classes, function(c) {\r
9722                                                                                 if (dom.hasClass(pn, c))\r
9723                                                                                         dom.removeClass(n, c);\r
9724                                                                         });\r
9725                                                                 }\r
9726                                                         }\r
9727 \r
9728                                                         return false;\r
9729                                                 });\r
9730 \r
9731                                                 n.removeAttribute('_mce_new');\r
9732                                         }\r
9733                                 });\r
9734 \r
9735                                 // Remove empty span elements\r
9736                                 each(dom.select(na).reverse(), function(n) {\r
9737                                         var c = 0;\r
9738 \r
9739                                         // Check if there is any attributes\r
9740                                         each(dom.getAttribs(n), function(an) {\r
9741                                                 if (an.nodeName.substring(0, 1) != '_' && dom.getAttrib(n, an.nodeName) != '') {\r
9742                                                         //console.log(dom.getOuterHTML(n), dom.getAttrib(n, an.nodeName));\r
9743                                                         c++;\r
9744                                                 }\r
9745                                         });\r
9746 \r
9747                                         // No attributes then remove the element and keep the children\r
9748                                         if (c == 0)\r
9749                                                 dom.remove(n, 1);\r
9750                                 });\r
9751 \r
9752                                 ed.selection.moveToBookmark(bm);\r
9753 \r
9754                                 return !!bm;\r
9755                         };\r
9756 \r
9757                         // Create inline elements\r
9758                         ed.focus();\r
9759                         ed.getDoc().execCommand('FontName', false, 'mceinline');\r
9760                         replaceFonts();\r
9761 \r
9762                         if (kh = t._applyInlineStyle.keyhandler) {\r
9763                                 ed.onKeyUp.remove(kh);\r
9764                                 ed.onKeyPress.remove(kh);\r
9765                                 ed.onKeyDown.remove(kh);\r
9766                                 ed.onSetContent.remove(t._applyInlineStyle.chandler);\r
9767                         }\r
9768 \r
9769                         if (ed.selection.isCollapsed()) {\r
9770                                 // Start collecting styles\r
9771                                 t._pendingStyles = tinymce.extend(t._pendingStyles || {}, at.style);\r
9772 \r
9773                                 t._applyInlineStyle.chandler = ed.onSetContent.add(function() {\r
9774                                         delete t._pendingStyles;\r
9775                                 });\r
9776 \r
9777                                 t._applyInlineStyle.keyhandler = kh = function(e) {\r
9778                                         // Use pending styles\r
9779                                         if (t._pendingStyles) {\r
9780                                                 at.style = t._pendingStyles;\r
9781                                                 delete t._pendingStyles;\r
9782                                         }\r
9783 \r
9784                                         if (replaceFonts()) {\r
9785                                                 ed.onKeyDown.remove(t._applyInlineStyle.keyhandler);\r
9786                                                 ed.onKeyPress.remove(t._applyInlineStyle.keyhandler);\r
9787                                         }\r
9788 \r
9789                                         if (e.type == 'keyup')\r
9790                                                 ed.onKeyUp.remove(t._applyInlineStyle.keyhandler);\r
9791                                 };\r
9792 \r
9793                                 ed.onKeyDown.add(kh);\r
9794                                 ed.onKeyPress.add(kh);\r
9795                                 ed.onKeyUp.add(kh);\r
9796                         } else\r
9797                                 t._pendingStyles = 0;\r
9798                 },\r
9799 \r
9800 /*\r
9801                 _mceBlockQuote : function() {\r
9802                         var t = this, s = t.editor.selection, b = s.getBookmark(), bq, dom = t.editor.dom;\r
9803 \r
9804                         function findBQ(e) {\r
9805                                 return dom.getParent(e, function(n) {return n.nodeName === 'BLOCKQUOTE';});\r
9806                         };\r
9807 \r
9808                         // Remove blockquote(s)\r
9809                         if (findBQ(s.getStart())) {\r
9810                                 each(t._getSelectedBlocks(findBQ(s.getStart()), findBQ(s.getEnd())), function(e) {\r
9811                                         // Found BQ lets remove it\r
9812                                         if (e.nodeName == 'BLOCKQUOTE')\r
9813                                                 dom.remove(e, 1);\r
9814                                 });\r
9815 \r
9816                                 t.editor.selection.moveToBookmark(b);\r
9817                                 return;\r
9818                         }\r
9819 \r
9820                         each(t._getSelectedBlocks(findBQ(s.getStart()), findBQ(s.getEnd())), function(e) {\r
9821                                 var n;\r
9822 \r
9823                                 // Found existing BQ add to this one\r
9824                                 if (e.nodeName == 'BLOCKQUOTE' && !bq) {\r
9825                                         bq = e;\r
9826                                         return;\r
9827                                 }\r
9828 \r
9829                                 // No BQ found, create one\r
9830                                 if (!bq) {\r
9831                                         bq = dom.create('blockquote');\r
9832                                         e.parentNode.insertBefore(bq, e);\r
9833                                 }\r
9834 \r
9835                                 // Add children from existing BQ\r
9836                                 if (e.nodeName == 'BLOCKQUOTE' && bq) {\r
9837                                         n = e.firstChild;\r
9838 \r
9839                                         while (n) {\r
9840                                                 bq.appendChild(n.cloneNode(true));\r
9841                                                 n = n.nextSibling;\r
9842                                         }\r
9843 \r
9844                                         dom.remove(e);\r
9845 \r
9846                                         return;\r
9847                                 }\r
9848 \r
9849                                 // Add non BQ element to BQ\r
9850                                 bq.appendChild(dom.remove(e));\r
9851                         });\r
9852 \r
9853                         t.editor.selection.moveToBookmark(b);\r
9854                 },\r
9855 */\r
9856                 _getSelectedBlocks : function(st, en) {\r
9857                         var ed = this.editor, dom = ed.dom, s = ed.selection, sb, eb, n, bl = [];\r
9858 \r
9859                         sb = dom.getParent(st || s.getStart(), isBlock);\r
9860                         eb = dom.getParent(en || s.getEnd(), isBlock);\r
9861 \r
9862                         if (sb)\r
9863                                 bl.push(sb);\r
9864 \r
9865                         if (sb && eb && sb != eb) {\r
9866                                 n = sb;\r
9867 \r
9868                                 while ((n = n.nextSibling) && n != eb) {\r
9869                                         if (isBlock(n))\r
9870                                                 bl.push(n);\r
9871                                 }\r
9872                         }\r
9873 \r
9874                         if (eb && sb != eb)\r
9875                                 bl.push(eb);\r
9876 \r
9877                         return bl;\r
9878                 }\r
9879         });\r
9880 })();\r
9881 \r
9882 \r
9883 /* file:jscripts/tiny_mce/classes/UndoManager.js */\r
9884 \r
9885 tinymce.create('tinymce.UndoManager', {\r
9886         index : 0,\r
9887         data : null,\r
9888         typing : 0,\r
9889 \r
9890         UndoManager : function(ed) {\r
9891                 var t = this, Dispatcher = tinymce.util.Dispatcher;\r
9892 \r
9893                 t.editor = ed;\r
9894                 t.data = [];\r
9895                 t.onAdd = new Dispatcher(this);\r
9896                 t.onUndo = new Dispatcher(this);\r
9897                 t.onRedo = new Dispatcher(this);\r
9898         },\r
9899 \r
9900         add : function(l) {\r
9901                 var t = this, i, ed = t.editor, b, s = ed.settings, la;\r
9902 \r
9903                 l = l || {};\r
9904                 l.content = l.content || ed.getContent({format : 'raw', no_events : 1});\r
9905 \r
9906                 // Add undo level if needed\r
9907                 l.content = l.content.replace(/^\s*|\s*$/g, '');\r
9908                 la = t.data[t.index > 0 && (t.index == 0 || t.index == t.data.length) ? t.index - 1 : t.index];\r
9909                 if (!l.initial && la && l.content == la.content)\r
9910                         return null;\r
9911 \r
9912                 // Time to compress\r
9913                 if (s.custom_undo_redo_levels) {\r
9914                         if (t.data.length > s.custom_undo_redo_levels) {\r
9915                                 for (i = 0; i < t.data.length - 1; i++)\r
9916                                         t.data[i] = t.data[i + 1];\r
9917 \r
9918                                 t.data.length--;\r
9919                                 t.index = t.data.length;\r
9920                         }\r
9921                 }\r
9922 \r
9923                 if (s.custom_undo_redo_restore_selection && !l.initial)\r
9924                         l.bookmark = b = l.bookmark || ed.selection.getBookmark();\r
9925 \r
9926                 if (t.index < t.data.length)\r
9927                         t.index++;\r
9928 \r
9929                 // Only initial marked undo levels should be allowed as first item\r
9930                 // This to workaround a bug with Firefox and the blur event\r
9931                 if (t.data.length === 0 && !l.initial)\r
9932                         return null;\r
9933 \r
9934                 // Add level\r
9935                 t.data.length = t.index + 1;\r
9936                 t.data[t.index++] = l;\r
9937 \r
9938                 if (l.initial)\r
9939                         t.index = 0;\r
9940 \r
9941                 // Set initial bookmark use first real undo level\r
9942                 if (t.data.length == 2 && t.data[0].initial)\r
9943                         t.data[0].bookmark = b;\r
9944 \r
9945                 t.onAdd.dispatch(t, l);\r
9946                 ed.isNotDirty = 0;\r
9947 \r
9948                 //console.dir(t.data);\r
9949 \r
9950                 return l;\r
9951         },\r
9952 \r
9953         undo : function() {\r
9954                 var t = this, ed = t.editor, l = l, i;\r
9955 \r
9956                 if (t.typing) {\r
9957                         t.add();\r
9958                         t.typing = 0;\r
9959                 }\r
9960 \r
9961                 if (t.index > 0) {\r
9962                         // If undo on last index then take snapshot\r
9963                         if (t.index == t.data.length && t.index > 1) {\r
9964                                 i = t.index;\r
9965                                 t.typing = 0;\r
9966 \r
9967                                 if (!t.add())\r
9968                                         t.index = i;\r
9969 \r
9970                                 --t.index;\r
9971                         }\r
9972 \r
9973                         l = t.data[--t.index];\r
9974                         ed.setContent(l.content, {format : 'raw'});\r
9975                         ed.selection.moveToBookmark(l.bookmark);\r
9976 \r
9977                         t.onUndo.dispatch(t, l);\r
9978                 }\r
9979 \r
9980                 return l;\r
9981         },\r
9982 \r
9983         redo : function() {\r
9984                 var t = this, ed = t.editor, l = null;\r
9985 \r
9986                 if (t.index < t.data.length - 1) {\r
9987                         l = t.data[++t.index];\r
9988                         ed.setContent(l.content, {format : 'raw'});\r
9989                         ed.selection.moveToBookmark(l.bookmark);\r
9990 \r
9991                         t.onRedo.dispatch(t, l);\r
9992                 }\r
9993 \r
9994                 return l;\r
9995         },\r
9996 \r
9997         clear : function() {\r
9998                 var t = this;\r
9999 \r
10000                 t.data = [];\r
10001                 t.index = 0;\r
10002                 t.typing = 0;\r
10003                 t.add({initial : true});\r
10004         },\r
10005 \r
10006         hasUndo : function() {\r
10007                 return this.index != 0 || this.typing;\r
10008         },\r
10009 \r
10010         hasRedo : function() {\r
10011                 return this.index < this.data.length - 1;\r
10012         }\r
10013 \r
10014         });\r
10015 /* file:jscripts/tiny_mce/classes/ForceBlocks.js */\r
10016 \r
10017 (function() {\r
10018         // Shorten names\r
10019         var Event, isIE, isGecko, isOpera, each, extend;\r
10020 \r
10021         Event = tinymce.dom.Event;\r
10022         isIE = tinymce.isIE;\r
10023         isGecko = tinymce.isGecko;\r
10024         isOpera = tinymce.isOpera;\r
10025         each = tinymce.each;\r
10026         extend = tinymce.extend;\r
10027 \r
10028         tinymce.create('tinymce.ForceBlocks', {\r
10029                 ForceBlocks : function(ed) {\r
10030                         var t = this, s = ed.settings, elm;\r
10031 \r
10032                         t.editor = ed;\r
10033                         t.dom = ed.dom;\r
10034                         elm = (s.forced_root_block || 'p').toLowerCase();\r
10035                         s.element = elm.toUpperCase();\r
10036 \r
10037                         ed.onPreInit.add(t.setup, t);\r
10038 \r
10039                         t.reOpera = new RegExp('(\\u00a0|&#160;|&nbsp;)<\/' + elm + '>', 'gi');\r
10040                         t.rePadd = new RegExp('<p( )([^>]+)><\\\/p>|<p( )([^>]+)\\\/>|<p( )([^>]+)>\\s+<\\\/p>|<p><\\\/p>|<p\\\/>|<p>\\s+<\\\/p>'.replace(/p/g, elm), 'gi');\r
10041                         t.reNbsp2BR1 = new RegExp('<p( )([^>]+)>[\\s\\u00a0]+<\\\/p>|<p>[\\s\\u00a0]+<\\\/p>'.replace(/p/g, elm), 'gi');\r
10042                         t.reNbsp2BR2 = new RegExp('<p( )([^>]+)>(&nbsp;|&#160;)<\\\/p>|<p>(&nbsp;|&#160;)<\\\/p>'.replace(/p/g, elm), 'gi');\r
10043                         t.reBR2Nbsp = new RegExp('<p( )([^>]+)>\\s*<br \\\/>\\s*<\\\/p>|<p>\\s*<br \\\/>\\s*<\\\/p>'.replace(/p/g, elm), 'gi');\r
10044                         t.reTrailBr = new RegExp('\\s*<br \\/>\\s*<\\\/p>'.replace(/p/g, elm), 'gi');\r
10045 \r
10046                         function padd(ed, o) {\r
10047                                 if (isOpera)\r
10048                                         o.content = o.content.replace(t.reOpera, '</' + elm + '>');\r
10049 \r
10050                                 o.content = o.content.replace(t.rePadd, '<' + elm + '$1$2$3$4$5$6>\u00a0</' + elm + '>');\r
10051 \r
10052                                 if (!isIE && !isOpera && o.set) {\r
10053                                         // Use &nbsp; instead of BR in padded paragraphs\r
10054                                         o.content = o.content.replace(t.reNbsp2BR1, '<' + elm + '$1$2><br /></' + elm + '>');\r
10055                                         o.content = o.content.replace(t.reNbsp2BR2, '<' + elm + '$1$2><br /></' + elm + '>');\r
10056                                 } else {\r
10057                                         o.content = o.content.replace(t.reBR2Nbsp, '<' + elm + '$1$2>\u00a0</' + elm + '>');\r
10058                                         o.content = o.content.replace(t.reTrailBr, '</' + elm + '>');\r
10059                                 }\r
10060                         };\r
10061 \r
10062                         ed.onBeforeSetContent.add(padd);\r
10063                         ed.onPostProcess.add(padd);\r
10064 \r
10065                         if (s.forced_root_block) {\r
10066                                 ed.onInit.add(t.forceRoots, t);\r
10067                                 ed.onSetContent.add(t.forceRoots, t);\r
10068                                 ed.onBeforeGetContent.add(t.forceRoots, t);\r
10069                         }\r
10070                 },\r
10071 \r
10072                 setup : function() {\r
10073                         var t = this, ed = t.editor, s = ed.settings;\r
10074 \r
10075                         // Force root blocks when typing and when getting output\r
10076                         if (s.forced_root_block) {\r
10077                                 ed.onKeyUp.add(t.forceRoots, t);\r
10078                                 ed.onPreProcess.add(t.forceRoots, t);\r
10079                         }\r
10080 \r
10081                         if (s.force_br_newlines) {\r
10082                                 // Force IE to produce BRs on enter\r
10083                                 if (isIE) {\r
10084                                         ed.onKeyPress.add(function(ed, e) {\r
10085                                                 var n, s = ed.selection;\r
10086 \r
10087                                                 if (e.keyCode == 13 && s.getNode().nodeName != 'LI') {\r
10088                                                         s.setContent('<br id="__" /> ', {format : 'raw'});\r
10089                                                         n = ed.dom.get('__');\r
10090                                                         n.removeAttribute('id');\r
10091                                                         s.select(n);\r
10092                                                         s.collapse();\r
10093                                                         return Event.cancel(e);\r
10094                                                 }\r
10095                                         });\r
10096                                 }\r
10097 \r
10098                                 return;\r
10099                         }\r
10100 \r
10101                         if (!isIE && s.force_p_newlines) {\r
10102 /*                              ed.onPreProcess.add(function(ed, o) {\r
10103                                         each(ed.dom.select('br', o.node), function(n) {\r
10104                                                 var p = n.parentNode;\r
10105 \r
10106                                                 // Replace <p><br /></p> with <p>&nbsp;</p>\r
10107                                                 if (p && p.nodeName == 'p' && (p.childNodes.length == 1 || p.lastChild == n)) {\r
10108                                                         p.replaceChild(ed.getDoc().createTextNode('\u00a0'), n);\r
10109                                                 }\r
10110                                         });\r
10111                                 });*/\r
10112 \r
10113                                 ed.onKeyPress.add(function(ed, e) {\r
10114                                         if (e.keyCode == 13 && !e.shiftKey) {\r
10115                                                 if (!t.insertPara(e))\r
10116                                                         Event.cancel(e);\r
10117                                         }\r
10118                                 });\r
10119 \r
10120                                 if (isGecko) {\r
10121                                         ed.onKeyDown.add(function(ed, e) {\r
10122                                                 if ((e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey)\r
10123                                                         t.backspaceDelete(e, e.keyCode == 8);\r
10124                                         });\r
10125                                 }\r
10126                         }\r
10127 \r
10128                         function ren(rn, na) {\r
10129                                 var ne = ed.dom.create(na);\r
10130 \r
10131                                 each(rn.attributes, function(a) {\r
10132                                         if (a.specified && a.nodeValue)\r
10133                                                 ne.setAttribute(a.nodeName.toLowerCase(), a.nodeValue);\r
10134                                 });\r
10135 \r
10136                                 each(rn.childNodes, function(n) {\r
10137                                         ne.appendChild(n.cloneNode(true));\r
10138                                 });\r
10139 \r
10140                                 rn.parentNode.replaceChild(ne, rn);\r
10141 \r
10142                                 return ne;\r
10143                         };\r
10144 \r
10145                         // Replaces IE:s auto generated paragraphs with the specified element name\r
10146                         if (isIE && s.element != 'P') {\r
10147                                 ed.onKeyPress.add(function(ed, e) {\r
10148                                         t.lastElm = ed.selection.getNode().nodeName;\r
10149                                 });\r
10150 \r
10151                                 ed.onKeyUp.add(function(ed, e) {\r
10152                                         var bl, sel = ed.selection, n = sel.getNode(), b = ed.getBody();\r
10153 \r
10154                                         if (b.childNodes.length === 1 && n.nodeName == 'P') {\r
10155                                                 n = ren(n, s.element);\r
10156                                                 sel.select(n);\r
10157                                                 sel.collapse();\r
10158                                                 ed.nodeChanged();\r
10159                                         } else if (e.keyCode == 13 && !e.shiftKey && t.lastElm != 'P') {\r
10160                                                 bl = ed.dom.getParent(n, 'P');\r
10161 \r
10162                                                 if (bl) {\r
10163                                                         ren(bl, s.element);\r
10164                                                         ed.nodeChanged();\r
10165                                                 }\r
10166                                         }\r
10167                                 });\r
10168                         }\r
10169                 },\r
10170 \r
10171                 find : function(n, t, s) {\r
10172                         var ed = this.editor, w = ed.getDoc().createTreeWalker(n, 4, null, false), c = -1;\r
10173 \r
10174                         while (n = w.nextNode()) {\r
10175                                 c++;\r
10176 \r
10177                                 // Index by node\r
10178                                 if (t == 0 && n == s)\r
10179                                         return c;\r
10180 \r
10181                                 // Node by index\r
10182                                 if (t == 1 && c == s)\r
10183                                         return n;\r
10184                         }\r
10185 \r
10186                         return -1;\r
10187                 },\r
10188 \r
10189                 forceRoots : function(ed, e) {\r
10190                         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
10191                         var nx, bl, bp, sp, le, nl = b.childNodes, i, n, eid;\r
10192 \r
10193                         // Fix for bug #1863847\r
10194                         //if (e && e.keyCode == 13)\r
10195                         //      return true;\r
10196 \r
10197                         // Wrap non blocks into blocks\r
10198                         for (i = nl.length - 1; i >= 0; i--) {\r
10199                                 nx = nl[i];\r
10200 \r
10201                                 // Is text or non block element\r
10202                                 if (nx.nodeType == 3 || (!t.dom.isBlock(nx) && nx.nodeType != 8)) {\r
10203                                         if (!bl) {\r
10204                                                 // Create new block but ignore whitespace\r
10205                                                 if (nx.nodeType != 3 || /[^\s]/g.test(nx.nodeValue)) {\r
10206                                                         // Store selection\r
10207                                                         if (si == -2 && r) {\r
10208                                                                 if (!isIE) {\r
10209                                                                         // If selection is element then mark it\r
10210                                                                         if (r.startContainer.nodeType == 1 && (n = r.startContainer.childNodes[r.startOffset]) && n.nodeType == 1) {\r
10211                                                                                 // Save the id of the selected element\r
10212                                                                                 eid = n.getAttribute("id");\r
10213                                                                                 n.setAttribute("id", "__mce");\r
10214                                                                         } else {\r
10215                                                                                 // If element is inside body, might not be the case in contentEdiable mode\r
10216                                                                                 if (ed.dom.getParent(r.startContainer, function(e) {return e === b;})) {\r
10217                                                                                         so = r.startOffset;\r
10218                                                                                         eo = r.endOffset;\r
10219                                                                                         si = t.find(b, 0, r.startContainer);\r
10220                                                                                         ei = t.find(b, 0, r.endContainer);\r
10221                                                                                 }\r
10222                                                                         }\r
10223                                                                 } else {\r
10224                                                                         tr = d.body.createTextRange();\r
10225                                                                         tr.moveToElementText(b);\r
10226                                                                         tr.collapse(1);\r
10227                                                                         bp = tr.move('character', c) * -1;\r
10228 \r
10229                                                                         tr = r.duplicate();\r
10230                                                                         tr.collapse(1);\r
10231                                                                         sp = tr.move('character', c) * -1;\r
10232 \r
10233                                                                         tr = r.duplicate();\r
10234                                                                         tr.collapse(0);\r
10235                                                                         le = (tr.move('character', c) * -1) - sp;\r
10236 \r
10237                                                                         si = sp - bp;\r
10238                                                                         ei = le;\r
10239                                                                 }\r
10240                                                         }\r
10241 \r
10242                                                         bl = ed.dom.create(ed.settings.forced_root_block);\r
10243                                                         bl.appendChild(nx.cloneNode(1));\r
10244                                                         nx.parentNode.replaceChild(bl, nx);\r
10245                                                 }\r
10246                                         } else {\r
10247                                                 if (bl.hasChildNodes())\r
10248                                                         bl.insertBefore(nx, bl.firstChild);\r
10249                                                 else\r
10250                                                         bl.appendChild(nx);\r
10251                                         }\r
10252                                 } else\r
10253                                         bl = null; // Time to create new block\r
10254                         }\r
10255 \r
10256                         // Restore selection\r
10257                         if (si != -2) {\r
10258                                 if (!isIE) {\r
10259                                         bl = b.getElementsByTagName(ed.settings.element)[0];\r
10260                                         r = d.createRange();\r
10261 \r
10262                                         // Select last location or generated block\r
10263                                         if (si != -1)\r
10264                                                 r.setStart(t.find(b, 1, si), so);\r
10265                                         else\r
10266                                                 r.setStart(bl, 0);\r
10267 \r
10268                                         // Select last location or generated block\r
10269                                         if (ei != -1)\r
10270                                                 r.setEnd(t.find(b, 1, ei), eo);\r
10271                                         else\r
10272                                                 r.setEnd(bl, 0);\r
10273 \r
10274                                         if (s) {\r
10275                                                 s.removeAllRanges();\r
10276                                                 s.addRange(r);\r
10277                                         }\r
10278                                 } else {\r
10279                                         try {\r
10280                                                 r = s.createRange();\r
10281                                                 r.moveToElementText(b);\r
10282                                                 r.collapse(1);\r
10283                                                 r.moveStart('character', si);\r
10284                                                 r.moveEnd('character', ei);\r
10285                                                 r.select();\r
10286                                         } catch (ex) {\r
10287                                                 // Ignore\r
10288                                         }\r
10289                                 }\r
10290                         } else if (!isIE && (n = ed.dom.get('__mce'))) {\r
10291                                 // Restore the id of the selected element\r
10292                                 if (eid)\r
10293                                         n.setAttribute('id', eid);\r
10294                                 else\r
10295                                         n.removeAttribute('id');\r
10296 \r
10297                                 // Move caret before selected element\r
10298                                 r = d.createRange();\r
10299                                 r.setStartBefore(n);\r
10300                                 r.setEndBefore(n);\r
10301                                 se.setRng(r);\r
10302                         }\r
10303                 },\r
10304 \r
10305                 getParentBlock : function(n) {\r
10306                         var d = this.dom;\r
10307 \r
10308                         return d.getParent(n, d.isBlock);\r
10309                 },\r
10310 \r
10311                 insertPara : function(e) {\r
10312                         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
10313                         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
10314 \r
10315                         function isEmpty(n) {\r
10316                                 n = n.innerHTML;\r
10317                                 n = n.replace(/<(img|hr|table)/gi, '-'); // Keep these convert them to - chars\r
10318                                 n = n.replace(/<[^>]+>/g, ''); // Remove all tags\r
10319 \r
10320                                 return n.replace(/[ \t\r\n]+/g, '') == '';\r
10321                         };\r
10322 \r
10323                         // If root blocks are forced then use Operas default behavior since it's really good\r
10324 // Removed due to bug: #1853816\r
10325 //                      if (se.forced_root_block && isOpera)\r
10326 //                              return true;\r
10327 \r
10328                         // Setup before range\r
10329                         rb = d.createRange();\r
10330 \r
10331                         // If is before the first block element and in body, then move it into first block element\r
10332                         rb.setStart(s.anchorNode, s.anchorOffset);\r
10333                         rb.collapse(true);\r
10334 \r
10335                         // Setup after range\r
10336                         ra = d.createRange();\r
10337 \r
10338                         // If is before the first block element and in body, then move it into first block element\r
10339                         ra.setStart(s.focusNode, s.focusOffset);\r
10340                         ra.collapse(true);\r
10341 \r
10342                         // Setup start/end points\r
10343                         dir = rb.compareBoundaryPoints(rb.START_TO_END, ra) < 0;\r
10344                         sn = dir ? s.anchorNode : s.focusNode;\r
10345                         so = dir ? s.anchorOffset : s.focusOffset;\r
10346                         en = dir ? s.focusNode : s.anchorNode;\r
10347                         eo = dir ? s.focusOffset : s.anchorOffset;\r
10348 \r
10349                         // If selection is in empty table cell\r
10350                         if (sn === en && /^(TD|TH)$/.test(sn.nodeName)) {\r
10351                                 dom.remove(sn.firstChild); // Remove BR\r
10352 \r
10353                                 // Create two new block elements\r
10354                                 ed.dom.add(sn, se.element, null, '<br />');\r
10355                                 aft = ed.dom.add(sn, se.element, null, '<br />');\r
10356 \r
10357                                 // Move caret into the last one\r
10358                                 r = d.createRange();\r
10359                                 r.selectNodeContents(aft);\r
10360                                 r.collapse(1);\r
10361                                 ed.selection.setRng(r);\r
10362 \r
10363                                 return false;\r
10364                         }\r
10365 \r
10366                         // If the caret is in an invalid location in FF we need to move it into the first block\r
10367                         if (sn == b && en == b && b.firstChild && ed.dom.isBlock(b.firstChild)) {\r
10368                                 sn = en = sn.firstChild;\r
10369                                 so = eo = 0;\r
10370                                 rb = d.createRange();\r
10371                                 rb.setStart(sn, 0);\r
10372                                 ra = d.createRange();\r
10373                                 ra.setStart(en, 0);\r
10374                         }\r
10375 \r
10376                         // Never use body as start or end node\r
10377                         sn = sn.nodeName == "HTML" ? d.body : sn; // Fix for Opera bug: https://bugs.opera.com/show_bug.cgi?id=273224&comments=yes\r
10378                         sn = sn.nodeName == "BODY" ? sn.firstChild : sn;\r
10379                         en = en.nodeName == "HTML" ? d.body : en; // Fix for Opera bug: https://bugs.opera.com/show_bug.cgi?id=273224&comments=yes\r
10380                         en = en.nodeName == "BODY" ? en.firstChild : en;\r
10381 \r
10382                         // Get start and end blocks\r
10383                         sb = t.getParentBlock(sn);\r
10384                         eb = t.getParentBlock(en);\r
10385                         bn = sb ? sb.nodeName : se.element; // Get block name to create\r
10386 \r
10387                         // Return inside list use default browser behavior\r
10388                         if (t.dom.getParent(sb, function(n) { return /OL|UL|PRE/.test(n.nodeName); }))\r
10389                                 return true;\r
10390 \r
10391                         // If caption or absolute layers then always generate new blocks within\r
10392                         if (sb && (sb.nodeName == 'CAPTION' || /absolute|relative|static/gi.test(sb.style.position))) {\r
10393                                 bn = se.element;\r
10394                                 sb = null;\r
10395                         }\r
10396 \r
10397                         // If caption or absolute layers then always generate new blocks within\r
10398                         if (eb && (eb.nodeName == 'CAPTION' || /absolute|relative|static/gi.test(eb.style.position))) {\r
10399                                 bn = se.element;\r
10400                                 eb = null;\r
10401                         }\r
10402 \r
10403                         // Use P instead\r
10404                         if (/(TD|TABLE|TH|CAPTION)/.test(bn) || (sb && bn == "DIV" && /left|right/gi.test(sb.style.cssFloat))) {\r
10405                                 bn = se.element;\r
10406                                 sb = eb = null;\r
10407                         }\r
10408 \r
10409                         // Setup new before and after blocks\r
10410                         bef = (sb && sb.nodeName == bn) ? sb.cloneNode(0) : ed.dom.create(bn);\r
10411                         aft = (eb && eb.nodeName == bn) ? eb.cloneNode(0) : ed.dom.create(bn);\r
10412 \r
10413                         // Remove id from after clone\r
10414                         aft.removeAttribute('id');\r
10415 \r
10416                         // Is header and cursor is at the end, then force paragraph under\r
10417                         if (/^(H[1-6])$/.test(bn) && sn.nodeValue && so == sn.nodeValue.length)\r
10418                                 aft = ed.dom.create(se.element);\r
10419 \r
10420                         // Find start chop node\r
10421                         n = sc = sn;\r
10422                         do {\r
10423                                 if (n == b || n.nodeType == 9 || t.dom.isBlock(n) || /(TD|TABLE|TH|CAPTION)/.test(n.nodeName))\r
10424                                         break;\r
10425 \r
10426                                 sc = n;\r
10427                         } while ((n = n.previousSibling ? n.previousSibling : n.parentNode));\r
10428 \r
10429                         // Find end chop node\r
10430                         n = ec = en;\r
10431                         do {\r
10432                                 if (n == b || n.nodeType == 9 || t.dom.isBlock(n) || /(TD|TABLE|TH|CAPTION)/.test(n.nodeName))\r
10433                                         break;\r
10434 \r
10435                                 ec = n;\r
10436                         } while ((n = n.nextSibling ? n.nextSibling : n.parentNode));\r
10437 \r
10438                         // Place first chop part into before block element\r
10439                         if (sc.nodeName == bn)\r
10440                                 rb.setStart(sc, 0);\r
10441                         else\r
10442                                 rb.setStartBefore(sc);\r
10443 \r
10444                         rb.setEnd(sn, so);\r
10445                         bef.appendChild(rb.cloneContents() || d.createTextNode('')); // Empty text node needed for Safari\r
10446 \r
10447                         // Place secnd chop part within new block element\r
10448                         try {\r
10449                                 ra.setEndAfter(ec);\r
10450                         } catch(ex) {\r
10451                                 //console.debug(s.focusNode, s.focusOffset);\r
10452                         }\r
10453 \r
10454                         ra.setStart(en, eo);\r
10455                         aft.appendChild(ra.cloneContents() || d.createTextNode('')); // Empty text node needed for Safari\r
10456 \r
10457                         // Create range around everything\r
10458                         r = d.createRange();\r
10459                         if (!sc.previousSibling && sc.parentNode.nodeName == bn) {\r
10460                                 r.setStartBefore(sc.parentNode);\r
10461                         } else {\r
10462                                 if (rb.startContainer.nodeName == bn && rb.startOffset == 0)\r
10463                                         r.setStartBefore(rb.startContainer);\r
10464                                 else\r
10465                                         r.setStart(rb.startContainer, rb.startOffset);\r
10466                         }\r
10467 \r
10468                         if (!ec.nextSibling && ec.parentNode.nodeName == bn)\r
10469                                 r.setEndAfter(ec.parentNode);\r
10470                         else\r
10471                                 r.setEnd(ra.endContainer, ra.endOffset);\r
10472 \r
10473                         // Delete and replace it with new block elements\r
10474                         r.deleteContents();\r
10475 \r
10476                         if (isOpera)\r
10477                                 ed.getWin().scrollTo(0, vp.y);\r
10478 \r
10479                         // Never wrap blocks in blocks\r
10480                         if (bef.firstChild && bef.firstChild.nodeName == bn)\r
10481                                 bef.innerHTML = bef.firstChild.innerHTML;\r
10482 \r
10483                         if (aft.firstChild && aft.firstChild.nodeName == bn)\r
10484                                 aft.innerHTML = aft.firstChild.innerHTML;\r
10485 \r
10486                         // Padd empty blocks\r
10487                         if (isEmpty(bef))\r
10488                                 bef.innerHTML = '<br />';\r
10489 \r
10490                         function appendStyles(e, en) {\r
10491                                 var nl = [], nn, n, i;\r
10492 \r
10493                                 e.innerHTML = '';\r
10494 \r
10495                                 // Make clones of style elements\r
10496                                 if (se.keep_styles) {\r
10497                                         n = en;\r
10498                                         do {\r
10499                                                 // We only want style specific elements\r
10500                                                 if (/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(n.nodeName)) {\r
10501                                                         nn = n.cloneNode(false);\r
10502                                                         dom.setAttrib(nn, 'id', ''); // Remove ID since it needs to be unique\r
10503                                                         nl.push(nn);\r
10504                                                 }\r
10505                                         } while (n = n.parentNode);\r
10506                                 }\r
10507 \r
10508                                 // Append style elements to aft\r
10509                                 if (nl.length > 0) {\r
10510                                         for (i = nl.length - 1, nn = e; i >= 0; i--)\r
10511                                                 nn = nn.appendChild(nl[i]);\r
10512 \r
10513                                         // Padd most inner style element\r
10514                                         nl[0].innerHTML = isOpera ? '&nbsp;' : '<br />'; // Extra space for Opera so that the caret can move there\r
10515                                         return nl[0]; // Move caret to most inner element\r
10516                                 } else\r
10517                                         e.innerHTML = isOpera ? '&nbsp;' : '<br />'; // Extra space for Opera so that the caret can move there\r
10518                         };\r
10519 \r
10520                         // Fill empty afterblook with current style\r
10521                         if (isEmpty(aft))\r
10522                                 car = appendStyles(aft, en);\r
10523 \r
10524                         // Opera needs this one backwards for older versions\r
10525                         if (isOpera && parseFloat(opera.version()) < 9.5) {\r
10526                                 r.insertNode(bef);\r
10527                                 r.insertNode(aft);\r
10528                         } else {\r
10529                                 r.insertNode(aft);\r
10530                                 r.insertNode(bef);\r
10531                         }\r
10532 \r
10533                         // Normalize\r
10534                         aft.normalize();\r
10535                         bef.normalize();\r
10536 \r
10537                         function first(n) {\r
10538                                 return d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false).nextNode() || n;\r
10539                         };\r
10540 \r
10541                         // Move cursor and scroll into view\r
10542                         r = d.createRange();\r
10543                         r.selectNodeContents(isGecko ? first(car || aft) : car || aft);\r
10544                         r.collapse(1);\r
10545                         s.removeAllRanges();\r
10546                         s.addRange(r);\r
10547 \r
10548                         // 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
10549                         y = ed.dom.getPos(aft).y;\r
10550                         ch = aft.clientHeight;\r
10551 \r
10552                         // Is element within viewport\r
10553                         if (y < vp.y || y + ch > vp.y + vp.h) {\r
10554                                 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
10555                                 //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
10556                         }\r
10557 \r
10558                         return false;\r
10559                 },\r
10560 \r
10561                 backspaceDelete : function(e, bs) {\r
10562                         var t = this, ed = t.editor, b = ed.getBody(), n, se = ed.selection, r = se.getRng(), sc = r.startContainer, n, w, tn;\r
10563 \r
10564                         // The caret sometimes gets stuck in Gecko if you delete empty paragraphs\r
10565                         // This workaround removes the element by hand and moves the caret to the previous element\r
10566                         if (sc && ed.dom.isBlock(sc) && !/^(TD|TH)$/.test(sc.nodeName) && bs) {\r
10567                                 if (sc.childNodes.length == 0 || (sc.childNodes.length == 1 && sc.firstChild.nodeName == 'BR')) {\r
10568                                         // Find previous block element\r
10569                                         n = sc;\r
10570                                         while ((n = n.previousSibling) && !ed.dom.isBlock(n)) ;\r
10571 \r
10572                                         if (n) {\r
10573                                                 if (sc != b.firstChild) {\r
10574                                                         // Find last text node\r
10575                                                         w = ed.dom.doc.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);\r
10576                                                         while (tn = w.nextNode())\r
10577                                                                 n = tn;\r
10578 \r
10579                                                         // Place caret at the end of last text node\r
10580                                                         r = ed.getDoc().createRange();\r
10581                                                         r.setStart(n, n.nodeValue ? n.nodeValue.length : 0);\r
10582                                                         r.setEnd(n, n.nodeValue ? n.nodeValue.length : 0);\r
10583                                                         se.setRng(r);\r
10584 \r
10585                                                         // Remove the target container\r
10586                                                         ed.dom.remove(sc);\r
10587                                                 }\r
10588 \r
10589                                                 return Event.cancel(e);\r
10590                                         }\r
10591                                 }\r
10592                         }\r
10593 \r
10594                         // Gecko generates BR elements here and there, we don't like those so lets remove them\r
10595                         function handler(e) {\r
10596                                 var pr;\r
10597 \r
10598                                 e = e.target;\r
10599 \r
10600                                 // A new BR was created in a block element, remove it\r
10601                                 if (e && e.parentNode && e.nodeName == 'BR' && (n = t.getParentBlock(e))) {\r
10602                                         pr = e.previousSibling;\r
10603 \r
10604                                         Event.remove(b, 'DOMNodeInserted', handler);\r
10605 \r
10606                                         // Is there whitespace at the end of the node before then we might need the pesky BR\r
10607                                         // to place the caret at a correct location see bug: #2013943\r
10608                                         if (pr && pr.nodeType == 3 && /\s+$/.test(pr.nodeValue))\r
10609                                                 return;\r
10610 \r
10611                                         // Only remove BR elements that got inserted in the middle of the text\r
10612                                         if (e.previousSibling || e.nextSibling)\r
10613                                                 ed.dom.remove(e);\r
10614                                 }\r
10615                         };\r
10616 \r
10617                         // Listen for new nodes\r
10618                         Event._add(b, 'DOMNodeInserted', handler);\r
10619 \r
10620                         // Remove listener\r
10621                         window.setTimeout(function() {\r
10622                                 Event._remove(b, 'DOMNodeInserted', handler);\r
10623                         }, 1);\r
10624                 }\r
10625         });\r
10626 })();\r
10627 \r
10628 /* file:jscripts/tiny_mce/classes/ControlManager.js */\r
10629 \r
10630 (function() {\r
10631         // Shorten names\r
10632         var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, extend = tinymce.extend;\r
10633 \r
10634         tinymce.create('tinymce.ControlManager', {\r
10635                 ControlManager : function(ed, s) {\r
10636                         var t = this, i;\r
10637 \r
10638                         s = s || {};\r
10639                         t.editor = ed;\r
10640                         t.controls = {};\r
10641                         t.onAdd = new tinymce.util.Dispatcher(t);\r
10642                         t.onPostRender = new tinymce.util.Dispatcher(t);\r
10643                         t.prefix = s.prefix || ed.id + '_';\r
10644                         t._cls = {};\r
10645 \r
10646                         t.onPostRender.add(function() {\r
10647                                 each(t.controls, function(c) {\r
10648                                         c.postRender();\r
10649                                 });\r
10650                         });\r
10651                 },\r
10652 \r
10653                 get : function(id) {\r
10654                         return this.controls[this.prefix + id] || this.controls[id];\r
10655                 },\r
10656 \r
10657                 setActive : function(id, s) {\r
10658                         var c = null;\r
10659 \r
10660                         if (c = this.get(id))\r
10661                                 c.setActive(s);\r
10662 \r
10663                         return c;\r
10664                 },\r
10665 \r
10666                 setDisabled : function(id, s) {\r
10667                         var c = null;\r
10668 \r
10669                         if (c = this.get(id))\r
10670                                 c.setDisabled(s);\r
10671 \r
10672                         return c;\r
10673                 },\r
10674 \r
10675                 add : function(c) {\r
10676                         var t = this;\r
10677 \r
10678                         if (c) {\r
10679                                 t.controls[c.id] = c;\r
10680                                 t.onAdd.dispatch(c, t);\r
10681                         }\r
10682 \r
10683                         return c;\r
10684                 },\r
10685 \r
10686                 createControl : function(n) {\r
10687                         var c, t = this, ed = t.editor;\r
10688 \r
10689                         each(ed.plugins, function(p) {\r
10690                                 if (p.createControl) {\r
10691                                         c = p.createControl(n, t);\r
10692 \r
10693                                         if (c)\r
10694                                                 return false;\r
10695                                 }\r
10696                         });\r
10697 \r
10698                         switch (n) {\r
10699                                 case "|":\r
10700                                 case "separator":\r
10701                                         return t.createSeparator();\r
10702                         }\r
10703 \r
10704                         if (!c && ed.buttons && (c = ed.buttons[n]))\r
10705                                 return t.createButton(n, c);\r
10706 \r
10707                         return t.add(c);\r
10708                 },\r
10709 \r
10710                 createDropMenu : function(id, s, cc) {\r
10711                         var t = this, ed = t.editor, c, bm, v, cls;\r
10712 \r
10713                         s = extend({\r
10714                                 'class' : 'mceDropDown',\r
10715                                 constrain : ed.settings.constrain_menus\r
10716                         }, s);\r
10717 \r
10718                         s['class'] = s['class'] + ' ' + ed.getParam('skin') + 'Skin';\r
10719                         if (v = ed.getParam('skin_variant'))\r
10720                                 s['class'] += ' ' + ed.getParam('skin') + 'Skin' + v.substring(0, 1).toUpperCase() + v.substring(1);\r
10721 \r
10722                         id = t.prefix + id;\r
10723                         cls = cc || t._cls.dropmenu || tinymce.ui.DropMenu;\r
10724                         c = t.controls[id] = new cls(id, s);\r
10725                         c.onAddItem.add(function(c, o) {\r
10726                                 var s = o.settings;\r
10727 \r
10728                                 s.title = ed.getLang(s.title, s.title);\r
10729 \r
10730                                 if (!s.onclick) {\r
10731                                         s.onclick = function(v) {\r
10732                                                 ed.execCommand(s.cmd, s.ui || false, s.value);\r
10733                                         };\r
10734                                 }\r
10735                         });\r
10736 \r
10737                         ed.onRemove.add(function() {\r
10738                                 c.destroy();\r
10739                         });\r
10740 \r
10741                         // Fix for bug #1897785, #1898007\r
10742                         if (tinymce.isIE) {\r
10743                                 c.onShowMenu.add(function() {\r
10744                                         bm = ed.selection.getBookmark(1);\r
10745                                 });\r
10746 \r
10747                                 c.onHideMenu.add(function() {\r
10748                                         if (bm)\r
10749                                                 ed.selection.moveToBookmark(bm);\r
10750                                 });\r
10751                         }\r
10752 \r
10753                         return t.add(c);\r
10754                 },\r
10755 \r
10756                 createListBox : function(id, s, cc) {\r
10757                         var t = this, ed = t.editor, cmd, c, cls;\r
10758 \r
10759                         if (t.get(id))\r
10760                                 return null;\r
10761 \r
10762                         s.title = ed.translate(s.title);\r
10763                         s.scope = s.scope || ed;\r
10764 \r
10765                         if (!s.onselect) {\r
10766                                 s.onselect = function(v) {\r
10767                                         ed.execCommand(s.cmd, s.ui || false, v || s.value);\r
10768                                 };\r
10769                         }\r
10770 \r
10771                         s = extend({\r
10772                                 title : s.title,\r
10773                                 'class' : 'mce_' + id,\r
10774                                 scope : s.scope,\r
10775                                 control_manager : t\r
10776                         }, s);\r
10777 \r
10778                         id = t.prefix + id;\r
10779 \r
10780                         if (ed.settings.use_native_selects)\r
10781                                 c = new tinymce.ui.NativeListBox(id, s);\r
10782                         else {\r
10783                                 cls = cc || t._cls.listbox || tinymce.ui.ListBox;\r
10784                                 c = new cls(id, s);\r
10785                         }\r
10786 \r
10787                         t.controls[id] = c;\r
10788 \r
10789                         // Fix focus problem in Safari\r
10790                         if (tinymce.isWebKit) {\r
10791                                 c.onPostRender.add(function(c, n) {\r
10792                                         // Store bookmark on mousedown\r
10793                                         Event.add(n, 'mousedown', function() {\r
10794                                                 ed.bookmark = ed.selection.getBookmark('simple');\r
10795                                         });\r
10796 \r
10797                                         // Restore on focus, since it might be lost\r
10798                                         Event.add(n, 'focus', function() {\r
10799                                                 ed.selection.moveToBookmark(ed.bookmark);\r
10800                                                 ed.bookmark = null;\r
10801                                         });\r
10802                                 });\r
10803                         }\r
10804 \r
10805                         if (c.hideMenu)\r
10806                                 ed.onMouseDown.add(c.hideMenu, c);\r
10807 \r
10808                         return t.add(c);\r
10809                 },\r
10810 \r
10811                 createButton : function(id, s, cc) {\r
10812                         var t = this, ed = t.editor, o, c, cls;\r
10813 \r
10814                         if (t.get(id))\r
10815                                 return null;\r
10816 \r
10817                         s.title = ed.translate(s.title);\r
10818                         s.label = ed.translate(s.label);\r
10819                         s.scope = s.scope || ed;\r
10820 \r
10821                         if (!s.onclick && !s.menu_button) {\r
10822                                 s.onclick = function() {\r
10823                                         ed.execCommand(s.cmd, s.ui || false, s.value);\r
10824                                 };\r
10825                         }\r
10826 \r
10827                         s = extend({\r
10828                                 title : s.title,\r
10829                                 'class' : 'mce_' + id,\r
10830                                 unavailable_prefix : ed.getLang('unavailable', ''),\r
10831                                 scope : s.scope,\r
10832                                 control_manager : t\r
10833                         }, s);\r
10834 \r
10835                         id = t.prefix + id;\r
10836 \r
10837                         if (s.menu_button) {\r
10838                                 cls = cc || t._cls.menubutton || tinymce.ui.MenuButton;\r
10839                                 c = new cls(id, s);\r
10840                                 ed.onMouseDown.add(c.hideMenu, c);\r
10841                         } else {\r
10842                                 cls = t._cls.button || tinymce.ui.Button;\r
10843                                 c = new cls(id, s);\r
10844                         }\r
10845 \r
10846                         return t.add(c);\r
10847                 },\r
10848 \r
10849                 createMenuButton : function(id, s, cc) {\r
10850                         s = s || {};\r
10851                         s.menu_button = 1;\r
10852 \r
10853                         return this.createButton(id, s, cc);\r
10854                 },\r
10855 \r
10856                 createSplitButton : function(id, s, cc) {\r
10857                         var t = this, ed = t.editor, cmd, c, cls;\r
10858 \r
10859                         if (t.get(id))\r
10860                                 return null;\r
10861 \r
10862                         s.title = ed.translate(s.title);\r
10863                         s.scope = s.scope || ed;\r
10864 \r
10865                         if (!s.onclick) {\r
10866                                 s.onclick = function(v) {\r
10867                                         ed.execCommand(s.cmd, s.ui || false, v || s.value);\r
10868                                 };\r
10869                         }\r
10870 \r
10871                         if (!s.onselect) {\r
10872                                 s.onselect = function(v) {\r
10873                                         ed.execCommand(s.cmd, s.ui || false, v || s.value);\r
10874                                 };\r
10875                         }\r
10876 \r
10877                         s = extend({\r
10878                                 title : s.title,\r
10879                                 'class' : 'mce_' + id,\r
10880                                 scope : s.scope,\r
10881                                 control_manager : t\r
10882                         }, s);\r
10883 \r
10884                         id = t.prefix + id;\r
10885                         cls = cc || t._cls.splitbutton || tinymce.ui.SplitButton;\r
10886                         c = t.add(new cls(id, s));\r
10887                         ed.onMouseDown.add(c.hideMenu, c);\r
10888 \r
10889                         return c;\r
10890                 },\r
10891 \r
10892                 createColorSplitButton : function(id, s, cc) {\r
10893                         var t = this, ed = t.editor, cmd, c, cls, bm;\r
10894 \r
10895                         if (t.get(id))\r
10896                                 return null;\r
10897 \r
10898                         s.title = ed.translate(s.title);\r
10899                         s.scope = s.scope || ed;\r
10900 \r
10901                         if (!s.onclick) {\r
10902                                 s.onclick = function(v) {\r
10903                                         ed.execCommand(s.cmd, s.ui || false, v || s.value);\r
10904                                 };\r
10905                         }\r
10906 \r
10907                         if (!s.onselect) {\r
10908                                 s.onselect = function(v) {\r
10909                                         ed.execCommand(s.cmd, s.ui || false, v || s.value);\r
10910                                 };\r
10911                         }\r
10912 \r
10913                         s = extend({\r
10914                                 title : s.title,\r
10915                                 'class' : 'mce_' + id,\r
10916                                 'menu_class' : ed.getParam('skin') + 'Skin',\r
10917                                 scope : s.scope,\r
10918                                 more_colors_title : ed.getLang('more_colors')\r
10919                         }, s);\r
10920 \r
10921                         id = t.prefix + id;\r
10922                         cls = cc || t._cls.colorsplitbutton || tinymce.ui.ColorSplitButton;\r
10923                         c = new cls(id, s);\r
10924                         ed.onMouseDown.add(c.hideMenu, c);\r
10925 \r
10926                         // Remove the menu element when the editor is removed\r
10927                         ed.onRemove.add(function() {\r
10928                                 c.destroy();\r
10929                         });\r
10930 \r
10931                         // Fix for bug #1897785, #1898007\r
10932                         if (tinymce.isIE) {\r
10933                                 c.onShowMenu.add(function() {\r
10934                                         bm = ed.selection.getBookmark(1);\r
10935                                 });\r
10936 \r
10937                                 c.onHideMenu.add(function() {\r
10938                                         if (bm) {\r
10939                                                 ed.selection.moveToBookmark(bm);\r
10940                                                 bm = 0;\r
10941                                         }\r
10942                                 });\r
10943                         }\r
10944 \r
10945                         return t.add(c);\r
10946                 },\r
10947 \r
10948                 createToolbar : function(id, s, cc) {\r
10949                         var c, t = this, cls;\r
10950 \r
10951                         id = t.prefix + id;\r
10952                         cls = cc || t._cls.toolbar || tinymce.ui.Toolbar;\r
10953                         c = new cls(id, s);\r
10954 \r
10955                         if (t.get(id))\r
10956                                 return null;\r
10957 \r
10958                         return t.add(c);\r
10959                 },\r
10960 \r
10961                 createSeparator : function(cc) {\r
10962                         var cls = cc || this._cls.separator || tinymce.ui.Separator;\r
10963 \r
10964                         return new cls();\r
10965                 },\r
10966 \r
10967                 setControlType : function(n, c) {\r
10968                         return this._cls[n.toLowerCase()] = c;\r
10969                 },\r
10970 \r
10971                 destroy : function() {\r
10972                         each(this.controls, function(c) {\r
10973                                 c.destroy();\r
10974                         });\r
10975 \r
10976                         this.controls = null;\r
10977                 }\r
10978 \r
10979                 });\r
10980 })();\r
10981 \r
10982 /* file:jscripts/tiny_mce/classes/WindowManager.js */\r
10983 \r
10984 (function() {\r
10985         var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each, isIE = tinymce.isIE, isOpera = tinymce.isOpera;\r
10986 \r
10987         tinymce.create('tinymce.WindowManager', {\r
10988                 WindowManager : function(ed) {\r
10989                         var t = this;\r
10990 \r
10991                         t.editor = ed;\r
10992                         t.onOpen = new Dispatcher(t);\r
10993                         t.onClose = new Dispatcher(t);\r
10994                         t.params = {};\r
10995                         t.features = {};\r
10996                 },\r
10997 \r
10998                 open : function(s, p) {\r
10999                         var t = this, f = '', x, y, mo = t.editor.settings.dialog_type == 'modal', w, sw, sh, vp = tinymce.DOM.getViewPort(), u;\r
11000 \r
11001                         // Default some options\r
11002                         s = s || {};\r
11003                         p = p || {};\r
11004                         sw = isOpera ? vp.w : screen.width; // Opera uses windows inside the Opera window\r
11005                         sh = isOpera ? vp.h : screen.height;\r
11006                         s.name = s.name || 'mc_' + new Date().getTime();\r
11007                         s.width = parseInt(s.width || 320);\r
11008                         s.height = parseInt(s.height || 240);\r
11009                         s.resizable = true;\r
11010                         s.left = s.left || parseInt(sw / 2.0) - (s.width / 2.0);\r
11011                         s.top = s.top || parseInt(sh / 2.0) - (s.height / 2.0);\r
11012                         p.inline = false;\r
11013                         p.mce_width = s.width;\r
11014                         p.mce_height = s.height;\r
11015                         p.mce_auto_focus = s.auto_focus;\r
11016 \r
11017                         if (mo) {\r
11018                                 if (isIE) {\r
11019                                         s.center = true;\r
11020                                         s.help = false;\r
11021                                         s.dialogWidth = s.width + 'px';\r
11022                                         s.dialogHeight = s.height + 'px';\r
11023                                         s.scroll = s.scrollbars || false;\r
11024                                 }\r
11025                         }\r
11026 \r
11027                         // Build features string\r
11028                         each(s, function(v, k) {\r
11029                                 if (tinymce.is(v, 'boolean'))\r
11030                                         v = v ? 'yes' : 'no';\r
11031 \r
11032                                 if (!/^(name|url)$/.test(k)) {\r
11033                                         if (isIE && mo)\r
11034                                                 f += (f ? ';' : '') + k + ':' + v;\r
11035                                         else\r
11036                                                 f += (f ? ',' : '') + k + '=' + v;\r
11037                                 }\r
11038                         });\r
11039 \r
11040                         t.features = s;\r
11041                         t.params = p;\r
11042                         t.onOpen.dispatch(t, s, p);\r
11043 \r
11044                         u = s.url || s.file;\r
11045                         if (tinymce.relaxedDomain)\r
11046                                 u += (u.indexOf('?') == -1 ? '?' : '&') + 'mce_rdomain=' + tinymce.relaxedDomain;\r
11047 \r
11048                         u = tinymce._addVer(u);\r
11049 \r
11050                         try {\r
11051                                 if (isIE && mo) {\r
11052                                         w = 1;\r
11053                                         window.showModalDialog(u, window, f);\r
11054                                 } else\r
11055                                         w = window.open(u, s.name, f);\r
11056                         } catch (ex) {\r
11057                                 // Ignore\r
11058                         }\r
11059 \r
11060                         if (!w)\r
11061                                 alert(t.editor.getLang('popup_blocked'));\r
11062                 },\r
11063 \r
11064                 close : function(w) {\r
11065                         w.close();\r
11066                         this.onClose.dispatch(this);\r
11067                 },\r
11068 \r
11069                 createInstance : function(cl, a, b, c, d, e) {\r
11070                         var f = tinymce.resolve(cl);\r
11071 \r
11072                         return new f(a, b, c, d, e);\r
11073                 },\r
11074 \r
11075                 confirm : function(t, cb, s, w) {\r
11076                         w = w || window;\r
11077 \r
11078                         cb.call(s || this, w.confirm(this._decode(this.editor.getLang(t, t))));\r
11079                 },\r
11080 \r
11081                 alert : function(tx, cb, s, w) {\r
11082                         var t = this;\r
11083 \r
11084                         w = w || window;\r
11085                         w.alert(t._decode(t.editor.getLang(tx, tx)));\r
11086 \r
11087                         if (cb)\r
11088                                 cb.call(s || t);\r
11089                 },\r
11090 \r
11091                 // Internal functions\r
11092 \r
11093                 _decode : function(s) {\r
11094                         return tinymce.DOM.decode(s).replace(/\\n/g, '\n');\r
11095                 }\r
11096 \r
11097                 });\r
11098 }());