Navigate up and down in scrollable div with keycodes - javascript

I have a searchable textbox which populates a div with the search results. The div is scrollable. What I am trying to achieve, is to navigate through the result items with page up and down (keycode 38 & 40). But as soon as I try this, the whole div scrolls, and the result item itself does not take on the new selected css class.
Below is some of my code
this.TagNavigation = function (event) {
var div = $("#TagSearchResults");
var anchors = $("#TagSearchResults a");
var selectedAnchor = $("#TagSearchResults a.selected");
var position = anchors.index(selectedAnchor);
if (event.keyCode == "13" && anchors.length > 0) {
FRAMEWORK.AddUpdateInterventionTags(selectedAnchor.attr("id").split("-")[1] + "|" + selectedAnchor.text(), "add");
}
if (event.keyCode == "13" && anchors.length == 0 && $("#txtTagSearch").val() != "Start typing to search Tags") {
FRAMEWORK.AddNewTag($("#txtTagSearch").val());
}
else if (event.keyCode == "38") {
if (position > 0) {
canClose = false;
selectedAnchor.removeClass("selected");
var newSelectedAnchor = $(anchors.get(position - 1));
newSelectedAnchor.addClass("selected");
$("#txtTagSearch").val(newSelectedAnchor.text());
}
}
else if (event.keyCode == "40") {
if (position <= anchors.length) {
canClose = false;
selectedAnchor.removeClass("selected");
var newSelectedAnchor = $(anchors.get(position + 1));
newSelectedAnchor.addClass("selected");
$("#txtTagSearch").val(newSelectedAnchor.text());
//newSelectedAnchor.focus();
}
}
};
this.AjaxSearch = function (text) {
var div = $("#TagSearchResults");
var anchors = $("#TagSearchResults a");
var selectedAnchor = $("#TagSearchResults a.selected");
var position = anchors.index(selectedAnchor);
if (event.keyCode == "13") {
FRAMEWORK.TagNavigation(event);
}
else if (event.keyCode == "38") {
FRAMEWORK.TagNavigation(event);
}
else if (event.keyCode == "40") {
FRAMEWORK.TagNavigation(event);
}
else if (text.length >= 3) {
FRAMEWORK.RenderSearchResults(text);
}
else {
$("#TagSearchResults").html("");
$("#TagSearchResults").hide();
}
};
As you can see in the TagNavigation function (keycode 40), I tried to set the focus on the active element, but still no success.
Any help please.

You need to check weather the newly selected element has a higher Y value that the bottom of the containing div. If so, then scroll the div by the height of the new element. Change your 'if (event.keyCode == "40")' statement to the following:
this.TagNavigation = function (event) {
var div = $("#TagSearchResults");
var anchors = $("#TagSearchResults a");
var selectedAnchor = $("#TagSearchResults a.selected");
var position = anchors.index(selectedAnchor);
if (event.keyCode == "13" && anchors.length > 0) {
FRAMEWORK.AddUpdateInterventionTags(selectedAnchor.attr("id").split("-")[1] + "|" + selectedAnchor.text(), "add");
}
if (event.keyCode == "13" && anchors.length == 0 && $("#txtTagSearch").val() != "Start typing to search Tags") {
FRAMEWORK.AddNewTag($("#txtTagSearch").val());
}
else if (event.keyCode == "38") {
if (position > 0) {
canClose = false;
selectedAnchor.removeClass("selected");
var newSelectedAnchor = $(anchors.get(position - 1));
newSelectedAnchor.addClass("selected");
$("#txtTagSearch").val(newSelectedAnchor.text());
var newSelectedAnchorPosistion = newSelectedAnchor.offset();
var divPosition = div.offset();
divPosition = divPosition.top;
if (newSelectedAnchorPosistion.top + 1 > divPosition) {
var newPos = div.scrollTop() - newSelectedAnchor.outerHeight();
div.scrollTop(newPos);
}
}
}
else if (event.keyCode == "40") {
if (position < anchors.length - 1) {
canClose = false;
selectedAnchor.removeClass("selected");
var newSelectedAnchor = $(anchors.get(position + 1));
newSelectedAnchor.addClass("selected");
$("#txtTagSearch").val(newSelectedAnchor.text());
var newSelectedAnchorPosistion = newSelectedAnchor.offset();
var divPosition = div.offset();
divPosition = divPosition.top + div.outerHeight();
if (newSelectedAnchorPosistion.top + 1 >= divPosition) {
var newPos = div.scrollTop() + newSelectedAnchor.outerHeight();
div.scrollTop(newPos);
}
}
}
};

