searchbox wip
This commit is contained in:
parent
153562054d
commit
8d3c4feeb5
4 changed files with 394 additions and 11 deletions
|
|
@ -108,7 +108,7 @@ env.editor.commands.addCommands([{
|
|||
editor.gotoLine(line);
|
||||
},
|
||||
readOnly: true
|
||||
}, {
|
||||
}/*, {
|
||||
name: "find",
|
||||
bindKey: {win: "Ctrl-F", mac: "Command-F"},
|
||||
exec: function(editor, needle) {
|
||||
|
|
@ -121,7 +121,7 @@ env.editor.commands.addCommands([{
|
|||
editor.find(needle);
|
||||
},
|
||||
readOnly: true
|
||||
}, {
|
||||
}*/, {
|
||||
name: "focusCommandLine",
|
||||
bindKey: "shift-esc",
|
||||
exec: function(editor, needle) { editor.cmdLine.focus(); },
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ define(function(require, exports, module) {
|
|||
|
||||
var lang = require("../lib/lang");
|
||||
|
||||
var SearchBox = require("ace/ext/searchbox");
|
||||
function bindKey(win, mac) {
|
||||
return {
|
||||
win: win,
|
||||
|
|
@ -94,8 +95,7 @@ exports.commands = [{
|
|||
name: "find",
|
||||
bindKey: bindKey("Ctrl-F", "Command-F"),
|
||||
exec: function(editor) {
|
||||
var needle = prompt("Find:", editor.getCopyText());
|
||||
editor.find(needle);
|
||||
SearchBox.SearchBox(editor, editor.getSelectionRange());
|
||||
},
|
||||
readOnly: true
|
||||
}, {
|
||||
|
|
@ -345,13 +345,7 @@ exports.commands = [{
|
|||
name: "replace",
|
||||
bindKey: bindKey("Ctrl-R", "Command-Option-F"),
|
||||
exec: function(editor) {
|
||||
var needle = prompt("Find:", editor.getCopyText());
|
||||
if (!needle)
|
||||
return;
|
||||
var replacement = prompt("Replacement:");
|
||||
if (!replacement)
|
||||
return;
|
||||
editor.replace(replacement, {needle: needle});
|
||||
SearchBox.SearchBox(editor, editor.getSelectionRange(), true);
|
||||
}
|
||||
}, {
|
||||
name: "replaceall",
|
||||
|
|
|
|||
|
|
@ -366,3 +366,133 @@
|
|||
.ace_italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------
|
||||
* Editor Search Form
|
||||
* --------------------------------------------------------------------------------------- */
|
||||
.ace_search {
|
||||
background-color: #ddd;
|
||||
border: 1px solid #cbcbcb;
|
||||
border-top: 0 none;
|
||||
max-width: 297px;
|
||||
overflow: hidden;
|
||||
padding: 4px;
|
||||
padding-right: 6px;
|
||||
padding-bottom: 0;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
z-index: 99;
|
||||
}
|
||||
.ace_search.left {
|
||||
border-left: 0 none;
|
||||
border-radius: 0px 0px 5px 0px;
|
||||
left: 0;
|
||||
}
|
||||
.ace_search.right {
|
||||
border-radius: 0px 0px 0px 5px;
|
||||
border-right: 0 none;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.ace_search_form {
|
||||
border-radius: 3px;
|
||||
border: 1px solid #cbcbcb;
|
||||
float: left;
|
||||
margin-bottom: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.ace_search label {
|
||||
float: left;
|
||||
color: #656565;
|
||||
}
|
||||
.ace_search input {
|
||||
background: white;
|
||||
border-right: 1px solid #cbcbcb;
|
||||
border: 0 none;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
float: left;
|
||||
height: 22px;
|
||||
outline: 0;
|
||||
padding: 0 7px;
|
||||
width: 214px;
|
||||
}
|
||||
.ace_searchbtn,
|
||||
.ace_replacebtn {
|
||||
background: #fff;
|
||||
border: 0 none;
|
||||
border-left: 1px solid #dcdcdc;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
float: left;
|
||||
height: 22px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
}
|
||||
.ace_searchbtn:last-child,
|
||||
.ace_replacebtn:last-child {
|
||||
border-top-right-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
}
|
||||
.ace_searchbtn {
|
||||
width: 27px;
|
||||
}
|
||||
.ace_searchbtn:after {
|
||||
border: 2px solid #656565;
|
||||
content: "";
|
||||
display: block;
|
||||
height: 4px;
|
||||
position: absolute;
|
||||
width: 4px;
|
||||
-webkit-transform: rotateZ(45deg);
|
||||
}
|
||||
.ace_searchbtn.prev:after {
|
||||
border-right: 0 none;
|
||||
border-bottom: 0 none;
|
||||
left: 10px;
|
||||
top: 9px;
|
||||
}
|
||||
.ace_searchbtn.next:after {
|
||||
border-left: 0 none;
|
||||
border-top: 0 none;
|
||||
left: 10px;
|
||||
top: 7px;
|
||||
}
|
||||
.ace_searchbtn:disabled {
|
||||
background: none;
|
||||
cursor: default;
|
||||
}
|
||||
.ace_searchbtn:disabled:after {
|
||||
border-color: #ccc;
|
||||
}
|
||||
.ace_searchbtn_close {
|
||||
background: none;
|
||||
border-radius: 50%;
|
||||
border: 0 none;
|
||||
color: #656565;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
float: right;
|
||||
font-family: Arial;
|
||||
font-size: 16px;
|
||||
height: 14px;
|
||||
line-height: 16px;
|
||||
margin: 5px 1px 9px 5px;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
width: 14px;
|
||||
}
|
||||
.ace_searchbtn_close:hover {
|
||||
background: #656565;
|
||||
color: white;
|
||||
}
|
||||
.ace_replacebtn {
|
||||
}
|
||||
.ace_replacebtn.prev {
|
||||
width: 54px
|
||||
}
|
||||
.ace_replacebtn.next {
|
||||
width: 27px
|
||||
}
|
||||
259
lib/ace/ext/searchbox.js
Normal file
259
lib/ace/ext/searchbox.js
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Distributed under the BSD license:
|
||||
*
|
||||
* Copyright (c) 2010, Ajax.org B.V.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Ajax.org B.V. nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
var dom = require("ace/lib/dom");
|
||||
var event = require("ace/lib/event");
|
||||
var Range = require("ace/range").Range;
|
||||
|
||||
exports.SearchBox = function (editor, range, showReplaceForm) {
|
||||
var _self = this;
|
||||
var sb = null;//search box
|
||||
var n = null;//needle
|
||||
var r = null;//replace
|
||||
var p = null;//parent DOM node
|
||||
|
||||
var needle = editor.session.getTextRange(range);
|
||||
|
||||
this.$init = function() {
|
||||
|
||||
p = editor.container.parentNode;
|
||||
sb = p.querySelector(".ace_search"); //the complete form
|
||||
|
||||
if(!sb) {
|
||||
|
||||
//Create the elements
|
||||
sb = document.createElement("div");
|
||||
sb.setAttribute("class", "ace_search right");
|
||||
p.appendChild( sb );
|
||||
|
||||
var c = document.createElement("button"); //cancel btn
|
||||
c.setAttribute("type","button");
|
||||
c.setAttribute("class","ace_searchbtn_close");
|
||||
c.innerHTML = "×";
|
||||
sb.appendChild( c );
|
||||
c.onclick = _self.hide;
|
||||
|
||||
var sf = document.createElement("div"); //search form
|
||||
sf.setAttribute("id", "ace_search_form");
|
||||
sf.setAttribute("class", "ace_search_form");
|
||||
sb.appendChild( sf );
|
||||
|
||||
n = document.createElement("input"); //needle
|
||||
n.setAttribute("class", "ace_search_field");
|
||||
n.setAttribute("id", "ace_search_field");
|
||||
n.setAttribute("placeholder", "Search for");
|
||||
n.setAttribute("type", "text");
|
||||
sf.appendChild( n );
|
||||
|
||||
var sp = document.createElement("button");
|
||||
sp.setAttribute("type","button");
|
||||
sp.setAttribute("class","ace_searchbtn prev");
|
||||
sf.appendChild( sp );
|
||||
sp.onclick = _self.findPrev;
|
||||
|
||||
var sn = document.createElement("button");
|
||||
sn.setAttribute("type","button");
|
||||
sn.setAttribute("class","ace_searchbtn next");
|
||||
sf.appendChild( sn );
|
||||
sn.onclick = _self.findNext;
|
||||
|
||||
var rf = document.createElement("div"); //replace form
|
||||
rf.setAttribute("id", "ace_replace_form");
|
||||
rf.setAttribute("class", "ace_search_form");
|
||||
rf.setAttribute("style", "display: none");
|
||||
sb.appendChild( rf);
|
||||
|
||||
r = document.createElement("input"); //needle
|
||||
r.setAttribute("class", "ace_search_field");
|
||||
r.setAttribute("id", "ace_replace_field");
|
||||
r.setAttribute("placeholder", "Replace with");
|
||||
r.setAttribute("type", "text");
|
||||
rf.appendChild( r );
|
||||
|
||||
var rr = document.createElement("button");
|
||||
rr.setAttribute("type","button");
|
||||
rr.setAttribute("class","ace_replacebtn prev");
|
||||
rr.innerHTML = "Replace";
|
||||
rf.appendChild( rr );
|
||||
rr.onclick = _self.replace;
|
||||
|
||||
var ra = document.createElement("button");
|
||||
ra.setAttribute("type","button");
|
||||
ra.setAttribute("class","ace_replacebtn next");
|
||||
ra.innerHTML = "All";
|
||||
rf.appendChild( ra );
|
||||
ra.onclick = _self.replaceAll;
|
||||
|
||||
|
||||
} else {
|
||||
sb.removeAttribute("style");
|
||||
n = sb.querySelector("#ace_search_field");
|
||||
r = sb.querySelector("#ace_replace_field");
|
||||
}
|
||||
|
||||
console.log( "showReplaceForm", showReplaceForm );
|
||||
if( showReplaceForm ) {
|
||||
p.querySelector("#ace_replace_form").removeAttribute("style");
|
||||
}
|
||||
|
||||
|
||||
if( needle )
|
||||
n.value = needle;
|
||||
|
||||
//set initial focus and select text in input
|
||||
n.focus();
|
||||
n.select();
|
||||
|
||||
//keybinging outsite of the searchbox
|
||||
_self.$searchKeybingin = {
|
||||
handleKeyboard: function(data, hashId, keyString, keyCode) {
|
||||
console.log("MERGE");
|
||||
if (keyString == "esc")
|
||||
return {command: this.command};
|
||||
},
|
||||
command: {
|
||||
exec: function(editor) {
|
||||
_self.hide();
|
||||
}
|
||||
}
|
||||
};
|
||||
editor.keyBinding.addKeyboardHandler(this.$searchKeybingin);
|
||||
|
||||
n.onkeydown = searchonkeydown;
|
||||
r.onkeydown = searchonkeydown;
|
||||
function searchonkeydown(e) {
|
||||
|
||||
var cmdKey = e.metaKey || e.ctrlKey;
|
||||
|
||||
console.log(cmdKey);
|
||||
|
||||
if( cmdKey ) {
|
||||
if( e.which == 70 ) { //f key
|
||||
var rf = p.querySelector("#ace_replace_form");
|
||||
if( e.altKey && rf.hasAttribute("style") ) {
|
||||
p.querySelector("#ace_replace_form").removeAttribute("style");
|
||||
} else {
|
||||
_self.hide();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if( e.which === 9 ) { //tab
|
||||
if( e.target == n ) {
|
||||
r.focus();
|
||||
r.select();
|
||||
} else {
|
||||
n.focus();
|
||||
n.select();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
n.onpaste = function(e) {
|
||||
//I do this because the onpaste event is fired before the value of the input actually changes
|
||||
setTimeout(function() {
|
||||
e.target.onkeyup();
|
||||
}, 100);
|
||||
}
|
||||
n.onkeyup = function(e){
|
||||
console.log("KEYUP", e);
|
||||
if(!e) {
|
||||
e = {};
|
||||
e.which = 0;
|
||||
}
|
||||
|
||||
if( e.which === 27 ) { //esc key
|
||||
_self.hide();
|
||||
} else if( e.which === 13 ) { //enter key
|
||||
_self.findNext( );
|
||||
} else {
|
||||
editor.moveCursorTo( range.start.row, range.start.column );
|
||||
_self.findNext();
|
||||
}
|
||||
};
|
||||
r.onkeyup = function(e){
|
||||
if( e.which === 27 ) { //esc key
|
||||
_self.hide();
|
||||
} else if( e.which === 13 ) { //enter key
|
||||
editor.moveCursorTo( range.start.row, range.start.column );
|
||||
_self.replace();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
this.findPrev = function() {
|
||||
editor.find(n.value, {
|
||||
backwards: true,
|
||||
wrap: true
|
||||
});
|
||||
};
|
||||
this.findNext = function() {
|
||||
editor.find(n.value, {
|
||||
backwards: false,
|
||||
wrap: true
|
||||
});
|
||||
};
|
||||
this.replace = function() {
|
||||
editor.replace( r.value );
|
||||
_self.findNext();
|
||||
};
|
||||
this.replaceAll = function() {
|
||||
editor.replaceAll( r.value );
|
||||
};
|
||||
|
||||
this.hide = function () {
|
||||
n.value = "";
|
||||
r.value = "";
|
||||
sb.setAttribute("style", "display: none");
|
||||
sb.querySelector("#ace_replace_form").setAttribute("style", "display: none");
|
||||
editor.keyBinding.removeKeyboardHandler(this.$searchKeybingin);
|
||||
editor.focus();
|
||||
};
|
||||
|
||||
_self.$init();
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------
|
||||
* TODO
|
||||
* --------------------------------------------------------------------------------------- */
|
||||
/*
|
||||
- move search form to the left if it masks current word
|
||||
- includ all options that search has. ex: regex
|
||||
- searchbox.searchbox is not that pretty. we should have just searchbox
|
||||
- disable prev button if it makes sence
|
||||
*/
|
||||
Loading…
Add table
Add a link
Reference in a new issue