938 lines
26 KiB
JavaScript
938 lines
26 KiB
JavaScript
/**
|
|
* NicEdit - Micro Inline WYSIWYG
|
|
* Copyright 2007-2008 Brian Kirchoff, http://nicedit.com/
|
|
* Copyright 2012-2015 Vitaliy Filippov, http://yourcmc.ru/wiki/nicEdit
|
|
* Version: 2015-07-13
|
|
*
|
|
* NicEdit is distributed under the terms of the MIT license
|
|
* Do not remove this copyright message
|
|
*/
|
|
|
|
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;
|
|
},
|
|
|
|
removeAllEvents : function() {
|
|
bkLib.removeAllEvents(this);
|
|
return this;
|
|
},
|
|
|
|
setContent : function(c) {
|
|
this.innerHTML = c;
|
|
return this;
|
|
},
|
|
|
|
pos : function() {
|
|
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];
|
|
},
|
|
|
|
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;
|
|
}
|
|
});
|
|
|
|
var bkLib = {
|
|
isMSIE : (navigator.appVersion.indexOf("MSIE") != -1),
|
|
|
|
addEvent : function(obj, type, fn) {
|
|
obj._bkE = obj._bkE||[];
|
|
obj._bkE.push([type, fn]);
|
|
(obj.addEventListener) ? obj.addEventListener( type, fn, false ) : obj.attachEvent("on"+type, fn);
|
|
},
|
|
|
|
removeEvent : function(obj, type, fn) {
|
|
(obj.removeEventListener) ? obj.removeEventListener( type, fn, false ) : obj.detachEvent("on"+type, fn);
|
|
},
|
|
|
|
removeAllEvents : function(obj) {
|
|
if (!obj._bkE) return;
|
|
for (var i = 0; i < obj._bkE.length; i++) {
|
|
bkLib.removeEvent(obj,obj._bkE[i][0],obj._bkE[i][1]);
|
|
}
|
|
obj._bkE = [];
|
|
},
|
|
|
|
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) {
|
|
var e = document.createElement('script');
|
|
e.setAttribute('defer', 'defer');
|
|
e.setAttribute('src', location.protocol == "https:" ? "javascript:void(0)" : "//0");
|
|
(document.head || document.documentElement).appendChild(e);
|
|
e.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);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
if (!__) {
|
|
__ = 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) );
|
|
};
|
|
}
|
|
|
|
|
|
/* START CONFIG */
|
|
|
|
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 : '../nicEditorIcons.gif',
|
|
buttonList : ['save','bold','italic','underline','strikethrough','left','center','right','justify','ol','ul','fontSize','fontFamily','fontFormat','image','upload','link','unlink','removeformat','forecolor','bgcolor','indent','outdent','subscript','superscript','xhtml','table'],
|
|
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":24,"arrow":26,"upload":27,"table":28}
|
|
|
|
});
|
|
/* END CONFIG */
|
|
|
|
|
|
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;
|
|
},
|
|
|
|
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));
|
|
var st = document.createElement('style');
|
|
st.appendChild(document.createTextNode(".nicEdit-main p { margin: .3em 0; }"));
|
|
(document.head || document.documentElement).appendChild(st);
|
|
},
|
|
|
|
panelInstance : function(e,o) {
|
|
e = this.checkReplace($BK(e));
|
|
var panelElm = new bkElement('DIV').setStyle({width : (parseInt(e.getStyle('width')) || e.clientWidth)+'px'}).appendBefore(e);
|
|
this.setPanel(panelElm);
|
|
return this.addInstance(e,o);
|
|
},
|
|
|
|
checkReplace : function(e) {
|
|
var r = nicEditors.findEditor(e);
|
|
if(r) {
|
|
r.removeInstance(e);
|
|
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) {
|
|
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)*-18) : 0)+'px 0px'};
|
|
},
|
|
|
|
selectCheck : function(e,t) {
|
|
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 || {};
|
|
|
|
newX = parseInt(e.getStyle('width')) || e.clientWidth;
|
|
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+'px',
|
|
border: '1px solid #ccc',
|
|
boxSizing: 'border-box',
|
|
overflowY: 'auto',
|
|
overflowX: 'hidden'
|
|
};
|
|
s[ie7s ? 'height' : 'maxHeight'] = isTextarea ? newY+'px' : (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: (newX-10)+'px',
|
|
padding: '4px',
|
|
minHeight: (newY-10)+'px'
|
|
}).addClass('main').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');
|
|
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.elm.removeAllEvents();
|
|
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) return;
|
|
if (s.rangeCount > 0) {
|
|
return s.getRangeAt(0);
|
|
} else if (typeof s.createRange == 'undefined') {
|
|
return document.createRange();
|
|
}
|
|
return 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());
|
|
}
|
|
},
|
|
|
|
selBlockType : function() {
|
|
var e = this.selElm();
|
|
var t = {'P':1,'PRE':1,'H1':1,'H2':1,'H3':1,'H4':1,'H5':1,'H6':1};
|
|
while (e != this.elm) {
|
|
if (t[e.nodeName]) {
|
|
return e.nodeName;
|
|
}
|
|
e = e.parentNode;
|
|
}
|
|
return false;
|
|
},
|
|
|
|
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.keyCode == 13 || e.keyCode == 10) {
|
|
if (!e.shiftKey && !this.selBlockType()) {
|
|
this.ne.nicCommand('formatBlock', 'p');
|
|
}
|
|
}
|
|
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');
|
|
}
|
|
return false;
|
|
},
|
|
|
|
blur : function() {
|
|
this.isFocused = false;
|
|
this.elm.removeClass('selected');
|
|
},
|
|
|
|
saveContent : function() {
|
|
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() {
|
|
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) {
|
|
this.elm.focus();
|
|
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: '100px', 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() {
|
|
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) {
|
|
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),100);
|
|
}
|
|
|
|
|
|
});
|
|
var nicEditorPanel = bkClass.extend({
|
|
construct : function(e,options,nicEditor) {
|
|
this.elm = e;
|
|
this.options = options;
|
|
this.ne = nicEditor;
|
|
this.panelButtons = new Array();
|
|
this.buttonList = bkExtend([],this.ne.options.buttonList);
|
|
|
|
this.panelContain = new bkElement('DIV').setStyle({overflow : 'hidden', width : '100%', border : '1px solid #cccccc', backgroundColor : '#efefef'}).addClass('panelContain');
|
|
this.panelElm = new bkElement('DIV').setStyle({margin : '2px', marginTop : '0px', zoom : 1, overflow : 'hidden'}).addClass('panel').appendTo(this.panelContain);
|
|
this.panelContain.appendTo(e);
|
|
|
|
var opt = this.ne.options;
|
|
var buttons = opt.buttons;
|
|
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 = null;
|
|
|
|
if (button['type']) {
|
|
type = typeof(window[button['type']]) == undefined ? null : window[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;
|
|
|
|
this.margin = new bkElement('DIV').setStyle({'float' : 'left', marginTop : '2px'}).appendTo(e);
|
|
this.contain = new bkElement('DIV').setStyle({width : '20px', height : '20px'}).addClass('buttonContain').appendTo(this.margin);
|
|
this.border = new bkElement('DIV').setStyle({backgroundColor : '#efefef', border : '1px solid #efefef'}).appendTo(this.contain);
|
|
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);
|
|
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) { this.setBg('active'); }
|
|
else { this.setBg(); }
|
|
},
|
|
|
|
setBg : function(state) {
|
|
switch(state) {
|
|
case 'hover':
|
|
var stateStyle = {border : '1px solid #666', backgroundColor : '#ddd'};
|
|
break;
|
|
case 'active':
|
|
var stateStyle = {border : '1px solid #666', backgroundColor : '#ccc'};
|
|
break;
|
|
default:
|
|
var stateStyle = {border : '1px solid #efefef', backgroundColor : '#efefef'};
|
|
}
|
|
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) {
|
|
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) {
|
|
np.addButton(button,this.options);
|
|
}
|
|
np.reorder();
|
|
},
|
|
|
|
init : function() { }
|
|
});
|
|
|