/* NicEdit - Micro Inline WYSIWYG
 * ------------------------------------------------------------
 * Copyright 2007-2008 Brian Kirchoff
 *
 * CleverCherry Custom/Fork Version
 *           2022-     CleverCherry Dev Team
 *
 * NicEdit is distributed under the terms of the MIT license
 * For more information visit http://nicedit.com/
 * Do not remove this copyright message
 */

// added custom plugin smalltext currently used for phq3 15/10

// import imgUrl from './nicEditcc.gif'
import imgUrl from './cc-nicedit-icons-3.svg'

var bkExtend = function(){
	var args = arguments;
	if (args.length == 1) args = [this, args[0]];
	for (var prop in args[1]) args[0][prop] = args[1][prop];
	return args[0];
};
function bkClass() { }
bkClass.prototype.construct = function() {};
bkClass.extend = function(def) {
  var classDef = function() {
      if (arguments[0] !== bkClass) { return this.construct.apply(this, arguments); }
  };
  var proto = new this(bkClass);
  bkExtend(proto,def);
  classDef.prototype = proto;
  classDef.extend = this.extend;      
  return classDef;
};

var bkElement = bkClass.extend({
	construct : function(elm,d) {
		if(typeof(elm) == "string") {
			elm = (d || document).createElement(elm);
		}
		elm = $BK(elm);
		return elm;
	},
	
	appendTo : function(elm) {
		elm.appendChild(this);	
		return this;
	},
	
	appendBefore : function(elm) {
		elm.parentNode.insertBefore(this,elm);	
		return this;
	},
	
	addEvent : function(type, fn) {
		bkLib.addEvent(this,type,fn);
		return this;	
	},
	
	setContent : function(c) {
		console.log('ccdev setContent 60');
		this.innerHTML = c;
		return this;
	},
	
	pos : function() {
		var curleft = 0;
		var curtop = 0;
		var o = this;
		var obj = this;

		/*var curleft = curtop = 0;
		var o = obj = this;*/
		if (obj.offsetParent) {
			do {
				curleft += obj.offsetLeft;
				curtop += obj.offsetTop;
			} while (obj = obj.offsetParent);
		}
		var b = (!window.opera) ? parseInt(this.getStyle('border-width') || this.style.border) || 0 : 0;
		return [curleft+b,curtop+b+this.offsetHeight];
	},
	
	noSelect : function() {
		bkLib.noSelect(this);
		return this;
	},
	
	parentTag : function(t) {
		var elm = this;
		 do {
			if(elm && elm.nodeName && elm.nodeName.toUpperCase() == t) {
				return elm;
			}
			elm = elm.parentNode;
		} while(elm);
		return false;
	},
	
	hasClass : function(cls) {
		return this.className.match(new RegExp('(\\s|^)nicEdit-'+cls+'(\\s|$)'));
	},
	
	addClass : function(cls) {
		if (!this.hasClass(cls)) { this.className += " nicEdit-"+cls };
		return this;
	},
	
	removeClass : function(cls) {
		if (this.hasClass(cls)) {
			this.className = this.className.replace(new RegExp('(\\s|^)nicEdit-'+cls+'(\\s|$)'),' ');
		}
		return this;
	},

	setStyle : function(st) {
		var elmStyle = this.style;
		for(var itm in st) {
			switch(itm) {
				case 'float':
					elmStyle['cssFloat'] = elmStyle['styleFloat'] = st[itm];
					break;
				case 'opacity':
					elmStyle.opacity = st[itm];
					elmStyle.filter = "alpha(opacity=" + Math.round(st[itm]*100) + ")"; 
					break;
				case 'className':
					this.className = st[itm];
					break;
				default:
					//if(document.compatMode || itm != "cursor") { // Nasty Workaround for IE 5.5
						elmStyle[itm] = st[itm];
					//}		
			}
		}
		return this;
	},
	
	getStyle : function( cssRule, d ) {
		var doc = (!d) ? document.defaultView : d; 
		if(this.nodeType == 1)
		return (doc && doc.getComputedStyle) ? doc.getComputedStyle( this, null ).getPropertyValue(cssRule) : this.currentStyle[ bkLib.camelize(cssRule) ];
	},
	
	remove : function() {
		this.parentNode.removeChild(this);
		return this;	
	},
	
	setAttributes : function(at) {
		for(var itm in at) {
			this[itm] = at[itm];
		}
		return this;
	}
});

export var bkLib = {
	isMSIE : (navigator.appVersion.indexOf("MSIE") != -1),
	
	addEvent : function(obj, type, fn) {
		(obj.addEventListener) ? obj.addEventListener( type, fn, false ) : obj.attachEvent("on"+type, fn);	
	},
	
	toArray : function(iterable) {
		var length = iterable.length, results = new Array(length);
    	while (length--) { results[length] = iterable[length] };
    	return results;	
	},
	
	noSelect : function(element) {
		if(element.setAttribute && element.nodeName.toLowerCase() != 'input' && element.nodeName.toLowerCase() != 'textarea') {
			element.setAttribute('unselectable','on');
		}
		for(var i=0;i<element.childNodes.length;i++) {
			bkLib.noSelect(element.childNodes[i]);
		}
	},
	camelize : function(s) {
		return s.replace(/\-(.)/g, function(m, l){return l.toUpperCase()});
	},
	inArray : function(arr,item) {
	    return (bkLib.search(arr,item) != null);
	},
	search : function(arr,itm) {
		for(var i=0; i < arr.length; i++) {
			if(arr[i] == itm)
				return i;
		}
		return null;	
	},
	cancelEvent : function(e) {
		e = e || window.event;
		if(e.preventDefault && e.stopPropagation) {
			e.preventDefault();
			e.stopPropagation();
		}
		return false;
	},
	domLoad : [],
	domLoaded : function() {
		if (arguments.callee.done) return;
		arguments.callee.done = true;
		for (i = 0;i < bkLib.domLoad.length;i++) bkLib.domLoad[i]();
	},
	onDomLoaded : function(fireThis) {
		this.domLoad.push(fireThis);
		if (document.addEventListener) {
			document.addEventListener("DOMContentLoaded", bkLib.domLoaded, null);
		} else if(bkLib.isMSIE) {
			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>");
			$BK("__ie_onload").onreadystatechange = function() {
			    if (this.readyState == "complete"){bkLib.domLoaded();}
			};
		}
	    window.onload = bkLib.domLoaded;
	}
};

function $BK(elm) {
	if(typeof(elm) == "string") {
		elm = document.getElementById(elm);
	}
	return (elm && !elm.appendTo) ? bkExtend(elm,bkElement.prototype) : elm;
}

var bkEvent = {
	addEvent : function(evType, evFunc) {
		if(evFunc) {
			this.eventList = this.eventList || {};
			this.eventList[evType] = this.eventList[evType] || [];
			this.eventList[evType].push(evFunc);
		}
		return this;
	},
	fireEvent : function() {
		var args = bkLib.toArray(arguments), evType = args.shift();
		if(this.eventList && this.eventList[evType]) {
			for(var i=0;i<this.eventList[evType].length;i++) {
				this.eventList[evType][i].apply(this,args);
			}
		}
	}	
};

function __(s) {
	return s;
}

Function.prototype.closure = function() {
  var __method = this, args = bkLib.toArray(arguments), obj = args.shift();
  return function() { if(typeof(bkLib) != 'undefined') { return __method.apply(obj,args.concat(bkLib.toArray(arguments))); } };
}
	
Function.prototype.closureListener = function() {
  	var __method = this, args = bkLib.toArray(arguments), object = args.shift(); 
  	return function(e) { 
  	e = e || window.event;
  	if(e.target) { var target = e.target; } else { var target =  e.srcElement };
	  	return __method.apply(object, [e,target].concat(args) ); 
	};
}		

//buttons can be defined in the vite.config.js file
/**
 * add
 *  define :{
 *       adminNicEditButtons : ['fontFormat', 'bold','italic','underline','ol','ul','link','small','subscript','superscript',unlink','image','upload','removeformat','xhtml']
 *  }
 */
