mirror of
https://github.com/twisterarmy/twister-calm.git
synced 2025-02-04 11:04:20 +00:00
replaced autocomplete by simple and stable
This commit is contained in:
parent
8667bbbf24
commit
133599cb89
@ -11,6 +11,8 @@
|
||||
<script src="js/jquery.json-2.4.js"></script>
|
||||
<script src="js/jquery.jsonrpcclient.js"></script>
|
||||
<script src="js/jquery.storageapi.js"></script>
|
||||
<script src="js/jquery.a-tools-1.4.1.js"></script>
|
||||
<script src="js/jquery.asuggest.js"></script>
|
||||
<script src="js/mobile_abstract.js"></script>
|
||||
<script src="js/twister_io.js"></script>
|
||||
<script src="js/polyglot.min.js"></script>
|
||||
@ -29,11 +31,10 @@
|
||||
<script src="js/calm.js"></script>
|
||||
|
||||
<script>
|
||||
$(document).ready(function(){initInterfaceFollowing()});
|
||||
$(function(){initInterfaceFollowing(); homeIntInit();});
|
||||
changeStyle();
|
||||
</script>
|
||||
|
||||
<link rel="icon" type="image/png" href="img/twister_mini.png" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@ -246,7 +247,7 @@
|
||||
<!-- TEMPLATE INVÓLUCRO DO POST EXPANDIDO END -->
|
||||
|
||||
<!-- TEMPLATE DO MODAL GENÉRICO INIT -->
|
||||
<div class="modal-blackout">
|
||||
<div class="modal-blackout cancel">
|
||||
<div class="modal-wrapper">
|
||||
<div class="modal-header">
|
||||
<h3></h3>
|
||||
|
@ -11,6 +11,8 @@
|
||||
<script src="js/jquery.json-2.4.js"></script>
|
||||
<script src="js/jquery.jsonrpcclient.js"></script>
|
||||
<script src="js/jquery.storageapi.js"></script>
|
||||
<script src="js/jquery.a-tools-1.4.1.js"></script>
|
||||
<script src="js/jquery.asuggest.js"></script>
|
||||
<script src="js/mobile_abstract.js"></script>
|
||||
<script src="js/twister_io.js"></script>
|
||||
<script src="js/polyglot.min.js"></script>
|
||||
@ -26,7 +28,6 @@
|
||||
<script src="js/interface_common.js"></script>
|
||||
<script src="js/interface_home.js"></script>
|
||||
<script src="js/jquery.animate-colors-min.js"></script>
|
||||
<script src="js/jquery.textcomplete.js"></script>
|
||||
<script src="js/calm.js"></script>
|
||||
<script src="js/options.js"></script>
|
||||
<script src="jquery-emotions/jquery.emotions.js"></script>
|
||||
|
63
js/calm.js
63
js/calm.js
@ -1,7 +1,4 @@
|
||||
$(function(){
|
||||
$('.dropdown-menu').on('keydown', function(e){
|
||||
e.stopPropagation();
|
||||
})
|
||||
$('.post-text').on('click', 'a', function(e){
|
||||
e.stopPropagation();
|
||||
});
|
||||
@ -16,24 +13,25 @@ $(function(){
|
||||
$('.bitmessage-ctc').on('click', function(){
|
||||
window.prompt('Press Ctrl/Cmd+C to copy then Enter to close', $(this).attr('data'))
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
|
||||
function dhtIndicatorBg(){
|
||||
var bgcolor = '';
|
||||
if(twisterDhtNodes <= 20){bgcolor = '#770900'
|
||||
}else if(twisterDhtNodes <= 60){bgcolor = '#773400'
|
||||
}else if(twisterDhtNodes <= 90){bgcolor = '#774c00'
|
||||
}else if(twisterDhtNodes <= 120){bgcolor = '#776400'
|
||||
}else if(twisterDhtNodes <= 150){bgcolor = '#707500'
|
||||
}else if(twisterDhtNodes <= 180){bgcolor = '#3f6900'
|
||||
}else if(twisterDhtNodes <= 210){bgcolor = '#005f15'
|
||||
}else if(twisterDhtNodes >= 250){bgcolor = '#009922'
|
||||
}
|
||||
$('.userMenu-dhtindicator').animate({'background-color': bgcolor });
|
||||
};
|
||||
setTimeout(dhtIndicatorBg, 300);
|
||||
setTimeout(function() {setInterval(dhtIndicatorBg, 2000)}, 400);
|
||||
function dhtIndicatorBg(){
|
||||
var bgcolor = '';
|
||||
if(twisterDhtNodes <= 20){bgcolor = '#770900'
|
||||
}else if(twisterDhtNodes <= 60){bgcolor = '#773400'
|
||||
}else if(twisterDhtNodes <= 90){bgcolor = '#774c00'
|
||||
}else if(twisterDhtNodes <= 120){bgcolor = '#776400'
|
||||
}else if(twisterDhtNodes <= 150){bgcolor = '#707500'
|
||||
}else if(twisterDhtNodes <= 180){bgcolor = '#3f6900'
|
||||
}else if(twisterDhtNodes <= 210){bgcolor = '#005f15'
|
||||
}else if(twisterDhtNodes >= 250){bgcolor = '#009922'
|
||||
}
|
||||
$('.userMenu-dhtindicator').animate({'background-color': bgcolor });
|
||||
};
|
||||
setTimeout(dhtIndicatorBg, 300);
|
||||
setTimeout(function() {setInterval(dhtIndicatorBg, 2000)}, 400);
|
||||
|
||||
function modalDMIntr() {
|
||||
$(".cancel").on('click', function(event){
|
||||
@ -48,29 +46,16 @@ function modalDMIntr() {
|
||||
});
|
||||
};
|
||||
|
||||
function mensAutocomplete() {
|
||||
function mensAutocomplete(t) {
|
||||
var suggests = [];
|
||||
|
||||
for(var i = 0; i < followingUsers.length; i++){
|
||||
|
||||
for (var i = 0; i < followingUsers.length; i++){
|
||||
if(followingUsers[i] == localStorage.defaultScreenName) continue;
|
||||
suggests.push(followingUsers[i]);
|
||||
suggests.unshift("@"+followingUsers[i]);
|
||||
}
|
||||
suggests.reverse();
|
||||
$('textarea').textcomplete([
|
||||
{ // html
|
||||
mentions: suggests,
|
||||
match: /\B@(\w*)$/,
|
||||
search: function (term, callback) {
|
||||
callback($.map(this.mentions, function (mention) {
|
||||
return mention.indexOf(term) === 0 ? mention : null;
|
||||
}));
|
||||
},
|
||||
index: 1,
|
||||
replace: function (mention) {
|
||||
return '@' + mention + ' ';
|
||||
}
|
||||
}
|
||||
])
|
||||
$(t).asuggest(suggests, {
|
||||
'minChunkSize': 2
|
||||
});
|
||||
}
|
||||
|
||||
function changeStyle() {
|
||||
@ -94,5 +79,5 @@ function changeStyle() {
|
||||
|
||||
function homeIntInit () {
|
||||
modalDMIntr ();
|
||||
setTimeout(mensAutocomplete, 800);
|
||||
$('textarea').on('click', function() {mensAutocomplete(this)});
|
||||
}
|
@ -119,11 +119,9 @@ function openProfileModal(e)
|
||||
unfollow(username);
|
||||
});
|
||||
};
|
||||
|
||||
//fix .modal-content height
|
||||
$mc = $('.modal-content');
|
||||
// $mch = parseInt($('.modal-content').css('height'));//
|
||||
// $pch = parseInt($('.profile-card').css('height'));//
|
||||
// $mc.css('height', $mch - ($pch + Math.floor($mch/50)));//hed//fix .modal-content height
|
||||
|
||||
$mc.off('profileloaded');
|
||||
$mc.on('profileloaded', function() {
|
||||
var viewHeader = $mc.find(".postboard > h2");
|
||||
|
578
js/jquery.a-tools-1.4.1.js
Normal file
578
js/jquery.a-tools-1.4.1.js
Normal file
@ -0,0 +1,578 @@
|
||||
/*!
|
||||
* a-tools 1.4.1
|
||||
*
|
||||
* Copyright (c) 2009 Andrey Kramarev(andrey.kramarev[at]ampparit.com), Ampparit Inc. (www.ampparit.com)
|
||||
* Licensed under the MIT license.
|
||||
* http://www.ampparit.fi/a-tools/license.txt
|
||||
*
|
||||
* Basic usage:
|
||||
|
||||
<textarea></textarea>
|
||||
<input type="text" />
|
||||
|
||||
// Get current selection
|
||||
var sel = $("textarea").getSelection()
|
||||
|
||||
// Replace current selection
|
||||
$("input").replaceSelection("foo");
|
||||
|
||||
// Count characters
|
||||
alert($("textarea").countCharacters());
|
||||
|
||||
// Set max length without callback function
|
||||
$("textarea").setMaxLength(7);
|
||||
|
||||
// Set max length with callback function which will be called when limit is exceeded
|
||||
$("textarea").setMaxLength(10, function() {
|
||||
alert("hello")
|
||||
});
|
||||
|
||||
// Removing limit:
|
||||
$("textarea").setMaxLength(-1);
|
||||
|
||||
// Insert text at current caret position
|
||||
$("#textarea").insertAtCaretPos("hello");
|
||||
|
||||
// Set caret position (1 = beginning, -1 = end)
|
||||
$("#textArea").setCaretPos(10);
|
||||
|
||||
// Set Selection
|
||||
$("#textArea").setSelection(10,15);
|
||||
|
||||
*/
|
||||
var caretPositionAmp;
|
||||
|
||||
jQuery.fn.extend({
|
||||
getSelection: function() { // function for getting selection, and position of the selected text
|
||||
var input = this.jquery ? this[0] : this;
|
||||
var start;
|
||||
var end;
|
||||
var part;
|
||||
var number = 0;
|
||||
input.onmousedown = function() { // for IE because it loses caret position when focus changed
|
||||
if (document.selection && typeof(input.selectionStart) != "number") {
|
||||
document.selection.empty();
|
||||
} else {
|
||||
window.getSelection().removeAllRanges();
|
||||
}
|
||||
}
|
||||
if (document.selection) {
|
||||
// part for IE and Opera
|
||||
var s = document.selection.createRange();
|
||||
var minus = 0;
|
||||
var position = 0;
|
||||
var minusEnd = 0;
|
||||
var re;
|
||||
var rc;
|
||||
if (input.value.match(/\n/g) != null) {
|
||||
number = input.value.match(/\n/g).length;// number of EOL simbols
|
||||
}
|
||||
if (s.text) {
|
||||
part = s.text;
|
||||
// OPERA support
|
||||
if (typeof(input.selectionStart) == "number") {
|
||||
start = input.selectionStart;
|
||||
end = input.selectionEnd;
|
||||
// return null if the selected text not from the needed area
|
||||
if (start == end) {
|
||||
return { start: start, end: end, text: s.text, length: end - start };
|
||||
}
|
||||
} else {
|
||||
// IE support
|
||||
var firstRe;
|
||||
var secondRe;
|
||||
re = input.createTextRange();
|
||||
rc = re.duplicate();
|
||||
firstRe = re.text;
|
||||
re.moveToBookmark(s.getBookmark());
|
||||
secondRe = re.text;
|
||||
rc.setEndPoint("EndToStart", re);
|
||||
// return null if the selectyed text not from the needed area
|
||||
if (firstRe == secondRe && firstRe != s.text) {
|
||||
return this;
|
||||
}
|
||||
start = rc.text.length;
|
||||
end = rc.text.length + s.text.length;
|
||||
}
|
||||
// remove all EOL to have the same start and end positons as in MOZILLA
|
||||
if (number > 0) {
|
||||
for (var i = 0; i <= number; i++) {
|
||||
var w = input.value.indexOf("\n", position);
|
||||
if (w != -1 && w < start) {
|
||||
position = w + 1;
|
||||
minus++;
|
||||
minusEnd = minus;
|
||||
} else if (w != -1 && w >= start && w <= end) {
|
||||
if (w == start + 1) {
|
||||
minus--;
|
||||
minusEnd--;
|
||||
position = w + 1;
|
||||
continue;
|
||||
}
|
||||
position = w + 1;
|
||||
minusEnd++;
|
||||
} else {
|
||||
i = number;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s.text.indexOf("\n", 0) == 1) {
|
||||
minusEnd = minusEnd + 2;
|
||||
}
|
||||
start = start - minus;
|
||||
end = end - minusEnd;
|
||||
|
||||
return { start: start, end: end, text: s.text, length: end - start };
|
||||
}
|
||||
input.focus ();
|
||||
if (typeof(input.selectionStart) == "number") {
|
||||
start = input.selectionStart;
|
||||
} else {
|
||||
s = document.selection.createRange();
|
||||
re = input.createTextRange();
|
||||
rc = re.duplicate();
|
||||
re.moveToBookmark(s.getBookmark());
|
||||
rc.setEndPoint("EndToStart", re);
|
||||
start = rc.text.length;
|
||||
}
|
||||
if (number > 0) {
|
||||
for (var i = 0; i <= number; i++) {
|
||||
var w = input.value.indexOf("\n", position);
|
||||
if (w != -1 && w < start) {
|
||||
position = w + 1;
|
||||
minus++;
|
||||
} else {
|
||||
i = number;
|
||||
}
|
||||
}
|
||||
}
|
||||
start = start - minus;
|
||||
return { start: start, end: start, text: s.text, length: 0 };
|
||||
} else if (typeof(input.selectionStart) == "number" ) {
|
||||
start = input.selectionStart;
|
||||
end = input.selectionEnd;
|
||||
part = input.value.substring(input.selectionStart, input.selectionEnd);
|
||||
return { start: start, end: end, text: part, length: end - start };
|
||||
} else { return { start: undefined, end: undefined, text: undefined, length: undefined }; }
|
||||
},
|
||||
|
||||
// function for the replacement of the selected text
|
||||
replaceSelection: function(inputStr) {
|
||||
var input = this.jquery ? this[0] : this;
|
||||
//part for IE and Opera
|
||||
var start;
|
||||
var end;
|
||||
var position = 0;
|
||||
var rc;
|
||||
var re;
|
||||
var number = 0;
|
||||
var minus = 0;
|
||||
var mozScrollFix = ( input.scrollTop == undefined ) ? 0 : input.scrollTop;
|
||||
if (document.selection && typeof(input.selectionStart) != "number") {
|
||||
var s = document.selection.createRange();
|
||||
|
||||
// IE support
|
||||
if (typeof(input.selectionStart) != "number") { // return null if the selected text not from the needed area
|
||||
var firstRe;
|
||||
var secondRe;
|
||||
re = input.createTextRange();
|
||||
rc = re.duplicate();
|
||||
firstRe = re.text;
|
||||
re.moveToBookmark(s.getBookmark());
|
||||
secondRe = re.text;
|
||||
rc.setEndPoint("EndToStart", re);
|
||||
if (firstRe == secondRe && firstRe != s.text) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
if (s.text) {
|
||||
part = s.text;
|
||||
if (input.value.match(/\n/g) != null) {
|
||||
number = input.value.match(/\n/g).length;// number of EOL simbols
|
||||
}
|
||||
// IE support
|
||||
start = rc.text.length;
|
||||
// remove all EOL to have the same start and end positons as in MOZILLA
|
||||
if (number > 0) {
|
||||
for (var i = 0; i <= number; i++) {
|
||||
var w = input.value.indexOf("\n", position);
|
||||
if (w != -1 && w < start) {
|
||||
position = w + 1;
|
||||
minus++;
|
||||
|
||||
} else {
|
||||
i = number;
|
||||
}
|
||||
}
|
||||
}
|
||||
s.text = inputStr;
|
||||
caretPositionAmp = rc.text.length + inputStr.length;
|
||||
re.move("character", caretPositionAmp);
|
||||
document.selection.empty();
|
||||
input.blur();
|
||||
}
|
||||
return this;
|
||||
} else if (typeof(input.selectionStart) == "number" && // MOZILLA support
|
||||
input.selectionStart != input.selectionEnd) {
|
||||
|
||||
start = input.selectionStart;
|
||||
end = input.selectionEnd;
|
||||
input.value = input.value.substr(0, start) + inputStr + input.value.substr(end);
|
||||
position = start + inputStr.length;
|
||||
input.setSelectionRange(position, position);
|
||||
input.scrollTop = mozScrollFix;
|
||||
return this;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
//Set Selection in text
|
||||
setSelection: function(startPosition, endPosition) {
|
||||
startPosition = parseInt(startPosition);
|
||||
endPosition = parseInt(endPosition);
|
||||
|
||||
var input = this.jquery ? this[0] : this;
|
||||
input.focus ();
|
||||
if (typeof(input.selectionStart) != "number") {
|
||||
re = input.createTextRange();
|
||||
if (re.text.length < endPosition) {
|
||||
endPosition = re.text.length+1;
|
||||
}
|
||||
}
|
||||
if (endPosition < startPosition) {
|
||||
return this;
|
||||
}
|
||||
if (document.selection) {
|
||||
var number = 0;
|
||||
var plus = 0;
|
||||
var position = 0;
|
||||
var plusEnd = 0;
|
||||
if (typeof(input.selectionStart) != "number") { // IE
|
||||
re.collapse(true);
|
||||
re.moveEnd('character', endPosition);
|
||||
re.moveStart('character', startPosition);
|
||||
re.select();
|
||||
return this;
|
||||
} else if (typeof(input.selectionStart) == "number") { // Opera
|
||||
if (input.value.match(/\n/g) != null) {
|
||||
number = input.value.match(/\n/g).length;// number of EOL simbols
|
||||
}
|
||||
if (number > 0) {
|
||||
for (var i = 0; i <= number; i++) {
|
||||
var w = input.value.indexOf("\n", position);
|
||||
if (w != -1 && w < startPosition) {
|
||||
position = w + 1;
|
||||
plus++;
|
||||
plusEnd = plus;
|
||||
} else if (w != -1 && w >= startPosition && w <= endPosition) {
|
||||
if (w == startPosition + 1) {
|
||||
plus--;
|
||||
plusEnd--;
|
||||
position = w + 1;
|
||||
continue;
|
||||
}
|
||||
position = w + 1;
|
||||
plusEnd++;
|
||||
} else {
|
||||
i = number;
|
||||
}
|
||||
}
|
||||
}
|
||||
startPosition = startPosition +plus;
|
||||
endPosition = endPosition + plusEnd;
|
||||
input.selectionStart = startPosition;
|
||||
input.selectionEnd = endPosition;
|
||||
return this;
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
else if (input.selectionStart) { // MOZILLA support
|
||||
input.focus ();
|
||||
input.selectionStart = startPosition;
|
||||
input.selectionEnd = endPosition;
|
||||
return this;
|
||||
}
|
||||
},
|
||||
|
||||
// insert text at current caret position
|
||||
insertAtCaretPos: function(inputStr) {
|
||||
var input = this.jquery ? this[0] : this;
|
||||
var start;
|
||||
var end;
|
||||
var position;
|
||||
var s;
|
||||
var re;
|
||||
var rc;
|
||||
var point;
|
||||
var minus = 0;
|
||||
var number = 0;
|
||||
var mozScrollFix = ( input.scrollTop == undefined ) ? 0 : input.scrollTop;
|
||||
input.focus();
|
||||
if (document.selection && typeof(input.selectionStart) != "number") {
|
||||
if (input.value.match(/\n/g) != null) {
|
||||
number = input.value.match(/\n/g).length;// number of EOL simbols
|
||||
}
|
||||
point = parseInt(caretPositionAmp);
|
||||
if (number > 0) {
|
||||
for (var i = 0; i <= number; i++) {
|
||||
var w = input.value.indexOf("\n", position);
|
||||
if (w != -1 && w <= point) {
|
||||
position = w + 1;
|
||||
point = point - 1;
|
||||
minus++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
caretPositionAmp = parseInt(caretPositionAmp);
|
||||
// IE
|
||||
input.onmouseup = function() { // for IE because it loses caret position when focus changed
|
||||
if (document.selection && typeof(input.selectionStart) != "number") {
|
||||
input.focus();
|
||||
s = document.selection.createRange();
|
||||
re = input.createTextRange();
|
||||
rc = re.duplicate();
|
||||
re.moveToBookmark(s.getBookmark());
|
||||
rc.setEndPoint("EndToStart", re);
|
||||
caretPositionAmp = rc.text.length;
|
||||
}
|
||||
}
|
||||
|
||||
if (document.selection && typeof(input.selectionStart) != "number") {
|
||||
s = document.selection.createRange();
|
||||
if (s.text.length != 0) {
|
||||
return this;
|
||||
}
|
||||
re = input.createTextRange();
|
||||
textLength = re.text.length;
|
||||
rc = re.duplicate();
|
||||
re.moveToBookmark(s.getBookmark());
|
||||
rc.setEndPoint("EndToStart", re);
|
||||
start = rc.text.length;
|
||||
if (caretPositionAmp > 0 && start ==0) {
|
||||
minus = caretPositionAmp - minus;
|
||||
re.move("character", minus);
|
||||
re.select();
|
||||
s = document.selection.createRange();
|
||||
caretPositionAmp += inputStr.length;
|
||||
} else if (!(caretPositionAmp >= 0) && textLength ==0) {
|
||||
s = document.selection.createRange();
|
||||
caretPositionAmp = inputStr.length + textLength;
|
||||
} else if (!(caretPositionAmp >= 0) && start ==0) {
|
||||
re.move("character", textLength);
|
||||
re.select();
|
||||
s = document.selection.createRange();
|
||||
caretPositionAmp = inputStr.length + textLength;
|
||||
} else if (!(caretPositionAmp >= 0) && start > 0) {
|
||||
re.move("character", 0);
|
||||
document.selection.empty();
|
||||
re.select();
|
||||
s = document.selection.createRange();
|
||||
caretPositionAmp = start + inputStr.length;
|
||||
} else if (caretPositionAmp >= 0 && caretPositionAmp == textLength) {
|
||||
if (textLength != 0) {
|
||||
re.move("character", textLength);
|
||||
re.select();
|
||||
} else {
|
||||
re.move("character", 0);
|
||||
}
|
||||
s = document.selection.createRange();
|
||||
caretPositionAmp = inputStr.length + textLength;
|
||||
} else if (caretPositionAmp >= 0 && start != 0 && caretPositionAmp >= start) {
|
||||
minus = caretPositionAmp - start;
|
||||
re.move("character", minus);
|
||||
document.selection.empty();
|
||||
re.select();
|
||||
s = document.selection.createRange();
|
||||
caretPositionAmp = caretPositionAmp + inputStr.length;
|
||||
} else if (caretPositionAmp >= 0 && start != 0 && caretPositionAmp < start) {
|
||||
re.move("character", 0);
|
||||
document.selection.empty();
|
||||
re.select();
|
||||
s = document.selection.createRange();
|
||||
caretPositionAmp = caretPositionAmp + inputStr.length;
|
||||
} else {
|
||||
document.selection.empty();
|
||||
re.select();
|
||||
s = document.selection.createRange();
|
||||
caretPositionAmp = caretPositionAmp + inputStr.length;
|
||||
}
|
||||
s.text = inputStr;
|
||||
input.focus();
|
||||
|
||||
return this;
|
||||
} else if (typeof(input.selectionStart) == "number" && // MOZILLA support
|
||||
input.selectionStart == input.selectionEnd) {
|
||||
position = input.selectionStart + inputStr.length;
|
||||
start = input.selectionStart;
|
||||
end = input.selectionEnd;
|
||||
input.value = input.value.substr(0, start) + inputStr + input.value.substr(end);
|
||||
input.setSelectionRange(position, position);
|
||||
input.scrollTop = mozScrollFix;
|
||||
return this;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
// Set caret position
|
||||
setCaretPos: function(inputStr) {
|
||||
|
||||
var input = this.jquery ? this[0] : this;
|
||||
var s;
|
||||
var re;
|
||||
var position;
|
||||
var number = 0;
|
||||
var minus = 0;
|
||||
var w;
|
||||
input.focus();
|
||||
if (parseInt(inputStr) == 0) {
|
||||
return this;
|
||||
}
|
||||
//if (document.selection && typeof(input.selectionStart) == "number") {
|
||||
if (parseInt(inputStr) > 0) {
|
||||
inputStr = parseInt(inputStr) - 1;
|
||||
if (document.selection && typeof(input.selectionStart) == "number" && input.selectionStart == input.selectionEnd) {
|
||||
if (input.value.match(/\n/g) != null) {
|
||||
number = input.value.match(/\n/g).length;// number of EOL simbols
|
||||
}
|
||||
if (number > 0) {
|
||||
for (var i = 0; i <= number; i++) {
|
||||
w = input.value.indexOf("\n", position);
|
||||
if (w != -1 && w <= inputStr) {
|
||||
position = w + 1;
|
||||
inputStr = parseInt(inputStr) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (parseInt(inputStr) < 0) {
|
||||
inputStr = parseInt(inputStr) + 1;
|
||||
if (document.selection && typeof(input.selectionStart) != "number") {
|
||||
inputStr = input.value.length + parseInt(inputStr);
|
||||
if (input.value.match(/\n/g) != null) {
|
||||
number = input.value.match(/\n/g).length;// number of EOL simbols
|
||||
}
|
||||
if (number > 0) {
|
||||
for (var i = 0; i <= number; i++) {
|
||||
w = input.value.indexOf("\n", position);
|
||||
if (w != -1 && w <= inputStr) {
|
||||
position = w + 1;
|
||||
inputStr = parseInt(inputStr) - 1;
|
||||
minus += 1;
|
||||
}
|
||||
}
|
||||
inputStr = inputStr + minus - number;
|
||||
}
|
||||
} else if (document.selection && typeof(input.selectionStart) == "number") {
|
||||
inputStr = input.value.length + parseInt(inputStr);
|
||||
if (input.value.match(/\n/g) != null) {
|
||||
number = input.value.match(/\n/g).length;// number of EOL simbols
|
||||
}
|
||||
if (number > 0) {
|
||||
inputStr = parseInt(inputStr) - number;
|
||||
for (var i = 0; i <= number; i++) {
|
||||
w = input.value.indexOf("\n", position);
|
||||
if (w != -1 && w <= (inputStr)) {
|
||||
position = w + 1;
|
||||
inputStr = parseInt(inputStr) + 1;
|
||||
minus += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { inputStr = input.value.length + parseInt(inputStr); }
|
||||
} else { return this; }
|
||||
// IE
|
||||
if (document.selection && typeof(input.selectionStart) != "number") {
|
||||
s = document.selection.createRange();
|
||||
if (s.text != 0) {
|
||||
return this;
|
||||
}
|
||||
re = input.createTextRange();
|
||||
re.collapse(true);
|
||||
re.moveEnd('character', inputStr);
|
||||
re.moveStart('character', inputStr);
|
||||
re.select();
|
||||
caretPositionAmp = inputStr;
|
||||
|
||||
return this;
|
||||
} else if (typeof(input.selectionStart) == "number" && // MOZILLA support
|
||||
input.selectionStart == input.selectionEnd) {
|
||||
input.setSelectionRange(inputStr, inputStr);
|
||||
return this;
|
||||
}
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
countCharacters: function(str) {
|
||||
var input = this.jquery ? this[0] : this;
|
||||
if (input.value.match(/\r/g) != null) {
|
||||
return input.value.length - input.value.match(/\r/g).length;
|
||||
}
|
||||
return input.value.length;
|
||||
},
|
||||
|
||||
setMaxLength: function(max, f) {
|
||||
this.each(function() {
|
||||
var input = this.jquery ? this[0] : this;
|
||||
var type = input.type;
|
||||
var isSelected;
|
||||
var maxCharacters;
|
||||
// remove limit if input is a negative number
|
||||
if (parseInt(max) < 0) {
|
||||
max=100000000;
|
||||
}
|
||||
if (type == "text") {
|
||||
input.maxLength = max;
|
||||
}
|
||||
if (type == "textarea" || type == "text") {
|
||||
input.onkeypress = function(e) {
|
||||
var spacesR = input.value.match(/\r/g);
|
||||
maxCharacters = max;
|
||||
if (spacesR != null) {
|
||||
maxCharacters = parseInt(maxCharacters) + spacesR.length;
|
||||
}
|
||||
// get event
|
||||
var key = e || event;
|
||||
var keyCode = key.keyCode;
|
||||
// check if any part of text is selected
|
||||
if (document.selection) {
|
||||
isSelected = document.selection.createRange().text.length > 0;
|
||||
} else {
|
||||
isSelected = input.selectionStart != input.selectionEnd;
|
||||
}
|
||||
if (input.value.length >= maxCharacters && (keyCode > 47 || keyCode == 32 ||
|
||||
keyCode == 0 || keyCode == 13) && !key.ctrlKey && !key.altKey && !isSelected) {
|
||||
input.value = input.value.substring(0,maxCharacters);
|
||||
if (typeof(f) == "function") { f() } //callback function
|
||||
return false;
|
||||
}
|
||||
}
|
||||
input.onkeyup = function() {
|
||||
var spacesR = input.value.match(/\r/g);
|
||||
var plus = 0;
|
||||
var position = 0;
|
||||
maxCharacters = max;
|
||||
if (spacesR != null) {
|
||||
for (var i = 0; i <= spacesR.length; i++) {
|
||||
if (input.value.indexOf("\n", position) <= parseInt(max)) {
|
||||
plus++;
|
||||
position = input.value.indexOf("\n", position) + 1;
|
||||
}
|
||||
}
|
||||
maxCharacters = parseInt(max) + plus;
|
||||
}
|
||||
if (input.value.length > maxCharacters) {
|
||||
input.value = input.value.substring(0, maxCharacters);
|
||||
if (typeof(f) == "function") { f() }
|
||||
return this;
|
||||
}
|
||||
}
|
||||
} else { return this; }
|
||||
})
|
||||
return this;
|
||||
}
|
||||
});
|
231
js/jquery.asuggest.js
Normal file
231
js/jquery.asuggest.js
Normal file
@ -0,0 +1,231 @@
|
||||
/*
|
||||
* jQuery textarea suggest plugin
|
||||
*
|
||||
* Copyright (c) 2009-2010 Roman Imankulov
|
||||
*
|
||||
* Dual licensed under the MIT and GPL licenses:
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
* Requires:
|
||||
* - jQuery (tested with 1.3.x and 1.4.x)
|
||||
* - jquery.a-tools >= 1.4.1 (http://plugins.jquery.com/project/a-tools)
|
||||
*/
|
||||
|
||||
/*globals jQuery,document */
|
||||
|
||||
(function ($) {
|
||||
// workaround for Opera browser
|
||||
if (navigator.userAgent.match(/opera/i)) {
|
||||
$(document).keypress(function (e) {
|
||||
if ($.asuggestFocused) {
|
||||
$.asuggestFocused.focus();
|
||||
$.asuggestFocused = null;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$.asuggestKeys = {
|
||||
UNKNOWN: 0,
|
||||
SHIFT: 16,
|
||||
CTRL: 17,
|
||||
ALT: 18,
|
||||
LEFT: 37,
|
||||
UP: 38,
|
||||
RIGHT: 39,
|
||||
DOWN: 40,
|
||||
DEL: 46,
|
||||
TAB: 9,
|
||||
RETURN: 13,
|
||||
ESC: 27,
|
||||
COMMA: 188,
|
||||
PAGEUP: 33,
|
||||
PAGEDOWN: 34,
|
||||
BACKSPACE: 8,
|
||||
SPACE: 32
|
||||
};
|
||||
$.asuggestFocused = null;
|
||||
|
||||
$.fn.asuggest = function (suggests, options) {
|
||||
return this.each(function () {
|
||||
$.makeSuggest(this, suggests, options);
|
||||
});
|
||||
};
|
||||
|
||||
$.fn.asuggest.defaults = {
|
||||
'delimiters': '\n ',
|
||||
'minChunkSize': 1,
|
||||
'cycleOnTab': true,
|
||||
'autoComplete': true,
|
||||
'endingSymbols': ' ',
|
||||
'stopSuggestionKeys': [$.asuggestKeys.RETURN, $.asuggestKeys.SPACE],
|
||||
'ignoreCase': false
|
||||
};
|
||||
|
||||
/* Make suggest:
|
||||
*
|
||||
* create and return jQuery object on the top of DOM object
|
||||
* and store suggests as part of this object
|
||||
*
|
||||
* @param area: HTML DOM element to add suggests to
|
||||
* @param suggests: The array of suggest strings
|
||||
* @param options: The options object
|
||||
*/
|
||||
$.makeSuggest = function (area, suggests, options) {
|
||||
options = $.extend({}, $.fn.asuggest.defaults, options);
|
||||
|
||||
var KEY = $.asuggestKeys,
|
||||
$area = $(area);
|
||||
$area.suggests = suggests;
|
||||
$area.options = options;
|
||||
|
||||
/* Internal method: get the chunk of text before the cursor */
|
||||
$area.getChunk = function () {
|
||||
var delimiters = this.options.delimiters.split(''), // array of chars
|
||||
textBeforeCursor = this.val().substr(0, this.getSelection().start),
|
||||
indexOfDelimiter = -1,
|
||||
i,
|
||||
d,
|
||||
idx;
|
||||
for (i = 0; i < delimiters.length; i++) {
|
||||
d = delimiters[i];
|
||||
idx = textBeforeCursor.lastIndexOf(d);
|
||||
if (idx > indexOfDelimiter) {
|
||||
indexOfDelimiter = idx;
|
||||
}
|
||||
}
|
||||
if (indexOfDelimiter < 0) {
|
||||
return textBeforeCursor;
|
||||
} else {
|
||||
return textBeforeCursor.substr(indexOfDelimiter + 1);
|
||||
}
|
||||
};
|
||||
|
||||
/* Internal method: get completion.
|
||||
* If performCycle is true then analyze getChunk() and and getSelection()
|
||||
*/
|
||||
$area.getCompletion = function (performCycle) {
|
||||
var text = this.getChunk(),
|
||||
selectionText = this.getSelection().text,
|
||||
suggests = this.suggests,
|
||||
foundAlreadySelectedValue = false,
|
||||
firstMatchedValue = null,
|
||||
i,
|
||||
suggest;
|
||||
// search the variant
|
||||
for (i = 0; i < suggests.length; i++) {
|
||||
suggest = suggests[i];
|
||||
if ($area.options.ignoreCase) {
|
||||
suggest = suggest.toLowerCase();
|
||||
text = text.toLowerCase();
|
||||
}
|
||||
// some variant is found
|
||||
if (suggest.indexOf(text) === 0) {
|
||||
if (performCycle) {
|
||||
if (text + selectionText === suggest) {
|
||||
foundAlreadySelectedValue = true;
|
||||
} else if (foundAlreadySelectedValue) {
|
||||
return suggest.substr(text.length);
|
||||
} else if (firstMatchedValue === null) {
|
||||
firstMatchedValue = suggest;
|
||||
}
|
||||
} else {
|
||||
return suggest.substr(text.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (performCycle && firstMatchedValue) {
|
||||
return firstMatchedValue.substr(text.length);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
$area.updateSelection = function (completion) {
|
||||
if (completion) {
|
||||
var _selectionStart = $area.getSelection().start,
|
||||
_selectionEnd = _selectionStart + completion.length;
|
||||
if ($area.getSelection().text === "") {
|
||||
if ($area.val().length === _selectionStart) { // Weird IE workaround, I really have no idea why it works
|
||||
$area.setCaretPos(_selectionStart + 10000);
|
||||
}
|
||||
$area.insertAtCaretPos(completion);
|
||||
} else {
|
||||
$area.replaceSelection(completion);
|
||||
}
|
||||
$area.setSelection(_selectionStart, _selectionEnd);
|
||||
}
|
||||
};
|
||||
|
||||
$area.unbind('keydown.asuggest').bind('keydown.asuggest', function (e) {
|
||||
if (e.keyCode === KEY.TAB) {
|
||||
if ($area.options.cycleOnTab) {
|
||||
var chunk = $area.getChunk();
|
||||
if (chunk.length >= $area.options.minChunkSize) {
|
||||
$area.updateSelection($area.getCompletion(true));
|
||||
}
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
$area.focus();
|
||||
$.asuggestFocused = this;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Check for conditions to stop suggestion
|
||||
if ($area.getSelection().length &&
|
||||
$.inArray(e.keyCode, $area.options.stopSuggestionKeys) !== -1) {
|
||||
// apply suggestion. Clean up selection and insert a space
|
||||
var _selectionEnd = $area.getSelection().end +
|
||||
$area.options.endingSymbols.length;
|
||||
var _text = $area.getSelection().text +
|
||||
$area.options.endingSymbols;
|
||||
$area.replaceSelection(_text);
|
||||
$area.setSelection(_selectionEnd, _selectionEnd);
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.focus();
|
||||
$.asuggestFocused = this;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
$area.unbind('keyup.asuggest').bind('keyup.asuggest', function (e) {
|
||||
var hasSpecialKeys = e.altKey || e.metaKey || e.ctrlKey,
|
||||
hasSpecialKeysOrShift = hasSpecialKeys || e.shiftKey;
|
||||
switch (e.keyCode) {
|
||||
case KEY.UNKNOWN: // Special key released
|
||||
case KEY.SHIFT:
|
||||
case KEY.CTRL:
|
||||
case KEY.ALT:
|
||||
case KEY.RETURN: // we don't want to suggest when RETURN key has pressed (another IE workaround)
|
||||
break;
|
||||
case KEY.TAB:
|
||||
if (!hasSpecialKeysOrShift && $area.options.cycleOnTab) {
|
||||
break;
|
||||
}
|
||||
case KEY.ESC:
|
||||
case KEY.BACKSPACE:
|
||||
case KEY.DEL:
|
||||
case KEY.UP:
|
||||
case KEY.DOWN:
|
||||
case KEY.LEFT:
|
||||
case KEY.RIGHT:
|
||||
if (!hasSpecialKeysOrShift && $area.options.autoComplete) {
|
||||
$area.replaceSelection("");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (!hasSpecialKeys && $area.options.autoComplete) {
|
||||
var chunk = $area.getChunk();
|
||||
if (chunk.length >= $area.options.minChunkSize) {
|
||||
$area.updateSelection($area.getCompletion(false));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
return $area;
|
||||
};
|
||||
}(jQuery));
|
@ -1,554 +0,0 @@
|
||||
/*!
|
||||
* jQuery.textcomplete.js
|
||||
*
|
||||
* Repositiory: https://github.com/yuku-t/jquery-textcomplete
|
||||
* License: MIT
|
||||
* Author: Yuku Takahashi
|
||||
*/
|
||||
|
||||
;(function ($) {
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Exclusive execution control utility.
|
||||
*/
|
||||
var lock = function (func) {
|
||||
var free, locked;
|
||||
free = function () { locked = false; };
|
||||
return function () {
|
||||
var args;
|
||||
if (locked) return;
|
||||
locked = true;
|
||||
args = toArray(arguments);
|
||||
args.unshift(free);
|
||||
func.apply(this, args);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert arguments into a real array.
|
||||
*/
|
||||
var toArray = function (args) {
|
||||
var result;
|
||||
result = Array.prototype.slice.call(args);
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the styles of any element from property names.
|
||||
*/
|
||||
var getStyles = (function () {
|
||||
var color;
|
||||
color = $('<div></div>').css(['color']).color;
|
||||
if (typeof color !== 'undefined') {
|
||||
return function ($el, properties) {
|
||||
return $el.css(properties);
|
||||
};
|
||||
} else { // for jQuery 1.8 or below
|
||||
return function ($el, properties) {
|
||||
var styles;
|
||||
styles = {};
|
||||
$.each(properties, function (i, property) {
|
||||
styles[property] = $el.css(property);
|
||||
});
|
||||
return styles;
|
||||
};
|
||||
}
|
||||
})();
|
||||
|
||||
/**
|
||||
* Default template function.
|
||||
*/
|
||||
var identity = function (obj) { return obj; };
|
||||
|
||||
/**
|
||||
* Memoize a search function.
|
||||
*/
|
||||
var memoize = function (func) {
|
||||
var memo = {};
|
||||
return function (term, callback) {
|
||||
if (memo[term]) {
|
||||
callback(memo[term]);
|
||||
} else {
|
||||
func.call(this, term, function (data) {
|
||||
memo[term] = (memo[term] || []).concat(data);
|
||||
callback.apply(null, arguments);
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine if the array contains a given value.
|
||||
*/
|
||||
var include = function (array, value) {
|
||||
var i, l;
|
||||
if (array.indexOf) return array.indexOf(value) != -1;
|
||||
for (i = 0, l = array.length; i < l; i++) {
|
||||
if (array[i] === value) return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Textarea manager class.
|
||||
*/
|
||||
var Completer = (function () {
|
||||
var html, css, $baseWrapper, $baseList, _id;
|
||||
|
||||
html = {
|
||||
wrapper: '<div class="textcomplete-wrapper"></div>',
|
||||
list: '<ul class="dropdown-menu"></ul>'
|
||||
};
|
||||
css = {
|
||||
wrapper: {
|
||||
position: 'relative'
|
||||
},
|
||||
list: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
zIndex: '100',
|
||||
display: 'none'
|
||||
}
|
||||
};
|
||||
$baseWrapper = $(html.wrapper).css(css.wrapper);
|
||||
$baseList = $(html.list).css(css.list);
|
||||
_id = 0;
|
||||
|
||||
function Completer($el) {
|
||||
var focus;
|
||||
this.el = $el.get(0); // textarea element
|
||||
focus = this.el === document.activeElement;
|
||||
// Cannot wrap $el at initialize method lazily due to Firefox's behavior.
|
||||
this.$el = wrapElement($el); // Focus is lost
|
||||
this.id = 'textComplete' + _id++;
|
||||
this.strategies = [];
|
||||
if (focus) {
|
||||
this.initialize();
|
||||
this.$el.focus();
|
||||
} else {
|
||||
this.$el.one('focus.textComplete', $.proxy(this.initialize, this));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Completer's public methods
|
||||
*/
|
||||
$.extend(Completer.prototype, {
|
||||
|
||||
/**
|
||||
* Prepare ListView and bind events.
|
||||
*/
|
||||
initialize: function () {
|
||||
var $list, globalEvents;
|
||||
$list = $baseList.clone();
|
||||
this.listView = new ListView($list, this);
|
||||
this.$el
|
||||
.before($list)
|
||||
.on({
|
||||
'keyup.textComplete': $.proxy(this.onKeyup, this),
|
||||
'keydown.textComplete': $.proxy(this.listView.onKeydown,
|
||||
this.listView)
|
||||
});
|
||||
globalEvents = {};
|
||||
globalEvents['click.' + this.id] = $.proxy(this.onClickDocument, this);
|
||||
globalEvents['keyup.' + this.id] = $.proxy(this.onKeyupDocument, this);
|
||||
$(document).on(globalEvents);
|
||||
},
|
||||
|
||||
/**
|
||||
* Register strategies to the completer.
|
||||
*/
|
||||
register: function (strategies) {
|
||||
this.strategies = this.strategies.concat(strategies);
|
||||
},
|
||||
|
||||
/**
|
||||
* Show autocomplete list next to the caret.
|
||||
*/
|
||||
renderList: function (data) {
|
||||
if (this.clearAtNext) {
|
||||
this.listView.clear();
|
||||
this.clearAtNext = false;
|
||||
}
|
||||
if (data.length) {
|
||||
if (!this.listView.shown) {
|
||||
this.listView
|
||||
.setPosition(this.getCaretPosition())
|
||||
.clear()
|
||||
.activate();
|
||||
this.listView.strategy = this.strategy;
|
||||
}
|
||||
data = data.slice(0, this.strategy.maxCount);
|
||||
this.listView.render(data);
|
||||
}
|
||||
|
||||
if (!this.listView.data.length && this.listView.shown) {
|
||||
this.listView.deactivate();
|
||||
}
|
||||
},
|
||||
|
||||
searchCallbackFactory: function (free) {
|
||||
var self = this;
|
||||
return function (data, keep) {
|
||||
self.renderList(data);
|
||||
if (!keep) {
|
||||
// This is the last callback for this search.
|
||||
free();
|
||||
self.clearAtNext = true;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Keyup event handler.
|
||||
*/
|
||||
onKeyup: function (e) {
|
||||
var searchQuery, term;
|
||||
if (this.skipSearch(e)) { return; }
|
||||
|
||||
searchQuery = this.extractSearchQuery(this.getTextFromHeadToCaret());
|
||||
if (searchQuery.length) {
|
||||
term = searchQuery[1];
|
||||
if (this.term === term) return; // Ignore shift-key or something.
|
||||
this.term = term;
|
||||
this.search(searchQuery);
|
||||
} else {
|
||||
this.term = null;
|
||||
this.listView.deactivate();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Suppress searching if it returns true.
|
||||
*/
|
||||
skipSearch: function (e) {
|
||||
if (this.skipNextKeyup) {
|
||||
this.skipNextKeyup = false;
|
||||
return true;
|
||||
}
|
||||
switch (e.keyCode) {
|
||||
case 40:
|
||||
case 38:
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
onSelect: function (value) {
|
||||
var pre, post, newSubStr;
|
||||
pre = this.getTextFromHeadToCaret();
|
||||
post = this.el.value.substring(this.el.selectionEnd);
|
||||
|
||||
newSubStr = this.strategy.replace(value);
|
||||
if ($.isArray(newSubStr)) {
|
||||
post = newSubStr[1] + post;
|
||||
newSubStr = newSubStr[0];
|
||||
}
|
||||
pre = pre.replace(this.strategy.match, newSubStr);
|
||||
this.$el.val(pre + post)
|
||||
.trigger('change')
|
||||
.trigger('textComplete:select', value);
|
||||
this.el.focus();
|
||||
this.el.selectionStart = this.el.selectionEnd = pre.length;
|
||||
this.skipNextKeyup = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Global click event handler.
|
||||
*/
|
||||
onClickDocument: function (e) {
|
||||
if (e.originalEvent && !e.originalEvent.keepTextCompleteDropdown) {
|
||||
this.listView.deactivate();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Global keyup event handler.
|
||||
*/
|
||||
onKeyupDocument: function (e) {
|
||||
if (this.listView.shown && e.keyCode === 27) { // ESC
|
||||
this.listView.deactivate();
|
||||
this.$el.focus();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove all event handlers and the wrapper element.
|
||||
*/
|
||||
destroy: function () {
|
||||
var $wrapper;
|
||||
this.$el.off('.textComplete');
|
||||
$(document).off('.' + this.id);
|
||||
if (this.listView) { this.listView.destroy(); }
|
||||
$wrapper = this.$el.parent();
|
||||
$wrapper.after(this.$el).remove();
|
||||
this.$el.data('textComplete', void 0);
|
||||
this.$el = null;
|
||||
},
|
||||
|
||||
// Helper methods
|
||||
// ==============
|
||||
|
||||
/**
|
||||
* Returns caret's relative coordinates from textarea's left top corner.
|
||||
*/
|
||||
getCaretPosition: function () {
|
||||
// Browser native API does not provide the way to know the position of
|
||||
// caret in pixels, so that here we use a kind of hack to accomplish
|
||||
// the aim. First of all it puts a div element and completely copies
|
||||
// the textarea's style to the element, then it inserts the text and a
|
||||
// span element into the textarea.
|
||||
// Consequently, the span element's position is the thing what we want.
|
||||
|
||||
if (this.el.selectionEnd === 0) return;
|
||||
var properties, css, $div, $span, position, dir;
|
||||
|
||||
dir = this.$el.attr('dir') || this.$el.css('direction');
|
||||
properties = ['border-width', 'font-family', 'font-size', 'font-style',
|
||||
'font-variant', 'font-weight', 'height', 'letter-spacing',
|
||||
'word-spacing', 'line-height', 'text-decoration', 'text-align',
|
||||
'width', 'padding-top', 'padding-right', 'padding-bottom',
|
||||
'padding-left', 'margin-top', 'margin-right', 'margin-bottom',
|
||||
'margin-left'
|
||||
];
|
||||
css = $.extend({
|
||||
position: 'absolute',
|
||||
overflow: 'auto',
|
||||
'white-space': 'pre-wrap',
|
||||
top: 0,
|
||||
left: -9999,
|
||||
direction: dir
|
||||
}, getStyles(this.$el, properties));
|
||||
|
||||
$div = $('<div></div>').css(css).text(this.getTextFromHeadToCaret());
|
||||
$span = $('<span></span>').text('.').appendTo($div);
|
||||
this.$el.before($div);
|
||||
position = $span.position();
|
||||
position.top += $span.height() - this.$el.scrollTop();
|
||||
if (dir === 'rtl') { position.left -= this.listView.$el.width(); }
|
||||
$div.remove();
|
||||
return position;
|
||||
},
|
||||
|
||||
getTextFromHeadToCaret: function () {
|
||||
var text, selectionEnd, range;
|
||||
selectionEnd = this.el.selectionEnd;
|
||||
if (typeof selectionEnd === 'number') {
|
||||
text = this.el.value.substring(0, selectionEnd);
|
||||
} else if (document.selection) {
|
||||
range = this.el.createTextRange();
|
||||
range.moveStart('character', 0);
|
||||
range.moveEnd('textedit');
|
||||
text = range.text;
|
||||
}
|
||||
return text;
|
||||
},
|
||||
|
||||
/**
|
||||
* Parse the value of textarea and extract search query.
|
||||
*/
|
||||
extractSearchQuery: function (text) {
|
||||
// If a search query found, it returns used strategy and the query
|
||||
// term. If the caret is currently in a code block or search query does
|
||||
// not found, it returns an empty array.
|
||||
|
||||
var i, l, strategy, match;
|
||||
for (i = 0, l = this.strategies.length; i < l; i++) {
|
||||
strategy = this.strategies[i];
|
||||
match = text.match(strategy.match);
|
||||
if (match) { return [strategy, match[strategy.index]]; }
|
||||
}
|
||||
return [];
|
||||
},
|
||||
|
||||
search: lock(function (free, searchQuery) {
|
||||
var term;
|
||||
this.strategy = searchQuery[0];
|
||||
term = searchQuery[1];
|
||||
this.strategy.search(term, this.searchCallbackFactory(free));
|
||||
})
|
||||
});
|
||||
|
||||
/**
|
||||
* Completer's private functions
|
||||
*/
|
||||
var wrapElement = function ($el) {
|
||||
return $el.wrap($baseWrapper.clone().css('display', $el.css('display')));
|
||||
};
|
||||
|
||||
return Completer;
|
||||
})();
|
||||
|
||||
/**
|
||||
* Dropdown menu manager class.
|
||||
*/
|
||||
var ListView = (function () {
|
||||
|
||||
function ListView($el, completer) {
|
||||
this.data = [];
|
||||
this.$el = $el;
|
||||
this.index = 0;
|
||||
this.completer = completer;
|
||||
|
||||
this.$el.on('click.textComplete', 'li.textcomplete-item',
|
||||
$.proxy(this.onClick, this));
|
||||
}
|
||||
|
||||
$.extend(ListView.prototype, {
|
||||
shown: false,
|
||||
|
||||
render: function (data) {
|
||||
var html, i, l, index, val;
|
||||
|
||||
html = '';
|
||||
for (i = 0, l = data.length; i < l; i++) {
|
||||
val = data[i];
|
||||
if (include(this.data, val)) continue;
|
||||
index = this.data.length;
|
||||
this.data.push(val);
|
||||
html += '<li class="textcomplete-item" data-index="' + index + '"><a>';
|
||||
html += this.strategy.template(val);
|
||||
html += '</a></li>';
|
||||
if (this.data.length === this.strategy.maxCount) break;
|
||||
}
|
||||
this.$el.append(html);
|
||||
if (!this.data.length) {
|
||||
this.deactivate();
|
||||
} else {
|
||||
this.activateIndexedItem();
|
||||
}
|
||||
},
|
||||
|
||||
clear: function () {
|
||||
this.data = [];
|
||||
this.$el.html('');
|
||||
this.index = 0;
|
||||
return this;
|
||||
},
|
||||
|
||||
activateIndexedItem: function () {
|
||||
this.$el.find('.active').removeClass('active');
|
||||
this.getActiveItem().addClass('active');
|
||||
},
|
||||
|
||||
getActiveItem: function () {
|
||||
return $(this.$el.children().get(this.index));
|
||||
},
|
||||
|
||||
activate: function () {
|
||||
if (!this.shown) {
|
||||
this.$el.show();
|
||||
this.completer.$el.trigger('textComplete:show');
|
||||
this.shown = true;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
deactivate: function () {
|
||||
if (this.shown) {
|
||||
this.$el.hide();
|
||||
this.completer.$el.trigger('textComplete:hide');
|
||||
this.shown = false;
|
||||
this.data = this.index = null;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
setPosition: function (position) {
|
||||
this.$el.css(position);
|
||||
return this;
|
||||
},
|
||||
|
||||
select: function (index) {
|
||||
var self = this;
|
||||
this.completer.onSelect(this.data[index]);
|
||||
// Deactive at next tick to allow other event handlers to know whether
|
||||
// the dropdown has been shown or not.
|
||||
setTimeout(function () { self.deactivate(); }, 0);
|
||||
},
|
||||
|
||||
onKeydown: function (e) {
|
||||
if (!this.shown) return;
|
||||
if (e.keyCode === 38) { // UP
|
||||
e.preventDefault();
|
||||
if (this.index === 0) {
|
||||
this.index = this.data.length-1;
|
||||
} else {
|
||||
this.index -= 1;
|
||||
}
|
||||
this.activateIndexedItem();
|
||||
} else if (e.keyCode === 40) { // DOWN
|
||||
e.preventDefault();
|
||||
if (this.index === this.data.length - 1) {
|
||||
this.index = 0;
|
||||
} else {
|
||||
this.index += 1;
|
||||
}
|
||||
this.activateIndexedItem();
|
||||
} else if (e.keyCode === 13 || e.keyCode === 9) { // ENTER or TAB
|
||||
e.preventDefault();
|
||||
|
||||
this.select(parseInt(this.getActiveItem().data('index'), 10));
|
||||
}
|
||||
},
|
||||
|
||||
onClick: function (e) {
|
||||
var $e = $(e.target);
|
||||
e.originalEvent.keepTextCompleteDropdown = true;
|
||||
if (!$e.hasClass('textcomplete-item')) {
|
||||
$e = $e.parents('li.textcomplete-item');
|
||||
}
|
||||
this.select(parseInt($e.data('index'), 10));
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
this.deactivate();
|
||||
this.$el.off('click.textComplete').remove();
|
||||
this.$el = null;
|
||||
}
|
||||
});
|
||||
|
||||
return ListView;
|
||||
})();
|
||||
|
||||
$.fn.textcomplete = function (strategies) {
|
||||
var i, l, strategy, dataKey;
|
||||
|
||||
dataKey = 'textComplete';
|
||||
|
||||
if (strategies === 'destroy') {
|
||||
return this.each(function () {
|
||||
var completer = $(this).data(dataKey);
|
||||
if (completer) { completer.destroy(); }
|
||||
});
|
||||
}
|
||||
|
||||
for (i = 0, l = strategies.length; i < l; i++) {
|
||||
strategy = strategies[i];
|
||||
if (!strategy.template) {
|
||||
strategy.template = identity;
|
||||
}
|
||||
if (strategy.index == null) {
|
||||
strategy.index = 2;
|
||||
}
|
||||
if (strategy.cache) {
|
||||
strategy.search = memoize(strategy.search);
|
||||
}
|
||||
strategy.maxCount || (strategy.maxCount = 10);
|
||||
}
|
||||
|
||||
return this.each(function () {
|
||||
var $this, completer;
|
||||
$this = $(this);
|
||||
completer = $this.data(dataKey);
|
||||
if (!completer) {
|
||||
completer = new Completer($this);
|
||||
$this.data(dataKey, completer);
|
||||
}
|
||||
completer.register(strategies);
|
||||
});
|
||||
};
|
||||
|
||||
})(window.jQuery || window.Zepto);
|
@ -32,7 +32,8 @@ function soundNotifOptions() {
|
||||
|
||||
function volumeControl () {
|
||||
var playerVol = $('#playerVol');
|
||||
playerVol[0].value = localStorage[playerVol[0].id] ? localStorage[playerVol[0].id] : 100;
|
||||
if(!localStorage[playerVol[0].id]) localStorage[playerVol[0].id] = 1;
|
||||
playerVol[0].value = localStorage[playerVol[0].id];
|
||||
$('.volValue').text((localStorage[playerVol[0].id] * 100).toFixed());
|
||||
|
||||
playerVol.on('change',function(){
|
||||
|
Loading…
x
Reference in New Issue
Block a user