You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
209 lines
4.7 KiB
209 lines
4.7 KiB
/*
|
|
* 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));
|