var defButtons = ['fontFormat', 'bold','italic','underline','ol','ul','link','unlink','image','upload','removeformat','xhtml'];
if(typeof(adminNicEditButtons) != 'undefined')
	defButtons = adminNicEditButtons ;

var nicEditorConfig = bkClass.extend({
	buttons : {
		'bold' : {name : __('Click to Bold'), command : 'Bold', tags : ['B','STRONG'], css : {'font-weight' : 'bold'}, key : 'b'},
		'italic' : {name : __('Click to Italic'), command : 'Italic', tags : ['EM','I'], css : {'font-style' : 'italic'}, key : 'i'},
		'underline' : {name : __('Click to Underline'), command : 'Underline', tags : ['U'], css : {'text-decoration' : 'underline'}, key : 'u'},
		'left' : {name : __('Left Align'), command : 'justifyleft', noActive : true},
		'center' : {name : __('Center Align'), command : 'justifycenter', noActive : true},
		'right' : {name : __('Right Align'), command : 'justifyright', noActive : true},
		'justify' : {name : __('Justify Align'), command : 'justifyfull', noActive : true},
		'ol' : {name : __('Insert Ordered List'), command : 'insertorderedlist', tags : ['OL']},
		'ul' : 	{name : __('Insert Unordered List'), command : 'insertunorderedlist', tags : ['UL']},
		'subscript' : {name : __('Click to Subscript'), command : 'subscript', tags : ['SUB']},
		'superscript' : {name : __('Click to Superscript'), command : 'superscript', tags : ['SUP']},
		'strikethrough' : {name : __('Click to Strike Through'), command : 'strikeThrough', css : {'text-decoration' : 'line-through'}},
		'removeformat' : {name : __('Remove Formatting'), command : 'removeformat', noActive : true},
		'indent' : {name : __('Indent Text'), command : 'indent', noActive : true},
		'outdent' : {name : __('Remove Indent'), command : 'outdent', noActive : true},
		'hr' : {name : __('Horizontal Rule'), command : 'insertHorizontalRule', noActive : true},
	},
	iconsPath : imgUrl,
	// default buttons, add your new plugins here
	// buttonList : ['save','bold','italic','underline','left','center','right','justify','ol','ul','removeformat',
	//               'fontSize','fontFamily','fontFormat','indent','outdent','image','upload','link','unlink',
	// 			  'forecolor','bgcolor', 'iblock', 'itable'],
	buttonList : defButtons,
	// default icons, icons for your plugins can be separate files or appended to the main one, in which case add them here
	iconList :  {"xhtml":10,"bgcolor":2,"forecolor":20,"bold":1,"center":5,"hr":6,"indent":7,"italic":2,
				 "justify":9,"left":10,"ol":7,"outdent":12,
				 "removeformat":9,"right":14,"save":25,"strikethrough":16,
				 "subscript":12,"superscript":13,"ul":6,"underline":3,"image":8,
				 "link":4,"unlink":5,"close":6,"arrow":26,"upload":27,"smalltext":14}	
});

export var nicEditors = {
	nicPlugins : [],
	editors : [],
	
	registerPlugin : function(plugin,options) {
		this.nicPlugins.push({p : plugin, o : options});
	},

	allTextAreas : function(nicOptions) {
		var textareas = document.getElementsByTagName("textarea");
		for(var i=0;i<textareas.length;i++) {
			nicEditors.editors.push(new nicEditor(nicOptions).panelInstance(textareas[i]));
		}
		return nicEditors.editors;
	},

	byQrySelectorAll : function(qrySelector, nicOptions) { //clevercherry 2022 ianj
		//var textareas = document.getElementsByTagName("textarea");
		var textareas = document.querySelectorAll(qrySelector);
		for(var i=0;i<textareas.length;i++) {
			nicEditors.editors.push(new nicEditor(nicOptions).panelInstance(textareas[i]));
		}
		return nicEditors.editors;
	},

	byElements : function(textareas, nicOptions) { //clevercherry 2022 ianj
		//var textareas = document.getElementsByTagName("textarea");
		for(var i=0;i<textareas.length;i++) {
			nicEditors.editors.push(new nicEditor(nicOptions).panelInstance(textareas[i]));
		}
		return nicEditors.editors;
	},
	
	findEditor : function(e) {
		var editors = nicEditors.editors;
		for(var i=0;i<editors.length;i++) {
			if(editors[i].instanceById(e)) {
				return editors[i].instanceById(e);
			}
		}
	}
};

var nicEditor = bkClass.extend({
	construct : function(o) {
		this.options = new nicEditorConfig();
		bkExtend(this.options,o);
		this.nicInstances = new Array();
		this.loadedPlugins = new Array();
		
		var plugins = nicEditors.nicPlugins;
		for(var i=0;i<plugins.length;i++) {
			this.loadedPlugins.push(new plugins[i].p(this,plugins[i].o));
		}
		nicEditors.editors.push(this);
		bkLib.addEvent(document.body,'mousedown', this.selectCheck.closureListener(this) );
	},
	
	panelInstance : function(e,o) {
		e = this.checkReplace($BK(e));
		//var wide = (parseInt(e.getStyle('width')) || e.clientWidth)  + 'px';
		//console.log('ccdev 347, wide: ', wide);
		var wide = "100%";
		var panelElm = new bkElement('DIV').setStyle({width : wide }).appendBefore(e);
		this.setPanel(panelElm);
		return this.addInstance(e,o);
	},

	checkReplace : function(e) {
		var r = nicEditors.findEditor(e);
		if(r) {
			if(typeof r.removeInstance === 'function')
				r.removeInstance(e);
			if(typeof r.removePanel === 'function')
				r.removePanel();
		}
		return e;
	},

	addInstance : function(e,o) {
		e = this.checkReplace($BK(e));
		if( e.contentEditable || !!window.opera ) {
			var newInstance = new nicEditorInstance(e,o,this);
		} else {
			var newInstance = new nicEditorIFrameInstance(e,o,this);
		}
		this.nicInstances.push(newInstance);
		return this;
	},
	
	removeInstance : function(e) {
		e = $BK(e);
		var instances = this.nicInstances;
		for(var i=0;i<instances.length;i++) {	
			if(instances[i].e == e) {
				instances[i].remove();
				this.nicInstances.splice(i,1);
			}
		}
	},

	removePanel : function(e) {
		if(this.nicPanel) {
			this.nicPanel.remove();
			this.nicPanel = null;
		}	
	},

	instanceById : function(e) {
		e = $BK(e);
		var instances = this.nicInstances;
		for(var i=0;i<instances.length;i++) {
			if(instances[i].e == e) {
				return instances[i];
			}
		}	
	},

	setPanel : function(e) {
		//console.log('ccdev 373', this.options.buttons);
		this.nicPanel = new nicEditorPanel($BK(e),this.options,this);
		this.fireEvent('panel',this.nicPanel);
		return this;
	},
	
	nicCommand : function(cmd,args) {	
		if(this.selectedInstance) {
			this.selectedInstance.nicCommand(cmd,args);
		}
	},
	
	getIcon : function(iconName,options) {
		var icon = this.options.iconList[iconName];
		var file = (options.iconFiles) ? options.iconFiles[iconName] : '';
		return {backgroundImage : "url('"+((icon) ? this.options.iconsPath : file)+"')", backgroundPosition : ((icon) ? ((icon-1)*-32) : 0)+'px 0px'};	
	},
		
	selectCheck : function(e,t) {
		var found = false;
		do{
			if(t.className && t.className.indexOf('nicEdit') != -1) {
				return false;
			}
		} while(t = t.parentNode);
		this.fireEvent('blur',this.selectedInstance,t);
		this.lastSelectedInstance = this.selectedInstance;
		this.selectedInstance = null;
		return false;
	}
	
});
nicEditor = nicEditor.extend(bkEvent);

