Compare commits

...

No commits in common. "master" and "old-orig" have entirely different histories.

18 changed files with 2312 additions and 2103 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.DS_Store

8
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,8 @@
## Bug and Feature Requests
Please read through the [issues](https://github.com/danishkhan/NicEdit/issues). If you do not see an issue created yet
for your bug then [create an issue](https://github.com/danishkhan/NicEdit/issues/new).
Make sure to outline what the bug is. If you know how to fix the bug yourself please send a
[pull request](https://github.com/danishkhan/NicEdit/pulls).

View File

@ -1,6 +1,6 @@
NicEdit License
Copyright (c) 2007-2008 Brian Kirchoff [(http://nicedit.com)](http://nicedit.com), (c) 2012+ Vitaliy Filippov (vitalif@mail.ru)
Copyright (c) 2007-2008 Brian Kirchoff [(http://nicedit.com)](http://nicedit.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View File

@ -1,12 +1,7 @@
nicEdit is a lightweight, Cross Platform WYSIWYG editor
Lightweight, Cross Platform WYSIWYG editor.
This is my (Vitaliy Filippov's) fork of nicEdit which I use in my projects since 2012.
If you have any problems please create an issue.
It has several improvements:
* Table plugin
* Example plugins for "wiki-like CMS integrated" image uploads and link insertions
* Russian localisation
* Reworked nicFloatingPanel
* Sanitize pasted HTML plugin (removes all the crap that MSWord inserts)
Pull requests are welcomed and greatly appreciated.
Not sure if it's easy to merge all this to upstream, but I'll try... maybe :)
Project is a member of the [OSS Manifesto](http://ossmanifesto.org/)

37
demos/demo01.html Normal file
View File

@ -0,0 +1,37 @@
<html>
<head>
<title>Demo 1 : Convert All Textareas</title>
</head>
<body>
<div id="menu"></div>
<div id="intro">
By calling the nicEditors.allTextareas() function the below example replaces all 3 textareas on the page with nicEditors. NicEditors will match the size of the editor window with the size of the textarea it replaced.
</div>
<br />
<div id="sample">
<script type="text/javascript" src="../nicEdit.js"></script>
<script type="text/javascript">
bkLib.onDomLoaded(function() { nicEditors.allTextAreas() });
</script>
<h4>First Textarea</h4>
<textarea name="area1" cols="40"></textarea>
<br />
<h4>Second Textarea</h4>
<textarea name="area2" style="width: 100%;">
Some Initial Content was in this textarea
</textarea>
<br />
<h4>Third Textarea</h4>
<textarea name="area3" style="width: 300px; height: 100px;">
HTML <b>content</b> <i>default</i> in textarea
</textarea>
</div>
</body>
</html>

57
demos/demo02.html Normal file
View File

@ -0,0 +1,57 @@
<html>
<head>
<title>Demo 2 : NicEdit Configuration</title>
</head>
<body>
<div id="menu"></div>
<div id="intro">
<p>NicEdit is highly configurable by passing the configuration when you create the NicEditor. Pass your configuration when you call:</p>
<p>new NicEditor({CONFIG HERE})</p>
<p>Add .panelInstance('ID TO TEXTAREA HERE') to add the editor to the textarea.</p>
<p>See the examples below:</p>
</div>
<br />
<div id="sample">
<script src="../nicEdit.js" type="text/javascript"></script>
<script type="text/javascript">
bkLib.onDomLoaded(function() {
new nicEditor().panelInstance('area1');
new nicEditor({fullPanel : true}).panelInstance('area2');
new nicEditor({iconsPath : '../nicEditorIcons.gif'}).panelInstance('area3');
new nicEditor({buttonList : ['fontSize','bold','italic','underline','strikeThrough','subscript','superscript','html','image']}).panelInstance('area4');
new nicEditor({maxHeight : 100}).panelInstance('area5');
});
</script>
<h4>Default (No Config Specified)</h4>
<p>new nicEditor().panelInstance('area1');</p>
<textarea cols="50" id="area1"></textarea>
<h4>All Available Buttons {fullPanel : true}</h4>
<p>new nicEditor({fullPanel : true}).panelInstance('area2');</p>
<textarea cols="60" id="area2">Some Initial Content was in this textarea</textarea>
<h4>Change Path to Icon File {iconsPath : 'path/to/nicEditorIcons.gif'}</h4>
<p>new nicEditor({iconsPath : 'nicEditorIcons.gif'}).panelInstance('area3');</p>
<textarea cols="50" id="area3"></textarea>
<h4>Customize the Panel Buttons/Select List</h4>
<p>{buttonList : ['fontSize','bold','italic','underline','strikeThrough','subscript','superscript']}</p>
<textarea cols="50" id="area4">HTML <b>content</b> <i>default</i> in textarea</textarea>
<h4>Set a maximum expansion size (maxHeight)</h4>
<p>{maxHeight : 100}</p>
<textarea style="height: 100px;" cols="50" id="area5">HTML <b>content</b> <i>default</i> in textarea</textarea>
</div>
</div>
</body>
</html>

56
demos/demo03.html Normal file
View File

@ -0,0 +1,56 @@
<html>
<head>
<title>Demo 3 : Add/Remove NicEditors</title>
</head>
<body>
<div id="menu"></div>
<div id="intro">
<p>The demo below shows toggling the display of NicEditors on both textarea and div elements. NicEdit instances can be added and removed at any time</p>
</div>
<br />
<div id="sample">
<h4>Div Example</h4>
<div id="myArea1" style="width: 300px; height: 100px; border: 1px solid #000;">
This is some TEST CONTENT<br />
In a DIV Tag<br />
Click the Buttons to activate
</div>
<button onClick="toggleArea1();">Toggle DIV Editor</button>
<br /><br />
<h4>Textarea Example</h4>
<div>
<textarea style="width: 300px; height: 100px;" id="myArea2"></textarea>
<br />
<button onClick="addArea2();">Add Editor to TEXTAREA</button> <button onClick="removeArea2();">Remove Editor from TEXTAREA</button>
</div>
<div style="clear: both;"></div>
<script src="../nicEdit.js" type="text/javascript"></script>
<script>
var area1, area2;
function toggleArea1() {
if(!area1) {
area1 = new nicEditor({fullPanel : true}).panelInstance('myArea1',{hasPanel : true});
} else {
area1.removeInstance('myArea1');
area1 = null;
}
}
function addArea2() {
area2 = new nicEditor({fullPanel : true}).panelInstance('myArea2');
}
function removeArea2() {
area2.removeInstance('myArea2');
}
bkLib.onDomLoaded(function() { toggleArea1(); });
</script>
</div>
</body>
</html>

49
demos/demo04.html Normal file
View File

@ -0,0 +1,49 @@
<html>
<head>
<title>Demo 4 : Inline NicEditors</title>
</head>
<body>
<div id="menu"></div>
<div id="intro">
<p>In addition to replacing textareas NicEdit instances can also replace any element (divs,spans,paragraphs,ect.) with editor instances without effecting the layout of the page. As you will see in other examples content can be saved via AJAX to the server or retrieved from javascript</p>
<p>To make use of Inline Editing you should first create an empty element as a placeholder for the Editor Panel. In this case I use a div with id="myNicPanel" set. Its usually a good idea to set a width on element but it is not required.</p>
</div>
<div id="sample">
<script src="../nicEdit.js" type="text/javascript"></script>
<script type="text/javascript">
bkLib.onDomLoaded(function() {
var myNicEditor = new nicEditor();
myNicEditor.setPanel('myNicPanel');
myNicEditor.addInstance('myInstance1');
myNicEditor.addInstance('myInstance2');
myNicEditor.addInstance('myInstance3');
});
</script>
This is text above the Panel
<div id="myNicPanel" style="width: 525px;"></div>
This is text below the Panel
<br /><br />
<h4>Inline Div</h4>
<div id="myInstance1" style="font-size: 16px; background-color: #ccc; padding: 3px; border: 5px solid #000; width: 400px;">
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed magna dolor, faucibus ac, iaculis non, cursus et, dui. Donec non urna. Aliquam volutpat ornare augue. Phasellus egestas, nisl fermentum porttitor rutrum, magna metus rutrum risus, id fringilla magna mi nec lorem. Etiam eget metus sed justo ultricies rhoncus. Praesent rhoncus arcu non dolor. Proin eu eros. Curabitur vehicula. Nulla vehicula lectus eget eros. Nulla vel nulla at dui dictum mollis. Etiam purus felis, pretium vel, eleifend id, consectetuer nec, purus. Vivamus pretium orci ac sapien. Etiam at tortor. Nunc tincidunt mi sed sapien. Etiam lacus pede, fermentum eu, blandit ac, congue eget, metus. Quisque sed sem. Mauris at sapien. Ut luctus.
</div>
<br />
<h4>Inline Span</h4>
<span id="myInstance2" style="display: block;">
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed magna dolor, faucibus ac, iaculis non, cursus et, dui. Donec non urna. Aliquam volutpat ornare augue. Phasellus egestas, nisl fermentum porttitor rutrum, magna metus rutrum risus, id fringilla magna mi nec lorem. Etiam eget metus sed justo ultricies rhoncus. Praesent rhoncus arcu non dolor. Proin eu eros. Curabitur vehicula. Nulla vehicula lectus eget eros. Nulla vel nulla at dui dictum mollis. Etiam purus felis, pretium vel, eleifend id, consectetuer nec, purus. Vivamus pretium orci ac sapien. Etiam at tortor. Nunc tincidunt mi sed sapien. Etiam lacus pede, fermentum eu, blandit ac, congue eget, metus. Quisque sed sem. Mauris at sapien. Ut luctus.
</span>
<br />
<h4>Inline Paragraph</h4>
<p id="myInstance3" style="border: 1px solid #000;">This is some text that can be edited in the inline paragraph editor.</p>
</div>
</body>
</html>

54
demos/demo05.html Normal file
View File

@ -0,0 +1,54 @@
<html>
<head>
<title>Demo 5 : Editor Styles</title>
<style type="text/css">
#myInstance1 {
border: 2px dashed #0000ff;
}
.nicEdit-selected {
border: 2px solid #0000ff !important;
}
.nicEdit-panel {
background-color: #fff !important;
}
.nicEdit-button {
background-color: #fff !important;
}
</style>
</head>
<body>
<div id="menu"></div>
<div id="intro">
<p>NicEdit instances and the panel can be styled using CSS classes to fit the look and feel of your site.</p>
</div>
<div id="sample">
<script src="../nicEdit.js" type="text/javascript"></script>
<script type="text/javascript">
bkLib.onDomLoaded(function() {
var myNicEditor = new nicEditor();
myNicEditor.setPanel('myNicPanel');
myNicEditor.addInstance('myInstance1');
});
</script>
This is text above the Panel
<div id="myNicPanel" style="width: 350px;"></div>
This is text below the Panel
<br /><br />
<h4>Selected Style Example</h4>
<div id="myInstance1" style="font-size: 16px; background-color: #ccc; padding: 3px; width: 400px;">
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed magna dolor, faucibus ac, iaculis non, cursus et, dui. Donec non urna. Aliquam volutpat ornare augue. Phasellus egestas, nisl fermentum porttitor rutrum, magna metus rutrum risus, id fringilla magna mi nec lorem. Etiam eget metus sed justo ultricies rhoncus. Praesent rhoncus arcu non dolor. Proin eu eros. Curabitur vehicula. Nulla vehicula lectus eget eros. Nulla vel nulla at dui dictum mollis. Etiam purus felis, pretium vel, eleifend id, consectetuer nec, purus. Vivamus pretium orci ac sapien. Etiam at tortor. Nunc tincidunt mi sed sapien. Etiam lacus pede, fermentum eu, blandit ac, congue eget, metus. Quisque sed sem. Mauris at sapien. Ut luctus.
</div>
</body>
</html>

3363
nicEdit.js Normal file → Executable file

File diff suppressed because it is too large Load Diff

BIN
nicEditorIcons.gif Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -1,154 +0,0 @@
/** nicImage */
/* 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' : 'http://', style : {width: '150px'}},
'alt' : {type : 'text', txt : __('Alt Text'), style : {width: '100px'}},
'align' : {type : 'select', txt : __('Align'), options : {none : __('Inline'),'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,
title : this.inputs['alt'].value,
align : this.inputs['align'].value
});
}
}
});
nicEditors.registerPlugin(nicPlugin,nicImageOptions);
/** nicUpload */
/* START CONFIG */
var nicUploadOptions = {
buttons : {
'upload' : {name : __('Upload Image'), type : 'nicUploadButton'}
}
};
/* END CONFIG */
var nicUploadButton = nicEditorAdvancedButton.extend({
nicURI : 'http://api.imgur.com/2/upload.json',
errorText : __('Failed to upload image'),
addPane : function() {
if(typeof window.FormData === "undefined") {
return this.onError(__("Image uploads are not supported in this browser, use Chrome, Firefox, or Safari instead."));
}
this.im = this.ne.selectedInstance.selElm().parentTag('IMG');
var container = new bkElement('div')
.setStyle({ padding: '10px' })
.appendTo(this.pane.pane);
new bkElement('div')
.setStyle({ fontSize: '14px', fontWeight : 'bold', paddingBottom: '5px' })
.setContent(__('Insert an Image'))
.appendTo(container);
this.fileInput = new bkElement('input')
.setAttributes({ 'type' : 'file' })
.appendTo(container);
this.progress = new bkElement('progress')
.setStyle({ width : '100%', display: 'none' })
.setAttributes('max', 100)
.appendTo(container);
this.fileInput.onchange = this.uploadFile.closure(this);
},
onError : function(msg) {
this.removePane();
alert(msg || __("Failed to upload image"));
},
uploadFile : function() {
var file = this.fileInput.files[0];
if (!file || !file.type.match(/image.*/)) {
this.onError(__("Only image files can be uploaded"));
return;
}
this.fileInput.setStyle({ display: 'none' });
this.setProgress(0);
var fd = new FormData(); // https://hacks.mozilla.org/2011/01/how-to-develop-a-html5-image-uploader/
fd.append("image", file);
fd.append("key", "b7ea18a4ecbda8e92203fa4968d10660");
var xhr = new XMLHttpRequest();
xhr.open("POST", this.ne.options.uploadURI || this.nicURI);
xhr.onload = function() {
try {
var res = JSON.parse(xhr.responseText);
} catch(e) {
return this.onError();
}
this.onUploaded(res.upload);
}.closure(this);
xhr.onerror = this.onError.closure(this);
xhr.upload.onprogress = function(e) {
this.setProgress(e.loaded / e.total);
}.closure(this);
xhr.send(fd);
},
setProgress : function(percent) {
this.progress.setStyle({ display: 'block' });
if(percent < .98) {
this.progress.value = percent;
} else {
this.progress.removeAttribute('value');
}
},
onUploaded : function(options) {
this.removePane();
var src = options.links.original;
if(!this.im) {
this.ne.selectedInstance.restoreRng();
var tmp = 'javascript:nicImTemp();';
this.ne.nicCommand("insertImage", src);
this.im = this.findElm('IMG','src', src);
}
var w = parseInt(this.ne.selectedInstance.elm.getStyle('width'));
if(this.im) {
this.im.setAttributes({
src : src,
width : (w && options.image.width) ? Math.min(w, options.image.width) : ''
});
}
}
});
nicEditors.registerPlugin(nicPlugin,nicUploadOptions);

View File

@ -1,245 +0,0 @@
/** nicImageUploadGT (Image + Upload + Lightbox support) -- example image uploads integrated with wiki-like site CMS */
/* START CONFIG */
var nicImageUploadGTOptions = {
buttons: {
'image': {name: __('Add Image'), type: 'nicImageUploadGTButton', tags: ['IMG']}
}
};
/* END CONFIG */
var nicImageUploadGTButton = nicEditorAdvancedButton.extend({
addPane: function() {
this.im = (this.selElm || this.ne.selectedInstance.selElm()).parentTag('IMG');
var s, params = this.parseParams(this.im);
this.addForm({
'': {type: 'title', txt: __('Add/Edit Image')},
'src': {type: 'text', txt: __('URL or Name'), style: {width: '150px'}},
'upload': {type: 'container', txt: __('Or upload')},
'href': {type: 'text', txt: __('Hyperlink'), style: {width: '150px'}},
'size': {type: 'container', txt: __('Max Size')},
'align': {type: 'select', txt: __('Align'), options: {'': __('Inline'), floatleft: __('Left'), floatright: __('Right')}},
'alt': {type: 'text', txt: __('Popup text'), style: {width: '150px'}}
}, params);
this.hinter = new SimpleAutocomplete(this.inputs['src'], this.gtLoadData.closure(this), {
emptyText: false,
allowHTML: true
});
s = this.inputs['href'].parentNode;
new bkElement('br').appendTo(s);
this.inputs['newwindow'] = new bkElement('input').setAttributes({type: 'checkbox', id: 'newwindow', checked: 1 && params.newwindow}).appendTo(s);
new bkElement('label').setAttributes({htmlFor: 'newwindow'}).setContent(__('Open in new window')).appendTo(s);
var self = this;
s = this.inputs['upload'];
this.inputs['fileName'] = new bkElement('input').setStyle({width: '150px', height: '20px'}).setAttributes({type: 'button', value: __('Select file')}).appendTo(s);
this.inputs['fileName'].addEvent('click', function() { self.inputs['file'].click(); });
this.inputs['file'] = new bkElement('input').setStyle({ width: '150px', position: 'absolute', left: '0', top: '-100px' }).setAttributes({type: 'file', size: 5}).appendTo(s);
this.inputs['file'].addEvent('change', this.onFileChange.closure(this));
new bkElement('br').appendTo(s);
this.inputs['progress'] = new bkElement('progress')
.setStyle({ width: '100%', display: 'none' })
.setAttributes('max', 100)
.appendTo(s);
s = this.inputs['size'];
this.inputs['width'] = new bkElement('input').setAttributes({type: 'text', size: 5, value: params.width||''}).appendTo(s);
s.appendChild(document.createTextNode(' x '));
this.inputs['height'] = new bkElement('input').setAttributes({type: 'text', size: 5, value: params.height||''}).appendTo(s);
},
onFileChange: function() {
this.inputs['src'].value = '';
this.inputs['fileName'].value = this.inputs['file'].files[0].name;
},
checkNodes: function(e) {
var r = nicEditorAdvancedButton.prototype.checkNodes.apply(this, [e]);
this.selElm = r ? e : null;
return r;
},
parseParams: function(elm) {
var r = { getAttribute: function(n) { return this[n]; } };
if (!elm) return r;
if (elm.parentNode.nodeName == 'A') {
r.href = elm.parentNode.href;
if (r.href.substr(0, GT.domain.length+10) == GT.domain+'/file.php?' ||
r.href.substr(0, 9) == 'file.php?') {
// Clear lightbox link
r.href = '';
}
if (elm.parentNode.target == '_blank') {
r.newwindow = true;
}
} else {
r.href = '-';
}
r.align = elm.className;
var abs = elm.src.substr(0, GT.domain.length+10) == GT.domain+'/file.php?';
if (abs || elm.src.substr(0, 9) == 'file.php?') {
var id, p, m = elm.src.substr(abs ? GT.domain.length+10 : 9).split('&');
for (var i = 0; i < m.length; i++) {
p = m[i].split('=', 2);
if (p[0] == 'id') {
id = p[1];
} else if (p[0] == 'w') {
r.width = p[1];
} else if (p[0] == 'h') {
r.height = p[1];
}
}
r.src = '#'+id+' - '+elm.title;
} else {
r.src = elm.src;
r.width = elm.style.maxWidth.replace('px', '');
r.height = elm.style.maxHeight.replace('px', '');
}
r.alt = elm.alt;
return r;
},
removePane: function() {
if (this.hinter) {
this.hinter.remove();
this.hinter = null;
}
nicEditorAdvancedButton.prototype.removePane.apply(this);
},
gtLoadData: function(hint, value, more) {
POST(GT.domain+'/api.php?action=listimgs&format=json', {value: value, more: more}, function(r){
try { hint.replaceItems(JSON.parse(r.responseText), more > 0); }
catch(e) {}
});
},
submit: function(e) {
if (!this.inputs['src'].value && this.inputs['file'].files[0]) {
// Upload the file, then continue from a callback
this.uploadFile();
return false;
}
var src = this.inputs['src'].value;
var gtId = /^#(\d+)(\s*-\s*)?(.*)/.exec(src);
var alt = this.inputs['alt'].value;
var style = {};
var w = this.inputs['width'].value;
var h = this.inputs['height'].value;
if (!/^[1-9]\d*$/.exec(w)) w = '';
if (!/^[1-9]\d*$/.exec(h)) h = '';
if (gtId && gtId[1]) {
if (!alt) {
alt = gtId[3];
}
// Save relative path to the page text
// FIXME This will work only for the same level pages, but OK
src = 'file.php?action=thumb&id='+gtId[1]+'&w='+w+'&h='+h;
} else if (/^https?:\/\/./.exec(src)) {
if (w) style.maxWidth = w+'px';
if (h) style.maxHeight = h+'px';
} else {
alert(__('To insert an image you must select uploaded file ID or enter the image URL!'));
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) {
var lnk = {
href: this.inputs['href'].value,
target: this.inputs['newwindow'].checked ? '_blank' : '',
title: alt
};
if (lnk.href.substr(0, GT.domain.length) == GT.domain) {
var l = lnk.href.substr(GT.domain.length+1).replace(/^\/+/, '');
if (/^[a-z_]/.exec(l)) {
lnk.href = l;
}
}
if (!lnk.href.length) {
if (gtId && gtId[1] && (w || h)) {
// If link URL is not '-', add lightbox (relative path)
lnk.href = 'file.php?action=thumb&id='+gtId[1];
lnk.target = '_blank';
lnk.rel = 'lightbox';
} else {
lnk.href = '-';
}
}
var p = $BK(this.im.parentNode);
if (p.nodeName != 'A' && lnk.href != '-') {
p = $BK(document.createElement('A'));
this.im.parentNode.insertBefore(p, this.im);
p.appendChild(this.im);
}
if (p && p.nodeName == 'A') {
if (lnk.href != '-') {
p.setAttributes(lnk);
} else {
p.parentNode.appendChild(this.im);
p.removeChild(parentNode);
}
}
this.im.setStyle(style).setAttributes({ src: src, alt: alt, title: alt })
.className = this.inputs['align'].value;
}
},
uploadFile: function() {
var file = this.inputs['file'].files[0];
if (!file || !file.type.match(/image.*/)) {
alert(__("Only image files can be uploaded"));
return;
}
this.inputs['file'].setStyle({display: 'none'});
this.setProgress(0);
var fd = new FormData(); // https://hacks.mozilla.org/2011/01/how-to-develop-a-html5-image-uploader/
fd.append("e_file", file);
fd.append("e_title", file.name);
var self = this;
var xhr = new XMLHttpRequest();
xhr.open("POST", GT.domain+'/file.php?action=save&format=json');
xhr.onload = function() {
try { var res = JSON.parse(xhr.responseText); } catch(e) {}
if (res && (res.file || res.duplicate)) {
self.onUploaded(res);
} else {
alert(__('Failed to upload image') + (res && (res.exception || res.error) ? ': '+(res.exception || res.error) : ''));
}
};
xhr.onerror = function(e) { alert(__('Error uploading file')+': '+e); };
xhr.upload.onprogress = function(e) {
self.setProgress(e.loaded / e.total);
};
xhr.send(fd);
},
onUploaded: function(r) {
var f = r.file||r.duplicate;
this.inputs['src'].value = '#'+f.id+' - '+f.title;
this.submit();
},
setProgress: function(percent) {
var p = this.inputs['progress'];
p.setStyle({display: 'block'});
if(percent < .98) {
p.value = percent;
} else {
p.removeAttribute('value');
}
},
});
nicEditors.registerPlugin(nicPlugin,nicImageUploadGTOptions);

View File

@ -1,46 +0,0 @@
/** nicLink */
/* 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({
addPane : function() {
this.ln = this.ne.selectedInstance.selElm().parentTag('A');
this.addForm({
'' : {type : 'title', txt : __('Add/Edit Link')},
'href' : {type : 'text', txt : 'URL', value : 'http://', style : {width: '150px'}},
'title' : {type : 'text', txt : __('Hint')},
'target' : {type : 'select', txt : __('Open In'), options : {'' : __('Current Window'), '_blank' : __('New Window')},style : {width : '100px'}}
},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);

View File

@ -1,92 +0,0 @@
/** nicLinkGT -- example link insertion integrated with wiki-like site CMS */
/* START CONFIG */
var nicLinkGTOptions = {
buttons: {
link: {name: __('Add Link'), type: 'nicLinkGTButton', tags: ['A']},
unlink: {name: __('Remove Link'), command: 'unlink', noActive: true}
}
};
/* END CONFIG */
var nicLinkGTButton = nicEditorAdvancedButton.extend({
addPane: function() {
this.ln = this.ne.selectedInstance.selElm().parentTag('A');
this.addForm({
'': {type: 'title', txt: __('Add/Edit Link')},
'href': {type: 'text', txt: __('URL or Page'), value: '', style: {width: '150px'}},
'title': {type: 'text', txt: __('Hint')},
'target': {type: 'select', txt: __('Open In'), options: {'': __('Current Window'), '_blank': __('New Window')}, style: {width: '100px'}}
}, this.parseParams(this.ln || {}));
this.hinter = new SimpleAutocomplete(this.inputs['href'], this.gtLoadData.closure(this), {
emptyText: false,
allowHTML: true
});
},
parseParams: function(elm) {
var r = { getAttribute: function(n) { return this[n]; } };
r.href = elm.href || '';
if (r.href.substr(0, GT.domain.length+10) == GT.domain+'/page.php?' ||
r.href.substr(0, 9) == 'page.php?') {
var m = /[\?&]alias=([^\?&]+)/.exec(r.href);
if (m) {
r.href = '#'+m[1]+' - '+elm.title;
}
}
r.title = elm.title;
r.target = elm.target;
return r;
},
gtLoadData: function(hint, value) {
POST(GT.domain+'/api.php?action=listpages&format=json', {value: value}, function(r){
try { hint.replaceItems(JSON.parse(r.responseText)); }
catch(e) {}
});
},
submit: function(e) {
var url = this.inputs['href'].value;
var title = this.inputs['title'].value;
if(url == "http://" || url == "") {
alert(__("You must enter a URL to Create a Link"));
return false;
}
var gtId = /^#(\S+)\s+-(\s*(.+))?/.exec(url);
if (gtId) {
url = 'page.php?alias='+gtId[1];
if (!title && gtId[3]) {
title = gtId[3];
}
}
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.ne.nicCommand("insertHTML",'<a href="'+tmp+'">'+(title||url)+'</a>');
this.ln = this.findElm('A','href',tmp);
}
}
if(this.ln) {
this.ln.setAttributes({
href: url,
title: title,
target: this.inputs['target'].options[this.inputs['target'].selectedIndex].value
});
}
},
removePane: function() {
if (this.hinter) {
this.hinter.remove();
this.hinter = null;
}
nicEditorAdvancedButton.prototype.removePane.apply(this);
}
});
nicEditors.registerPlugin(nicPlugin,nicLinkGTOptions);

103
nicRu.js
View File

@ -1,103 +0,0 @@
/* Russian localisation for NicEdit - Micro Inline WYSIWYG
* Copyright 2012 Vitaliy Filippov
*
* This file is distributed under the terms of the MIT license
*/
var nicRu = {
'Submit': 'Сохранить',
'Click to Bold': 'Полужирный',
'Click to Italic': 'Курсив',
'Click to Underline': 'Подчёркнутый',
'Left Align': 'По левому краю',
'Center Align': 'По центру',
'Right Align': 'По правому краю',
'Justify Align': 'По ширине',
'Insert Ordered List': 'Нумерованный список',
'Insert Unordered List': 'Маркированный список',
'Click to Subscript': 'Нижний индекс',
'Click to Superscript': 'Верхний индекс',
'Click to Strike Through': 'Зачёркнутый',
'Remove Formatting': 'Убрать форматирование',
'Indent Text': 'Увеличить отступ',
'Remove Indent': 'Уменьшить отступ',
'Horizontal Rule': 'Горизонтальная линия',
'Font&nbsp;Size...': 'Размер...',
'Font&nbsp;Family...': 'Шрифт...',
'Font&nbsp;Format...': 'Формат...',
'Select Font Size': 'Выберите размер шрифта',
'Select Font Family': 'Выберите шрифт',
'Select Font Format': 'Выберите формат абзаца',
'Sans-Serif': 'Беззасечный',
'Serif': 'С засечками',
'Fantasy': 'Декоративный',
'Monospace': 'Моноширинный',
'Cursive': 'Рукописный',
'Paragraph': 'Обычный',
'Pre': 'Код',
'Heading&nbsp;6': 'Заголовок&nbsp;6',
'Heading&nbsp;5': 'Заголовок&nbsp;5',
'Heading&nbsp;4': 'Заголовок&nbsp;4',
'Heading&nbsp;3': 'Заголовок&nbsp;3',
'Heading&nbsp;2': 'Заголовок&nbsp;2',
'Heading&nbsp;1': 'Заголовок&nbsp;1',
'Change Text Color': 'Цвет текста',
'Change Background Color': 'Цвет фона',
'Save this content': 'Сохранить',
'Add Link': 'Вставить ссылку',
'URL or Page': 'URL или страница',
'Remove Link': 'Убрать ссылку',
'Add/Edit Link': 'Ссылка',
'Hint': 'Подсказка',
'Open In': 'Открыть',
'Current Window': 'В этом окне',
'New Window': 'В новом окне',
'You must enter a URL to Create a Link': 'Чтобы создать ссылку, введите её URL',
'Add Image': 'Вставить картинку',
'Add/Edit Image': 'Картинка',
'Alt Text': 'Подсказка',
'Align': 'Положение',
'Inline': 'В тексте',
'Left': 'Слева',
'Right': 'Справа',
'Insert an Image': 'Вставить картинку',
'You must enter a Image URL to insert': 'Чтобы вставить картинку, введите её URL',
'URL or Name': 'URL или имя',
'Hyperlink': 'Ссылка',
'Open in new window': 'Открывать в новом окне',
'Max Size': 'Макс. размер',
'To insert an image you must select uploaded file ID or enter the image URL!': 'Чтобы вставить картинку, либо выберите её из выпадающего списка (работают подсказки по названию), либо введите её прямой URL!',
'Or upload': 'Или загрузить',
'Select file': 'Выбрать файл',
'Popup text': 'Подпись',
'Upload Image': 'Загрузить картинку',
'Failed to upload image': 'Ошибка загрузки картинки',
'Only image files can be uploaded': 'Так загружать можно только картинки',
'Image uploads are not supported in this browser, use Chrome, Firefox, or Safari instead.': 'Чтобы загружать картинки, используйте современный браузер - Chrome, Firefox, или Safari.',
'Edit HTML': 'Править HTML-код',
'Add Table': 'Вставить таблицу',
'Add/Edit Table': 'Таблица',
'Columns': 'Колонки',
'Rows': 'Строки',
'Headers': 'Заголовок',
'None': 'Нет',
'Top': 'Сверху',
'Top and Left': 'Сверху и слева',
'Borders': 'Рамки',
'Yes': 'Да',
'No': 'Нет'
};
function __(s) {
return nicRu[s] || s;
};

View File

@ -1,30 +0,0 @@
/** nicSanitize */
// Sanitize pasted HTML
var nicSanitize = bkClass.extend({
construct: function(nicEditor)
{
this.ne = nicEditor;
this.ne.addEvent('add', this.add.closure(this));
},
add: function(instance)
{
instance.elm.addEvent('paste', this.paste.closureListener(this));
},
paste: function(ev, target)
{
var d = ev.clipboardData || window.clipboardData;
var h = d.getData('text/html') || d.getData('Text');
if (h)
{
this.sanitizeCfg = this.sanitizeCfg || getSanitizeCfg();
h = sanitizeHtml(h, this.sanitizeCfg);
if (h)
this.ne.nicCommand('insertHTML', h);
bkLib.cancelEvent(ev);
}
}
});
nicEditors.registerPlugin(nicSanitize);

View File

@ -1,105 +0,0 @@
/**
* DOM based HTML sanitizer
* License: Mozilla Public License 2.0 or later version
* (c) Vitaliy Filippov 2015+
* Version 2015-08-11
*/
(function() {
window.getSanitizeCfg = function(nest, attr)
{
// Default configuration is for sanitizing pasted html
if (!nest)
{
var inline = 'a b i strong em strike code tt sub sup br table span font';
nest = {
'hr br': '/',
'p': '#text '+inline,
'ul': 'li',
'ol': 'li',
'dl': 'dt dd',
'table': 'tr thead tbody',
'thead tbody': 'tr',
'tr': 'td th',
'* h1 h2 h3 h4 h5 h6 blockquote li dt dd pre td th': 'h1 h2 h3 h4 h5 h6 blockquote p ul ol dl pre hr #text '+inline,
'td th': '/'
};
nest[inline] = '#text '+inline;
}
if (!attr)
{
attr = {
'p': 'align',
'a': 'href name target',
'td': 'colspan rowspan',
'th': 'colspan rowspan'
};
}
var r = { nest: {}, attr: {} };
for (var k in nest)
{
var v = nest[k];
k = k.toUpperCase().split(' ');
v = v.toUpperCase().split(' ');
for (var i = 0; i < k.length; i++)
{
for (var j = 0; j < v.length; j++)
{
r.nest[k[i]] = r.nest[k[i]] || {};
r.nest[k[i]][v[j]] = true;
}
}
}
for (var k in attr)
{
var v = attr[k].split(' ');
k = k.toUpperCase();
r.attr[k] = {};
for (var i = 0; i < v.length; i++)
r.attr[k][v[i]] = true;
}
return r;
};
window.sanitizeHtml = function(html, cfg)
{
var r = document.createElement('div');
r.innerHTML = html;
sanitize(r, true, cfg);
return r.innerHTML.replace(/[ \t]*(\n[ \t]*)+/g, '\n').replace(/[ \t]{2,}/g, ' ').replace(/^\s*/, '');
};
function sanitize(el, is_root, cfg)
{
var n = is_root ? '*' : el.nodeName;
for (var i = 0; i < el.childNodes.length; i++)
{
var c = el.childNodes[i];
if (c.nodeType != 1 && c.nodeType != 3 ||
!cfg.nest[n][c.nodeType == 1 ? c.nodeName : '#TEXT'] ||
c.nodeType == 1 && !sanitize(c, false, cfg))
{
// Keep contents of generally allowed tags which are just not in place
if (c.nodeType == 1 && cfg.nest[c.nodeName])
while (c.childNodes.length)
el.insertBefore(c.childNodes[0], c);
el.removeChild(c);
i--;
}
}
if (!is_root)
{
for (var i = el.attributes.length-1; i >= 0; i--)
if (!cfg.attr[n] || !cfg.attr[n][el.attributes[i].nodeName])
el.removeAttribute(el.attributes[i].nodeName);
if (el.nodeName == 'A' && !(el.getAttribute('href') || '').match(/^https?:\/\/|^mailto:/i))
el.removeAttribute('href');
if ((el.nodeName == 'A' || el.nodeName == 'SPAN' || el.nodeName == 'FONT') && !el.attributes.length ||
el.innerHTML.match(/^\s*$/) && !cfg.nest[n]['/'])
return false;
}
return true;
}
})();