PageSourceSearch

https://pravo812.ru/js/editor/editor.js

js pravo812.ru collected 2026-10-08 15:01:24 UTC 52,772 bytes, 1,828 lines download raw bytes

1	__lang = {
2		bold: 'Жирный',
3		italic: 'Курсивный',
4		underline: 'Подчеркнутый',
5		marker_list: 'Маркированный список',
6		numeric_list: 'Нумерованный список',
7		outdent: 'Уменьшить отступ',
8		indent: 'Увеличить отступ',
9		align_left: 'Выровнять по левому краю',
10		align_center: 'Выровнять по центру',
11		align_right: 'Выровнять по правому краю',
12		align_justify: 'Выровнять по ширине',
13		add_link: 'Добавить ссылку',
14		remove_link: 'Удалить ссылку',
15		format: 'Формат',
16		paragraph: 'Параграф',
17		h1: 'Заголовок',
18		h2: 'Подзаголовок',
19		addLink: 'Добавить ссылку'
20	};
21
22	var bkExtend = function() {
23		var args = arguments;
24
25		if(args.length == 1) {
26			args = [this, args[0]];
27		}
28
29		for(var prop in args[1]) {
30			args[0][prop] = args[1][prop];
31		}
32
33		return args[0];
34	};
35
36	function bkClass() { }
37
38	bkClass.prototype.construct = function() {};
39
40	bkClass.extend = function(def) {
41		var classDef = function() {
42			if (arguments[0] !== bkClass) {
43				return this.construct.apply(this, arguments);
44			}
45		};
46
47		var proto = new this(bkClass);
48
49		bkExtend(proto, def);
50
51		classDef.prototype = proto;
52		classDef.extend = this.extend;
53
54		return classDef;
55	};
56
57	var bkElement = bkClass.extend({
58		construct : function(elm,d) {
59			if(typeof(elm) == "string") {
60				elm = (d || document).createElement(elm);
61			}
62			elm = $BK(elm);
63			return elm;
64		},
65
66		appendTo : function(elm) {
67			elm.appendChild(this);
68			return this;
69		},
70
71		appendBefore : function(elm) {
72			elm.parentNode.insertBefore(this,elm);
73			return this;
74		},
75
76		addEvent : function(type, fn) {
77			bkLib.addEvent(this,type,fn);
78			return this;
79		},
80
81		setContent : function(c) {
82			this.innerHTML = c;
83			return this;
84		},
85
86		pos : function() {
87			var curleft = curtop = 0;
88			var o = obj = this;
89			if (obj.offsetParent) {
90				do {
91					curleft += obj.offsetLeft;
92					curtop += obj.offsetTop;
93				} while (obj = obj.offsetParent);
94			}
95			var b = (!window.opera) ? parseInt(this.getStyle('border-width') || this.style.border) || 0 : 0;
96			return [curleft+b,curtop+b+this.offsetHeight];
97		},
98
99		noSelect : function() {
100			bkLib.noSelect(this);
101			return this;
102		},
103
104		parentTag : function(t) {
105			var elm = this;
106			 do {
107				if(elm && elm.nodeName && elm.nodeName.toUpperCase() == t) {
108					return elm;
109				}
110				elm = elm.parentNode;
111			} while(elm);
112			return false;
113		},
114
115		hasClass : function(cls) {
116			return this.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));
117		},
118
119		addClass : function(cls) {
120			if (!this.hasClass(cls)) { this.className += cls };
121			return this;
122		},
123
124		removeClass : function(cls) {
125			if (this.hasClass(cls)) {
126				this.className = this.className.replace(new RegExp('(\\s|^)'+cls+'(\\s|$)'),' ');
127			}
128			return this;
129		},
130
131		setStyle : function(st) {
132			var elmStyle = this.style;
133			for(var itm in st) {
134				switch(itm) {
135					case 'float':
136						elmStyle['cssFloat'] = elmStyle['styleFloat'] = st[itm];
137						break;
138					case 'opacity':
139						elmStyle.opacity = st[itm];
140						elmStyle.filter = "alpha(opacity=" + Math.round(st[itm]*100) + ")";
141						break;
142					case 'className':
143						this.className = st[itm];
144						break;
145					default:
146						//if(document.compatMode || itm != "cursor") { // Nasty Workaround for IE 5.5
147							elmStyle[itm] = st[itm];
148						//}
149				}
150			}
151			return this;
152		},
153
154		getStyle : function( cssRule, d ) {
155			var doc = (!d) ? document.defaultView : d;
156			if(this.nodeType == 1)
157			return (doc && doc.getComputedStyle) ? doc.getComputedStyle( this, null ).getPropertyValue(cssRule) : this.currentStyle[ bkLib.camelize(cssRule) ];
158		},
159
160		remove : function() {
161			this.parentNode.removeChild(this);
162			return this;
163		},
164
165		setAttributes : function(at) {
166			for(var itm in at) {
167				this[itm] = at[itm];
168			}
169			return this;
170		}
171	});
172
173	var bkLib = {
174		isMSIE : (navigator.appVersion.indexOf("MSIE") != -1),
175
176		addEvent : function(obj, type, fn) {
177			(obj.addEventListener) ? obj.addEventListener( type, fn, false ) : obj.attachEvent("on"+type, fn
177);
178		},
179
180		toArray : function(iterable) {
181			var length = iterable.length, results = new Array(length);
182	    	while (length--) { results[length] = iterable[length] };
183	    	return results;
184		},
185
186		noSelect : function(element) {
187			if(element.setAttribute && element.nodeName.toLowerCase() != 'input' && element.nodeName.toLowerCase() != 'textarea') {
188				element.setAttribute('unselectable','on');
189			}
190			for(var i=0;i<element.childNodes.length;i++) {
191				bkLib.noSelect(element.childNodes[i]);
192			}
193		},
194		camelize : function(s) {
195			return s.replace(/\-(.)/g, function(m, l){return l.toUpperCase()});
196		},
197		inArray : function(arr,item) {
198		    return (bkLib.search(arr,item) != null);
199		},
200		search : function(arr,itm) {
201			for(var i=0; i < arr.length; i++) {
202				if(arr[i] == itm)
203					return i;
204			}
205			return null;
206		},
207		cancelEvent : function(e) {
208			e = e || window.event;
209			if(e.preventDefault && e.stopPropagation) {
210				e.preventDefault();
211				e.stopPropagation();
212			}
213			return false;
214		},
215		domLoad : [],
216		domLoaded : function() {
217			if (arguments.callee.done) return;
218			arguments.callee.done = true;
219			for (i = 0;i < bkLib.domLoad.length;i++) bkLib.domLoad[i]();
220		},
221		onDomLoaded : function(fireThis) {
222			this.domLoad.push(fireThis);
223			if (document.addEventListener) {
224				document.addEventListener("DOMContentLoaded", bkLib.domLoaded, null);
225			} else if(bkLib.isMSIE) {
226				//document.write("<style>.nicEdit-main p { margin: 0; }</style><scr"+"ipt id=__ie_onload defer " + ((location.protocol == "https:") ? "src='javascript:void(0)'" : "src=//0") + "><\/scr"+"ipt>");
227				$BK("__ie_onload").onreadystatechange = function() {
228				    if (this.readyState == "complete"){ bkLib.domLoaded(); }
229				};
230			}
231
232			window.onload = bkLib.domLoaded;
233		}
234	};
235
236	function $BK(elm) {
237		if(typeof(elm) == "string") {
238			elm = document.getElementById(elm);
239		}
240
241		return (elm && !elm.appendTo) ? bkExtend(elm,bkElement.prototype) : elm;
242	}
243
244	var bkEvent = {
245		addEvent : function(evType, evFunc) {
246			if(evFunc) {
247				this.eventList = this.eventList || {};
248				this.eventList[evType] = this.eventList[evType] || [];
249				this.eventList[evType].push(evFunc);
250			}
251			return this;
252		},
253		fireEvent : function() {
254			var args = bkLib.toArray(arguments), evType = args.shift();
255			if(this.eventList && this.eventList[evType]) {
256				for(var i=0;i<this.eventList[evType].length;i++) {
257					this.eventList[evType][i].apply(this,args);
258				}
259			}
260		}
261	};
262
263	function __(s) {
264		return s;
265	}
266
267	Function.prototype.closure = function() {
268		var __method = this, args = bkLib.toArray(arguments), obj = args.shift();
269
270		return function() {
271			if(typeof(bkLib) != 'undefined') { return __method.apply(obj,args.concat(bkLib.toArray(arguments))); }
272		};
273	}
274
275	Function.prototype.closureListener = function() {
276	  	var __method = this, args = bkLib.toArray(arguments), object = args.shift();
277	  	return function(e) {
278	  	e = e || window.event;
279	  	if(e.target) { var target = e.target; } else { var target =  e.srcElement };
280		  	return __method.apply(object, [e,target].concat(args) );
281		};
282	}
283
284
285	/* START CONFIG */
286	var nicEditorConfig = bkClass.extend({
287		buttons : {
288			'bold' : {name : __lang.bold, command : 'Bold', tags : ['B','STRONG'], css : {'font-weight' : 'bold'}, key : 'b'},
289			'italic' : {name : __lang.italic, command : 'Italic', tags : ['EM','I'], css : {'font-style' : 'italic'}, key : 'i'},
290			'underline' : {name : __lang.underline, command : 'Underline', tags : ['U'], css : {'text-decoration' : 'underline'}, key : 'u'},
291			'left' : {name : __lang.align_left, command : 'justifyleft', noActive : true},
292			'center' : {name : __lang.align_center, command : 'justifycenter', noActive : true},
293			'right' : {name : __lang.align_right, command : 'justifyright', noActive : true},
294			'justify' : {name : __lang.align_justify, command : 'justifyfull', noActive : true},
295			'ol' : {name : __lang.numeric_list, command : 'insertorderedlist', tags : ['OL']},
296			'ul' : 	{name : __lang.marker_list, command : 'insertunorderedlist', tags : ['UL']},
297			'subscript' : {name : __('Click to Subscript'), command : 'subscript', tags : ['SUB']},
298			'superscript' : {name : __('Click to Superscript'), command : 'superscript', tags : ['SUP']},
299			'strikethrough' : {name : __('Click to Strike Through'), command : 'strikeThrough', css : {'text-decoration' : 'line-through'}},
300			'removeformat' : {name : __('Remove Formatting'), command : 'removeformat', noActive : true},
301			'indent' : {name : __lang.indent, command : 'indent', noActive : true},
302			'outdent' : {name : __lang.outdent, command : 'outdent', noActive : true},
303			'hr' : {name : __('Horizontal Rule'), command : 'insertHorizontalRule', noActive : true},
304			'separator' : {name : __('separator'), command : 'separator', noActive : true}
305		},
306		iconsPath : '../nicEditorIcons.gif',
307		buttonList : ['save','bold','italic','underline','left','center','right','justify','ol','ul','fontSize','fontFamily','fontFormat','indent','outdent','image','upload','link','unlink','forecolor','bgcolor', 'separator', 'strikeThrough'],
308		iconList : {"xhtml":1,"bgcolor":2,"forecolor":3,"bold":4,"center":5,"hr":6,"indent":7,"italic":8,"justify":9,"left":10,"ol":11,"outdent":12,"removeformat":13,"right":14,"save":25,"strikethrough":16,"subscript":17,"superscript":18,"ul":19,"underline":20,"image":21,"link":22,"unlink":23,"close"
308:24,"arrow":26,"upload":27}
309	});
310	/* END CONFIG */
311
312
313	var nicEditors = {
314		nicPlugins : [],
315		editors : [],
316
317		registerPlugin : function(plugin,options) {
318			this.nicPlugins.push({p : plugin, o : options});
319		},
320
321		allTextAreas : function(nicOptions) {
322			var textareas = document.getElementsByTagName("textarea");
323			for(var i=0;i<textareas.length;i++) {
324				nicEditors.editors.push(new nicEditor(nicOptions).panelInstance(textareas[i]));
325			}
326			return nicEditors.editors;
327		},
328
329		findEditor : function(e) {
330			var editors = nicEditors.editors;
331			for(var i=0;i<editors.length;i++) {
332				if(editors[i].instanceById(e)) {
333					return editors[i].instanceById(e);
334				}
335			}
336		}
337	};
338
339
340	var nicEditor = bkClass.extend({
341		construct : function(o) {
342			this.options = new nicEditorConfig();
343			bkExtend(this.options,o);
344			this.nicInstances = new Array();
345			this.loadedPlugins = new Array();
346
347			var plugins = nicEditors.nicPlugins;
348			for(var i=0;i<plugins.length;i++) {
349				this.loadedPlugins.push(new plugins[i].p(this,plugins[i].o));
350			}
351
352			nicEditors.editors.push(this);
353
354			bkLib.addEvent(document.body, 'mousedown', this.selectCheck.closureListener(this) );
355		},
356
357		panelInstance : function(e,o) {
358			e = this.checkReplace($BK(e));
359			var panelElm = new bkElement('DIV').addClass('wysiwyg').appendBefore(e);
360			this.setPanel(panelElm);
361			return this.addInstance(e,o);
362		},
363
364		checkReplace : function(e) {
365			var r = nicEditors.findEditor(e);
366			if(r) {
367				r.removeInstance(e);
368				r.removePanel();
369			}
370
371			return e;
372		},
373
374		addInstance : function(e,o) {
375			e = this.checkReplace($BK(e));
376			if( e.contentEditable || !!window.opera ) {
377				var newInstance = new nicEditorInstance(e,o,this);
378			} else {
379				var newInstance = new nicEditorIFrameInstance(e,o,this);
380			}
381			this.nicInstances.push(newInstance);
382			return this;
383		},
384
385		removeInstance : function(e) {
386			e = $BK(e);
387			var instances = this.nicInstances;
388			for(var i=0;i<instances.length;i++) {
389				if(instances[i].e == e) {
390					instances[i].remove();
391					this.nicInstances.splice(i,1);
392				}
393			}
394		},
395
396		removePanel : function(e) {
397			if(this.nicPanel) {
398				this.nicPanel.remove();
399				this.nicPanel = null;
400			}
401		},
402
403		instanceById : function(e) {
404			e = $BK(e);
405			var instances = this.nicInstances;
406			for(var i=0;i<instances.length;i++) {
407				if(instances[i].e == e) {
408					return instances[i];
409				}
410			}
411		},
412
413		setPanel : function(e) {
414			this.nicPanel = new nicEditorPanel($BK(e),this.options,this);
415			this.fireEvent('panel',this.nicPanel);
416			return this;
417		},
418
419		nicCommand : function(cmd,args) {
420			if(this.selectedInstance) {
421				this.selectedInstance.nicCommand(cmd,args);
422			}
423		},
424
425		getIcon : function(iconName,options) {
426			var icon = this.options.iconList[iconName];
427			var file = (options.iconFiles) ? options.iconFiles[iconName] : '';
428			return {backgroundImage : "url('"+((icon) ? this.options.iconsPath : file)+"')", backgroundPosition : ((icon) ? ((icon-1)*-18) : 0)+'px 0px'};
429		},
430
431		selectCheck : function(e,t) {
432			var found = false;
433
434			do{
435				if(t.className && t.className.indexOf('wysiwyg') != -1) {
436					return false;
437				}
438			} while(t = t.parentNode);
439
440			this.fireEvent('blur',this.selectedInstance,t);
441			this.lastSelectedInstance = this.selectedInstance;
442			this.selectedInstance = null;
443
444			return false;
445		}
446
447	});
448
449	nicEditor = nicEditor.extend(bkEvent);
450
451	var nicEditorInstance = bkClass.extend({
452		isSelected : false,
453
454		construct : function(e,options,nicEditor) {
455			this.ne = nicEditor;
456			this.elm = this.e = e;
457			this.options = options || {};
458
459			newX = parseInt(e.getStyle('width')) || e.clientWidth;
460			newY = parseInt(e.getStyle('height')) || e.clientHeight;
461			this.initialHeight = newY-8;
462
463			var isTextarea = (e.nodeName.toLowerCase() == "textarea");
464			if(isTextarea || this.options.hasPanel) {
465				var ie7s = (bkLib.isMSIE && !((typeof document.body.style.maxHeight != "undefined") && document.compatMode == "CSS1Compat"))
466				var s = {};
467				s[(ie7s) ? 'height' : 'maxHeight'] = (this.ne.options.maxHeight) ? this.ne.options.maxHeight+'px' : null;
468				this.editorContain = new bkElement('DIV').setStyle(s).addClass('wysiwyg-holder').appendBefore(e);
469				var editorElm = new bkElement('DIV').addClass('wysiwyg-main').appendTo(this.editorContain);
470
471				nicEditor.editor = editorElm;
472
473				e.setStyle({display : 'none'});
474
475				editorElm.innerHTML = e.innerHTML;
476				if(isTextarea) {
477					editorElm.setContent(e.value);
478					this.copyElm = e;
479					var f = e.parentTag('FORM');
480					if(f) { bkLib.addEvent( f, 'submit', this.saveContent.closure(this)); }
481				}
482				editorElm.setStyle((ie7s) ? {height : newY+'px'} : {overflow: 'hidden'});
483				this.elm = editorElm;
484			}
485
486			this.ne.addEvent('blur', this.blur.closure(this));
487
488			this.init();
489			this.blur();
490		},
491
492		init : function() {
493			this.elm.setAttribute('contentEditable','true');
494			if(this.getContent() == "") {
495				this.setContent('<br />');
496			}
497			this.instanceDoc = document.defaultView;
498			this.elm.addEvent('mousedown',this.selected.closureListener(this)).addEvent('keypress',this.keyDown.closureListener(this)).addEvent('focus',this.selected.closure(this)).addEvent('blur',this.blur.closure(this)).addEvent('keyup',this.selected.closure(this));
499			this.ne.fireEvent('add',this);
500		},
501
502		remove : function() {
503			this.saveContent();
504			if(this.copyElm || this.options.hasPanel) {
505				this.editorContain.remove();
506				this.e.setStyle({'display' : 'block'});
507				this.ne.removePanel();
508			}
509			this.disable();
510			this.ne.fireEvent('remove',this);
511		},
512
513		disable : function() {
514			this.elm.setAttribute('contentEditable','false');
515		},
516
517		getSel : function() {
518			return (window.getSelection) ? window.getSelection() : document.selection;
519		},
520
521		getRng : function() {
522			var s = this.getSel();
523
524			if(!s) { return null; }
525			return (s.rangeCount > 0) ? s.getRangeAt(0) : document.createRange();
526		},
527
528		selRng : function(rng,s) {
529			if(window.getSelection) {
530				s.removeAllRanges();
531				s.addRange(rng);
532			} else {
533				rng.select();
534			}
535		},
536
537		selElm : function() {
538			var r = this.getRng();
539			if(r.startContainer) {
540				var contain = r.startContainer;
541				if(r.cloneContents().childNodes.length == 1) {
542					for(var i=0;i<contain.childNodes.length;i++) {
543						var rng = contain.childNodes[i].ownerDocument.createRange();
544						rng.selectNode(contain.childNodes[i]);
545						if(r.compareBoundaryPoints(Range.START_TO_START,rng) != 1 &&
546							r.compareBoundaryPoints(Range.END_TO_END,rng) != -1) {
547							return $BK(contain.childNodes[i]);
548						}
549					}
550				}
551				return $BK(contain);
552			} else {
553				return $BK((this.getSel().type == "Control") ? r.item(0) : r.parentElement());
554			}
555		},
556
557		saveRng : function() {
558			this.savedRange = this.getRng();
559			this.savedSel = this.getSel();
560		},
561
562		restoreRng : function() {
563			if(this.savedRange) {
564				this.selRng(this.savedRange,this.savedSel);
565			}
566		},
567
568		keyDown : function(e,t) {
569			if(e.ctrlKey) {
570				this.ne.fireEvent('key',this,e);
571			}
572		},
573
574		selected : function(e,t) {
575			if(!t) {t = this.selElm()}
576			if(!e.ctrlKey) {
577				var selInstance = this.ne.selectedInstance;
578				if(selInstance != this) {
579					if(selInstance) {
580						this.ne.fireEvent('blur',selInstance,t);
581					}
582					this.ne.selectedInstance = this;
583					this.ne.fireEvent('focus',selInstance,t);
584				}
585
586				this.ne.fireEvent('selected',selInstance,t);
587				this.isFocused = true;
588
589				//this.elm.addClass(' selected');
590			}
591
592			return false;
593		},
594
595		blur : function() {
596			this.isFocused = false;
597			//this.elm.removeClass(' selected');
598
599			$('form5-fulltext').set('html', this.elm.get('html'));
600		},
601
602		saveContent : function() {
603			if(this.copyElm || this.options.hasPanel) {
604				this.ne.fireEvent('save',this);
605				(this.copyElm) ? this.copyElm.value = this.getContent() : this.e.innerHTML = this.getContent();
606			}
607		},
608
609		getElm : function() {
610			return this.elm;
611		},
612
613		getContent : function() {
614			this.content = this.getElm().innerHTML;
615			this.ne.fireEvent('get',this);
616			return this.content;
617		},
618
619		setContent : function(e) {
620			this.content = e;
621			this.ne.fireEvent('set',this);
622			this.elm.innerHTML = this.content;
623		},
624
625		nicCommand : function(cmd,args) {
626			document.execCommand(cmd,false,args);
627		}
628	});
629
630	var nicEditorIFrameInstance = nicEditorInstance.extend({
631		savedStyles : [],
632
633		init : function() {
634			var c = this.elm.innerHTML.replace(/^\s+|\s+$/g, '');
635			this.elm.innerHTML = '';
636			(!c) ? c = "<br />" : c;
637			this.initialContent = c;
638
639			this.elmFrame = new bkElement('iframe').setAttributes({'src' : 'javascript:;', 'frameBorder' : 0, 'allowTransparency' : 'true', 'scrolling' : 'no'}).setStyle({height: '100px', width: '100%'}).addClass('wysiwyg-frame').appendTo(this.elm);
640
641			if(this.copyElm) { this.elmFrame.setStyle({width : (this.elm.offsetWidth-4)+'px'}); }
642
643			var styleList = ['font-size','font-family','font-weight','color'];
644			for(itm in styleList) {
645				this.savedStyles[bkLib.camelize(itm)] = this.elm.getStyle(itm);
646			}
647
648			setTimeout(this.initFrame.closure(this),50);
649		},
650
651		disable : function() {
652			this.elm.innerHTML = this.getContent();
653		},
654
655		initFrame : function() {
656			var fd = $BK(this.elmFrame.contentWindow.document);
657			fd.designMode = "on";
658			fd.open();
659			var css = this.ne.options.externalCSS;
660			fd.write('<html><head>'+((css) ? '<link href="'+css+'" rel="stylesheet" type="text/css" />' : '')+'</head><body id="nicEditContent" style="margin: 0 !important; background-color: transparent !important;">'+this.initialContent+'</body></html>');
661			fd.close();
662			this.frameDoc = fd;
663
664			this.frameWin = $BK(this.elmFrame.contentWindow);
665			this.frameContent = $BK(this.frameWin.document.body).setStyle(this.savedStyles);
666			this.instanceDoc = this.frameWin.document.defaultView;
667
668			this.heightUpdate();
669			this.frameDoc.addEvent('mousedown', this.selected.closureListener(this)).addEvent('keyup',this.heightUpdate.closureListener(this)).addEvent('keydown',this.keyDown.closureListener(this)).addEvent('keyup',this.selected.closure(this));
670			this.ne.fireEvent('add',this);
671		},
672
673		getElm : function() {
674			return this.frameContent;
675		},
676
677		setContent : function(c) {
678			this.content = c;
679			this.ne.fireEvent('set',this);
680			this.frameContent.innerHTML = this.content;
681			this.heightUpdate();
682		},
683
684		getSel : function() {
685			return (this.frameWin) ? this.frameWin.getSelection() : this.frameDoc.selection;
686		},
687
688		heightUpdate : function() {
689			this.elmFrame.style.height = Math.max(this.frameContent.offsetHeight,this.initialHeight)+'px';
690		},
691
692		nicCommand : function(cmd,args) {
693			this.frameDoc.execCommand(cmd,false,args);
694			setTimeout(this.heightUpdate.closure(this),100);
695		}
696	});
697
698
699	var nicEditorPanel = bkClass.extend({
700		construct : function(e,options,nicEditor) {
701			this.elm = e;
702			this.options = options;
703			this.ne = nicEditor;
704			this.panelButtons = new Array();
705			this.buttonList = bkExtend([],this.ne.options.buttonList);
706
707			this.panelElm = new bkElement('DIV').addClass('wysiwyg-bar c0').appendTo(e);
708
709			var opt = this.ne.options;
710			var buttons = opt.buttons;
711
712			for(button in buttons) {
713				this.addButton(button,opt,true);
714			}
715	/*
716			for(var i = 0; i < this.buttonList.length; i++) {
717				this.addButton(this.buttonList[i],opt,true);
718			}*/
719
720			this.reorder();
721			e.noSelect();
722		},
723
724		addButton : function(buttonName,options,noOrder) {
725			/*var button = options.buttons[buttonName];
726			var hasButton = bkLib.inArray(this.buttonList,buttonName);
727
728			if(hasButton && options.buttons[buttonName] != undefined) {
729				var type = nicEditorButton;
730				this.panelButtons.push(new type(this.panelElm,buttonName,options,this.ne));
731			}*/
732
733
734			var button = options.buttons[buttonName];
735
736			var type = (button['type']) ? eval('(typeof('+button['type']+') == "undefined") ? null : '+button['type']+';') : nicEditorButton;
737
738			var hasButton = bkLib.inArray(this.buttonList,buttonName);
739			if(type && (hasButton || this.ne.options.fullPanel)) {
740				this.panelButtons.push(new type(this.panelElm,buttonName,options,this.ne));
741				if(!hasButton) {
742					this.buttonList.push(buttonName);
743				}
744			}
745		},
746
747		findButton : function(itm) {
748			for(var i=0;i<this.panelButtons.length;i++) {
749				if(this.panelButtons[i].name == itm)
750					return this.panelButtons[i];
751			}
752		},
753
754		reorder : function() {
755			var bl = this.buttonList;
756			for(var i=0;i<bl.length;i++) {
757				var button = this.findButton(bl[i]);
758				if(button) {
759					this.panelElm.appendChild(button.margin);
760				}
761			}
762		},
763
764		remove : function() {
765			this.elm.remove();
766		}
767	});
768
769	var nicEditorButton = bkClass.extend({
770
771		construct : function(e,buttonName,options,nicEditor) {
772			this.options = options.buttons[buttonName];
773
774			this.name = buttonName;
775			this.ne = nicEditor;
776			this.elm = e;
777
778			if(buttonName === 'separator') {
779				this.margin = new bkElement('DIV').setStyle({'float' : 'left'}).appendTo(e);
780				this.contain = new bkElement('DIV').addClass('sep').appendTo(this.margin);
781			} else {
782				this.margin = new bkElement('DIV').setStyle({'float' : 'left'}).appendTo(e);
783				this.contain = new bkElement('DIV').setStyle({width : '20px', height : '20px'}).addClass('buttonContain').appendTo(this.margin);
784				this.border = new bkElement('DIV').setStyle({backgroundColor : '#efefef', border : '1px solid #efefef'}).appendTo(this.contain);
785				this.button = new bkElement('DIV').setStyle({width : '18px', height : '18px', overflow : 'hidden', zoom : 1, cursor : 'pointer'}).addClass('button').setStyle(this.ne.getIcon(buttonName,options)).appendTo(this.border);
786				this.button.addEvent('mouseover', this.hoverOn.closure(this)).addEvent('mouseout',this.hoverOff.closure(this)).addEvent('mousedown',this.mouseClick.closure(this)).noSelect();
787
788				if(!window.opera) {
789					this.button.onmousedown = this.button.onclick = bkLib.cancelEvent;
790				}
791
792				nicEditor.addEvent('selected', this.enable.closure(this)).addEvent('blur', this.disable.closure(this)).addEvent('key',this.key.closure(this));
793				this.disable();
794			}
795
796			this.init();
797		},
798
799		init : function() {  },
800
801		hide : function() {
802			this.contain.setStyle({display : 'none'});
803		},
804
805		updateState : function() {
806			if(this.isDisabled) { this.setBg(); }
807			else if(this.isHover) { this.setBg('hover'); }
808			else if(this.isActive) { this.setBg('active'); }
809			else { this.setBg(); }
810		},
811
812		setBg : function(state) {
813			switch(state) {
814				case 'hover':
815					var stateStyle = {border : '1px solid #666', backgroundColor : '#ddd'};
816					break;
817			case 'active':
818				var stateStyle = {border : '1px solid #666', backgroundColor : '#ccc'};
819				break;
820			default:
821				var stateStyle = {border : '1px solid #efefef', backgroundColor : '#efefef'};
822		}
823		this.border.setStyle(stateStyle).addClass('button-'+state);
824	},
825
826	checkNodes : function(e) {
827		var elm = e;
828		do {
829			if(this.options.tags && bkLib.inArray(this.options.tags,elm.nodeName)) {
830				this.activate();
831				return true;
832			}
833		} while(elm = elm.parentNode && elm.className != "wysiwyg");
834		elm = $BK(e);
835		while(elm.nodeType == 3) {
836			elm = $BK(elm.parentNode);
837		}
838		if(this.options.css) {
839			for(itm in this.options.css) {
840				if(elm.getStyle(itm,this.ne.selectedInstance.instanceDoc) == this.options.css[itm]) {
841					this.activate();
842					return true;
843				}
844			}
845		}
846		this.deactivate();
847		return false;
848	},
849
850	activate : function() {
851		if(!this.isDisabled) {
852			this.isActive = true;
853			this.updateState();
854			this.ne.fireEvent('buttonActivate',this);
855		}
856	},
857
858	deactivate : function() {
859		this.isActive = false;
860		this.updateState();
861		if(!this.isDisabled) {
862			this.ne.fireEvent('buttonDeactivate',this);
863		}
864	},
865
866	enable : function(ins,t) {
867		this.isDisabled = false;
868		this.contain.setStyle({'opacity' : 1}).addClass('buttonEnabled');
869		this.updateState();
870		this.checkNodes(t);
871	},
872
873	disable : function(ins,t) {
874		this.isDisabled = true;
875		this.contain.setStyle({'opacity' : 0.6}).removeClass('buttonEnabled');
876		this.updateState();
877	},
878
879	toggleActive : function() {
880		(this.isActive) ? this.deactivate() : this.activate();
881	},
882
883	hoverOn : function() {
884		if(!this.isDisabled) {
885			this.isHover = true;
886			this.updateState();
887			this.ne.fireEvent("buttonOver",this);
888		}
889	},
890
891	hoverOff : function() {
892		this.isHover = false;
893		this.updateState();
894		this.ne.fireEvent("buttonOut",this);
895	},
896
897	mouseClick : function() {
898		if(this.options.command) {
899			this.ne.nicCommand(this.options.command,this.options.commandArgs);
900			if(!this.options.noActive) {
901				this.toggleActive();
902			}
903		}
904		this.ne.fireEvent("buttonClick",this);
905	},
906
907	key : function(nicInstance,e) {
908		if(this.options.key && e.ctrlKey && String.fromCharCode(e.keyCode || e.charCode).toLowerCase() == this.options.key) {
909			this.mouseClick();
910			if(e.preventDefault) e.preventDefault();
911		}
912	}
913
914});
915
916
917var nicPlugin = bkClass.extend({
918
919	construct : function(nicEditor,options) {
920		this.options = options;
921		this.ne = nicEditor;
922		this.ne.addEvent('panel',this.loadPanel.closure(this));
923
924		this.init();
925	},
926
927	loadPanel : function(np) {
928		var buttons = this.options.buttons;
929
930		for(var button in buttons) {
931			np.addButton(button,this.options);
932		}
933		//np.reorder();
934	},
935
936	init : function() {  }
937});
938
939
940
941
942 /* START CONFIG */
943var nicPaneOptions = { };
944/* END CONFIG */
945
946var nicEditorPane = bkClass.extend({
947	construct : function(elm,nicEditor,options,openButton) {
948		this.ne = nicEditor;
949		this.elm = elm;
950		this.pos = elm.pos();
951
952		if(typeof(options.addclass) == 'string') {
953			this.contain = new bkElement('div').setStyle({ left : this.pos[0]+'px', top : this.pos[1]+'px' }).addClass(options.addclass);
954		} else {
955			this.contain = new bkElement('div').setStyle({ left : this.pos[0]+'px', top : this.pos[1]+'px' }).addClass('w-tooltips');
956		}
957
958		this.pane = new bkElement('div').appendTo(this.contain);
959
960		if(openButton && !openButton.options.noClose) {
961			this.close = new bkElement('div').setStyle({'float' : 'right', height: '16px', width : '16px', cursor : 'pointer'}).setStyle(this.ne.getIcon('close',nicPaneOptions)).addEvent('mousedown',openButton.removePane.closure(this)).appendTo(this.pane);
962		}
963
964		this.contain.noSelect().appendTo(document.body);
965
966		this.position();
967		this.init();
968	},
969
970	init : function() { },
971
972	position : function() {
973		if(this.ne.nicPanel) {
974			var panelElm = this.ne.nicPanel.elm;
975			var panelPos = panelElm.pos();
976			var newLeft = panelPos[0]+parseInt(panelElm.getStyle('width'))-(parseInt(this.pane.getStyle('width'))+8);
977			if(newLeft < this.pos[0]) {
978				this.contain.setStyle({left : newLeft+'px'});
979			}
980		}
981	},
982
983	toggle : function() {
984		this.isVisible = !this.isVisible;
985		this.contain.setStyle({display : ((this.isVisible) ? 'block' : 'none')});
986	},
987
988	remove : function() {
989		if(this.contain) {
990			this.contain.remove();
991			this.contain = null;
992		}
993	},
994
995	append : function(c) {
996		c.appendTo(this.pane);
997	},
998
999	setContent : function(c) {
1000		this.pane.setContent(c);
1001	}
1002
1003});
1004
1005
1006
1007var nicEditorAdvancedButton = nicEditorButton.extend({
1008
1009	init : function() {
1010		this.ne.addEvent('selected',this.removePane.closure(this)).addEvent('blur',this.removePane.closure(this));
1011	},
1012
1013	mouseClick : function() {
1014		if(!this.isDisabled) {
1015			if(this.pane && this.pane.pane) {
1016				this.removePane();
1017			} else {
1018				this.pane = new nicEditorPane(this.contain,this.ne,{ addclass:'wswlform' },this);
1019				this.addPane();
1020				this.ne.selectedInstance.saveRng();
1021			}
1022		}
1023	},
1024
1025	addForm : function(f,elm) {
1026		this.form = new bkElement('form').addEvent('submit', this.submit.closureListener(this));
1027		this.form.addClass('form');
1028
1029		this.pane.append(this.form);
1030
1031		this.inputs = {};
1032
1033		for(itm in f) {
1034			var field = f[itm];
1035			var val = '';
1036			if(elm) {
1037				val = elm.getAttribute(itm);
1038			}
1039			if(!val) {
1040				val = field['value'] || '';
1041			}
1042			var type = f[itm].type;
1043
1044			if(type == 'title') {
1045				new bkElement('div').setContent(field.txt).addClass('title').appendTo(this.form);
1046			} else {
1047				var contain = new bkElement('div').setStyle({overflow : 'hidden', clear : 'both'}).appendTo(this.form);
1048				if(field.txt) {
1049					new bkElement('label').setAttributes({'for' : itm}).setContent(field.txt).setStyle({margin : '2px 4px', fontSize : '13px', width: '50px', lineHeight : '20px', textAlign : 'right', 'float' : 'left'}).appendTo(contain);
1050				}
1051
1052				switch(type) {
1053					case 'text':
1054						this.inputs[itm] = new bkElement('input').setAttributes({id : itm, 'value' : val, 'type' : 'text'}).setStyle({margin : '2px 0', fontSize : '13px', 'float' : 'left', height : '20px', border : '1px solid #ccc', overflow : 'hidden'}).setStyle(field.style).appendTo(contain);
1055						break;
1056					case 'select':
1057						this.inputs[itm] = new bkElement('select').setAttributes({id : itm}).setStyle({border : '1px solid #ccc', 'float' : 'left', margin : '2px 0'}).appendTo(contain);
1058						for(opt in field.options) {
1059							var o = new bkElement('option').setAttributes({value : opt, selected : (opt == val) ? 'selected' : ''}).setContent(field.options[opt]).appendTo(this.inputs[itm]);
1060						}
1061						break;
1062					case 'content':
1063						this.inputs[itm] = new bkElement('textarea').setAttributes({id : itm}).setStyle({border : '1px solid #ccc', 'float' : 'left'}).setStyle(field.style).appendTo(contain);
1064						this.inputs[itm].value = val;
1065				}
1066			}
1067		}
1068		new bkElement('input').setAttributes({'type' : 'submit'}).setStyle({backgroundColor : '#efefef',border : '1px solid #ccc', margin : '3px 0', 'float' : 'left', 'clear' : 'both'}).appendTo(this.form);
1069		this.form.onsubmit = bkLib.cancelEvent;
1070	},
1071
1072	submit : function() { },
1073
1074	findElm : function(tag,attr,val) {
1075		var list = this.ne.selectedInstance.getElm().getElementsByTagName(tag);
1076		for(var i=0;i<list.length;i++) {
1077			if(list[i].getAttribute(attr) == val) {
1078				return $BK(list[i]);
1079			}
1080		}
1081	},
1082
1083	removePane : function() {
1084		if(this.pane) {
1085			this.pane.remove();
1086			this.pane = null;
1087			this.ne.selectedInstance.restoreRng();
1088		}
1089	}
1090});
1091
1092
1093var nicButtonTips = bkClass.extend({
1094	construct : function(nicEditor) {
1095		this.ne = nicEditor;
1096		nicEditor.addEvent('buttonOver',this.show.closure(this)).addEvent('buttonOut',this.hide.closure(this));
1097
1098	},
1099
1100	show : function(button) {
1101		this.timer = setTimeout(this.create.closure(this,button),400);
1102	},
1103
1104	create : function(button) {
1105		this.timer = null;
1106		if(!this.pane) {
1107			this.pane = new nicEditorPane(button.button,this.ne,{fontSize : '12px', marginTop : '5px'});
1108			this.pane.setContent(button.options.name);
1109		}
1110	},
1111
1112	hide : function(button) {
1113		if(this.timer) {
1114			clearTimeout(this.timer);
1115		}
1116		if(this.pane) {
1117			this.pane = this.pane.remove();
1118		}
1119	}
1120});
1121nicEditors.registerPlugin(nicButtonTips);
1122
1123
1124
1125
1126
1127 /* START CONFIG */
1128var nicSelectOptions = {
1129	buttons : {
1130		'fontSize' : {name : __('Select Font Size'), type : 'nicEditorFontSizeSelect', command : 'fontsize'},
1131		'fontFamily' : {name : __('Select Font Family'), type : 'nicEditorFontFamilySelect', command : 'fontname'},
1132		'fontFormat' : {name : __lang.format, type : 'nicEditorFontFormatSelect', command : 'formatBlock'}
1133	}
1134};
1135/* END CONFIG */
1136var nicEditorSelect = bkClass.extend({
1137
1138	construct : function(e,buttonName,options,nicEditor) {
1139		this.options = options.buttons[buttonName];
1140		this.elm = e;
1141		this.ne = nicEditor;
1142		this.name = buttonName;
1143		this.selOptions = new Array();
1144
1145		this.margin = new bkElement('div').setStyle({'float' : 'left', margin : '2px 1px 0 1px'}).appendTo(this.elm);
1146		this.contain = new bkElement('div').setStyle({width: '90px', height : '20px', cursor : 'pointer', overflow: 'hidden'}).addClass('selectContain').addEvent('click',this.toggle.closure(this)).appendTo(this.margin);
1147
1148		this.items = new bkElement('div').setStyle({overflow : 'hidden', zoom : 1, border: '1px solid #ccc', paddingLeft : '3px', backgroundColor : '#fff'}).appendTo(this.contain);
1149		this.control = new bkElement('div').setStyle({overflow : 'hidden', 'float' : 'right', height: '18px', width : '16px'}).addClass('selectControl').setStyle(this.ne.getIcon('arrow',options)).appendTo(this.items);
1150		this.txt = new bkElement('div').setStyle({overflow : 'hidden', 'float' : 'left', width : '66px', height : '14px', marginTop : '1px', fontFamily : 'sans-serif', textAlign : 'center', fontSize : '12px'}).addClass('selectTxt').appendTo(this.items);
1151
1152		if(!window.opera) {
1153			this.contain.onmousedown = this.control.onmousedown = this.txt.onmousedown = bkLib.cancelEvent;
1154		}
1155
1156		this.margin.noSelect();
1157
1158		this.ne.addEvent('selected', this.enable.closure(this)).addEvent('blur', this.disable.closure(this));
1159
1160		this.disable();
1161		this.init();
1162	},
1163
1164	disable : function() {
1165		this.isDisabled = true;
1166		this.close();
1167		this.contain.setStyle({opacity : 0.6});
1168	},
1169
1170	enable : function(t) {
1171		this.isDisabled = false;
1172		this.close();
1173		this.contain.setStyle({opacity : 1});
1174	},
1175
1176	setDisplay : function(txt) {
1177		this.txt.setContent(txt);
1178	},
1179
1180	toggle : function() {
1181		if(!this.isDisabled) {
1182			(this.pane) ? this.close() : this.open();
1183		}
1184	},
1185
1186	open : function() {
1187		this.pane = new nicEditorPane(this.items,this.ne, {width : '188px', addclass: 'ws-p-format'});
1188
1189		for(var i=0;i<this.selOptions.length;i++) {
1190			var opt = this.selOptions[i];
1191			var itm = new bkElement('div').addClass('i').setContent(opt[1]).noSelect();
1192			itm.addEvent('click', this.update.closure(this,opt[0])).addEvent('mouseover',this.over.closure(this,itm)).addEvent('mouseout',this.out.closure(this,itm)).setAttributes('id',opt[0]);
1193			this.pane.append(itm);
1194			if(!window.opera) {
1195				itm.onmousedown = bkLib.cancelEvent;
1196			}
1197		}
1198	},
1199
1200	close : function() {
1201		if(this.pane) {
1202			this.pane = this.pane.remove();
1203		}
1204	},
1205
1206	over : function(opt) {
1207		opt.setStyle({backgroundColor : '#ccc'});
1208	},
1209
1210	out : function(opt) {
1211		opt.setStyle({backgroundColor : '#fff'});
1212	},
1213
1214
1215	add : function(k,v) {
1216		this.selOptions.push(new Array(k,v));
1217	},
1218
1219	update : function(elm) {
1220		this.ne.nicCommand(this.options.command,elm);
1221		this.close();
1222	}
1223});
1224
1225var nicEditorFontSizeSelect = nicEditorSelect.extend({
1226	sel : {1 : '1&nbsp;(8pt)', 2 : '2&nbsp;(10pt)', 3 : '3&nbsp;(12pt)', 4 : '4&nbsp;(14pt)', 5 : '5&nbsp;(18pt)', 6 : '6&nbsp;(24pt)'},
1227	init : function() {
1228		this.setDisplay('Font&nbsp;Size...');
1229		for(itm in this.sel) {
1230			this.add(itm,'<font size="'+itm+'">'+this.sel[itm]+'</font>');
1231		}
1232	}
1233});
1234
1235var nicEditorFontFamilySelect = nicEditorSelect.extend({
1236	sel : {'arial' : 'Arial','comic sans ms' : 'Comic Sans','courier new' : 'Courier New','georgia' : 'Georgia', 'helvetica' : 'Helvetica', 'impact' : 'Impact', 'times new roman' : 'Times', 'trebuchet ms' : 'Trebuchet', 'verdana' : 'Verdana'},
1237
1238	init : function() {
1239		this.setDisplay('Font&nbsp;Family...');
1240		for(itm in this.sel) {
1241			this.add(itm,'<font face="'+itm+'">'+this.sel[itm]+'</font>');
1242		}
1243	}
1244});
1245
1246var nicEditorFontFormatSelect = nicEditorSelect.extend({
1247	sel : {'p' : __lang.paragraph, 'h2' : __lang.h2, 'h1' : __lang.h1},
1248
1249	init : function() {
1250		this.setDisplay(__lang.format);
1251
1252		for(itm in this.sel) {
1253			var tag = itm.toUpperCase();
1254			this.add('<'+tag+'>',this.sel[itm]);
1255		}
1256	}
1257});
1258
1259
1260nicEditors.registerPlugin(nicPlugin, nicSelectOptions);
1261
1262
1263/* START CONFIG */
1264var nicLinkOptions = {
1265	buttons : {
1266		'link' : { name : __lang.add_link, type : 'nicLinkButton', tags : ['A'] },
1267		'unlink' : { name : __lang.remove_link, command : 'unlink', noActive : false }
1268	},
1269
1270	className: 'w-add-link'
1271};
1272/* END CONFIG */
1273
1274var nicLinkButton = nicEditorAdvancedButton.extend({
1275	addPane : function() {
1276		this.ln = this.ne.selectedInstance.selElm().parentTag('A');
1277		this.addForm({
1278			'' : {type : 'title', txt : __lang.addLink},
1279			'href' : {type : 'text', txt : 'URL', value : 'http://', style : {width: '150px'}},
1280			'title' : {type : 'text', txt : 'Title'},
1281			'target' : {type : 'select', txt : 'Open In', options : {'' : 'Current Window', '_blank' : 'New Window'},style : {width : '100px'}}
1282		},this.ln);
1283	},
1284
1285	submit : function(e) {
1286		var url = this.inputs['href'].value;
1287		if(url == "http://" || url == "") {
1288			alert("You must enter a URL to Create a Link");
1289			return false;
1290		}
1291		this.removePane();
1292
1293		if(!this.ln) {
1294			var tmp = 'javascript:nicTemp();';
1295			this.ne.nicCommand("createlink",tmp);
1296			this.ln = this.findElm('A','href',tmp);
1297		}
1298		if(this.ln) {
1299			this.ln.setAttributes({
1300				href : this.inputs['href'].value,
1301				title : this.inputs['title'].value,
1302				target : this.inputs['target'].options[this.inputs['target'].selectedIndex].value
1303			});
1304		}
1305	}
1306});
1307
1308nicEditors.registerPlugin(nicPlugin,nicLinkOptions);
1309
1310
1311
1312/* START CONFIG */
1313var nicColorOptions = {
1314	buttons : {
1315		'forecolor' : {name : __('Change Text Color'), type : 'nicEditorColorButton', noClose : true},
1316		'bgcolor' : {name : __('Change Background Color'), type : 'nicEditorBgColorButton', noClose : true}
1317	}
1318};
1319/* END CONFIG */
1320
1321var nicEditorColorButton = nicEditorAdvancedButton.extend({
1322	addPane : function() {
1323			var colorList = {0 : '00',1 : '33',2 : '66',3 :'99',4 : 'CC',5 : 'FF'};
1324			var colorItems = new bkElement('DIV').setStyle({width: '270px'});
1325
1326			for(var r in colorList) {
1327				for(var b in colorList) {
1328					for(var g in colorList) {
1329						var colorCode = '#'+colorList[r]+colorList[g]+colorList[b];
1330
1331						var colorSquare = new bkElement('DIV').setStyle({'cursor' : 'pointer', 'height' : '15px', 'float' : 'left'}).appendTo(colorItems);
1332						var colorBorder = new bkElement('DIV').setStyle({border: '2px solid '+colorCode}).appendTo(colorSquare);
1333						var colorInner = new bkElement('DIV').setStyle({backgroundColor : colorCode, overflow : 'hidden', width : '11px', height : '11px'}).addEvent('click',this.colorSelect.closure(this,colorCode)).addEvent('mouseover',this.on.closure(this,colorBorder)).addEvent('mouseout',this.off.closure(this,colorBorder,colorCode)).appendTo(colorBorder);
1334
1335						if(!window.opera) {
1336							colorSquare.onmousedown = colorInner.onmousedown = bkLib.cancelEvent;
1337						}
1338
1339					}
1340				}
1341			}
1342			this.pane.append(colorItems.noSelect());
1343	},
1344
1345	colorSelect : function(c) {
1346		this.ne.nicCommand('foreColor',c);
1347		this.removePane();
1348	},
1349
1350	on : function(colorBorder) {
1351		colorBorder.setStyle({border : '2px solid #000'});
1352	},
1353
1354	off : function(colorBorder,colorCode) {
1355		colorBorder.setStyle({border : '2px solid '+colorCode});
1356	}
1357});
1358
1359var nicEditorBgColorButton = nicEditorColorButton.extend({
1360	colorSelect : function(c) {
1361		this.ne.nicCommand('hiliteColor',c);
1362		this.removePane();
1363	}
1364});
1365
1366nicEditors.registerPlugin(nicPlugin,nicColorOptions);
1367
1368
1369
1370/* START CONFIG */
1371var nicImageOptions = {
1372	buttons : {
1373		'image' : {name : 'Add Image', type : 'nicImageButton', tags : ['IMG']}
1374	}
1375
1376};
1377/* END CONFIG */
1378
1379var nicImageButton = nicEditorAdvancedButton.extend({
1380	addPane : function() {
1381		this.im = this.ne.selectedInstance.selElm().parentTag('IMG');
1382		this.addForm({
1383			'' : {type : 'title', txt : 'Add/Edit Image'},
1384			'src' : {type : 'text', txt : 'URL', 'value' : 'http://', style : {width: '150px'}},
1385			'alt' : {type : 'text', txt : 'Alt Text', style : {width: '100px'}},
1386			'align' : {type : 'select', txt : 'Align', options : {none : 'Default','left' : 'Left', 'right' : 'Right'}}
1387		},this.im);
1388	},
1389
1390	submit : function(e) {
1391		var src = this.inputs['src'].value;
1392		if(src == "" || src == "http://") {
1393			alert("You must enter a Image URL to insert");
1394			return false;
1395		}
1396		this.removePane();
1397
1398		if(!this.im) {
1399			var tmp = 'javascript:nicImTemp();';
1400			this.ne.nicCommand("insertImage",tmp);
1401			this.im = this.findElm('IMG','src',tmp);
1402		}
1403		if(this.im) {
1404			this.im.setAttributes({
1405				src : this.inputs['src'].value,
1406				alt : this.inputs['alt'].value,
1407				align : this.inputs['align'].value
1408			});
1409		}
1410	}
1411});
1412
1413nicEditors.registerPlugin(nicPlugin,nicImageOptions);
1414
1415
1416
1417
1418/* START CONFIG */
1419var nicSaveOptions = {
1420	buttons : {
1421		'save' : {name : __('Save this content'), type : 'nicEditorSaveButton'}
1422	}
1423};
1424/* END CONFIG */
1425
1426var nicEditorSaveButton = nicEditorButton.extend({
1427	init : function() {
1428		if(!this.ne.options.onSave) {
1429			this.margin.setStyle({'display' : 'none'});
1430		}
1431	},
1432	mouseClick : function() {
1433		var onSave = this.ne.options.onSave;
1434		var selectedInstance = this.ne.selectedInstance;
1435		onSave(selectedInstance.getContent(), selectedInstance.elm.id, selectedInstance);
1436	}
1437});
1438
1439nicEditors.registerPlugin(nicPlugin,nicSaveOptions);
1440
1441
1442
1443/* START CONFIG */
1444var nicUploadOptions = {
1445	buttons : {
1446		'upload' : {name : 'Upload Image', type : 'nicUploadButton'}
1447	}
1448
1449};
1450/* END CONFIG */
1451
1452var nicUploadButton = nicEditorAdvancedButton.extend({
1453	nicURI : 'http://files.nicedit.com/',
1454
1455	addPane : function() {
1456		this.im = this.ne.selectedInstance.selElm().parentTag('IMG');
1457		this.myID = Math.round(Math.random()*Math.pow(10,15));
1458		this.requestInterval = 1000;
1459		this.uri = this.ne.options.uploadURI || this.nicURI;
1460		nicUploadButton.lastPlugin = this;
1461
1462		this.myFrame = new bkElement('iframe').setAttributes({ width : '100%', height : '100px', frameBorder : 0, scrolling : 'no' }).setStyle({border : 0}).appendTo(this.pane.pane);
1463		this.progressWrapper = new bkElement('div').setStyle({display: 'none', width: '100%', height: '20px', border : '1px solid #ccc'}).appendTo(this.pane.pane);
1464		this.progress = new bkElement('div').setStyle({width: '0%', height: '20px', backgroundColor : '#ccc'}).setContent('&nbsp').appendTo(this.progressWrapper);
1465
1466		setTimeout(this.addForm.closure(this),50);
1467	},
1468
1469	addForm : function() {
1470		var myDoc = this.myDoc = this.myFrame.contentWindow.document;
1471		myDoc.open();
1472		myDoc.write("<html><body>");
1473		myDoc.write('<form method="post" action="'+this.uri+'?id='+this.myID+'" enctype="multipart/form-data">');
1474		myDoc.write('<input type="hidden" name="APC_UPLOAD_PROGRESS" value="'+this.myID+'" />');
1475		if(this.uri == this.nicURI) {
1476			myDoc.write('<div style="position: absolute; margin-left: 160px;"><img src="http://imageshack.us/img/imageshack.png" width="30" style="float: left;" /><div style="float: left; margin-left: 5px; font-size: 10px;">Hosted by<br /><a href="http://www.imageshack.us/" target="_blank">ImageShack</a></div></div>');
1477		}
1478		myDoc.write('<div style="font-size: 14px; font-weight: bold; padding-top: 5px;">Insert an Image</div>');
1479		myDoc.write('<input name="nicImage" type="file" style="margin-top: 10px;" />');
1480		myDoc.write('</form>');
1481		myDoc.write("</body></html>");
1482		myDoc.close();
1483
1484		this.myBody = myDoc.body;
1485
1486		this.myForm = $BK(this.myBody.getElementsByTagName('form')[0]);
1487		this.myInput = $BK(this.myBody.getElementsByTagName('input')[1]).addEvent('change', this.startUpload.closure(this));
1488		this.myStatus = new bkElement('div',this.myDoc).setStyle({textAlign : 'center', fontSize : '14px'}).appendTo(this.myBody);
1489	},
1490
1491	startUpload : function() {
1492		this.myForm.setStyle({display : 'none'});
1493		this.myStatus.setContent('<img src="http://files.nicedit.com/ajax-loader.gif" style="float: right; margin-right: 40px;" /><strong>Uploading...</strong><br />Please wait');
1494		this.myForm.submit();
1495		setTimeout(this.makeRequest.closure(this),this.requestInterval);
1496	},
1497
1498	makeRequest : function() {
1499		if(this.pane && this.pane.pane) {
1500			nicUploadButton.lastPlugin = this;
1501			var s = new bkElement('script').setAttributes({ type : 'text/javascript', src : this.uri+'?check='+this.myID+'&rand='+Math.round(Math.random()*Math.pow(10,15))}).addEvent('load', function() {
1502				s.parentNode.removeChild(s);
1503			}).appendTo(document.getElementsByTagName('head')[0]);
1504			if(this.requestInterval) {
1505				setTimeout(this.makeRequest.closure(this), this.requestInterval);
1506			}
1507		}
1508	},
1509
1510	setProgress : function(percent) {
1511		this.progressWrapper.setStyle({display: 'block'});
1512		this.progress.setStyle({width : percent+'%'});
1513	},
1514
1515	update : function(o) {
1516		if(o == false) {
1517			this.progressWrapper.setStyle({display : 'none'});
1518		} else if(o.url) {
1519			this.setProgress(100);
1520			this.requestInterval = false;
1521
1522			if(!this.im) {
1523				this.ne.selectedInstance.restoreRng();
1524				var tmp = 'javascript:nicImTemp();';
1525				this.ne.nicCommand("insertImage",tmp);
1526				this.im = this.findElm('IMG','src',tmp);
1527			}
1528			var w = parseInt(this.ne.selectedInstance.elm.getStyle('width'));
1529			if(this.im) {
1530				this.im.setAttributes({
1531					src : o.url,
1532					width : (w && o.width) ? Math.min(w,o.width) : ''
1533				});
1534			}
1535
1536			this.removePane();
1537		} else if(o.error) {
1538			this.requestInterval = false;
1539			this.setProgress(100);
1540			alert("There was an error uploading your image ("+o.error+").");
1541			this.removePane();
1542		} else if(o.noprogress) {
1543			this.progressWrapper.setStyle({display : 'none'});
1544			if(this.uri.indexOf('http:') == -1 || this.uri.indexOf(window.location.host) != -1) {
1545				this.requestInterval = false;
1546			}
1547		} else {
1548			this.setProgress( Math.round( (o.current/o.total) * 75) );
1549			if(o.interval) {
1550				this.requestInterval = o.interval;
1551			}
1552		}
1553	}
1554
1555});
1556
1557nicUploadButton.statusCb = function(o) {
1558	nicUploadButton.lastPlugin.update(o);
1559}
1560
1561nicEditors.registerPlugin(nicPlugin,nicUploadOptions);
1562
1563
1564
1565var nicXHTML = bkClass.extend({
1566	stripAttributes : ['_moz_dirty','_moz_resizing','_extended'],
1567	noShort : ['style','title','script','textarea','a'],
1568	cssReplace : {'font-weight:bold;' : 'strong', 'font-style:italic;' : 'em'},
1569	sizes : {1 : 'xx-small', 2 : 'x-small', 3 : 'small', 4 : 'medium', 5 : 'large', 6 : 'x-large'},
1570
1571	construct : function(nicEditor) {
1572		this.ne = nicEditor;
1573		if(this.ne.options.xhtml) {
1574			nicEditor.addEvent('get',this.cleanup.closure(this));
1575		}
1576	},
1577
1578	cleanup : function(ni) {
1579		var node = ni.getElm();
1580		var xhtml = this.toXHTML(node);
1581		ni.content = xhtml;
1582	},
1583
1584	toXHTML : function(n,r,d) {
1585		var txt = '';
1586		var attrTxt = '';
1587		var cssTxt = '';
1588		var nType = n.nodeType;
1589		var nName = n.nodeName.toLowerCase();
1590		var nChild = n.hasChildNodes && n.hasChildNodes();
1591		var extraNodes = new Array();
1592
1593		switch(nType) {
1594			case 1:
1595				var nAttributes = n.attributes;
1596
1597				switch(nName) {
1598					case 'b':
1599						nName = 'strong';
1600						break;
1601					case 'i':
1602						nName = 'em';
1603						break;
1604					case 'font':
1605						nName = 'span';
1606						break;
1607				}
1608
1609				if(r) {
1610					for(var i=0;i<nAttributes.length;i++) {
1611						var attr = nAttributes[i];
1612
1613						var attributeName = attr.nodeName.toLowerCase();
1614						var attributeValue = attr.nodeValue;
1615
1616						if(!attr.specified || !attributeValue || bkLib.inArray(this.stripAttributes,attributeName) || typeof(attributeValue) == "function") {
1617							continue;
1618						}
1619
1620						switch(attributeName) {
1621							case 'style':
1622								var css = attributeValue.replace(/ /g,"");
1623								for(itm in this.cssReplace) {
1624									if(css.indexOf(itm) != -1) {
1625										extraNodes.push(this.cssReplace[itm]);
1626										css = css.replace(itm,'');
1627									}
1628								}
1629								cssTxt += css;
1630								attributeValue = "";
1631							break;
1632							case 'class':
1633								attributeValue = attributeValue.replace("Apple-style-span","");
1634							break;
1635							case 'size':
1636								cssTxt += "font-size:"+this.sizes[attributeValue]+';';
1637								attributeValue = "";
1638							break;
1639						}
1640
1641						if(attributeValue) {
1642							attrTxt += ' '+attributeName+'="'+attributeValue+'"';
1643						}
1644					}
1645
1646					if(cssTxt) {
1647						attrTxt += ' style="'+cssTxt+'"';
1648					}
1649
1650					for(var i=0;i<extraNodes.length;i++) {
1651						txt += '<'+extraNodes[i]+'>';
1652					}
1653
1654					if(attrTxt == "" && nName == "span") {
1655						r = false;
1656					}
1657					if(r) {
1658						txt += '<'+nName;
1659						if(nName != 'br') {
1660							txt += attrTxt;
1661						}
1662					}
1663				}
1664
1665
1666
1667				if(!nChild && !bkLib.inArray(this.noShort,attributeName)) {
1668					if(r) {
1669						txt += ' />';
1670					}
1671				} else {
1672					if(r) {
1673						txt += '>';
1674					}
1675
1676					for(var i=0;i<n.childNodes.length;i++) {
1677						var results = this.toXHTML(n.childNodes[i],true,true);
1678						if(results) {
1679							txt += results;
1680						}
1681					}
1682				}
1683
1684				if(r && nChild) {
1685					txt += '</'+nName+'>';
1686				}
1687
1688				for(var i=0;i<extraNodes.length;i++) {
1689					txt += '</'+extraNodes[i]+'>';
1690				}
1691
1692				break;
1693			case 3:
1694				//if(n.nodeValue != '\n') {
1695					txt += n.nodeValue;
1696				//}
1697				break;
1698		}
1699
1700		return txt;
1701	}
1702});
1703nicEditors.registerPlugin(nicXHTML);
1704
1705
1706
1707var nicBBCode = bkClass.extend({
1708	construct : function(nicEditor) {
1709		this.ne = nicEditor;
1710		if(this.ne.options.bbCode) {
1711			nicEditor.addEvent('get',this.bbGet.closure(this));
1712			nicEditor.addEvent('set',this.bbSet.closure(this));
1713
1714			var loadedPlugins = this.ne.loadedPlugins;
1715			for(itm in loadedPlugins) {
1716				if(loadedPlugins[itm].toXHTML) {
1717					this.xhtml = loadedPlugins[itm];
1718				}
1719			}
1720		}
1721	},
1722
1723	bbGet : function(ni) {
1724		var xhtml = this.xhtml.toXHTML(ni.getElm());
1725		ni.content = this.toBBCode(xhtml);
1726	},
1727
1728	bbSet : function(ni) {
1729		ni.content = this.fromBBCode(ni.content);
1730	},
1731
1732	toBBCode : function(xhtml) {
1733		function rp(r,m) {
1734			xhtml = xhtml.replace(r,m);
1735		}
1736
1737		rp(/\n/gi,"");
1738		rp(/<strong>(.*?)<\/strong>/gi,"[b]$1[/b]");
1739		rp(/<em>(.*?)<\/em>/gi,"[i]$1[/i]");
1740		rp(/<span.*?style="text-decoration:underline;">(.*?)<\/span>/gi,"[u]$1[/u]");
1741		rp(/<ul>(.*?)<\/ul>/gi,"[list]$1[/list]");
1742		rp(/<li>(.*?)<\/li>
1742/gi,"[*]$1[/*]");
1743		rp(/<ol>(.*?)<\/ol>/gi,"[list=1]$1[/list]");
1744		rp(/<img.*?src="(.*?)".*?>/gi,"[img]$1[/img]");
1745		rp(/<a.*?href="(.*?)".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]");
1746		rp(/<br.*?>/gi,"\n");
1747		rp(/<.*?>.*?<\/.*?>/gi,"");
1748
1749		return xhtml;
1750	},
1751
1752	fromBBCode : function(bbCode) {
1753		function rp(r,m) {
1754			bbCode = bbCode.replace(r,m);
1755		}
1756
1757		rp(/\[b\](.*?)\[\/b\]/gi,"<strong>$1</strong>");
1758		rp(/\[i\](.*?)\[\/i\]/gi,"<em>$1</em>");
1759		rp(/\[u\](.*?)\[\/u\]/gi,"<span style=\"text-decoration:underline;\">$1</span>");
1760		rp(/\[list\](.*?)\[\/list\]/gi,"<ul>$1</ul>");
1761		rp(/\[list=1\](.*?)\[\/list\]/gi,"<ol>$1</ol>");
1762		rp(/\[\*\](.*?)\[\/\*\]/gi,"<li>$1</li>");
1763		rp(/\[img\](.*?)\[\/img\]/gi,"<img src=\"$1\" />");
1764		rp(/\[url=(.*?)\](.*?)\[\/url\]/gi,"<a href=\"$1\">$2</a>");
1765		rp(/\n/gi,"<br />");
1766		//rp(/\[.*?\](.*?)\[\/.*?\]/gi,"$1");
1767
1768		return bbCode;
1769	}
1770
1771
1772});
1773nicEditors.registerPlugin(nicBBCode);
1774
1775
1776
1777nicEditor = nicEditor.extend({
1778        floatingPanel : function() {
1779                this.floating = new bkElement('DIV').setStyle({position: 'absolute', top : '-1000px'}).appendTo(document.body);
1780                this.addEvent('focus', this.reposition.closure(this)).addEvent('blur', this.hide.closure(this));
1781                this.setPanel(this.floating);
1782        },
1783
1784        reposition : function() {
1785                var e = this.selectedInstance.e;
1786                this.floating.setStyle({ width : (parseInt(e.getStyle('width')) || e.clientWidth)+'px' });
1787                var top = e.offsetTop-this.floating.offsetHeight;
1788                if(top < 0) {
1789                        top = e.offsetTop+e.offsetHeight;
1790                }
1791
1792                this.floating.setStyle({ top : top+'px', left : e.offsetLeft+'px', display : 'block' });
1793        },
1794
1795        hide : function() {
1796                this.floating.setStyle({ top : '-1000px'});
1797        }
1798});
1799
1800
1801
1802/* START CONFIG */
1803var nicCodeOptions = {
1804	buttons : {
1805		'xhtml' : {name : 'Edit HTML', type : 'nicCodeButton'}
1806	}
1807
1808};
1809
1810/* END CONFIG */
1811var nicCodeButton = nicEditorAdvancedButton.extend({
1812	width : '350px',
1813
1814	addPane : function() {
1815		this.addForm({
1816			'' : {type : 'title', txt : 'Edit HTML'},
1817			'code' : {type : 'content', 'value' : this.ne.selectedInstance.getContent(), style : {width: '340px', height : '200px'}}
1818		});
1819	},
1820
1821	submit : function(e) {
1822		var code = this.inputs['code'].value;
1823		this.ne.selectedInstance.setContent(code);
1824		this.removePane();
1825	}
1826});
1827
1828nicEditors.registerPlugin(nicPlugin,nicCodeOptions);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.