var nicEditorInstance = bkClass.extend({
	isSelected : false,
	
	construct : function(e,options,nicEditor) {
		this.ne = nicEditor;
		this.elm = this.e = e;
		this.options = options || {};
		
		//var newX = (parseInt(e.getStyle('width')) || e.clientWidth) + 'px';
		//console.log('ccdev 448, ',e.getStyle('width'), e.clientWidth);
		var newX = '100%';
		var newY = parseInt(e.getStyle('height')) || e.clientHeight;
		this.initialHeight = newY-8;
		
		var isTextarea = (e.nodeName.toLowerCase() == "textarea");
		if(isTextarea || this.options.hasPanel) {
			var ie7s = (bkLib.isMSIE && !((typeof document.body.style.maxHeight != "undefined") && document.compatMode == "CSS1Compat"))
			var s = {width: newX };
			s[(ie7s) ? 'height' : 'maxHeight'] = (this.ne.options.maxHeight) ? this.ne.options.maxHeight+'px' : null;
			this.editorContain = new bkElement('DIV').setStyle(s).appendBefore(e);
			//var editorElm = new bkElement('DIV').setStyle({width : "calc("+newX+" - 2rem)", margin: '1rem', minHeight : newY+'px'}).addClass('main').appendTo(this.editorContain);
			var editorElm = new bkElement('DIV')
                .addClass('main wysiwyg__textarea')
                .appendTo(this.editorContain);

			e.setStyle({display : 'none'});
				
			editorElm.innerHTML = e.innerHTML;		
			if(isTextarea) {
				editorElm.setContent(e.value);
				this.copyElm = e;
				var f = e.parentTag('FORM');
				if(f) { bkLib.addEvent( f, 'submit', this.saveContent.closure(this)); }
			}
			editorElm.setStyle((ie7s) ? {height : newY+'px'} : {overflow: 'hidden'});
			this.elm = editorElm;	
		}
		this.ne.addEvent('blur',this.blur.closure(this));

		this.init();
		this.blur();
	},
	
	init : function() {
		this.elm.setAttribute('contentEditable','true');	

        // Removed so <br> doesn't break empty field logic
		// if(this.getContent() == "") {
		// 	this.setContent('<br />');
		// }
		this.instanceDoc = document.defaultView;
		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));
		this.ne.fireEvent('add',this);
	},
	
	remove : function() {
		this.saveContent();
		if(this.copyElm || this.options.hasPanel) {
			this.editorContain.remove();
			this.e.setStyle({'display' : 'block'});
			this.ne.removePanel();
		}
		this.disable();
		this.ne.fireEvent('remove',this);
	},
	
	disable : function() {
		this.elm.setAttribute('contentEditable','false');
	},
	
	getSel : function() {
		return (window.getSelection) ? window.getSelection() : document.selection;	
	},
	
	getRng : function() {
		var s = this.getSel();
		if(!s || s.rangeCount === 0) { return; }
		return (s.rangeCount > 0) ? s.getRangeAt(0) : s.createRange();
	},
	
	selRng : function(rng,s) {
		if(window.getSelection) {
			s.removeAllRanges();
			s.addRange(rng);
		} else {
			rng.select();
		}
	},
	
	selElm : function() {
		var r = this.getRng();
		if(!r) { return; }
		if(r.startContainer) {
			var contain = r.startContainer;
			if(r.cloneContents().childNodes.length == 1) {
				for(var i=0;i<contain.childNodes.length;i++) {
					var rng = contain.childNodes[i].ownerDocument.createRange();
					rng.selectNode(contain.childNodes[i]);					
					if(r.compareBoundaryPoints(Range.START_TO_START,rng) != 1 && 
						r.compareBoundaryPoints(Range.END_TO_END,rng) != -1) {
						return $BK(contain.childNodes[i]);
					}
				}
			}
			return $BK(contain);
		} else {
			return $BK((this.getSel().type == "Control") ? r.item(0) : r.parentElement());
		}
	},
	
	saveRng : function() {
		this.savedRange = this.getRng();
		this.savedSel = this.getSel();
	},
	
	restoreRng : function() {
		if(this.savedRange) {
			this.selRng(this.savedRange,this.savedSel);
		}
	},
	
	keyDown : function(e,t) {
		if(e.ctrlKey) {
			this.ne.fireEvent('key',this,e);
		}
	},
	
	selected : function(e,t) {
		if(!t && !(t = this.selElm)) { t = this.selElm(); }
		if(!e.ctrlKey) {
			var selInstance = this.ne.selectedInstance;
			if(selInstance != this) {
				if(selInstance) {
					this.ne.fireEvent('blur',selInstance,t);
				}
				this.ne.selectedInstance = this;	
				this.ne.fireEvent('focus',selInstance,t);
			}
			this.ne.fireEvent('selected',selInstance,t);
			this.isFocused = true;
			this.elm.addClass('selected');
			this.elm.setAttribute('data-selected', 'true');
		}
		return false;
	},
	
	blur : function() {
		this.isFocused = false;
		this.elm.removeClass('selected');
        this.elm.removeAttribute('data-selected');
        this.saveContent(); //auto-save data back to original text-area on losing focus
	},
	
	saveContent : function() {
        //customised for baskslash 4
		//console.log('ccdev saveContent 608', this.copyElm, this.getContent());

		if(this.copyElm || this.options.hasPanel) {
			this.ne.fireEvent('save',this);
            if(this.copyElm)
            { this.copyElm.value = this.getContent();
              this.copyElm.innerHTML = this.getContent();
              //console.log('ccdev save 614', this.copyElm, this.getContent());
              
              var chEvent = new Event('change');
			  this.copyElm.dispatchEvent(chEvent);
			  //console.log('ccdev save 620',chEvent.defaultPrevented, chEvent.bubbles, chEvent.type);
			  
            } else
            { this.copyElm.value = this.getContent();
              this.e.innerHTML = this.getContent();
              //console.log('ccdev save 624', this.getContent());

              var chEvent = new Event('change');
              this.e.dispatchEvent(chEvent);
            }
		}	
		/*
		if(this.copyElm || this.options.hasPanel) {
			this.ne.fireEvent('save',this);
			(this.copyElm) ? this.copyElm.value = this.getContent() : this.e.innerHTML = this.getContent();
		}*/	
	},	
	
	getElm : function() {
		return this.elm;
	},
	
	getContent : function() {
		//console.log('ccdev getContent 639', this.copyElm);
		this.content = this.getElm().innerHTML;
		this.ne.fireEvent('get',this);
		return this.content;
	},
	
	setContent : function(e) {
		this.content = e;
		this.ne.fireEvent('set',this);
		this.elm.innerHTML = this.content;	
	},
	
	nicCommand : function(cmd,args) {
		document.execCommand(cmd,false,args);
	}		
});

var nicEditorIFrameInstance = nicEditorInstance.extend({
	savedStyles : [],
	
	init : function() {	
		var c = this.elm.innerHTML.replace(/^\s+|\s+$/g, '');
		this.elm.innerHTML = '';
		(!c) ? c = "<br />" : c;
		this.initialContent = c;
		
		this.elmFrame = new bkElement('iframe')
								.setAttributes({'src' : 'javascript:;', 'frameBorder' : 0, 'allowTransparency' : 'true', 'scrolling' : 'no'})
							    .setStyle({height: '100%', width: '100%'})
							    .addClass('frame').appendTo(this.elm);

		if(this.copyElm) { this.elmFrame.setStyle({width : (this.elm.offsetWidth-4)+'px'}); }
		
		var styleList = ['font-size','font-family','font-weight','color'];
		for(itm in styleList) {
			this.savedStyles[bkLib.camelize(itm)] = this.elm.getStyle(itm);
		}
     	
		setTimeout(this.initFrame.closure(this),50);
	},
	
	disable : function() {
		console.log('ccdev disable 681', this.copyElm, this.getContent());
		this.elm.innerHTML = this.getContent();
	},
	
	initFrame : function() {
		var fd = $BK(this.elmFrame.contentWindow.document);
		fd.designMode = "on";		
		fd.open();
		var css = this.ne.options.externalCSS;
		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>');
		fd.close();
		this.frameDoc = fd;

		this.frameWin = $BK(this.elmFrame.contentWindow);
		this.frameContent = $BK(this.frameWin.document.body).setStyle(this.savedStyles);
		this.instanceDoc = this.frameWin.document.defaultView;
		
		this.heightUpdate();
		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));
		this.ne.fireEvent('add',this);
	},
	
	getElm : function() {
		return this.frameContent;
	},
	
	setContent : function(c) {
		console.log('ccdev setContent 708', this.copyElm, this.getContent());
		this.content = c;
		this.ne.fireEvent('set',this);
		this.frameContent.innerHTML = this.content;	
		this.heightUpdate();
	},
	
	getSel : function() {
		return (this.frameWin) ? this.frameWin.getSelection() : this.frameDoc.selection;
	},
	
	heightUpdate : function() {	
		this.elmFrame.style.height = Math.max(this.frameContent.offsetHeight,this.initialHeight)+'px';
	},
    
	nicCommand : function(cmd,args) {
		this.frameDoc.execCommand(cmd,false,args);
		setTimeout(this.heightUpdate.closure(this),109);
	}

	
});

