209 lines
4.7 KiB
JavaScript
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Project: Long Press
* Description: Pops a list of alternate characters when a key is long-pressed
* Author: Quentin Thiaucourt, http://toki-woki.net
* Licence: MIT License http://opensource.org/licenses/mit-license.php
*/
;(function ($, window, undefined) {
var pluginName = 'longPress',
document = window.document,
defaults = {/*
propertyName: "value"
*/};
var moreChars={
// extended latin (and african latin)
// upper
'A':'ĀĂÀÁÂÃÄÅĄⱭ∀Æ',
'B':'Ɓ',
'C':'ÇĆĈĊČƆ',
'D':'ÐĎĐḎƊ',
'E':'ÈÉÊËĒĖĘẸĚƏÆƎƐ€',
'F':'ƑƩ',
'G':'ĜĞĠĢƢ',
'H':'ĤĦ',
'I':'ÌÍÎÏĪĮỊİIƗIJ',
'J':'ĴIJ',
'K':'ĶƘ',
'L':'ĹĻĽŁΛ',
'N':'ÑŃŅŇŊƝ₦',
'O':'ÒÓÔÕÖŌØŐŒƠƟ',
'P':'Ƥ¶',
'R':'ŔŘɌⱤ',
'S':'ßſŚŜŞṢŠÞ§',
'T':'ŢŤṮƬƮ',
'U':'ÙÚÛÜŪŬŮŰŲɄƯƱ',
'V':'Ʋ',
'W':'ŴẄΩ',
'Y':'ÝŶŸƔƳ',
'Z':'ŹŻŽƵƷẔ',
// lower
'a':'āăàáâãäåąɑæαª',
'b':'ßβɓ',
'c':'çςćĉċč¢ɔ',
'd':'ðďđɖḏɖɗ',
'e':'èéêëēėęẹěəæεɛ€',
'f':'ƒʃƭ',
'g':'ĝğġģɠƣ',
'h':'ĥħɦẖ',
'i':'ìíîïīįịiiɨijι',
'j':'ĵɟij',
'k':'ķƙ',
'l':'ĺļľłλ',
'n':'ñńņňŋɲ',
'o':'òóôõöōøőœơɵ°',
'p':'ƥ¶',
'r':'ŕřɍɽ',
's':'ßſśŝşṣšþ§',
't':'ţťṯƭʈ',
'u':'ùúûüūŭůűųưμυʉʊ',
'v':'ʋ',
'w':'ŵẅω',
'y':'ýŷÿɣyƴ',
'z':'źżžƶẕʒƹ',
// Misc
'$':'£¥€₩₨₳Ƀ¤',
'!':'¡‼‽',
'?':'¿‽',
'%':'‰',
'.':'…••',
'-':'±‐–—',
'+':'±†‡',
'\'':'′″‴‘’‚‛',
'"':'“”„‟',
'<':'≤‹',
'>':'≥›',
'=':'≈≠≡'
};
var ignoredKeys=[8, 13, 37, 38, 39, 40];
var selectedCharIndex;
var lastWhich;
var timer;
var activeElement;
var popup=$('<ul class=long-press-popup />');
$(window).mousewheel(onWheel);
$(window).keyup(onKeyUp);
function onKeyDown(e) {
// Arrow key with popup visible
if ($('.long-press-popup').length>0 && (e.which==37 || e.which==39)) {
if (e.which==37) activePreviousLetter();
else if (e.which==39) activateNextLetter();
e.preventDefault();
return;
}
if (ignoredKeys.indexOf(e.which)>-1) return;
activeElement=e.target;
if (e.which==lastWhich) {
e.preventDefault();
if (!timer) timer=setTimeout(onTimer, 10);
return;
}
lastWhich=e.which;
}
function onKeyUp(e) {
if (ignoredKeys.indexOf(e.which)>-1) return;
if (activeElement==null) return;
lastWhich=null;
clearTimeout(timer);
timer=null;
hidePopup();
}
function onTimer() {
var typedChar=$(activeElement).val().split('')[getCaretPosition(activeElement)-1];
if (moreChars[typedChar]) {
showPopup((moreChars[typedChar]));
} else {
hidePopup();
}
}
function showPopup(chars) {
popup.empty();
var letter;
for (var i=0; i<chars.length; i++) {
letter=$('<li class=long-press-letter />').text(chars[i]);
letter.mouseenter(activateLetter);
popup.append(letter);
}
$('body').append(popup);
selectedCharIndex=-1;
}
function activateLetter(e) {
selectCharIndex($(e.target).index());
}
function activateRelativeLetter(i) {
selectCharIndex(($('.long-press-letter').length+selectedCharIndex+i) % $('.long-press-letter').length);
}
function activateNextLetter() {
activateRelativeLetter(1);
}
function activePreviousLetter() {
activateRelativeLetter(-1);
}
function hidePopup() {
popup.detach();
}
function onWheel(e, delta, deltaX, deltaY) {
if ($('.long-press-popup').length==0) return;
e.preventDefault();
delta<0 ? activateNextLetter() : activePreviousLetter();
}
function selectCharIndex(i) {
$('.long-press-letter.selected').removeClass('selected');
$('.long-press-letter').eq(i).addClass('selected');
selectedCharIndex=i;
updateChar();
}
function updateChar() {
var newChar=$('.long-press-letter.selected').text();
var pos=getCaretPosition(activeElement);
var arVal=$(activeElement).val().split('');
arVal[pos-1]=newChar;
$(activeElement).val(arVal.join(''));
setCaretPosition(activeElement, pos);
}
function LongPress( element, options ) {
this.element = element;
this.options = $.extend( {}, defaults, options) ;
this._defaults = defaults;
this._name = pluginName;
this.init();
}
LongPress.prototype = {
init: function () {
$(this.element).keydown(onKeyDown);
}
};
$.fn[pluginName] = function ( options ) {
return this.each(function () {
if (!$.data(this, 'plugin_' + pluginName)) {
$.data(this, 'plugin_' + pluginName, new LongPress( this, options ));
}
});
};
}(jQuery, window));