Related

Javascript keydown event doesn´t give me the char # in EDGE

I'm working in a mentioning directive, basically when the user is typing in the input field ( a div with contentEditable=true in this case ), is gonna display a list of user for then insert the name of the user in a specific format, now the list is gonna displayed after the user press #, for chrome and firefox work just great but for EDGE and IE ( unfortunately i need to support ) doesn't work because in this case the # apparently doesn't exist.
now for the key press I'm using the #HostListener('keydown', ['$event'])
HostListener
#HostListener('keydown', ['$event']) keyHandler(event: any, nativeElement: HTMLInputElement = this._element.nativeElement) {
let val: string = getValue(nativeElement);
let pos = getCaretPosition(nativeElement, this.iframe);
let charPressed = this.keyCodeSpecified ? event.keyCode : event.key;
if (!charPressed) {
let charCode = event.which || event.keyCode;
if (!event.shiftKey && (charCode >= 65 && charCode <= 90)) {
charPressed = String.fromCharCode(charCode + 32);
} else if (event.shiftKey && charCode === KEY_2) {
charPressed = this.triggerChar;
} else {
charPressed = String.fromCharCode(event.which || event.keyCode);
}
}
if (event.keyCode == KEY_ENTER && event.wasClick && pos < this.startPos) {
// put caret back in position prior to contenteditable menu click
pos = this.startNode.length;
setCaretPosition(this.startNode, pos, this.iframe);
}
// console.log('=== keyHandler', this.startPos, pos, val, charPressed, event);
this.triggerList(event, charPressed, nativeElement, val, pos);
}
Now as you can see I'm using event.keycode and event.key to get the key from the event keydown, I pass does values to the method this.triggerList()
that basically is gonna display the list of mentions options if and only if the user press # that is the trigger char ( this.triggerChar ).
TriggerList Method
private triggerList(event, charPressed, nativeElement, val, pos): any {
if (charPressed == this.triggerChar) {
this.startPos = pos;
this.startNode = (this.iframe ? this.iframe.contentWindow.getSelection() : window.getSelection()).anchorNode;
// console.log('=== HERE CHAR', this.startNode, this.startPos);
// check if mentioning is allowed based on the text before the mention start char
if (!this.configService.appConfig.platform.EDGE) {
let position = this.getHtmlCaretPosition(nativeElement);
const charBefore = val[position - 1];
if (charBefore == undefined || charBefore.trim() == '' || charBefore == ':') {
this.log.trace('Start mentioning');
this.stopSearch = false;
this.searchString = null;
this.showSearchList(nativeElement);
this.updateSearchList();
}
} else {
this.stopSearch = false;
this.searchString = null;
this.showSearchList(nativeElement);
this.updateSearchList();
}
} else if (this.startPos >= 0 && !this.stopSearch) {
if (pos <= this.startPos) {
this.searchList.hidden = true;
}
// ignore shift when pressed alone, but not when used with another key
else if (event.keyCode !== KEY_SHIFT && !event.metaKey && !event.altKey && !event.ctrlKey && pos > this.startPos) {
if (event.keyCode === KEY_SPACE) {
this.startPos = -1;
} else if (event.keyCode === KEY_BACKSPACE && pos > 0) {
pos--;
if (pos == 0) {
this.stopSearch = true;
}
this.searchList.hidden = this.stopSearch;
} else if (!this.searchList.hidden) {
if (event.keyCode === KEY_TAB || event.keyCode === KEY_ENTER) {
this.stopEvent(event);
this.searchList.hidden = true;
// value is inserted without a trailing space for consistency
// between element types (div and iframe do not preserve the space)
let textValue = this.mentionSelect(this.searchList.activeItem);
insertValue(nativeElement, this.startPos, pos, textValue, this.iframe);
this.emitSelection(nativeElement);
if (this.htmlStyling) {
let quillElement = document.querySelector('.ql-editor');
let innerHtml = quillElement.innerHTML;
let strings = innerHtml.split(textValue);
if (strings.length === 2) {
innerHtml = `${strings[0]}<span id="mention${textValue.substring(1)}${strings.length - 1}" style="color: #0065FF; background: rgba(0,101,255,.2)">${textValue}</span> ${strings[1]}`;
} else {
let openSpan = false;
innerHtml = strings.reduce((total, current, currentIndex) => {
if (current.indexOf(`mention${textValue.substring(1)}`) > 0) {
return `${total}${openSpan ? '</span> ' : ''}${current}${textValue}`;
} else if (openSpan) {
return `${total}</span> ${currentIndex < strings.length - 1 ? current + textValue : current}`;
} else {
openSpan = true;
return `${total}${current}<span id="mention${textValue.substring(1)}${strings.length - 1}" style="color: #0065FF; background: rgba(0,101,255,.2)">${textValue}`;
}
}, '');
}
quillElement.innerHTML = innerHtml;
// tslint:disable-next-line:no-angle-bracket-type-assertion
let mentionElement: HTMLInputElement = document.getElementById(`mention${textValue.substring(1)}${strings.length - 1}`) as HTMLInputElement;
// tslint:disable-next-line:no-angle-bracket-type-assertion
setCaretPosition(mentionElement.nextSibling as HTMLInputElement, 1);
}
// fire input event so angular bindings are updated
if ('createEvent' in document) {
let evt = document.createEvent('HTMLEvents');
evt.initEvent('input', false, true);
nativeElement.dispatchEvent(evt);
}
this.startPos = -1;
return false;
} else if (event.keyCode === KEY_ESCAPE) {
this.stopEvent(event);
this.searchList.hidden = true;
this.stopSearch = true;
return false;
} else if (event.keyCode === KEY_DOWN) {
this.stopEvent(event);
this.searchList.activateNextItem();
return false;
} else if (event.keyCode === KEY_UP) {
this.stopEvent(event);
this.searchList.activatePreviousItem();
return false;
}
}
if (event.keyCode === KEY_LEFT || event.keyCode === KEY_RIGHT) {
this.stopEvent(event);
return false;
} else {
let mention = val.substring(this.startPos + 1, pos);
if (event.keyCode !== KEY_BACKSPACE) {
mention += charPressed;
}
this.searchString = mention;
this.searchTerm.emit(this.searchString);
this.updateSearchList();
}
}
}
}
now the issue here is that if the user to insert the char # need to use the combination of ALT + Q EDGE only detect ALT and then Q, compare to firefox and chrome that with the combination ALT + Q detect # for this reason the list is not display because the char never match.
First i replace the event keydown for keypress, then where i save the char in the variable charPress i create a condition to check if the browser is EDGE or IE, and get char code using event.charCode and convert it in to string using String.fromCharCode(event.charCode) at the end looks like this.
#HostListener('keypress', ['$event']) keyHandler(event: any, nativeElement: HTMLInputElement = this._element.nativeElement) {
let val: string = getValue(nativeElement);
let pos = getCaretPosition(nativeElement, this.iframe);
let charPressed = this.keyCodeSpecified ? event.keyCode : event.key;
if (this.configService.appConfig.platform.EDGE) {
charPressed = String.fromCharCode(event.charCode);
}
......