var nicEditorPanel = bkClass.extend({
	construct : function(e,options,nicEditor) {
		//console.log('ccdev 648', nicEditor.options.buttons);
		this.elm = e;
		this.options = options;
		this.ne = nicEditor;
		//console.log('ccdev 648', this.ne.options.buttons);
		this.panelButtons = new Array();
		this.buttonList = bkExtend([],this.ne.options.buttonList);
		
		this.panelContain = new bkElement('DIV')
			.setStyle({overflow : 'hidden', width : '100%', backgroundColor : 'transparent', marginBottom : '.75rem'})
		    .addClass('panelContain');
		this.panelElm = new bkElement('DIV')									
		    .addClass('toolbar wysiwyg__toolbar')
			.appendTo(this.panelContain);
		this.panelContain.appendTo(e);

		var opt = this.ne.options;
		var buttons = opt.buttons;
		var _t=this;
		//console.log('ccdev 722', buttons);
		Object.keys(buttons).forEach(function(button,index) {
			_t.addButton(button,opt,true);
		});
		/*
		for(button in buttons) {
				this.addButton(button,opt,true);
		}*/
		this.reorder();
		e.noSelect();
	},
	
	addButton : function(buttonName,options,noOrder) {
		var button = options.buttons[buttonName];
		//var type = (button['type']) ? eval('(typeof('+button['type']+') == "undefined") ? null : '+button['type']+';') : nicEditorButton;
		var type;
		if(button['type']) // this is to avoid using eval which fails to minify & work under npm run build
		{ 	switch(button['type']) {
				case 'nicEditorBgColorButton':
					type = nicEditorBgColorButton;
					break;
				case 'nicImageButton':
					type = nicImageButton;
					break;
				case 'nicEditorFontSizeSelect':
					type = nicEditorFontSizeSelect;
					break;
				case 'nicEditorFontFamilySelect':
					type = nicEditorFontFamilySelect;
					break;
				case 'nicEditorFontFormatSelect':
					type = nicEditorFontFormatSelect;
					break;
				case 'nicLinkButton':
					type = nicLinkButton;
					break;
				case 'nicEditorSaveButton':
					type = nicEditorSaveButton;
					break;
				case 'nicCodeButton':
					type = nicCodeButton;
					break;
				case 'nicSmallButton':
					type = nicSmallButton;
					break;	
				case 'nicBlockButton':
					type = nicBlockButton;
					break;
				case 'nicInsertTable':
					type = nicInsertTable;
					break;
				default: //fall back, but eval does not minify nor work 'under npm run build'
					if( eval('typeof('+button['type']+')') == "undefined" )
					{	type = null;
					} else
					{	type = eval(button['type']);
		    		}
			}
			if(type==null)
				console.warn('ccdev 777 **WARINING**', 'You have to add your button class, "'+ button['type']+'", to the select for it to work with "npm run build"');
			
			//console.info('ccdev 780', button['type']);
		} else
		{ type = nicEditorButton;
		}

		var hasButton = bkLib.inArray(this.buttonList,buttonName);
		if(type && (hasButton || this.ne.options.fullPanel)) {
			this.panelButtons.push(new type(this.panelElm, buttonName, options, this.ne));
			if(!hasButton) {	
				this.buttonList.push(buttonName);
			}
		}
	},
	
	findButton : function(itm) {
		for(var i=0;i<this.panelButtons.length;i++) {
			if(this.panelButtons[i].name == itm)
				return this.panelButtons[i];
		}	
	},
	
	reorder : function() {
		var bl = this.buttonList;
		for(var i=0;i<bl.length;i++) {
			var button = this.findButton(bl[i]);
			if(button) {
				this.panelElm.appendChild(button.margin);
			}
		}	
	},
	
	remove : function() {
		this.elm.remove();
	}
});

var nicEditorButton = bkClass.extend({
	
	construct : function(e,buttonName,options,nicEditor) {
		this.options = options.buttons[buttonName];
		this.name = buttonName;
		this.ne = nicEditor;
		this.elm = e;

		//console.info('ccdev 821', buttonName);
		this.margin = new bkElement('DIV').setStyle({})
                                          .addClass('icon wysiwyg__icon')
		                                  .appendTo(e);
		this.contain = new bkElement('DIV').setStyle({width : 'var(--space-8)', height : 'var(--space-8)'})
		                                   .addClass('buttonContain')
										   .appendTo(this.margin);
		this.border = new bkElement('DIV').setStyle({backgroundColor : '#efefef'})
		                                  .appendTo(this.contain);
		this.button = new bkElement('DIV').setStyle({width : 'var(--space-8)', height : 'var(--space-8)', overflow : 'hidden', zoom : 1, cursor : 'pointer'})
		                                  .addClass('button')
										  .setStyle(this.ne.getIcon(buttonName,options))
										  .appendTo(this.border);
                                          
		this.button.addEvent('mouseover', this.hoverOn.closure(this))
		           .addEvent('mouseout',this.hoverOff.closure(this))
				   .addEvent('mousedown',this.mouseClick.closure(this))
				   .noSelect();
		
		if(!window.opera) {
			this.button.onmousedown = this.button.onclick = bkLib.cancelEvent;
		}
		
		nicEditor.addEvent('selected', this.enable.closure(this))
		         .addEvent('blur', this.disable.closure(this))
				 .addEvent('key',this.key.closure(this));
		
		this.disable();
		this.init();
	},
	
	init : function() {  },
	
	hide : function() {
		this.contain.setStyle({display : 'none'});
	},
	
	updateState : function() {
		if (this.isDisabled) { 
            this.setBg();
        } else if (this.isHover) { 
            this.setBg('hover'); 
        } else if (this.isActive) { 
            console.log(this);
            this.setBg('active'); 
        } else { 
            this.setBg(); 
        }
	},
	
	setBg : function(state) {
		switch(state) {
			case 'hover':
				var stateStyle = {backgroundColor : 'var(--button-primary-muted-hover-bg)', borderColor : 'var(--button-primary-muted-border-color)', color : 'var(--button-primary-muted-color)'};
				break;
			case 'active':
				var stateStyle = {backgroundColor : 'var(--button-primary-muted-active-bg)', borderColor : 'var(--button-primary-muted-border-color)', color : 'var(--button-primary-muted-active-color)'};
				break;
			default:
				var stateStyle = {borderRadius : 'var(--rounded-sm)', backgroundColor : 'transparent', transition : 'all 300ms ease-in-out'};	
		}
		this.border.setStyle(stateStyle).addClass('button-'+state);
	},
	
	checkNodes : function(e) {
		var elm = e;	
		do {
			if(this.options.tags && bkLib.inArray(this.options.tags,elm.nodeName)) {
				this.activate();
				return true;
			}
		} while(elm = elm.parentNode && elm.className != "nicEdit");
		elm = $BK(e);
		while(elm.nodeType == 3) {
			elm = $BK(elm.parentNode);
		}
		if(this.options.css) {
			var _t=this;
			var _return=null;
			Object.keys(this.options.css).forEach(function(itm,index) {
				if(elm.getStyle(itm,_t.ne.selectedInstance.instanceDoc) == _t.options.css[itm]) {
					_t.activate();
					//return true;
					_return=true;
				}
			});
			if(_return!=null)
				return _return;
			/*
			for(itm in this.options.css) {
				if(elm.getStyle(itm,this.ne.selectedInstance.instanceDoc) == this.options.css[itm]) {
					this.activate();
					return true;
				}
			}*/
		}
		this.deactivate();
		return false;
	},
	
	activate : function() {
		if(!this.isDisabled) {
			this.isActive = true;
			this.updateState();	
			this.ne.fireEvent('buttonActivate',this);
		}
	},
	
	deactivate : function() {
		this.isActive = false;
		this.updateState();	
		if(!this.isDisabled) {
			this.ne.fireEvent('buttonDeactivate',this);
		}
	},
	
	enable : function(ins,t) {
		this.isDisabled = false;
		this.contain.setStyle({'opacity' : 1}).addClass('buttonEnabled');
		this.updateState();
		this.checkNodes(t);
	},
	
	disable : function(ins,t) {		
		this.isDisabled = true;
		this.contain.setStyle({'opacity' : 0.6}).removeClass('buttonEnabled');
		this.updateState();	
	},
	
	toggleActive : function() {
		(this.isActive) ? this.deactivate() : this.activate();	
	},
	
	hoverOn : function() {
		if(!this.isDisabled) {
			this.isHover = true;
			this.updateState();
			this.ne.fireEvent("buttonOver",this);
		}
	}, 
	
	hoverOff : function() {
		this.isHover = false;
		this.updateState();
		this.ne.fireEvent("buttonOut",this);
	},
	
	mouseClick : function() {
		if(this.options.command) {
			this.ne.nicCommand(this.options.command,this.options.commandArgs);
			if(!this.options.noActive) {
				this.toggleActive();
			}
		}
		this.ne.fireEvent("buttonClick",this);
	},
	
	key : function(nicInstance,e) {
		if(this.options.key && e.ctrlKey && String.fromCharCode(e.keyCode || e.charCode).toLowerCase() == this.options.key) {
			this.mouseClick();
			if(e.preventDefault) e.preventDefault();
		}
	}
	
});

