/* 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 = [ '