Synchronous input update with selected digit in HTML/JavaScript

I'm trying to implement a customised input that can use left or right arrow key to select the digit and use up/down arrow key to increment/decrement the digit. Here's the code in jsfiddle: http://jsfiddle.net/uk5t3z4d/48/. However, I have two problems:
I cannot add digit using the number pad, the input always stays at X.XX
When I use another function I wrote (parseLocalFloat which is commented out), the output stops displaying anything, and I cannot use the left and right key to select the digit etc.
How can I overcome these two issues? Please shed a light on me, thanks!
HTML
<div class="display" id="out"></div>
<div class="form-group">
<label for="comment">value:</label>
<input class="form-control" type="text" value="0.00" id="in"></input>
</div>
JavaScript
function createSelection(field, start, end) {
if( field.createTextRange ) {
var selRange = field.createTextRange();
selRange.collapse(true);
selRange.moveStart('character', start);
selRange.moveEnd('character', end);
selRange.select();
} else if( field.setSelectionRange ) {
field.setSelectionRange(start, end);
} else if( field.selectionStart ) {
field.selectionStart = start;
field.selectionEnd = end;
}
}
function getLocalDecimalSeparator() {
var n = 1.1;
return n.toLocaleString().substring(1,2);
}
function parseLocalFloat(num) {
return +(num.replace(getLocalDecimalSeparator(), '.'));
}
var inputBox = document.getElementById('in');
//var inputBox = parseLocalFloat(document.getElementByID('in').value);
inputBox.onkeyup = function(){
document.getElementById('out').innerHTML = inputBox.value;
}
$('#in').on("keydown", function(e){
var gotCode = false;
var curPos = this.selectionStart;
var endPos = this.selectionEnd;
if(curPos !== endPos) {
createSelection(this, curPos, curPos+1);
}
// get the position
if(e.keyCode == 37){
curPos--;
gotCode=true;
}
if(e.keyCode == 39){
curPos++;
gotCode=true;
}
var before = $(this).val().substring(0,curPos);
var after = $(this).val().substring(curPos+1);
var cur = Number($(this).val().substring(curPos, curPos+1));
// avoid adding extra stuff
if(curPos < $(this).val().length) {
if(e.keyCode == 38) {
cur++;
if(cur > 9) cur = 0;
$(this).val(before + '' + cur + '' + after);
gotCode=true;
}
if(e.keyCode == 40) {
cur--;
if(cur < 0) cur = 9;
$(this).val(before + '' + cur + '' + after);
gotCode=true;
}
}
if(!gotCode) {
e.preventDefault();
return false;
}
var field = this;
window.setTimeout(function(){
createSelection(field, curPos, curPos+1);
}, 10);
});
as for the "get number keys to work":
as stated you need to add the keys you want to support:
if(e.keyCode >= 48 && e.keyCode <= 57) {
var num = e.keyCode - 48; // 0=48; 9=59
$(this).val(before + '' + num + '' + after);
gotCode = true;
e.preventDefault(); // otherwise a new number is added as well
}
(this needs to come before the if (!gotCode) ... )
as for the customFloat: the the response from Moishe
For #1:
if(!gotCode) {
e.preventDefault();
return false;
}
ensures that if gotCode is false the default event (which in this case is the default keydown event) will not occur.
gotCode only seems to be true if keyCode is equal to 37, 38, 39, or 40 (the arrow keys). You are essentially preventing the other keys (like number keys) from having any effect on the textBox.
You probably would like to enable the number keys (when shift or caps aren't on) and number pad keys.
Additionally, you may want to check that the cur is a number (and not .) before attempting to increment or decrement its value.
You could do:
var isNumberKey = (
( e.keyCode >= 48 //is more than or equal to 0 key
&& e.keyCode <= 57 //is less than or equal to 9 key
&& !e.shiftKey) //shift key or cap key not on
|| ( e.keyCode >= 96 //more than or equal to 0 key in number pad
&& e.keyCode <= 105)); //less than or equal to 9 key in number pad
if(!gotCode && !isNumberKey) { //not arrow key or number key
console.log(e);
e.preventDefault();
return false;
}
For #2:
var inputBox = parseLocalFloat(document.getElementByID('in').value);
is setting inputBox to whatever parseLocalFloat returns which happens to be a number.
This is problematic because you then attempt to attach a keyUp event to that number instead of the inputBox:
inputBox.onkeyup = function(){
document.getElementById('out').innerHTML = inputBox.value;
}
You may want to instead call parseLocalFloat on the number and set the out textBox's value to that:
var inputBox = document.getElementById('in');
inputBox.onkeyup = function(){
document.getElementById('out').innerHTML = parseLocalFloat(inputBox.value);
}
function createSelection(field, start, end) {
if( field.createTextRange ) {
var selRange = field.createTextRange();
selRange.collapse(true);
selRange.moveStart('character', start);
selRange.moveEnd('character', end);
selRange.select();
} else if( field.setSelectionRange ) {
field.setSelectionRange(start, end);
} else if( field.selectionStart ) {
field.selectionStart = start;
field.selectionEnd = end;
}
}
function getLocalDecimalSeparator() {
var n = 1.1;
return n.toLocaleString().substring(1,2);
}
function parseLocalFloat(num) {
return +(num.replace(getLocalDecimalSeparator(), '.'));
}
var inputBox = document.getElementById('in');
// var inputBox = parseLocalFloat(document.getElementByID('in').value);
inputBox.onkeyup = function(){
document.getElementById('out').innerHTML = parseLocalFloat(inputBox.value);
}
$('#in').on("keydown", function(e){
var gotCode = false;
var curPos = this.selectionStart;
var endPos = this.selectionEnd;
if(curPos !== endPos) {
createSelection(this, curPos, curPos+1);
}
// get the position
if(e.keyCode == 37){
curPos--;
gotCode=true;
}
if(e.keyCode == 39){
curPos++;
gotCode=true;
}
var $thisVal = $(this).val();
var before = $thisVal.substring(0,curPos);
var after = $thisVal.substring(curPos+1);
var cur = Number($thisVal.substring(curPos, curPos+1));
// avoid adding extra stuff
if(curPos < $thisVal.length && !isNaN(cur)) {
if(e.keyCode == 38) {
cur++;
if(cur > 9) cur = 0;
$(this).val(before + '' + cur + '' + after);
gotCode=true;
}
if(e.keyCode == 40) {
cur--;
if(cur < 0) cur = 9;
$(this).val(before + '' + cur + '' + after);
gotCode=true;
}
}
var isNumberKey = ((e.keyCode >= 48 && e.keyCode <= 57 && [16, 20].indexOf(e.keyCode) == -1 && !e.shiftKey) || (e.keyCode >= 96 && e.keyCode <= 105));
if(!gotCode && !isNumberKey) {
console.log(e);
e.preventDefault();
return false;
}
var field = this;
window.setTimeout(function(){
createSelection(field, curPos, curPos+1);
}, 10);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="display" id="out"></div>
<div class="form-group">
<label for="comment">value:</label>
<input class="form-control" type="text" value="0.00" id="in"></input>
</div>

Easy Smooth Scroll Plugin: How do I offset scroll?

I am using the Easy Smooth Scroll Plugin for Wordpress.
Below is the .js file that the plugin uses:
var ss = {
fixAllLinks: function() {
var allLinks = document.getElementsByTagName('a');
for (var i = 0; i < allLinks.length; i++) {
var lnk = allLinks[i];
if ((lnk.href && lnk.href.indexOf('#') != -1) && ((lnk.pathname == location.pathname) || ('/' + lnk.pathname == location.pathname)) && (lnk.search == location.search)) {
ss.addEvent(lnk, 'click', ss.smoothScroll);
}
}
},
smoothScroll: function(e) {
if (window.event) {
target = window.event.srcElement;
} else if (e) {
target = e.target;
} else return;
if (target.nodeName.toLowerCase() != 'a') {
target = target.parentNode;
}
if (target.nodeName.toLowerCase() != 'a') return;
anchor = target.hash.substr(1);
var allLinks = document.getElementsByTagName('a');
var destinationLink = null;
for (var i = 0; i < allLinks.length; i++) {
var lnk = allLinks[i];
if (lnk.name && (lnk.name == anchor)) {
destinationLink = lnk;
break;
}
}
if (!destinationLink) destinationLink = document.getElementById(anchor);
if (!destinationLink) return true;
var destx = destinationLink.offsetLeft;
var desty = destinationLink.offsetTop;
var thisNode = destinationLink;
while (thisNode.offsetParent && (thisNode.offsetParent != document.body)) {
thisNode = thisNode.offsetParent;
destx += thisNode.offsetLeft;
desty += thisNode.offsetTop;
}
clearInterval(ss.INTERVAL);
cypos = ss.getCurrentYPos();
ss_stepsize = parseInt((desty - cypos) / ss.STEPS);
ss.INTERVAL = setInterval('ss.scrollWindow(' + ss_stepsize + ',' + desty + ',"' + anchor + '")', 10);
if (window.event) {
window.event.cancelBubble = true;
window.event.returnValue = false;
}
if (e && e.preventDefault && e.stopPropagation) {
e.preventDefault();
e.stopPropagation();
}
},
scrollWindow: function(scramount, dest, anchor) {
wascypos = ss.getCurrentYPos();
isAbove = (wascypos < dest);
window.scrollTo(0, wascypos + scramount);
iscypos = ss.getCurrentYPos();
isAboveNow = (iscypos < dest);
if ((isAbove != isAboveNow) || (wascypos == iscypos)) {
window.scrollTo(0, dest);
clearInterval(ss.INTERVAL);
location.hash = anchor;
}
},
getCurrentYPos: function() {
if (document.body && document.body.scrollTop) return document.body.scrollTop;
if (document.documentElement && document.documentElement.scrollTop) return document.documentElement.scrollTop;
if (window.pageYOffset) return window.pageYOffset;
return 0;
},
addEvent: function(elm, evType, fn, useCapture) {
if (elm.addEventListener) {
elm.addEventListener(evType, fn, useCapture);
return true;
} else if (elm.attachEvent) {
var r = elm.attachEvent("on" + evType, fn);
return r;
} else {
alert("Handler could not be removed");
}
}
}
ss.STEPS = 25;
ss.addEvent(window, "load", ss.fixAllLinks);
The live page is here: http://iamjoepro.com/album/promaha/
I have the smooth scroll scrolling to an anchor, but I would like to offset it by the height of my fixed header (120px)
I am no javascript expert, I'm hoping this is easy for someone, but I can't decipher where to add the offset in my .js file?
I had a similar issue and found that the following solution worked for me.
Change the line:
var desty = destinationLink.offsetTop;
to read:
var desty = destinationLink.offsetTop - 120;
(where '120' is the height in pixels of your fixed header)
Then, remove the line:
location.hash = anchor;
(otherwise, the page will scroll to your 120px offset but then return back to the location of the anchor)
Hope this helps!

How to make this validation work on cloned inputs

I have this id validation field, i just need to know how i can make the validation and the keydown and keyup functions work on cloned inputs. also inserted data is carrying over to the duplicate fields.
js fiddle- http://www.jsfiddle.net/dawidvdh/xRh9v/
Heres the js:
$(document).ready(function() {
idAmount = [0,1,2,3,4,5,6,7,8,9,10,12,13];
var idinc =1;
var id_val;
jQuery(idAmount).each(function() {
var index = "id"+idinc++;
var id_input = "<input class='id' id="+'"'+index+'"'+" "+" maxlength='1' />";
id_val = $(this).attr('value');
jQuery(id_input).appendTo('#id');
});
$("#clone").click(function () {
var clonedObj=$('#id').clone().insertAfter("#id");
clonedObj.find('.id').each(function(){
this.id='id' + idinc++;
});
});
function Validate() {
jQuery('#error p').remove();
var id_val = '';
$('.id').each(function(){ id_val+=($(this).val());});
var idNumber = id_val;
console.log(id_val);
var correct = true;
if (idNumber.length != 13 || !isNumber(idNumber)) {
correct = false;
}
var tempDate = new Date(idNumber.substring(0, 2), idNumber.substring(2, 4) - 1, idNumber.substring(4, 6));
console.log(tempDate);
var id_date = tempDate.getDate();
var id_month = tempDate.getMonth();
var id_year = tempDate.getFullYear();
var currentYear = (new Date).getFullYear();
var age = currentYear - id_year;
var fullDate = id_date + "-" + (id_month + 1) + "-" + id_year;
if (!((tempDate.getYear() == idNumber.substring(0, 2)) && (id_month == idNumber.substring(2, 4) - 1) && (id_date == idNumber.substring(4, 6)))) {
correct = false;
}
// get the gender
var genderCode = idNumber.substring(6, 10);
var gender = parseInt(genderCode) < 5000 ? "Female" : "Male";
// get country ID for citzenship
var citzenship = parseInt(idNumber.substring(10, 11)) == 0 ? "Yes" : "No";
// apply Luhn formula for check-digits
var tempTotal = 0;
var checkSum = 0;
var multiplier = 1;
for (var i = 0; i < 13; ++i) {
tempTotal = parseInt(idNumber.charAt(i)) * multiplier;
if (tempTotal > 9) {
tempTotal = parseInt(tempTotal.toString().charAt(0)) + parseInt(tempTotal.toString().charAt(1));
}
checkSum = checkSum + tempTotal;
multiplier = (multiplier % 2 == 0) ? 1 : 2;
}
if ((checkSum % 10) != 0) {
correct = false;
};
// if no error found, hide the error message
if (correct) {
jQuery('.id').css("border","1px solid #9A8B7D");
// clear the result div
jQuery('#result').empty();
// and put together a result message
jQuery('#result').append('<p>South African ID Number: ' + idNumber + '</p><p>Birth Date: ' + fullDate + '</p><p>Gender: ' + gender + '</p><p>SA Citizen: ' + citzenship + '</p><p>AGE: ' + age + '</p>');
jQuery('#status').html("correct");
}
// otherwise, show the error
else {
jQuery('.id').css("border","1px solid #FF0000");
jQuery('#status').html("incorrect")
}
return false;
}
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
$('input.id').keydown(function(e){
if(e.keyCode == 8){
$(this).val('');
$(this).prev().val('');
$(this).prev().focus();
Validate()
}
});
$('input.id').on('keyup', function(){
if (this.value.match(/\d+/)) {
var $this = $(this);
if ($this.next('input').length) {
$this.next().focus();
} else {
Validate()
}
}
});
$(".id").keydown(function(event) {
// Allow: backspace, delete, tab, escape, and enter
if ( event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 || event.keyCode == 13 ||
// Allow: Ctrl+A
(event.keyCode == 65 && event.ctrlKey === true) ||
// Allow: home, end, left, right
(event.keyCode >= 35 && event.keyCode <= 39)) {
// let it happen, don't do anything
return;
}
else {
// Ensure that it is a number and stop the keypress
if (event.shiftKey || (event.keyCode < 48 || event.keyCode > 57) && (event.keyCode < 96 || event.keyCode > 105 )) {
event.preventDefault();
}
}
});
});
HTML:
<div id="id">
<span id="label">ID NUMBER:</span>
<span id="status"></span>
</div>
<button id="clone">clone</button>
<div id="result"> </div>
CSS:
#error {
color: red;
border: 1px solid red;
padding: 5px;
display: none;
}
#result {
padding: 20px;
}
.id {
width:16px;
height:16px;
border:1px solid #9A8B7D;
margin:0;
float:left;
text-align:center;
font-family:'itc_avant_garde_gothic_bookOb',Helvetica,sans-serif;
font-size:11pt;
padding:2px;
}
#label {
float:left;
font-family:'itc_avant_garde_gothic_bookOb',Helvetica,sans-serif;
line-height:18px;
font-size:11pt;
margin-right:10px;
}
The only time that I see you call Validate is here :
$('input.id').on('keyup', function(){
//code
});
and here
$('input.id').keydown(function(e){
//code
});
Which means that the issue is the event handler is not delegated to a static element
$(document).on('keyup', 'input.id', function(){
//code
});
$(document).on('keydown', 'input.id', function(){
//code
});
Binding it to the document will ensure that any dynamically created elements will have the same event delegated to them as any static elements of the same selector.
Forgot the last part.
clonedObj.find('.id').each(function(){
this.id='id' + idinc++;
this.value = ''; //simply add this to remove the value
});
Although, because you're using jQuery, you should try to stick to using jQuery.
clonedObj.find('.id').each(function(){
$(this).prop('id', 'id'+ idinc++).val(''); // chain the commands
});