var nicPlugin = bkClass.extend({
	
	construct : function(nicEditor,options) {
		this.options = options;
		this.ne = nicEditor;
		this.ne.addEvent('panel',this.loadPanel.closure(this));
		this.init();
	},

	loadPanel : function(np) {
		var buttons = this.options.buttons;
		//for(var button in buttons) {
		var _t=this;
		Object.keys(buttons).forEach(function(button,index) {
			np.addButton(button,_t.options);
		});
		np.reorder();
	},

	init : function() {  }
});
 
 /* START CONFIG */
var nicPaneOptions = { };
/* END CONFIG */
var nicEditorPane = bkClass.extend({
	construct : function(elm,nicEditor,options,openButton) {
		this.ne = nicEditor;
		this.elm = elm;
		this.pos = elm.pos();
		
		this.contain = new bkElement('div').setStyle({zIndex : '99999', overflow : 'hidden', position : 'absolute', left : this.pos[0]+'px', top : this.pos[1]+'px'})
		this.pane = new bkElement('div').setStyle({}).addClass('overlay wysiwyg__overlay').setStyle(options).appendTo(this.contain);
		
		if(openButton && !openButton.options.noClose) {
			this.close = new bkElement('div')
            .setStyle({})
            .setStyle(this.ne.getIcon('close',nicPaneOptions))
            .addClass('overlay-close wysiwyg__overlay-close')
            .addEvent('mousedown',openButton.removePane
            .closure(this))
            .appendTo(this.pane);
		}
		
		this.contain.noSelect().appendTo(document.body);
		
		this.position();
		this.init();	
	},
	
	init : function() { },
	
	position : function() {
		if(this.ne.nicPanel) {
			var panelElm = this.ne.nicPanel.elm;	
			var panelPos = panelElm.pos();
			var newLeft = panelPos[0]+parseInt(panelElm.getStyle('width'))-(parseInt(this.pane.getStyle('width'))+8);
			if(newLeft < this.pos[0]) {
				this.contain.setStyle({left : newLeft+'px'});
			}
		}
	},
	
	toggle : function() {
		this.isVisible = !this.isVisible;
		this.contain.setStyle({display : ((this.isVisible) ? 'block' : 'none')});
	},
	
	remove : function() {
		if(this.contain) {
			this.contain.remove();
			this.contain = null;
		}
	},
	
	append : function(c) {
		c.appendTo(this.pane);
	},
	
	setContent : function(c) {
		this.pane.setContent(c);
	}
	
});



// ------------------------------------------------------------------------------------------------------------------------
// advanced-button --	Panel button with support for opening a nicPane with configuration form
export var nicEditorAdvancedButton = nicEditorButton.extend({
	
	init : function() {
		this.ne.addEvent('selected',this.removePane.closure(this)).addEvent('blur',this.removePane.closure(this));	
	},
	
	mouseClick : function() {
		if(!this.isDisabled) {
			if(this.pane && this.pane.pane) {
				this.removePane();
			} else {
				this.pane = new nicEditorPane(this.contain,this.ne,{width : (this.width || '270px'), backgroundColor : '#fff'},this);
				this.addPane();
				this.ne.selectedInstance.saveRng();
			}
		}
	},
	
	addForm : function(f,elm) {
		this.form = new bkElement('form').addEvent('submit',this.submit.closureListener(this));
		this.pane.append(this.form);
		this.inputs = {};
		
		//for(itm in f) {
        var _t=this;
		Object.keys(f).forEach(function(itm,index) {
			var field = f[itm];
			var val = '';
			if(elm) {
				val = elm.getAttribute(itm);
			}
			if(!val) {
				val = field['value'] || '';
			}
			var type = f[itm].type;
			
			if(type == 'title') {
					new bkElement('div').setContent(field.txt)
					                    .setStyle({})
                                        .addClass('title font-semi-bold text-body-secondary mb-3')
                                        .appendTo(_t.form);
			} else {
				var contain = new bkElement('div').setStyle()
                                                  .addClass('form-group wysiwyg__form-group')
				                                  .appendTo(_t.form);
				if(field.txt) {
					new bkElement('label').setAttributes({'for' : itm})
					                      .setContent(field.txt)
                                          .addClass('label wysiwyg__label')
					                      .setStyle({})
										  .appendTo(contain);
				}
				
				switch(type) {
					case 'text':
						_t.inputs[itm] = new bkElement('input')
						                     .setAttributes({id : itm, 'value' : val, 'type' : 'text'})
						                     .setStyle({})
                                             .addClass('input wysiwyg__input')
											 .setStyle(field.style)
											 .appendTo(contain);
						break;
					case 'select':
						_t.inputs[itm] = new bkElement('select').setAttributes({id : itm})
						                                        .setStyle({})
                                                                .addClass('input wysiwyg__input')
																.appendTo(contain);
						//for(opt in field.options) {
						Object.keys(field.options).forEach(function(opt,index) {
							var o = new bkElement('option').setAttributes({value : opt, selected : (opt == val) ? 'selected' : ''})
							                               .setContent(field.options[opt])
														   .appendTo(_t.inputs[itm]);
						});
						break;
					case 'content':
						_t.inputs[itm] = new bkElement('textarea').setAttributes({id : itm})
						                                          .setStyle({border : '1px solid #ccc', 'float' : 'left'})
                                                                  .addClass('input wysiwyg__input')
																  .setStyle(field.style)
																  .appendTo(contain);
						_t.inputs[itm].value = val;
					}
			}
		});
		new bkElement('input')
            .setAttributes({'type': 'submit'})
		    .setStyle({})
            .addClass('button wysiwyg__button')
			.appendTo(this.form);
		this.form.onsubmit = bkLib.cancelEvent;	
	},
	
	submit : function() { },
	
	findElm : function(tag,attr,val) {
		var list = this.ne.selectedInstance.getElm().getElementsByTagName(tag);
		for(var i=0;i<list.length;i++) {
			if(list[i].getAttribute(attr) == val) {
				return $BK(list[i]);
			}
		}
	},
	
	removePane : function() {
		if(this.pane) {
			this.pane.remove();
			this.pane = null;
			this.ne.selectedInstance.restoreRng();
		}	
	}	
});



