| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674 |
- /* global CodeMirror */
- /* global define */
- (function(mod) {
- 'use strict';
-
- if (typeof exports === 'object' && typeof module === 'object') // CommonJS
- mod(require('../../lib/codemirror'));
- else if (typeof define === 'function' && define.amd) // AMD
- define(['../../lib/codemirror'], mod);
- else
- mod(CodeMirror);
- })(function(CodeMirror) {
- 'use strict';
-
- var Search;
-
- CodeMirror.defineOption('searchbox', false, function(cm) {
- cm.addKeyMap({
- 'Ctrl-F': function() {
- if (!Search)
- Search = new SearchBox(cm);
-
- Search.show();
- },
-
- 'Esc': function() {
- if (Search && Search.isVisible()) {
- Search.hide();
-
- if (typeof event !== 'undefined')
- event.stopPropagation();
- }
-
- return false;
- },
-
- 'Cmd-F': function() {
- if (!Search)
- Search = new SearchBox(cm);
-
- Search.show();
- }
- });
- });
-
- function SearchBox(cm) {
- var self = this;
-
- init();
-
- function initElements(el) {
- self.searchBox = el.querySelector('.ace_search_form');
- self.replaceBox = el.querySelector('.ace_replace_form');
- self.searchOptions = el.querySelector('.ace_search_options');
-
- self.regExpOption = el.querySelector('[action=toggleRegexpMode]');
- self.caseSensitiveOption = el.querySelector('[action=toggleCaseSensitive]');
- self.wholeWordOption = el.querySelector('[action=toggleWholeWords]');
-
- self.searchInput = self.searchBox.querySelector('.ace_search_field');
- self.replaceInput = self.replaceBox.querySelector('.ace_search_field');
- }
-
- function init() {
- var el = self.element = addHtml();
-
- addStyle();
-
- initElements(el);
- bindKeys();
-
- el.addEventListener('mousedown', function(e) {
- setTimeout(function(){
- self.activeInput.focus();
- }, 0);
-
- e.stopPropagation();
- });
-
- el.addEventListener('click', function(e) {
- var t = e.target || e.srcElement;
- var action = t.getAttribute('action');
- if (action && self[action])
- self[action]();
- else if (self.commands[action])
- self.commands[action]();
-
- e.stopPropagation();
- });
-
- self.searchInput.addEventListener('input', function() {
- self.$onChange.schedule(20);
- });
-
- self.searchInput.addEventListener('focus', function() {
- self.activeInput = self.searchInput;
- });
-
- self.replaceInput.addEventListener('focus', function() {
- self.activeInput = self.replaceInput;
- });
-
- self.$onChange = delayedCall(function() {
- self.find(false, false);
- });
- }
-
- function bindKeys() {
- var sb = self,
- obj = {
- 'Ctrl-F|Cmd-F|Ctrl-H|Command-Alt-F': function() {
- var isReplace = sb.isReplace = !sb.isReplace;
- sb.replaceBox.style.display = isReplace ? '' : 'none';
- sb[isReplace ? 'replaceInput' : 'searchInput'].focus();
- },
- 'Ctrl-G|Cmd-G': function() {
- sb.findNext();
- },
- 'Ctrl-Shift-G|Cmd-Shift-G': function() {
- sb.findPrev();
- },
- 'Esc': function() {
- setTimeout(function() { sb.hide();});
- },
- 'Enter': function() {
- if (sb.activeInput === sb.replaceInput)
- sb.replace();
- sb.findNext();
- },
- 'Shift-Enter': function() {
- if (sb.activeInput === sb.replaceInput)
- sb.replace();
- sb.findPrev();
- },
- 'Alt-Enter': function() {
- if (sb.activeInput === sb.replaceInput)
- sb.replaceAll();
- sb.findAll();
- },
- 'Tab': function() {
- if (self.activeInput === self.replaceInput)
- self.searchInput.focus();
- else
- self.replaceInput.focus();
- }
- };
-
- self.element.addEventListener('keydown', function(event) {
- Object.keys(obj).some(function(name) {
- var is = key(name, event);
-
- if (is) {
- event.stopPropagation();
- event.preventDefault();
- obj[name](event);
- }
-
- return is;
- });
- });
- }
-
- this.commands = {
- toggleRegexpMode: function() {
- self.regExpOption.checked = !self.regExpOption.checked;
- self.$syncOptions();
- },
-
- toggleCaseSensitive: function() {
- self.caseSensitiveOption.checked = !self.caseSensitiveOption.checked;
- self.$syncOptions();
- },
-
- toggleWholeWords: function() {
- self.wholeWordOption.checked = !self.wholeWordOption.checked;
- self.$syncOptions();
- }
- };
-
- this.$syncOptions = function() {
- setCssClass(this.regExpOption, 'checked', this.regExpOption.checked);
- setCssClass(this.wholeWordOption, 'checked', this.wholeWordOption.checked);
- setCssClass(this.caseSensitiveOption, 'checked', this.caseSensitiveOption.checked);
-
- this.find(false, false);
- };
-
- this.find = function(skipCurrent, backwards) {
- var value = this.searchInput.value,
- options = {
- skipCurrent: skipCurrent,
- backwards: backwards,
- regExp: this.regExpOption.checked,
- caseSensitive: this.caseSensitiveOption.checked,
- wholeWord: this.wholeWordOption.checked
- };
-
- find(value, options, function(searchCursor) {
- var current = searchCursor.matches(false, searchCursor.from());
- cm.setSelection(current.from, current.to);
- });
- };
-
- function find(value, options, callback) {
- var done,
- noMatch, searchCursor, next, prev, matches, cursor,
- position,
- o = options,
- is = true,
- caseSensitive = o.caseSensitive,
- regExp = o.regExp,
- wholeWord = o.wholeWord;
-
- if (regExp || wholeWord) {
- if (options.wholeWord)
- value = '\\b' + value + '\\b';
-
- value = RegExp(value);
- }
-
- if (o.backwards)
- position = o.skipCurrent ? 'from': 'to';
- else
- position = o.skipCurrent ? 'to' : 'from';
-
- cursor = cm.getCursor(position);
- searchCursor = cm.getSearchCursor(value, cursor, !caseSensitive);
-
- next = searchCursor.findNext.bind(searchCursor),
- prev = searchCursor.findPrevious.bind(searchCursor),
- matches = searchCursor.matches.bind(searchCursor);
-
- if (o.backwards && !prev()) {
- is = next();
-
- if (is) {
- cm.setCursor(cm.doc.size - 1, 0);
- find(true, true, callback);
- done = true;
- }
- } else if (!o.backwards && !next()) {
- is = prev();
-
- if (is) {
- cm.setCursor(0, 0);
- find(true, false, callback);
- done = true;
- }
- }
-
- noMatch = !is && self.searchInput.value;
- setCssClass(self.searchBox, 'ace_nomatch', noMatch);
-
- if (!done && is)
- callback(searchCursor);
- }
-
- this.findNext = function() {
- this.find(true, false);
- };
-
- this.findPrev = function() {
- this.find(true, true);
- };
-
- this.findAll = function(){
- /*
- var range = this.editor.findAll(this.searchInput.value, {
- regExp: this.regExpOption.checked,
- caseSensitive: this.caseSensitiveOption.checked,
- wholeWord: this.wholeWordOption.checked
- });
- */
-
- var value = this.searchInput.value,
- range,
- noMatch = !range && this.searchInput.value;
-
- setCssClass(this.searchBox, 'ace_nomatch', noMatch);
-
- if (cm.showMatchesOnScrollbar)
- cm.showMatchesOnScrollbar(value);
-
- this.hide();
- };
-
- this.replace = function() {
- if (!cm.getOption('readOnly'))
- cm.replaceSelection(this.replaceInput.value, 'start');
- };
-
- this.replaceAndFindNext = function() {
- if (!cm.getOption('readOnly')) {
- this.editor.replace(this.replaceInput.value);
- this.findNext();
- }
- };
-
- this.replaceAll = function() {
- var value,
- cursor,
- from = this.searchInput.value,
- to = this.replaceInput.value,
- reg = RegExp(from, 'g');
-
- if (!cm.getOption('readOnly')) {
- cursor = cm.getCursor();
- value = cm.getValue();
- value = value.replace(reg, to);
-
- cm.setValue(value);
- cm.setCursor(cursor);
- }
- };
-
- this.hide = function() {
- this.element.style.display = 'none';
- cm.focus();
- };
-
- this.isVisible = function() {
- var is = this.element.style.display === '';
-
- return is;
- };
-
- this.show = function(value, isReplace) {
- this.element.style.display = '';
- this.replaceBox.style.display = isReplace ? '' : 'none';
-
- this.isReplace = isReplace;
-
- if (value)
- this.searchInput.value = value;
-
- this.searchInput.focus();
- this.searchInput.select();
- };
-
- this.isFocused = function() {
- var el = document.activeElement;
- return el === this.searchInput || el === this.replaceInput;
- };
-
- function addStyle() {
- var style = document.createElement('style'),
- css = [
- '.ace_search {',
- 'background-color: #ddd;',
- 'border: 1px solid #cbcbcb;',
- 'border-top: 0 none;',
- 'max-width: 325px;',
- 'overflow: hidden;',
- 'margin: 0;',
- 'padding: 4px;',
- 'padding-right: 6px;',
- 'padding-bottom: 0;',
- 'position: absolute;',
- 'top: 0px;',
- 'z-index: 99;',
- 'white-space: normal;',
- '}',
- '.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, .ace_replace_form {',
- 'border-radius: 3px;',
- 'border: 1px solid #cbcbcb;',
- 'float: left;',
- 'margin-bottom: 4px;',
- 'overflow: hidden;',
- '}',
- '.ace_search_form.ace_nomatch {',
- 'outline: 1px solid red;',
- '}',
- '.ace_search_field {',
- 'background-color: white;',
- 'border-right: 1px solid #cbcbcb;',
- 'border: 0 none;',
- '-webkit-box-sizing: border-box;',
- '-moz-box-sizing: border-box;',
- 'box-sizing: border-box;',
- 'float: left;',
- 'height: 22px;',
- 'outline: 0;',
- 'padding: 0 7px;',
- 'width: 214px;',
- 'margin: 0;',
- '}',
- '.ace_searchbtn,',
- '.ace_replacebtn {',
- 'background: #fff;',
- 'border: 0 none;',
- 'border-left: 1px solid #dcdcdc;',
- 'cursor: pointer;',
- '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:disabled {',
- 'background: none;',
- 'cursor: default;',
- '}',
- '.ace_searchbtn {',
- 'background-position: 50% 50%;',
- 'background-repeat: no-repeat;',
- 'width: 27px;',
- '}',
- '.ace_searchbtn.prev {',
- 'background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADFJREFUeNpiSU1NZUAC/6E0I0yACYskCpsJiySKIiY0SUZk40FyTEgCjGgKwTRAgAEAQJUIPCE+qfkAAAAASUVORK5CYII=); ',
- '}',
- '.ace_searchbtn.next {',
- 'background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNpiTE1NZQCC/0DMyIAKwGJMUAYDEo3M/s+EpvM/mkKwCQxYjIeLMaELoLMBAgwAU7UJObTKsvAAAAAASUVORK5CYII=); ',
- '}',
- '.ace_searchbtn_close {',
- 'background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0;',
- 'border-radius: 50%;',
- 'border: 0 none;',
- 'color: #656565;',
- 'cursor: pointer;',
- 'float: right;',
- 'font: 16px/16px Arial;',
- 'height: 14px;',
- 'margin: 5px 1px 9px 5px;',
- 'padding: 0;',
- 'text-align: center;',
- 'width: 14px;',
- '}',
- '.ace_searchbtn_close:hover {',
- 'background-color: #656565;',
- 'background-position: 50% 100%;',
- 'color: white;',
- '}',
- '.ace_replacebtn.prev {',
- 'width: 54px',
- '}',
- '.ace_replacebtn.next {',
- 'width: 27px',
- '}',
- '.ace_button {',
- 'margin-left: 2px;',
- 'cursor: pointer;',
- '-webkit-user-select: none;',
- '-moz-user-select: none;',
- '-o-user-select: none;',
- '-ms-user-select: none;',
- 'user-select: none;',
- 'overflow: hidden;',
- 'opacity: 0.7;',
- 'border: 1px solid rgba(100,100,100,0.23);',
- 'padding: 1px;',
- '-moz-box-sizing: border-box;',
- 'box-sizing: border-box;',
- 'color: black;',
- '}',
- '.ace_button:hover {',
- 'background-color: #eee;',
- 'opacity:1;',
- '}',
- '.ace_button:active {',
- 'background-color: #ddd;',
- '}',
- '.ace_button.checked {',
- 'border-color: #3399ff;',
- 'opacity:1;',
- '}',
- '.ace_search_options{',
- 'margin-bottom: 3px;',
- 'text-align: right;',
- '-webkit-user-select: none;',
- '-moz-user-select: none;',
- '-o-user-select: none;',
- '-ms-user-select: none;',
- 'user-select: none;',
- '}'
- ].join('');
-
- style.setAttribute('data-name', 'js-searchbox');
-
- style.textContent = css;
-
- document.head.appendChild(style);
- }
-
- function addHtml() {
- var elSearch,
- el = document.querySelector('.CodeMirror'),
- div = document.createElement('div'),
- html = [
- '<div class="ace_search right">',
- '<button type="button" action="hide" class="ace_searchbtn_close"></button>',
- '<div class="ace_search_form">',
- '<input class="ace_search_field" placeholder="Search for" spellcheck="false"></input>',
- '<button type="button" action="findNext" class="ace_searchbtn next"></button>',
- '<button type="button" action="findPrev" class="ace_searchbtn prev"></button>',
- '<button type="button" action="findAll" class="ace_searchbtn" title="Alt-Enter">All</button>',
- '</div>',
- '<div class="ace_replace_form">',
- '<input class="ace_search_field" placeholder="Replace with" spellcheck="false"></input>',
- '<button type="button" action="replaceAndFindNext" class="ace_replacebtn">Replace</button>',
- '<button type="button" action="replaceAll" class="ace_replacebtn">All</button>',
- '</div>',
- '<div class="ace_search_options">',
- '<span action="toggleRegexpMode" class="ace_button" title="RegExp Search">.*</span>',
- '<span action="toggleCaseSensitive" class="ace_button" title="CaseSensitive Search">Aa</span>',
- '<span action="toggleWholeWords" class="ace_button" title="Whole Word Search">\\b</span>',
- '</div>',
- '</div>'
- ].join('');
-
- div.innerHTML = html;
-
- elSearch = div.firstChild;
-
- el.parentElement.appendChild(elSearch);
-
- return elSearch;
- }
- }
-
- function setCssClass(el, className, condition) {
- var list = el.classList;
-
- list[condition ? 'add' : 'remove'](className);
- }
-
- function delayedCall(fcn, defaultTimeout) {
- var timer,
- callback = function() {
- timer = null;
- fcn();
- },
-
- _self = function(timeout) {
- if (!timer)
- timer = setTimeout(callback, timeout || defaultTimeout);
- };
-
- _self.delay = function(timeout) {
- timer && clearTimeout(timer);
- timer = setTimeout(callback, timeout || defaultTimeout);
- };
- _self.schedule = _self;
-
- _self.call = function() {
- this.cancel();
- fcn();
- };
-
- _self.cancel = function() {
- timer && clearTimeout(timer);
- timer = null;
- };
-
- _self.isPending = function() {
- return timer;
- };
-
- return _self;
- }
-
- /* https://github.com/coderaiser/key */
- function key(str, event) {
- var right,
- KEY = {
- BACKSPACE : 8,
- TAB : 9,
- ENTER : 13,
- ESC : 27,
-
- SPACE : 32,
- PAGE_UP : 33,
- PAGE_DOWN : 34,
- END : 35,
- HOME : 36,
- UP : 38,
- DOWN : 40,
-
- INSERT : 45,
- DELETE : 46,
-
- INSERT_MAC : 96,
-
- ASTERISK : 106,
- PLUS : 107,
- MINUS : 109,
-
- F1 : 112,
- F2 : 113,
- F3 : 114,
- F4 : 115,
- F5 : 116,
- F6 : 117,
- F7 : 118,
- F8 : 119,
- F9 : 120,
- F10 : 121,
-
- SLASH : 191,
- TRA : 192, /* Typewritten Reverse Apostrophe (`) */
- BACKSLASH : 220
- };
-
- keyCheck(str, event);
-
- right = str.split('|').some(function(combination) {
- var wrong;
-
- wrong = combination.split('-').some(function(key) {
- var right;
-
- switch(key) {
- case 'Ctrl':
- right = event.ctrlKey;
- break;
-
- case 'Shift':
- right = event.shiftKey;
- break;
-
- case 'Alt':
- right = event.altKey;
- break;
-
- case 'Cmd':
- right = event.metaKey;
- break;
-
- default:
- if (key.length === 1)
- right = event.keyCode === key.charCodeAt(0);
- else
- Object.keys(KEY).some(function(name) {
- var up = key.toUpperCase();
-
- if (up === name)
- right = event.keyCode === KEY[name];
- });
- break;
- }
-
- return !right;
- });
-
- return !wrong;
- });
-
- return right;
- }
-
- function keyCheck(str, event) {
- if (typeof str !== 'string')
- throw(Error('str should be string!'));
-
- if (typeof event !== 'object')
- throw(Error('event should be object!'));
- }
- });
|