iclop_v1/public/js/codemirror-ui.js
2022-08-21 07:46:19 +07:00

504 lines
16 KiB
JavaScript
Vendored

/* Demonstration of embedding CodeMirror in a bigger application. The
* interface defined here is a mess of prompts and confirms, and
* should probably not be used in a real project.
*/
//var CodeMirrorUI = Class.create();
function CodeMirrorUI(place, options, mirrorOptions) {
this.initialize(place, options, mirrorOptions);
}
CodeMirrorUI.prototype = {
initialize: function(textarea, options, mirrorOptions) {
var defaultOptions = {
searchMode: 'popup', // other options are 'inline' and 'dialog'. The 'dialog' option needs work.
imagePath: 'images/silk',
path: 'js',
buttons: ['search', 'undo', 'redo', 'jump', 'reindentSelection', 'reindent','about'],
saveCallback: function() {},
}
this.textarea = textarea
this.options = options;
this.setDefaults(this.options, defaultOptions);
this.buttonDefs = {
'save': ["Save", "save", this.options.imagePath + "/page_save.png", this.save],
'search': ["Search/Replace", "find_replace_popup", this.options.imagePath + "/find.png", this.find_replace_popup],
'searchClose': ["Close", "find_replace_popup_close", this.options.imagePath + "/cancel.png", this.find_replace_popup_close],
'searchDialog': ["Search/Replace", "find_replace_window", this.options.imagePath + "/find.png", this.find_replace_window],
'undo': ["Undo", "undo", this.options.imagePath + "/arrow_undo.png", this.undo],
'redo': ["Redo", "redo", this.options.imagePath + "/arrow_redo.png", this.redo],
'jump': ["Jump to line #", "jump", this.options.imagePath + "/page_go.png", this.jump],
'reindentSelection': ["Reformat selection", "reindentSelect", this.options.imagePath + "/text_indent.png", this.reindentSelection],
'reindent': ["Reformat whole document", "reindent", this.options.imagePath + "/page_refresh.png", this.reindent],
'about': ["About CodeMirror-UI", "about", this.options.imagePath + "/help.png", this.about]
};
//place = CodeMirror.replace(place)
this.home = document.createElement("div");
this.textarea.parentNode.insertBefore(this.home, this.textarea);
/*if (place.appendChild)
place.appendChild(this.home);
else
place(this.home);
*/
this.self = this;
var onChange = this.editorChanged.cmuiBind(this);
// preserve custom onChance handler
if (mirrorOptions.onChange) {
mirrorOptions.onChange = function() {
mirrorOptions.onChange();
onChange();
}
} else {
mirrorOptions.onChange = onChange;
}
mir = CodeMirror.fromTextArea(this.textarea, mirrorOptions);
//console.log(mir);
this.mirror = mir;
this.initButtons();
//this.initWordWrapControl(); // CodeMirror v2 does not support word wrapping
if (this.options.searchMode == 'inline') {
this.initFindControl();
} else if (this.options.searchMode == 'popup') {
this.initPopupFindControl();
}
if (this.saveButton) this.addClass(this.saveButton,'inactive');
if (this.undoButton) this.addClass(this.undoButton,'inactive');
if (this.redoButton) this.addClass(this.redoButton,'inactive');
},
setDefaults: function(object, defaults) {
for (var option in defaults) {
if (!object.hasOwnProperty(option))
object[option] = defaults[option];
}
},
toTextArea: function() {
this.home.parentNode.removeChild(this.home);
this.mirror.toTextArea();
},
initButtons: function() {
this.buttonFrame = document.createElement("div");
this.buttonFrame.className = "codemirror-ui-clearfix codemirror-ui-button-frame";
this.home.appendChild(this.buttonFrame);
for (var i = 0; i < this.options.buttons.length; i++) {
var buttonId = this.options.buttons[i];
var buttonDef = this.buttonDefs[buttonId];
this.addButton(buttonDef[0], buttonDef[1], buttonDef[2], buttonDef[3], this.buttonFrame);
}
//this.makeButton("Search", "search");
//this.makeButton("Replace", "replace");
//this.makeButton("Current line", "line");
//this.makeButton("Jump to line", "jump");
//this.makeButton("Insert constructor", "macro");
//this.makeButton("Indent all", "reindent");
},
/*
* This is left over from the MirrorFrame demo.
* Get rid of it quick.
*/
/*
makeButton : function(name, action){
var button = document.createElement("input");
button.type = "button";
button.value = name;
this.home.appendChild(button);
button.onclick = function(){
self[action].call(self);
};
},
*/
createFindBar: function() {
var findBar = document.createElement("div");
findBar.className = "codemirror-ui-find-bar";
this.findString = document.createElement("input");
this.findString.type = "text";
this.findString.size = 8;
this.findButton = document.createElement("input");
this.findButton.type = "button";
this.findButton.value = "Find";
this.findButton.onclick = function(){this.find()}.cmuiBind(this);
this.connect(this.findString, "keyup", function(e){
var code = e.keyCode;
if (code == 13){
this.find(this.mirror.getCursor(false))
}else{
if(!this.findString.value == ""){
this.find(this.mirror.getCursor(true))
}
}
this.findString.focus();
}.cmuiBind(this) );
var regLabel = document.createElement("label");
regLabel.title = "Regular Expressions"
this.regex = document.createElement("input");
this.regex.type = "checkbox"
this.regex.className = "codemirror-ui-checkbox"
regLabel.appendChild(this.regex);
regLabel.appendChild(document.createTextNode("RegEx"));
var caseLabel = document.createElement("label");
caseLabel.title = "Case Sensitive"
this.caseSensitive = document.createElement("input");
this.caseSensitive.type = "checkbox"
this.caseSensitive.className = "codemirror-ui-checkbox"
caseLabel.appendChild(this.caseSensitive);
caseLabel.appendChild(document.createTextNode("A/a"));
this.replaceString = document.createElement("input");
this.replaceString.type = "text";
this.replaceString.size = 8;
this.connect(this.replaceString, "keyup", function(e){
var code = e.keyCode;
if (code == 13){
this.replace()
}
}.cmuiBind(this) );
this.replaceButton = document.createElement("input");
this.replaceButton.type = "button";
this.replaceButton.value = "Replace";
this.replaceButton.onclick = this.replace.cmuiBind(this);
var replaceAllLabel = document.createElement("label");
replaceAllLabel.title = "Replace All"
this.replaceAll = document.createElement("input");
this.replaceAll.type = "checkbox"
this.replaceAll.className = "codemirror-ui-checkbox"
replaceAllLabel.appendChild(this.replaceAll);
replaceAllLabel.appendChild(document.createTextNode("All"));
findBar.appendChild(this.findString);
findBar.appendChild(this.findButton);
findBar.appendChild(caseLabel);
findBar.appendChild(regLabel);
findBar.appendChild(this.replaceString);
findBar.appendChild(this.replaceButton);
findBar.appendChild(replaceAllLabel);
return findBar;
},
initPopupFindControl: function() {
var findBar = this.createFindBar();
this.popupFindWrap = document.createElement("div");
this.popupFindWrap.className = "codemirror-ui-popup-find-wrap";
this.popupFindWrap.appendChild(findBar);
var buttonDef = this.buttonDefs['searchClose'];
this.addButton(buttonDef[0], buttonDef[1], buttonDef[2], buttonDef[3], this.popupFindWrap);
this.buttonFrame.appendChild(this.popupFindWrap);
},
initFindControl: function() {
var findBar = this.createFindBar();
this.buttonFrame.appendChild(findBar);
},
find: function( start ) {
var isCaseSensitive = this.caseSensitive.checked;
if(start == null){
start = this.mirror.getCursor();
}
var findString = this.findString.value;
if (findString == null || findString == '') {
alert('You must enter something to search for.');
return;
}
if (this.regex.checked) {
findString = new RegExp(findString, !isCaseSensitive ? "i" : "");
}
this.cursor = this.mirror.getSearchCursor(findString, start, !isCaseSensitive );
var found = this.cursor.findNext();
if (found) {
this.mirror.setSelection(this.cursor.from(),this.cursor.to())
//this.cursor.select();
} else {
if (confirm("No more matches. Should we start from the top?")) {
this.cursor = this.mirror.getSearchCursor(findString, 0, !isCaseSensitive);
found = this.cursor.findNext();
if (found) {
this.mirror.setSelection(this.cursor.from(),this.cursor.to())
//this.cursor.select();
} else {
alert("No matches found.");
}
}
}
},
replace: function() {
var findString = this.findString.value,
replaceString = this.replaceString.value,
isCaseSensitive = this.caseSensitive.checked,
isRegex = this.regex.checked,
regFindString = isRegex ? new RegExp(findString, !isCaseSensitive ? "i" : "") : "";
if (this.replaceAll.checked) {
var cursor = this.mirror.getSearchCursor(isRegex ? regFindString : findString, 0, !isCaseSensitive);
while (cursor.findNext())
this.mirror.replaceRange(
isRegex ? cursor.pos.match[0].replace(regFindString, replaceString) : replaceString
,cursor.from(),cursor.to());
//cursor.replace(this.replaceString.value);
} else {
this.mirror.replaceRange(
isRegex ? this.cursor.pos.match[0].replace(regFindString, replaceString) : replaceString
,this.cursor.from(),this.cursor.to())
//this.cursor.replace(this.replaceString.value);
this.find();
}
},
initWordWrapControl: function() {
var wrapDiv = document.createElement("div");
wrapDiv.className = "codemirror-ui-wrap"
var label = document.createElement("label");
this.wordWrap = document.createElement("input");
this.wordWrap.type = "checkbox"
this.wordWrap.checked = true;
label.appendChild(this.wordWrap);
label.appendChild(document.createTextNode("Word Wrap"));
this.wordWrap.onchange = this.toggleWordWrap.cmuiBind(this);
wrapDiv.appendChild(label);
this.buttonFrame.appendChild(wrapDiv);
},
toggleWordWrap: function() {
if (this.wordWrap.checked) {
this.mirror.setTextWrapping("nowrap");
} else {
this.mirror.setTextWrapping("");
}
},
addButton: function(name, action, image, func, frame) {
var button = document.createElement("a");
//button.href = "#";
button.className = "codemirror-ui-button " + action;
button.title = name;
button.func = func.cmuiBind(this);
button.onclick = function(event) {
//alert(event.target);
event.target.func();
return false;
//this.self[action].call(this);
//eval("this."+action)();
}
.cmuiBind(this, func);
var img = document.createElement("img");
img.src = image;
img.border = 0;
img.func = func.cmuiBind(this);
button.appendChild(img);
frame.appendChild(button);
if (action == 'save') {
this.saveButton = button;
}
if (action == 'undo') {
this.undoButton = button;
}
if (action == 'redo') {
this.redoButton = button;
}
},
classNameRegex: function(className) {
var regex = new RegExp("(.*) *" + className + " *(.*)");
return regex;
},
addClass: function(element, className) {
if (!element.className.match(this.classNameRegex(className))) {
element.className += " " + className;
}
},
removeClass: function(element, className) {
var m = element.className.match(this.classNameRegex(className))
if (m) {
element.className = m[1] + " " + m[2];
}
},
editorChanged: function() {
if(!this.mirror) {
return
}
var his = this.mirror.historySize();
if (his['undo'] > 0) {
this.removeClass(this.saveButton, 'inactive');
this.removeClass(this.undoButton, 'inactive');
} else {
this.addClass(this.saveButton, 'inactive');
this.addClass(this.undoButton, 'inactive');
}
if (his['redo'] > 0) {
this.removeClass(this.redoButton, 'inactive');
} else {
this.addClass(this.redoButton, 'inactive');
}
//alert("undo size = " + his['undo'] + " and redo size = " + his['redo']);
},
save: function() {
this.options.saveCallback();
this.addClass(this.saveButton, 'inactive');
},
undo: function() {
this.mirror.undo();
},
redo: function() {
this.mirror.redo();
},
replaceSelection: function(newVal) {
this.mirror.replaceSelection(newVal);
this.searchWindow.focus();
},
raise_search_window: function() {
//alert('raising window!');
this.searchWindow.focus();
},
find_replace_window: function() {
if (this.searchWindow == null) {
this.searchWindow = window.open(this.options.path + "find_replace.html", "mywindow", "scrollbars=1,width=400,height=350,modal=yes");
this.searchWindow.codeMirrorUI = this;
}
this.searchWindow.focus();
},
find_replace_popup: function() {
//alert('Hello!');
this.popupFindWrap.className = "codemirror-ui-popup-find-wrap active";
this.findString.focus();
},
find_replace_popup_close: function() {
//alert('Hello!');
this.popupFindWrap.className = "codemirror-ui-popup-find-wrap";
},
/*
find_replace: function(){
this.find_replace = document.createElement("div");
this.find_replace.className = "codemirror-search-replace";
this.find_replace.innerHTML = "Just a test!";
this.home.appendChild(this.find_replace);
},
search: function(){
var text = prompt("Enter search term:", "");
if (!text)
return;
var first = true;
do {
var cursor = this.mirror.getSearchCursor(text, first);
first = false;
while (cursor.findNext()) {
cursor.select();
if (!confirm("Search again?"))
return;
}
}
while (confirm("End of document reached. Start over?"));
},
replace: function(){
// This is a replace-all, but it is possible to implement a
// prompting replace.
var from = prompt("Enter search string:", ""), to;
if (from)
to = prompt("What should it be replaced with?", "");
if (to == null)
return;
var cursor = this.mirror.getSearchCursor(from, false);
while (cursor.findNext())
cursor.replace(to);
},
*/
jump: function() {
var line = prompt("Jump to line:", "");
if (line && !isNaN(Number(line))) {
this.mirror.setCursor(Number(line),0);
this.mirror.setSelection({line:Number(line),ch:0},{line:Number(line)+1,ch:0});
this.mirror.focus();
}
},
/*
line: function(){
alert("The cursor is currently at line " + this.mirror.currentLine());
this.mirror.focus();
},
macro: function(){
var name = prompt("Name your constructor:", "");
if (name)
this.mirror.replaceSelection("function " + name + "() {\n \n}\n\n" + name + ".prototype = {\n \n};\n");
},
*/
reindent: function() {
var lineCount = this.mirror.lineCount();
for(var line = 0; line < lineCount; line++) {
this.mirror.indentLine(line);
}
},
about : function() {
string = "CodeMirror-UI was written by Jeremy Green (http://www.octolabs.com/) as a light interface around CodeMirror by Marijn Haverbeke (http://codemirror.net)."
string += "\n\n"
string += "Documentation and the code can be found at https://github.com/jagthedrummer/codemirror-ui/."
alert(string);
},
reindentSelection: function() {
var cur = this.mirror.getCursor()
//console.log(cur)
var start = this.mirror.getCursor(true)["line"]
var end = this.mirror.getCursor(false)["line"]
for(var line = start; line <= end; line++) {
this.mirror.indentLine(line);
}
//this.mirror.reindentSelection();
},
// Event handler registration. If disconnect is true, it'll return a
// function that unregisters the handler.
// Borrowed from CodeMirror + modified
connect: function (node, type, handler, disconnect) {
/*function wrapHandler(event) {
handler(new Event(event || window.event));
}*/
if (typeof node.addEventListener == "function") {
node.addEventListener(type, handler, false);
if (disconnect)
return function() {
node.removeEventListener(type, handler, false);
};
} else {
node.attachEvent("on" + type, handler);
if (disconnect)
return function() {
node.detachEvent("on" + type, handler);
};
}
}
};
/*
* This makes coding callbacks much more sane
*/
Function.prototype.cmuiBind = function(scope) {
var _function = this;
return function() {
return _function.apply(scope, arguments);
}
}