// ------------------------------------------------------------------------------------------------------------------------
//button-tips -- Tooltips when buttons are moused over describing their function
var nicButtonTips = bkClass.extend({
	construct : function(nicEditor) {
		this.ne = nicEditor;
		nicEditor.addEvent('buttonOver',this.show.closure(this)).addEvent('buttonOut',this.hide.closure(this));

	},
	
	show : function(button) {
		this.timer = setTimeout(this.create.closure(this,button),400);
	},
	
	create : function(button) {
		this.timer = null;
		if(!this.pane) {
			this.pane = new nicEditorPane(button.button,this.ne,{fontSize : '12px', marginTop : '5px'});
            this.pane.pane.setAttribute('data-type', 'tooltip');
			this.pane.setContent(button.options.name);
		}		
	},
	
	hide : function(button) {
		if(this.timer) {
			clearTimeout(this.timer);
		}
		if(this.pane) {
			this.pane = this.pane.remove();
		}
	}
});
nicEditors.registerPlugin(nicButtonTips);



// ------------------------------------------------------------------------------------------------------------------------
//select-options -- Provides base select box class and font family, font size, and heading selects
/* START CONFIG */
var nicSelectOptions = {
	buttons : {
		'fontSize' : {name : __('Select Font Size'), type : 'nicEditorFontSizeSelect', command : 'fontsize'},
		'fontFamily' : {name : __('Select Font Family'), type : 'nicEditorFontFamilySelect', command : 'fontname'},
		'fontFormat' : {name : __('Select Font Format'), type : 'nicEditorFontFormatSelect', command : 'formatBlock'}
	}
};
/* END CONFIG */
var nicEditorSelect = bkClass.extend({
	
	construct : function(e,buttonName,options,nicEditor) {
		this.options = options.buttons[buttonName];
		this.elm = e;
		this.ne = nicEditor;
		this.name = buttonName;
		this.selOptions = new Array();
		
		this.margin = new bkElement('div').setStyle({'float' : 'left', marginRight : '1rem'})
								.appendTo(this.elm);
		this.contain = new bkElement('div').setStyle({'min-width' : '20rem'})
								.addClass('selectContain')
								.addEvent('click',this.toggle.closure(this))
								.appendTo(this.margin);
		this.items = new bkElement('div').setStyle({overflow : 'hidden', zoom : 1, backgroundColor : 'transparent'})
								.appendTo(this.contain);
		this.control = new bkElement('div').setStyle({overflow : 'hidden', 'position' : 'absolute', height: '18px', width : '16px', display : 'none'})
								.addClass('selectControl')
								.setStyle(this.ne.getIcon('arrow',options))
								.appendTo(this.items);
		this.txt = new bkElement('div').setStyle({})
								.addClass('selectTxt select')
								.appendTo(this.items);
		
		if(!window.opera) {
			this.contain.onmousedown = this.control.onmousedown = this.txt.onmousedown = bkLib.cancelEvent;
		}
		
		this.margin.noSelect();
		
		this.ne.addEvent('selected', this.enable.closure(this)).addEvent('blur', this.disable.closure(this));
		
		this.disable();
		this.init();
	},
	
	disable : function() {
		this.isDisabled = true;
		this.close();
		this.contain.setStyle({opacity : 0.6});
	},
	
	enable : function(t) {
		this.isDisabled = false;
		this.close();
		this.contain.setStyle({opacity : 1});
	},
	
	setDisplay : function(txt) {
		this.txt.setContent(txt);
	},
	
	toggle : function() {
		if(!this.isDisabled) {
			(this.pane) ? this.close() : this.open();
		}
	},
	
	open : function() {
		this.pane = new nicEditorPane(this.items,this.ne,{width : '20rem', padding: '0px', overflow : 'hidden', border : 'var(--form-input-border-width) solid var(--form-input-border-color)', borderRadius : 'var(--form-input-border-radius)', backgroundColor : 'var(--form-input-bg)', boxShadow : 'var(--shadow-lg)', marginTop : 'var(--space-1)'});
		
		for(var i=0;i<this.selOptions.length;i++) {
			var opt = this.selOptions[i];
			var itmContain = new bkElement('div')
									.setStyle({overflow : 'hidden', borderBottom : 'var(--form-input-border-width) solid var(--form-input-border-color)', width: '100%', textAlign : 'left', cursor : 'pointer'})
			var itm = new bkElement('div').setStyle({}).addClass('option menu__item').setContent(opt[1]).appendTo(itmContain).noSelect();
			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]);
			this.pane.append(itmContain);
			if(!window.opera) {
				itm.onmousedown = bkLib.cancelEvent;
			}
		}
	},
	
	close : function() {
		if(this.pane) {
			this.pane = this.pane.remove();
		}	
	},
	
	over : function(opt) {
		opt.setStyle({});			
	},
	
	out : function(opt) {
		opt.setStyle({});
	},
	
	
	add : function(k,v) {
		this.selOptions.push(new Array(k,v));	
	},
	
	update : function(elm) {
		this.ne.nicCommand(this.options.command,elm);
		this.close();	
	}
});

var nicEditorFontSizeSelect = nicEditorSelect.extend({
	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)'},
	init : function() {
		this.setDisplay('Font&nbsp;Size...');

		var _t=this;
		Object.keys(this.sel).forEach(function(itm,index) {
			_t.add(itm,'<font size="'+itm+'">'+_t.sel[itm]+'</font>');
		});
		/*for(itm in this.sel) {
			this.add(itm,'<font size="'+itm+'">'+this.sel[itm]+'</font>');
		}*/		
	}
});

var nicEditorFontFamilySelect = nicEditorSelect.extend({
	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'},
	
	init : function() {
		this.setDisplay('Font&nbsp;Family...');

		var _t=this;
		Object.keys(this.sel).forEach(function(itm,index) {
			_t.add(itm,'<font face="'+itm+'">'+_t.sel[itm]+'</font>');
		});
		/*for(itm in this.sel) {
			this.add(itm,'<font face="'+itm+'">'+this.sel[itm]+'</font>');
		}*/
	}
});

var nicEditorFontFormatSelect = nicEditorSelect.extend({
		sel : {'p' : 'Paragraph', 'pre' : 'Pre', 'h6' : 'Heading&nbsp;6', 'h5' : 'Heading&nbsp;5', 'h4' : 'Heading&nbsp;4', 'h3' : 'Heading&nbsp;3', 'h2' : 'Heading&nbsp;2', 'h1' : 'Heading&nbsp;1'},
		
	init : function() {
		this.setDisplay('Font&nbsp;Format...');

		var _t=this;
		Object.keys(this.sel).forEach(function(itm,index) {
			var tag = itm.toUpperCase();
			_t.add('<'+tag+'>','<'+itm+' style="font: inherit;">'+_t.sel[itm]+'</'+tag+'>');
		});
		/*for(itm in this.sel) {
			var tag = itm.toUpperCase();
			this.add('<'+tag+'>','<'+itm+' style="padding: 0px; margin: 0px;">'+this.sel[itm]+'</'+tag+'>');
		}*/
	}
});
nicEditors.registerPlugin(nicPlugin, nicSelectOptions);



// ------------------------------------------------------------------------------------------------------------------------
//link-options -- Adds buttons to create page links in nicEdit
/* START CONFIG */
var nicLinkOptions = {
	buttons : {
		'link' : {name : 'Add Link', type : 'nicLinkButton', tags : ['A']},
		'unlink' : {name : 'Remove Link',  command : 'unlink', noActive : true}
	}
};
/* END CONFIG */

