alecpl
2008-09-20 c17dc6aa31aaa6e7f61bd25993be55354e428996
commit | author | age
d9344f 1
S 2 /* file:jscripts/tiny_mce/classes/tinymce.js */
3
4 var tinymce = {
5     majorVersion : '3',
18240a 6     minorVersion : '1.0.1',
A 7     releaseDate : '2008-06-18',
d9344f 8
S 9     _init : function() {
18240a 10         var t = this, d = document, w = window, na = navigator, ua = na.userAgent, i, nl, n, base, p, v;
d9344f 11
S 12         // Browser checks
18240a 13         t.isOpera = w.opera && opera.buildNumber;
d9344f 14         t.isWebKit = /WebKit/.test(ua);
18240a 15         t.isOldWebKit = t.isWebKit && !w.getSelection().getRangeAt;
A 16         t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(na.appName);
d9344f 17         t.isIE6 = t.isIE && /MSIE [56]/.test(ua);
S 18         t.isGecko = !t.isWebKit && /Gecko/.test(ua);
19         t.isMac = ua.indexOf('Mac') != -1;
20
21         // TinyMCE .NET webcontrol might be setting the values for TinyMCE
18240a 22         if (w.tinyMCEPreInit) {
d9344f 23             t.suffix = tinyMCEPreInit.suffix;
S 24             t.baseURL = tinyMCEPreInit.base;
18240a 25             t.query = tinyMCEPreInit.query;
d9344f 26             return;
S 27         }
28
29         // Get suffix and base
30         t.suffix = '';
31
32         // If base element found, add that infront of baseURL
18240a 33         nl = d.getElementsByTagName('base');
d9344f 34         for (i=0; i<nl.length; i++) {
18240a 35             if (v = nl[i].href) {
A 36                 // Host only value like http://site.com or http://site.com:8008
37                 if (/^https?:\/\/[^\/]+$/.test(v))
38                     v += '/';
39
40                 base = v ? v.match(/.*\//)[0] : ''; // Get only directory
41             }
d9344f 42         }
S 43
44         function getBase(n) {
45             if (n.src && /tiny_mce(|_dev|_src|_gzip|_jquery|_prototype).js/.test(n.src)) {
46                 if (/_(src|dev)\.js/g.test(n.src))
47                     t.suffix = '_src';
18240a 48
A 49                 if ((p = n.src.indexOf('?')) != -1)
50                     t.query = n.src.substring(p + 1);
d9344f 51
S 52                 t.baseURL = n.src.substring(0, n.src.lastIndexOf('/'));
53
54                 // If path to script is relative and a base href was found add that one infront
55                 if (base && t.baseURL.indexOf('://') == -1)
56                     t.baseURL = base + t.baseURL;
57
58                 return t.baseURL;
59             }
60
61             return null;
62         };
63
64         // Check document
18240a 65         nl = d.getElementsByTagName('script');
d9344f 66         for (i=0; i<nl.length; i++) {
S 67             if (getBase(nl[i]))
68                 return;
69         }
70
71         // Check head
18240a 72         n = d.getElementsByTagName('head')[0];
d9344f 73         if (n) {
S 74             nl = n.getElementsByTagName('script');
75             for (i=0; i<nl.length; i++) {
76                 if (getBase(nl[i]))
77                     return;
78             }
79         }
80
81         return;
82     },
83
84     is : function(o, t) {
85         var n = typeof(o);
86
87         if (!t)
88             return n != 'undefined';
89
90         if (t == 'array' && (o instanceof Array))
91             return true;
92
93         return n == t;
94     },
95
96     // #if !jquery
97
98     each : function(o, cb, s) {
99         var n, l;
100
101         if (!o)
102             return 0;
103
104         s = s || o;
105
106         if (typeof(o.length) != 'undefined') {
107             // Indexed arrays, needed for Safari
108             for (n=0, l = o.length; n<l; n++) {
109                 if (cb.call(s, o[n], n, o) === false)
110                     return 0;
111             }
112         } else {
113             // Hashtables
114             for (n in o) {
115                 if (o.hasOwnProperty(n)) {
116                     if (cb.call(s, o[n], n, o) === false)
117                         return 0;
118                 }
119             }
120         }
121
122         return 1;
123     },
124
125     map : function(a, f) {
126         var o = [];
127
128         tinymce.each(a, function(v) {
129             o.push(f(v));
130         });
131
132         return o;
133     },
134
135     grep : function(a, f) {
136         var o = [];
137
138         tinymce.each(a, function(v) {
139             if (!f || f(v))
140                 o.push(v);
141         });
142
143         return o;
144     },
145
146     inArray : function(a, v) {
147         var i, l;
148
149         if (a) {
150             for (i = 0, l = a.length; i < l; i++) {
151                 if (a[i] === v)
152                     return i;
153             }
154         }
155
156         return -1;
157     },
158
159     extend : function(o, e) {
160         var i, a = arguments;
161
162         for (i=1; i<a.length; i++) {
163             e = a[i];
164
165             tinymce.each(e, function(v, n) {
166                 if (typeof(v) !== 'undefined')
167                     o[n] = v;
168             });
169         }
170
171         return o;
172     },
173
174     trim : function(s) {
175         return (s ? '' + s : '').replace(/^\s*|\s*$/g, '');
176     },
177
178     // #endif
179
180     create : function(s, p) {
181         var t = this, sp, ns, cn, scn, c, de = 0;
182
183         // Parse : <prefix> <class>:<super class>
184         s = /^((static) )?([\w.]+)(:([\w.]+))?/.exec(s);
185         cn = s[3].match(/(^|\.)(\w+)$/i)[2]; // Class name
186
187         // Create namespace for new class
188         ns = t.createNS(s[3].replace(/\.\w+$/, ''));
189
190         // Class already exists
191         if (ns[cn])
192             return;
193
194         // Make pure static class
195         if (s[2] == 'static') {
196             ns[cn] = p;
197
198             if (this.onCreate)
199                 this.onCreate(s[2], s[3], ns[cn]);
200
201             return;
202         }
203
204         // Create default constructor
205         if (!p[cn]) {
206             p[cn] = function() {};
207             de = 1;
208         }
209
210         // Add constructor and methods
211         ns[cn] = p[cn];
212         t.extend(ns[cn].prototype, p);
213
214         // Extend
215         if (s[5]) {
216             sp = t.resolve(s[5]).prototype;
217             scn = s[5].match(/\.(\w+)$/i)[1]; // Class name
218
219             // Extend constructor
220             c = ns[cn];
221             if (de) {
222                 // Add passthrough constructor
223                 ns[cn] = function() {
224                     return sp[scn].apply(this, arguments);
225                 };
226             } else {
227                 // Add inherit constructor
228                 ns[cn] = function() {
229                     this.parent = sp[scn];
230                     return c.apply(this, arguments);
231                 };
232             }
233             ns[cn].prototype[cn] = ns[cn];
234
235             // Add super methods
236             t.each(sp, function(f, n) {
237                 ns[cn].prototype[n] = sp[n];
238             });
239
240             // Add overridden methods
241             t.each(p, function(f, n) {
242                 // Extend methods if needed
243                 if (sp[n]) {
244                     ns[cn].prototype[n] = function() {
245                         this.parent = sp[n];
246                         return f.apply(this, arguments);
247                     };
248                 } else {
249                     if (n != cn)
250                         ns[cn].prototype[n] = f;
251                 }
252             });
253         }
254
255         // Add static methods
256         t.each(p['static'], function(f, n) {
257             ns[cn][n] = f;
258         });
259
260         if (this.onCreate)
261             this.onCreate(s[2], s[3], ns[cn].prototype);
262     },
263
264     walk : function(o, f, n, s) {
265         s = s || this;
266
267         if (o) {
268             if (n)
269                 o = o[n];
270
271             tinymce.each(o, function(o, i) {
272                 if (f.call(s, o, i, n) === false)
273                     return false;
274
275                 tinymce.walk(o, f, n, s);
276             });
277         }
278     },
279
280     createNS : function(n, o) {
281         var i, v;
282
283         o = o || window;
284
285         n = n.split('.');
286         for (i=0; i<n.length; i++) {
287             v = n[i];
288
289             if (!o[v])
290                 o[v] = {};
291
292             o = o[v];
293         }
294
295         return o;
296     },
297
298     resolve : function(n, o) {
299         var i, l;
300
301         o = o || window;
302
303         n = n.split('.');
304         for (i=0, l = n.length; i<l; i++) {
305             o = o[n[i]];
306
307             if (!o)
308                 break;
309         }
310
311         return o;
312     },
313
314     addUnload : function(f, s) {
18240a 315         var t = this, w = window;
d9344f 316
S 317         f = {func : f, scope : s || this};
318
319         if (!t.unloads) {
18240a 320             function unload() {
d9344f 321                 var li = t.unloads, o, n;
S 322
18240a 323                 if (li) {
A 324                     // Call unload handlers
325                     for (n in li) {
326                         o = li[n];
d9344f 327
18240a 328                         if (o && o.func)
A 329                             o.func.call(o.scope, 1); // Send in one arg to distinct unload and user destroy
330                     }
331
332                     // Detach unload function
333                     if (w.detachEvent) {
334                         w.detachEvent('onbeforeunload', fakeUnload);
335                         w.detachEvent('onunload', unload);
336                     } else if (w.removeEventListener)
337                         w.removeEventListener('unload', unload, false);
338
339                     // Destroy references
340                     t.unloads = o = li = w = unload = null;
341
342                     // Run garbarge collector on IE
343                     if (window.CollectGarbage)
344                         window.CollectGarbage();
d9344f 345                 }
18240a 346             };
d9344f 347
18240a 348             function fakeUnload() {
A 349                 var d = document;
d9344f 350
18240a 351                 // Is there things still loading, then do some magic
A 352                 if (d.readyState == 'interactive') {
353                     function stop() {
354                         // Prevent memory leak
355                         d.detachEvent('onstop', stop);
d9344f 356
18240a 357                         // Call unload handler
A 358                         unload();
359
360                         d = null;
361                     };
362
363                     // Fire unload when the currently loading page is stopped
364                     d.attachEvent('onstop', stop);
365
366                     // Remove onstop listener after a while to prevent the unload function
367                     // to execute if the user presses cancel in an onbeforeunload
368                     // confirm dialog and then presses the browser stop button
369                     window.setTimeout(function() {
370                         d.detachEvent('onstop', stop);
371                     }, 0);
372                 }
d9344f 373             };
S 374
375             // Attach unload handler
18240a 376             if (w.attachEvent) {
d9344f 377                 w.attachEvent('onunload', unload);
18240a 378                 w.attachEvent('onbeforeunload', fakeUnload);
A 379             } else if (w.addEventListener)
d9344f 380                 w.addEventListener('unload', unload, false);
S 381
382             // Setup initial unload handler array
383             t.unloads = [f];
384         } else
385             t.unloads.push(f);
386
387         return f;
388     },
389
390     removeUnload : function(f) {
391         var u = this.unloads, r = null;
392
393         tinymce.each(u, function(o, i) {
394             if (o && o.func == f) {
395                 u.splice(i, 1);
396                 r = f;
397                 return false;
398             }
399         });
400
401         return r;
402     },
403
404     explode : function(s, d) {
18240a 405         return s ? tinymce.map(s.split(d || ','), tinymce.trim) : s;
A 406     },
407
408     _addVer : function(u) {
409         var v;
410
411         if (!this.query)
412             return u;
413
414         v = (u.indexOf('?') == -1 ? '?' : '&') + this.query;
415
416         if (u.indexOf('#') == -1)
417             return u + v;
418
419         return u.replace('#', v + '#');
d9344f 420     }
S 421
422     };
423
424 // Required for GZip AJAX loading
425 window.tinymce = tinymce;
426
427 // Initialize the API
428 tinymce._init();
429
430 /* file:jscripts/tiny_mce/classes/adapter/jquery/adapter.js */
431
432
433 /* file:jscripts/tiny_mce/classes/adapter/prototype/adapter.js */
434
435
436 /* file:jscripts/tiny_mce/classes/util/Dispatcher.js */
437
438 tinymce.create('tinymce.util.Dispatcher', {
439     scope : null,
440     listeners : null,
441
442     Dispatcher : function(s) {
443         this.scope = s || this;
444         this.listeners = [];
445     },
446
447     add : function(cb, s) {
448         this.listeners.push({cb : cb, scope : s || this.scope});
449
450         return cb;
451     },
452
453     addToTop : function(cb, s) {
454         this.listeners.unshift({cb : cb, scope : s || this.scope});
455
456         return cb;
457     },
458
459     remove : function(cb) {
460         var l = this.listeners, o = null;
461
462         tinymce.each(l, function(c, i) {
463             if (cb == c.cb) {
464                 o = cb;
465                 l.splice(i, 1);
466                 return false;
467             }
468         });
469
470         return o;
471     },
472
473     dispatch : function() {
474         var s, a = arguments, i, li = this.listeners, c;
475
476         // Needs to be a real loop since the listener count might change while looping
477         // And this is also more efficient
478         for (i = 0; i<li.length; i++) {
479             c = li[i];
480             s = c.cb.apply(c.scope, a);
481
482             if (s === false)
483                 break;
484         }
485
486         return s;
487     }
488
489     });
490
491 /* file:jscripts/tiny_mce/classes/util/URI.js */
492
493 (function() {
494     var each = tinymce.each;
495
496     tinymce.create('tinymce.util.URI', {
497         URI : function(u, s) {
498             var t = this, o, a, b;
499
500             // Default settings
501             s = t.settings = s || {};
502
503             // Strange app protocol or local anchor
504             if (/^(mailto|news|javascript|about):/i.test(u) || /^\s*#/.test(u)) {
505                 t.source = u;
506                 return;
507             }
508
509             // Absolute path with no host, fake host and protocol
510             if (u.indexOf('/') === 0 && u.indexOf('//') !== 0)
511                 u = (s.base_uri ? s.base_uri.protocol || 'http' : 'http') + '://mce_host' + u;
512
513             // Relative path
514             if (u.indexOf('://') === -1 && u.indexOf('//') !== 0)
515                 u = (s.base_uri.protocol || 'http') + '://mce_host' + t.toAbsPath(s.base_uri.path, u);
516
517             // Parse URL (Credits goes to Steave, http://blog.stevenlevithan.com/archives/parseuri)
518             u = u.replace(/@@/g, '(mce_at)'); // Zope 3 workaround, they use @@something
519             u = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(u);
520             each(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], function(v, i) {
521                 var s = u[i];
522
523                 // Zope 3 workaround, they use @@something
524                 if (s)
525                     s = s.replace(/\(mce_at\)/g, '@@');
526
527                 t[v] = s;
528             });
529
530             if (b = s.base_uri) {
531                 if (!t.protocol)
532                     t.protocol = b.protocol;
533
534                 if (!t.userInfo)
535                     t.userInfo = b.userInfo;
536
537                 if (!t.port && t.host == 'mce_host')
538                     t.port = b.port;
539
540                 if (!t.host || t.host == 'mce_host')
541                     t.host = b.host;
542
543                 t.source = '';
544             }
545
546             //t.path = t.path || '/';
547         },
548
549         setPath : function(p) {
550             var t = this;
551
552             p = /^(.*?)\/?(\w+)?$/.exec(p);
553
554             // Update path parts
555             t.path = p[0];
556             t.directory = p[1];
557             t.file = p[2];
558
559             // Rebuild source
560             t.source = '';
561             t.getURI();
562         },
563
564         toRelative : function(u) {
565             var t = this, o;
566
567             u = new tinymce.util.URI(u, {base_uri : t});
568
569             // Not on same domain/port or protocol
570             if ((u.host != 'mce_host' && t.host != u.host && u.host) || t.port != u.port || t.protocol != u.protocol)
571                 return u.getURI();
572
573             o = t.toRelPath(t.path, u.path);
574
575             // Add query
576             if (u.query)
577                 o += '?' + u.query;
578
579             // Add anchor
580             if (u.anchor)
581                 o += '#' + u.anchor;
582
583             return o;
584         },
585     
586         toAbsolute : function(u, nh) {
587             var u = new tinymce.util.URI(u, {base_uri : this});
588
589             return u.getURI(this.host == u.host ? nh : 0);
590         },
591
592         toRelPath : function(base, path) {
593             var items, bp = 0, out = '', i;
594
595             // Split the paths
596             base = base.substring(0, base.lastIndexOf('/'));
597             base = base.split('/');
598             items = path.split('/');
599
600             if (base.length >= items.length) {
601                 for (i = 0; i < base.length; i++) {
602                     if (i >= items.length || base[i] != items[i]) {
603                         bp = i + 1;
604                         break;
605                     }
606                 }
607             }
608
609             if (base.length < items.length) {
610                 for (i = 0; i < items.length; i++) {
611                     if (i >= base.length || base[i] != items[i]) {
612                         bp = i + 1;
613                         break;
614                     }
615                 }
616             }
617
618             if (bp == 1)
619                 return path;
620
621             for (i = 0; i < base.length - (bp - 1); i++)
622                 out += "../";
623
624             for (i = bp - 1; i < items.length; i++) {
625                 if (i != bp - 1)
626                     out += "/" + items[i];
627                 else
628                     out += items[i];
629             }
630
631             return out;
632         },
633
634         toAbsPath : function(base, path) {
635             var i, nb = 0, o = [];
636
637             // Split paths
638             base = base.split('/');
639             path = path.split('/');
640
641             // Remove empty chunks
642             each(base, function(k) {
643                 if (k)
644                     o.push(k);
645             });
646
647             base = o;
648
649             // Merge relURLParts chunks
650             for (i = path.length - 1, o = []; i >= 0; i--) {
651                 // Ignore empty or .
652                 if (path[i].length == 0 || path[i] == ".")
653                     continue;
654
655                 // Is parent
656                 if (path[i] == '..') {
657                     nb++;
658                     continue;
659                 }
660
661                 // Move up
662                 if (nb > 0) {
663                     nb--;
664                     continue;
665                 }
666
667                 o.push(path[i]);
668             }
669
670             i = base.length - nb;
671
672             // If /a/b/c or /
673             if (i <= 0)
674                 return '/' + o.reverse().join('/');
675
676             return '/' + base.slice(0, i).join('/') + '/' + o.reverse().join('/');
677         },
678
679         getURI : function(nh) {
680             var s, t = this;
681
682             // Rebuild source
683             if (!t.source || nh) {
684                 s = '';
685
686                 if (!nh) {
687                     if (t.protocol)
688                         s += t.protocol + '://';
689
690                     if (t.userInfo)
691                         s += t.userInfo + '@';
692
693                     if (t.host)
694                         s += t.host;
695
696                     if (t.port)
697                         s += ':' + t.port;
698                 }
699
700                 if (t.path)
701                     s += t.path;
702
703                 if (t.query)
704                     s += '?' + t.query;
705
706                 if (t.anchor)
707                     s += '#' + t.anchor;
708
709                 t.source = s;
710             }
711
712             return t.source;
713         }
714
715         });
716 })();
717
718 /* file:jscripts/tiny_mce/classes/util/Cookie.js */
719
720 (function() {
721     var each = tinymce.each;
722
723     tinymce.create('static tinymce.util.Cookie', {
724         getHash : function(n) {
725             var v = this.get(n), h;
726
727             if (v) {
728                 each(v.split('&'), function(v) {
729                     v = v.split('=');
730                     h = h || {};
731                     h[unescape(v[0])] = unescape(v[1]);
732                 });
733             }
734
735             return h;
736         },
737
738         setHash : function(n, v, e, p, d, s) {
739             var o = '';
740
741             each(v, function(v, k) {
742                 o += (!o ? '' : '&') + escape(k) + '=' + escape(v);
743             });
744
745             this.set(n, o, e, p, d, s);
746         },
747
748         get : function(n) {
749             var c = document.cookie, e, p = n + "=", b;
750
751             // Strict mode
752             if (!c)
753                 return;
754
755             b = c.indexOf("; " + p);
756
757             if (b == -1) {
758                 b = c.indexOf(p);
759
760                 if (b != 0)
761                     return null;
762             } else
763                 b += 2;
764
765             e = c.indexOf(";", b);
766
767             if (e == -1)
768                 e = c.length;
769
770             return unescape(c.substring(b + p.length, e));
771         },
772
773         set : function(n, v, e, p, d, s) {
774             document.cookie = n + "=" + escape(v) +
775                 ((e) ? "; expires=" + e.toGMTString() : "") +
776                 ((p) ? "; path=" + escape(p) : "") +
777                 ((d) ? "; domain=" + d : "") +
778                 ((s) ? "; secure" : "");
779         },
780
781         remove : function(n, p) {
782             var d = new Date();
783
784             d.setTime(d.getTime() - 1000);
785
786             this.set(n, '', d, p, d);
787         }
788
789         });
790 })();
791
792 /* file:jscripts/tiny_mce/classes/util/JSON.js */
793
794 tinymce.create('static tinymce.util.JSON', {
795     serialize : function(o) {
796         var i, v, s = tinymce.util.JSON.serialize, t;
797
798         if (o == null)
799             return 'null';
800
801         t = typeof o;
802
803         if (t == 'string') {
804             v = '\bb\tt\nn\ff\rr\""\'\'\\\\';
805
806             return '"' + o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'])/g, function(a, b) {
807                 i = v.indexOf(b);
808
809                 if (i + 1)
810                     return '\\' + v.charAt(i + 1);
811
812                 a = b.charCodeAt().toString(16);
813
814                 return '\\u' + '0000'.substring(a.length) + a;
815             }) + '"';
816         }
817
818         if (t == 'object') {
819             if (o instanceof Array) {
820                     for (i=0, v = '['; i<o.length; i++)
821                         v += (i > 0 ? ',' : '') + s(o[i]);
822
823                     return v + ']';
824                 }
825
826                 v = '{';
827
828                 for (i in o)
829                     v += typeof o[i] != 'function' ? (v.length > 1 ? ',"' : '"') + i + '":' + s(o[i]) : '';
830
831                 return v + '}';
832         }
833
834         return '' + o;
835     },
836
837     parse : function(s) {
838         try {
839             return eval('(' + s + ')');
840         } catch (ex) {
841             // Ignore
842         }
843     }
844
845     });
846
847 /* file:jscripts/tiny_mce/classes/util/XHR.js */
848
849 tinymce.create('static tinymce.util.XHR', {
850     send : function(o) {
851         var x, t, w = window, c = 0;
852
853         // Default settings
854         o.scope = o.scope || this;
855         o.success_scope = o.success_scope || o.scope;
856         o.error_scope = o.error_scope || o.scope;
857         o.async = o.async === false ? false : true;
858         o.data = o.data || '';
859
860         function get(s) {
861             x = 0;
862
863             try {
864                 x = new ActiveXObject(s);
865             } catch (ex) {
866             }
867
868             return x;
869         };
870
871         x = w.XMLHttpRequest ? new XMLHttpRequest() : get('Microsoft.XMLHTTP') || get('Msxml2.XMLHTTP');
872
873         if (x) {
874             if (x.overrideMimeType)
875                 x.overrideMimeType(o.content_type);
876
877             x.open(o.type || (o.data ? 'POST' : 'GET'), o.url, o.async);
878
879             if (o.content_type)
880                 x.setRequestHeader('Content-Type', o.content_type);
881
882             x.send(o.data);
883
18240a 884             function ready() {
A 885                 if (!o.async || x.readyState == 4 || c++ > 10000) {
d9344f 886                     if (o.success && c < 10000 && x.status == 200)
S 887                         o.success.call(o.success_scope, '' + x.responseText, x, o);
888                     else if (o.error)
889                         o.error.call(o.error_scope, c > 10000 ? 'TIMED_OUT' : 'GENERAL', x, o);
890
891                     x = null;
18240a 892                 } else
A 893                     w.setTimeout(ready, 10);
894             };
895
896             // Syncronous request
897             if (!o.async)
898                 return ready();
899
900             // Wait for response, onReadyStateChange can not be used since it leaks memory in IE
901             t = w.setTimeout(ready, 10);
d9344f 902         }
S 903
904         }
905 });
906
907 /* file:jscripts/tiny_mce/classes/util/JSONRequest.js */
908
909 (function() {
910     var extend = tinymce.extend, JSON = tinymce.util.JSON, XHR = tinymce.util.XHR;
911
912     tinymce.create('tinymce.util.JSONRequest', {
913         JSONRequest : function(s) {
914             this.settings = extend({
915             }, s);
916             this.count = 0;
917         },
918
919         send : function(o) {
920             var ecb = o.error, scb = o.success;
921
922             o = extend(this.settings, o);
923
924             o.success = function(c, x) {
925                 c = JSON.parse(c);
926
927                 if (typeof(c) == 'undefined') {
928                     c = {
929                         error : 'JSON Parse error.'
930                     };
931                 }
932
933                 if (c.error)
934                     ecb.call(o.error_scope || o.scope, c.error, x);
935                 else
936                     scb.call(o.success_scope || o.scope, c.result);
937             };
938
939             o.error = function(ty, x) {
940                 ecb.call(o.error_scope || o.scope, ty, x);
941             };
942
943             o.data = JSON.serialize({
944                 id : o.id || 'c' + (this.count++),
945                 method : o.method,
946                 params : o.params
947             });
948
949             // JSON content type for Ruby on rails. Bug: #1883287
950             o.content_type = 'application/json';
951
952             XHR.send(o);
953         },
954
955         'static' : {
956             sendRPC : function(o) {
957                 return new tinymce.util.JSONRequest().send(o);
958             }
959         }
960
961         });
962 }());
963 /* file:jscripts/tiny_mce/classes/dom/DOMUtils.js */
964
965 (function() {
966     // Shorten names
967     var each = tinymce.each, is = tinymce.is;
968     var isWebKit = tinymce.isWebKit, isIE = tinymce.isIE;
969
970     tinymce.create('tinymce.dom.DOMUtils', {
971         doc : null,
972         root : null,
973         files : null,
974         listeners : {},
975         pixelStyles : /^(top|left|bottom|right|width|height|borderWidth)$/,
976         cache : {},
977         idPattern : /^#[\w]+$/,
978         elmPattern : /^[\w_*]+$/,
979         elmClassPattern : /^([\w_]*)\.([\w_]+)$/,
980
981         DOMUtils : function(d, s) {
982             var t = this;
983
984             t.doc = d;
985             t.win = window;
986             t.files = {};
987             t.cssFlicker = false;
988             t.counter = 0;
989             t.boxModel = !tinymce.isIE || d.compatMode == "CSS1Compat"; 
990             t.stdMode = d.documentMode === 8;
991
992             this.settings = s = tinymce.extend({
993                 keep_values : false,
994                 hex_colors : 1,
995                 process_html : 1
996             }, s);
997
998             // Fix IE6SP2 flicker and check it failed for pre SP2
999             if (tinymce.isIE6) {
1000                 try {
1001                     d.execCommand('BackgroundImageCache', false, true);
1002                 } catch (e) {
1003                     t.cssFlicker = true;
1004                 }
1005             }
1006
1007             tinymce.addUnload(t.destroy, t);
1008         },
1009
1010         getRoot : function() {
1011             var t = this, s = t.settings;
1012
1013             return (s && t.get(s.root_element)) || t.doc.body;
1014         },
1015
1016         getViewPort : function(w) {
1017             var d, b;
1018
1019             w = !w ? this.win : w;
1020             d = w.document;
1021             b = this.boxModel ? d.documentElement : d.body;
1022
1023             // Returns viewport size excluding scrollbars
1024             return {
1025                 x : w.pageXOffset || b.scrollLeft,
1026                 y : w.pageYOffset || b.scrollTop,
1027                 w : w.innerWidth || b.clientWidth,
1028                 h : w.innerHeight || b.clientHeight
1029             };
1030         },
1031
1032         getRect : function(e) {
1033             var p, t = this, w, h;
1034
1035             e = t.get(e);
1036             p = t.getPos(e);
1037             w = t.getStyle(e, 'width');
1038             h = t.getStyle(e, 'height');
1039
1040             // Non pixel value, then force offset/clientWidth
1041             if (w.indexOf('px') === -1)
1042                 w = 0;
1043
1044             // Non pixel value, then force offset/clientWidth
1045             if (h.indexOf('px') === -1)
1046                 h = 0;
1047
1048             return {
1049                 x : p.x,
1050                 y : p.y,
1051                 w : parseInt(w) || e.offsetWidth || e.clientWidth,
1052                 h : parseInt(h) || e.offsetHeight || e.clientHeight
1053             };
1054         },
1055
1056         getParent : function(n, f, r) {
1057             var na, se = this.settings;
1058
1059             n = this.get(n);
1060
1061             if (se.strict_root)
1062                 r = r || this.getRoot();
1063
1064             // Wrap node name as func
1065             if (is(f, 'string')) {
1066                 na = f.toUpperCase();
1067
1068                 f = function(n) {
1069                     var s = false;
1070
1071                     // Any element
1072                     if (n.nodeType == 1 && na === '*') {
1073                         s = true;
1074                         return false;
1075                     }
1076
1077                     each(na.split(','), function(v) {
18240a 1078                         if (n.nodeType == 1 && ((se.strict && n.nodeName.toUpperCase() == v) || n.nodeName.toUpperCase() == v)) {
d9344f 1079                             s = true;
S 1080                             return false; // Break loop
1081                         }
1082                     });
1083
1084                     return s;
1085                 };
1086             }
1087
1088             while (n) {
1089                 if (n == r)
1090                     return null;
1091
1092                 if (f(n))
1093                     return n;
1094
1095                 n = n.parentNode;
1096             }
1097
1098             return null;
1099         },
1100
1101         get : function(e) {
1102             var n;
1103
18240a 1104             if (e && this.doc && typeof(e) == 'string') {
d9344f 1105                 n = e;
S 1106                 e = this.doc.getElementById(e);
1107
1108                 // IE and Opera returns meta elements when they match the specified input ID, but getElementsByName seems to do the trick
1109                 if (e && e.id !== n)
1110                     return this.doc.getElementsByName(n)[1];
1111             }
1112
1113             return e;
1114         },
1115
1116         // #if !jquery
1117
1118         select : function(pa, s) {
1119             var t = this, cs, c, pl, o = [], x, i, l, n;
1120
1121             s = t.get(s) || t.doc;
1122
1123             // Look for native support and use that if it's found
1124             if (s.querySelectorAll) {
1125                 // Element scope then use temp id
1126                 // We need to do this to be compatible with other implementations
1127                 // See bug report: http://bugs.webkit.org/show_bug.cgi?id=17461
1128                 if (s != t.doc) {
1129                     i = s.id;
1130                     s.id = '_mc_tmp';
1131                     pa = '#_mc_tmp ' + pa;
1132                 }
1133
1134                 // Select elements
1135                 l = tinymce.grep(s.querySelectorAll(pa));
1136
1137                 // Restore old id
1138                 s.id = i;
1139
1140                 return l;
1141             }
1142
1143             if (t.settings.strict) {
1144                 function get(s, n) {
1145                     return s.getElementsByTagName(n.toLowerCase());
1146                 };
1147             } else {
1148                 function get(s, n) {
1149                     return s.getElementsByTagName(n);
1150                 };
1151             }
1152
1153             // Simple element pattern. For example: "p" or "*"
1154             if (t.elmPattern.test(pa)) {
1155                 x = get(s, pa);
1156
1157                 for (i = 0, l = x.length; i<l; i++)
1158                     o.push(x[i]);
1159
1160                 return o;
1161             }
1162
1163             // Simple class pattern. For example: "p.class" or ".class"
1164             if (t.elmClassPattern.test(pa)) {
1165                 pl = t.elmClassPattern.exec(pa);
1166                 x = get(s, pl[1] || '*');
1167                 c = ' ' + pl[2] + ' ';
1168
1169                 for (i = 0, l = x.length; i<l; i++) {
1170                     n = x[i];
1171
1172                     if (n.className && (' ' + n.className + ' ').indexOf(c) !== -1)
1173                         o.push(n);
1174                 }
1175
1176                 return o;
1177             }
1178
1179             function collect(n) {
1180                 if (!n.mce_save) {
1181                     n.mce_save = 1;
1182                     o.push(n);
1183                 }
1184             };
1185
1186             function collectIE(n) {
1187                 if (!n.getAttribute('mce_save')) {
1188                     n.setAttribute('mce_save', '1');
1189                     o.push(n);
1190                 }
1191             };
1192
1193             function find(n, f, r) {
1194                 var i, l, nl = get(r, n);
1195
1196                 for (i = 0, l = nl.length; i < l; i++)
1197                     f(nl[i]);
1198             };
1199
1200             each(pa.split(','), function(v, i) {
1201                 v = tinymce.trim(v);
1202
1203                 // Simple element pattern, most common in TinyMCE
1204                 if (t.elmPattern.test(v)) {
1205                     each(get(s, v), function(n) {
1206                         collect(n);
1207                     });
1208
1209                     return;
1210                 }
1211
1212                 // Simple element pattern with class, fairly common in TinyMCE
1213                 if (t.elmClassPattern.test(v)) {
1214                     x = t.elmClassPattern.exec(v);
1215
1216                     each(get(s, x[1]), function(n) {
1217                         if (t.hasClass(n, x[2]))
1218                             collect(n);
1219                     });
1220
1221                     return;
1222                 }
1223
1224                 if (!(cs = t.cache[pa])) {
1225                     cs = 'x=(function(cf, s) {';
1226                     pl = v.split(' ');
1227
1228                     each(pl, function(v) {
1229                         var p = /^([\w\\*]+)?(?:#([\w\\]+))?(?:\.([\w\\\.]+))?(?:\[\@([\w\\]+)([\^\$\*!]?=)([\w\\]+)\])?(?:\:([\w\\]+))?/i.exec(v);
1230
1231                         // Find elements
1232                         p[1] = p[1] || '*';
1233                         cs += 'find("' + p[1] + '", function(n) {';
1234
1235                         // Check id
1236                         if (p[2])
1237                             cs += 'if (n.id !== "' + p[2] + '") return;';
1238
1239                         // Check classes
1240                         if (p[3]) {
1241                             cs += 'var c = " " + n.className + " ";';
1242                             cs += 'if (';
1243                             c = '';
1244                             each(p[3].split('.'), function(v) {
1245                                 if (v)
1246                                     c += (c ? '||' : '') + 'c.indexOf(" ' + v + ' ") === -1';
1247                             });
1248                             cs += c + ') return;';
1249                         }
1250                     });
1251
1252                     cs += 'cf(n);';
1253
1254                     for (i = pl.length - 1; i >= 0; i--)
1255                         cs += '}, ' + (i ? 'n' : 's') + ');';
1256
1257                     cs += '})';
1258
1259                     // Compile CSS pattern function
1260                     t.cache[pa] = cs = eval(cs);
1261                 }
1262
1263                 // Run selector function
1264                 cs(isIE ? collectIE : collect, s);
1265             });
1266
1267             // Cleanup
1268             each(o, function(n) {
1269                 if (isIE)
1270                     n.removeAttribute('mce_save');
1271                 else
1272                     delete n.mce_save;
1273             });
1274
1275             return o;
1276         },
1277
1278         // #endif
1279
1280         add : function(p, n, a, h, c) {
1281             var t = this;
1282
1283             return this.run(p, function(p) {
1284                 var e, k;
1285
1286                 e = is(n, 'string') ? t.doc.createElement(n) : n;
1287
1288                 if (a) {
1289                     for (k in a) {
1290                         if (a.hasOwnProperty(k) && !is(a[k], 'object'))
1291                             t.setAttrib(e, k, '' + a[k]);
1292                     }
1293
1294                     if (a.style && !is(a.style, 'string')) {
1295                         each(a.style, function(v, n) {
1296                             t.setStyle(e, n, v);
1297                         });
1298                     }
1299                 }
1300
1301                 if (h) {
1302                     if (h.nodeType)
1303                         e.appendChild(h);
1304                     else
1305                         t.setHTML(e, h);
1306                 }
1307
1308                 return !c ? p.appendChild(e) : e;
1309             });
1310         },
1311
1312         create : function(n, a, h) {
1313             return this.add(this.doc.createElement(n), n, a, h, 1);
1314         },
1315
1316         createHTML : function(n, a, h) {
1317             var o = '', t = this, k;
1318
1319             o += '<' + n;
1320
1321             for (k in a) {
1322                 if (a.hasOwnProperty(k))
1323                     o += ' ' + k + '="' + t.encode(a[k]) + '"';
1324             }
1325
1326             if (tinymce.is(h))
1327                 return o + '>' + h + '</' + n + '>';
1328
1329             return o + ' />';
1330         },
1331
1332         remove : function(n, k) {
1333             return this.run(n, function(n) {
1334                 var p, g;
1335
1336                 p = n.parentNode;
1337
1338                 if (!p)
1339                     return null;
1340
1341                 if (k) {
1342                     each (n.childNodes, function(c) {
1343                         p.insertBefore(c.cloneNode(true), n);
1344                     });
1345                 }
1346
1347                 // Fix IE psuedo leak
1348         /*        if (isIE) {
1349                     p = n.cloneNode(true);
1350                     n.outerHTML = '';
1351
1352                     return p;
1353                 }*/
1354
1355                 return p.removeChild(n);
1356             });
1357         },
1358
1359         // #if !jquery
1360
1361         setStyle : function(n, na, v) {
1362             var t = this;
1363
1364             return t.run(n, function(e) {
1365                 var s, i;
1366
1367                 s = e.style;
1368
1369                 // Camelcase it, if needed
1370                 na = na.replace(/-(\D)/g, function(a, b){
1371                     return b.toUpperCase();
1372                 });
1373
1374                 // Default px suffix on these
1375                 if (t.pixelStyles.test(na) && (tinymce.is(v, 'number') || /^[\-0-9\.]+$/.test(v)))
1376                     v += 'px';
1377
1378                 switch (na) {
1379                     case 'opacity':
1380                         // IE specific opacity
1381                         if (isIE) {
1382                             s.filter = v === '' ? '' : "alpha(opacity=" + (v * 100) + ")";
1383
1384                             if (!n.currentStyle || !n.currentStyle.hasLayout)
1385                                 s.display = 'inline-block';
1386                         }
1387
1388                         // Fix for older browsers
1389                         s[na] = s['-moz-opacity'] = s['-khtml-opacity'] = v || '';
1390                         break;
1391
1392                     case 'float':
1393                         isIE ? s.styleFloat = v : s.cssFloat = v;
1394                         break;
1395                     
1396                     default:
1397                         s[na] = v || '';
1398                 }
1399
1400                 // Force update of the style data
1401                 if (t.settings.update_styles)
1402                     t.setAttrib(e, 'mce_style');
1403             });
1404         },
1405
1406         getStyle : function(n, na, c) {
1407             n = this.get(n);
1408
1409             if (!n)
1410                 return false;
1411
1412             // Gecko
1413             if (this.doc.defaultView && c) {
1414                 // Remove camelcase
1415                 na = na.replace(/[A-Z]/g, function(a){
1416                     return '-' + a;
1417                 });
1418
1419                 try {
1420                     return this.doc.defaultView.getComputedStyle(n, null).getPropertyValue(na);
1421                 } catch (ex) {
1422                     // Old safari might fail
1423                     return null;
1424                 }
1425             }
1426
1427             // Camelcase it, if needed
1428             na = na.replace(/-(\D)/g, function(a, b){
1429                 return b.toUpperCase();
1430             });
1431
1432             if (na == 'float')
1433                 na = isIE ? 'styleFloat' : 'cssFloat';
1434
1435             // IE & Opera
1436             if (n.currentStyle && c)
1437                 return n.currentStyle[na];
1438
1439             return n.style[na];
1440         },
1441
1442         setStyles : function(e, o) {
1443             var t = this, s = t.settings, ol;
1444
1445             ol = s.update_styles;
1446             s.update_styles = 0;
1447
1448             each(o, function(v, n) {
1449                 t.setStyle(e, n, v);
1450             });
1451
1452             // Update style info
1453             s.update_styles = ol;
1454             if (s.update_styles)
1455                 t.setAttrib(e, s.cssText);
1456         },
1457
1458         setAttrib : function(e, n, v) {
1459             var t = this;
1460
1461             // Strict XML mode
1462             if (t.settings.strict)
1463                 n = n.toLowerCase();
1464
1465             return this.run(e, function(e) {
1466                 var s = t.settings;
1467
1468                 switch (n) {
1469                     case "style":
18240a 1470                         // No mce_style for elements with these since they might get resized by the user
d9344f 1471                         if (s.keep_values) {
18240a 1472                             if (v && !t._isRes(v))
d9344f 1473                                 e.setAttribute('mce_style', v, 2);
S 1474                             else
1475                                 e.removeAttribute('mce_style', 2);
1476                         }
1477
1478                         e.style.cssText = v;
1479                         break;
1480
1481                     case "class":
1482                         e.className = v || ''; // Fix IE null bug
1483                         break;
1484
1485                     case "src":
1486                     case "href":
1487                         if (s.keep_values) {
1488                             if (s.url_converter)
1489                                 v = s.url_converter.call(s.url_converter_scope || t, v, n, e);
1490
1491                             t.setAttrib(e, 'mce_' + n, v, 2);
1492                         }
1493
18240a 1494                         break;
A 1495                     
1496                     case "shape":
1497                         e.setAttribute('mce_style', v);
d9344f 1498                         break;
S 1499                 }
1500
1501                 if (is(v) && v !== null && v.length !== 0)
1502                     e.setAttribute(n, '' + v, 2);
1503                 else
1504                     e.removeAttribute(n, 2);
1505             });
1506         },
1507
1508         setAttribs : function(e, o) {
1509             var t = this;
1510
1511             return this.run(e, function(e) {
1512                 each(o, function(v, n) {
1513                     t.setAttrib(e, n, v);
1514                 });
1515             });
1516         },
1517
1518         // #endif
1519
1520         getAttrib : function(e, n, dv) {
1521             var v, t = this;
1522
1523             e = t.get(e);
1524
18240a 1525             if (!e || e.nodeType !== 1)
d9344f 1526                 return false;
S 1527
1528             if (!is(dv))
1529                 dv = "";
1530
1531             // Try the mce variant for these
18240a 1532             if (/^(src|href|style|coords|shape)$/.test(n)) {
d9344f 1533                 v = e.getAttribute("mce_" + n);
S 1534
1535                 if (v)
1536                     return v;
1537             }
1538
1539             v = e.getAttribute(n, 2);
1540
1541             if (!v) {
1542                 switch (n) {
1543                     case 'class':
1544                         v = e.className;
1545                         break;
1546
1547                     default:
1548                         // Fix for IE crash Bug: #1884376 probably due to invalid DOM structure
1549                         if (isIE && n === 'name' && e.nodeName === 'A') {
1550                             v = e.name;
1551                             break;
1552                         }
1553
1554                         v = e.attributes[n];
1555                         v = v && is(v.nodeValue) ? v.nodeValue : v;
1556                 }
1557             }
1558
1559             switch (n) {
1560                 case 'style':
1561                     v = v || e.style.cssText;
1562
1563                     if (v) {
1564                         v = t.serializeStyle(t.parseStyle(v));
1565
18240a 1566                         if (t.settings.keep_values && !t._isRes(v))
d9344f 1567                             e.setAttribute('mce_style', v);
S 1568                     }
1569
1570                     break;
1571             }
1572
1573             // Remove Apple and WebKit stuff
1574             if (isWebKit && n === "class" && v)
1575                 v = v.replace(/(apple|webkit)\-[a-z\-]+/gi, '');
1576
1577             // Handle IE issues
1578             if (isIE) {
1579                 switch (n) {
1580                     case 'rowspan':
1581                     case 'colspan':
1582                         // IE returns 1 as default value
1583                         if (v === 1)
1584                             v = '';
1585
1586                         break;
1587
1588                     case 'size':
1589                         // IE returns +0 as default value for size
1590                         if (v === '+0')
1591                             v = '';
1592
1593                         break;
1594
1595                     case 'hspace':
1596                         // IE returns -1 as default value
1597                         if (v === -1)
1598                             v = '';
1599
1600                         break;
1601
1602                     case 'tabindex':
18240a 1603                         // IE returns default value
d9344f 1604                         if (v === 32768)
18240a 1605                             v = '';
A 1606
1607                         break;
1608
1609                     case 'maxlength':
1610                         // IE returns  default value
1611                         if (v === 2147483647)
d9344f 1612                             v = '';
S 1613
1614                         break;
1615
1616                     case 'shape':
1617                         v = v.toLowerCase();
1618                         break;
1619
1620                     default:
1621                         // IE has odd anonymous function for event attributes
1622                         if (n.indexOf('on') === 0 && v)
1623                             v = ('' + v).replace(/^function\s+anonymous\(\)\s+\{\s+(.*)\s+\}$/, '$1');
1624                 }
1625             }
1626
1627             return (v && v != '') ? '' + v : dv;
1628         },
1629
1630         getPos : function(n) {
1631             var t = this, x = 0, y = 0, e, d = t.doc, r;
1632
1633             n = t.get(n);
1634
1635             // Use getBoundingClientRect on IE, Opera has it but it's not perfect
1636             if (n && isIE) {
1637                 n = n.getBoundingClientRect();
1638                 e = t.boxModel ? d.documentElement : d.body;
1639                 x = t.getStyle(t.select('html')[0], 'borderWidth'); // Remove border
1640                 x = (x == 'medium' || t.boxModel && !t.isIE6) && 2 || x;
1641                 n.top += t.win.self != t.win.top ? 2 : 0; // IE adds some strange extra cord if used in a frameset
1642
1643                 return {x : n.left + e.scrollLeft - x, y : n.top + e.scrollTop - x};
1644             }
1645
1646             r = n;
1647             while (r) {
1648                 x += r.offsetLeft || 0;
1649                 y += r.offsetTop || 0;
1650                 r = r.offsetParent;
1651             }
1652
1653             r = n;
1654             while (r) {
1655                 // Opera 9.25 bug fix, fixed in 9.50
1656                 if (!/^table-row|inline.*/i.test(t.getStyle(r, "display", 1))) {
1657                     x -= r.scrollLeft || 0;
1658                     y -= r.scrollTop || 0;
1659                 }
1660
1661                 r = r.parentNode;
1662
1663                 if (r == d.body)
1664                     break;
1665             }
1666
1667             return {x : x, y : y};
1668         },
1669
1670         parseStyle : function(st) {
1671             var t = this, s = t.settings, o = {};
1672
1673             if (!st)
1674                 return o;
1675
1676             function compress(p, s, ot) {
1677                 var t, r, b, l;
1678
1679                 // Get values and check it it needs compressing
1680                 t = o[p + '-top' + s];
1681                 if (!t)
1682                     return;
1683
1684                 r = o[p + '-right' + s];
1685                 if (t != r)
1686                     return;
1687
1688                 b = o[p + '-bottom' + s];
1689                 if (r != b)
1690                     return;
1691
1692                 l = o[p + '-left' + s];
1693                 if (b != l)
1694                     return;
1695
1696                 // Compress
1697                 o[ot] = l;
1698                 delete o[p + '-top' + s];
1699                 delete o[p + '-right' + s];
1700                 delete o[p + '-bottom' + s];
1701                 delete o[p + '-left' + s];
1702             };
1703
1704             function compress2(ta, a, b, c) {
1705                 var t;
1706
1707                 t = o[a];
1708                 if (!t)
1709                     return;
1710
1711                 t = o[b];
1712                 if (!t)
1713                     return;
1714
1715                 t = o[c];
1716                 if (!t)
1717                     return;
1718
1719                 // Compress
1720                 o[ta] = o[a] + ' ' + o[b] + ' ' + o[c];
1721                 delete o[a];
1722                 delete o[b];
1723                 delete o[c];
1724             };
1725
18240a 1726             st = st.replace(/&(#?[a-z0-9]+);/g, '&$1_MCE_SEMI_'); // Protect entities
A 1727
d9344f 1728             each(st.split(';'), function(v) {
S 1729                 var sv, ur = [];
1730
1731                 if (v) {
18240a 1732                     v = v.replace(/_MCE_SEMI_/g, ';'); // Restore entities
d9344f 1733                     v = v.replace(/url\([^\)]+\)/g, function(v) {ur.push(v);return 'url(' + ur.length + ')';});
S 1734                     v = v.split(':');
1735                     sv = tinymce.trim(v[1]);
1736                     sv = sv.replace(/url\(([^\)]+)\)/g, function(a, b) {return ur[parseInt(b) - 1];});
1737
1738                     sv = sv.replace(/rgb\([^\)]+\)/g, function(v) {
1739                         return t.toHex(v);
1740                     });
1741
1742                     if (s.url_converter) {
1743                         sv = sv.replace(/url\([\'\"]?([^\)\'\"]+)[\'\"]?\)/g, function(x, c) {
18240a 1744                             return 'url(' + s.url_converter.call(s.url_converter_scope || t, t.decode(c), 'style', null) + ')';
d9344f 1745                         });
S 1746                     }
1747
1748                     o[tinymce.trim(v[0]).toLowerCase()] = sv;
1749                 }
1750             });
1751
1752             compress("border", "", "border");
1753             compress("border", "-width", "border-width");
1754             compress("border", "-color", "border-color");
1755             compress("border", "-style", "border-style");
1756             compress("padding", "", "padding");
1757             compress("margin", "", "margin");
1758             compress2('border', 'border-width', 'border-style', 'border-color');
1759
1760             if (isIE) {
1761                 // Remove pointless border
1762                 if (o.border == 'medium none')
1763                     o.border = '';
1764             }
1765
1766             return o;
1767         },
1768
1769         serializeStyle : function(o) {
1770             var s = '';
1771
1772             each(o, function(v, k) {
1773                 if (k && v) {
18240a 1774                     if (tinymce.isGecko && k.indexOf('-moz-') === 0)
A 1775                         return;
1776
d9344f 1777                     switch (k) {
S 1778                         case 'color':
1779                         case 'background-color':
1780                             v = v.toLowerCase();
1781                             break;
1782                     }
1783
1784                     s += (s ? ' ' : '') + k + ': ' + v + ';';
1785                 }
1786             });
1787
1788             return s;
1789         },
1790
1791         loadCSS : function(u) {
1792             var t = this, d = t.doc;
1793
1794             if (!u)
1795                 u = '';
1796
1797             each(u.split(','), function(u) {
1798                 if (t.files[u])
1799                     return;
1800
1801                 t.files[u] = true;
18240a 1802                 t.add(t.select('head')[0], 'link', {rel : 'stylesheet', href : tinymce._addVer(u)});
d9344f 1803             });
S 1804         },
1805
1806         // #if !jquery
1807
1808         addClass : function(e, c) {
1809             return this.run(e, function(e) {
1810                 var o;
1811
1812                 if (!c)
1813                     return 0;
1814
1815                 if (this.hasClass(e, c))
1816                     return e.className;
1817
1818                 o = this.removeClass(e, c);
1819
1820                 return e.className = (o != '' ? (o + ' ') : '') + c;
1821             });
1822         },
1823
1824         removeClass : function(e, c) {
1825             var t = this, re;
1826
1827             return t.run(e, function(e) {
1828                 var v;
1829
1830                 if (t.hasClass(e, c)) {
1831                     if (!re)
1832                         re = new RegExp("(^|\\s+)" + c + "(\\s+|$)", "g");
1833
1834                     v = e.className.replace(re, ' ');
1835
1836                     return e.className = tinymce.trim(v != ' ' ? v : '');
1837                 }
1838
1839                 return e.className;
1840             });
1841         },
1842
1843         hasClass : function(n, c) {
1844             n = this.get(n);
1845
1846             if (!n || !c)
1847                 return false;
1848
1849             return (' ' + n.className + ' ').indexOf(' ' + c + ' ') !== -1;
1850         },
1851
1852         show : function(e) {
1853             return this.setStyle(e, 'display', 'block');
1854         },
1855
1856         hide : function(e) {
1857             return this.setStyle(e, 'display', 'none');
1858         },
1859
1860         isHidden : function(e) {
1861             e = this.get(e);
1862
1863             return e.style.display == 'none' || this.getStyle(e, 'display') == 'none';
1864         },
1865
1866         // #endif
1867
1868         uniqueId : function(p) {
1869             return (!p ? 'mce_' : p) + (this.counter++);
1870         },
1871
1872         setHTML : function(e, h) {
1873             var t = this;
1874
1875             return this.run(e, function(e) {
1876                 var x, i, nl, n, p, x;
1877
1878                 h = t.processHTML(h);
1879
1880                 if (isIE) {
1881                     function set() {
1882                         try {
1883                             // IE will remove comments from the beginning
1884                             // unless you padd the contents with something
1885                             e.innerHTML = '<br />' + h;
1886                             e.removeChild(e.firstChild);
1887                         } catch (ex) {
1888                             // 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
1889                             // This seems to fix this problem
1890
1891                             // Remove all child nodes
1892                             while (e.firstChild)
1893                                 e.firstChild.removeNode();
1894
1895                             // Create new div with HTML contents and a BR infront to keep comments
1896                             x = t.create('div');
1897                             x.innerHTML = '<br />' + h;
1898
1899                             // Add all children from div to target
1900                             each (x.childNodes, function(n, i) {
1901                                 // Skip br element
1902                                 if (i)
1903                                     e.appendChild(n);
1904                             });
1905                         }
1906                     };
1907
1908                     // IE has a serious bug when it comes to paragraphs it can produce an invalid
1909                     // DOM tree if contents like this <p><ul><li>Item 1</li></ul></p> is inserted
1910                     // It seems to be that IE doesn't like a root block element placed inside another root block element
1911                     if (t.settings.fix_ie_paragraphs)
1912                         h = h.replace(/<p><\/p>|<p([^>]+)><\/p>|<p[^\/+]\/>/gi, '<p$1 mce_keep="true">&nbsp;</p>');
1913
1914                     set();
1915
1916                     if (t.settings.fix_ie_paragraphs) {
1917                         // Check for odd paragraphs this is a sign of a broken DOM
1918                         nl = e.getElementsByTagName("p");
1919                         for (i = nl.length - 1, x = 0; i >= 0; i--) {
1920                             n = nl[i];
1921
1922                             if (!n.hasChildNodes()) {
1923                                 if (!n.mce_keep) {
1924                                     x = 1; // Is broken
1925                                     break;
1926                                 }
1927
1928                                 n.removeAttribute('mce_keep');
1929                             }
1930                         }
1931                     }
1932
1933                     // Time to fix the madness IE left us
1934                     if (x) {
1935                         // So if we replace the p elements with divs and mark them and then replace them back to paragraphs
1936                         // after we use innerHTML we can fix the DOM tree
1937                         h = h.replace(/<p([^>]+)>|<p>/g, '<div$1 mce_tmp="1">');
1938                         h = h.replace(/<\/p>/g, '</div>');
1939
1940                         // Set the new HTML with DIVs
1941                         set();
1942
1943                         // Replace all DIV elements with he mce_tmp attibute back to paragraphs
1944                         // This is needed since IE has a annoying bug see above for details
1945                         // This is a slow process but it has to be done. :(
1946                         if (t.settings.fix_ie_paragraphs) {
1947                             nl = e.getElementsByTagName("DIV");
1948                             for (i = nl.length - 1; i >= 0; i--) {
1949                                 n = nl[i];
1950
1951                                 // Is it a temp div
1952                                 if (n.mce_tmp) {
1953                                     // Create new paragraph
1954                                     p = t.doc.createElement('p');
1955
1956                                     // Copy all attributes
1957                                     n.cloneNode(false).outerHTML.replace(/([a-z0-9\-_]+)=/gi, function(a, b) {
1958                                         var v;
1959
1960                                         if (b !== 'mce_tmp') {
1961                                             v = n.getAttribute(b);
1962
1963                                             if (!v && b === 'class')
1964                                                 v = n.className;
1965
1966                                             p.setAttribute(b, v);
1967                                         }
1968                                     });
1969
1970                                     // Append all children to new paragraph
1971                                     for (x = 0; x<n.childNodes.length; x++)
1972                                         p.appendChild(n.childNodes[x].cloneNode(true));
1973
1974                                     // Replace div with new paragraph
1975                                     n.swapNode(p);
1976                                 }
1977                             }
1978                         }
1979                     }
1980                 } else
1981                     e.innerHTML = h;
1982
1983                 return h;
1984             });
1985         },
1986
1987         processHTML : function(h) {
1988             var t = this, s = t.settings;
1989
1990             if (!s.process_html)
1991                 return h;
1992
1993             // Convert strong and em to b and i in FF since it can't handle them
1994             if (tinymce.isGecko) {
1995                 h = h.replace(/<(\/?)strong>|<strong( [^>]+)>/gi, '<$1b$2>');
1996                 h = h.replace(/<(\/?)em>|<em( [^>]+)>/gi, '<$1i$2>');
18240a 1997             } else if (isIE)
A 1998                 h = h.replace(/&apos;/g, '&#39;'); // IE can't handle apos
d9344f 1999
S 2000             // Fix some issues
2001             h = h.replace(/<a( )([^>]+)\/>|<a\/>/gi, '<a$1$2></a>'); // Force open
2002
2003             // Store away src and href in mce_src and mce_href since browsers mess them up
2004             if (s.keep_values) {
18240a 2005                 // Wrap scripts and styles in comments for serialization purposes
A 2006                 if (/<script|style/.test(h)) {
2007                     function trim(s) {
2008                         // Remove prefix and suffix code for element
2009                         s = s.replace(/^[\r\n]*|[\r\n]*$/g, '');
2010                         s = s.replace(/^\s*(\/\/\s*<!--|\/\/\s*<\[CDATA\[|<!--|<\[CDATA\[)[\r\n]*/g, '');
2011                         s = s.replace(/\s*(\/\/\s*\]\]>|\/\/\s*-->|\]\]>|-->)\s*$/g, '');
2012
2013                         return s;
2014                     };
2015
2016                     // Preserve script elements
2017                     h = h.replace(/<script([^>]+|)>([\s\S]*?)<\/script>/g, function(v, a, b) {
2018                         // Remove prefix and suffix code for script element
2019                         b = trim(b);
2020
2021                         // Force type attribute
2022                         if (!a)
2023                             a = ' type="text/javascript"';
2024
2025                         // Wrap contents in a comment
2026                         if (b)
2027                             b = '<!--\n' + b + '\n// -->';
2028
2029                         // Output fake element
2030                         return '<mce:script' + a + '>' + b + '</mce:script>';
2031                     });
2032
2033                     // Preserve style elements
2034                     h = h.replace(/<style([^>]+|)>([\s\S]*?)<\/style>/g, function(v, a, b) {
2035                         b = trim(b);
2036                         return '<mce:style' + a + '><!--\n' + b + '\n--></mce:style><style' + a + ' mce_bogus="1">' + b + '</style>';
2037                     });
d9344f 2038                 }
S 2039
2040                 // Process all tags with src, href or style
18240a 2041                 h = h.replace(/<([\w:]+) [^>]*(src|href|style|shape|coords)[^>]*>/gi, function(a, n) {
d9344f 2042                     function handle(m, b, c) {
S 2043                         var u = c;
2044
2045                         // Tag already got a mce_ version
2046                         if (a.indexOf('mce_' + b) != -1)
2047                             return m;
2048
2049                         if (b == 'style') {
2050                             // Why did I need this one?
2051                             //if (isIE)
2052                             //    u = t.serializeStyle(t.parseStyle(u));
2053
18240a 2054                             // No mce_style for elements with these since they might get resized by the user
A 2055                             if (t._isRes(c))
2056                                 return m;
2057
d9344f 2058                             if (s.hex_colors) {
S 2059                                 u = u.replace(/rgb\([^\)]+\)/g, function(v) {
2060                                     return t.toHex(v);
2061                                 });
2062                             }
2063
2064                             if (s.url_converter) {
2065                                 u = u.replace(/url\([\'\"]?([^\)\'\"]+)\)/g, function(x, c) {
2066                                     return 'url(' + t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), b, n)) + ')';
2067                                 });
2068                             }
18240a 2069                         } else if (b != 'coords' && b != 'shape') {
d9344f 2070                             if (s.url_converter)
S 2071                                 u = t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), b, n));
2072                         }
2073
2074                         return ' ' + b + '="' + c + '" mce_' + b + '="' + u + '"';
2075                     };
2076
18240a 2077                     a = a.replace(/ (src|href|style|coords|shape)=[\"]([^\"]+)[\"]/gi, handle); // W3C
A 2078                     a = a.replace(/ (src|href|style|coords|shape)=[\']([^\']+)[\']/gi, handle); // W3C
d9344f 2079
18240a 2080                     return a.replace(/ (src|href|style|coords|shape)=([^\s\"\'>]+)/gi, handle); // IE
d9344f 2081                 });
S 2082             }
2083
2084             return h;
2085         },
2086
2087         getOuterHTML : function(e) {
2088             var d;
2089
2090             e = this.get(e);
2091
2092             if (!e)
2093                 return null;
2094
2095             if (isIE)
2096                 return e.outerHTML;
2097
2098             d = (e.ownerDocument || this.doc).createElement("body");
2099             d.appendChild(e.cloneNode(true));
2100
2101             return d.innerHTML;
2102         },
2103
2104         setOuterHTML : function(e, h, d) {
2105             var t = this;
2106
2107             return this.run(e, function(e) {
2108                 var n, tp;
2109
2110                 e = t.get(e);
2111                 d = d || e.ownerDocument || t.doc;
2112
2113                 if (isIE && e.nodeType == 1)
2114                     e.outerHTML = h;
2115                 else {
2116                     tp = d.createElement("body");
2117                     tp.innerHTML = h;
2118
2119                     n = tp.lastChild;
2120                     while (n) {
2121                         t.insertAfter(n.cloneNode(true), e);
2122                         n = n.previousSibling;
2123                     }
2124
2125                     t.remove(e);
2126                 }
2127             });
2128         },
2129
2130         decode : function(s) {
2131             var e;
2132
2133             // Look for entities to decode
2134             if (/&[^;]+;/.test(s)) {
2135                 // Decode the entities using a div element not super efficient but less code
2136                 e = this.doc.createElement("div");
2137                 e.innerHTML = s;
2138
2139                 return !e.firstChild ? s : e.firstChild.nodeValue;
2140             }
2141
2142             return s;
2143         },
2144
2145         encode : function(s) {
2146             return s ? ('' + s).replace(/[<>&\"]/g, function (c, b) {
2147                 switch (c) {
2148                     case '&':
2149                         return '&amp;';
2150
2151                     case '"':
2152                         return '&quot;';
2153
2154                     case '<':
2155                         return '&lt;';
2156
2157                     case '>':
2158                         return '&gt;';
2159                 }
2160
2161                 return c;
2162             }) : s;
2163         },
2164
2165         // #if !jquery
2166
2167         insertAfter : function(n, r) {
2168             var t = this;
2169
2170             r = t.get(r);
2171
2172             return this.run(n, function(n) {
2173                 var p, ns;
2174
2175                 p = r.parentNode;
2176                 ns = r.nextSibling;
2177
2178                 if (ns)
2179                     p.insertBefore(n, ns);
2180                 else
2181                     p.appendChild(n);
2182
2183                 return n;
2184             });
2185         },
2186
2187         // #endif
2188
2189         isBlock : function(n) {
2190             if (n.nodeType && n.nodeType !== 1)
2191                 return false;
2192
2193             n = n.nodeName || n;
2194
18240a 2195             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);
d9344f 2196         },
S 2197
2198         // #if !jquery
2199
2200         replace : function(n, o, k) {
2201             if (is(o, 'array'))
2202                 n = n.cloneNode(true);
2203
2204             return this.run(o, function(o) {
2205                 if (k) {
2206                     each(o.childNodes, function(c) {
2207                         n.appendChild(c.cloneNode(true));
2208                     });
2209                 }
2210
2211                 // Fix IE psuedo leak for elements since replacing elements if fairly common
18240a 2212                 // Will break parentNode for some unknown reason
A 2213     /*            if (isIE && o.nodeType === 1) {
d9344f 2214                     o.parentNode.insertBefore(n, o);
S 2215                     o.outerHTML = '';
2216                     return n;
18240a 2217                 }*/
d9344f 2218
S 2219                 return o.parentNode.replaceChild(n, o);
2220             });
2221         },
2222
2223         // #endif
2224
2225         toHex : function(s) {
2226             var c = /^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(s);
2227
2228             function hex(s) {
2229                 s = parseInt(s).toString(16);
2230
2231                 return s.length > 1 ? s : '0' + s; // 0 -> 00
2232             };
2233
2234             if (c) {
2235                 s = '#' + hex(c[1]) + hex(c[2]) + hex(c[3]);
2236
2237                 return s;
2238             }
2239
2240             return s;
2241         },
2242
2243         getClasses : function() {
2244             var t = this, cl = [], i, lo = {}, f = t.settings.class_filter, ov;
2245
2246             if (t.classes)
2247                 return t.classes;
2248
2249             function addClasses(s) {
2250                 // IE style imports
2251                 each(s.imports, function(r) {
2252                     addClasses(r);
2253                 });
2254
2255                 each(s.cssRules || s.rules, function(r) {
2256                     // Real type or fake it on IE
2257                     switch (r.type || 1) {
2258                         // Rule
2259                         case 1:
2260                             if (r.selectorText) {
2261                                 each(r.selectorText.split(','), function(v) {
2262                                     v = v.replace(/^\s*|\s*$|^\s\./g, "");
2263
2264                                     // Is internal or it doesn't contain a class
2265                                     if (/\.mce/.test(v) || !/\.[\w\-]+$/.test(v))
2266                                         return;
2267
2268                                     // Remove everything but class name
2269                                     ov = v;
2270                                     v = v.replace(/.*\.([a-z0-9_\-]+).*/i, '$1');
2271
2272                                     // Filter classes
2273                                     if (f && !(v = f(v, ov)))
2274                                         return;
2275
2276                                     if (!lo[v]) {
2277                                         cl.push({'class' : v});
2278                                         lo[v] = 1;
2279                                     }
2280                                 });
2281                             }
2282                             break;
2283
2284                         // Import
2285                         case 3:
2286                             addClasses(r.styleSheet);
2287                             break;
2288                     }
2289                 });
2290             };
2291
2292             try {
2293                 each(t.doc.styleSheets, addClasses);
2294             } catch (ex) {
2295                 // Ignore
2296             }
2297
2298             if (cl.length > 0)
2299                 t.classes = cl;
2300
2301             return cl;
2302         },
2303
2304         run : function(e, f, s) {
2305             var t = this, o;
2306
2307             if (t.doc && typeof(e) === 'string')
2308                 e = t.doc.getElementById(e);
2309
2310             if (!e)
2311                 return false;
2312
2313             s = s || this;
2314             if (!e.nodeType && (e.length || e.length === 0)) {
2315                 o = [];
2316
2317                 each(e, function(e, i) {
2318                     if (e) {
2319                         if (typeof(e) == 'string')
2320                             e = t.doc.getElementById(e);
2321
2322                         o.push(f.call(s, e, i));
2323                     }
2324                 });
2325
2326                 return o;
2327             }
2328
2329             return f.call(s, e);
2330         },
2331
2332         getAttribs : function(n) {
2333             var o;
2334
2335             n = this.get(n);
2336
2337             if (!n)
2338                 return [];
2339
2340             if (isIE) {
2341                 o = [];
2342
2343                 // Object will throw exception in IE
2344                 if (n.nodeName == 'OBJECT')
2345                     return n.attributes;
2346
2347                 // It's crazy that this is faster in IE but it's because it returns all attributes all the time
2348                 n.cloneNode(false).outerHTML.replace(/([a-z0-9\:\-_]+)=/gi, function(a, b) {
2349                     o.push({specified : 1, nodeName : b});
2350                 });
2351
2352                 return o;
2353             }
2354
2355             return n.attributes;
2356         },
2357
2358         destroy : function(s) {
2359             var t = this;
2360
2361             t.win = t.doc = t.root = null;
2362
2363             // Manual destroy then remove unload handler
2364             if (!s)
2365                 tinymce.removeUnload(t.destroy);
18240a 2366         },
A 2367
2368         _isRes : function(c) {
2369             // Is live resizble element
2370             return /^(top|left|bottom|right|width|height)/i.test(c) || /;\s*(top|left|bottom|right|width|height)/i.test(c);
d9344f 2371         }
S 2372
2373         /*
2374         walk : function(n, f, s) {
2375             var d = this.doc, w;
2376
2377             if (d.createTreeWalker) {
2378                 w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);
2379
2380                 while ((n = w.nextNode()) != null)
2381                     f.call(s || this, n);
2382             } else
2383                 tinymce.walk(n, f, 'childNodes', s);
2384         }
2385         */
2386
2387         /*
2388         toRGB : function(s) {
2389             var c = /^\s*?#([0-9A-F]{2})([0-9A-F]{1,2})([0-9A-F]{2})?\s*?$/.exec(s);
2390
2391             if (c) {
2392                 // #FFF -> #FFFFFF
2393                 if (!is(c[3]))
2394                     c[3] = c[2] = c[1];
2395
2396                 return "rgb(" + parseInt(c[1], 16) + "," + parseInt(c[2], 16) + "," + parseInt(c[3], 16) + ")";
2397             }
2398
2399             return s;
2400         }
2401         */
2402
2403         });
2404
2405     // Setup page DOM
2406     tinymce.DOM = new tinymce.dom.DOMUtils(document, {process_html : 0});
2407 })();
2408
2409 /* file:jscripts/tiny_mce/classes/dom/Event.js */
2410
2411 (function() {
2412     // Shorten names
2413     var each = tinymce.each, DOM = tinymce.DOM, isIE = tinymce.isIE, isWebKit = tinymce.isWebKit, Event;
2414
2415     tinymce.create('static tinymce.dom.Event', {
2416         inits : [],
2417         events : [],
2418
2419         // #if !jquery
2420
2421         add : function(o, n, f, s) {
2422             var cb, t = this, el = t.events, r;
2423
2424             // Handle array
2425             if (o && o instanceof Array) {
2426                 r = [];
2427
2428                 each(o, function(o) {
2429                     o = DOM.get(o);
2430                     r.push(t.add(o, n, f, s));
2431                 });
2432
2433                 return r;
2434             }
2435
2436             o = DOM.get(o);
2437
2438             if (!o)
2439                 return;
2440
2441             // Setup event callback
2442             cb = function(e) {
2443                 e = e || window.event;
2444
2445                 // Patch in target in IE it's W3C valid
2446                 if (e && !e.target && isIE)
2447                     e.target = e.srcElement;
2448
2449                 if (!s)
2450                     return f(e);
2451
2452                 return f.call(s, e);
2453             };
2454
2455             if (n == 'unload') {
2456                 tinymce.unloads.unshift({func : cb});
2457                 return cb;
2458             }
2459
2460             if (n == 'init') {
2461                 if (t.domLoaded)
2462                     cb();
2463                 else
2464                     t.inits.push(cb);
2465
2466                 return cb;
2467             }
2468
2469             // Store away listener reference
2470             el.push({
2471                 obj : o,
2472                 name : n,
2473                 func : f,
2474                 cfunc : cb,
2475                 scope : s
2476             });
2477
2478             t._add(o, n, cb);
2479
2480             return f;
2481         },
2482
2483         remove : function(o, n, f) {
2484             var t = this, a = t.events, s = false, r;
2485
2486             // Handle array
2487             if (o && o instanceof Array) {
2488                 r = [];
2489
2490                 each(o, function(o) {
2491                     o = DOM.get(o);
2492                     r.push(t.remove(o, n, f));
2493                 });
2494
2495                 return r;
2496             }
2497
2498             o = DOM.get(o);
2499
2500             each(a, function(e, i) {
2501                 if (e.obj == o && e.name == n && (!f || (e.func == f || e.cfunc == f))) {
2502                     a.splice(i, 1);
2503                     t._remove(o, n, e.cfunc);
2504                     s = true;
2505                     return false;
2506                 }
2507             });
2508
2509             return s;
2510         },
2511
2512         clear : function(o) {
2513             var t = this, a = t.events, i, e;
2514
2515             if (o) {
2516                 o = DOM.get(o);
2517
2518                 for (i = a.length - 1; i >= 0; i--) {
2519                     e = a[i];
2520
2521                     if (e.obj === o) {
2522                         t._remove(e.obj, e.name, e.cfunc);
2523                         e.obj = e.cfunc = null;
2524                         a.splice(i, 1);
2525                     }
2526                 }
2527             }
2528         },
2529
2530         // #endif
2531
2532         cancel : function(e) {
2533             if (!e)
2534                 return false;
2535
2536             this.stop(e);
2537             return this.prevent(e);
2538         },
2539
2540         stop : function(e) {
2541             if (e.stopPropagation)
2542                 e.stopPropagation();
2543             else
2544                 e.cancelBubble = true;
2545
2546             return false;
2547         },
2548
2549         prevent : function(e) {
2550             if (e.preventDefault)
2551                 e.preventDefault();
2552             else
2553                 e.returnValue = false;
2554
2555             return false;
2556         },
2557
2558         _unload : function() {
2559             var t = Event;
2560
2561             each(t.events, function(e, i) {
2562                 t._remove(e.obj, e.name, e.cfunc);
2563                 e.obj = e.cfunc = null;
2564             });
2565
2566             t.events = [];
2567             t = null;
2568         },
2569
2570         _add : function(o, n, f) {
2571             if (o.attachEvent)
2572                 o.attachEvent('on' + n, f);
2573             else if (o.addEventListener)
2574                 o.addEventListener(n, f, false);
2575             else
2576                 o['on' + n] = f;
2577         },
2578
2579         _remove : function(o, n, f) {
2580             if (o) {
2581                 try {
2582                     if (o.detachEvent)
2583                         o.detachEvent('on' + n, f);
2584                     else if (o.removeEventListener)
2585                         o.removeEventListener(n, f, false);
2586                     else
2587                         o['on' + n] = null;
2588                 } catch (ex) {
2589                     // Might fail with permission denined on IE so we just ignore that
2590                 }
2591             }
2592         },
2593
2594         _pageInit : function() {
2595             var e = Event;
2596
2597             e._remove(window, 'DOMContentLoaded', e._pageInit);
2598             e.domLoaded = true;
2599
2600             each(e.inits, function(c) {
2601                 c();
2602             });
2603
2604             e.inits = [];
2605         },
2606
2607         _wait : function() {
2608             var t;
2609
2610             // No need since the document is already loaded
18240a 2611             if (window.tinyMCE_GZ && tinyMCE_GZ.loaded) {
A 2612                 Event.domLoaded = 1;
d9344f 2613                 return;
18240a 2614             }
d9344f 2615
S 2616             if (isIE && document.location.protocol != 'https:') {
2617                 // Fake DOMContentLoaded on IE
2618                 document.write('<script id=__ie_onload defer src=\'javascript:""\';><\/script>');
2619                 DOM.get("__ie_onload").onreadystatechange = function() {
2620                     if (this.readyState == "complete") {
2621                         Event._pageInit();
2622                         DOM.get("__ie_onload").onreadystatechange = null; // Prevent leak
2623                     }
2624                 };
2625             } else {
2626                 Event._add(window, 'DOMContentLoaded', Event._pageInit, Event);
2627
2628                 if (isIE || isWebKit) {
2629                     t = setInterval(function() {
2630                         if (/loaded|complete/.test(document.readyState)) {
2631                             clearInterval(t);
2632                             Event._pageInit();
2633                         }
2634                     }, 10);
2635                 }
2636             }
2637         }
2638
2639         });
2640
2641     // Shorten name
2642     Event = tinymce.dom.Event;
2643
2644     // Dispatch DOM content loaded event for IE and Safari
2645     Event._wait();
2646     tinymce.addUnload(Event._unload);
2647 })();
2648
2649 /* file:jscripts/tiny_mce/classes/dom/Element.js */
2650
2651 (function() {
2652     var each = tinymce.each;
2653
2654     tinymce.create('tinymce.dom.Element', {
2655         Element : function(id, s) {
2656             var t = this, dom, el;
2657
2658             s = s || {};
2659             t.id = id;
2660             t.dom = dom = s.dom || tinymce.DOM;
2661             t.settings = s;
2662
2663             // Only IE leaks DOM references, this is a lot faster
2664             if (!tinymce.isIE)
2665                 el = t.dom.get(t.id);
2666
2667             each([
2668                 'getPos',
2669                 'getRect',
2670                 'getParent',
2671                 'add',
2672                 'setStyle',
2673                 'getStyle',
2674                 'setStyles',
2675                 'setAttrib',
2676                 'setAttribs',
2677                 'getAttrib',
2678                 'addClass',
2679                 'removeClass',
2680                 'hasClass',
2681                 'getOuterHTML',
2682                 'setOuterHTML',
2683                 'remove',
2684                 'show',
2685                 'hide',
2686                 'isHidden',
2687                 'setHTML',
2688                 'get'
2689             ], function(k) {
2690                 t[k] = function() {
2691                     var a = arguments, o;
2692
2693                     // Opera fails
2694                     if (tinymce.isOpera) {
2695                         a = [id];
2696
2697                         each(arguments, function(v) {
2698                             a.push(v);
2699                         });
2700                     } else
2701                         Array.prototype.unshift.call(a, el || id);
2702
2703                     o = dom[k].apply(dom, a);
2704                     t.update(k);
2705
2706                     return o;
2707                 };
2708             });
2709         },
2710
2711         on : function(n, f, s) {
2712             return tinymce.dom.Event.add(this.id, n, f, s);
2713         },
2714
2715         getXY : function() {
2716             return {
2717                 x : parseInt(this.getStyle('left')),
2718                 y : parseInt(this.getStyle('top'))
2719             };
2720         },
2721
2722         getSize : function() {
2723             var n = this.dom.get(this.id);
2724
2725             return {
2726                 w : parseInt(this.getStyle('width') || n.clientWidth),
2727                 h : parseInt(this.getStyle('height') || n.clientHeight)
2728             };
2729         },
2730
2731         moveTo : function(x, y) {
2732             this.setStyles({left : x, top : y});
2733         },
2734
2735         moveBy : function(x, y) {
2736             var p = this.getXY();
2737
2738             this.moveTo(p.x + x, p.y + y);
2739         },
2740
2741         resizeTo : function(w, h) {
2742             this.setStyles({width : w, height : h});
2743         },
2744
2745         resizeBy : function(w, h) {
2746             var s = this.getSize();
2747
2748             this.resizeTo(s.w + w, s.h + h);
2749         },
2750
2751         update : function(k) {
2752             var t = this, b, dom = t.dom;
2753
2754             if (tinymce.isIE6 && t.settings.blocker) {
2755                 k = k || '';
2756
2757                 // Ignore getters
2758                 if (k.indexOf('get') === 0 || k.indexOf('has') === 0 || k.indexOf('is') === 0)
2759                     return;
2760
2761                 // Remove blocker on remove
2762                 if (k == 'remove') {
2763                     dom.remove(t.blocker);
2764                     return;
2765                 }
2766
2767                 if (!t.blocker) {
2768                     t.blocker = dom.uniqueId();
2769                     b = dom.add(t.settings.container || dom.getRoot(), 'iframe', {id : t.blocker, style : 'position:absolute;', frameBorder : 0, src : 'javascript:""'});
2770                     dom.setStyle(b, 'opacity', 0);
2771                 } else
2772                     b = dom.get(t.blocker);
2773
2774                 dom.setStyle(b, 'left', t.getStyle('left', 1));
2775                 dom.setStyle(b, 'top', t.getStyle('top', 1));
2776                 dom.setStyle(b, 'width', t.getStyle('width', 1));
2777                 dom.setStyle(b, 'height', t.getStyle('height', 1));
2778                 dom.setStyle(b, 'display', t.getStyle('display', 1));
2779                 dom.setStyle(b, 'zIndex', parseInt(t.getStyle('zIndex', 1) || 0) - 1);
2780             }
2781         }
2782
2783         });
2784 })();
2785
2786 /* file:jscripts/tiny_mce/classes/dom/Selection.js */
2787
2788 (function() {
18240a 2789     function trimNl(s) {
A 2790         return s.replace(/[\n\r]+/g, '');
2791     };
2792
d9344f 2793     // Shorten names
S 2794     var is = tinymce.is, isIE = tinymce.isIE, each = tinymce.each;
2795
2796     tinymce.create('tinymce.dom.Selection', {
2797         Selection : function(dom, win, serializer) {
2798             var t = this;
2799
2800             t.dom = dom;
2801             t.win = win;
2802             t.serializer = serializer;
2803
2804             // Prevent leaks
2805             tinymce.addUnload(t.destroy, t);
2806         },
2807
2808         getContent : function(s) {
2809             var t = this, r = t.getRng(), e = t.dom.create("body"), se = t.getSel(), wb, wa, n;
2810
2811             s = s || {};
2812             wb = wa = '';
2813             s.get = true;
2814             s.format = s.format || 'html';
2815
2816             if (s.format == 'text')
2817                 return t.isCollapsed() ? '' : (r.text || (se.toString ? se.toString() : ''));
2818
2819             if (r.cloneContents) {
2820                 n = r.cloneContents();
2821
2822                 if (n)
2823                     e.appendChild(n);
2824             } else if (is(r.item) || is(r.htmlText))
2825                 e.innerHTML = r.item ? r.item(0).outerHTML : r.htmlText;
2826             else
2827                 e.innerHTML = r.toString();
2828
2829             // Keep whitespace before and after
2830             if (/^\s/.test(e.innerHTML))
2831                 wb = ' ';
2832
2833             if (/\s+$/.test(e.innerHTML))
2834                 wa = ' ';
2835
2836             s.getInner = true;
2837
2838             return t.isCollapsed() ? '' : wb + t.serializer.serialize(e, s) + wa;
2839         },
2840
2841         setContent : function(h, s) {
18240a 2842             var t = this, r = t.getRng(), d = t.win.document;
d9344f 2843
S 2844             s = s || {format : 'html'};
2845             s.set = true;
2846             h = t.dom.processHTML(h);
2847
2848             if (r.insertNode) {
2849                 // Gecko has a bug where if you insert &nbsp; using InsertHTML it will insert a space instead
2850                 // So we simply check if the input is HTML or text and then insert text using the insertNode method
2851                 if (tinymce.isGecko && h.indexOf('<') == -1) {
2852                     r.deleteContents();
2853                     r.insertNode(t.getRng().createContextualFragment(h + '<span id="__caret">_</span>'));
2854                     t.select(t.dom.get('__caret'));
2855                     t.getRng().deleteContents();
2856                     return;
2857                 }
2858
2859                 // Use insert HTML if it exists (places cursor after content)
2860                 try {
2861                     // This might fail with an exception see bug #1893736
2862                     if (d.queryCommandEnabled('InsertHTML'))
2863                         return d.execCommand('InsertHTML', false, h);
2864                 } catch (ex) {
2865                     // Use old school method
2866                     r.deleteContents();
2867                     r.insertNode(t.getRng().createContextualFragment(h));
2868                 }
2869             } else {
18240a 2870                 if (r.item) {
A 2871                     // Delete content and get caret text selection
2872                     d.execCommand('Delete', false, null);
2873                     r = t.getRng();
2874                 }
2875
2876                 r.pasteHTML(h);
d9344f 2877             }
S 2878         },
2879
2880         getStart : function() {
2881             var t = this, r = t.getRng(), e;
2882
2883             if (isIE) {
2884                 if (r.item)
2885                     return r.item(0);
2886
2887                 r = r.duplicate();
2888                 r.collapse(1);
2889                 e = r.parentElement();
2890
18240a 2891                 if (e && e.nodeName == 'BODY')
d9344f 2892                     return e.firstChild;
S 2893
2894                 return e;
2895             } else {
2896                 e = r.startContainer;
2897
2898                 if (e.nodeName == 'BODY')
2899                     return e.firstChild;
2900
2901                 return t.dom.getParent(e, function(n) {return n.nodeType == 1;});
2902             }
2903         },
2904
2905         getEnd : function() {
2906             var t = this, r = t.getRng(), e;
2907
2908             if (isIE) {
2909                 if (r.item)
2910                     return r.item(0);
2911
2912                 r = r.duplicate();
2913                 r.collapse(0);
2914                 e = r.parentElement();
2915
18240a 2916                 if (e && e.nodeName == 'BODY')
d9344f 2917                     return e.lastChild;
S 2918
2919                 return e;
2920             } else {
2921                 e = r.endContainer;
2922
2923                 if (e.nodeName == 'BODY')
2924                     return e.lastChild;
2925
2926                 return t.dom.getParent(e, function(n) {return n.nodeType == 1;});
2927             }
2928         },
2929
2930         getBookmark : function(si) {
2931             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;
2932             sx = vp.x;
2933             sy = vp.y;
2934
2935             // Simple bookmark fast but not as persistent
2936             if (si == 'simple')
2937                 return {rng : r, scrollX : sx, scrollY : sy};
2938
2939             // Handle IE
2940             if (isIE) {
2941                 // Control selection
2942                 if (r.item) {
2943                     e = r.item(0);
2944
2945                     each(t.dom.select(e.nodeName), function(n, i) {
2946                         if (e == n) {
2947                             sp = i;
2948                             return false;
2949                         }
2950                     });
2951
2952                     return {
2953                         tag : e.nodeName,
2954                         index : sp,
2955                         scrollX : sx,
2956                         scrollY : sy
2957                     };
2958                 }
2959
2960                 // Text selection
2961                 tr = t.dom.doc.body.createTextRange();
2962                 tr.moveToElementText(ro);
2963                 tr.collapse(true);
2964                 bp = Math.abs(tr.move('character', c));
2965
2966                 tr = r.duplicate();
2967                 tr.collapse(true);
2968                 sp = Math.abs(tr.move('character', c));
2969
2970                 tr = r.duplicate();
2971                 tr.collapse(false);
2972                 le = Math.abs(tr.move('character', c)) - sp;
2973
2974                 return {
2975                     start : sp - bp,
2976                     length : le,
2977                     scrollX : sx,
2978                     scrollY : sy
2979                 };
2980             }
2981
2982             // Handle W3C
2983             e = t.getNode();
2984             s = t.getSel();
2985
2986             if (!s)
2987                 return null;
2988
2989             // Image selection
2990             if (e && e.nodeName == 'IMG') {
2991                 return {
2992                     scrollX : sx,
2993                     scrollY : sy
2994                 };
2995             }
2996
2997             // Text selection
2998
2999             function getPos(r, sn, en) {
3000                 var w = t.dom.doc.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {};
3001
3002                 while ((n = w.nextNode()) != null) {
3003                     if (n == sn)
3004                         d.start = p;
3005
3006                     if (n == en) {
3007                         d.end = p;
3008                         return d;
3009                     }
3010
18240a 3011                     p += trimNl(n.nodeValue || '').length;
d9344f 3012                 }
S 3013
3014                 return null;
3015             };
3016
3017             // Caret or selection
3018             if (s.anchorNode == s.focusNode && s.anchorOffset == s.focusOffset) {
3019                 e = getPos(ro, s.anchorNode, s.focusNode);
3020
3021                 if (!e)
3022                     return {scrollX : sx, scrollY : sy};
3023
3024                 // Count whitespace before
18240a 3025                 trimNl(s.anchorNode.nodeValue || '').replace(/^\s+/, function(a) {wb = a.length;});
d9344f 3026
S 3027                 return {
3028                     start : Math.max(e.start + s.anchorOffset - wb, 0),
3029                     end : Math.max(e.end + s.focusOffset - wb, 0),
3030                     scrollX : sx,
3031                     scrollY : sy,
3032                     beg : s.anchorOffset - wb == 0
3033                 };
3034             } else {
3035                 e = getPos(ro, r.startContainer, r.endContainer);
3036
3037                 // Count whitespace before start and end container
18240a 3038                 //(r.startContainer.nodeValue || '').replace(/^\s+/, function(a) {wb = a.length;});
A 3039                 //(r.endContainer.nodeValue || '').replace(/^\s+/, function(a) {wa = a.length;});
d9344f 3040
S 3041                 if (!e)
3042                     return {scrollX : sx, scrollY : sy};
3043
3044                 return {
3045                     start : Math.max(e.start + r.startOffset - wb, 0),
3046                     end : Math.max(e.end + r.endOffset - wa, 0),
3047                     scrollX : sx,
3048                     scrollY : sy,
3049                     beg : r.startOffset - wb == 0
3050                 };
3051             }
3052         },
3053
3054         moveToBookmark : function(b) {
3055             var t = this, r = t.getRng(), s = t.getSel(), ro = t.dom.getRoot(), sd, nvl, nv;
3056
3057             function getPos(r, sp, ep) {
3058                 var w = t.dom.doc.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {}, o, v, wa, wb;
3059
3060                 while ((n = w.nextNode()) != null) {
3061                     wa = wb = 0;
3062
3063                     nv = n.nodeValue || '';
18240a 3064                     //nv.replace(/^\s+[^\s]/, function(a) {wb = a.length - 1;});
A 3065                     //nv.replace(/[^\s]\s+$/, function(a) {wa = a.length - 1;});
d9344f 3066
18240a 3067                     nvl = trimNl(nv).length;
d9344f 3068                     p += nvl;
S 3069
3070                     if (p >= sp && !d.startNode) {
3071                         o = sp - (p - nvl);
3072
3073                         // Fix for odd quirk in FF
3074                         if (b.beg && o >= nvl)
3075                             continue;
3076
3077                         d.startNode = n;
3078                         d.startOffset = o + wb;
3079                     }
3080
3081                     if (p >= ep) {
3082                         d.endNode = n;
3083                         d.endOffset = ep - (p - nvl) + wb;
3084                         return d;
3085                     }
3086                 }
3087
3088                 return null;
3089             };
3090
3091             if (!b)
3092                 return false;
3093
3094             t.win.scrollTo(b.scrollX, b.scrollY);
3095
3096             // Handle explorer
3097             if (isIE) {
3098                 // Handle simple
3099                 if (r = b.rng) {
3100                     try {
3101                         r.select();
3102                     } catch (ex) {
3103                         // Ignore
3104                     }
3105
3106                     return true;
3107                 }
3108
3109                 t.win.focus();
3110
3111                 // Handle control bookmark
3112                 if (b.tag) {
3113                     r = ro.createControlRange();
3114
3115                     each(t.dom.select(b.tag), function(n, i) {
3116                         if (i == b.index)
3117                             r.addElement(n);
3118                     });
3119                 } else {
3120                     // Try/catch needed since this operation breaks when TinyMCE is placed in hidden divs/tabs
3121                     try {
3122                         // Incorrect bookmark
3123                         if (b.start < 0)
3124                             return true;
3125
3126                         r = s.createRange();
3127                         r.moveToElementText(ro);
3128                         r.collapse(true);
3129                         r.moveStart('character', b.start);
3130                         r.moveEnd('character', b.length);
3131                     } catch (ex2) {
3132                         return true;
3133                     }
3134                 }
3135
3136                 try {
3137                     r.select();
3138                 } catch (ex) {
3139                     // Needed for some odd IE bug #1843306
3140                 }
3141
3142                 return true;
3143             }
3144
3145             // Handle W3C
3146             if (!s)
3147                 return false;
3148
3149             // Handle simple
3150             if (b.rng) {
3151                 s.removeAllRanges();
3152                 s.addRange(b.rng);
3153             } else {
3154                 if (is(b.start) && is(b.end)) {
3155                     try {
3156                         sd = getPos(ro, b.start, b.end);
3157
3158                         if (sd) {
3159                             r = t.dom.doc.createRange();
3160                             r.setStart(sd.startNode, sd.startOffset);
3161                             r.setEnd(sd.endNode, sd.endOffset);
3162                             s.removeAllRanges();
3163                             s.addRange(r);
3164                         }
3165
3166                         if (!tinymce.isOpera)
3167                             t.win.focus();
3168                     } catch (ex) {
3169                         // Ignore
3170                     }
3171                 }
3172             }
3173         },
3174
3175         select : function(n, c) {
3176             var t = this, r = t.getRng(), s = t.getSel(), b, fn, ln, d = t.win.document;
3177
3178             function first(n) {
3179                 return n ? d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false).nextNode() : null;
3180             };
3181
3182             function last(n) {
3183                 var c, o, w;
3184
3185                 if (!n)
3186                     return null;
3187
3188                 w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);
3189                 while (c = w.nextNode())
3190                     o = c;
3191
3192                 return o;
3193             };
3194
3195             if (isIE) {
3196                 try {
3197                     b = d.body;
3198
3199                     if (/^(IMG|TABLE)$/.test(n.nodeName)) {
3200                         r = b.createControlRange();
3201                         r.addElement(n);
3202                     } else {
3203                         r = b.createTextRange();
3204                         r.moveToElementText(n);
3205                     }
3206
3207                     r.select();
3208                 } catch (ex) {
3209                     // Throws illigal agrument in IE some times
3210                 }
3211             } else {
3212                 if (c) {
3213                     fn = first(n);
3214                     ln = last(n);
3215
3216                     if (fn && ln) {
3217                         //console.debug(fn, ln);
3218                         r = d.createRange();
3219                         r.setStart(fn, 0);
3220                         r.setEnd(ln, ln.nodeValue.length);
3221                     } else
3222                         r.selectNode(n);
3223                 } else
3224                     r.selectNode(n);
3225
3226                 t.setRng(r);
3227             }
3228
3229             return n;
3230         },
3231
3232         isCollapsed : function() {
3233             var t = this, r = t.getRng(), s = t.getSel();
3234
3235             if (!r || r.item)
3236                 return false;
3237
3238             return !s || r.boundingWidth == 0 || s.isCollapsed;
3239         },
3240
3241         collapse : function(b) {
3242             var t = this, r = t.getRng(), n;
3243
3244             // Control range on IE
3245             if (r.item) {
3246                 n = r.item(0);
3247                 r = this.win.document.body.createTextRange();
3248                 r.moveToElementText(n);
3249             }
3250
3251             r.collapse(!!b);
3252             t.setRng(r);
3253         },
3254
3255         getSel : function() {
3256             var t = this, w = this.win;
3257
3258             return w.getSelection ? w.getSelection() : w.document.selection;
3259         },
3260
3261         getRng : function() {
3262             var t = this, s = t.getSel(), r;
3263
3264             try {
3265                 if (s)
3266                     r = s.rangeCount > 0 ? s.getRangeAt(0) : (s.createRange ? s.createRange() : t.win.document.createRange());
3267             } catch (ex) {
3268                 // IE throws unspecified error here if TinyMCE is placed in a frame/iframe
3269             }
3270
3271             // No range found then create an empty one
3272             // This can occur when the editor is placed in a hidden container element on Gecko
3273             // Or on IE when there was an exception
3274             if (!r)
3275                 r = isIE ? t.win.document.body.createTextRange() : t.win.document.createRange();
3276
3277             return r;
3278         },
3279
3280         setRng : function(r) {
3281             var s;
3282
3283             if (!isIE) {
3284                 s = this.getSel();
3285
3286                 if (s) {
3287                     s.removeAllRanges();
3288                     s.addRange(r);
3289                 }
3290             } else {
3291                 try {
3292                     r.select();
3293                 } catch (ex) {
3294                     // Needed for some odd IE bug #1843306
3295                 }
3296             }
3297         },
3298
3299         setNode : function(n) {
3300             var t = this;
3301
3302             t.setContent(t.dom.getOuterHTML(n));
3303
3304             return n;
3305         },
3306
3307         getNode : function() {
3308             var t = this, r = t.getRng(), s = t.getSel(), e;
3309
3310             if (!isIE) {
3311                 // Range maybe lost after the editor is made visible again
3312                 if (!r)
3313                     return t.dom.getRoot();
3314
3315                 e = r.commonAncestorContainer;
3316
3317                 // Handle selection a image or other control like element such as anchors
3318                 if (!r.collapsed) {
3319                     if (r.startContainer == r.endContainer || (tinymce.isWebKit && r.startContainer == r.endContainer.parentNode)) {
3320                         if (r.startOffset - r.endOffset < 2 || tinymce.isWebKit) {
3321                             if (r.startContainer.hasChildNodes())
3322                                 e = r.startContainer.childNodes[r.startOffset];
3323                         }
3324                     }
3325                 }
3326
3327                 return t.dom.getParent(e, function(n) {
3328                     return n.nodeType == 1;
3329                 });
3330             }
3331
3332             return r.item ? r.item(0) : r.parentElement();
3333         },
3334
3335         destroy : function(s) {
3336             var t = this;
3337
3338             t.win = null;
3339
3340             // Manual destroy then remove unload handler
3341             if (!s)
3342                 tinymce.removeUnload(t.destroy);
3343         }
3344
3345         });
3346 })();
3347
3348 /* file:jscripts/tiny_mce/classes/dom/XMLWriter.js */
3349
3350 (function() {
3351     tinymce.create('tinymce.dom.XMLWriter', {
3352         node : null,
3353
3354         XMLWriter : function(s) {
3355             // Get XML document
3356             function getXML() {
3357                 var i = document.implementation;
3358
3359                 if (!i || !i.createDocument) {
3360                     // Try IE objects
3361                     try {return new ActiveXObject('MSXML2.DOMDocument');} catch (ex) {}
3362                     try {return new ActiveXObject('Microsoft.XmlDom');} catch (ex) {}
3363                 } else
3364                     return i.createDocument('', '', null);
3365             };
3366
3367             this.doc = getXML();
3368             
3369             // Since Opera and WebKit doesn't escape > into &gt; we need to do it our self to normalize the output for all browsers
3370             this.valid = tinymce.isOpera || tinymce.isWebKit;
3371
3372             this.reset();
3373         },
3374
3375         reset : function() {
3376             var t = this, d = t.doc;
3377
3378             if (d.firstChild)
3379                 d.removeChild(d.firstChild);
3380
3381             t.node = d.appendChild(d.createElement("html"));
3382         },
3383
3384         writeStartElement : function(n) {
3385             var t = this;
3386
3387             t.node = t.node.appendChild(t.doc.createElement(n));
3388         },
3389
3390         writeAttribute : function(n, v) {
3391             if (this.valid)
3392                 v = v.replace(/>/g, '%MCGT%');
3393
3394             this.node.setAttribute(n, v);
3395         },
3396
3397         writeEndElement : function() {
3398             this.node = this.node.parentNode;
3399         },
3400
3401         writeFullEndElement : function() {
3402             var t = this, n = t.node;
3403
3404             n.appendChild(t.doc.createTextNode(""));
3405             t.node = n.parentNode;
3406         },
3407
3408         writeText : function(v) {
3409             if (this.valid)
3410                 v = v.replace(/>/g, '%MCGT%');
3411
3412             this.node.appendChild(this.doc.createTextNode(v));
3413         },
3414
3415         writeCDATA : function(v) {
3416             this.node.appendChild(this.doc.createCDATA(v));
3417         },
3418
3419         writeComment : function(v) {
18240a 3420             this.node.appendChild(this.doc.createComment(v.replace(/\-\-/g, ' ')));
d9344f 3421         },
S 3422
3423         getContent : function() {
3424             var h;
3425
3426             h = this.doc.xml || new XMLSerializer().serializeToString(this.doc);
3427             h = h.replace(/<\?[^?]+\?>|<html>|<\/html>|<html\/>|<!DOCTYPE[^>]+>/g, '');
3428             h = h.replace(/ ?\/>/g, ' />');
3429
3430             if (this.valid)
3431                 h = h.replace(/\%MCGT%/g, '&gt;');
3432
3433             return h;
3434         }
3435
3436         });
3437 })();
3438
3439 /* file:jscripts/tiny_mce/classes/dom/StringWriter.js */
3440
3441 (function() {
3442     tinymce.create('tinymce.dom.StringWriter', {
3443         str : null,
3444         tags : null,
3445         count : 0,
3446         settings : null,
3447         indent : null,
3448
3449         StringWriter : function(s) {
3450             this.settings = tinymce.extend({
3451                 indent_char : ' ',
3452                 indentation : 1
3453             }, s);
3454
3455             this.reset();
3456         },
3457
3458         reset : function() {
3459             this.indent = '';
3460             this.str = "";
3461             this.tags = [];
3462             this.count = 0;
3463         },
3464
3465         writeStartElement : function(n) {
3466             this._writeAttributesEnd();
3467             this.writeRaw('<' + n);
3468             this.tags.push(n);
3469             this.inAttr = true;
3470             this.count++;
3471             this.elementCount = this.count;
3472         },
3473
3474         writeAttribute : function(n, v) {
3475             var t = this;
3476
3477             t.writeRaw(" " + t.encode(n) + '="' + t.encode(v) + '"');
3478         },
3479
3480         writeEndElement : function() {
3481             var n;
3482
3483             if (this.tags.length > 0) {
3484                 n = this.tags.pop();
3485
3486                 if (this._writeAttributesEnd(1))
3487                     this.writeRaw('</' + n + '>');
3488
3489                 if (this.settings.indentation > 0)
3490                     this.writeRaw('\n');
3491             }
3492         },
3493
3494         writeFullEndElement : function() {
3495             if (this.tags.length > 0) {
3496                 this._writeAttributesEnd();
3497                 this.writeRaw('</' + this.tags.pop() + '>');
3498
3499                 if (this.settings.indentation > 0)
3500                     this.writeRaw('\n');
3501             }
3502         },
3503
3504         writeText : function(v) {
3505             this._writeAttributesEnd();
3506             this.writeRaw(this.encode(v));
3507             this.count++;
3508         },
3509
3510         writeCDATA : function(v) {
3511             this._writeAttributesEnd();
3512             this.writeRaw('<![CDATA[' + v + ']]>');
3513             this.count++;
3514         },
3515
3516         writeComment : function(v) {
3517             this._writeAttributesEnd();
3518             this.writeRaw('<!-- ' + v + '-->');
3519             this.count++;
3520         },
3521
3522         writeRaw : function(v) {
3523             this.str += v;
3524         },
3525
3526         encode : function(s) {
3527             return s.replace(/[<>&"]/g, function(v) {
3528                 switch (v) {
3529                     case '<':
3530                         return '&lt;';
3531
3532                     case '>':
3533                         return '&gt;';
3534
3535                     case '&':
3536                         return '&amp;';
3537
3538                     case '"':
3539                         return '&quot;';
3540                 }
3541
3542                 return v;
3543             });
3544         },
3545
3546         getContent : function() {
3547             return this.str;
3548         },
3549
3550         _writeAttributesEnd : function(s) {
3551             if (!this.inAttr)
3552                 return;
3553
3554             this.inAttr = false;
3555
3556             if (s && this.elementCount == this.count) {
3557                 this.writeRaw(' />');
3558                 return false;
3559             }
3560
3561             this.writeRaw('>');
3562
3563             return true;
3564         }
3565
3566         });
3567 })();
3568
3569 /* file:jscripts/tiny_mce/classes/dom/Serializer.js */
3570
3571 (function() {
3572     // Shorten names
3573     var extend = tinymce.extend, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher, isIE = tinymce.isIE, isGecko = tinymce.isGecko;
3574
3575     // Returns only attribites that have values not all attributes in IE
3576     function getIEAtts(n) {
3577         var o = [];
3578
3579         // Object will throw exception in IE
3580         if (n.nodeName == 'OBJECT')
3581             return n.attributes;
3582
3583         n.cloneNode(false).outerHTML.replace(/([a-z0-9\:\-_]+)=/gi, function(a, b) {
3584             o.push({specified : 1, nodeName : b});
3585         });
3586
3587         return o;
3588     };
3589
3590     function wildcardToRE(s) {
3591         return s.replace(/([?+*])/g, '.$1');
3592     };
3593
3594     tinymce.create('tinymce.dom.Serializer', {
3595         Serializer : function(s) {
3596             var t = this;
3597
3598             t.key = 0;
3599             t.onPreProcess = new Dispatcher(t);
3600             t.onPostProcess = new Dispatcher(t);
3601
3602             if (tinymce.relaxedDomain && tinymce.isGecko) {
3603                 // Gecko has a bug where we can't create a new XML document if domain relaxing is used
3604                 t.writer = new tinymce.dom.StringWriter();
3605             } else {
3606                 try {
3607                     t.writer = new tinymce.dom.XMLWriter();
3608                 } catch (ex) {
3609                     // IE might throw exception if ActiveX is disabled so we then switch to the slightly slower StringWriter
3610                     t.writer = new tinymce.dom.StringWriter();
3611                 }
3612             }
3613
3614             // Default settings
3615             t.settings = s = extend({
3616                 dom : tinymce.DOM,
3617                 valid_nodes : 0,
3618                 node_filter : 0,
3619                 attr_filter : 0,
3620                 invalid_attrs : /^(mce_|_moz_)/,
3621                 closed : /(br|hr|input|meta|img|link|param)/,
3622                 entity_encoding : 'named',
3623                 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',
3624                 valid_elements : '*[*]',
3625                 extended_valid_elements : 0,
3626                 valid_child_elements : 0,
3627                 invalid_elements : 0,
3628                 fix_table_elements : 0,
3629                 fix_list_elements : true,
3630                 fix_content_duplication : true,
3631                 convert_fonts_to_spans : false,
3632                 font_size_classes : 0,
3633                 font_size_style_values : 0,
3634                 apply_source_formatting : 0,
3635                 indent_mode : 'simple',
3636                 indent_char : '\t',
3637                 indent_levels : 1,
3638                 remove_linebreaks : 1
3639             }, s);
3640
3641             t.dom = s.dom;
3642
3643             if (s.fix_list_elements) {
3644                 t.onPreProcess.add(function(se, o) {
3645                     var nl, x, a = ['ol', 'ul'], i, n, p, r = /^(OL|UL)$/, np;
3646
3647                     function prevNode(e, n) {
3648                         var a = n.split(','), i;
3649
3650                         while ((e = e.previousSibling) != null) {
3651                             for (i=0; i<a.length; i++) {
3652                                 if (e.nodeName == a[i])
3653                                     return e;
3654                             }
3655                         }
3656
3657                         return null;
3658                     };
3659
3660                     for (x=0; x<a.length; x++) {
3661                         nl = t.dom.select(a[x], o.node);
3662
3663                         for (i=0; i<nl.length; i++) {
3664                             n = nl[i];
3665                             p = n.parentNode;
3666
3667                             if (r.test(p.nodeName)) {
3668                                 np = prevNode(n, 'LI');
3669
3670                                 if (!np) {
3671                                     np = t.dom.create('li');
3672                                     np.innerHTML = '&nbsp;';
3673                                     np.appendChild(n);
3674                                     p.insertBefore(np, p.firstChild);
3675                                 } else
3676                                     np.appendChild(n);
3677                             }
3678                         }
3679                     }
3680                 });
3681             }
3682
3683             if (s.fix_table_elements) {
3684                 t.onPreProcess.add(function(se, o) {
3685                     each(t.dom.select('table', o.node), function(e) {
3686                         var pa = t.dom.getParent(e, 'H1,H2,H3,H4,H5,H6,P'), pa2, n, tm, pl = [], i, ns;
3687
3688                         if (pa) {
3689                             pa2 = pa.cloneNode(false);
3690
3691                             pl.push(e);
3692                             for (n = e; n = n.parentNode;) {
3693                                 pl.push(n);
3694
3695                                 if (n == pa)
3696                                     break;
3697                             }
3698
3699                             tm = pa2;
3700                             for (i = pl.length - 1; i >= 0; i--) {
3701                                 if (i == pl.length - 1) {
3702                                     while (ns = pl[i - 1].nextSibling)
3703                                         tm.appendChild(ns.parentNode.removeChild(ns));
3704                                 } else {
3705                                     n = pl[i].cloneNode(false);
3706
3707                                     if (i != 0) {
3708                                         while (ns = pl[i - 1].nextSibling)
3709                                             n.appendChild(ns.parentNode.removeChild(ns));
3710                                     }
3711
3712                                     tm = tm.appendChild(n);
3713                                 }
3714                             }
3715
3716                             e = t.dom.insertAfter(e.parentNode.removeChild(e), pa);
3717                             t.dom.insertAfter(e, pa);
3718                             t.dom.insertAfter(pa2, e);
3719                         }
3720                     });
3721                 });
3722             }
3723         },
3724
3725         setEntities : function(s) {
3726             var t = this, a, i, l = {}, re = '', v;
3727
3728             // No need to setup more than once
3729             if (t.entityLookup)
3730                 return;
3731
3732             // Build regex and lookup array
3733             a = s.split(',');
3734             for (i = 0; i < a.length; i += 2) {
3735                 v = a[i];
3736
3737                 // Don't add default &amp; &quot; etc.
3738                 if (v == 34 || v == 38 || v == 60 || v == 62)
3739                     continue;
3740
3741                 l[String.fromCharCode(a[i])] = a[i + 1];
3742
3743                 v = parseInt(a[i]).toString(16);
3744                 re += '\\u' + '0000'.substring(v.length) + v;
3745             }
3746
3747             if (!re) {
3748                 t.settings.entity_encoding = 'raw';
3749                 return;
3750             }
3751
3752             t.entitiesRE = new RegExp('[' + re + ']', 'g');
3753             t.entityLookup = l;
3754         },
3755
3756         setValidChildRules : function(s) {
3757             this.childRules = null;
3758             this.addValidChildRules(s);
3759         },
3760
3761         addValidChildRules : function(s) {
3762             var t = this, inst, intr, bloc;
3763
3764             if (!s)
3765                 return;
3766
3767             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';
3768             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';
3769             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';
3770
3771             each(s.split(','), function(s) {
3772                 var p = s.split(/\[|\]/), re;
3773
3774                 s = '';
3775                 each(p[1].split('|'), function(v) {
3776                     if (s)
3777                         s += '|';
3778
3779                     switch (v) {
3780                         case '%itrans':
3781                             v = intr;
3782                             break;
3783
3784                         case '%itrans_na':
3785                             v = intr.substring(2);
3786                             break;
3787
3788                         case '%istrict':
3789                             v = inst;
3790                             break;
3791
3792                         case '%istrict_na':
3793                             v = inst.substring(2);
3794                             break;
3795
3796                         case '%btrans':
3797                             v = bloc;
3798                             break;
3799
3800                         case '%bstrict':
3801                             v = bloc;
3802                             break;
3803                     }
3804
3805                     s += v;
3806                 });
3807                 re = new RegExp('^(' + s.toLowerCase() + ')$', 'i');
3808
3809                 each(p[0].split('/'), function(s) {
3810                     t.childRules = t.childRules || {};
3811                     t.childRules[s] = re;
3812                 });
3813             });
3814
3815             // Build regex
3816             s = '';
3817             each(t.childRules, function(v, k) {
3818                 if (s)
3819                     s += '|';
3820
3821                 s += k;
3822             });
3823
3824             t.parentElementsRE = new RegExp('^(' + s.toLowerCase() + ')$', 'i');
3825
3826             /*console.debug(t.parentElementsRE.toString());
3827             each(t.childRules, function(v) {
3828                 console.debug(v.toString());
3829             });*/
3830         },
3831
3832         setRules : function(s) {
3833             var t = this;
3834
3835             t._setup();
3836             t.rules = {};
3837             t.wildRules = [];
3838             t.validElements = {};
3839
3840             return t.addRules(s);
3841         },
3842
3843         addRules : function(s) {
3844             var t = this, dr;
3845
3846             if (!s)
3847                 return;
3848
3849             t._setup();
3850
3851             each(s.split(','), function(s) {
3852                 var p = s.split(/\[|\]/), tn = p[0].split('/'), ra, at, wat, va = [];
3853
3854                 // Extend with default rules
3855                 if (dr)
3856                     at = tinymce.extend([], dr.attribs);
3857
3858                 // Parse attributes
3859                 if (p.length > 1) {
3860                     each(p[1].split('|'), function(s) {
3861                         var ar = {}, i;
3862
3863                         at = at || [];
3864
3865                         // Parse attribute rule
3866                         s = s.replace(/::/g, '~');
3867                         s = /^([!\-])?([\w*.?~_\-]+|)([=:<])?(.+)?$/.exec(s);
3868                         s[2] = s[2].replace(/~/g, ':');
3869
3870                         // Add required attributes
3871                         if (s[1] == '!') {
3872                             ra = ra || [];
3873                             ra.push(s[2]);
3874                         }
3875
3876                         // Remove inherited attributes
3877                         if (s[1] == '-') {
3878                             for (i = 0; i <at.length; i++) {
3879                                 if (at[i].name == s[2]) {
3880                                     at.splice(i, 1);
3881                                     return;
3882                                 }
3883                             }
3884                         }
3885
3886                         switch (s[3]) {
3887                             // Add default attrib values
3888                             case '=':
3889                                 ar.defaultVal = s[4] || '';
3890                                 break;
3891
3892                             // Add forced attrib values
3893                             case ':':
3894                                 ar.forcedVal = s[4];
3895                                 break;
3896
3897                             // Add validation values
3898                             case '<':
3899                                 ar.validVals = s[4].split('?');
3900                                 break;
3901                         }
3902
3903                         if (/[*.?]/.test(s[2])) {
3904                             wat = wat || [];
3905                             ar.nameRE = new RegExp('^' + wildcardToRE(s[2]) + '$');
3906                             wat.push(ar);
3907                         } else {
3908                             ar.name = s[2];
3909                             at.push(ar);
3910                         }
3911
3912                         va.push(s[2]);
3913                     });
3914                 }
3915
3916                 // Handle element names
3917                 each(tn, function(s, i) {
3918                     var pr = s.charAt(0), x = 1, ru = {};
3919
3920                     // Extend with default rule data
3921                     if (dr) {
3922                         if (dr.noEmpty)
3923                             ru.noEmpty = dr.noEmpty;
3924
3925                         if (dr.fullEnd)
3926                             ru.fullEnd = dr.fullEnd;
3927
3928                         if (dr.padd)
3929                             ru.padd = dr.padd;
3930                     }
3931
3932                     // Handle prefixes
3933                     switch (pr) {
3934                         case '-':
3935                             ru.noEmpty = true;
3936                             break;
3937
3938                         case '+':
3939                             ru.fullEnd = true;
3940                             break;
3941
3942                         case '#':
3943                             ru.padd = true;
3944                             break;
3945
3946                         default:
3947                             x = 0;
3948                     }
3949
3950                     tn[i] = s = s.substring(x);
3951                     t.validElements[s] = 1;
3952
3953                     // Add element name or element regex
3954                     if (/[*.?]/.test(tn[0])) {
3955                         ru.nameRE = new RegExp('^' + wildcardToRE(tn[0]) + '$');
3956                         t.wildRules = t.wildRules || {};
3957                         t.wildRules.push(ru);
3958                     } else {
3959                         ru.name = tn[0];
3960
3961                         // Store away default rule
3962                         if (tn[0] == '@')
3963                             dr = ru;
3964
3965                         t.rules[s] = ru;
3966                     }
3967
3968                     ru.attribs = at;
3969
3970                     if (ra)
3971                         ru.requiredAttribs = ra;
3972
3973                     if (wat) {
3974                         // Build valid attributes regexp
3975                         s = '';
3976                         each(va, function(v) {
3977                             if (s)
3978                                 s += '|';
3979
3980                             s += '(' + wildcardToRE(v) + ')';
3981                         });
3982                         ru.validAttribsRE = new RegExp('^' + s.toLowerCase() + '$');
3983                         ru.wildAttribs = wat;
3984                     }
3985                 });
3986             });
3987
3988             // Build valid elements regexp
3989             s = '';
3990             each(t.validElements, function(v, k) {
3991                 if (s)
3992                     s += '|';
3993
3994                 if (k != '@')
3995                     s += k;
3996             });
3997             t.validElementsRE = new RegExp('^(' + wildcardToRE(s.toLowerCase()) + ')$');
3998
3999             //console.debug(t.validElementsRE.toString());
4000             //console.dir(t.rules);
4001             //console.dir(t.wildRules);
4002         },
4003
4004         findRule : function(n) {
4005             var t = this, rl = t.rules, i, r;
4006
4007             t._setup();
4008
4009             // Exact match
4010             r = rl[n];
4011             if (r)
4012                 return r;
4013
4014             // Try wildcards
4015             rl = t.wildRules;
4016             for (i = 0; i < rl.length; i++) {
4017                 if (rl[i].nameRE.test(n))
4018                     return rl[i];
4019             }
4020
4021             return null;
4022         },
4023
4024         findAttribRule : function(ru, n) {
4025             var i, wa = ru.wildAttribs;
4026
4027             for (i = 0; i < wa.length; i++) {
4028                 if (wa[i].nameRE.test(n))
4029                     return wa[i];
4030             }
4031
4032             return null;
4033         },
4034
4035         serialize : function(n, o) {
4036             var h, t = this;
4037
4038             t._setup();
4039             o = o || {};
4040             o.format = o.format || 'html';
4041             t.processObj = o;
4042             n = n.cloneNode(true);
4043             t.key = '' + (parseInt(t.key) + 1);
4044
4045             // Pre process
4046             if (!o.no_events) {
4047                 o.node = n;
4048                 t.onPreProcess.dispatch(t, o);
4049             }
4050
4051             // Serialize HTML DOM into a string
4052             t.writer.reset();
4053             t._serializeNode(n, o.getInner);
4054
4055             // Post process
4056             o.content = t.writer.getContent();
4057
4058             if (!o.no_events)
4059                 t.onPostProcess.dispatch(t, o);
4060
4061             t._postProcess(o);
4062             o.node = null;
4063
4064             return tinymce.trim(o.content);
4065         },
4066
4067         // Internal functions
4068
4069         _postProcess : function(o) {
18240a 4070             var t = this, s = t.settings, h = o.content, sc = [], p;
d9344f 4071
S 4072             if (o.format == 'html') {
4073                 // Protect some elements
4074                 p = t._protect({
4075                     content : h,
4076                     patterns : [
18240a 4077                         {pattern : /(<script[^>]*>)(.*?)(<\/script>)/g},
A 4078                         {pattern : /(<style[^>]*>)(.*?)(<\/style>)/g},
4079                         {pattern : /(<pre[^>]*>)(.*?)(<\/pre>)/g, encode : 1}
d9344f 4080                     ]
S 4081                 });
4082
4083                 h = p.content;
4084
4085                 // Entity encode
18240a 4086                 if (s.entity_encoding !== 'raw')
A 4087                     h = t._encode(h);
d9344f 4088
S 4089                 // Use BR instead of &nbsp; padded P elements inside editor and use <p>&nbsp;</p> outside editor
4090 /*                if (o.set)
4091                     h = h.replace(/<p>\s+(&nbsp;|&#160;|\u00a0|<br \/>)\s+<\/p>/g, '<p><br /></p>');
4092                 else
4093                     h = h.replace(/<p>\s+(&nbsp;|&#160;|\u00a0|<br \/>)\s+<\/p>/g, '<p>$1</p>');*/
4094
4095                 // Since Gecko and Safari keeps whitespace in the DOM we need to
4096                 // remove it inorder to match other browsers. But I think Gecko and Safari is right.
4097                 // This process is only done when getting contents out from the editor.
4098                 if (!o.set) {
4099                     // We need to replace paragraph whitespace with an nbsp before indentation to keep the \u00a0 char
4100                     h = h.replace(/<p>\s+<\/p>|<p([^>]+)>\s+<\/p>/g, s.entity_encoding == 'numeric' ? '<p$1>&#160;</p>' : '<p$1>&nbsp;</p>');
4101
4102                     if (s.remove_linebreaks) {
4103                         h = h.replace(/\r?\n|\r/g, ' ');
4104                         h = h.replace(/(<[^>]+>)\s+/g, '$1 ');
4105                         h = h.replace(/\s+(<\/[^>]+>)/g, ' $1');
4106                         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
4107                         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
4108                         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
4109                     }
4110
4111                     // Simple indentation
4112                     if (s.apply_source_formatting && s.indent_mode == 'simple') {
4113                         // Add line breaks before and after block elements
4114                         h = h.replace(/<(\/?)(ul|hr|table|meta|link|tbody|tr|object|body|head|html|map)(|[^>]+)>\s*/g, '\n<$1$2$3>\n');
4115                         h = h.replace(/\s*<(p|h[1-6]|blockquote|div|title|style|pre|script|td|li|area)(|[^>]+)>/g, '\n<$1$2>');
4116                         h = h.replace(/<\/(p|h[1-6]|blockquote|div|title|style|pre|script|td|li)>\s*/g, '</$1>\n');
4117                         h = h.replace(/\n\n/g, '\n');
4118                     }
4119                 }
4120
4121                 h = t._unprotect(h, p);
4122
4123                 // Restore the \u00a0 character if raw mode is enabled
4124                 if (s.entity_encoding == 'raw')
4125                     h = h.replace(/<p>&nbsp;<\/p>|<p([^>]+)>&nbsp;<\/p>/g, '<p$1>\u00a0</p>');
4126             }
4127
4128             o.content = h;
4129         },
4130
4131         _serializeNode : function(n, inn) {
4132             var t = this, s = t.settings, w = t.writer, hc, el, cn, i, l, a, at, no, v, nn, ru, ar, iv;
4133
4134             if (!s.node_filter || s.node_filter(n)) {
4135                 switch (n.nodeType) {
4136                     case 1: // Element
4137                         if (n.hasAttribute ? n.hasAttribute('mce_bogus') : n.getAttribute('mce_bogus'))
4138                             return;
4139
4140                         iv = false;
4141                         hc = n.hasChildNodes();
4142                         nn = n.getAttribute('mce_name') || n.nodeName.toLowerCase();
4143
4144                         // Add correct prefix on IE
4145                         if (isIE) {
4146                             if (n.scopeName !== 'HTML' && n.scopeName !== 'html')
4147                                 nn = n.scopeName + ':' + nn;
4148                         }
4149
4150                         // Remove mce prefix on IE needed for the abbr element
4151                         if (nn.indexOf('mce:') === 0)
4152                             nn = nn.substring(4);
4153
4154                         // Check if valid
4155                         if (!t.validElementsRE.test(nn) || (t.invalidElementsRE && t.invalidElementsRE.test(nn)) || inn) {
4156                             iv = true;
4157                             break;
4158                         }
4159
4160                         if (isIE) {
4161                             // Fix IE content duplication (DOM can have multiple copies of the same node)
4162                             if (s.fix_content_duplication) {
4163                                 if (n.mce_serialized == t.key)
4164                                     return;
4165
4166                                 n.mce_serialized = t.key;
4167                             }
4168
4169                             // IE sometimes adds a / infront of the node name
4170                             if (nn.charAt(0) == '/')
4171                                 nn = nn.substring(1);
4172                         } else if (isGecko) {
4173                             // Ignore br elements
4174                             if (n.nodeName === 'BR' && n.getAttribute('type') == '_moz')
4175                                 return;
4176                         }
4177
4178                         // Check if valid child
4179                         if (t.childRules) {
4180                             if (t.parentElementsRE.test(t.elementName)) {
4181                                 if (!t.childRules[t.elementName].test(nn)) {
4182                                     iv = true;
4183                                     break;
4184                                 }
4185                             }
4186
4187                             t.elementName = nn;
4188                         }
4189
4190                         ru = t.findRule(nn);
4191                         nn = ru.name || nn;
4192
4193                         // Skip empty nodes or empty node name in IE
4194                         if ((!hc && ru.noEmpty) || (isIE && !nn)) {
4195                             iv = true;
4196                             break;
4197                         }
4198
4199                         // Check required
4200                         if (ru.requiredAttribs) {
4201                             a = ru.requiredAttribs;
4202
4203                             for (i = a.length - 1; i >= 0; i--) {
4204                                 if (this.dom.getAttrib(n, a[i]) !== '')
4205                                     break;
4206                             }
4207
4208                             // None of the required was there
4209                             if (i == -1) {
4210                                 iv = true;
4211                                 break;
4212                             }
4213                         }
4214
4215                         w.writeStartElement(nn);
4216
4217                         // Add ordered attributes
4218                         if (ru.attribs) {
4219                             for (i=0, at = ru.attribs, l = at.length; i<l; i++) {
4220                                 a = at[i];
4221                                 v = t._getAttrib(n, a);
4222
4223                                 if (v !== null)
4224                                     w.writeAttribute(a.name, v);
4225                             }
4226                         }
4227
4228                         // Add wild attributes
4229                         if (ru.validAttribsRE) {
4230                             at = isIE ? getIEAtts(n) : n.attributes;
4231                             for (i=at.length-1; i>-1; i--) {
4232                                 no = at[i];
4233
4234                                 if (no.specified) {
4235                                     a = no.nodeName.toLowerCase();
4236
4237                                     if (s.invalid_attrs.test(a) || !ru.validAttribsRE.test(a))
4238                                         continue;
4239
4240                                     ar = t.findAttribRule(ru, a);
4241                                     v = t._getAttrib(n, ar, a);
4242
4243                                     if (v !== null)
4244                                         w.writeAttribute(a, v);
4245                                 }
4246                             }
4247                         }
4248
4249                         // Padd empty nodes with a &nbsp;
4250                         if (!hc && ru.padd)
4251                             w.writeText('\u00a0');
4252
4253                         break;
4254
4255                     case 3: // Text
4256                         // Check if valid child
4257                         if (t.childRules && t.parentElementsRE.test(t.elementName)) {
4258                             if (!t.childRules[t.elementName].test(n.nodeName))
4259                                 return;
4260                         }
4261
4262                         return w.writeText(n.nodeValue);
4263
4264                     case 4: // CDATA
4265                         return w.writeCDATA(n.nodeValue);
4266
4267                     case 8: // Comment
4268                         return w.writeComment(n.nodeValue);
4269                 }
4270             } else if (n.nodeType == 1)
4271                 hc = n.hasChildNodes();
4272
4273             if (hc) {
4274                 cn = n.firstChild;
4275
4276                 while (cn) {
4277                     t._serializeNode(cn);
4278                     t.elementName = nn;
4279                     cn = cn.nextSibling;
4280                 }
4281             }
4282
4283             // Write element end
4284             if (!iv) {
4285                 if (hc || !s.closed.test(nn))
4286                     w.writeFullEndElement();
4287                 else
4288                     w.writeEndElement();
4289             }
4290         },
4291
4292         _protect : function(o) {
18240a 4293             var t = this;
A 4294
d9344f 4295             o.items = o.items || [];
S 4296
4297             function enc(s) {
4298                 return s.replace(/[\r\n\\]/g, function(c) {
4299                     if (c === '\n')
4300                         return '\\n';
4301                     else if (c === '\\')
4302                         return '\\\\';
4303
4304                     return '\\r';
4305                 });
4306             };
4307
4308             function dec(s) {
4309                 return s.replace(/\\[\\rn]/g, function(c) {
4310                     if (c === '\\n')
4311                         return '\n';
4312                     else if (c === '\\\\')
4313                         return '\\';
4314
4315                     return '\r';
4316                 });
4317             };
4318
4319             each(o.patterns, function(p) {
18240a 4320                 o.content = dec(enc(o.content).replace(p.pattern, function(x, a, b, c) {
A 4321                     b = dec(b);
4322
4323                     if (p.encode)
4324                         b = t._encode(b);
4325
4326                     o.items.push(b);
d9344f 4327                     return a + '<!--mce:' + (o.items.length - 1) + '-->' + c;
S 4328                 }));
4329             });
4330
4331             return o;
4332         },
4333
4334         _unprotect : function(h, o) {
4335             h = h.replace(/\<!--mce:([0-9]+)--\>/g, function(a, b) {
4336                 return o.items[parseInt(b)];
4337             });
4338
4339             o.items = [];
4340
4341             return h;
4342         },
4343
18240a 4344         _encode : function(h) {
A 4345             var t = this, s = t.settings, l;
4346
4347             // Entity encode
4348             if (s.entity_encoding !== 'raw') {
4349                 if (s.entity_encoding.indexOf('named') != -1) {
4350                     t.setEntities(s.entities);
4351                     l = t.entityLookup;
4352
4353                     h = h.replace(t.entitiesRE, function(a) {
4354                         var v;
4355
4356                         if (v = l[a])
4357                             a = '&' + v + ';';
4358
4359                         return a;
4360                     });
4361                 }
4362
4363                 if (s.entity_encoding.indexOf('numeric') != -1) {
4364                     h = h.replace(/[\u007E-\uFFFF]/g, function(a) {
4365                         return '&#' + a.charCodeAt(0) + ';';
4366                     });
4367                 }
4368             }
4369
4370             return h;
4371         },
4372
d9344f 4373         _setup : function() {
S 4374             var t = this, s = this.settings;
4375
4376             if (t.done)
4377                 return;
4378
4379             t.done = 1;
4380
4381             t.setRules(s.valid_elements);
4382             t.addRules(s.extended_valid_elements);
4383             t.addValidChildRules(s.valid_child_elements);
4384
4385             if (s.invalid_elements)
18240a 4386                 t.invalidElementsRE = new RegExp('^(' + wildcardToRE(s.invalid_elements.replace(/,/g, '|').toLowerCase()) + ')$');
d9344f 4387
S 4388             if (s.attrib_value_filter)
4389                 t.attribValueFilter = s.attribValueFilter;
4390         },
4391
4392         _getAttrib : function(n, a, na) {
4393             var i, v;
4394
4395             na = na || a.name;
4396
4397             if (a.forcedVal && (v = a.forcedVal)) {
4398                 if (v === '{$uid}')
4399                     return this.dom.uniqueId();
4400
4401                 return v;
4402             }
4403
4404             v = this.dom.getAttrib(n, na);
4405
4406             switch (na) {
4407                 case 'rowspan':
4408                 case 'colspan':
4409                     // Whats the point? Remove usless attribute value
4410                     if (v == '1')
4411                         v = '';
4412
4413                     break;
4414             }
4415
4416             if (this.attribValueFilter)
4417                 v = this.attribValueFilter(na, v, n);
4418
4419             if (a.validVals) {
4420                 for (i = a.validVals.length - 1; i >= 0; i--) {
4421                     if (v == a.validVals[i])
4422                         break;
4423                 }
4424
4425                 if (i == -1)
4426                     return null;
4427             }
4428
4429             if (v === '' && typeof(a.defaultVal) != 'undefined') {
4430                 v = a.defaultVal;
4431
4432                 if (v === '{$uid}')
4433                     return this.dom.uniqueId();
4434
4435                 return v;
4436             } else {
4437                 // Remove internal mceItemXX classes when content is extracted from editor
4438                 if (na == 'class' && this.processObj.get)
4439                     v = v.replace(/\s?mceItem\w+\s?/g, '');
4440             }
4441
4442             if (v === '')
4443                 return null;
4444
4445
4446             return v;
4447         }
4448
4449         });
4450 })();
4451
4452 /* file:jscripts/tiny_mce/classes/dom/ScriptLoader.js */
4453
4454 (function() {
4455     var each = tinymce.each;
4456
4457     tinymce.create('tinymce.dom.ScriptLoader', {
4458         ScriptLoader : function(s) {
4459             this.settings = s || {};
4460             this.queue = [];
4461             this.lookup = {};
4462         },
4463
4464         isDone : function(u) {
4465             return this.lookup[u] ? this.lookup[u].state == 2 : 0;
4466         },
4467
4468         markDone : function(u) {
4469             this.lookup[u] = {state : 2, url : u};
4470         },
4471
4472         add : function(u, cb, s, pr) {
4473             var t = this, lo = t.lookup, o;
4474
4475             if (o = lo[u]) {
4476                 // Is loaded fire callback
4477                 if (cb && o.state == 2)
4478                     cb.call(s || this);
4479
4480                 return o;
4481             }
4482
4483             o = {state : 0, url : u, func : cb, scope : s || this};
4484
4485             if (pr)
4486                 t.queue.unshift(o);
4487             else
4488                 t.queue.push(o);
4489
4490             lo[u] = o;
4491
4492             return o;
4493         },
4494
4495         load : function(u, cb, s) {
4496             var t = this, o;
4497
4498             if (o = t.lookup[u]) {
4499                 // Is loaded fire callback
4500                 if (cb && o.state == 2)
4501                     cb.call(s || t);
4502
4503                 return o;
4504             }
4505
4506             function loadScript(u) {
4507                 if (tinymce.dom.Event.domLoaded || t.settings.strict_mode) {
4508                     tinymce.util.XHR.send({
18240a 4509                         url : tinymce._addVer(u),
d9344f 4510                         error : t.settings.error,
S 4511                         async : false,
4512                         success : function(co) {
4513                             t.eval(co);
4514                         }
4515                     });
4516                 } else
18240a 4517                     document.write('<script type="text/javascript" src="' + tinymce._addVer(u) + '"></script>');
d9344f 4518             };
S 4519
4520             if (!tinymce.is(u, 'string')) {
4521                 each(u, function(u) {
4522                     loadScript(u);
4523                 });
4524
4525                 if (cb)
4526                     cb.call(s || t);
4527             } else {
4528                 loadScript(u);
4529
4530                 if (cb)
4531                     cb.call(s || t);
4532             }
4533         },
4534
4535         loadQueue : function(cb, s) {
4536             var t = this;
4537
4538             if (!t.queueLoading) {
4539                 t.queueLoading = 1;
4540                 t.queueCallbacks = [];
4541
4542                 t.loadScripts(t.queue, function() {
4543                     t.queueLoading = 0;
4544
4545                     if (cb)
4546                         cb.call(s || t);
4547
4548                     each(t.queueCallbacks, function(o) {
4549                         o.func.call(o.scope);
4550                     });
4551                 });
4552             } else if (cb)
4553                 t.queueCallbacks.push({func : cb, scope : s || t});
4554         },
4555
4556         eval : function(co) {
4557             var w = window;
4558
4559             // Evaluate script
4560             if (!w.execScript) {
4561                 try {
4562                     eval.call(w, co);
4563                 } catch (ex) {
4564                     eval(co, w); // Firefox 3.0a8
4565                 }
4566             } else
4567                 w.execScript(co); // IE
4568         },
4569
4570         loadScripts : function(sc, cb, s) {
4571             var t = this, lo = t.lookup;
4572
4573             function done(o) {
4574                 o.state = 2; // Has been loaded
4575
4576                 // Run callback
4577                 if (o.func)
4578                     o.func.call(o.scope || t);
4579             };
4580
4581             function allDone() {
4582                 var l;
4583
4584                 // Check if all files are loaded
4585                 l = sc.length;
4586                 each(sc, function(o) {
4587                     o = lo[o.url];
4588
4589                     if (o.state === 2) {// It has finished loading
4590                         done(o);
4591                         l--;
4592                     } else
4593                         load(o);
4594                 });
4595
4596                 // They are all loaded
4597                 if (l === 0 && cb) {
4598                     cb.call(s || t);
4599                     cb = 0;
4600                 }
4601             };
4602
4603             function load(o) {
4604                 if (o.state > 0)
4605                     return;
4606
4607                 o.state = 1; // Is loading
4608
4609                 tinymce.util.XHR.send({
4610                     url : o.url,
4611                     error : t.settings.error,
4612                     success : function(co) {
4613                         t.eval(co);
4614                         done(o);
4615                         allDone();
4616                     }
4617                 });
4618             };
4619
4620             each(sc, function(o) {
4621                 var u = o.url;
4622
4623                 // Add to queue if needed
4624                 if (!lo[u]) {
4625                     lo[u] = o;
4626                     t.queue.push(o);
4627                 } else
4628                     o = lo[u];
4629
4630                 // Is already loading or has been loaded
4631                 if (o.state > 0)
4632                     return;
4633
4634                 if (!tinymce.dom.Event.domLoaded && !t.settings.strict_mode) {
4635                     var ix, ol = '';
4636
4637                     // Add onload events
4638                     if (cb || o.func) {
4639                         o.state = 1; // Is loading
4640
4641                         ix = tinymce.dom.ScriptLoader._addOnLoad(function() {
4642                             done(o);
4643                             allDone();
4644                         });
4645
4646                         if (tinymce.isIE)
4647                             ol = ' onreadystatechange="';
4648                         else
4649                             ol = ' onload="';
4650
4651                         ol += 'tinymce.dom.ScriptLoader._onLoad(this,\'' + u + '\',' + ix + ');"';
4652                     }
4653
18240a 4654                     document.write('<script type="text/javascript" src="' + tinymce._addVer(u) + '"' + ol + '></script>');
d9344f 4655
S 4656                     if (!o.func)
4657                         done(o);
4658                 } else
4659                     load(o);
4660             });
4661
4662             allDone();
4663         },
4664
4665         // Static methods
4666         'static' : {
4667             _addOnLoad : function(f) {
4668                 var t = this;
4669
4670                 t._funcs = t._funcs || [];
4671                 t._funcs.push(f);
4672
4673                 return t._funcs.length - 1;
4674             },
4675
4676             _onLoad : function(e, u, ix) {
4677                 if (!tinymce.isIE || e.readyState == 'complete')
4678                     this._funcs[ix].call(this);
4679             }
4680         }
4681
4682         });
4683
4684     // Global script loader
4685     tinymce.ScriptLoader = new tinymce.dom.ScriptLoader();
4686 })();
4687
4688 /* file:jscripts/tiny_mce/classes/ui/Control.js */
4689
4690 (function() {
4691     // Shorten class names
4692     var DOM = tinymce.DOM, is = tinymce.is;
4693
4694     tinymce.create('tinymce.ui.Control', {
4695         Control : function(id, s) {
4696             this.id = id;
4697             this.settings = s = s || {};
4698             this.rendered = false;
4699             this.onRender = new tinymce.util.Dispatcher(this);
4700             this.classPrefix = '';
4701             this.scope = s.scope || this;
4702             this.disabled = 0;
4703             this.active = 0;
4704         },
4705
4706         setDisabled : function(s) {
4707             var e;
4708
4709             if (s != this.disabled) {
4710                 e = DOM.get(this.id);
4711
4712                 // Add accessibility title for unavailable actions
4713                 if (e && this.settings.unavailable_prefix) {
4714                     if (s) {
4715                         this.prevTitle = e.title;
4716                         e.title = this.settings.unavailable_prefix + ": " + e.title;
4717                     } else
4718                         e.title = this.prevTitle;
4719                 }
4720
4721                 this.setState('Disabled', s);
4722                 this.setState('Enabled', !s);
4723                 this.disabled = s;
4724             }
4725         },
4726
4727         isDisabled : function() {
4728             return this.disabled;
4729         },
4730
4731         setActive : function(s) {
4732             if (s != this.active) {
4733                 this.setState('Active', s);
4734                 this.active = s;
4735             }
4736         },
4737
4738         isActive : function() {
4739             return this.active;
4740         },
4741
4742         setState : function(c, s) {
4743             var n = DOM.get(this.id);
4744
4745             c = this.classPrefix + c;
4746
4747             if (s)
4748                 DOM.addClass(n, c);
4749             else
4750                 DOM.removeClass(n, c);
4751         },
4752
4753         isRendered : function() {
4754             return this.rendered;
4755         },
4756
4757         renderHTML : function() {
4758         },
4759
4760         renderTo : function(n) {
4761             DOM.setHTML(n, this.renderHTML());
4762         },
4763
4764         postRender : function() {
4765             var t = this, b;
4766
4767             // Set pending states
4768             if (is(t.disabled)) {
4769                 b = t.disabled;
4770                 t.disabled = -1;
4771                 t.setDisabled(b);
4772             }
4773
4774             if (is(t.active)) {
4775                 b = t.active;
4776                 t.active = -1;
4777                 t.setActive(b);
4778             }
4779         },
4780
4781         remove : function() {
4782             DOM.remove(this.id);
4783             this.destroy();
4784         },
4785
4786         destroy : function() {
4787             tinymce.dom.Event.clear(this.id);
4788         }
4789
4790         });
4791 })();
4792 /* file:jscripts/tiny_mce/classes/ui/Container.js */
4793
4794 tinymce.create('tinymce.ui.Container:tinymce.ui.Control', {
4795     Container : function(id, s) {
4796         this.parent(id, s);
4797         this.controls = [];
4798         this.lookup = {};
4799     },
4800
4801     add : function(c) {
4802         this.lookup[c.id] = c;
4803         this.controls.push(c);
4804
4805         return c;
4806     },
4807
4808     get : function(n) {
4809         return this.lookup[n];
4810     }
4811
4812     });
4813
4814
4815 /* file:jscripts/tiny_mce/classes/ui/Separator.js */
4816
4817 tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
4818     Separator : function(id, s) {
4819         this.parent(id, s);
4820         this.classPrefix = 'mceSeparator';
4821     },
4822
4823     renderHTML : function() {
4824         return tinymce.DOM.createHTML('span', {'class' : this.classPrefix});
4825     }
4826
4827     });
4828
4829 /* file:jscripts/tiny_mce/classes/ui/MenuItem.js */
4830
4831 (function() {
4832     var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk;
4833
4834     tinymce.create('tinymce.ui.MenuItem:tinymce.ui.Control', {
4835         MenuItem : function(id, s) {
4836             this.parent(id, s);
4837             this.classPrefix = 'mceMenuItem';
4838         },
4839
4840         setSelected : function(s) {
4841             this.setState('Selected', s);
4842             this.selected = s;
4843         },
4844
4845         isSelected : function() {
4846             return this.selected;
4847         },
4848
4849         postRender : function() {
4850             var t = this;
4851             
4852             t.parent();
4853
4854             // Set pending state
4855             if (is(t.selected))
4856                 t.setSelected(t.selected);
4857         }
4858
4859         });
4860 })();
4861
4862 /* file:jscripts/tiny_mce/classes/ui/Menu.js */
4863
4864 (function() {
4865     var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk;
4866
4867     tinymce.create('tinymce.ui.Menu:tinymce.ui.MenuItem', {
4868         Menu : function(id, s) {
4869             var t = this;
4870
4871             t.parent(id, s);
4872             t.items = {};
4873             t.collapsed = false;
4874             t.menuCount = 0;
4875             t.onAddItem = new tinymce.util.Dispatcher(this);
4876         },
4877
4878         expand : function(d) {
4879             var t = this;
4880
4881             if (d) {
4882                 walk(t, function(o) {
4883                     if (o.expand)
4884                         o.expand();
4885                 }, 'items', t);
4886             }
4887
4888             t.collapsed = false;
4889         },
4890
4891         collapse : function(d) {
4892             var t = this;
4893
4894             if (d) {
4895                 walk(t, function(o) {
4896                     if (o.collapse)
4897                         o.collapse();
4898                 }, 'items', t);
4899             }
4900
4901             t.collapsed = true;
4902         },
4903
4904         isCollapsed : function() {
4905             return this.collapsed;
4906         },
4907
4908         add : function(o) {
4909             if (!o.settings)
4910                 o = new tinymce.ui.MenuItem(o.id || DOM.uniqueId(), o);
4911
4912             this.onAddItem.dispatch(this, o);
4913
4914             return this.items[o.id] = o;
4915         },
4916
4917         addSeparator : function() {
4918             return this.add({separator : true});
4919         },
4920
4921         addMenu : function(o) {
4922             if (!o.collapse)
4923                 o = this.createMenu(o);
4924
4925             this.menuCount++;
4926
4927             return this.add(o);
4928         },
4929
4930         hasMenus : function() {
4931             return this.menuCount !== 0;
4932         },
4933
4934         remove : function(o) {
4935             delete this.items[o.id];
4936         },
4937
4938         removeAll : function() {
4939             var t = this;
4940
4941             walk(t, function(o) {
4942                 if (o.removeAll)
4943                     o.removeAll();
4944                 else
4945                     o.remove();
4946
4947                 o.destroy();
4948             }, 'items', t);
4949
4950             t.items = {};
4951         },
4952
4953         createMenu : function(o) {
4954             var m = new tinymce.ui.Menu(o.id || DOM.uniqueId(), o);
4955
4956             m.onAddItem.add(this.onAddItem.dispatch, this.onAddItem);
4957
4958             return m;
4959         }
4960
4961         });
4962 })();
4963 /* file:jscripts/tiny_mce/classes/ui/DropMenu.js */
4964
4965 (function() {
4966     var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, Event = tinymce.dom.Event, Element = tinymce.dom.Element;
4967
4968     tinymce.create('tinymce.ui.DropMenu:tinymce.ui.Menu', {
4969         DropMenu : function(id, s) {
4970             s = s || {};
4971             s.container = s.container || DOM.doc.body;
4972             s.offset_x = s.offset_x || 0;
4973             s.offset_y = s.offset_y || 0;
4974             s.vp_offset_x = s.vp_offset_x || 0;
4975             s.vp_offset_y = s.vp_offset_y || 0;
4976
4977             if (is(s.icons) && !s.icons)
4978                 s['class'] += ' mceNoIcons';
4979
4980             this.parent(id, s);
4981             this.onShowMenu = new tinymce.util.Dispatcher(this);
4982             this.onHideMenu = new tinymce.util.Dispatcher(this);
4983             this.classPrefix = 'mceMenu';
4984         },
4985
4986         createMenu : function(s) {
4987             var t = this, cs = t.settings, m;
4988
4989             s.container = s.container || cs.container;
4990             s.parent = t;
4991             s.constrain = s.constrain || cs.constrain;
4992             s['class'] = s['class'] || cs['class'];
4993             s.vp_offset_x = s.vp_offset_x || cs.vp_offset_x;
4994             s.vp_offset_y = s.vp_offset_y || cs.vp_offset_y;
4995             m = new tinymce.ui.DropMenu(s.id || DOM.uniqueId(), s);
4996
4997             m.onAddItem.add(t.onAddItem.dispatch, t.onAddItem);
4998
4999             return m;
5000         },
5001
5002         update : function() {
5003             var t = this, s = t.settings, tb = DOM.get('menu_' + t.id + '_tbl'), co = DOM.get('menu_' + t.id + '_co'), tw, th;
5004
5005             tw = s.max_width ? Math.min(tb.clientWidth, s.max_width) : tb.clientWidth;
5006             th = s.max_height ? Math.min(tb.clientHeight, s.max_height) : tb.clientHeight;
5007
5008             if (!DOM.boxModel)
5009                 t.element.setStyles({width : tw + 2, height : th + 2});
5010             else
5011                 t.element.setStyles({width : tw, height : th});
5012
5013             if (s.max_width)
5014                 DOM.setStyle(co, 'width', tw);
5015
5016             if (s.max_height) {
5017                 DOM.setStyle(co, 'height', th);
5018
5019                 if (tb.clientHeight < s.max_height)
5020                     DOM.setStyle(co, 'overflow', 'hidden');
5021             }
5022         },
5023
5024         showMenu : function(x, y, px) {
5025             var t = this, s = t.settings, co, vp = DOM.getViewPort(), w, h, mx, my, ot = 2, dm, tb, cp = t.classPrefix;
5026
5027             t.collapse(1);
5028
5029             if (t.isMenuVisible)
5030                 return;
5031
5032             if (!t.rendered) {
5033                 co = DOM.add(t.settings.container, t.renderNode());
5034
5035                 each(t.items, function(o) {
5036                     o.postRender();
5037                 });
5038
5039                 t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container});
5040             } else
5041                 co = DOM.get('menu_' + t.id);
5042
5043             // Move layer out of sight unless it's Opera since it scrolls to top of page due to an bug
5044             if (!tinymce.isOpera)
5045                 DOM.setStyles(co, {left : -0xFFFF , top : -0xFFFF});
5046
5047             DOM.show(co);
5048             t.update();
5049
5050             x += s.offset_x || 0;
5051             y += s.offset_y || 0;
5052             vp.w -= 4;
5053             vp.h -= 4;
5054
5055             // Move inside viewport if not submenu
5056             if (s.constrain) {
5057                 w = co.clientWidth - ot;
5058                 h = co.clientHeight - ot;
5059                 mx = vp.x + vp.w;
5060                 my = vp.y + vp.h;
5061
5062                 if ((x + s.vp_offset_x + w) > mx)
5063                     x = px ? px - w : Math.max(0, (mx - s.vp_offset_x) - w);
5064
5065                 if ((y + s.vp_offset_y + h) > my)
5066                     y = Math.max(0, (my - s.vp_offset_y) - h);
5067             }
5068
5069             DOM.setStyles(co, {left : x , top : y});
5070             t.element.update();
5071
5072             t.isMenuVisible = 1;
18240a 5073             t.mouseClickFunc = Event.add(co, 'click', function(e) {
d9344f 5074                 var m;
S 5075
5076                 e = e.target;
5077
5078                 if (e && (e = DOM.getParent(e, 'TR')) && !DOM.hasClass(e, cp + 'ItemSub')) {
5079                     m = t.items[e.id];
5080
5081                     if (m.isDisabled())
5082                         return;
5083
5084                     dm = t;
5085
5086                     while (dm) {
5087                         if (dm.hideMenu)
5088                             dm.hideMenu();
5089
5090                         dm = dm.settings.parent;
5091                     }
5092
5093                     if (m.settings.onclick)
5094                         m.settings.onclick(e);
5095
5096                     return Event.cancel(e); // Cancel to fix onbeforeunload problem
5097                 }
5098             });
5099
5100             if (t.hasMenus()) {
5101                 t.mouseOverFunc = Event.add(co, 'mouseover', function(e) {
5102                     var m, r, mi;
5103
5104                     e = e.target;
5105                     if (e && (e = DOM.getParent(e, 'TR'))) {
5106                         m = t.items[e.id];
5107
5108                         if (t.lastMenu)
5109                             t.lastMenu.collapse(1);
5110
5111                         if (m.isDisabled())
5112                             return;
5113
5114                         if (e && DOM.hasClass(e, cp + 'ItemSub')) {
5115                             //p = DOM.getPos(s.container);
5116                             r = DOM.getRect(e);
5117                             m.showMenu((r.x + r.w - ot), r.y - ot, r.x);
5118                             t.lastMenu = m;
5119                             DOM.addClass(DOM.get(m.id).firstChild, cp + 'ItemActive');
5120                         }
5121                     }
5122                 });
5123             }
5124
5125             t.onShowMenu.dispatch(t);
5126
5127             if (s.keyboard_focus) {
5128                 Event.add(co, 'keydown', t._keyHandler, t);
5129                 DOM.select('a', 'menu_' + t.id)[0].focus(); // Select first link
18240a 5130                 t._focusIdx = 0;
d9344f 5131             }
S 5132         },
5133
5134         hideMenu : function(c) {
5135             var t = this, co = DOM.get('menu_' + t.id), e;
5136
5137             if (!t.isMenuVisible)
5138                 return;
5139
5140             Event.remove(co, 'mouseover', t.mouseOverFunc);
18240a 5141             Event.remove(co, 'click', t.mouseClickFunc);
d9344f 5142             Event.remove(co, 'keydown', t._keyHandler);
S 5143             DOM.hide(co);
5144             t.isMenuVisible = 0;
5145
5146             if (!c)
5147                 t.collapse(1);
5148
5149             if (t.element)
5150                 t.element.hide();
5151
5152             if (e = DOM.get(t.id))
5153                 DOM.removeClass(e.firstChild, t.classPrefix + 'ItemActive');
5154
5155             t.onHideMenu.dispatch(t);
5156         },
5157
5158         add : function(o) {
5159             var t = this, co;
5160
5161             o = t.parent(o);
5162
5163             if (t.isRendered && (co = DOM.get('menu_' + t.id)))
5164                 t._add(DOM.select('tbody', co)[0], o);
5165
5166             return o;
5167         },
5168
5169         collapse : function(d) {
5170             this.parent(d);
5171             this.hideMenu(1);
5172         },
5173
5174         remove : function(o) {
5175             DOM.remove(o.id);
5176             this.destroy();
5177
5178             return this.parent(o);
5179         },
5180
5181         destroy : function() {
5182             var t = this, co = DOM.get('menu_' + t.id);
5183
5184             Event.remove(co, 'mouseover', t.mouseOverFunc);
5185             Event.remove(co, 'click', t.mouseClickFunc);
5186
5187             if (t.element)
5188                 t.element.remove();
5189
5190             DOM.remove(co);
5191         },
5192
5193         renderNode : function() {
5194             var t = this, s = t.settings, n, tb, co, w;
5195
5196             w = DOM.create('div', {id : 'menu_' + t.id, 'class' : s['class'], 'style' : 'position:absolute;left:0;top:0;z-index:200000'});
5197             co = DOM.add(w, 'div', {id : 'menu_' + t.id + '_co', 'class' : t.classPrefix + (s['class'] ? ' ' + s['class'] : '')});
5198             t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container});
5199
5200             if (s.menu_line)
5201                 DOM.add(co, 'span', {'class' : t.classPrefix + 'Line'});
5202
5203 //            n = DOM.add(co, 'div', {id : 'menu_' + t.id + '_co', 'class' : 'mceMenuContainer'});
5204             n = DOM.add(co, 'table', {id : 'menu_' + t.id + '_tbl', border : 0, cellPadding : 0, cellSpacing : 0});
5205             tb = DOM.add(n, 'tbody');
5206
5207             each(t.items, function(o) {
5208                 t._add(tb, o);
5209             });
5210
5211             t.rendered = true;
5212
5213             return w;
5214         },
5215
5216         // Internal functions
5217
5218         _keyHandler : function(e) {
18240a 5219             var t = this, kc = e.keyCode;
A 5220
5221             function focus(d) {
5222                 var i = t._focusIdx + d, e = DOM.select('a', 'menu_' + t.id)[i];
5223
5224                 if (e) {
5225                     t._focusIdx = i;
5226                     e.focus();
5227                 }
5228             };
5229
5230             switch (kc) {
5231                 case 38:
5232                     focus(-1); // Select first link
5233                     return;
5234
5235                 case 40:
5236                     focus(1);
5237                     return;
5238
5239                 case 13:
5240                     return;
5241
5242                 case 27:
5243                     return this.hideMenu();
5244             }
d9344f 5245         },
S 5246
5247         _add : function(tb, o) {
5248             var n, s = o.settings, a, ro, it, cp = this.classPrefix;
5249
5250             if (s.separator) {
5251                 ro = DOM.add(tb, 'tr', {id : o.id, 'class' : cp + 'ItemSeparator'});
5252                 DOM.add(ro, 'td', {'class' : cp + 'ItemSeparator'});
5253
5254                 if (n = ro.previousSibling)
5255                     DOM.addClass(n, 'mceLast');
5256
5257                 return;
5258             }
5259
5260             n = ro = DOM.add(tb, 'tr', {id : o.id, 'class' : cp + 'Item ' + cp + 'ItemEnabled'});
5261             n = it = DOM.add(n, 'td');
5262             n = a = DOM.add(n, 'a', {href : 'javascript:;', onclick : "return false;", onmousedown : 'return false;'});
5263
5264             DOM.addClass(it, s['class']);
5265 //            n = DOM.add(n, 'span', {'class' : 'item'});
5266             DOM.add(n, 'span', {'class' : 'mceIcon' + (s.icon ? ' mce_' + s.icon : '')});
5267             n = DOM.add(n, s.element || 'span', {'class' : 'mceText', title : o.settings.title}, o.settings.title);
5268
5269             if (o.settings.style)
5270                 DOM.setAttrib(n, 'style', o.settings.style);
5271
5272             if (tb.childNodes.length == 1)
5273                 DOM.addClass(ro, 'mceFirst');
5274
5275             if ((n = ro.previousSibling) && DOM.hasClass(n, cp + 'ItemSeparator'))
5276                 DOM.addClass(ro, 'mceFirst');
5277
5278             if (o.collapse)
5279                 DOM.addClass(ro, cp + 'ItemSub');
5280
5281             if (n = ro.previousSibling)
5282                 DOM.removeClass(n, 'mceLast');
5283
5284             DOM.addClass(ro, 'mceLast');
5285         }
5286
5287         });
5288 })();
5289 /* file:jscripts/tiny_mce/classes/ui/Button.js */
5290
5291 (function() {
5292     var DOM = tinymce.DOM;
5293
5294     tinymce.create('tinymce.ui.Button:tinymce.ui.Control', {
5295         Button : function(id, s) {
5296             this.parent(id, s);
5297             this.classPrefix = 'mceButton';
5298         },
5299
5300         renderHTML : function() {
18240a 5301             var cp = this.classPrefix, s = this.settings, h, l;
A 5302
5303             l = DOM.encode(s.label || '');
5304             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) + '">';
d9344f 5305
S 5306             if (s.image)
18240a 5307                 h += '<img class="mceIcon" src="' + s.image + '" />' + l + '</a>';
d9344f 5308             else
18240a 5309                 h += '<span class="mceIcon ' + s['class'] + '"></span>' + (l ? '<span class="' + cp + 'Label">' + l + '</span>' : '') + '</a>';
d9344f 5310
S 5311             return h;
5312         },
5313
5314         postRender : function() {
5315             var t = this, s = t.settings;
5316
5317             tinymce.dom.Event.add(t.id, 'click', function(e) {
5318                 if (!t.isDisabled())
5319                     return s.onclick.call(s.scope, e);
5320             });
5321         }
5322
5323         });
5324 })();
5325
5326 /* file:jscripts/tiny_mce/classes/ui/ListBox.js */
5327
5328 (function() {
5329     var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher;
5330
5331     tinymce.create('tinymce.ui.ListBox:tinymce.ui.Control', {
5332         ListBox : function(id, s) {
5333             var t = this;
5334
5335             t.parent(id, s);
5336             t.items = [];
5337             t.onChange = new Dispatcher(t);
5338             t.onPostRender = new Dispatcher(t);
5339             t.onAdd = new Dispatcher(t);
5340             t.onRenderMenu = new tinymce.util.Dispatcher(this);
5341             t.classPrefix = 'mceListBox';
5342         },
5343
5344         select : function(v) {
5345             var t = this, e, fv;
5346
5347             // Do we need to do something?
5348             if (v != t.selectedValue) {
5349                 e = DOM.get(t.id + '_text');
5350                 t.selectedValue = v;
5351
5352                 // Find item
5353                 each(t.items, function(o) {
5354                     if (o.value == v) {
5355                         DOM.setHTML(e, DOM.encode(o.title));
5356                         fv = 1;
5357                         return false;
5358                     }
5359                 });
5360
5361                 // If no item was found then present title
5362                 if (!fv) {
5363                     DOM.setHTML(e, DOM.encode(t.settings.title));
5364                     DOM.addClass(e, 'mceTitle');
5365                     e = 0;
5366                     return;
5367                 } else
5368                     DOM.removeClass(e, 'mceTitle');
5369             }
5370
5371             e = 0;
5372         },
5373
5374         add : function(n, v, o) {
5375             var t = this;
5376
5377             o = o || {};
5378             o = tinymce.extend(o, {
5379                 title : n,
5380                 value : v
5381             });
5382
5383             t.items.push(o);
5384             t.onAdd.dispatch(t, o);
5385         },
5386
5387         getLength : function() {
5388             return this.items.length;
5389         },
5390
5391         renderHTML : function() {
5392             var h = '', t = this, s = t.settings, cp = t.classPrefix;
5393
5394             h = '<table id="' + t.id + '" cellpadding="0" cellspacing="0" class="' + cp + ' ' + cp + 'Enabled' + (s['class'] ? (' ' + s['class']) : '') + '"><tbody><tr>';
5395             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>';
5396             h += '<td>' + DOM.createHTML('a', {id : t.id + '_open', tabindex : -1, href : 'javascript:;', 'class' : 'mceOpen', onclick : "return false;", onmousedown : 'return false;'}, '<span></span>') + '</td>';
5397             h += '</tr></tbody></table>';
5398
5399             return h;
5400         },
5401
5402         showMenu : function() {
5403             var t = this, p1, p2, e = DOM.get(this.id), m;
5404
5405             if (t.isDisabled() || t.items.length == 0)
5406                 return;
5407
18240a 5408             if (t.menu && t.menu.isMenuVisible)
A 5409                 return t.hideMenu();
5410
d9344f 5411             if (!t.isMenuRendered) {
S 5412                 t.renderMenu();
5413                 t.isMenuRendered = true;
5414             }
5415
5416             p1 = DOM.getPos(this.settings.menu_container);
5417             p2 = DOM.getPos(e);
5418
5419             m = t.menu;
5420             m.settings.offset_x = p2.x;
5421             m.settings.offset_y = p2.y;
18240a 5422             m.settings.keyboard_focus = !tinymce.isOpera; // Opera is buggy when it comes to auto focus
d9344f 5423
S 5424             // Select in menu
5425             if (t.oldID)
5426                 m.items[t.oldID].setSelected(0);
5427
5428             each(t.items, function(o) {
5429                 if (o.value === t.selectedValue) {
5430                     m.items[o.id].setSelected(1);
5431                     t.oldID = o.id;
5432                 }
5433             });
5434
5435             m.showMenu(0, e.clientHeight);
5436
5437             Event.add(DOM.doc, 'mousedown', t.hideMenu, t);
5438             DOM.addClass(t.id, t.classPrefix + 'Selected');
18240a 5439
A 5440             //DOM.get(t.id + '_text').focus();
d9344f 5441         },
S 5442
5443         hideMenu : function(e) {
5444             var t = this;
18240a 5445
A 5446             // Prevent double toogles by canceling the mouse click event to the button
5447             if (e && e.type == "mousedown" && (e.target.id == t.id + '_text' || e.target.id == t.id + '_open'))
5448                 return;
d9344f 5449
S 5450             if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceMenu');})) {
5451                 DOM.removeClass(t.id, t.classPrefix + 'Selected');
5452                 Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);
5453
5454                 if (t.menu)
5455                     t.menu.hideMenu();
5456             }
5457         },
5458
5459         renderMenu : function() {
5460             var t = this, m;
5461
5462             m = t.settings.control_manager.createDropMenu(t.id + '_menu', {
5463                 menu_line : 1,
5464                 'class' : t.classPrefix + 'Menu mceNoIcons',
5465                 max_width : 150,
5466                 max_height : 150
5467             });
5468
5469             m.onHideMenu.add(t.hideMenu, t);
5470
5471             m.add({
5472                 title : t.settings.title,
18240a 5473                 'class' : 'mceMenuItemTitle',
A 5474                 onclick : function() {
5475                     if (t.settings.onselect('') !== false)
5476                         t.select(''); // Must be runned after
5477                 }
5478             });
d9344f 5479
S 5480             each(t.items, function(o) {
5481                 o.id = DOM.uniqueId();
5482                 o.onclick = function() {
5483                     if (t.settings.onselect(o.value) !== false)
5484                         t.select(o.value); // Must be runned after
5485                 };
5486
5487                 m.add(o);
5488             });
5489
5490             t.onRenderMenu.dispatch(t, m);
5491             t.menu = m;
5492         },
5493
5494         postRender : function() {
5495             var t = this, cp = t.classPrefix;
5496
5497             Event.add(t.id, 'click', t.showMenu, t);
18240a 5498             Event.add(t.id + '_text', 'focus', function(e) {
A 5499                 if (!t._focused) {
5500                     t.keyDownHandler = Event.add(t.id + '_text', 'keydown', function(e) {
5501                         var idx = -1, v, kc = e.keyCode;
5502
5503                         // Find current index
5504                         each(t.items, function(v, i) {
5505                             if (t.selectedValue == v.value)
5506                                 idx = i;
5507                         });
5508
5509                         // Move up/down
5510                         if (kc == 38)
5511                             v = t.items[idx - 1];
5512                         else if (kc == 40)
5513                             v = t.items[idx + 1];
5514                         else if (kc == 13) {
5515                             // Fake select on enter
5516                             v = t.selectedValue;
5517                             t.selectedValue = null; // Needs to be null to fake change
5518                             t.settings.onselect(v);
5519                             return Event.cancel(e);
5520                         }
5521
5522                         if (v) {
5523                             t.hideMenu();
5524                             t.select(v.value);
5525                         }
5526                     });
5527                 }
5528
5529                 t._focused = 1;
5530             });
5531             Event.add(t.id + '_text', 'blur', function() {Event.remove(t.id + '_text', 'keydown', t.keyDownHandler); t._focused = 0;});
d9344f 5532
S 5533             // Old IE doesn't have hover on all elements
5534             if (tinymce.isIE6 || !DOM.boxModel) {
5535                 Event.add(t.id, 'mouseover', function() {
5536                     if (!DOM.hasClass(t.id, cp + 'Disabled'))
5537                         DOM.addClass(t.id, cp + 'Hover');
5538                 });
5539
5540                 Event.add(t.id, 'mouseout', function() {
5541                     if (!DOM.hasClass(t.id, cp + 'Disabled'))
5542                         DOM.removeClass(t.id, cp + 'Hover');
5543                 });
5544             }
5545
5546             t.onPostRender.dispatch(t, DOM.get(t.id));
5547         },
5548
5549         destroy : function() {
5550             this.parent();
5551
5552             Event.clear(this.id + '_text');
5553         }
5554
5555         });
5556 })();
5557 /* file:jscripts/tiny_mce/classes/ui/NativeListBox.js */
5558
5559 (function() {
5560     var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher;
5561
5562     tinymce.create('tinymce.ui.NativeListBox:tinymce.ui.ListBox', {
5563         NativeListBox : function(id, s) {
5564             this.parent(id, s);
5565             this.classPrefix = 'mceNativeListBox';
5566         },
5567
5568         setDisabled : function(s) {
5569             DOM.get(this.id).disabled = s;
5570         },
5571
5572         isDisabled : function() {
5573             return DOM.get(this.id).disabled;
5574         },
5575
5576         select : function(v) {
5577             var e = DOM.get(this.id), ol = e.options;
5578
5579             v = '' + (v || '');
5580
5581             e.selectedIndex = 0;
5582             each(ol, function(o, i) {
5583                 if (o.value == v) {
5584                     e.selectedIndex = i;
5585                     return false;
5586                 }
5587             });
5588         },
5589
5590         add : function(n, v, a) {
5591             var o, t = this;
5592
5593             a = a || {};
5594             a.value = v;
5595
5596             if (t.isRendered())
5597                 DOM.add(DOM.get(this.id), 'option', a, n);
5598
5599             o = {
5600                 title : n,
5601                 value : v,
5602                 attribs : a
5603             };
5604
5605             t.items.push(o);
5606             t.onAdd.dispatch(t, o);
5607         },
5608
5609         getLength : function() {
5610             return DOM.get(this.id).options.length - 1;
5611         },
5612
5613         renderHTML : function() {
5614             var h, t = this;
5615
5616             h = DOM.createHTML('option', {value : ''}, '-- ' + t.settings.title + ' --');
5617
5618             each(t.items, function(it) {
5619                 h += DOM.createHTML('option', {value : it.value}, it.title);
5620             });
5621
5622             h = DOM.createHTML('select', {id : t.id, 'class' : 'mceNativeListBox'}, h);
5623
5624             return h;
5625         },
5626
5627         postRender : function() {
5628             var t = this, ch;
5629
5630             t.rendered = true;
5631
5632             function onChange(e) {
5633                 var v = e.target.options[e.target.selectedIndex].value;
5634
5635                 t.onChange.dispatch(t, v);
5636
5637                 if (t.settings.onselect)
5638                     t.settings.onselect(v);
5639             };
5640
5641             Event.add(t.id, 'change', onChange);
5642
5643             // Accessibility keyhandler
5644             Event.add(t.id, 'keydown', function(e) {
5645                 var bf;
5646
5647                 Event.remove(t.id, 'change', ch);
5648
5649                 bf = Event.add(t.id, 'blur', function() {
5650                     Event.add(t.id, 'change', onChange);
5651                     Event.remove(t.id, 'blur', bf);
5652                 });
5653
5654                 if (e.keyCode == 13 || e.keyCode == 32) {
5655                     onChange(e);
5656                     return Event.cancel(e);
5657                 }
5658             });
5659
5660             t.onPostRender.dispatch(t, DOM.get(t.id));
5661         }
5662
5663         });
5664 })();
5665 /* file:jscripts/tiny_mce/classes/ui/MenuButton.js */
5666
5667 (function() {
5668     var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each;
5669
5670     tinymce.create('tinymce.ui.MenuButton:tinymce.ui.Button', {
5671         MenuButton : function(id, s) {
5672             this.parent(id, s);
5673             this.onRenderMenu = new tinymce.util.Dispatcher(this);
5674             s.menu_container = s.menu_container || DOM.doc.body;
5675         },
5676
5677         showMenu : function() {
5678             var t = this, p1, p2, e = DOM.get(t.id), m;
5679
5680             if (t.isDisabled())
5681                 return;
5682
5683             if (!t.isMenuRendered) {
5684                 t.renderMenu();
5685                 t.isMenuRendered = true;
5686             }
5687
18240a 5688             if (t.isMenuVisible)
A 5689                 return t.hideMenu();
5690
d9344f 5691             p1 = DOM.getPos(t.settings.menu_container);
S 5692             p2 = DOM.getPos(e);
5693
5694             m = t.menu;
5695             m.settings.offset_x = p2.x;
5696             m.settings.offset_y = p2.y;
5697             m.settings.vp_offset_x = p2.x;
5698             m.settings.vp_offset_y = p2.y;
5699             m.settings.keyboard_focus = t._focused;
5700             m.showMenu(0, e.clientHeight);
5701
5702             Event.add(DOM.doc, 'mousedown', t.hideMenu, t);
5703             t.setState('Selected', 1);
18240a 5704
A 5705             t.isMenuVisible = 1;
d9344f 5706         },
S 5707
5708         renderMenu : function() {
5709             var t = this, m;
5710
5711             m = t.settings.control_manager.createDropMenu(t.id + '_menu', {
5712                 menu_line : 1,
5713                 'class' : this.classPrefix + 'Menu',
5714                 icons : t.settings.icons
5715             });
5716
5717             m.onHideMenu.add(t.hideMenu, t);
5718
5719             t.onRenderMenu.dispatch(t, m);
5720             t.menu = m;
5721         },
5722
5723         hideMenu : function(e) {
5724             var t = this;
5725
18240a 5726             // Prevent double toogles by canceling the mouse click event to the button
A 5727             if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id || e.id === t.id + '_open';}))
5728                 return;
5729
d9344f 5730             if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceMenu');})) {
S 5731                 t.setState('Selected', 0);
5732                 Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);
5733                 if (t.menu)
5734                     t.menu.hideMenu();
5735             }
18240a 5736
A 5737             t.isMenuVisible = 0;
d9344f 5738         },
S 5739
5740         postRender : function() {
5741             var t = this, s = t.settings;
5742
5743             Event.add(t.id, 'click', function() {
5744                 if (!t.isDisabled()) {
5745                     if (s.onclick)
5746                         s.onclick(t.value);
5747
5748                     t.showMenu();
5749                 }
5750             });
5751         }
5752
5753         });
5754 })();
5755
5756 /* file:jscripts/tiny_mce/classes/ui/SplitButton.js */
5757
5758 (function() {
5759     var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each;
5760
5761     tinymce.create('tinymce.ui.SplitButton:tinymce.ui.MenuButton', {
5762         SplitButton : function(id, s) {
5763             this.parent(id, s);
5764             this.classPrefix = 'mceSplitButton';
5765         },
5766
5767         renderHTML : function() {
5768             var h, t = this, s = t.settings, h1;
5769
5770             h = '<tbody><tr>';
5771
5772             if (s.image)
5773                 h1 = DOM.createHTML('img ', {src : s.image, 'class' : 'mceAction ' + s['class']});
5774             else
5775                 h1 = DOM.createHTML('span', {'class' : 'mceAction ' + s['class']}, '');
5776
5777             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>';
5778     
5779             h1 = DOM.createHTML('span', {'class' : 'mceOpen ' + s['class']});
5780             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>';
5781
5782             h += '</tr></tbody>';
5783
5784             return DOM.createHTML('table', {id : t.id, 'class' : 'mceSplitButton mceSplitButtonEnabled ' + s['class'], cellpadding : '0', cellspacing : '0', onmousedown : 'return false;', title : s.title}, h);
5785         },
5786
5787         postRender : function() {
5788             var t = this, s = t.settings;
5789
5790             if (s.onclick) {
5791                 Event.add(t.id + '_action', 'click', function() {
5792                     if (!t.isDisabled())
5793                         s.onclick(t.value);
5794                 });
5795             }
5796
5797             Event.add(t.id + '_open', 'click', t.showMenu, t);
5798             Event.add(t.id + '_open', 'focus', function() {t._focused = 1;});
5799             Event.add(t.id + '_open', 'blur', function() {t._focused = 0;});
5800
5801             // Old IE doesn't have hover on all elements
5802             if (tinymce.isIE6 || !DOM.boxModel) {
5803                 Event.add(t.id, 'mouseover', function() {
5804                     if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled'))
5805                         DOM.addClass(t.id, 'mceSplitButtonHover');
5806                 });
5807
5808                 Event.add(t.id, 'mouseout', function() {
5809                     if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled'))
5810                         DOM.removeClass(t.id, 'mceSplitButtonHover');
5811                 });
5812             }
5813         },
5814
5815         destroy : function() {
5816             this.parent();
5817
5818             Event.clear(this.id + '_action');
5819             Event.clear(this.id + '_open');
5820         }
5821
5822         });
5823 })();
5824
5825 /* file:jscripts/tiny_mce/classes/ui/ColorSplitButton.js */
5826
5827 (function() {
5828     var DOM = tinymce.DOM, Event = tinymce.dom.Event, is = tinymce.is, each = tinymce.each;
5829
5830     tinymce.create('tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton', {
5831         ColorSplitButton : function(id, s) {
5832             var t = this;
5833
5834             t.parent(id, s);
5835
5836             t.settings = s = tinymce.extend({
5837                 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',
5838                 grid_width : 8,
5839                 default_color : '#888888'
5840             }, t.settings);
5841
18240a 5842             t.onShowMenu = new tinymce.util.Dispatcher(t);
A 5843             t.onHideMenu = new tinymce.util.Dispatcher(t);
5844
d9344f 5845             t.value = s.default_color;
S 5846         },
5847
5848         showMenu : function() {
5849             var t = this, r, p, e, p2;
5850
5851             if (t.isDisabled())
5852                 return;
5853
5854             if (!t.isMenuRendered) {
5855                 t.renderMenu();
5856                 t.isMenuRendered = true;
5857             }
18240a 5858
A 5859             if (t.isMenuVisible)
5860                 return t.hideMenu();
d9344f 5861
S 5862             e = DOM.get(t.id);
5863             DOM.show(t.id + '_menu');
5864             DOM.addClass(e, 'mceSplitButtonSelected');
5865             p2 = DOM.getPos(e);
5866             DOM.setStyles(t.id + '_menu', {
5867                 left : p2.x,
5868                 top : p2.y + e.clientHeight,
5869                 zIndex : 200000
5870             });
5871             e = 0;
5872
5873             Event.add(DOM.doc, 'mousedown', t.hideMenu, t);
5874
5875             if (t._focused) {
5876                 t._keyHandler = Event.add(t.id + '_menu', 'keydown', function(e) {
5877                     if (e.keyCode == 27)
5878                         t.hideMenu();
5879                 });
5880
5881                 DOM.select('a', t.id + '_menu')[0].focus(); // Select first link
5882             }
18240a 5883
A 5884             t.onShowMenu.dispatch(t);
5885
5886             t.isMenuVisible = 1;
d9344f 5887         },
S 5888
5889         hideMenu : function(e) {
5890             var t = this;
18240a 5891
A 5892             // Prevent double toogles by canceling the mouse click event to the button
5893             if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id + '_open';}))
5894                 return;
d9344f 5895
S 5896             if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceSplitButtonMenu');})) {
5897                 DOM.removeClass(t.id, 'mceSplitButtonSelected');
5898                 Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);
5899                 Event.remove(t.id + '_menu', 'keydown', t._keyHandler);
5900                 DOM.hide(t.id + '_menu');
5901             }
18240a 5902
A 5903             t.onHideMenu.dispatch(t);
5904
5905             t.isMenuVisible = 0;
d9344f 5906         },
S 5907
5908         renderMenu : function() {
5909             var t = this, m, i = 0, s = t.settings, n, tb, tr, w;
5910
5911             w = DOM.add(s.menu_container, 'div', {id : t.id + '_menu', 'class' : s['menu_class'] + ' ' + s['class'], style : 'position:absolute;left:0;top:-1000px;'});
5912             m = DOM.add(w, 'div', {'class' : s['class'] + ' mceSplitButtonMenu'});
5913             DOM.add(m, 'span', {'class' : 'mceMenuLine'});
5914
5915             n = DOM.add(m, 'table', {'class' : 'mceColorSplitMenu'});
5916             tb = DOM.add(n, 'tbody');
5917
5918             // Generate color grid
5919             i = 0;
5920             each(is(s.colors, 'array') ? s.colors : s.colors.split(','), function(c) {
5921                 c = c.replace(/^#/, '');
5922
5923                 if (!i--) {
5924                     tr = DOM.add(tb, 'tr');
5925                     i = s.grid_width - 1;
5926                 }
5927
5928                 n = DOM.add(tr, 'td');
5929
5930                 n = DOM.add(n, 'a', {
5931                     href : 'javascript:;',
5932                     style : {
5933                         backgroundColor : '#' + c
5934                     },
5935                     mce_color : '#' + c
5936                 });
5937             });
5938
5939             if (s.more_colors_func) {
5940                 n = DOM.add(tb, 'tr');
5941                 n = DOM.add(n, 'td', {colspan : s.grid_width, 'class' : 'mceMoreColors'});
5942                 n = DOM.add(n, 'a', {id : t.id + '_more', href : 'javascript:;', onclick : 'return false;', 'class' : 'mceMoreColors'}, s.more_colors_title);
5943
5944                 Event.add(n, 'click', function(e) {
5945                     s.more_colors_func.call(s.more_colors_scope || this);
5946                     return Event.cancel(e); // Cancel to fix onbeforeunload problem
5947                 });
5948             }
5949
5950             DOM.addClass(m, 'mceColorSplitMenu');
5951
5952             Event.add(t.id + '_menu', 'click', function(e) {
5953                 var c;
5954
5955                 e = e.target;
5956
5957                 if (e.nodeName == 'A' && (c = e.getAttribute('mce_color')))
5958                     t.setColor(c);
18240a 5959
A 5960                 return Event.cancel(e); // Prevent IE auto save warning
d9344f 5961             });
S 5962
5963             return w;
5964         },
5965
5966         setColor : function(c) {
5967             var t = this;
5968
5969             DOM.setStyle(t.id + '_preview', 'backgroundColor', c);
5970
5971             t.value = c;
5972             t.hideMenu();
5973             t.settings.onselect(c);
5974         },
5975
5976         postRender : function() {
5977             var t = this, id = t.id;
5978
5979             t.parent();
5980             DOM.add(id + '_action', 'div', {id : id + '_preview', 'class' : 'mceColorPreview'});
5981         },
5982
5983         destroy : function() {
5984             this.parent();
5985
5986             Event.clear(this.id + '_menu');
5987             Event.clear(this.id + '_more');
5988             DOM.remove(this.id + '_menu');
5989         }
5990
5991         });
5992 })();
5993
5994 /* file:jscripts/tiny_mce/classes/ui/Toolbar.js */
5995
5996 tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
5997     renderHTML : function() {
5998         var t = this, h = '', c, co, dom = tinymce.DOM, s = t.settings, i, pr, nx, cl;
5999
6000         cl = t.controls;
6001         for (i=0; i<cl.length; i++) {
6002             // Get current control, prev control, next control and if the control is a list box or not
6003             co = cl[i];
6004             pr = cl[i - 1];
6005             nx = cl[i + 1];
6006
6007             // Add toolbar start
6008             if (i === 0) {
6009                 c = 'mceToolbarStart';
6010
6011                 if (co.Button)
6012                     c += ' mceToolbarStartButton';
6013                 else if (co.SplitButton)
6014                     c += ' mceToolbarStartSplitButton';
6015                 else if (co.ListBox)
6016                     c += ' mceToolbarStartListBox';
6017
6018                 h += dom.createHTML('td', {'class' : c}, dom.createHTML('span', null, '<!-- IE -->'));
6019             }
6020
6021             // Add toolbar end before list box and after the previous button
6022             // This is to fix the o2k7 editor skins
6023             if (pr && co.ListBox) {
6024                 if (pr.Button || pr.SplitButton)
6025                     h += dom.createHTML('td', {'class' : 'mceToolbarEnd'}, dom.createHTML('span', null, '<!-- IE -->'));
6026             }
6027
6028             // Render control HTML
6029
6030             // IE 8 quick fix, needed to propertly generate a hit area for anchors
6031             if (dom.stdMode)
6032                 h += '<td style="position: relative">' + co.renderHTML() + '</td>';
6033             else
6034                 h += '<td>' + co.renderHTML() + '</td>';
6035
6036             // Add toolbar start after list box and before the next button
6037             // This is to fix the o2k7 editor skins
6038             if (nx && co.ListBox) {
6039                 if (nx.Button || nx.SplitButton)
6040                     h += dom.createHTML('td', {'class' : 'mceToolbarStart'}, dom.createHTML('span', null, '<!-- IE -->'));
6041             }
6042         }
6043
6044         c = 'mceToolbarEnd';
6045
6046         if (co.Button)
6047             c += ' mceToolbarEndButton';
6048         else if (co.SplitButton)
6049             c += ' mceToolbarEndSplitButton';
6050         else if (co.ListBox)
6051             c += ' mceToolbarEndListBox';
6052
6053         h += dom.createHTML('td', {'class' : c}, dom.createHTML('span', null, '<!-- IE -->'));
6054
6055         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>');
6056     }
6057
6058     });
6059
6060 /* file:jscripts/tiny_mce/classes/AddOnManager.js */
6061
6062 (function() {
6063     var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each;
6064
6065     tinymce.create('tinymce.AddOnManager', {
6066         items : [],
6067         urls : {},
6068         lookup : {},
6069         onAdd : new Dispatcher(this),
6070
6071         get : function(n) {
6072             return this.lookup[n];
6073         },
6074
6075         requireLangPack : function(n) {
6076             var u, s;
6077
6078             if (tinymce.EditorManager.settings) {
6079                 u = this.urls[n] + '/langs/' + tinymce.EditorManager.settings.language + '.js';
6080                 s = tinymce.EditorManager.settings;
6081
6082                 if (s) {
6083                     if (!tinymce.dom.Event.domLoaded && !s.strict_mode)
6084                         tinymce.ScriptLoader.load(u);
6085                     else
6086                         tinymce.ScriptLoader.add(u);
6087                 }
6088             }
6089         },
6090
6091         add : function(id, o) {
6092             this.items.push(o);
6093             this.lookup[id] = o;
6094             this.onAdd.dispatch(this, id, o);
6095
6096             return o;
6097         },
6098
6099         load : function(n, u, cb, s) {
6100             var t = this;
6101
6102             if (t.urls[n])
6103                 return;
6104
6105             if (u.indexOf('/') != 0 && u.indexOf('://') == -1)
6106                 u = tinymce.baseURL + '/' +  u;
6107
6108             t.urls[n] = u.substring(0, u.lastIndexOf('/'));
6109             tinymce.ScriptLoader.add(u, cb, s);
6110         }
6111
6112         });
6113
6114     // Create plugin and theme managers
6115     tinymce.PluginManager = new tinymce.AddOnManager();
6116     tinymce.ThemeManager = new tinymce.AddOnManager();
6117 }());
6118 /* file:jscripts/tiny_mce/classes/EditorManager.js */
6119
6120 (function() {
6121     // Shorten names
6122     var each = tinymce.each, extend = tinymce.extend, DOM = tinymce.DOM, Event = tinymce.dom.Event, ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, explode = tinymce.explode;
6123
6124     tinymce.create('static tinymce.EditorManager', {
6125         editors : {},
6126         i18n : {},
6127         activeEditor : null,
6128
6129         preInit : function() {
6130             var t = this, lo = window.location;
6131
6132             // Setup some URLs where the editor API is located and where the document is
6133             tinymce.documentBaseURL = lo.href.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');
6134             if (!/[\/\\]$/.test(tinymce.documentBaseURL))
6135                 tinymce.documentBaseURL += '/';
6136
6137             tinymce.baseURL = new tinymce.util.URI(tinymce.documentBaseURL).toAbsolute(tinymce.baseURL);
6138             tinymce.EditorManager.baseURI = new tinymce.util.URI(tinymce.baseURL);
6139
6140             // Setup document domain
6141             if (tinymce.EditorManager.baseURI.host != lo.hostname && lo.hostname)
6142                 document.domain = tinymce.relaxedDomain = lo.hostname.replace(/.*\.(.+\..+)$/, '$1');
6143
6144             // Add before unload listener
6145             // This was required since IE was leaking memory if you added and removed beforeunload listeners
6146             // with attachEvent/detatchEvent so this only adds one listener and instances can the attach to the onBeforeUnload event
6147             t.onBeforeUnload = new tinymce.util.Dispatcher(t);
6148
6149             // Must be on window or IE will leak if the editor is placed in frame or iframe
6150             Event.add(window, 'beforeunload', function(e) {
6151                 t.onBeforeUnload.dispatch(t, e);
6152             });
6153         },
6154
6155         init : function(s) {
18240a 6156             var t = this, pl, sl = tinymce.ScriptLoader, c, e;
d9344f 6157
S 6158             function execCallback(se, n, s) {
6159                 var f = se[n];
6160
6161                 if (!f)
6162                     return;
6163
6164                 if (tinymce.is(f, 'string')) {
6165                     s = f.replace(/\.\w+$/, '');
6166                     s = s ? tinymce.resolve(s) : 0;
6167                     f = tinymce.resolve(f);
6168                 }
6169
6170                 return f.apply(s || this, Array.prototype.slice.call(arguments, 2));
6171             };
6172
6173             s = extend({
6174                 theme : "simple",
6175                 language : "en",
6176                 strict_loading_mode : document.contentType == 'application/xhtml+xml'
6177             }, s);
6178
6179             t.settings = s;
6180
6181             // If page not loaded and strict mode isn't enabled then load them
6182             if (!Event.domLoaded && !s.strict_loading_mode) {
6183                 // Load language
6184                 if (s.language)
6185                     sl.add(tinymce.baseURL + '/langs/' + s.language + '.js');
6186
6187                 // Load theme
6188                 if (s.theme && s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme])
6189                     ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js');
6190
6191                 // Load plugins
6192                 if (s.plugins) {
6193                     pl = explode(s.plugins);
6194
6195                     // Load compat2x first
6196                     if (tinymce.inArray(pl, 'compat2x') != -1)
6197                         PluginManager.load('compat2x', 'plugins/compat2x/editor_plugin' + tinymce.suffix + '.js');
6198
6199                     // Load rest if plugins
6200                     each(pl, function(v) {
6201                         if (v && v.charAt(0) != '-' && !PluginManager.urls[v]) {
6202                             // Skip safari plugin for other browsers
6203                             if (!tinymce.isWebKit && v == 'safari')
6204                                 return;
6205
6206                             PluginManager.load(v, 'plugins/' + v + '/editor_plugin' + tinymce.suffix + '.js');
6207                         }
6208                     });
6209                 }
6210
6211                 sl.loadQueue();
6212             }
6213
6214             // Legacy call
6215             Event.add(document, 'init', function() {
6216                 var l, co;
6217
6218                 execCallback(s, 'onpageload');
6219
6220                 // Verify that it's a valid browser
6221                 if (s.browsers) {
6222                     l = false;
6223
6224                     each(explode(s.browsers), function(v) {
6225                         switch (v) {
6226                             case 'ie':
6227                             case 'msie':
6228                                 if (tinymce.isIE)
6229                                     l = true;
6230                                 break;
6231
6232                             case 'gecko':
6233                                 if (tinymce.isGecko)
6234                                     l = true;
6235                                 break;
6236
6237                             case 'safari':
6238                             case 'webkit':
6239                                 if (tinymce.isWebKit)
6240                                     l = true;
6241                                 break;
6242
6243                             case 'opera':
6244                                 if (tinymce.isOpera)
6245                                     l = true;
6246
6247                                 break;
6248                         }
6249                     });
6250
6251                     // Not a valid one
6252                     if (!l)
6253                         return;
6254                 }
6255
6256                 switch (s.mode) {
6257                     case "exact":
6258                         l = s.elements || '';
6259
6260                         if(l.length > 0) {
6261                             each(explode(l), function(v) {
6262                                 if (DOM.get(v))
6263                                     new tinymce.Editor(v, s).render(1);
6264                                 else {
6265                                     c = 0;
6266
6267                                     each(document.forms, function(f) {
6268                                         each(f.elements, function(e) {
6269                                             if (e.name === v) {
6270                                                 v = 'mce_editor_' + c;
6271                                                 DOM.setAttrib(e, 'id', v);
6272                                                 new tinymce.Editor(v, s).render(1);
6273                                             }
6274                                         });
6275                                     });
6276                                 }
6277                             });
6278                         }
6279                         break;
6280
6281                     case "textareas":
6282                     case "specific_textareas":
6283                         function hasClass(n, c) {
18240a 6284                             return c.constructor === RegExp ? c.test(n.className) : DOM.hasClass(n, c);
d9344f 6285                         };
S 6286
6287                         each(DOM.select('textarea'), function(v) {
6288                             if (s.editor_deselector && hasClass(v, s.editor_deselector))
6289                                 return;
6290
6291                             if (!s.editor_selector || hasClass(v, s.editor_selector)) {
18240a 6292                                 // Can we use the name
A 6293                                 e = DOM.get(v.name);
6294                                 if (!v.id && !e)
6295                                     v.id = v.name;
d9344f 6296
S 6297                                 // Generate unique name if missing or already exists
6298                                 if (!v.id || t.get(v.id))
6299                                     v.id = DOM.uniqueId();
6300
6301                                 new tinymce.Editor(v.id, s).render(1);
6302                             }
6303                         });
6304                         break;
6305                 }
6306
6307                 // Call onInit when all editors are initialized
6308                 if (s.oninit) {
6309                     l = co = 0;
6310
6311                     each (t.editors, function(ed) {
6312                         co++;
6313
6314                         if (!ed.initialized) {
6315                             // Wait for it
6316                             ed.onInit.add(function() {
6317                                 l++;
6318
6319                                 // All done
6320                                 if (l == co)
6321                                     execCallback(s, 'oninit');
6322                             });
6323                         } else
6324                             l++;
6325
6326                         // All done
6327                         if (l == co)
6328                             execCallback(s, 'oninit');                    
6329                     });
6330                 }
6331             });
6332         },
6333
6334         get : function(id) {
6335             return this.editors[id];
6336         },
6337
6338         getInstanceById : function(id) {
6339             return this.get(id);
6340         },
6341
6342         add : function(e) {
6343             this.editors[e.id] = e;
6344             this._setActive(e);
6345
6346             return e;
6347         },
6348
6349         remove : function(e) {
6350             var t = this;
6351
6352             // Not in the collection
6353             if (!t.editors[e.id])
6354                 return null;
6355
6356             delete t.editors[e.id];
6357
6358             // Select another editor since the active one was removed
6359             if (t.activeEditor == e) {
6360                 each(t.editors, function(e) {
6361                     t._setActive(e);
6362                     return false; // Break
6363                 });
6364             }
6365
6366             e.destroy();
6367
6368             return e;
6369         },
6370
6371         execCommand : function(c, u, v) {
6372             var t = this, ed = t.get(v), w;
6373
6374             // Manager commands
6375             switch (c) {
6376                 case "mceFocus":
6377                     ed.focus();
6378                     return true;
6379
6380                 case "mceAddEditor":
6381                 case "mceAddControl":
18240a 6382                     if (!t.get(v))
A 6383                         new tinymce.Editor(v, t.settings).render();
6384
d9344f 6385                     return true;
S 6386
6387                 case "mceAddFrameControl":
6388                     w = v.window;
6389
6390                     // Add tinyMCE global instance and tinymce namespace to specified window
6391                     w.tinyMCE = tinyMCE;
6392                     w.tinymce = tinymce;
6393
6394                     tinymce.DOM.doc = w.document;
6395                     tinymce.DOM.win = w;
6396
6397                     ed = new tinymce.Editor(v.element_id, v);
6398                     ed.render();
6399
6400                     // Fix IE memory leaks
6401                     if (tinymce.isIE) {
6402                         function clr() {
6403                             ed.destroy();
6404                             w.detachEvent('onunload', clr);
6405                             w = w.tinyMCE = w.tinymce = null; // IE leak
6406                         };
6407
6408                         w.attachEvent('onunload', clr);
6409                     }
6410
6411                     v.page_window = null;
6412
6413                     return true;
6414
6415                 case "mceRemoveEditor":
6416                 case "mceRemoveControl":
6417                     ed.remove();
6418                     return true;
6419
6420                 case 'mceToggleEditor':
6421                     if (!ed) {
6422                         t.execCommand('mceAddControl', 0, v);
6423                         return true;
6424                     }
6425
6426                     if (ed.isHidden())
6427                         ed.show();
6428                     else
6429                         ed.hide();
6430
6431                     return true;
6432             }
6433
6434             // Run command on active editor
6435             if (t.activeEditor)
6436                 return t.activeEditor.execCommand(c, u, v);
6437
6438             return false;
6439         },
6440
6441         execInstanceCommand : function(id, c, u, v) {
6442             var ed = this.get(id);
6443
6444             if (ed)
6445                 return ed.execCommand(c, u, v);
6446
6447             return false;
6448         },
6449
6450         triggerSave : function() {
6451             each(this.editors, function(e) {
6452                 e.save();
6453             });
6454         },
6455
6456         addI18n : function(p, o) {
6457             var lo, i18n = this.i18n;
6458
6459             if (!tinymce.is(p, 'string')) {
6460                 each(p, function(o, lc) {
6461                     each(o, function(o, g) {
6462                         each(o, function(o, k) {
6463                             if (g === 'common')
6464                                 i18n[lc + '.' + k] = o;
6465                             else
6466                                 i18n[lc + '.' + g + '.' + k] = o;
6467                         });
6468                     });
6469                 });
6470             } else {
6471                 each(o, function(o, k) {
6472                     i18n[p + '.' + k] = o;
6473                 });
6474             }
6475         },
6476
6477         // Private methods
6478
6479         _setActive : function(e) {
6480             this.selectedInstance = this.activeEditor = e;
6481         }
6482
6483         });
6484
6485     tinymce.EditorManager.preInit();
6486 })();
6487
6488 // Short for editor manager window.tinyMCE is needed when TinyMCE gets loaded though a XHR call
6489 var tinyMCE = window.tinyMCE = tinymce.EditorManager;
6490
6491 /* file:jscripts/tiny_mce/classes/Editor.js */
6492
6493 (function() {
6494     var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, Dispatcher = tinymce.util.Dispatcher;
6495     var each = tinymce.each, isGecko = tinymce.isGecko, isIE = tinymce.isIE, isWebKit = tinymce.isWebKit;
6496     var is = tinymce.is, ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, EditorManager = tinymce.EditorManager;
6497     var inArray = tinymce.inArray, grep = tinymce.grep, explode = tinymce.explode;
6498
6499     tinymce.create('tinymce.Editor', {
6500         Editor : function(id, s) {
6501             var t = this;
6502
6503             t.id = t.editorId = id;
6504             t.execCommands = {};
6505             t.queryStateCommands = {};
6506             t.queryValueCommands = {};
6507             t.plugins = {};
6508
6509             // Add events to the editor
6510             each([
6511                 'onPreInit',
6512                 'onBeforeRenderUI',
6513                 'onPostRender',
6514                 'onInit',
6515                 'onRemove',
6516                 'onActivate',
6517                 'onDeactivate',
6518                 'onClick',
6519                 'onEvent',
6520                 'onMouseUp',
6521                 'onMouseDown',
6522                 'onDblClick',
6523                 'onKeyDown',
6524                 'onKeyUp',
6525                 'onKeyPress',
6526                 'onContextMenu',
6527                 'onSubmit',
6528                 'onReset',
6529                 'onPaste',
6530                 'onPreProcess',
6531                 'onPostProcess',
6532                 'onBeforeSetContent',
6533                 'onBeforeGetContent',
6534                 'onSetContent',
6535                 'onGetContent',
6536                 'onLoadContent',
6537                 'onSaveContent',
6538                 'onNodeChange',
6539                 'onChange',
6540                 'onBeforeExecCommand',
6541                 'onExecCommand',
6542                 'onUndo',
6543                 'onRedo',
6544                 'onVisualAid',
6545                 'onSetProgressState'
6546             ], function(e) {
6547                 t[e] = new Dispatcher(t);
6548             });
6549
6550             // Default editor config
6551             t.settings = s = extend({
6552                 id : id,
6553                 language : 'en',
6554                 docs_language : 'en',
6555                 theme : 'simple',
6556                 skin : 'default',
6557                 delta_width : 0,
6558                 delta_height : 0,
6559                 popup_css : '',
6560                 plugins : '',
6561                 document_base_url : tinymce.documentBaseURL,
6562                 add_form_submit_trigger : 1,
6563                 submit_patch : 1,
6564                 add_unload_trigger : 1,
6565                 convert_urls : 1,
6566                 relative_urls : 1,
6567                 remove_script_host : 1,
6568                 table_inline_editing : 0,
6569                 object_resizing : 1,
6570                 cleanup : 1,
6571                 accessibility_focus : 1,
6572                 custom_shortcuts : 1,
6573                 custom_undo_redo_keyboard_shortcuts : 1,
6574                 custom_undo_redo_restore_selection : 1,
6575                 custom_undo_redo : 1,
6576                 doctype : '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">',
6577                 visual_table_class : 'mceItemTable',
6578                 visual : 1,
6579                 inline_styles : true,
6580                 convert_fonts_to_spans : true,
6581                 font_size_style_values : 'xx-small,x-small,small,medium,large,x-large,xx-large',
6582                 apply_source_formatting : 1,
6583                 directionality : 'ltr',
6584                 forced_root_block : 'p',
18240a 6585                 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],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',
d9344f 6586                 hidden_input : 1,
S 6587                 padd_empty_editor : 1,
6588                 render_ui : 1,
6589                 init_theme : 1,
6590                 force_p_newlines : 1,
6591                 indentation : '30px'
6592             }, s);
6593
6594             // Setup URIs
6595             t.documentBaseURI = new tinymce.util.URI(s.document_base_url || tinymce.documentBaseURL, {
6596                 base_uri : tinyMCE.baseURI
6597             });
6598             t.baseURI = EditorManager.baseURI;
6599
6600             // Call setup
6601             t.execCallback('setup', t);
6602         },
6603
6604         render : function(nst) {
6605             var t = this, s = t.settings, id = t.id, sl = tinymce.ScriptLoader;
6606
6607             // Page is not loaded yet, wait for it
6608             if (!Event.domLoaded) {
6609                 Event.add(document, 'init', function() {
6610                     t.render();
6611                 });
6612                 return;
6613             }
6614
6615             // Force strict loading mode if render us called by user and not internally
6616             if (!nst) {
6617                 s.strict_loading_mode = 1;
6618                 tinyMCE.settings = s;
6619             }
6620
6621             // Element not found, then skip initialization
6622             if (!t.getElement())
6623                 return;
6624
6625             if (s.strict_loading_mode) {
6626                 sl.settings.strict_mode = s.strict_loading_mode;
6627                 tinymce.DOM.settings.strict = 1;
6628             }
6629
6630             // Add hidden input for non input elements inside form elements
6631             if (!/TEXTAREA|INPUT/i.test(t.getElement().nodeName) && s.hidden_input && DOM.getParent(id, 'form'))
6632                 DOM.insertAfter(DOM.create('input', {type : 'hidden', name : id}), id);
6633
6634             t.windowManager = new tinymce.WindowManager(t);
6635
6636             if (s.encoding == 'xml') {
6637                 t.onGetContent.add(function(ed, o) {
18240a 6638                     if (o.save)
d9344f 6639                         o.content = DOM.encode(o.content);
S 6640                 });
6641             }
6642
6643             if (s.add_form_submit_trigger) {
6644                 t.onSubmit.addToTop(function() {
6645                     if (t.initialized) {
6646                         t.save();
6647                         t.isNotDirty = 1;
6648                     }
6649                 });
6650             }
6651
18240a 6652             if (s.add_unload_trigger && !s.ask) {
d9344f 6653                 t._beforeUnload = tinyMCE.onBeforeUnload.add(function() {
18240a 6654                     if (t.initialized && !t.destroyed && !t.isHidden())
d9344f 6655                         t.save({format : 'raw', no_events : true});
S 6656                 });
6657             }
6658
6659             tinymce.addUnload(t.destroy, t);
6660
6661             if (s.submit_patch) {
6662                 t.onBeforeRenderUI.add(function() {
6663                     var n = t.getElement().form;
6664
6665                     if (!n)
6666                         return;
6667
6668                     // Already patched
6669                     if (n._mceOldSubmit)
6670                         return;
6671
6672                     // Check page uses id="submit" or name="submit" for it's submit button
6673                     if (!n.submit.nodeType && !n.submit.length) {
6674                         t.formElement = n;
6675                         n._mceOldSubmit = n.submit;
6676                         n.submit = function() {
6677                             // Save all instances
6678                             EditorManager.triggerSave();
6679                             t.isNotDirty = 1;
6680
6681                             return this._mceOldSubmit(this);
6682                         };
6683                     }
6684
6685                     n = null;
6686                 });
6687             }
6688
6689             // Load scripts
6690             function loadScripts() {
6691                 if (s.language)
6692                     sl.add(tinymce.baseURL + '/langs/' + s.language + '.js');
6693
6694                 if (s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme])
6695                     ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js');
6696
6697                 each(explode(s.plugins), function(p) {
6698                     if (p && p.charAt(0) != '-' && !PluginManager.urls[p]) {
6699                         // Skip safari plugin for other browsers
6700                         if (!isWebKit && p == 'safari')
6701                             return;
6702
6703                         PluginManager.load(p, 'plugins/' + p + '/editor_plugin' + tinymce.suffix + '.js');
6704                     }
6705                 });
6706
6707                 // Init when que is loaded
6708                 sl.loadQueue(function() {
6709                     if (s.ask) {
6710                         function ask() {
18240a 6711                             // Yield for awhile to avoid focus bug on FF 3 when cancel is pressed
A 6712                             window.setTimeout(function() {
6713                                 Event.remove(t.id, 'focus', ask);
6714
6715                                 t.windowManager.confirm(t.getLang('edit_confirm'), function(s) {
6716                                     if (s)
6717                                         t.init();
6718                                 });
6719                             }, 0);
d9344f 6720                         };
S 6721
6722                         Event.add(t.id, 'focus', ask);
6723                         return;
6724                     }
6725
6726                     if (!t.removed)
6727                         t.init();
6728                 });
6729             };
6730
6731             // Load compat2x first
6732             if (s.plugins.indexOf('compat2x') != -1) {
6733                 PluginManager.load('compat2x', 'plugins/compat2x/editor_plugin' + tinymce.suffix + '.js');
6734                 sl.loadQueue(loadScripts);
6735             } else
6736                 loadScripts();
6737         },
6738
6739         init : function() {
6740             var n, t = this, s = t.settings, w, h, e = t.getElement(), o, ti, u, bi, bc, re;
6741
6742             EditorManager.add(t);
6743
6744             // Create theme
6745             s.theme = s.theme.replace(/-/, '');
6746             o = ThemeManager.get(s.theme);
6747             t.theme = new o();
6748
6749             if (t.theme.init && s.init_theme)
6750                 t.theme.init(t, ThemeManager.urls[s.theme] || tinymce.documentBaseURL.replace(/\/$/, ''));
6751
6752             // Create all plugins
6753             each(explode(s.plugins.replace(/\-/g, '')), function(p) {
6754                 var c = PluginManager.get(p), u = PluginManager.urls[p] || tinymce.documentBaseURL.replace(/\/$/, ''), po;
6755
6756                 if (c) {
6757                     po = new c(t, u);
6758
6759                     t.plugins[p] = po;
6760
6761                     if (po.init)
6762                         po.init(t, u);
6763                 }
6764             });
6765
6766             // Setup popup CSS path(s)
6767             if (s.popup_css)
6768                 s.popup_css = t.documentBaseURI.toAbsolute(s.popup_css);
6769             else
6770                 s.popup_css = t.baseURI.toAbsolute("themes/" + s.theme + "/skins/" + s.skin + "/dialog.css");
6771
6772             if (s.popup_css_add)
6773                 s.popup_css += ',' + t.documentBaseURI.toAbsolute(s.popup_css_add);
6774
6775             // Setup control factory
6776             t.controlManager = new tinymce.ControlManager(t);
6777             t.undoManager = new tinymce.UndoManager(t);
6778
6779             // Pass through
6780             t.undoManager.onAdd.add(function(um, l) {
18240a 6781                 if (!l.initial)
A 6782                     return t.onChange.dispatch(t, l, um);
d9344f 6783             });
S 6784
6785             t.undoManager.onUndo.add(function(um, l) {
6786                 return t.onUndo.dispatch(t, l, um);
6787             });
6788
6789             t.undoManager.onRedo.add(function(um, l) {
6790                 return t.onRedo.dispatch(t, l, um);
6791             });
6792
6793             if (s.custom_undo_redo) {
6794                 t.onExecCommand.add(function(ed, cmd, ui, val, a) {
6795                     if (cmd != 'Undo' && cmd != 'Redo' && cmd != 'mceRepaint' && (!a || !a.skip_undo))
6796                         t.undoManager.add();
6797                 });
6798             }
6799
6800             t.onExecCommand.add(function(ed, c) {
6801                 // Don't refresh the select lists until caret move
6802                 if (!/^(FontName|FontSize)$/.test(c))
6803                     t.nodeChanged();
6804             });
6805
6806             // Remove ghost selections on images and tables in Gecko
6807             if (isGecko) {
6808                 function repaint(a, o) {
6809                     if (!o || !o.initial)
6810                         t.execCommand('mceRepaint');
6811                 };
6812
6813                 t.onUndo.add(repaint);
6814                 t.onRedo.add(repaint);
6815                 t.onSetContent.add(repaint);
6816             }
6817
6818             // Enables users to override the control factory
6819             t.onBeforeRenderUI.dispatch(t, t.controlManager);
6820
6821             // Measure box
6822             if (s.render_ui) {
18240a 6823                 w = s.width || e.style.width || e.offsetWidth;
A 6824                 h = s.height || e.style.height || e.offsetHeight;
d9344f 6825                 t.orgDisplay = e.style.display;
S 6826                 re = /^[0-9\.]+(|px)$/i;
6827
6828                 if (re.test('' + w))
6829                     w = Math.max(parseInt(w) + (o.deltaWidth || 0), 100);
6830
6831                 if (re.test('' + h))
6832                     h = Math.max(parseInt(h) + (o.deltaHeight || 0), 100);
6833
6834                 // Render UI
6835                 o = t.theme.renderUI({
6836                     targetNode : e,
6837                     width : w,
6838                     height : h,
6839                     deltaWidth : s.delta_width,
6840                     deltaHeight : s.delta_height
6841                 });
6842
6843                 t.editorContainer = o.editorContainer;
6844             }
6845
6846             
6847             // Resize editor
6848             DOM.setStyles(o.sizeContainer || o.editorContainer, {
6849                 width : w,
6850                 height : h
6851             });
6852
6853             h = (o.iframeHeight || h) + ((h + '').indexOf('%') == -1 ? (o.deltaHeight || 0) : '');
6854             if (h < 100)
6855                 h = 100;
6856
18240a 6857             t.iframeHTML = s.doctype + '<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="' + t.documentBaseURI.getURI() + '" />';
d9344f 6858             t.iframeHTML += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
S 6859
6860             if (tinymce.relaxedDomain)
6861                 t.iframeHTML += '<script type="text/javascript">document.domain = "' + tinymce.relaxedDomain + '";</script>';
6862
6863             bi = s.body_id || 'tinymce';
6864             if (bi.indexOf('=') != -1) {
6865                 bi = t.getParam('body_id', '', 'hash');
6866                 bi = bi[t.id] || bi;
6867             }
6868
6869             bc = s.body_class || '';
6870             if (bc.indexOf('=') != -1) {
6871                 bc = t.getParam('body_class', '', 'hash');
6872                 bc = bc[t.id] || '';
6873             }
6874
6875             t.iframeHTML += '</head><body id="' + bi + '" class="mceContentBody ' + bc + '"></body></html>';
6876
6877             // Domain relaxing enabled, then set document domain
6878             if (tinymce.relaxedDomain) {
6879                 // We need to write the contents here in IE since multiple writes messes up refresh button and back button
6880                 if (isIE)
6881                     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();})()';
6882                 else if (tinymce.isOpera)
6883                     u = 'javascript:(function(){document.open();document.domain="' + document.domain + '";document.close();ed.setupIframe();})()';                    
6884             }
6885
6886             // Create iframe
6887             n = DOM.add(o.iframeContainer, 'iframe', {
6888                 id : t.id + "_ifr",
6889                 src : u || 'javascript:""', // Workaround for HTTPS warning in IE6/7
6890                 frameBorder : '0',
6891                 style : {
6892                     width : '100%',
6893                     height : h
6894                 }
6895             });
6896
6897             t.contentAreaContainer = o.iframeContainer;
6898             DOM.get(o.editorContainer).style.display = t.orgDisplay;
6899             DOM.get(t.id).style.display = 'none';
6900
6901             // Safari 2.x requires us to wait for the load event and load a real HTML doc
6902             if (tinymce.isOldWebKit) {
6903                 Event.add(n, 'load', t.setupIframe, t);
6904                 n.src = tinymce.baseURL + '/plugins/safari/blank.htm';
6905             } else {
6906                 if (!isIE || !tinymce.relaxedDomain)
6907                     t.setupIframe();
6908
6909                 e = n = o = null; // Cleanup
6910             }
6911         },
6912
6913         setupIframe : function() {
6914             var t = this, s = t.settings, e = DOM.get(t.id), d = t.getDoc(), h, b;
6915
6916             // Setup iframe body
6917             if (!isIE || !tinymce.relaxedDomain) {
6918                 d.open();
6919                 d.write(t.iframeHTML);
6920                 d.close();
6921             }
6922
6923             // Design mode needs to be added here Ctrl+A will fail otherwise
6924             if (!isIE) {
6925                 try {
6926                     d.designMode = 'On';
6927                 } catch (ex) {
6928                     // Will fail on Gecko if the editor is placed in an hidden container element
6929                     // The design mode will be set ones the editor is focused
6930                 }
6931             }
6932
6933             // IE needs to use contentEditable or it will display non secure items for HTTPS
6934             if (isIE) {
6935                 // It will not steal focus if we hide it while setting contentEditable
6936                 b = t.getBody();
6937                 DOM.hide(b);
6938                 b.contentEditable = true;
6939                 DOM.show(b);
6940             }
6941
6942             // Setup objects
6943             t.dom = new tinymce.DOM.DOMUtils(t.getDoc(), {
6944                 keep_values : true,
6945                 url_converter : t.convertURL,
6946                 url_converter_scope : t,
6947                 hex_colors : s.force_hex_style_colors,
6948                 class_filter : s.class_filter,
6949                 update_styles : 1,
6950                 fix_ie_paragraphs : 1
6951             });
6952
6953             t.serializer = new tinymce.dom.Serializer({
6954                 entity_encoding : s.entity_encoding,
6955                 entities : s.entities,
6956                 valid_elements : s.verify_html === false ? '*[*]' : s.valid_elements,
6957                 extended_valid_elements : s.extended_valid_elements,
6958                 valid_child_elements : s.valid_child_elements,
6959                 invalid_elements : s.invalid_elements,
6960                 fix_table_elements : s.fix_table_elements,
6961                 fix_list_elements : s.fix_list_elements,
6962                 fix_content_duplication : s.fix_content_duplication,
6963                 convert_fonts_to_spans : s.convert_fonts_to_spans,
6964                 font_size_classes  : s.font_size_classes,
6965                 font_size_style_values : s.font_size_style_values,
6966                 apply_source_formatting : s.apply_source_formatting,
6967                 remove_linebreaks : s.remove_linebreaks,
6968                 dom : t.dom
6969             });
6970
6971             t.selection = new tinymce.dom.Selection(t.dom, t.getWin(), t.serializer);
6972             t.forceBlocks = new tinymce.ForceBlocks(t, {
6973                 forced_root_block : s.forced_root_block
6974             });
6975             t.editorCommands = new tinymce.EditorCommands(t);
6976
6977             // Pass through
6978             t.serializer.onPreProcess.add(function(se, o) {
6979                 return t.onPreProcess.dispatch(t, o, se);
6980             });
6981
6982             t.serializer.onPostProcess.add(function(se, o) {
6983                 return t.onPostProcess.dispatch(t, o, se);
6984             });
6985
6986             t.onPreInit.dispatch(t);
6987
6988             if (!s.gecko_spellcheck)
6989                 t.getBody().spellcheck = 0;
6990
6991             t._addEvents();
6992
6993             t.controlManager.onPostRender.dispatch(t, t.controlManager);
6994             t.onPostRender.dispatch(t);
6995
6996             if (s.directionality)
6997                 t.getBody().dir = s.directionality;
6998
6999             if (s.nowrap)
7000                 t.getBody().style.whiteSpace = "nowrap";
7001
7002             if (s.auto_resize)
7003                 t.onNodeChange.add(t.resizeToContent, t);
7004
7005             if (s.custom_elements) {
7006                 function handleCustom(ed, o) {
7007                     each(explode(s.custom_elements), function(v) {
7008                         var n;
7009
7010                         if (v.indexOf('~') === 0) {
7011                             v = v.substring(1);
7012                             n = 'span';
7013                         } else
7014                             n = 'div';
7015
7016                         o.content = o.content.replace(new RegExp('<(' + v + ')([^>]*)>', 'g'), '<' + n + ' mce_name="$1"$2>');
7017                         o.content = o.content.replace(new RegExp('</(' + v + ')>', 'g'), '</' + n + '>');
7018                     });
7019                 };
7020
7021                 t.onBeforeSetContent.add(handleCustom);
7022                 t.onPostProcess.add(function(ed, o) {
7023                     if (o.set)
7024                         handleCustom(ed, o)
7025                 });
7026             }
7027
7028             if (s.handle_node_change_callback) {
7029                 t.onNodeChange.add(function(ed, cm, n) {
7030                     t.execCallback('handle_node_change_callback', t.id, n, -1, -1, true, t.selection.isCollapsed());
7031                 });
7032             }
7033
7034             if (s.save_callback) {
7035                 t.onSaveContent.add(function(ed, o) {
7036                     var h = t.execCallback('save_callback', t.id, o.content, t.getBody());
7037
7038                     if (h)
7039                         o.content = h;
7040                 });
7041             }
7042
7043             if (s.onchange_callback) {
7044                 t.onChange.add(function(ed, l) {
7045                     t.execCallback('onchange_callback', t, l);
7046                 });
7047             }
7048
7049             if (s.convert_newlines_to_brs) {
7050                 t.onBeforeSetContent.add(function(ed, o) {
7051                     if (o.initial)
7052                         o.content = o.content.replace(/\r?\n/g, '<br />');
7053                 });
7054             }
7055
7056             if (s.fix_nesting && isIE) {
7057                 t.onBeforeSetContent.add(function(ed, o) {
7058                     o.content = t._fixNesting(o.content);
7059                 });
7060             }
7061
7062             if (s.preformatted) {
7063                 t.onPostProcess.add(function(ed, o) {
7064                     o.content = o.content.replace(/^\s*<pre.*?>/, '');
7065                     o.content = o.content.replace(/<\/pre>\s*$/, '');
7066
7067                     if (o.set)
7068                         o.content = '<pre class="mceItemHidden">' + o.content + '</pre>';
7069                 });
7070             }
7071
7072             if (s.verify_css_classes) {
7073                 t.serializer.attribValueFilter = function(n, v) {
7074                     var s, cl;
7075
7076                     if (n == 'class') {
7077                         // Build regexp for classes
7078                         if (!t.classesRE) {
7079                             cl = t.dom.getClasses();
7080
7081                             if (cl.length > 0) {
7082                                 s = '';
7083
7084                                 each (cl, function(o) {
7085                                     s += (s ? '|' : '') + o['class'];
7086                                 });
7087
7088                                 t.classesRE = new RegExp('(' + s + ')', 'gi');
7089                             }
7090                         }
7091
7092                         return !t.classesRE || /(\bmceItem\w+\b|\bmceTemp\w+\b)/g.test(v) || t.classesRE.test(v) ? v : '';
7093                     }
7094
7095                     return v;
7096                 };
7097             }
7098
7099             if (s.convert_fonts_to_spans)
7100                 t._convertFonts();
7101
7102             if (s.inline_styles)
7103                 t._convertInlineElements();
7104
7105             if (s.cleanup_callback) {
7106                 t.onBeforeSetContent.add(function(ed, o) {
7107                     o.content = t.execCallback('cleanup_callback', 'insert_to_editor', o.content, o);
7108                 });
7109
7110                 t.onPreProcess.add(function(ed, o) {
7111                     if (o.set)
7112                         t.execCallback('cleanup_callback', 'insert_to_editor_dom', o.node, o);
7113
7114                     if (o.get)
7115                         t.execCallback('cleanup_callback', 'get_from_editor_dom', o.node, o);
7116                 });
7117
7118                 t.onPostProcess.add(function(ed, o) {
7119                     if (o.set)
7120                         o.content = t.execCallback('cleanup_callback', 'insert_to_editor', o.content, o);
7121
7122                     if (o.get)                        
7123                         o.content = t.execCallback('cleanup_callback', 'get_from_editor', o.content, o);
7124                 });
7125             }
7126
7127             if (s.save_callback) {
7128                 t.onGetContent.add(function(ed, o) {
7129                     if (o.save)
7130                         o.content = t.execCallback('save_callback', t.id, o.content, t.getBody());
7131                 });
7132             }
7133
7134             if (s.handle_event_callback) {
7135                 t.onEvent.add(function(ed, e, o) {
7136                     if (t.execCallback('handle_event_callback', e, ed, o) === false)
7137                         Event.cancel(e);
7138                 });
7139             }
7140
7141             t.onSetContent.add(function() {
7142                 // Safari needs some time, it will crash the browser when a link is created otherwise
7143                 // I think this crash issue is resolved in the latest 3.0.4
7144                 //window.setTimeout(function() {
7145                     t.addVisual(t.getBody());
7146                 //}, 1);
7147             });
7148
7149             // Remove empty contents
7150             if (s.padd_empty_editor) {
7151                 t.onPostProcess.add(function(ed, o) {
18240a 7152                     o.content = o.content.replace(/^(<p>(&nbsp;|&#160;|\s|\u00a0|)<\/p>[\r\n]*|<br \/>[\r\n]*)$/, '');
d9344f 7153                 });
S 7154             }
7155
7156             if (isGecko) {
7157                 try {
7158                     // Design mode must be set here once again to fix a bug where
7159                     // Ctrl+A/Delete/Backspace didn't work if the editor was added using mceAddControl then removed then added again
7160                     d.designMode = 'Off';
7161                     d.designMode = 'On';
7162                 } catch (ex) {
7163                     // Will fail on Gecko if the editor is placed in an hidden container element
7164                     // The design mode will be set ones the editor is focused
7165                 }
7166             }
7167
7168             // A small timeout was needed since firefox will remove. Bug: #1838304
7169             setTimeout(function () {
7170                 if (t.removed)
7171                     return;
7172
7173                 t.load({initial : true, format : (s.cleanup_on_startup ? 'html' : 'raw')});
7174                 t.startContent = t.getContent({format : 'raw'});
7175                 t.undoManager.add({initial : true});
7176                 t.initialized = true;
7177
7178                 t.onInit.dispatch(t);
7179                 t.execCallback('setupcontent_callback', t.id, t.getBody(), t.getDoc());
7180                 t.execCallback('init_instance_callback', t);
7181                 t.focus(true);
7182                 t.nodeChanged({initial : 1});
7183
7184                 // Load specified content CSS last
7185                 if (s.content_css) {
7186                     tinymce.each(explode(s.content_css), function(u) {
7187                         t.dom.loadCSS(t.documentBaseURI.toAbsolute(u));
7188                     });
7189                 }
7190
7191                 // Handle auto focus
7192                 if (s.auto_focus) {
7193                     setTimeout(function () {
7194                         var ed = EditorManager.get(s.auto_focus);
7195
7196                         ed.selection.select(ed.getBody(), 1);
7197                         ed.selection.collapse(1);
7198                         ed.getWin().focus();
7199                     }, 100);
7200                 }
7201             }, 1);
7202     
7203             e = null;
7204         },
7205
7206         
7207         focus : function(sf) {
18240a 7208             var oed, t = this, ce = t.settings.content_editable;
d9344f 7209
S 7210             if (!sf) {
18240a 7211                 // Is not content editable or the selection is outside the area in IE
A 7212                 // the IE statement is needed to avoid bluring if element selections inside layers since
7213                 // the layer is like it's own document in IE
7214                 if (!ce && (!isIE || t.selection.getNode().ownerDocument != t.getDoc()))
7215                     t.getWin().focus();
d9344f 7216
S 7217                             }
7218
7219             if (EditorManager.activeEditor != t) {
7220                 if ((oed = EditorManager.activeEditor) != null)
7221                     oed.onDeactivate.dispatch(oed, t);
7222
7223                 t.onActivate.dispatch(t, oed);
7224             }
7225
7226             EditorManager._setActive(t);
7227         },
7228
7229         execCallback : function(n) {
7230             var t = this, f = t.settings[n], s;
7231
7232             if (!f)
7233                 return;
7234
7235             // Look through lookup
7236             if (t.callbackLookup && (s = t.callbackLookup[n])) {
7237                 f = s.func;
7238                 s = s.scope;
7239             }
7240
7241             if (is(f, 'string')) {
7242                 s = f.replace(/\.\w+$/, '');
7243                 s = s ? tinymce.resolve(s) : 0;
7244                 f = tinymce.resolve(f);
7245                 t.callbackLookup = t.callbackLookup || {};
7246                 t.callbackLookup[n] = {func : f, scope : s};
7247             }
7248
7249             return f.apply(s || t, Array.prototype.slice.call(arguments, 1));
7250         },
7251
7252         translate : function(s) {
7253             var c = this.settings.language, i18n = EditorManager.i18n;
7254
7255             if (!s)
7256                 return '';
7257
7258             return i18n[c + '.' + s] || s.replace(/{\#([^}]+)\}/g, function(a, b) {
7259                 return i18n[c + '.' + b] || '{#' + b + '}';
7260             });
7261         },
7262
7263         getLang : function(n, dv) {
7264             return EditorManager.i18n[this.settings.language + '.' + n] || (is(dv) ? dv : '{#' + n + '}');
7265         },
7266
7267         getParam : function(n, dv, ty) {
7268             var tr = tinymce.trim, v = is(this.settings[n]) ? this.settings[n] : dv, o;
7269
7270             if (ty === 'hash') {
7271                 o = {};
7272
7273                 if (is(v, 'string')) {
7274                     each(v.indexOf('=') > 0 ? v.split(/[;,](?![^=;,]*(?:[;,]|$))/) : v.split(','), function(v) {
7275                         v = v.split('=');
7276
7277                         if (v.length > 1)
7278                             o[tr(v[0])] = tr(v[1]);
7279                         else
7280                             o[tr(v[0])] = tr(v);
7281                     });
7282                 } else
7283                     o = v;
7284
7285                 return o;
7286             }
7287
7288             return v;
7289         },
7290
7291         nodeChanged : function(o) {
7292             var t = this, s = t.selection, n = s.getNode() || t.getBody();
7293
7294             // Fix for bug #1896577 it seems that this can not be fired while the editor is loading
7295             if (t.initialized) {
7296                 t.onNodeChange.dispatch(
7297                     t,
7298                     o ? o.controlManager || t.controlManager : t.controlManager,
7299                     isIE && n.ownerDocument != t.getDoc() ? t.getBody() : n, // Fix for IE initial state
7300                     s.isCollapsed(),
7301                     o
7302                 );
7303             }
7304         },
7305
7306         addButton : function(n, s) {
7307             var t = this;
7308
7309             t.buttons = t.buttons || {};
7310             t.buttons[n] = s;
7311         },
7312
7313         addCommand : function(n, f, s) {
7314             this.execCommands[n] = {func : f, scope : s || this};
7315         },
7316
7317         addQueryStateHandler : function(n, f, s) {
7318             this.queryStateCommands[n] = {func : f, scope : s || this};
7319         },
7320
7321         addQueryValueHandler : function(n, f, s) {
7322             this.queryValueCommands[n] = {func : f, scope : s || this};
7323         },
7324
7325         addShortcut : function(pa, desc, cmd_func, sc) {
7326             var t = this, c;
7327
7328             if (!t.settings.custom_shortcuts)
7329                 return false;
7330
7331             t.shortcuts = t.shortcuts || {};
7332
7333             if (is(cmd_func, 'string')) {
7334                 c = cmd_func;
7335
7336                 cmd_func = function() {
7337                     t.execCommand(c, false, null);
7338                 };
7339             }
7340
7341             if (is(cmd_func, 'object')) {
7342                 c = cmd_func;
7343
7344                 cmd_func = function() {
7345                     t.execCommand(c[0], c[1], c[2]);
7346                 };
7347             }
7348
7349             each(explode(pa), function(pa) {
7350                 var o = {
7351                     func : cmd_func,
7352                     scope : sc || this,
7353                     desc : desc,
7354                     alt : false,
7355                     ctrl : false,
7356                     shift : false
7357                 };
7358
7359                 each(explode(pa, '+'), function(v) {
7360                     switch (v) {
7361                         case 'alt':
7362                         case 'ctrl':
7363                         case 'shift':
7364                             o[v] = true;
7365                             break;
7366
7367                         default:
7368                             o.charCode = v.charCodeAt(0);
7369                             o.keyCode = v.toUpperCase().charCodeAt(0);
7370                     }
7371                 });
7372
7373                 t.shortcuts[(o.ctrl ? 'ctrl' : '') + ',' + (o.alt ? 'alt' : '') + ',' + (o.shift ? 'shift' : '') + ',' + o.keyCode] = o;
7374             });
7375
7376             return true;
7377         },
7378
7379         execCommand : function(cmd, ui, val, a) {
18240a 7380             var t = this, s = 0, o, st;
d9344f 7381
S 7382             if (!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(cmd) && (!a || !a.skip_focus))
7383                 t.focus();
7384
7385             o = {};
7386             t.onBeforeExecCommand.dispatch(t, cmd, ui, val, o);
7387             if (o.terminate)
7388                 return false;
7389
18240a 7390             // Command callback
d9344f 7391             if (t.execCallback('execcommand_callback', t.id, t.selection.getNode(), cmd, ui, val)) {
S 7392                 t.onExecCommand.dispatch(t, cmd, ui, val, a);
7393                 return true;
7394             }
7395
7396             // Registred commands
7397             if (o = t.execCommands[cmd]) {
18240a 7398                 st = o.func.call(o.scope, ui, val);
A 7399
7400                 // Fall through on true
7401                 if (st !== true) {
7402                     t.onExecCommand.dispatch(t, cmd, ui, val, a);
7403                     return st;
7404                 }
d9344f 7405             }
S 7406
7407             // Plugin commands
7408             each(t.plugins, function(p) {
7409                 if (p.execCommand && p.execCommand(cmd, ui, val)) {
7410                     t.onExecCommand.dispatch(t, cmd, ui, val, a);
7411                     s = 1;
7412                     return false;
7413                 }
7414             });
7415
7416             if (s)
7417                 return true;
7418
7419             // Theme commands
7420             if (t.theme.execCommand && t.theme.execCommand(cmd, ui, val)) {
7421                 t.onExecCommand.dispatch(t, cmd, ui, val, a);
7422                 return true;
7423             }
7424
7425             // Editor commands
7426             if (t.editorCommands.execCommand(cmd, ui, val)) {
7427                 t.onExecCommand.dispatch(t, cmd, ui, val, a);
7428                 return true;
7429             }
7430
7431             // Browser commands
7432             t.getDoc().execCommand(cmd, ui, val);
7433             t.onExecCommand.dispatch(t, cmd, ui, val, a);
7434         },
7435
7436         queryCommandState : function(c) {
18240a 7437             var t = this, o, s;
d9344f 7438
S 7439             // Is hidden then return undefined
7440             if (t._isHidden())
7441                 return;
7442
7443             // Registred commands
18240a 7444             if (o = t.queryStateCommands[c]) {
A 7445                 s = o.func.call(o.scope);
7446
7447                 // Fall though on true
7448                 if (s !== true)
7449                     return s;
7450             }
d9344f 7451
S 7452             // Registred commands
7453             o = t.editorCommands.queryCommandState(c);
7454             if (o !== -1)
7455                 return o;
7456
7457             // Browser commands
7458             try {
7459                 return this.getDoc().queryCommandState(c);
7460             } catch (ex) {
7461                 // Fails sometimes see bug: 1896577
7462             }
7463         },
7464
7465         queryCommandValue : function(c) {
18240a 7466             var t = this, o, s;
d9344f 7467
S 7468             // Is hidden then return undefined
7469             if (t._isHidden())
7470                 return;
7471
7472             // Registred commands
18240a 7473             if (o = t.queryValueCommands[c]) {
A 7474                 s = o.func.call(o.scope);
7475
7476                 // Fall though on true
7477                 if (s !== true)
7478                     return s;
7479             }
d9344f 7480
S 7481             // Registred commands
7482             o = t.editorCommands.queryCommandValue(c);
7483             if (is(o))
7484                 return o;
7485
7486             // Browser commands
7487             try {
7488                 return this.getDoc().queryCommandValue(c);
7489             } catch (ex) {
7490                 // Fails sometimes see bug: 1896577
7491             }
7492         },
7493
7494         show : function() {
7495             var t = this;
7496
7497             DOM.show(t.getContainer());
7498             DOM.hide(t.id);
7499             t.load();
7500         },
7501
7502         hide : function() {
7503             var t = this, d = t.getDoc();
7504
7505             // Fixed bug where IE has a blinking cursor left from the editor
7506             if (isIE && d)
7507                 d.execCommand('SelectAll');
7508
7509             // We must save before we hide so Safari doesn't crash
7510             t.save();
7511             DOM.hide(t.getContainer());
7512             DOM.setStyle(t.id, 'display', t.orgDisplay);
7513         },
7514
7515         isHidden : function() {
7516             return !DOM.isHidden(this.id);
7517         },
7518
7519         setProgressState : function(b, ti, o) {
7520             this.onSetProgressState.dispatch(this, b, ti, o);
7521
7522             return b;
7523         },
7524
7525         resizeToContent : function() {
7526             var t = this;
7527
7528             DOM.setStyle(t.id + "_ifr", 'height', t.getBody().scrollHeight);
7529         },
7530
7531         load : function(o) {
7532             var t = this, e = t.getElement(), h;
7533
7534             o = o || {};
7535             o.load = true;
7536
7537             h = t.setContent(is(e.value) ? e.value : e.innerHTML, o);
7538             o.element = e;
7539
7540             if (!o.no_events)
7541                 t.onLoadContent.dispatch(t, o);
7542
7543             o.element = e = null;
7544
7545             return h;
7546         },
7547
7548         save : function(o) {
7549             var t = this, e = t.getElement(), h, f;
7550
7551             if (!t.initialized)
7552                 return;
7553
7554             o = o || {};
7555             o.save = true;
7556
18240a 7557             // Add undo level will trigger onchange event
A 7558             if (!o.no_events) {
7559                 t.undoManager.typing = 0;
7560                 t.undoManager.add();
7561             }
7562
d9344f 7563             o.element = e;
S 7564             h = o.content = t.getContent(o);
7565
7566             if (!o.no_events)
7567                 t.onSaveContent.dispatch(t, o);
7568
7569             h = o.content;
7570
7571             if (!/TEXTAREA|INPUT/i.test(e.nodeName)) {
7572                 e.innerHTML = h;
7573
7574                 // Update hidden form element
7575                 if (f = DOM.getParent(t.id, 'form')) {
7576                     each(f.elements, function(e) {
7577                         if (e.name == t.id) {
7578                             e.value = h;
7579                             return false;
7580                         }
7581                     });
7582                 }
7583             } else
7584                 e.value = h;
7585
7586             o.element = e = null;
7587
7588             return h;
7589         },
7590
7591         setContent : function(h, o) {
7592             var t = this;
7593
7594             o = o || {};
7595             o.format = o.format || 'html';
7596             o.set = true;
7597             o.content = h;
7598
7599             if (!o.no_events)
7600                 t.onBeforeSetContent.dispatch(t, o);
7601
7602             // Padd empty content in Gecko and Safari. Commands will otherwise fail on the content
7603             // It will also be impossible to place the caret in the editor unless there is a BR element present
7604             if (!tinymce.isIE && (h.length === 0 || /^\s+$/.test(h))) {
18240a 7605                 o.content = t.dom.setHTML(t.getBody(), '<br mce_bogus="1" />');
d9344f 7606                 o.format = 'raw';
S 7607             }
7608
7609             o.content = t.dom.setHTML(t.getBody(), tinymce.trim(o.content));
7610
7611             if (o.format != 'raw' && t.settings.cleanup) {
7612                 o.getInner = true;
7613                 o.content = t.dom.setHTML(t.getBody(), t.serializer.serialize(t.getBody(), o));
7614             }
7615
7616             if (!o.no_events)
7617                 t.onSetContent.dispatch(t, o);
7618
7619             return o.content;
7620         },
7621
7622         getContent : function(o) {
7623             var t = this, h;
7624
7625             o = o || {};
7626             o.format = o.format || 'html';
7627             o.get = true;
7628
7629             if (!o.no_events)
7630                 t.onBeforeGetContent.dispatch(t, o);
7631
7632             if (o.format != 'raw' && t.settings.cleanup) {
7633                 o.getInner = true;
7634                 h = t.serializer.serialize(t.getBody(), o);
7635             } else
7636                 h = t.getBody().innerHTML;
7637
7638             h = h.replace(/^\s*|\s*$/g, '');
18240a 7639             o.content = h;
A 7640
7641             if (!o.no_events)
7642                 t.onGetContent.dispatch(t, o);
d9344f 7643
S 7644             return o.content;
7645         },
7646
7647         isDirty : function() {
7648             var t = this;
7649
7650             return tinymce.trim(t.startContent) != tinymce.trim(t.getContent({format : 'raw', no_events : 1})) && !t.isNotDirty;
7651         },
7652
7653         getContainer : function() {
7654             var t = this;
7655
7656             if (!t.container)
7657                 t.container = DOM.get(t.editorContainer || t.id + '_parent');
7658
7659             return t.container;
7660         },
7661
7662         getContentAreaContainer : function() {
7663             return this.contentAreaContainer;
7664         },
7665
7666         getElement : function() {
7667             return DOM.get(this.settings.content_element || this.id);
7668         },
7669
7670         getWin : function() {
7671             var t = this, e;
7672
7673             if (!t.contentWindow) {
7674                 e = DOM.get(t.id + "_ifr");
7675
7676                 if (e)
7677                     t.contentWindow = e.contentWindow;
7678             }
7679
7680             return t.contentWindow;
7681         },
7682
7683         getDoc : function() {
7684             var t = this, w;
7685
7686             if (!t.contentDocument) {
7687                 w = t.getWin();
7688
7689                 if (w)
7690                     t.contentDocument = w.document;
7691             }
7692
7693             return t.contentDocument;
7694         },
7695
7696         getBody : function() {
7697             return this.bodyElement || this.getDoc().body;
7698         },
7699
7700         convertURL : function(u, n, e) {
7701             var t = this, s = t.settings;
7702
7703             // Use callback instead
7704             if (s.urlconverter_callback)
7705                 return t.execCallback('urlconverter_callback', u, e, true, n);
7706
7707             // Don't convert link href since thats the CSS files that gets loaded into the editor also skip local file URLs
7708             if (!s.convert_urls || (e && e.nodeName == 'LINK') || u.indexOf('file:') === 0)
7709                 return u;
7710
7711             // Convert to relative
7712             if (s.relative_urls)
7713                 return t.documentBaseURI.toRelative(u);
7714
7715             // Convert to absolute
7716             u = t.documentBaseURI.toAbsolute(u, s.remove_script_host);
7717
7718             return u;
7719         },
7720
7721         addVisual : function(e) {
7722             var t = this, s = t.settings;
7723
7724             e = e || t.getBody();
7725
7726             if (!is(t.hasVisual))
7727                 t.hasVisual = s.visual;
7728
7729             each(t.dom.select('table,a', e), function(e) {
7730                 var v;
7731
7732                 switch (e.nodeName) {
7733                     case 'TABLE':
7734                         v = t.dom.getAttrib(e, 'border');
7735
7736                         if (!v || v == '0') {
7737                             if (t.hasVisual)
7738                                 t.dom.addClass(e, s.visual_table_class);
7739                             else
7740                                 t.dom.removeClass(e, s.visual_table_class);
7741                         }
7742
7743                         return;
7744
7745                     case 'A':
7746                         v = t.dom.getAttrib(e, 'name');
7747
7748                         if (v) {
7749                             if (t.hasVisual)
7750                                 t.dom.addClass(e, 'mceItemAnchor');
7751                             else
7752                                 t.dom.removeClass(e, 'mceItemAnchor');
7753                         }
7754
7755                         return;
7756                 }
7757             });
7758
7759             t.onVisualAid.dispatch(t, e, t.hasVisual);
7760         },
7761
7762         remove : function() {
7763             var t = this, e = t.getContainer();
7764
7765             t.removed = 1; // Cancels post remove event execution
7766             t.hide();
7767
7768             t.execCallback('remove_instance_callback', t);
7769             t.onRemove.dispatch(t);
7770
7771             // Clear all execCommand listeners this is required to avoid errors if the editor was removed inside another command
7772             t.onExecCommand.listeners = [];
7773
7774             EditorManager.remove(t);
7775             DOM.remove(e);
7776         },
7777
7778         destroy : function(s) {
7779             var t = this;
7780
7781             // One time is enough
7782             if (t.destroyed)
7783                 return;
7784
7785             if (!s) {
7786                 tinymce.removeUnload(t.destroy);
7787                 tinyMCE.onBeforeUnload.remove(t._beforeUnload);
7788
7789                 // Manual destroy
7790                 if (t.theme.destroy)
7791                     t.theme.destroy();
7792
7793                 // Destroy controls, selection and dom
7794                 t.controlManager.destroy();
7795                 t.selection.destroy();
7796                 t.dom.destroy();
7797
7798                 // Remove all events
18240a 7799
A 7800                 // Don't clear the window or document if content editable
7801                 // is enabled since other instances might still be present
7802                 if (!t.settings.content_editable) {
7803                     Event.clear(t.getWin());
7804                     Event.clear(t.getDoc());
7805                 }
7806
d9344f 7807                 Event.clear(t.getBody());
S 7808                 Event.clear(t.formElement);
7809             }
7810
7811             if (t.formElement) {
7812                 t.formElement.submit = t.formElement._mceOldSubmit;
7813                 t.formElement._mceOldSubmit = null;
7814             }
7815
7816             t.contentAreaContainer = t.formElement = t.container = t.settings.content_element = t.bodyElement = t.contentDocument = t.contentWindow = null;
7817
7818             if (t.selection)
7819                 t.selection = t.selection.win = t.selection.dom = t.selection.dom.doc = null;
7820
7821             t.destroyed = 1;
7822         },
7823
7824         // Internal functions
7825
7826         _addEvents : function() {
7827             // 'focus', 'blur', 'dblclick', 'beforedeactivate', submit, reset
7828             var t = this, i, s = t.settings, lo = {
7829                 mouseup : 'onMouseUp',
7830                 mousedown : 'onMouseDown',
7831                 click : 'onClick',
7832                 keyup : 'onKeyUp',
7833                 keydown : 'onKeyDown',
7834                 keypress : 'onKeyPress',
7835                 submit : 'onSubmit',
7836                 reset : 'onReset',
7837                 contextmenu : 'onContextMenu',
7838                 dblclick : 'onDblClick',
7839                 paste : 'onPaste' // Doesn't work in all browsers yet
7840             };
7841
7842             function eventHandler(e, o) {
7843                 var ty = e.type;
7844
7845                 // Don't fire events when it's removed
7846                 if (t.removed)
7847                     return;
7848
7849                 // Generic event handler
7850                 if (t.onEvent.dispatch(t, e, o) !== false) {
7851                     // Specific event handler
7852                     t[lo[e.fakeType || e.type]].dispatch(t, e, o);
7853                 }
7854             };
7855
7856             // Add DOM events
7857             each(lo, function(v, k) {
7858                 switch (k) {
7859                     case 'contextmenu':
7860                         if (tinymce.isOpera) {
7861                             // Fake contextmenu on Opera
18240a 7862                             Event.add(t.getBody(), 'mousedown', function(e) {
d9344f 7863                                 if (e.ctrlKey) {
S 7864                                     e.fakeType = 'contextmenu';
7865                                     eventHandler(e);
7866                                 }
7867                             });
7868                         } else
18240a 7869                             Event.add(t.getBody(), k, eventHandler);
d9344f 7870                         break;
S 7871
7872                     case 'paste':
7873                         Event.add(t.getBody(), k, function(e) {
7874                             var tx, h, el, r;
7875
7876                             // Get plain text data
7877                             if (e.clipboardData)
7878                                 tx = e.clipboardData.getData('text/plain');
7879                             else if (tinymce.isIE)
7880                                 tx = t.getWin().clipboardData.getData('Text');
7881
7882                             // Get HTML data
7883                             /*if (tinymce.isIE) {
7884                                 el = DOM.add(DOM.doc.body, 'div', {style : 'visibility:hidden;overflow:hidden;position:absolute;width:1px;height:1px'});
7885                                 r = DOM.doc.body.createTextRange();
7886                                 r.moveToElementText(el);
7887                                 r.execCommand('Paste');
7888                                 h = el.innerHTML;
7889                                 DOM.remove(el);
7890                             }*/
7891
7892                             eventHandler(e, {text : tx, html : h});
7893                         });
7894                         break;
7895
7896                     case 'submit':
7897                     case 'reset':
7898                         Event.add(t.getElement().form || DOM.getParent(t.id, 'form'), k, eventHandler);
7899                         break;
7900
7901                     default:
7902                         Event.add(s.content_editable ? t.getBody() : t.getDoc(), k, eventHandler);
7903                 }
7904             });
7905
7906             Event.add(s.content_editable ? t.getBody() : (isGecko ? t.getDoc() : t.getWin()), 'focus', function(e) {
7907                 t.focus(true);
7908             });
7909
7910             
7911             // Fixes bug where a specified document_base_uri could result in broken images
7912             // This will also fix drag drop of images in Gecko
7913             if (tinymce.isGecko) {
7914                 // Convert all images to absolute URLs
7915 /*                t.onSetContent.add(function(ed, o) {
7916                     each(ed.dom.select('img'), function(e) {
7917                         var v;
7918
7919                         if (v = e.getAttribute('mce_src'))
7920                             e.src = t.documentBaseURI.toAbsolute(v);
7921                     })
7922                 });*/
7923
7924                 Event.add(t.getDoc(), 'DOMNodeInserted', function(e) {
7925                     var v;
7926
7927                     e = e.target;
7928
7929                     if (e.nodeType === 1 && e.nodeName === 'IMG' && (v = e.getAttribute('mce_src')))
7930                         e.src = t.documentBaseURI.toAbsolute(v);
7931                 });
7932             }
7933
7934             // Set various midas options in Gecko
7935             if (isGecko) {
7936                 function setOpts() {
7937                     var t = this, d = t.getDoc(), s = t.settings;
7938
7939                     if (isGecko) {
7940                         if (t._isHidden()) {
7941                             try {
7942                                 if (!s.content_editable)
7943                                     d.designMode = 'On';
7944                             } catch (ex) {
7945                                 // Fails if it's hidden
7946                             }
7947                         }
7948
7949                         try {
7950                             // Try new Gecko method
7951                             d.execCommand("styleWithCSS", 0, false);
7952                         } catch (ex) {
7953                             // Use old method
7954                             if (!t._isHidden())
18240a 7955                                 try {d.execCommand("useCSS", 0, true);} catch (ex) {}
d9344f 7956                         }
S 7957
7958                         if (!s.table_inline_editing)
7959                             try {d.execCommand('enableInlineTableEditing', false, false);} catch (ex) {}
7960
7961                         if (!s.object_resizing)
7962                             try {d.execCommand('enableObjectResizing', false, false);} catch (ex) {}
7963                     }
7964                 };
7965
7966                 t.onBeforeExecCommand.add(setOpts);
7967                 t.onMouseDown.add(setOpts);
7968             }
7969
7970             // Add node change handlers
7971             t.onMouseUp.add(t.nodeChanged);
7972             t.onClick.add(t.nodeChanged);
7973             t.onKeyUp.add(function(ed, e) {
7974                 if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45 || e.keyCode == 46 || e.keyCode == 8 || e.ctrlKey)
7975                     t.nodeChanged();
7976             });
7977
7978             // Add reset handler
7979             t.onReset.add(function() {
7980                 t.setContent(t.startContent, {format : 'raw'});
7981             });
7982
7983             if (t.getParam('tab_focus')) {
7984                 function tabCancel(ed, e) {
7985                     if (e.keyCode === 9)
7986                         return Event.cancel(e);
7987                 };
7988
7989                 function tabHandler(ed, e) {
7990                     var x, i, f, el, v;
7991
7992                     function find(d) {
7993                         f = DOM.getParent(ed.id, 'form');
7994                         el = f.elements;
7995
7996                         if (f) {
7997                             each(el, function(e, i) {
7998                                 if (e.id == ed.id) {
7999                                     x = i;
8000                                     return false;
8001                                 }
8002                             });
8003
8004                             if (d > 0) {
8005                                 for (i = x + 1; i < el.length; i++) {
8006                                     if (el[i].type != 'hidden')
8007                                         return el[i];
8008                                 }
8009                             } else {
8010                                 for (i = x - 1; i >= 0; i--) {
8011                                     if (el[i].type != 'hidden')
8012                                         return el[i];
8013                                 }
8014                             }
8015                         }
8016
8017                         return null;
8018                     };
8019
8020                     if (e.keyCode === 9) {
8021                         v = explode(ed.getParam('tab_focus'));
8022
8023                         if (v.length == 1) {
8024                             v[1] = v[0];
8025                             v[0] = ':prev';
8026                         }
8027
8028                         // Find element to focus
8029                         if (e.shiftKey) {
8030                             if (v[0] == ':prev')
8031                                 el = find(-1);
8032                             else
8033                                 el = DOM.get(v[0]);
8034                         } else {
8035                             if (v[1] == ':next')
8036                                 el = find(1);
8037                             else
8038                                 el = DOM.get(v[1]);
8039                         }
8040
8041                         if (el) {
8042                             if (ed = EditorManager.get(el.id || el.name))
8043                                 ed.focus();
8044                             else
8045                                 window.setTimeout(function() {window.focus();el.focus();}, 10);
8046
8047                             return Event.cancel(e);
8048                         }
8049                     }
8050                 };
8051
8052                 t.onKeyUp.add(tabCancel);
8053
8054                 if (isGecko) {
8055                     t.onKeyPress.add(tabHandler);
8056                     t.onKeyDown.add(tabCancel);
8057                 } else
8058                     t.onKeyDown.add(tabHandler);
8059             }
8060
8061             // Add shortcuts
8062             if (s.custom_shortcuts) {
8063                 if (s.custom_undo_redo_keyboard_shortcuts) {
8064                     t.addShortcut('ctrl+z', t.getLang('undo_desc'), 'Undo');
8065                     t.addShortcut('ctrl+y', t.getLang('redo_desc'), 'Redo');
8066                 }
8067
8068                 // Add default shortcuts for gecko
8069                 if (isGecko) {
8070                     t.addShortcut('ctrl+b', t.getLang('bold_desc'), 'Bold');
8071                     t.addShortcut('ctrl+i', t.getLang('italic_desc'), 'Italic');
8072                     t.addShortcut('ctrl+u', t.getLang('underline_desc'), 'Underline');
8073                 }
8074
8075                 // BlockFormat shortcuts keys
8076                 for (i=1; i<=6; i++)
8077                     t.addShortcut('ctrl+' + i, '', ['FormatBlock', false, '<h' + i + '>']);
8078
8079                 t.addShortcut('ctrl+7', '', ['FormatBlock', false, '<p>']);
8080                 t.addShortcut('ctrl+8', '', ['FormatBlock', false, '<div>']);
8081                 t.addShortcut('ctrl+9', '', ['FormatBlock', false, '<address>']);
8082
8083                 function find(e) {
8084                     var v = null;
8085
8086                     if (!e.altKey && !e.ctrlKey && !e.metaKey)
8087                         return v;
8088
8089                     each(t.shortcuts, function(o) {
8090                         if (o.ctrl != e.ctrlKey && (!tinymce.isMac || o.ctrl == e.metaKey))
8091                             return;
8092
8093                         if (o.alt != e.altKey)
8094                             return;
8095
8096                         if (o.shift != e.shiftKey)
8097                             return;
8098
8099                         if (e.keyCode == o.keyCode || (e.charCode && e.charCode == o.charCode)) {
8100                             v = o;
8101                             return false;
8102                         }
8103                     });
8104
8105                     return v;
8106                 };
8107
8108                 t.onKeyUp.add(function(ed, e) {
8109                     var o = find(e);
8110
8111                     if (o)
8112                         return Event.cancel(e);
8113                 });
8114
8115                 t.onKeyPress.add(function(ed, e) {
8116                     var o = find(e);
8117
8118                     if (o)
8119                         return Event.cancel(e);
8120                 });
8121
8122                 t.onKeyDown.add(function(ed, e) {
8123                     var o = find(e);
8124
8125                     if (o) {
8126                         o.func.call(o.scope);
8127                         return Event.cancel(e);
8128                     }
8129                 });
8130             }
8131
8132             if (tinymce.isIE) {
8133                 // Fix so resize will only update the width and height attributes not the styles of an image
8134                 // It will also block mceItemNoResize items
8135                 Event.add(t.getDoc(), 'controlselect', function(e) {
8136                     var re = t.resizeInfo, cb;
8137
8138                     e = e.target;
8139
8140                     // Don't do this action for non image elements
8141                     if (e.nodeName !== 'IMG')
8142                         return;
8143
8144                     if (re)
8145                         Event.remove(re.node, re.ev, re.cb);
8146
8147                     if (!t.dom.hasClass(e, 'mceItemNoResize')) {
8148                         ev = 'resizeend';
8149                         cb = Event.add(e, ev, function(e) {
8150                             var v;
8151
8152                             e = e.target;
8153
8154                             if (v = t.dom.getStyle(e, 'width')) {
8155                                 t.dom.setAttrib(e, 'width', v.replace(/[^0-9%]+/g, ''));
8156                                 t.dom.setStyle(e, 'width', '');
8157                             }
8158
8159                             if (v = t.dom.getStyle(e, 'height')) {
8160                                 t.dom.setAttrib(e, 'height', v.replace(/[^0-9%]+/g, ''));
8161                                 t.dom.setStyle(e, 'height', '');
8162                             }
8163                         });
8164                     } else {
8165                         ev = 'resizestart';
8166                         cb = Event.add(e, 'resizestart', Event.cancel, Event);
8167                     }
8168
8169                     re = t.resizeInfo = {
8170                         node : e,
8171                         ev : ev,
8172                         cb : cb
8173                     };
8174                 });
8175
8176                 t.onKeyDown.add(function(ed, e) {
8177                     switch (e.keyCode) {
8178                         case 8:
8179                             // Fix IE control + backspace browser bug
8180                             if (t.selection.getRng().item) {
8181                                 t.selection.getRng().item(0).removeNode();
8182                                 return Event.cancel(e);
8183                             }
8184                     }
8185                 });
8186             }
8187
8188             if (tinymce.isOpera) {
8189                 t.onClick.add(function(ed, e) {
8190                     Event.prevent(e);
8191                 });
8192             }
8193
8194             // Add custom undo/redo handlers
8195             if (s.custom_undo_redo) {
8196                 function addUndo() {
8197                     t.undoManager.typing = 0;
8198                     t.undoManager.add();
8199                 };
8200
8201                 // Add undo level on editor blur
8202                 if (tinymce.isIE) {
8203                     Event.add(t.getWin(), 'blur', function(e) {
8204                         var n;
8205
8206                         // Check added for fullscreen bug
8207                         if (t.selection) {
8208                             n = t.selection.getNode();
8209
8210                             // Add undo level is selection was lost to another document
8211                             if (!t.removed && n.ownerDocument && n.ownerDocument != t.getDoc())
8212                                 addUndo();
8213                         }
8214                     });
8215                 } else {
8216                     Event.add(t.getDoc(), 'blur', function() {
8217                         if (t.selection && !t.removed)
8218                             addUndo();
8219                     });
8220                 }
8221
8222                 t.onMouseDown.add(addUndo);
8223
8224                 t.onKeyUp.add(function(ed, e) {
8225                     if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45 || e.ctrlKey) {
8226                         t.undoManager.typing = 0;
8227                         t.undoManager.add();
8228                     }
8229                 });
8230
8231                 t.onKeyDown.add(function(ed, e) {
8232                     // Is caracter positon keys
8233                     if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45) {
8234                         if (t.undoManager.typing) {
8235                             t.undoManager.add();
8236                             t.undoManager.typing = 0;
8237                         }
8238
8239                         return;
8240                     }
8241
8242                     if (!t.undoManager.typing) {
8243                         t.undoManager.add();
8244                         t.undoManager.typing = 1;
8245                     }
8246                 });
8247             }
8248         },
8249
8250         _convertInlineElements : function() {
8251             var t = this, s = t.settings, dom = t.dom, v, e, na, st, sp;
8252
8253             function convert(ed, o) {
8254                 if (!s.inline_styles)
8255                     return;
8256
8257                 if (o.get) {
8258                     each(t.dom.select('table,u,strike', o.node), function(n) {
8259                         switch (n.nodeName) {
8260                             case 'TABLE':
8261                                 if (v = dom.getAttrib(n, 'height')) {
8262                                     dom.setStyle(n, 'height', v);
8263                                     dom.setAttrib(n, 'height', '');
8264                                 }
8265                                 break;
8266
8267                             case 'U':
8268                             case 'STRIKE':
18240a 8269                                 //sp = dom.create('span', {style : dom.getAttrib(n, 'style')});
A 8270                                 n.style.textDecoration = n.nodeName == 'U' ? 'underline' : 'line-through';
8271                                 dom.setAttrib(n, 'mce_style', '');
8272                                 dom.setAttrib(n, 'mce_name', 'span');
d9344f 8273                                 break;
S 8274                         }
8275                     });
8276                 } else if (o.set) {
18240a 8277                     each(t.dom.select('table,span', o.node).reverse(), function(n) {
d9344f 8278                         if (n.nodeName == 'TABLE') {
S 8279                             if (v = dom.getStyle(n, 'height'))
8280                                 dom.setAttrib(n, 'height', v.replace(/[^0-9%]+/g, ''));
8281                         } else {
8282                             // Convert spans to elements
8283                             if (n.style.textDecoration == 'underline')
8284                                 na = 'u';
8285                             else if (n.style.textDecoration == 'line-through')
8286                                 na = 'strike';
8287                             else
8288                                 na = '';
8289
8290                             if (na) {
8291                                 n.style.textDecoration = '';
8292                                 dom.setAttrib(n, 'mce_style', '');
8293
8294                                 e = dom.create(na, {
8295                                     style : dom.getAttrib(n, 'style')
8296                                 });
8297
8298                                 dom.replace(e, n, 1);
8299                             }
8300                         }
8301                     });
8302                 }
8303             };
8304
8305             t.onPreProcess.add(convert);
8306
8307             if (!s.cleanup_on_startup) {
18240a 8308                 t.onSetContent.add(function(ed, o) {
A 8309                     if (o.initial)
8310                         convert(t, {node : t.getBody(), set : 1});
d9344f 8311                 });
S 8312             }
8313         },
8314
8315         _convertFonts : function() {
8316             var t = this, s = t.settings, dom = t.dom, fz, fzn, sl, cl;
8317
8318             // No need
8319             if (!s.inline_styles)
8320                 return;
8321
8322             // Font pt values and font size names
8323             fz = [8, 10, 12, 14, 18, 24, 36];
8324             fzn = ['xx-small', 'x-small','small','medium','large','x-large', 'xx-large'];
8325
8326             if (sl = s.font_size_style_values)
8327                 sl = explode(sl);
8328
8329             if (cl = s.font_size_classes)
8330                 cl = explode(cl);
8331
8332             function convertToFonts(no) {
8333                 var n, f, nl, x, i, v, st;
8334
8335                 // Convert spans to fonts on non WebKit browsers
8336                 if (tinymce.isWebKit || !s.inline_styles)
8337                     return;
8338
8339                 nl = t.dom.select('span', no);
8340                 for (x = nl.length - 1; x >= 0; x--) {
8341                     n = nl[x];
8342
8343                     f = dom.create('font', {
8344                         color : dom.toHex(dom.getStyle(n, 'color')),
8345                         face : dom.getStyle(n, 'fontFamily'),
8346                         style : dom.getAttrib(n, 'style'),
8347                         'class' : dom.getAttrib(n, 'class')
8348                     });
8349
8350                     // Clear color and font family
8351                     st = f.style;
8352                     if (st.color || st.fontFamily) {
8353                         st.color = st.fontFamily = '';
8354                         dom.setAttrib(f, 'mce_style', ''); // Remove cached style data
8355                     }
8356
8357                     if (sl) {
8358                         i = inArray(sl, dom.getStyle(n, 'fontSize'));
8359
8360                         if (i != -1) {
8361                             dom.setAttrib(f, 'size', '' + (i + 1 || 1));
18240a 8362                             //f.style.fontSize = '';
d9344f 8363                         }
S 8364                     } else if (cl) {
8365                         i = inArray(cl, dom.getAttrib(n, 'class'));
8366                         v = dom.getStyle(n, 'fontSize');
8367
8368                         if (i == -1 && v.indexOf('pt') > 0)
8369                             i = inArray(fz, parseInt(v));
8370
8371                         if (i == -1)
8372                             i = inArray(fzn, v);
8373
8374                         if (i != -1) {
8375                             dom.setAttrib(f, 'size', '' + (i + 1 || 1));
8376                             f.style.fontSize = '';
8377                         }
8378                     }
8379
8380                     if (f.color || f.face || f.size) {
8381                         f.style.fontFamily = '';
8382                         dom.setAttrib(f, 'mce_style', '');
8383                         dom.replace(f, n, 1);
8384                     }
8385
8386                     f = n = null;
8387                 }
8388             };
8389
8390             // Run on setup
8391             t.onSetContent.add(function(ed, o) {
8392                 convertToFonts(ed.getBody());
8393             });
8394
8395             // Run on cleanup
8396             t.onPreProcess.add(function(ed, o) {
8397                 var n, sp, nl, x;
8398
8399                 // Keep unit tests happy
8400                 if (!s.inline_styles)
8401                     return;
8402
8403                 if (o.get) {
8404                     nl = t.dom.select('font', o.node);
8405                     for (x = nl.length - 1; x >= 0; x--) {
8406                         n = nl[x];
8407
8408                         sp = dom.create('span', {
8409                             style : dom.getAttrib(n, 'style'),
8410                             'class' : dom.getAttrib(n, 'class')
8411                         });
8412
8413                         dom.setStyles(sp, {
8414                             fontFamily : dom.getAttrib(n, 'face'),
8415                             color : dom.getAttrib(n, 'color'),
8416                             backgroundColor : n.style.backgroundColor
8417                         });
8418
8419                         if (n.size) {
8420                             if (sl)
8421                                 dom.setStyle(sp, 'fontSize', sl[parseInt(n.size) - 1]);
8422                             else
8423                                 dom.setAttrib(sp, 'class', cl[parseInt(n.size) - 1]);
8424                         }
8425
8426                         dom.setAttrib(sp, 'mce_style', '');
8427                         dom.replace(sp, n, 1);
8428                     }
8429                 }
8430             });
8431         },
8432
8433         _isHidden : function() {
8434             var s;
8435
8436             if (!isGecko)
8437                 return 0;
8438
8439             // Weird, wheres that cursor selection?
8440             s = this.selection.getSel();
8441             return (!s || !s.rangeCount || s.rangeCount == 0);
8442         },
8443
8444         // Fix for bug #1867292
8445         _fixNesting : function(s) {
8446             var d = [], i;
8447
8448             s = s.replace(/<(\/)?([^\s>]+)[^>]*?>/g, function(a, b, c) {
8449                 var e;
8450
8451                 // Handle end element
8452                 if (b === '/') {
8453                     if (!d.length)
8454                         return '';
8455
8456                     if (c !== d[d.length - 1].tag) {
8457                         for (i=d.length - 1; i>=0; i--) {
8458                             if (d[i].tag === c) {
8459                                 d[i].close = 1;
8460                                 break;
8461                             }
8462                         }
8463
8464                         return '';
8465                     } else {
8466                         d.pop();
8467
8468                         if (d.length && d[d.length - 1].close) {
8469                             a = a + '</' + d[d.length - 1].tag + '>';
8470                             d.pop();
8471                         }
8472                     }
8473                 } else {
8474                     // Ignore these
8475                     if (/^(br|hr|input|meta|img|link|param)$/i.test(c))
8476                         return a;
8477
8478                     // Ignore closed ones
8479                     if (/\/>$/.test(a))
8480                         return a;
8481
8482                     d.push({tag : c}); // Push start element
8483                 }
8484
8485                 return a;
8486             });
8487
8488             // End all open tags
8489             for (i=d.length - 1; i>=0; i--)
8490                 s += '</' + d[i].tag + '>';
8491
8492             return s;
8493         }
8494
8495         });
8496 })();
8497
8498 /* file:jscripts/tiny_mce/classes/EditorCommands.js */
8499
8500 (function() {
8501     var each = tinymce.each, isIE = tinymce.isIE, isGecko = tinymce.isGecko, isOpera = tinymce.isOpera, isWebKit = tinymce.isWebKit;
8502
8503     tinymce.create('tinymce.EditorCommands', {
8504         EditorCommands : function(ed) {
8505             this.editor = ed;
8506         },
8507
8508         execCommand : function(cmd, ui, val) {
8509             var t = this, ed = t.editor, f;
8510
8511             switch (cmd) {
8512                 case 'Cut':
8513                 case 'Copy':
8514                 case 'Paste':
8515                     try {
8516                         ed.getDoc().execCommand(cmd, ui, val);
8517                     } catch (ex) {
8518                         if (isGecko) {
8519                             ed.windowManager.confirm(ed.getLang('clipboard_msg'), function(s) {
8520                                 if (s)
8521                                     window.open('http://www.mozilla.org/editor/midasdemo/securityprefs.html', 'mceExternal');
8522                             });
8523                         } else
8524                             ed.windowManager.alert(ed.getLang('clipboard_no_support'));
8525                     }
8526
8527                     return true;
8528
8529                 // Ignore these
8530                 case 'mceResetDesignMode':
8531                 case 'mceBeginUndoLevel':
8532                     return true;
8533
8534                 // Ignore these
8535                 case 'unlink':
8536                     t.UnLink();
8537                     return true;
8538
8539                 // Bundle these together
8540                 case 'JustifyLeft':
8541                 case 'JustifyCenter':
8542                 case 'JustifyRight':
8543                 case 'JustifyFull':
8544                     t.mceJustify(cmd, cmd.substring(7).toLowerCase());
8545                     return true;
8546
8547                 case 'mceEndUndoLevel':
8548                 case 'mceAddUndoLevel':
8549                     ed.undoManager.add();
8550                     return true;
8551
8552                 default:
8553                     f = this[cmd];
8554
8555                     if (f) {
8556                         f.call(this, ui, val);
8557                         return true;
8558                     }
8559             }
8560
8561             return false;
8562         },
8563
8564         Indent : function() {
8565             var ed = this.editor, d = ed.dom, s = ed.selection, e, iv, iu;
8566
8567             // Setup indent level
8568             iv = ed.settings.indentation;
8569             iu = /[a-z%]+$/i.exec(iv);
8570             iv = parseInt(iv);
8571
8572             if (ed.settings.inline_styles && (!this.queryStateInsertUnorderedList() && !this.queryStateInsertOrderedList())) {
8573                 each(this._getSelectedBlocks(), function(e) {
8574                     d.setStyle(e, 'paddingLeft', (parseInt(e.style.paddingLeft || 0) + iv) + iu);
8575                 });
8576
8577                 return;
8578             }
8579
8580             ed.getDoc().execCommand('Indent', false, null);
8581
8582             if (isIE) {
8583                 d.getParent(s.getNode(), function(n) {
8584                     if (n.nodeName == 'BLOCKQUOTE') {
8585                         n.dir = n.style.cssText = '';
8586                     }
8587                 });
8588             }
8589         },
8590
8591         Outdent : function() {
8592             var ed = this.editor, d = ed.dom, s = ed.selection, e, v, iv, iu;
8593
8594             // Setup indent level
8595             iv = ed.settings.indentation;
8596             iu = /[a-z%]+$/i.exec(iv);
8597             iv = parseInt(iv);
8598
8599             if (ed.settings.inline_styles && (!this.queryStateInsertUnorderedList() && !this.queryStateInsertOrderedList())) {
8600                 each(this._getSelectedBlocks(), function(e) {
8601                     v = Math.max(0, parseInt(e.style.paddingLeft || 0) - iv);
8602                     d.setStyle(e, 'paddingLeft', v ? v + iu : '');
8603                 });
8604
8605                 return;
8606             }
8607
8608             ed.getDoc().execCommand('Outdent', false, null);
8609         },
8610
8611         mceSetAttribute : function(u, v) {
8612             var ed = this.editor, d = ed.dom, e;
8613
8614             if (e = d.getParent(ed.selection.getNode(), d.isBlock))
8615                 d.setAttrib(e, v.name, v.value);
8616         },
8617
8618         mceSetContent : function(u, v) {
8619             this.editor.setContent(v);
8620         },
8621
8622         mceToggleVisualAid : function() {
8623             var ed = this.editor;
8624
8625             ed.hasVisual = !ed.hasVisual;
8626             ed.addVisual();
8627         },
8628
8629         mceReplaceContent : function(u, v) {
8630             var s = this.editor.selection;
8631
8632             s.setContent(v.replace(/\{\$selection\}/g, s.getContent({format : 'text'})));
8633         },
8634
8635         mceInsertLink : function(u, v) {
18240a 8636             var ed = this.editor, s = ed.selection, e = ed.dom.getParent(s.getNode(), 'A');
d9344f 8637
S 8638             if (tinymce.is(v, 'string'))
8639                 v = {href : v};
8640
8641             function set(e) {
8642                 each(v, function(v, k) {
8643                     ed.dom.setAttrib(e, k, v);
8644                 });
8645             };
8646
8647             if (!e) {
8648                 ed.execCommand('CreateLink', false, 'javascript:mctmp(0);');
8649                 each(ed.dom.select('a'), function(e) {
8650                     if (e.href == 'javascript:mctmp(0);')
8651                         set(e);
8652                 });
8653             } else {
8654                 if (v.href)
8655                     set(e);
8656                 else
8657                     ed.dom.remove(e, 1);
8658             }
8659         },
8660
8661         UnLink : function() {
8662             var ed = this.editor, s = ed.selection;
8663
8664             if (s.isCollapsed())
8665                 s.select(s.getNode());
8666
8667             ed.getDoc().execCommand('unlink', false, null);
8668             s.collapse(0);
8669         },
8670
8671         FontName : function(u, v) {
8672             var t = this, ed = t.editor, s = ed.selection, e;
8673
8674             if (!v) {
8675                 if (s.isCollapsed())
8676                     s.select(s.getNode());
8677
8678                 t.RemoveFormat();
8679             } else
8680                 ed.getDoc().execCommand('FontName', false, v);
18240a 8681         },
A 8682
8683         FontSize : function(u, v) {
8684             var ed = this.editor, s = ed.settings, fz = tinymce.explode(s.font_size_style_values), fzc = tinymce.explode(s.font_size_classes), h, bm;
8685
8686             // Remove style sizes
8687             each(ed.dom.select('font'), function(e) {
8688                 e.style.fontSize = '';
8689             });
8690
8691             // Let the browser add new size it will remove unneded ones in some browsers
8692             ed.getDoc().execCommand('FontSize', false, v);
8693
8694             // Add style values
8695             if (s.inline_styles) {
8696                 each(ed.dom.select('font'), function(e) {
8697                     // Try remove redundant font elements
8698                     if (e.parentNode.nodeName == 'FONT' && e.size == e.parentNode.size) {
8699                         if (!bm)
8700                             bm = ed.selection.getBookmark();
8701
8702                         ed.dom.remove(e, 1);
8703                         return;
8704                     }
8705
8706                     // Setup font size based on font size value
8707                     if (v = e.size) {
8708                         if (fzc && fzc.length > 0)
8709                             ed.dom.setAttrib(e, 'class', fzc[parseInt(v) - 1]);
8710                         else
8711                             ed.dom.setStyle(e, 'fontSize', fz[parseInt(v) - 1]);
8712                     }
8713                 });
8714             }
8715
8716             ed.selection.moveToBookmark(bm);
d9344f 8717         },
S 8718
8719         queryCommandValue : function(c) {
8720             var f = this['queryValue' + c];
8721
8722             if (f)
8723                 return f.call(this, c);
8724
8725             return false;
8726         },
8727
8728         queryCommandState : function(cmd) {
8729             var f;
8730
8731             switch (cmd) {
8732                 // Bundle these together
8733                 case 'JustifyLeft':
8734                 case 'JustifyCenter':
8735                 case 'JustifyRight':
8736                 case 'JustifyFull':
8737                     return this.queryStateJustify(cmd, cmd.substring(7).toLowerCase());
8738
8739                 default:
8740                     if (f = this['queryState' + cmd])
8741                         return f.call(this, cmd);
8742             }
8743
8744             return -1;
8745         },
8746
8747         _queryState : function(c) {
8748             try {
8749                 return this.editor.getDoc().queryCommandState(c);
8750             } catch (ex) {
8751                 // Ignore exception
8752             }
8753         },
8754
8755         _queryVal : function(c) {
8756             try {
8757                 return this.editor.getDoc().queryCommandValue(c);
8758             } catch (ex) {
8759                 // Ignore exception
8760             }
8761         },
8762
8763         queryValueFontSize : function() {
8764             var ed = this.editor, v = 0, p;
8765
8766             if (isOpera || isWebKit) {
8767                 if (p = ed.dom.getParent(ed.selection.getNode(), 'FONT'))
8768                     v = p.size;
8769
8770                 return v;
8771             }
8772
8773             return this._queryVal('FontSize');
8774         },
8775
8776         queryValueFontName : function() {
8777             var ed = this.editor, v = 0, p;
8778
8779             if (p = ed.dom.getParent(ed.selection.getNode(), 'FONT'))
8780                 v = p.face;
8781
8782             if (!v)
8783                 v = this._queryVal('FontName');
8784
8785             return v;
8786         },
8787
8788         mceJustify : function(c, v) {
8789             var ed = this.editor, se = ed.selection, n = se.getNode(), nn = n.nodeName, bl, nb, dom = ed.dom, rm;
8790
8791             if (ed.settings.inline_styles && this.queryStateJustify(c, v))
8792                 rm = 1;
8793
8794             bl = dom.getParent(n, ed.dom.isBlock);
8795
8796             if (nn == 'IMG') {
8797                 if (v == 'full')
8798                     return;
8799
8800                 if (rm) {
8801                     if (v == 'center')
8802                         dom.setStyle(n.parentNode, 'textAlign', '');
8803
8804                     dom.setStyle(n, 'float', '');
8805                     this.mceRepaint();
8806                     return;
8807                 }
8808
8809                 if (v == 'center') {
8810                     // Do not change table elements
8811                     if (/^(TD|TH)$/.test(bl.nodeName))
8812                         bl = 0;
8813
8814                     if (!bl || bl.childNodes.length > 1) {
8815                         nb = dom.create('p');
8816                         nb.appendChild(n.cloneNode(false));
8817
8818                         if (bl)
8819                             dom.insertAfter(nb, bl);
8820                         else
8821                             dom.insertAfter(nb, n);
8822
8823                         dom.remove(n);
8824                         n = nb.firstChild;
8825                         bl = nb;
8826                     }
8827
8828                     dom.setStyle(bl, 'textAlign', v);
8829                     dom.setStyle(n, 'float', '');
8830                 } else {
8831                     dom.setStyle(n, 'float', v);
8832                     dom.setStyle(n.parentNode, 'textAlign', '');
8833                 }
8834
8835                 this.mceRepaint();
8836                 return;
8837             }
8838
8839             // Handle the alignment outselfs, less quirks in all browsers
8840             if (ed.settings.inline_styles && ed.settings.forced_root_block) {
8841                 if (rm)
8842                     v = '';
8843
8844                 each(this._getSelectedBlocks(dom.getParent(se.getStart(), dom.isBlock), dom.getParent(se.getEnd(), dom.isBlock)), function(e) {
8845                     dom.setAttrib(e, 'align', '');
8846                     dom.setStyle(e, 'textAlign', v == 'full' ? 'justify' : v);
8847                 });
8848
8849                 return;
8850             } else if (!rm)
8851                 ed.getDoc().execCommand(c, false, null);
8852
8853             if (ed.settings.inline_styles) {
8854                 if (rm) {
8855                     dom.getParent(ed.selection.getNode(), function(n) {
8856                         if (n.style && n.style.textAlign)
8857                             dom.setStyle(n, 'textAlign', '');
8858                     });
8859
8860                     return;
8861                 }
8862
8863                 each(dom.select('*'), function(n) {
8864                     var v = n.align;
8865
8866                     if (v) {
8867                         if (v == 'full')
8868                             v = 'justify';
8869
8870                         dom.setStyle(n, 'textAlign', v);
8871                         dom.setAttrib(n, 'align', '');
8872                     }
8873                 });
8874             }
8875         },
8876
8877         mceSetCSSClass : function(u, v) {
8878             this.mceSetStyleInfo(0, {command : 'setattrib', name : 'class', value : v});
8879         },
8880
8881         getSelectedElement : function() {
8882             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;
8883
8884             if (se.isCollapsed() || r.item)
8885                 return se.getNode();
8886
8887             // Setup regexp
8888             re = ed.settings.merge_styles_invalid_parents;
8889             if (tinymce.is(re, 'string'))
8890                 re = new RegExp(re, 'i');
8891
8892             if (isIE) {
8893                 r1 = r.duplicate();
8894                 r1.collapse(true);
8895                 sc = r1.parentElement();
8896
8897                 r2 = r.duplicate();
8898                 r2.collapse(false);
8899                 ec = r2.parentElement();
8900
8901                 if (sc != ec) {
8902                     r1.move('character', 1);
8903                     sc = r1.parentElement();
8904                 }
8905
8906                 if (sc == ec) {
8907                     r1 = r.duplicate();
8908                     r1.moveToElementText(sc);
8909
8910                     if (r1.compareEndPoints('StartToStart', r) == 0 && r1.compareEndPoints('EndToEnd', r) == 0)
8911                         return re && re.test(sc.nodeName) ? null : sc;
8912                 }
8913             } else {
8914                 function getParent(n) {
8915                     return dom.getParent(n, function(n) {return n.nodeType == 1;});
8916                 };
8917
8918                 sc = r.startContainer;
8919                 ec = r.endContainer;
8920                 so = r.startOffset;
8921                 eo = r.endOffset;
8922
8923                 if (!r.collapsed) {
8924                     if (sc == ec) {
8925                         if (so - eo < 2) {
8926                             if (sc.hasChildNodes()) {
8927                                 sp = sc.childNodes[so];
8928                                 return re && re.test(sp.nodeName) ? null : sp;
8929                             }
8930                         }
8931                     }
8932                 }
8933
8934                 if (sc.nodeType != 3 || ec.nodeType != 3)
8935                     return null;
8936
8937                 if (so == 0) {
8938                     sp = getParent(sc);
8939
8940                     if (sp && sp.firstChild != sc)
8941                         sp = null;
8942                 }
8943
8944                 if (so == sc.nodeValue.length) {
8945                     e = sc.nextSibling;
8946
8947                     if (e && e.nodeType == 1)
8948                         sp = sc.nextSibling;
8949                 }
8950
8951                 if (eo == 0) {
8952                     e = ec.previousSibling;
8953
8954                     if (e && e.nodeType == 1)
8955                         ep = e;
8956                 }
8957
8958                 if (eo == ec.nodeValue.length) {
8959                     ep = getParent(ec);
8960
8961                     if (ep && ep.lastChild != ec)
8962                         ep = null;
8963                 }
8964
8965                 // Same element
8966                 if (sp == ep)
8967                     return re && sp && re.test(sp.nodeName) ? null : sp;
8968             }
8969
8970             return null;
8971         },
8972
8973         InsertHorizontalRule : function() {
8974             // Fix for Gecko <hr size="1" /> issue and IE bug rep(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]");
8975             if (isGecko || isIE)
8976                 this.editor.selection.setContent('<hr />');
8977             else
8978                 this.editor.getDoc().execCommand('InsertHorizontalRule', false, '');
8979         },
8980
8981         RemoveFormat : function() {
8982             var t = this, ed = t.editor, s = ed.selection, b;
8983
8984             // Safari breaks tables
8985             if (isWebKit)
8986                 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'});
8987             else
8988                 ed.getDoc().execCommand('RemoveFormat', false, null);
8989
8990             t.mceSetStyleInfo(0, {command : 'removeformat'});
8991             ed.addVisual();
8992         },
8993
8994         mceSetStyleInfo : function(u, v) {
8995             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;
8996
8997             function set(n, e) {
8998                 if (n.nodeType == 1) {
8999                     switch (v.command) {
9000                         case 'setattrib':
9001                             return dom.setAttrib(n, v.name, v.value);
9002
9003                         case 'setstyle':
9004                             return dom.setStyle(n, v.name, v.value);
9005
9006                         case 'removeformat':
9007                             return dom.setAttrib(n, 'class', '');
9008                     }
9009                 }
9010             };
9011
9012             // Setup regexp
9013             re = ed.settings.merge_styles_invalid_parents;
9014             if (tinymce.is(re, 'string'))
9015                 re = new RegExp(re, 'i');
9016
9017             // Set style info on selected element
9018             if (e = t.getSelectedElement())
9019                 set(e, 1);
9020             else {
9021                 // Generate wrappers and set styles on them
9022                 d.execCommand('FontName', false, '__');
9023                 each(isWebKit ? dom.select('span') : dom.select('font'), function(n) {
9024                     var sp, e;
9025
9026                     if (dom.getAttrib(n, 'face') == '__' || n.style.fontFamily === '__') {
9027                         sp = dom.create(nn, {mce_new : '1'});
9028
9029                         set(sp);
9030
9031                         each (n.childNodes, function(n) {
9032                             sp.appendChild(n.cloneNode(true));
9033                         });
9034
9035                         dom.replace(sp, n);
9036                     }
9037                 });
9038             }
9039
9040             // Remove wrappers inside new ones
9041             each(dom.select(nn).reverse(), function(n) {
9042                 var p = n.parentNode;
9043
9044                 // Check if it's an old span in a new wrapper
9045                 if (!dom.getAttrib(n, 'mce_new')) {
9046                     // Find new wrapper
9047                     p = dom.getParent(n, function(n) {
9048                         return n.nodeType == 1 && dom.getAttrib(n, 'mce_new');
9049                     });
9050
9051                     if (p)
9052                         dom.remove(n, 1);
9053                 }
9054             });
9055
9056             // Merge wrappers with parent wrappers
9057             each(dom.select(nn).reverse(), function(n) {
9058                 var p = n.parentNode;
9059
9060                 if (!p || !dom.getAttrib(n, 'mce_new'))
9061                     return;
9062
9063                 // Has parent of the same type and only child
9064                 if (p.nodeName == nn.toUpperCase() && p.childNodes.length == 1)
9065                     return dom.remove(p, 1);
9066
9067                 // Has parent that is more suitable to have the class and only child
9068                 if (n.nodeType == 1 && (!re || !re.test(p.nodeName)) && p.childNodes.length == 1) {
9069                     set(p); // Set style info on parent instead
9070                     dom.setAttrib(n, 'class', '');
9071                 }
9072             });
9073
9074             // Remove empty wrappers
9075             each(dom.select(nn).reverse(), function(n) {
9076                 if (dom.getAttrib(n, 'mce_new') || (dom.getAttribs(n).length <= 1 && n.className === '')) {
9077                     if (!dom.getAttrib(n, 'class') && !dom.getAttrib(n, 'style'))
9078                         return dom.remove(n, 1);
9079
9080                     dom.setAttrib(n, 'mce_new', ''); // Remove mce_new marker
9081                 }
9082             });
9083
9084             s.moveToBookmark(b);
9085         },
9086
9087         queryStateJustify : function(c, v) {
9088             var ed = this.editor, n = ed.selection.getNode(), dom = ed.dom;
9089
9090             if (n && n.nodeName == 'IMG') {
9091                 if (dom.getStyle(n, 'float') == v)
9092                     return 1;
9093
9094                 return n.parentNode.style.textAlign == v;
9095             }
9096
9097             n = dom.getParent(ed.selection.getStart(), function(n) {
9098                 return n.nodeType == 1 && n.style.textAlign;
9099             });
9100
9101             if (v == 'full')
9102                 v = 'justify';
9103
9104             if (ed.settings.inline_styles)
9105                 return (n && n.style.textAlign == v);
9106
9107             return this._queryState(c);
9108         },
9109
9110         HiliteColor : function(ui, val) {
9111             var t = this, ed = t.editor, d = ed.getDoc();
9112
9113             function set(s) {
9114                 if (!isGecko)
9115                     return;
9116
9117                 try {
9118                     // Try new Gecko method
9119                     d.execCommand("styleWithCSS", 0, s);
9120                 } catch (ex) {
9121                     // Use old
9122                     d.execCommand("useCSS", 0, !s);
9123                 }
9124             };
9125
9126             if (isGecko || isOpera) {
9127                 set(true);
9128                 d.execCommand('hilitecolor', false, val);
9129                 set(false);
9130             } else
9131                 d.execCommand('BackColor', false, val);
9132         },
9133
9134         Undo : function() {
9135             var ed = this.editor;
9136
9137             if (ed.settings.custom_undo_redo) {
9138                 ed.undoManager.undo();
9139                 ed.nodeChanged();
9140             } else
9141                 ed.getDoc().execCommand('Undo', false, null);
9142         },
9143
9144         Redo : function() {
9145             var ed = this.editor;
9146
9147             if (ed.settings.custom_undo_redo) {
9148                 ed.undoManager.redo();
9149                 ed.nodeChanged();
9150             } else
9151                 ed.getDoc().execCommand('Redo', false, null);
9152         },
9153
9154         FormatBlock : function(ui, val) {
18240a 9155             var t = this, ed = t.editor, s = ed.selection, dom = ed.dom, bl, nb, b;
A 9156
9157             function isBlock(n) {
9158                 return /^(P|DIV|H[1-6]|ADDRESS|BLOCKQUOTE|PRE)$/.test(n.nodeName);
9159             };
9160
9161             bl = dom.getParent(s.getNode(), function(n) {
9162                 return isBlock(n);
9163             });
9164
9165             // IE has an issue where it removes the parent div if you change format on the paragrah in <div><p>Content</p></div>
9166             // FF and Opera doesn't change parent DIV elements if you switch format
9167             if (bl) {
9168                 if ((isIE && isBlock(bl.parentNode)) || bl.nodeName == 'DIV') {
9169                     // Rename block element
9170                     nb = ed.dom.create(val);
9171
9172                     each(dom.getAttribs(bl), function(v) {
9173                         dom.setAttrib(nb, v.nodeName, dom.getAttrib(bl, v.nodeName));
9174                     });
9175
9176                     b = s.getBookmark();
9177                     dom.replace(nb, bl, 1);
9178                     s.moveToBookmark(b);
9179                     ed.nodeChanged();
9180                     return;
9181                 }
9182             }
d9344f 9183
S 9184             val = ed.settings.forced_root_block ? (val || '<p>') : val;
9185
9186             if (val.indexOf('<') == -1)
9187                 val = '<' + val + '>';
9188
9189             if (tinymce.isGecko)
9190                 val = val.replace(/<(div|blockquote|code|dt|dd|dl|samp)>/gi, '$1');
9191
9192             ed.getDoc().execCommand('FormatBlock', false, val);
9193         },
9194
9195         mceCleanup : function() {
9196             var ed = this.editor, s = ed.selection, b = s.getBookmark();
9197             ed.setContent(ed.getContent());
9198             s.moveToBookmark(b);
9199         },
9200
9201         mceRemoveNode : function(ui, val) {
9202             var ed = this.editor, s = ed.selection, b, n = val || s.getNode();
9203
9204             // Make sure that the body node isn't removed
9205             if (n == ed.getBody())
9206                 return;
9207
9208             b = s.getBookmark();
9209             ed.dom.remove(n, 1);
9210             s.moveToBookmark(b);
9211             ed.nodeChanged();
9212         },
9213
9214         mceSelectNodeDepth : function(ui, val) {
9215             var ed = this.editor, s = ed.selection, c = 0;
9216
9217             ed.dom.getParent(s.getNode(), function(n) {
9218                 if (n.nodeType == 1 && c++ == val) {
9219                     s.select(n);
9220                     ed.nodeChanged();
9221                     return false;
9222                 }
9223             }, ed.getBody());
9224         },
9225
9226         mceSelectNode : function(u, v) {
9227             this.editor.selection.select(v);
9228         },
9229
9230         mceInsertContent : function(ui, val) {
9231             this.editor.selection.setContent(val);
9232         },
9233
9234         mceInsertRawHTML : function(ui, val) {
9235             var ed = this.editor;
9236
9237             ed.selection.setContent('tiny_mce_marker');
9238             ed.setContent(ed.getContent().replace(/tiny_mce_marker/g, val));
9239         },
9240
9241         mceRepaint : function() {
9242             var s, b, e = this.editor;
9243
9244             if (tinymce.isGecko) {
9245                 try {
9246                     s = e.selection;
9247                     b = s.getBookmark(true);
9248
9249                     if (s.getSel())
9250                         s.getSel().selectAllChildren(e.getBody());
9251
9252                     s.collapse(true);
9253                     s.moveToBookmark(b);
9254                 } catch (ex) {
9255                     // Ignore
9256                 }
9257             }
9258         },
9259
9260         queryStateUnderline : function() {
18240a 9261             var ed = this.editor, n = ed.selection.getNode();
d9344f 9262
S 9263             if (n && n.nodeName == 'A')
9264                 return false;
9265
9266             return this._queryState('Underline');
9267         },
9268
9269         queryStateOutdent : function() {
9270             var ed = this.editor, n;
9271
9272             if (ed.settings.inline_styles) {
9273                 if ((n = ed.dom.getParent(ed.selection.getStart(), ed.dom.isBlock)) && parseInt(n.style.paddingLeft) > 0)
9274                     return true;
9275
9276                 if ((n = ed.dom.getParent(ed.selection.getEnd(), ed.dom.isBlock)) && parseInt(n.style.paddingLeft) > 0)
9277                     return true;
9278             } else
9279                 return !!ed.dom.getParent(ed.selection.getNode(), 'BLOCKQUOTE');
9280
9281             return this.queryStateInsertUnorderedList() || this.queryStateInsertOrderedList();
9282         },
9283
9284         queryStateInsertUnorderedList : function() {
9285             return this.editor.dom.getParent(this.editor.selection.getNode(), 'UL');
9286         },
9287
9288         queryStateInsertOrderedList : function() {
9289             return this.editor.dom.getParent(this.editor.selection.getNode(), 'OL');
9290         },
9291
9292         queryStatemceBlockQuote : function() {
9293             return !!this.editor.dom.getParent(this.editor.selection.getStart(), function(n) {return n.nodeName === 'BLOCKQUOTE';});
9294         },
9295
9296         mceBlockQuote : function() {
9297             var t = this, ed = t.editor, s = ed.selection, dom = ed.dom, sb, eb, n, bm, bq, r, bq2, i, nl;
9298
9299             function getBQ(e) {
9300                 return dom.getParent(e, function(n) {return n.nodeName === 'BLOCKQUOTE';});
9301             };
9302
9303             // Get start/end block
9304             sb = dom.getParent(s.getStart(), dom.isBlock);
9305             eb = dom.getParent(s.getEnd(), dom.isBlock);
9306
9307             // Remove blockquote(s)
9308             if (bq = getBQ(sb)) {
9309                 if (sb != eb || sb.childNodes.length > 1 || (sb.childNodes.length == 1 && sb.firstChild.nodeName != 'BR'))
9310                     bm = s.getBookmark();
9311
9312                 // Move all elements after the end block into new bq
9313                 if (getBQ(eb)) {
9314                     bq2 = bq.cloneNode(false);
9315
9316                     while (n = eb.nextSibling)
9317                         bq2.appendChild(n.parentNode.removeChild(n));
9318                 }
9319
9320                 // Add new bq after
9321                 if (bq2)
9322                     dom.insertAfter(bq2, bq);
9323
9324                 // Move all selected blocks after the current bq
9325                 nl = t._getSelectedBlocks(sb, eb);
9326                 for (i = nl.length - 1; i >= 0; i--) {
9327                     dom.insertAfter(nl[i], bq);
9328                 }
9329
9330                 // Empty bq, then remove it
9331                 if (/^\s*$/.test(bq.innerHTML))
9332                     dom.remove(bq, 1); // Keep children so boomark restoration works correctly
9333
9334                 // Empty bq, then remote it
9335                 if (bq2 && /^\s*$/.test(bq2.innerHTML))
9336                     dom.remove(bq2, 1); // Keep children so boomark restoration works correctly
9337
9338                 if (!bm) {
9339                     // Move caret inside empty block element
9340                     if (!isIE) {
9341                         r = ed.getDoc().createRange();
9342                         r.setStart(sb, 0);
9343                         r.setEnd(sb, 0);
9344                         s.setRng(r);
9345                     } else {
9346                         s.select(sb);
9347                         s.collapse(0);
9348
9349                         // IE misses the empty block some times element so we must move back the caret
9350                         if (dom.getParent(s.getStart(), dom.isBlock) != sb) {
9351                             r = s.getRng();
9352                             r.move('character', -1);
9353                             r.select();
9354                         }
9355                     }
9356                 } else
9357                     t.editor.selection.moveToBookmark(bm);
9358
9359                 return;
9360             }
9361
9362             // Since IE can start with a totally empty document we need to add the first bq and paragraph
9363             if (isIE && !sb && !eb) {
9364                 t.editor.getDoc().execCommand('Indent');
9365                 n = getBQ(s.getNode());
9366                 n.style.margin = n.dir = ''; // IE adds margin and dir to bq
9367                 return;
9368             }
9369
9370             if (!sb || !eb)
9371                 return;
9372
9373             // If empty paragraph node then do not use bookmark
9374             if (sb != eb || sb.childNodes.length > 1 || (sb.childNodes.length == 1 && sb.firstChild.nodeName != 'BR'))
9375                 bm = s.getBookmark();
9376
9377             // Move selected block elements into a bq
9378             each(t._getSelectedBlocks(getBQ(s.getStart()), getBQ(s.getEnd())), function(e) {
9379                 // Found existing BQ add to this one
9380                 if (e.nodeName == 'BLOCKQUOTE' && !bq) {
9381                     bq = e;
9382                     return;
9383                 }
9384
9385                 // No BQ found, create one
9386                 if (!bq) {
9387                     bq = dom.create('blockquote');
9388                     e.parentNode.insertBefore(bq, e);
9389                 }
9390
9391                 // Add children from existing BQ
9392                 if (e.nodeName == 'BLOCKQUOTE' && bq) {
9393                     n = e.firstChild;
9394
9395                     while (n) {
9396                         bq.appendChild(n.cloneNode(true));
9397                         n = n.nextSibling;
9398                     }
9399
9400                     dom.remove(e);
9401                     return;
9402                 }
9403
9404                 // Add non BQ element to BQ
9405                 bq.appendChild(dom.remove(e));
9406             });
9407
9408             if (!bm) {
9409                 // Move caret inside empty block element
9410                 if (!isIE) {
9411                     r = ed.getDoc().createRange();
9412                     r.setStart(sb, 0);
9413                     r.setEnd(sb, 0);
9414                     s.setRng(r);
9415                 } else {
9416                     s.select(sb);
9417                     s.collapse(1);
9418                 }
9419             } else
9420                 s.moveToBookmark(bm);
9421         },
9422 /*
9423         _mceBlockQuote : function() {
9424             var t = this, s = t.editor.selection, b = s.getBookmark(), bq, dom = t.editor.dom;
9425
9426             function findBQ(e) {
9427                 return dom.getParent(e, function(n) {return n.nodeName === 'BLOCKQUOTE';});
9428             };
9429
9430             // Remove blockquote(s)
9431             if (findBQ(s.getStart())) {
9432                 each(t._getSelectedBlocks(findBQ(s.getStart()), findBQ(s.getEnd())), function(e) {
9433                     // Found BQ lets remove it
9434                     if (e.nodeName == 'BLOCKQUOTE')
9435                         dom.remove(e, 1);
9436                 });
9437
9438                 t.editor.selection.moveToBookmark(b);
9439                 return;
9440             }
9441
9442             each(t._getSelectedBlocks(findBQ(s.getStart()), findBQ(s.getEnd())), function(e) {
9443                 var n;
9444
9445                 // Found existing BQ add to this one
9446                 if (e.nodeName == 'BLOCKQUOTE' && !bq) {
9447                     bq = e;
9448                     return;
9449                 }
9450
9451                 // No BQ found, create one
9452                 if (!bq) {
9453                     bq = dom.create('blockquote');
9454                     e.parentNode.insertBefore(bq, e);
9455                 }
9456
9457                 // Add children from existing BQ
9458                 if (e.nodeName == 'BLOCKQUOTE' && bq) {
9459                     n = e.firstChild;
9460
9461                     while (n) {
9462                         bq.appendChild(n.cloneNode(true));
9463                         n = n.nextSibling;
9464                     }
9465
9466                     dom.remove(e);
9467
9468                     return;
9469                 }
9470
9471                 // Add non BQ element to BQ
9472                 bq.appendChild(dom.remove(e));
9473             });
9474
9475             t.editor.selection.moveToBookmark(b);
9476         },
9477 */
9478         _getSelectedBlocks : function(st, en) {
9479             var ed = this.editor, dom = ed.dom, s = ed.selection, sb, eb, n, bl = [];
9480
9481             sb = dom.getParent(st || s.getStart(), dom.isBlock);
9482             eb = dom.getParent(en || s.getEnd(), dom.isBlock);
9483
9484             if (sb)
9485                 bl.push(sb);
9486
9487             if (sb && eb && sb != eb) {
9488                 n = sb;
9489
9490                 while ((n = n.nextSibling) && n != eb) {
9491                     if (dom.isBlock(n))
9492                         bl.push(n);
9493                 }
9494             }
9495
9496             if (eb && sb != eb)
9497                 bl.push(eb);
9498
9499             return bl;
9500         }
9501     });
9502 })();
9503
9504
9505 /* file:jscripts/tiny_mce/classes/UndoManager.js */
9506
9507 tinymce.create('tinymce.UndoManager', {
9508     index : 0,
9509     data : null,
9510     typing : 0,
9511
9512     UndoManager : function(ed) {
9513         var t = this, Dispatcher = tinymce.util.Dispatcher;
9514
9515         t.editor = ed;
9516         t.data = [];
9517         t.onAdd = new Dispatcher(this);
9518         t.onUndo = new Dispatcher(this);
9519         t.onRedo = new Dispatcher(this);
9520     },
9521
9522     add : function(l) {
9523         var t = this, i, ed = t.editor, b, s = ed.settings, la;
9524
9525         l = l || {};
9526         l.content = l.content || ed.getContent({format : 'raw', no_events : 1});
9527
9528         // Add undo level if needed
9529         l.content = l.content.replace(/^\s*|\s*$/g, '');
18240a 9530         la = t.data[t.index > 0 && (t.index == 0 || t.index == t.data.length) ? t.index - 1 : t.index];
d9344f 9531         if (!l.initial && la && l.content == la.content)
S 9532             return null;
9533
9534         // Time to compress
9535         if (s.custom_undo_redo_levels) {
9536             if (t.data.length > s.custom_undo_redo_levels) {
9537                 for (i = 0; i < t.data.length - 1; i++)
9538                     t.data[i] = t.data[i + 1];
9539
9540                 t.data.length--;
9541                 t.index = t.data.length;
9542             }
9543         }
9544
9545         if (s.custom_undo_redo_restore_selection && !l.initial)
9546             l.bookmark = b = l.bookmark || ed.selection.getBookmark();
9547
18240a 9548         if (t.index < t.data.length)
d9344f 9549             t.index++;
18240a 9550
A 9551         // Only initial marked undo levels should be allowed as first item
9552         // This to workaround a bug with Firefox and the blur event
9553         if (t.data.length === 0 && !l.initial)
9554             return null;
d9344f 9555
S 9556         // Add level
9557         t.data.length = t.index + 1;
9558         t.data[t.index++] = l;
9559
9560         if (l.initial)
9561             t.index = 0;
9562
9563         // Set initial bookmark use first real undo level
9564         if (t.data.length == 2 && t.data[0].initial)
9565             t.data[0].bookmark = b;
9566
9567         t.onAdd.dispatch(t, l);
9568         ed.isNotDirty = 0;
9569
9570         //console.dir(t.data);
9571
9572         return l;
9573     },
9574
9575     undo : function() {
9576         var t = this, ed = t.editor, l = l, i;
9577
9578         if (t.typing) {
9579             t.add();
9580             t.typing = 0;
9581         }
9582
9583         if (t.index > 0) {
9584             // If undo on last index then take snapshot
9585             if (t.index == t.data.length && t.index > 1) {
9586                 i = t.index;
9587                 t.typing = 0;
9588
9589                 if (!t.add())
9590                     t.index = i;
9591
9592                 --t.index;
9593             }
9594
9595             l = t.data[--t.index];
9596             ed.setContent(l.content, {format : 'raw'});
9597             ed.selection.moveToBookmark(l.bookmark);
9598
9599             t.onUndo.dispatch(t, l);
9600         }
9601
9602         return l;
9603     },
9604
9605     redo : function() {
9606         var t = this, ed = t.editor, l = null;
9607
9608         if (t.index < t.data.length - 1) {
9609             l = t.data[++t.index];
9610             ed.setContent(l.content, {format : 'raw'});
9611             ed.selection.moveToBookmark(l.bookmark);
9612
9613             t.onRedo.dispatch(t, l);
9614         }
9615
9616         return l;
9617     },
9618
9619     clear : function() {
9620         var t = this;
9621
9622         t.data = [];
9623         t.index = 0;
9624         t.typing = 0;
9625         t.add({initial : true});
9626     },
9627
9628     hasUndo : function() {
9629         return this.index != 0 || this.typing;
9630     },
9631
9632     hasRedo : function() {
9633         return this.index < this.data.length - 1;
9634     }
9635
9636     });
9637 /* file:jscripts/tiny_mce/classes/ForceBlocks.js */
9638
9639 (function() {
9640     // Shorten names
9641     var Event, isIE, isGecko, isOpera, each, extend;
9642
9643     Event = tinymce.dom.Event;
9644     isIE = tinymce.isIE;
9645     isGecko = tinymce.isGecko;
9646     isOpera = tinymce.isOpera;
9647     each = tinymce.each;
9648     extend = tinymce.extend;
9649
9650     tinymce.create('tinymce.ForceBlocks', {
9651         ForceBlocks : function(ed) {
9652             var t = this, s = ed.settings, elm;
9653
9654             t.editor = ed;
9655             t.dom = ed.dom;
9656             elm = (s.forced_root_block || 'p').toLowerCase();
9657             s.element = elm.toUpperCase();
9658
9659             ed.onPreInit.add(t.setup, t);
9660
9661             t.reOpera = new RegExp('(\\u00a0|&#160;|&nbsp;)<\/' + elm + '>', 'gi');
9662             t.rePadd = new RegExp('<p( )([^>]+)><\\\/p>|<p( )([^>]+)\\\/>|<p( )([^>]+)>\\s+<\\\/p>|<p><\\\/p>|<p\\\/>|<p>\\s+<\\\/p>'.replace(/p/g, elm), 'gi');
9663             t.reNbsp2BR1 = new RegExp('<p( )([^>]+)>[\\s\\u00a0]+<\\\/p>|<p>[\\s\\u00a0]+<\\\/p>'.replace(/p/g, elm), 'gi');
9664             t.reNbsp2BR2 = new RegExp('<p( )([^>]+)>(&nbsp;|&#160;)<\\\/p>|<p>(&nbsp;|&#160;)<\\\/p>'.replace(/p/g, elm), 'gi');
9665             t.reBR2Nbsp = new RegExp('<p( )([^>]+)>\\s*<br \\\/>\\s*<\\\/p>|<p>\\s*<br \\\/>\\s*<\\\/p>'.replace(/p/g, elm), 'gi');
9666             t.reTrailBr = new RegExp('\\s*<br \\/>\\s*<\\\/p>'.replace(/p/g, elm), 'gi');
9667
9668             function padd(ed, o) {
9669                 if (isOpera)
9670                     o.content = o.content.replace(t.reOpera, '</' + elm + '>');
9671
9672                 o.content = o.content.replace(t.rePadd, '<' + elm + '$1$2$3$4$5$6>\u00a0</' + elm + '>');
9673
9674                 if (!isIE && !isOpera && o.set) {
9675                     // Use &nbsp; instead of BR in padded paragraphs
9676                     o.content = o.content.replace(t.reNbsp2BR1, '<' + elm + '$1$2><br /></' + elm + '>');
9677                     o.content = o.content.replace(t.reNbsp2BR2, '<' + elm + '$1$2><br /></' + elm + '>');
9678                 } else {
9679                     o.content = o.content.replace(t.reBR2Nbsp, '<' + elm + '$1$2>\u00a0</' + elm + '>');
9680                     o.content = o.content.replace(t.reTrailBr, '</' + elm + '>');
9681                 }
9682             };
9683
9684             ed.onBeforeSetContent.add(padd);
9685             ed.onPostProcess.add(padd);
9686
9687             if (s.forced_root_block) {
9688                 ed.onInit.add(t.forceRoots, t);
9689                 ed.onSetContent.add(t.forceRoots, t);
9690                 ed.onBeforeGetContent.add(t.forceRoots, t);
9691             }
9692         },
9693
9694         setup : function() {
9695             var t = this, ed = t.editor, s = ed.settings;
9696
9697             // Force root blocks when typing and when getting output
9698             if (s.forced_root_block) {
9699                 ed.onKeyUp.add(t.forceRoots, t);
9700                 ed.onPreProcess.add(t.forceRoots, t);
9701             }
9702
9703             if (s.force_br_newlines) {
9704                 // Force IE to produce BRs on enter
9705                 if (isIE) {
9706                     ed.onKeyPress.add(function(ed, e) {
9707                         var n, s = ed.selection;
9708
9709                         if (e.keyCode == 13 && s.getNode().nodeName != 'LI') {
9710                             s.setContent('<br id="__" /> ', {format : 'raw'});
9711                             n = ed.dom.get('__');
9712                             n.removeAttribute('id');
9713                             s.select(n);
9714                             s.collapse();
9715                             return Event.cancel(e);
9716                         }
9717                     });
9718                 }
9719
9720                 return;
9721             }
9722
9723             if (!isIE && s.force_p_newlines) {
9724 /*                ed.onPreProcess.add(function(ed, o) {
9725                     each(ed.dom.select('br', o.node), function(n) {
9726                         var p = n.parentNode;
9727
9728                         // Replace <p><br /></p> with <p>&nbsp;</p>
9729                         if (p && p.nodeName == 'p' && (p.childNodes.length == 1 || p.lastChild == n)) {
9730                             p.replaceChild(ed.getDoc().createTextNode('\u00a0'), n);
9731                         }
9732                     });
9733                 });*/
9734
9735                 ed.onKeyPress.add(function(ed, e) {
9736                     if (e.keyCode == 13 && !e.shiftKey) {
9737                         if (!t.insertPara(e))
9738                             Event.cancel(e);
9739                     }
9740                 });
9741
9742                 if (isGecko) {
9743                     ed.onKeyDown.add(function(ed, e) {
9744                         if ((e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey)
9745                             t.backspaceDelete(e, e.keyCode == 8);
9746                     });
9747                 }
9748             }
9749
9750             function ren(rn, na) {
9751                 var ne = ed.dom.create(na);
9752
9753                 each(rn.attributes, function(a) {
9754                     if (a.specified && a.nodeValue)
9755                         ne.setAttribute(a.nodeName.toLowerCase(), a.nodeValue);
9756                 });
9757
9758                 each(rn.childNodes, function(n) {
9759                     ne.appendChild(n.cloneNode(true));
9760                 });
9761
9762                 rn.parentNode.replaceChild(ne, rn);
9763
9764                 return ne;
9765             };
9766
9767             // Replaces IE:s auto generated paragraphs with the specified element name
9768             if (isIE && s.element != 'P') {
9769                 ed.onKeyPress.add(function(ed, e) {
9770                     t.lastElm = ed.selection.getNode().nodeName;
9771                 });
9772
9773                 ed.onKeyUp.add(function(ed, e) {
9774                     var bl, sel = ed.selection, n = sel.getNode(), b = ed.getBody();
9775
9776                     if (b.childNodes.length === 1 && n.nodeName == 'P') {
9777                         n = ren(n, s.element);
9778                         sel.select(n);
9779                         sel.collapse();
9780                         ed.nodeChanged();
9781                     } else if (e.keyCode == 13 && !e.shiftKey && t.lastElm != 'P') {
9782                         bl = ed.dom.getParent(n, 'P');
9783
9784                         if (bl) {
9785                             ren(bl, s.element);
9786                             ed.nodeChanged();
9787                         }
9788                     }
9789                 });
9790             }
9791         },
9792
9793         find : function(n, t, s) {
9794             var ed = this.editor, w = ed.getDoc().createTreeWalker(n, 4, null, false), c = -1;
9795
9796             while (n = w.nextNode()) {
9797                 c++;
9798
9799                 // Index by node
9800                 if (t == 0 && n == s)
9801                     return c;
9802
9803                 // Node by index
9804                 if (t == 1 && c == s)
9805                     return n;
9806             }
9807
9808             return -1;
9809         },
9810
9811         forceRoots : function(ed, e) {
9812             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;
9813             var nx, bl, bp, sp, le, nl = b.childNodes, i;
9814
9815             // Fix for bug #1863847
9816             if (e && e.keyCode == 13)
9817                 return true;
9818
9819             // Wrap non blocks into blocks
9820             for (i = nl.length - 1; i >= 0; i--) {
9821                 nx = nl[i];
9822
9823                 // Is text or non block element
9824                 if (nx.nodeType == 3 || (!t.dom.isBlock(nx) && nx.nodeType != 8)) {
9825                     if (!bl) {
9826                         // Create new block but ignore whitespace
9827                         if (nx.nodeType != 3 || /[^\s]/g.test(nx.nodeValue)) {
9828                             // Store selection
9829                             if (si == -2 && r) {
9830                                 if (!isIE) {
18240a 9831                                     // If element is inside body, might not be the case in contentEdiable mode
A 9832                                     if (ed.dom.getParent(r.startContainer, function(e) {return e === b;})) {
9833                                         so = r.startOffset;
9834                                         eo = r.endOffset;
9835                                         si = t.find(b, 0, r.startContainer);
9836                                         ei = t.find(b, 0, r.endContainer);
9837                                     }
d9344f 9838                                 } else {
S 9839                                     tr = d.body.createTextRange();
9840                                     tr.moveToElementText(b);
9841                                     tr.collapse(1);
9842                                     bp = tr.move('character', c) * -1;
9843
9844                                     tr = r.duplicate();
9845                                     tr.collapse(1);
9846                                     sp = tr.move('character', c) * -1;
9847
9848                                     tr = r.duplicate();
9849                                     tr.collapse(0);
9850                                     le = (tr.move('character', c) * -1) - sp;
9851
9852                                     si = sp - bp;
9853                                     ei = le;
9854                                 }
9855                             }
9856
9857                             bl = ed.dom.create(ed.settings.forced_root_block);
9858                             bl.appendChild(nx.cloneNode(1));
9859                             nx.parentNode.replaceChild(bl, nx);
9860                         }
9861                     } else {
9862                         if (bl.hasChildNodes())
9863                             bl.insertBefore(nx, bl.firstChild);
9864                         else
9865                             bl.appendChild(nx);
9866                     }
9867                 } else
9868                     bl = null; // Time to create new block
9869             }
9870
9871             // Restore selection
9872             if (si != -2) {
9873                 if (!isIE) {
18240a 9874                     bl = b.getElementsByTagName(ed.settings.element)[0];
d9344f 9875                     r = d.createRange();
S 9876
9877                     // Select last location or generated block
9878                     if (si != -1)
9879                         r.setStart(t.find(b, 1, si), so);
9880                     else
9881                         r.setStart(bl, 0);
9882
9883                     // Select last location or generated block
9884                     if (ei != -1)
9885                         r.setEnd(t.find(b, 1, ei), eo);
9886                     else
9887                         r.setEnd(bl, 0);
9888
9889                     if (s) {
9890                         s.removeAllRanges();
9891                         s.addRange(r);
9892                     }
9893                 } else {
9894                     try {
9895                         r = s.createRange();
9896                         r.moveToElementText(b);
9897                         r.collapse(1);
9898                         r.moveStart('character', si);
9899                         r.moveEnd('character', ei);
9900                         r.select();
9901                     } catch (ex) {
9902                         // Ignore
9903                     }
9904                 }
9905             }
9906         },
9907
9908         getParentBlock : function(n) {
9909             var d = this.dom;
9910
9911             return d.getParent(n, d.isBlock);
9912         },
9913
9914         insertPara : function(e) {
18240a 9915             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;
A 9916             var rb, ra, dir, sn, so, en, eo, sb, eb, bn, bef, aft, sc, ec, n, vp = dom.getViewPort(ed.getWin()), y, ch;
d9344f 9917
S 9918             function isEmpty(n) {
9919                 n = n.innerHTML;
9920                 n = n.replace(/<(img|hr|table)/gi, '-'); // Keep these convert them to - chars
9921                 n = n.replace(/<[^>]+>/g, ''); // Remove all tags
9922
9923                 return n.replace(/[ \t\r\n]+/g, '') == '';
9924             };
9925
9926             // If root blocks are forced then use Operas default behavior since it's really good
9927 // Removed due to bug: #1853816
9928 //            if (se.forced_root_block && isOpera)
9929 //                return true;
9930
9931             // Setup before range
9932             rb = d.createRange();
9933
9934             // If is before the first block element and in body, then move it into first block element
9935             rb.setStart(s.anchorNode, s.anchorOffset);
9936             rb.collapse(true);
9937
9938             // Setup after range
9939             ra = d.createRange();
9940
9941             // If is before the first block element and in body, then move it into first block element
9942             ra.setStart(s.focusNode, s.focusOffset);
9943             ra.collapse(true);
9944
9945             // Setup start/end points
9946             dir = rb.compareBoundaryPoints(rb.START_TO_END, ra) < 0;
9947             sn = dir ? s.anchorNode : s.focusNode;
9948             so = dir ? s.anchorOffset : s.focusOffset;
9949             en = dir ? s.focusNode : s.anchorNode;
9950             eo = dir ? s.focusOffset : s.anchorOffset;
18240a 9951
A 9952             // If selection is in empty table cell
9953             if (sn === en && /^(TD|TH)$/.test(sn.nodeName)) {
9954                 dom.remove(sn.firstChild); // Remove BR
9955
9956                 // Create two new block elements
9957                 ed.dom.add(sn, se.element, null, '<br />');
9958                 aft = ed.dom.add(sn, se.element, null, '<br />');
9959
9960                 // Move caret into the last one
9961                 r = d.createRange();
9962                 r.selectNodeContents(aft);
9963                 r.collapse(1);
9964                 ed.selection.setRng(r);
9965
9966                 return false;
9967             }
d9344f 9968
S 9969             // If the caret is in an invalid location in FF we need to move it into the first block
9970             if (sn == b && en == b && b.firstChild && ed.dom.isBlock(b.firstChild)) {
9971                 sn = en = sn.firstChild;
9972                 so = eo = 0;
9973                 rb = d.createRange();
9974                 rb.setStart(sn, 0);
9975                 ra = d.createRange();
9976                 ra.setStart(en, 0);
9977             }
9978
9979             // Never use body as start or end node
9980             sn = sn.nodeName == "HTML" ? d.body : sn; // Fix for Opera bug: https://bugs.opera.com/show_bug.cgi?id=273224&comments=yes
9981             sn = sn.nodeName == "BODY" ? sn.firstChild : sn;
9982             en = en.nodeName == "HTML" ? d.body : en; // Fix for Opera bug: https://bugs.opera.com/show_bug.cgi?id=273224&comments=yes
9983             en = en.nodeName == "BODY" ? en.firstChild : en;
9984
9985             // Get start and end blocks
9986             sb = t.getParentBlock(sn);
9987             eb = t.getParentBlock(en);
9988             bn = sb ? sb.nodeName : se.element; // Get block name to create
9989
9990             // Return inside list use default browser behavior
9991             if (t.dom.getParent(sb, function(n) { return /OL|UL|PRE/.test(n.nodeName); }))
9992                 return true;
9993
9994             // If caption or absolute layers then always generate new blocks within
9995             if (sb && (sb.nodeName == 'CAPTION' || /absolute|relative|static/gi.test(sb.style.position))) {
9996                 bn = se.element;
9997                 sb = null;
9998             }
9999
10000             // If caption or absolute layers then always generate new blocks within
10001             if (eb && (eb.nodeName == 'CAPTION' || /absolute|relative|static/gi.test(eb.style.position))) {
10002                 bn = se.element;
10003                 eb = null;
10004             }
10005
10006             // Use P instead
10007             if (/(TD|TABLE|TH|CAPTION)/.test(bn) || (sb && bn == "DIV" && /left|right/gi.test(sb.style.cssFloat))) {
10008                 bn = se.element;
10009                 sb = eb = null;
10010             }
10011
10012             // Setup new before and after blocks
10013             bef = (sb && sb.nodeName == bn) ? sb.cloneNode(0) : ed.dom.create(bn);
10014             aft = (eb && eb.nodeName == bn) ? eb.cloneNode(0) : ed.dom.create(bn);
10015
10016             // Remove id from after clone
10017             aft.removeAttribute('id');
10018
10019             // Is header and cursor is at the end, then force paragraph under
10020             if (/^(H[1-6])$/.test(bn) && sn.nodeValue && so == sn.nodeValue.length)
10021                 aft = ed.dom.create(se.element);
10022
10023             // Find start chop node
10024             n = sc = sn;
10025             do {
10026                 if (n == b || n.nodeType == 9 || t.dom.isBlock(n) || /(TD|TABLE|TH|CAPTION)/.test(n.nodeName))
10027                     break;
10028
10029                 sc = n;
10030             } while ((n = n.previousSibling ? n.previousSibling : n.parentNode));
10031
10032             // Find end chop node
10033             n = ec = en;
10034             do {
10035                 if (n == b || n.nodeType == 9 || t.dom.isBlock(n) || /(TD|TABLE|TH|CAPTION)/.test(n.nodeName))
10036                     break;
10037
10038                 ec = n;
10039             } while ((n = n.nextSibling ? n.nextSibling : n.parentNode));
10040
10041             // Place first chop part into before block element
10042             if (sc.nodeName == bn)
10043                 rb.setStart(sc, 0);
10044             else
10045                 rb.setStartBefore(sc);
10046
10047             rb.setEnd(sn, so);
10048             bef.appendChild(rb.cloneContents() || d.createTextNode('')); // Empty text node needed for Safari
10049
10050             // Place secnd chop part within new block element
10051             try {
10052                 ra.setEndAfter(ec);
10053             } catch(ex) {
10054                 //console.debug(s.focusNode, s.focusOffset);
10055             }
10056
10057             ra.setStart(en, eo);
10058             aft.appendChild(ra.cloneContents() || d.createTextNode('')); // Empty text node needed for Safari
10059
10060             // Create range around everything
10061             r = d.createRange();
10062             if (!sc.previousSibling && sc.parentNode.nodeName == bn) {
10063                 r.setStartBefore(sc.parentNode);
10064             } else {
10065                 if (rb.startContainer.nodeName == bn && rb.startOffset == 0)
10066                     r.setStartBefore(rb.startContainer);
10067                 else
10068                     r.setStart(rb.startContainer, rb.startOffset);
10069             }
10070
10071             if (!ec.nextSibling && ec.parentNode.nodeName == bn)
10072                 r.setEndAfter(ec.parentNode);
10073             else
10074                 r.setEnd(ra.endContainer, ra.endOffset);
10075
10076             // Delete and replace it with new block elements
10077             r.deleteContents();
10078
10079             if (isOpera)
10080                 ed.getWin().scrollTo(0, vp.y);
10081
10082             // Never wrap blocks in blocks
10083             if (bef.firstChild && bef.firstChild.nodeName == bn)
10084                 bef.innerHTML = bef.firstChild.innerHTML;
10085
10086             if (aft.firstChild && aft.firstChild.nodeName == bn)
10087                 aft.innerHTML = aft.firstChild.innerHTML;
10088
10089             // Padd empty blocks
10090             if (isEmpty(bef))
10091                 bef.innerHTML = '<br />';
10092
10093             if (isEmpty(aft))
10094                 aft.innerHTML = isOpera ? '&nbsp;' : '<br />'; // Extra space for Opera so that the caret can move there
10095
18240a 10096             // Opera needs this one backwards for older versions
A 10097             if (isOpera && parseFloat(opera.version()) < 9.5) {
d9344f 10098                 r.insertNode(bef);
S 10099                 r.insertNode(aft);
10100             } else {
10101                 r.insertNode(aft);
10102                 r.insertNode(bef);
10103             }
10104
10105             // Normalize
10106             aft.normalize();
10107             bef.normalize();
10108
18240a 10109             function first(n) {
A 10110                 return d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false).nextNode() || n;
10111             };
10112
d9344f 10113             // Move cursor and scroll into view
S 10114             r = d.createRange();
18240a 10115             r.selectNodeContents(isGecko ? first(aft) : aft);
d9344f 10116             r.collapse(1);
S 10117             s.removeAllRanges();
10118             s.addRange(r);
10119
10120             // 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
10121             y = ed.dom.getPos(aft).y;
10122             ch = aft.clientHeight;
10123
10124             // Is element within viewport
10125             if (y < vp.y || y + ch > vp.y + vp.h) {
10126                 ed.getWin().scrollTo(0, y < vp.y ? y : y - vp.h + ch);
10127                 //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));
10128             }
10129
10130             return false;
10131         },
10132
10133         backspaceDelete : function(e, bs) {
10134             var t = this, ed = t.editor, b = ed.getBody(), n, se = ed.selection, r = se.getRng(), sc = r.startContainer, n, w, tn;
10135
10136             // The caret sometimes gets stuck in Gecko if you delete empty paragraphs
10137             // This workaround removes the element by hand and moves the caret to the previous element
10138             if (sc && ed.dom.isBlock(sc) && !/^(TD|TH)$/.test(sc.nodeName) && bs) {
10139                 if (sc.childNodes.length == 0 || (sc.childNodes.length == 1 && sc.firstChild.nodeName == 'BR')) {
10140                     // Find previous block element
10141                     n = sc;
10142                     while ((n = n.previousSibling) && !ed.dom.isBlock(n)) ;
10143
10144                     if (n) {
10145                         if (sc != b.firstChild) {
10146                             // Find last text node
10147                             w = ed.dom.doc.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);
10148                             while (tn = w.nextNode())
10149                                 n = tn;
10150
10151                             // Place caret at the end of last text node
10152                             r = ed.getDoc().createRange();
10153                             r.setStart(n, n.nodeValue ? n.nodeValue.length : 0);
10154                             r.setEnd(n, n.nodeValue ? n.nodeValue.length : 0);
10155                             se.setRng(r);
10156
10157                             // Remove the target container
10158                             ed.dom.remove(sc);
10159                         }
10160
10161                         return Event.cancel(e);
10162                     }
10163                 }
10164             }
10165
10166             // Gecko generates BR elements here and there, we don't like those so lets remove them
10167             function handler(e) {
10168                 e = e.target;
10169
10170                 // A new BR was created in a block element, remove it
10171                 if (e && e.parentNode && e.nodeName == 'BR' && (n = t.getParentBlock(e))) {
10172                     Event.remove(b, 'DOMNodeInserted', handler);
10173
10174                     // Only remove BR elements that got inserted in the middle of the text
10175                     if (e.previousSibling || e.nextSibling)
10176                         ed.dom.remove(e);
10177                 }
10178             };
10179
10180             // Listen for new nodes
10181             Event._add(b, 'DOMNodeInserted', handler);
10182
10183             // Remove listener
10184             window.setTimeout(function() {
10185                 Event._remove(b, 'DOMNodeInserted', handler);
10186             }, 1);
10187         }
10188     });
10189 })();
10190
10191 /* file:jscripts/tiny_mce/classes/ControlManager.js */
10192
10193 (function() {
10194     // Shorten names
10195     var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, extend = tinymce.extend;
10196
10197     tinymce.create('tinymce.ControlManager', {
10198         ControlManager : function(ed, s) {
10199             var t = this, i;
10200
10201             s = s || {};
10202             t.editor = ed;
10203             t.controls = {};
10204             t.onAdd = new tinymce.util.Dispatcher(t);
10205             t.onPostRender = new tinymce.util.Dispatcher(t);
10206             t.prefix = s.prefix || ed.id + '_';
10207             t._cls = {};
10208
10209             t.onPostRender.add(function() {
10210                 each(t.controls, function(c) {
10211                     c.postRender();
10212                 });
10213             });
10214         },
10215
10216         get : function(id) {
10217             return this.controls[this.prefix + id] || this.controls[id];
10218         },
10219
10220         setActive : function(id, s) {
10221             var c = null;
10222
10223             if (c = this.get(id))
10224                 c.setActive(s);
10225
10226             return c;
10227         },
10228
10229         setDisabled : function(id, s) {
10230             var c = null;
10231
10232             if (c = this.get(id))
10233                 c.setDisabled(s);
10234
10235             return c;
10236         },
10237
10238         add : function(c) {
10239             var t = this;
10240
10241             if (c) {
10242                 t.controls[c.id] = c;
10243                 t.onAdd.dispatch(c, t);
10244             }
10245
10246             return c;
10247         },
10248
10249         createControl : function(n) {
10250             var c, t = this, ed = t.editor;
10251
10252             each(ed.plugins, function(p) {
10253                 if (p.createControl) {
10254                     c = p.createControl(n, t);
10255
10256                     if (c)
10257                         return false;
10258                 }
10259             });
10260
10261             switch (n) {
10262                 case "|":
10263                 case "separator":
10264                     return t.createSeparator();
10265             }
10266
10267             if (!c && ed.buttons && (c = ed.buttons[n]))
10268                 return t.createButton(n, c);
10269
10270             return t.add(c);
10271         },
10272
10273         createDropMenu : function(id, s, cc) {
10274             var t = this, ed = t.editor, c, bm, v, cls;
10275
10276             s = extend({
10277                 'class' : 'mceDropDown',
10278                 constrain : ed.settings.constrain_menus
10279             }, s);
10280
10281             s['class'] = s['class'] + ' ' + ed.getParam('skin') + 'Skin';
10282             if (v = ed.getParam('skin_variant'))
10283                 s['class'] += ' ' + ed.getParam('skin') + 'Skin' + v.substring(0, 1).toUpperCase() + v.substring(1);
10284
10285             id = t.prefix + id;
10286             cls = cc || t._cls.dropmenu || tinymce.ui.DropMenu;
10287             c = t.controls[id] = new cls(id, s);
10288             c.onAddItem.add(function(c, o) {
10289                 var s = o.settings;
10290
10291                 s.title = ed.getLang(s.title, s.title);
10292
10293                 if (!s.onclick) {
10294                     s.onclick = function(v) {
10295                         ed.execCommand(s.cmd, s.ui || false, s.value);
10296                     };
10297                 }
10298             });
10299
10300             ed.onRemove.add(function() {
10301                 c.destroy();
10302             });
10303
10304             // Fix for bug #1897785, #1898007
10305             if (tinymce.isIE) {
10306                 c.onShowMenu.add(function() {
18240a 10307                     bm = ed.selection.getBookmark(1);
d9344f 10308                 });
S 10309
10310                 c.onHideMenu.add(function() {
10311                     if (bm)
10312                         ed.selection.moveToBookmark(bm);
10313                 });
10314             }
10315
10316             return t.add(c);
10317         },
10318
10319         createListBox : function(id, s, cc) {
10320             var t = this, ed = t.editor, cmd, c, cls;
10321
10322             if (t.get(id))
10323                 return null;
10324
10325             s.title = ed.translate(s.title);
10326             s.scope = s.scope || ed;
10327
10328             if (!s.onselect) {
10329                 s.onselect = function(v) {
10330                     ed.execCommand(s.cmd, s.ui || false, v || s.value);
10331                 };
10332             }
10333
10334             s = extend({
10335                 title : s.title,
10336                 'class' : 'mce_' + id,
10337                 scope : s.scope,
10338                 control_manager : t
10339             }, s);
10340
10341             id = t.prefix + id;
10342
10343             if (ed.settings.use_native_selects)
10344                 c = new tinymce.ui.NativeListBox(id, s);
10345             else {
10346                 cls = cc || t._cls.listbox || tinymce.ui.ListBox;
10347                 c = new cls(id, s);
10348             }
10349
10350             t.controls[id] = c;
10351
10352             // Fix focus problem in Safari
10353             if (tinymce.isWebKit) {
10354                 c.onPostRender.add(function(c, n) {
10355                     // Store bookmark on mousedown
10356                     Event.add(n, 'mousedown', function() {
10357                         ed.bookmark = ed.selection.getBookmark('simple');
10358                     });
10359
10360                     // Restore on focus, since it might be lost
10361                     Event.add(n, 'focus', function() {
10362                         ed.selection.moveToBookmark(ed.bookmark);
10363                         ed.bookmark = null;
10364                     });
10365                 });
10366             }
10367
10368             if (c.hideMenu)
10369                 ed.onMouseDown.add(c.hideMenu, c);
10370
10371             return t.add(c);
10372         },
10373
10374         createButton : function(id, s, cc) {
10375             var t = this, ed = t.editor, o, c, cls;
10376
10377             if (t.get(id))
10378                 return null;
10379
10380             s.title = ed.translate(s.title);
18240a 10381             s.label = ed.translate(s.label);
d9344f 10382             s.scope = s.scope || ed;
S 10383
10384             if (!s.onclick && !s.menu_button) {
10385                 s.onclick = function() {
10386                     ed.execCommand(s.cmd, s.ui || false, s.value);
10387                 };
10388             }
10389
10390             s = extend({
10391                 title : s.title,
10392                 'class' : 'mce_' + id,
10393                 unavailable_prefix : ed.getLang('unavailable', ''),
10394                 scope : s.scope,
10395                 control_manager : t
10396             }, s);
10397
10398             id = t.prefix + id;
10399
10400             if (s.menu_button) {
10401                 cls = cc || t._cls.menubutton || tinymce.ui.MenuButton;
10402                 c = new cls(id, s);
10403                 ed.onMouseDown.add(c.hideMenu, c);
10404             } else {
10405                 cls = t._cls.button || tinymce.ui.Button;
10406                 c = new cls(id, s);
10407             }
10408
10409             return t.add(c);
10410         },
10411
10412         createMenuButton : function(id, s) {
10413             s = s || {};
10414             s.menu_button = 1;
10415
10416             return this.createButton(id, s);
10417         },
10418
10419         createSplitButton : function(id, s, cc) {
10420             var t = this, ed = t.editor, cmd, c, cls;
10421
10422             if (t.get(id))
10423                 return null;
10424
10425             s.title = ed.translate(s.title);
10426             s.scope = s.scope || ed;
10427
10428             if (!s.onclick) {
10429                 s.onclick = function(v) {
10430                     ed.execCommand(s.cmd, s.ui || false, v || s.value);
10431                 };
10432             }
10433
10434             if (!s.onselect) {
10435                 s.onselect = function(v) {
10436                     ed.execCommand(s.cmd, s.ui || false, v || s.value);
10437                 };
10438             }
10439
10440             s = extend({
10441                 title : s.title,
10442                 'class' : 'mce_' + id,
10443                 scope : s.scope,
10444                 control_manager : t
10445             }, s);
10446
10447             id = t.prefix + id;
10448             cls = cc || t._cls.splitbutton || tinymce.ui.SplitButton;
10449             c = t.add(new cls(id, s));
10450             ed.onMouseDown.add(c.hideMenu, c);
10451
10452             return c;
10453         },
10454
10455         createColorSplitButton : function(id, s, cc) {
18240a 10456             var t = this, ed = t.editor, cmd, c, cls, bm;
d9344f 10457
S 10458             if (t.get(id))
10459                 return null;
10460
10461             s.title = ed.translate(s.title);
10462             s.scope = s.scope || ed;
10463
10464             if (!s.onclick) {
10465                 s.onclick = function(v) {
10466                     ed.execCommand(s.cmd, s.ui || false, v || s.value);
10467                 };
10468             }
10469
10470             if (!s.onselect) {
10471                 s.onselect = function(v) {
10472                     ed.execCommand(s.cmd, s.ui || false, v || s.value);
10473                 };
10474             }
10475
10476             s = extend({
10477                 title : s.title,
10478                 'class' : 'mce_' + id,
10479                 'menu_class' : ed.getParam('skin') + 'Skin',
10480                 scope : s.scope,
10481                 more_colors_title : ed.getLang('more_colors')
10482             }, s);
10483
10484             id = t.prefix + id;
10485             cls = cc || t._cls.colorsplitbutton || tinymce.ui.ColorSplitButton;
10486             c = new cls(id, s);
10487             ed.onMouseDown.add(c.hideMenu, c);
10488
10489             // Remove the menu element when the editor is removed
10490             ed.onRemove.add(function() {
10491                 c.destroy();
10492             });
18240a 10493
A 10494             // Fix for bug #1897785, #1898007
10495             if (tinymce.isIE) {
10496                 c.onShowMenu.add(function() {
10497                     bm = ed.selection.getBookmark(1);
10498                 });
10499
10500                 c.onHideMenu.add(function() {
10501                     if (bm) {
10502                         ed.selection.moveToBookmark(bm);
10503                         bm = 0;
10504                     }
10505                 });
10506             }
d9344f 10507
S 10508             return t.add(c);
10509         },
10510
10511         createToolbar : function(id, s, cc) {
10512             var c, t = this, cls;
10513
10514             id = t.prefix + id;
10515             cls = cc || t._cls.toolbar || tinymce.ui.Toolbar;
10516             c = new cls(id, s);
10517
10518             if (t.get(id))
10519                 return null;
10520
10521             return t.add(c);
10522         },
10523
10524         createSeparator : function(cc) {
10525             var cls = cc || this._cls.separator || tinymce.ui.Separator;
10526
10527             return new cls();
10528         },
10529
10530         setControlType : function(n, c) {
10531             return this._cls[n.toLowerCase()] = c;
10532         },
10533
10534         destroy : function() {
10535             each(this.controls, function(c) {
10536                 c.destroy();
10537             });
10538
10539             this.controls = null;
10540         }
10541
10542         });
10543 })();
10544
10545 /* file:jscripts/tiny_mce/classes/WindowManager.js */
10546
10547 (function() {
10548     var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each, isIE = tinymce.isIE, isOpera = tinymce.isOpera;
10549
10550     tinymce.create('tinymce.WindowManager', {
10551         WindowManager : function(ed) {
10552             var t = this;
10553
10554             t.editor = ed;
10555             t.onOpen = new Dispatcher(t);
10556             t.onClose = new Dispatcher(t);
10557             t.params = {};
10558             t.features = {};
10559         },
10560
10561         open : function(s, p) {
10562             var t = this, f = '', x, y, mo = t.editor.settings.dialog_type == 'modal', w, sw, sh, vp = tinymce.DOM.getViewPort(), u;
10563
10564             // Default some options
10565             s = s || {};
10566             p = p || {};
10567             sw = isOpera ? vp.w : screen.width; // Opera uses windows inside the Opera window
10568             sh = isOpera ? vp.h : screen.height;
10569             s.name = s.name || 'mc_' + new Date().getTime();
10570             s.width = parseInt(s.width || 320);
10571             s.height = parseInt(s.height || 240);
10572             s.resizable = true;
10573             s.left = s.left || parseInt(sw / 2.0) - (s.width / 2.0);
10574             s.top = s.top || parseInt(sh / 2.0) - (s.height / 2.0);
10575             p.inline = false;
10576             p.mce_width = s.width;
10577             p.mce_height = s.height;
10578             p.mce_auto_focus = s.auto_focus;
10579
10580             if (mo) {
10581                 if (isIE) {
10582                     s.center = true;
10583                     s.help = false;
10584                     s.dialogWidth = s.width + 'px';
10585                     s.dialogHeight = s.height + 'px';
10586                     s.scroll = s.scrollbars || false;
18240a 10587                 }
d9344f 10588             }
S 10589
10590             // Build features string
10591             each(s, function(v, k) {
10592                 if (tinymce.is(v, 'boolean'))
10593                     v = v ? 'yes' : 'no';
10594
10595                 if (!/^(name|url)$/.test(k)) {
10596                     if (isIE && mo)
10597                         f += (f ? ';' : '') + k + ':' + v;
10598                     else
10599                         f += (f ? ',' : '') + k + '=' + v;
10600                 }
10601             });
10602
10603             t.features = s;
10604             t.params = p;
10605             t.onOpen.dispatch(t, s, p);
10606
10607             u = s.url || s.file;
10608             if (tinymce.relaxedDomain)
10609                 u += (u.indexOf('?') == -1 ? '?' : '&') + 'mce_rdomain=' + tinymce.relaxedDomain;
10610
18240a 10611             u = tinymce._addVer(u);
A 10612
d9344f 10613             try {
S 10614                 if (isIE && mo) {
10615                     w = 1;
18240a 10616                     window.showModalDialog(u, window, f);
d9344f 10617                 } else
S 10618                     w = window.open(u, s.name, f);
10619             } catch (ex) {
10620                 // Ignore
10621             }
10622
10623             if (!w)
10624                 alert(t.editor.getLang('popup_blocked'));
10625         },
10626
10627         close : function(w) {
10628             w.close();
10629             this.onClose.dispatch(this);
10630         },
10631
10632         createInstance : function(cl, a, b, c, d, e) {
10633             var f = tinymce.resolve(cl);
10634
10635             return new f(a, b, c, d, e);
10636         },
10637
10638         confirm : function(t, cb, s) {
10639             cb.call(s || this, confirm(this._decode(this.editor.getLang(t, t))));
10640         },
10641
10642         alert : function(tx, cb, s) {
10643             var t = this;
10644     
10645             alert(t._decode(t.editor.getLang(tx, tx)));
10646
10647             if (cb)
10648                 cb.call(s || t);
10649         },
10650
10651         // Internal functions
10652
10653         _decode : function(s) {
10654             return tinymce.DOM.decode(s).replace(/\\n/g, '\n');
10655         }
10656
10657         });
10658 }());