From 99f904adcc37d93c90defcd8ce898598e25be212 Mon Sep 17 00:00:00 2001 From: Hugues Hiegel Date: Wed, 11 Mar 2015 16:55:04 +0100 Subject: Lot of plugins --- codemirror_ui/js/codemirror-ui.js | 505 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 505 insertions(+) create mode 100644 codemirror_ui/js/codemirror-ui.js (limited to 'codemirror_ui/js/codemirror-ui.js') diff --git a/codemirror_ui/js/codemirror-ui.js b/codemirror_ui/js/codemirror-ui.js new file mode 100644 index 0000000..d246132 --- /dev/null +++ b/codemirror_ui/js/codemirror-ui.js @@ -0,0 +1,505 @@ +/* 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.className = "button mainaction"; + 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.className = "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); + } +} -- cgit v1.2.3