var nicLinkButton = nicEditorAdvancedButton.extend({
	init: function() {
		//console.log('ccdev 1448',this.ne.nicPanel.elm);
        //this.ne.nicPanel.elm
		document.addEventListener('keydown', (event) => { 
			if(this.handleKeyDown) //we attached it to the document, so we need tests
			{	//needs to pass this otherwise it will fire on all nicedits
				this.handleKeyDown(event, this);
			}
		});
    },

    handleKeyDown: function(event, t) {
		if((event.metaKey || event.ctrlKey) //windows is control macos is meta
					&& event.key==='k' 
					&& event.target.classList.contains('nicEdit-selected'))
		{
			// console.log('ccdev 1461', event, event.target.classList.contains('nicEdit-selected'),
			// 		 t.ne);
			this.mouseClick();
			if(event.preventDefault) event.preventDefault();
			if(event.stopPropagation) event.stopPropagation();
        }
    },

    addPane: function() {
        this.ln = this.ne.selectedInstance.selElm().parentTag('A');
        this.addForm({
            '' : {type : 'title', txt : 'Add/Edit Link'},
            'href' : {type : 'text', txt : 'URL', value : '/'},
            'title' : {type : 'text', txt : 'Title'},
            'target' : {type : 'select', txt : 'Open in', options : {'' : 'Current tab', '_blank' : 'New tab'}, style : {width : '100%'}}
        }, this.ln);
    },

    submit : function(e) {
			var url = this.inputs['href'].value;
			if(url == "http://" || url == "") {
				alert("You must enter a URL to Create a Link");
				return false;
			}
			this.removePane();
			
			if(!this.ln) {
				var tmp = 'javascript:nicTemp();';
				this.ne.nicCommand("createlink",tmp);
				this.ln = this.findElm('A','href',tmp);
			}
			if(this.ln) {
				this.ln.setAttributes({
					href : this.inputs['href'].value,
					title : this.inputs['title'].value,
					target : this.inputs['target'].options[this.inputs['target'].selectedIndex].value
				});
			}
		}
});

nicEditors.registerPlugin(nicPlugin, nicLinkOptions);




// ------------------------------------------------------------------------------------------------------------------------
// color-options -- Provides buttons to control the foreground and background color of text
/* START CONFIG */
var nicColorOptions = {
	buttons : {
		'forecolor' : {name : __('Change Text Color'), type : 'nicEditorColorButton', noClose : true},
		'bgcolor' : {name : __('Change Background Color'), type : 'nicEditorBgColorButton', noClose : true}
	}
};
/* END CONFIG */

var nicEditorColorButton = nicEditorAdvancedButton.extend({	
	addPane : function() {
			var colorList = {0 : '00',1 : '33',2 : '66',3 :'99',4 : 'CC',5 : 'FF'};
			var colorItems = new bkElement('DIV').setStyle({width: '270px'});
			
			for(var r in colorList) {
				for(var b in colorList) {
					for(var g in colorList) {
						var colorCode = '#'+colorList[r]+colorList[g]+colorList[b];
						
						var colorSquare = new bkElement('DIV').setStyle({'cursor' : 'pointer', 'height' : '15px', 'float' : 'left'})
												.appendTo(colorItems);
						var colorBorder = new bkElement('DIV').setStyle({border: '2px solid '+colorCode})
												.appendTo(colorSquare);
						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);
						
						if(!window.opera) {
							colorSquare.onmousedown = colorInner.onmousedown = bkLib.cancelEvent;
						}

					}	
				}	
			}
			this.pane.append(colorItems.noSelect());	
	},
	
	colorSelect : function(c) {
		this.ne.nicCommand('foreColor',c);
		this.removePane();
	},
	
	on : function(colorBorder) {
		colorBorder.setStyle({border : '2px solid #000'});
	},
	
	off : function(colorBorder,colorCode) {
		colorBorder.setStyle({border : '2px solid '+colorCode});		
	}
});

var nicEditorBgColorButton = nicEditorColorButton.extend({
	colorSelect : function(c) {
		this.ne.nicCommand('hiliteColor',c);
		this.removePane();
	}	
});

nicEditors.registerPlugin(nicPlugin,nicColorOptions);


/* START CONFIG */
var nicImageOptions = {
	buttons : {
		'image' : {name : 'Add Image', type : 'nicImageButton', tags : ['IMG']}
	}
};
/* END CONFIG */
var nicImageButton = nicEditorAdvancedButton.extend({	
	addPane : function() {
		this.im = this.ne.selectedInstance.selElm().parentTag('IMG');
		this.addForm({
			'' : {type : 'title', txt : 'Add/Edit Image'},
			'src' : {type : 'text', txt : 'URL', 'value' : '/', style : {width: 'calc(100% - 6em)'}},
			'alt' : {type : 'text', txt : 'Alt Text', style : {width: 'calc(100% - 6em)'}},
			'align' : {type : 'select', txt : 'Align', options : {none : 'Default','left' : 'Left', 'right' : 'Right'}}
		},this.im);
	},
	
	submit : function(e) {
		var src = this.inputs['src'].value;
		if(src == "" || src == "http://") {
			alert("You must enter a Image URL to insert");
			return false;
		}
		this.removePane();

		if(!this.im) {
			var tmp = 'javascript:nicImTemp();';
			this.ne.nicCommand("insertImage",tmp);
			this.im = this.findElm('IMG','src',tmp);
		}
		if(this.im) {
			this.im.setAttributes({
				src : this.inputs['src'].value,
				alt : this.inputs['alt'].value,
				align : this.inputs['align'].value
			});
		}
	}
});
nicEditors.registerPlugin(nicPlugin,nicImageOptions);



/* START CONFIG */
var nicSaveOptions = {
	buttons : {
		'save' : {name : __('Save this content'), type : 'nicEditorSaveButton'}
	}
};
/* END CONFIG */
var nicEditorSaveButton = nicEditorButton.extend({
	init : function() {
		if(!this.ne.options.onSave) {
			this.margin.setStyle({'display' : 'none'});
		}
	},
	mouseClick : function() {
		var onSave = this.ne.options.onSave;
		var selectedInstance = this.ne.selectedInstance;
		onSave(selectedInstance.getContent(), selectedInstance.elm.id, selectedInstance);
	}
});
nicEditors.registerPlugin(nicPlugin,nicSaveOptions);


// ------------------------------------------------------------------------------------------------------------------------
// floating panel option
nicEditor = nicEditor.extend({
        floatingPanel : function() {
                this.floating = new bkElement('DIV').setStyle({position: 'absolute', top : '-1000px'}).appendTo(document.body);
                this.addEvent('focus', this.reposition.closure(this)).addEvent('blur', this.hide.closure(this));
                this.setPanel(this.floating);
        },
        
        reposition : function() {
                var e = this.selectedInstance.e;
				var wide = (parseInt(e.getStyle('width')) || e.clientWidth) + 'px' ;
                this.floating.setStyle({ width : wide });
                var top = e.offsetTop-this.floating.offsetHeight;
                if(top < 0) {
                        top = e.offsetTop+e.offsetHeight;
                }
                
                this.floating.setStyle({ top : top+'px', left : e.offsetLeft+'px', display : 'block' });
        },
        
        hide : function() {
                this.floating.setStyle({ top : '-1000px'});
        }
});


// ------------------------------------------------------------------------------------------------------------------------
// edit html code option
/* START CONFIG */
var nicCodeOptions = {
	buttons : {
		'xhtml' : {name : 'Edit HTML', type : 'nicCodeButton'}
	}	
};
/* END CONFIG */
var nicCodeButton = nicEditorAdvancedButton.extend({
	width : '350px',
		
	addPane : function() {
		this.addForm({
			'' : {type : 'title', txt : 'Edit HTML'},
			'code' : {type : 'content', 'value' : this.ne.selectedInstance.getContent(), style : {width: '340px', height : '200px'}}
		});
	},
	
	submit : function(e) {
		var code = this.inputs['code'].value;
		this.ne.selectedInstance.setContent(code);
		this.removePane();
	}
});
nicEditors.registerPlugin(nicPlugin,nicCodeOptions);



// ------------------------------------------------------------------------------------------------------------------------
/**-----------------------
 *  INSERT INDENTED BLOCK
 * --------- IAN J v0.001
 */
/* START CONFIG */
import imgBlockUrl from './nicIblock.gif'

