173 lines
5.2 KiB
JavaScript
173 lines
5.2 KiB
JavaScript
/* ------------------------------------------------------------------------*
|
|
* Copyright 2013-2014 Arne F. Claassen
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*-------------------------------------------------------------------------*/
|
|
|
|
var Josh = Josh || {};
|
|
(function (root, $, _) {
|
|
$.fn.josh_caretTo = function (index) {
|
|
return this.queue(function (next) {
|
|
if (this.createTextRange) {
|
|
var range = this.createTextRange();
|
|
range.move("character", index);
|
|
range.select();
|
|
} else if (this.selectionStart !== null) {
|
|
this.setSelectionRange(index, index);
|
|
}
|
|
next();
|
|
});
|
|
};
|
|
$.fn.josh_caretPosition = function () {
|
|
var el = this.get(0);
|
|
if (el.createTextRange) {
|
|
var range = el.createTextRange();
|
|
range.moveStart('character', -el.value.length);
|
|
return range.text.length;
|
|
} else if (el.selectionStart !== null) {
|
|
return el.selectionStart;
|
|
}
|
|
return 0;
|
|
};
|
|
|
|
var history = Josh.History();
|
|
var killring = new Josh.KillRing();
|
|
|
|
Josh.Input = function (config) {
|
|
config = config || {};
|
|
|
|
// instance fields
|
|
var _console = config.console || (Josh.Debug && root.console ? root.console : {
|
|
log: function () {
|
|
}
|
|
});
|
|
|
|
var _id = "#" + config.id;
|
|
var _blinktime = config.blinktime || 500;
|
|
var _active = false;
|
|
var _cursor_visible = false;
|
|
var _isInput = false;
|
|
var _history = config.history || history;
|
|
var _killring = config.killring || killring;
|
|
var _text;
|
|
var self = {
|
|
templates: {
|
|
span: _.template('<span class="input"><span class="left"/><span class="cursor"/><span class="right"/></span>')
|
|
},
|
|
history: _history,
|
|
killring: _killring
|
|
};
|
|
|
|
$(document).ready(function () {
|
|
var $input = $(_id);
|
|
var el = $input.get(0);
|
|
var readline = new Josh.ReadLine({
|
|
history: _history,
|
|
killring: _killring,
|
|
console: _console
|
|
});
|
|
self.readline = readline;
|
|
readline.attach(el);
|
|
var activate = null;
|
|
_isInput = $input.is('input');
|
|
if (_isInput) {
|
|
|
|
_console.log(_id + ' is an input');
|
|
|
|
function renderInput(line) {
|
|
var text = line ? line.text : '';
|
|
_text = text;
|
|
$input.val(text);
|
|
$input.josh_caretTo(line.cursor);
|
|
}
|
|
readline.onChange(renderInput);
|
|
$input.click(function() {
|
|
var line = readline.getLine();
|
|
line.cursor = $input.josh_caretPosition();
|
|
readline.setLine(line);
|
|
});
|
|
|
|
activate = function() {
|
|
// Note: have to re-render with a setTimeout, because on focus, but after the onfocus event is processed,
|
|
// the input will select all, invalidating our render
|
|
setTimeout(function() {
|
|
renderInput(readline.getLine());
|
|
}, 0);
|
|
};
|
|
} else {
|
|
_console.log(_id + ' is a non-input element');
|
|
$input.html(self.templates.span());
|
|
if(typeof $input.attr('tabindex') === 'undefined') {
|
|
$input.attr('tabindex',0);
|
|
}
|
|
var $left = $input.find('.left');
|
|
var $right = $input.find('.right');
|
|
var $cursor = $input.find('.cursor');
|
|
|
|
function renderSpan(line) {
|
|
var text = line.text || '';
|
|
_text = text;
|
|
var cursorIdx = line.cursor || 0;
|
|
var left = _.escape(text.substr(0, cursorIdx)).replace(/ /g, ' ');
|
|
var cursor = text.substr(cursorIdx, 1);
|
|
var right = _.escape(text.substr(cursorIdx + 1)).replace(/ /g, ' ');
|
|
$left.html(left);
|
|
if (!cursor) {
|
|
$cursor.html(' ').css('textDecoration', 'underline');
|
|
} else {
|
|
$cursor.text(cursor).css('textDecoration', 'underline');
|
|
}
|
|
$right.html(right);
|
|
}
|
|
|
|
function blinkCursor() {
|
|
if (!_active) {
|
|
return;
|
|
}
|
|
root.setTimeout(function () {
|
|
if (!_active) {
|
|
return;
|
|
}
|
|
_cursor_visible = !_cursor_visible;
|
|
if (_cursor_visible) {
|
|
$cursor.css('textDecoration', 'underline');
|
|
} else {
|
|
$cursor.css('textDecoration', '');
|
|
}
|
|
blinkCursor();
|
|
}, _blinktime);
|
|
}
|
|
|
|
activate = function () {
|
|
blinkCursor();
|
|
}
|
|
readline.onChange(renderSpan);
|
|
}
|
|
readline.unbind({keyCode: Josh.Keys.Special.Tab});
|
|
readline.unbind({'char': 'R', ctrlKey: true});
|
|
readline.onActivate(function () {
|
|
_active = true;
|
|
activate();
|
|
});
|
|
readline.onDeactivate(function () {
|
|
_active = false;
|
|
if (_text) {
|
|
_history.accept(_text);
|
|
}
|
|
});
|
|
|
|
});
|
|
return self;
|
|
}
|
|
})(this, $, _);
|