How do you make up and down arrows highlight items in a list? (jQuery)

I have a stack of <DIV> siblings and I want to let the user use the up and down arrows to move up and down the list and "highlight" an item. Only one item should be highlighted at any given moment.
What's the easiest way to do this?
$(document).keyup(function(e) {
var $hlight = $('div.hlight'), $div = $('div');
if (e.keyCode == 40) {
$hlight.removeClass('hlight').next().addClass('hlight');
if ($hlight.next().length == 0) {
$div.eq(0).addClass('hlight')
}
} else if (e.keyCode === 38) {
$hlight.removeClass('hlight').prev().addClass('hlight');
if ($hlight.prev().length == 0) {
$div.eq(-1).addClass('hlight')
}
}
})
Check working example at http://jsfiddle.net/wMdML/8/
OK...
var highlight = function(upOrDown){
var highlighted = $("#daddyDiv > div.higlighted");
if(highlighted[0] == null){
//If nothing is highlighted, highlight the first child
$("#daddyDiv > div:first").addClass("highlighted");
} else {
//Highlight the next thing
if(upOrDown == "down" && highlighted.index() != $("#daddyDiv > div").length()){
$("#daddyDiv > div").eq(highlighted.index()+1).addClass("highlighted");
$("#daddyDiv > div.higlighted").removeClass("highlighted");
} else if(upOrDown == "up" && highlighted.index() != 1){
$("#daddyDiv > div").eq(highlighted.index()-1).addClass("highlighted");
$("#daddyDiv > div.higlighted").removeClass("highlighted");
}
}
};
//Assuming you are using up/down buttons...
$("#upButton").click(function(){ highlight("up"); });
$("#downButton").click(function(){ highlight("down"); });
//Using the arrow keys...
$("body").keyup(function(e){
if(e.keyCode == "40"){
//Down key
highlight("down");
} else if(e.keyCode == "38"){
//Up key
highlight("down");
}
});
I made this up: http://jsfiddle.net/JPy76/.
It basically removes a highlighted class when moving up/down and adds it to the next/previous. Some extra code is necessary for moving down after the last one / moving up after the first one.
$('body').keydown(function(e) {
if(e.keyCode === 40) {
if($('.highlighted').next().length) {
$('.highlighted').removeClass('highlighted')
.next().addClass('highlighted');
}
else {
$('.highlighted').removeClass('highlighted');
var d = $('div');
d.length = 1;
d.addClass('highlighted');
}
}
if(e.keyCode === 38) {
if($('.highlighted').prev().length) {
$('.highlighted').removeClass('highlighted')
.prev().addClass('highlighted');
}
else {
$('.highlighted').removeClass('highlighted');
var d = $('div');
d = $(d[d.length - 1]);
d.addClass('highlighted');
}
}
});
Here's one way to do it without using IDs or classes. A working jsfiddle example is available here (make sure to click on the Result pane first).
The javascript:
var $currentDiv = $("#myContainer").children().first();
$currentDiv.css("background", "red");
$("html").keyup( function(keyEvent) {
if (keyEvent.keyCode == 40 ) {
var $nextDiv;
if ($currentDiv.next().size() == 0) {
$nextDiv = $("#myContainer").children().first();
}
else {
$nextDiv = $currentDiv.next();
}
$currentDiv.css("background", "");
$nextDiv.css("background", "red");
console.log($nextDiv);
console.log($currentDiv);
$currentDiv = $nextDiv;
}
else if (keyEvent.keyCode == 38) {
var $previousDiv;
if ($currentDiv.prev().size() == 0)
$previousDiv = $("#myContainer").children().last();
else {
$previousDiv = $currentDiv.prev();
}
$currentDiv.css("background", "");
$previousDiv.css("background", "red");
$currentDiv = $previousDiv;
}
});
The html:
<div id="myContainer">
<div> Div 1 </div>
<div> Div 2 </div>
<div> Div 3 </div>
<div> Div 4 </div>
</div>

Categories

Resources