var nicBlockOptions = {
	buttons : {
		'iblock' : {name : 'Insert Block', type : 'nicBlockButton', noClose : true}
	}
	,iconFiles : {'iblock' : imgBlockUrl}
};
/* END CONFIG */

var nicBlockButton = nicEditorAdvancedButton.extend({
  addPane : function() {
	var colorList = {0 : '00',1 : '33',2 : '66',3 :'99',4 : 'CC',5 : 'FF'};
	var colorItems = new bkElement('DIV').setStyle({width: '270px'});
	
	for(var r in colorList) {
		for(var b in colorList) {
			for(var g in colorList) {
				var colorCode = '#'+colorList[r]+colorList[g]+colorList[b];
				var colorSquare = new bkElement('DIV').setStyle({'cursor' : 'pointer', 'height' : '15px', 'float' : 'left'})
										.appendTo(colorItems);
				var colorBorder = new bkElement('DIV').setStyle({border: '2px solid '+colorCode})
										.appendTo(colorSquare);
				var colorInner = new bkElement('DIV')
										.setStyle({backgroundColor : colorCode, overflow : 'hidden', width : '11px', height : '11px'})
										.addEvent('click',this.colorSelect.closure(this,colorCode))
										.addEvent('mouseover',this.highlight.closure(this,colorBorder, '#'+contrastingColor(colorCode.substr(1))))
										.addEvent('mouseout',this.highlight.closure(this,colorBorder,colorCode))
										.appendTo(colorBorder);
					
				if(!window.opera)
				{	colorSquare.onmousedown = colorInner.onmousedown = bkLib.cancelEvent;
				}
			}	
		}	
	}
	var colorSquare = new bkElement('DIV')
							.setStyle({'cursor' : 'pointer', 'height' : '15px', 'float' : 'left'})
							.appendTo(colorItems);
	var colorBorder = new bkElement('DIV')
							.setStyle({border: '1px solid white'})
							.appendTo(colorSquare);
	var colorInner = new bkElement('DIV')
							.setStyle({backgroundColor : '#FFF', overflow : 'hidden', width : '22px', height : '11px', fontSize: '9px'})
							.addEvent('click',this.cleariblock.closure(this))
							.addEvent('mouseover',this.highlight.closure(this,colorBorder,'#000'))
							.addEvent('mouseout',this.highlight.closure(this,colorBorder,'#FFF'))
							.setContent('OFF')
							.appendTo(colorBorder);
		
	this.pane.append(colorItems.noSelect());
  },
  cleariblock : function()
  { this.removePane();
	var p = this.ne.selectedInstance.selElm().parentTag('P');
	if(p)
	{ p.setAttributes({ style:'' });
	}
  },
  colorSelect : function(c)
  { var contrast = '#'+contrastingColor(c.substr(1));
	this.removePane();
	
	var style = "background-color:"+c+";color:"+contrast+";";
	var p = this.ne.selectedInstance.selElm().parentTag('P');
	if(!p)
	{ p = this.ne.selectedInstance.selElm().parentTag('DIV');
	}

	if(p)
	{ p.setAttributes({ style, niceditiblock:"1" });
	  p.addClass('iblock');
	} else
	{ this.ne.nicCommand('insertHTML','<div class="nicEdit-iblock" style="'+style+'">indented para</div>');
	}
  },
  highlight : function(colorBorder,colorCode)
  { colorBorder.setStyle({border : '2px solid '+colorCode});
  }
});

function contrastingColor(color)
{ return (luma(color) >= 165) ? '000' : 'fff';
}
function luma(color) // color can be a hx string or an array of RGB values 0-255
{ var rgb = (typeof color === 'string') ? hexToRGBArray(color) : color;
  return (0.2126 * rgb[0]) + (0.7152 * rgb[1]) + (0.0722 * rgb[2]); // SMPTE C, Rec. 709 weightings
}
function hexToRGBArray(color)
{ if (color.length === 3)
    color = color.charAt(0) + color.charAt(0) + color.charAt(1) + color.charAt(1) + color.charAt(2) + color.charAt(2);
  else if (color.length !== 6)
    throw('Invalid hex color: ' + color);

  var rgb = [];
  for (var i = 0; i <= 2; i++)
    rgb[i] = parseInt(color.substr(i * 2, 2), 16);

  return rgb;
}
nicEditors.registerPlugin(nicPlugin, nicBlockOptions);



// ------------------------------------------------------------------------------------------------------------------------
/**--------------
 *  INSERT TABLE
 * --- Ian J v0.001
 */
 import imgTableUrl from './nicItable.gif'

/* START CONFIG */
var nicTableOptions = {
	buttons : {
		'itable' : {name : 'Insert Table', type : 'nicInsertTable', noClose : true}
	}
	/* NICEDIT_REMOVE_START */
	,iconFiles : {'itable' : imgTableUrl}
	/* NICEDIT_REMOVE_END */
};
/* END CONFIG */

var nicInsertTable = nicEditorAdvancedButton.extend({

	addPane : function() {
		var pdiv = new bkElement('DIV');
		var info = new bkElement('DIV').setContent('Insert Table...&nbsp;').appendTo(pdiv);
		for(var y=1; y<=20; y++)
		{	
			for(var x=1; x<=17; x++)
			{
				var colorSquare = new bkElement('DIV').setStyle({'cursor' : 'pointer', 'height' : '11px', 'float' : 'left'})
										.appendTo(pdiv);
				//if(x==1)
				//	cSquare.setStyle({'clear': 'both'});
				
				var colorBorder = new bkElement('DIV').setStyle({border: '2px solid silver', position: 'relative'})
										.appendTo(colorSquare);
				var colorInner = new bkElement('DIV')
										.setStyle({overflow : 'hidden', width : '11px', height : '11px'})
										.addEvent('click',this.insTable.closure(this,x,y))
										.addEvent('mouseover',this.on.closure(this,colorBorder, info, x, y))
										.addEvent('mouseout',this.off.closure(this,colorBorder, info, x, y))
										.appendTo(colorBorder);
					
				if(!window.opera)
				{	colorSquare.onmousedown = colorInner.onmousedown = bkLib.cancelEvent;
				}
			}
		}
		this.pane.append(pdiv.noSelect());
	},
  insTable : function(x,y)
  { this.removePane();

	var min=Math.min(101,5+x*5);
	var html='<table style="min-width:'+min+'%;">';
	for(var cy=1; cy<=y; cy++)
	{   html+="<tr>";
		for(var cx=1; cx<=x; cx++)
			html+='<td>&nbsp;</td>';
		html+='</tr>';
	}
	html+="</table>"
	this.ne.nicCommand('insertHTML',html);
  },
  on : function(colorBorder, info, x, y)
  { colorBorder.setStyle({border : '2px solid #000', zindex:99});
    info.setContent('Insert Table:'+x+','+y);
  },
  off : function(colorBorder, info, x, y)
  { colorBorder.setStyle({border : '2px solid silver', zindex:1});
    info.setContent('Insert Table...&nbsp;');
  }
});
nicEditors.registerPlugin(nicPlugin,nicTableOptions);

/* START CONFIG */
var nicSmallOptions = {
    buttons : {
        'smalltext' : {name : __('Small Text'), type : 'nicSmallButton'}
    }
	/* NICEDIT_REMOVE_END */
};
/* END CONFIG */
 
var nicSmallButton = nicEditorButton.extend({   
  mouseClick : function(e) {
    document.execCommand('styleWithCSS',false,true);
    var fontSize = window.getSelection().anchorNode.parentNode.style.fontSize;

	document.execCommand('fontSize',false, (fontSize == 'x-small' || fontSize == '1' || fontSize == 1) ? 3 : 1);
  }
});
 
nicEditors.registerPlugin(nicPlugin,nicSmallOptions);

// ------------------------------------------------------------------------------------------------------------------------
// edit html code option

//convert richtexteditor areas to nicedits
document.addEventListener('DOMContentLoaded', () => {
    //nicEditors.allTextAreas();
	console.log('ccdev 1789');
    nicEditors.byQrySelectorAll('textarea[richtexteditor]:not([style*="display:none"]');
	console.log('ccdev 1791');
});