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