summaryrefslogtreecommitdiff
path: root/codemirror_ui/js
diff options
context:
space:
mode:
Diffstat (limited to 'codemirror_ui/js')
-rw-r--r--codemirror_ui/js/codemirror-ui-find.js89
-rw-r--r--codemirror_ui/js/codemirror-ui.js505
-rw-r--r--codemirror_ui/js/find_replace.html68
3 files changed, 662 insertions, 0 deletions
diff --git a/codemirror_ui/js/codemirror-ui-find.js b/codemirror_ui/js/codemirror-ui-find.js
new file mode 100644
index 0000000..c1cc8c5
--- /dev/null
+++ b/codemirror_ui/js/codemirror-ui-find.js
@@ -0,0 +1,89 @@
+/**
+ * @author jgreen
+ */
+var cursor = null;
+
+function setupFindReplace(){
+ document.getElementById('closeButton').onclick = closeWindow;
+ document.getElementById('findButton').onclick = find;
+ document.getElementById('replaceButton').onclick = replace;
+ document.getElementById('replaceAllButton').onclick = replaceAll;
+ document.getElementById('replaceFindButton').onclick = replaceFind;
+}
+
+function closeWindow(){
+ codeMirrorUI.searchWindow = null;
+ window.close();
+}
+
+function find(){
+ var findString = document.getElementById('find').value;
+ if (findString == null || findString == '') {
+ alert('You must enter something to search for.');
+ return;
+ }
+
+ if(document.getElementById('regex').checked){
+ findString = new RegExp(findString);
+ }
+
+ cursor = codeMirrorUI.mirror.getSearchCursor(findString, true);
+ var found = moveCursor(cursor);
+
+ //if we didn't find anything, let's check to see if we should start from the top
+ if(!found && document.getElementById('wrap').checked){
+ cursor = codeMirrorUI.mirror.getSearchCursor(findString, false);
+ found = moveCursor(cursor);
+ }
+
+ if(found){
+ cursor.select();
+ }else{
+ alert("No instances found. (Maybe you need to enable 'Wrap Search'?)");
+ }
+
+}
+
+function moveCursor(cursor){
+ var found = false;
+ if( getFindDirection() == "forward" ){
+ found = cursor.findNext();
+ }else{
+ found = cursor.findPrevious();
+ }
+ return found;
+}
+
+
+function getFindDirection(){
+ var dRadio = document.forms[0].elements['direction'];
+
+ for (var i = 0; i < dRadio.length; i++) {
+ if (dRadio[i].checked) {
+ return dRadio[i].value;
+ }
+ }
+
+ return 'no-value?';
+
+}
+
+
+function replaceAll(){
+ var cursor = codeMirrorUI.mirror.getSearchCursor(document.getElementById('find').value, false);
+ while (cursor.findNext())
+ cursor.replace(document.getElementById('replace').value);
+}
+
+
+function replace(){
+ cursor.replace(document.getElementById('replace').value);
+ //codeMirrorUI.replaceSelection(document.getElementById('replace').value);
+ setTimeout(window.focus, 100);
+ //alert('replaced!');
+}
+
+function replaceFind(){
+ replace();
+ find();
+}
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);
+ }
+}
diff --git a/codemirror_ui/js/find_replace.html b/codemirror_ui/js/find_replace.html
new file mode 100644
index 0000000..3e551f4
--- /dev/null
+++ b/codemirror_ui/js/find_replace.html
@@ -0,0 +1,68 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>CodeMirror UI Find/Replace</title>
+ <link rel="stylesheet" href="../css/codemirror-ui-find.css" type="text/css" media="screen" />
+ <script src="codemirror-ui-find.js" type="text/javascript"></script>
+ </head>
+ <body>
+ <h3>Find/Replace</h3>
+ <form name="findReplaceForm">
+ <table>
+ <tr>
+ <td>Find</td>
+ <td><input id="find" type="text" value=""/></td>
+ </tr>
+ <tr>
+ <td>Replace</td>
+ <td><input id="replace" type="text" value=""/></td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <label>
+ <input type="radio" name="direction" value="forward" checked="checked"/>Forward
+ </label>
+ <label>
+ <input type="radio" name="direction" value="backward"/>Backward
+ </label>
+ <br/>
+ <label>
+ <input type="checkbox" id="wrap" value="true"/>Wrap Search
+ </label>
+ <br/>
+ <label>
+ <input type="checkbox" id="regex" value="true"/>Regex
+ </label>
+ </td>
+ </tr>
+ </table>
+ </form>
+ <table id="buttons">
+ <tr>
+ <td>
+ <a href="#" id="findButton">Find</a>
+ </td>
+ <td>
+ <a href="#" id="replaceFindButton">Replace/Find</a>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <a href="#" id="replaceButton">Replace</a>
+ </td>
+ <td>
+ <a href="#" id="replaceAllButton">Replace All</a>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <a href="#" id="closeButton">Close</a>
+ </td>
+ </tr>
+ </table>
+ <script type="text/javascript">
+ setupFindReplace();
+ </script>
+ </body>
+</html>