Keep an index within bounds and wrap around - javascript

I am doing a little carousel with a pager. The carousel displays elements 6 by 6 and I have 36 elements to display. I have a next and previous button. The first elements displayed are [0, 6]. If I press the previous button and there is no previous elements (eg I am on the first page), it should wrap around and go to the end. The same applies for the last elements and the next button.
My code looks like this:
$('#img_prev').click(function (e) {
# change this line so it wraps around
imgIndex = (imgIndex - 6) % 36;
alert(imgIndex)
refreshImages(imgIndex);
e.preventDefault();
return false;
});
$('#img_next').click(function (e) {
imgIndex = (imgIndex + 6) % 36;
refreshImages(imgIndex);
e.preventDefault();
return false;
});
And it fails miserably because -6 % 36 is -6 and not 30. I could handle it with if (index < 0) ... but I would prefer a condition with a modulo that best capture the wrapping behavior.
How can I get this to wrap around (see 2nd line) ?

One possible solution would be with this answer:
function mod(x, m) {
return (x%m + m)%m;
}
$('#img_prev').click(function (e) {
# this line has been changed, now it wraps around
imgIndex = mod(imgIndex - 6, 36);
...

You could try this:
var maxElements = 36;
$('#img_prev').click(function (e) {
// change this line so it wraps around
imgIndex = (maxElements - 1) - (imgIndex % maxElements);
alert(imgIndex)
refreshImages(imgIndex);
e.preventDefault();
return false;
});
$('#img_next').click(function (e) {
imgIndex = (imgIndex % maxElements);
refreshImages(imgIndex);
e.preventDefault();
return false;
});
Here's a fiddle showing the output of:
(imgIndex % maxElements)
and
(maxElements - 1) - (imgIndex % maxElements);

Related

Limit character length and add hyphen in javascript

Hello I am trying to make a code is entered and a - is added before the last two digits and is six characters long without the hyphen , the codes that I attach work, but separately, it doesn't matter if I try to join them to make it work or call them independent the result is always the same:
the code length is limited to 5, and the hyphen ends in the last character
how can I solve that?
function check(code) {
var r = code.value.replace('.', '');
vlr = r.replace('-', '');
body = r.slice(0, -2);
dv = vlr.slice(-2).toUpperCase();
code.value = body + '-' + dv
if ( body.length < 4 ||body.length > 6) {
patente.setCustomValidity("incorrect");
return false;
}
code.setCustomValidity('');
}
$(document).ready(function () {
var code = 6;
$('#code').keydown( function(e){
if ($(this).val().length >= code) {
$(this).val($(this).val().substr(0, code));
}
});
$('#code').keyup( function(e){
if ($(this).val().length >= code) {
$(this).val($(this).val().substr(0, code));
}
});
});

Use jquery to distribute array elements to list randomly

I have a simulator here that's working just fine, this simulator have 48 blocks (DIV elements), i'm using Math.floor((Math.random() * 48) + 1) to randomly attach the results on each block. The problem is that they're too close on the final simulation (see image below):
Is there a jquery / javascript function where i can return the array items from the simulation odd/even? Like, it will add each block like: 1,3,5,7,9 then 2,4,6,8.
My code looks like this right now:
if(adicionados.length < 48)
{
while(i<=eE && adicionados.length < 48)
{
sol = Math.floor((Math.random() * 48) + 1);
if(adicionados.length == 0 || adicionados.indexOf(sol) == -1)
{
adicionados.push(sol);
//console.log(adicionados);
$("#base"+sol).attr("src", foto);
$("#base"+sol).attr("data-i", $(this).parent().parent().find('.relacionados-img').attr('data-cor'));
i++;
}
}
Thanks!
You can use just two for loop because you have fixed row and col number and you are trying to draw a fixed pattern.
for(var i=1;i<=8;i++)
{
for(var j=1;j<=6;j++)
{
var sol=(i*6)+j;//if you are naming the boxes from left to right.
if(i%2==1)
{
if(j%2==1)
{
//your code to draw those boxes.
}
}
else
{
if(j%==0)
{
//your code to draw those boxes.
}
}
}
}

Trigger Alert When Slider Moves Left A Certain Amount

So, I am going to actually kill two birds with one stone. First off, I am trying to trigger an alert once the slider moves left to a specific degree. For example, once it goes to, let’s say, the 3rd slide I would like for it to trigger an alert. Also, I need help with the cycling of the slider. I want the slider to cycle like a rotation (360), but instead at the end of the cycle it slides all the way back to the start. View the Codepen to have a better understanding of what I mean. Thank you for your time. Your help is much appreciated.
Live Codepen
var W = $('#image_rotator').width(),
N = $('#slider .slide').length,
C = 0,
intv;
if (N <= 1) $('#left, #right').hide();
$('#slider').width(W * N);
$('#left, #right').click(function() {
C = (this.id == 'right' ? ++C : --C) < 0 ? N - 1 : C % N;
$('#slider').stop().animate({
left: -C * W
}, 300);
});
function setResetInterval(e) {
var intv = $("#slider");
if (e) {
timer = setInterval(function() {
$('#right').click();
}, 1000);
} else {
clearInterval(timer);
}
$('#slider').click(function() {
var x = $('#slider').offset();
alert("Top: " + x.top + " Left: " + x.left);
});
}
$("#btn").click(function(e) {
e.preventDefault();
setResetInterval(true);
});
$("#btn2").click(function(e) {
e.preventDefault();
setResetInterval(false);
});
$('#slider').hover(function(e) {
return e.type == 'mouseenter' ? setResetInterval(false) : setResetInterval(true);
});
This accomplishes both of the things that you wanted using the optional callback parameter in the animate function. It checks first to see if the variable C (the 0-based index of the current slide) is equal to 2 (3 in 1-based indexing), and shows an alert if it is. Then it checks to see if C is equal to 10 (which would mean that the slide currently being shown is the 9th one; The 9th image is just a duplicate of the 1st one) If it is on the 9th one, then jump back to the first one and trigger $("#right").click();.
$('#left, #right').click(function() {
C = (this.id == 'right' ? ++C : --C) < 0 ? N - 1 : C % N;
$('#slider').stop().animate({
left: -C * W
}, 300, function() {
if (C == 2){alert("3rd");}
if (C == 10) {
$('#slider').css("left", "0");
$('#right').click();
}
});
});
JSFiddle (Because CodePen's layout is weird to me)

javascript variable > than number

What I am tying to find is:
"if div contains '(a number greater than 1600 x a number greater than 1063)' alert success else alert error"
if (($('div:contains("(/*number greater than 1600*/ x /*number greater than 1063*/)")').length > 0)) {
alert("SUCCESS");
}
else {
alert("ERROR");
}
I thought I could use variables like
var w > 1600
var h > 1063
and then put them in like:
$('div:contains("('+ w + 'x' + h + ')")')
but that doesn't seem to work
Any ideas?
If your goal is to find all matching divs, you have to do a bit more work. Not a lot, but a bit:
var w = 1600;
var h = 1063;
// Find all divs and filter them
var matchingDivs = $("div").filter(function() {
// Does this div's text match the form (1601 x 1064)?
// If so, grab the numbers.
var match = /^\((\d+) x (\d+)\)$/.exec($(this).text());
if (match) {
// Yes, it does, do the numbers fit?
if (parseInt(match[1], 10) > w && // [1] = the first capture group
parseInt(match[2], 10) > h) { // [2] = the second capture group
// Keep this div
return true;
}
}
// Don't keep this div
return false;
});
If a div contains a number and nothing else, you can get it like this:
var num = Number($("#myDiv").text());
Or you can use the somewhat terser unary plus:
var num = +($("#myDiv").text());

Javascript conditional find/replace

For my javascript project, I have a list that looks like this:
<li id="1">101.33, "book name 1"</li>
<li id="2">600.01, book name 2</li>
<li id="3">001.11, book name 3</li>
etc...
Of which I am supposed to do the following:
Remap the bullet list entries to a new (consistent) tag type (your choice – make it look pretty!).
For entries between 100 and 200, add 100 to the Dewey decimal number.
For entries between 400 and 500, add 200 to the Dewey decimal number.
Entries between 850 and 900 need to have 100 removed from the Dewey decimal number.
Entries between 600 and 650 need to have 17 added to the Dewey decimal number
For items that get changed, append “changed” to the record.
For items that do not get changed, append “no change” to the record.
For records that are incorrect, append “invalid record” to the record
But I'm not sure how to go about it. I want to target any number in the body, or within a list item. Right now I have this:
var z = document.body.li.innerHTML;
if (z >+ 100 && z <= 200)
{
var q = z + 100;
document.body.li.innerHTML=q;
}
}
Can anyone point me in the right direction of the best approach to do this in javascript? Should I be using find/replace instead?
EDIT: Attempted to amend the last ternary if else statement in David Thomas' code. Can't seem to get it to work:
//define valid record number as at-least-one-integer.at-least-one-integer
var reggie = /\d+(.)+d/
if (_newText = reggie) {
'Invalid Record';
}
else if (_newText === a[textProp]) {
'no change';
}
else(_newText != a[textProp]) {
'changed';
}
+ ')';
One approach, is the following (using plain JavaScript, albeit you'll need to use an up-to-date browser):
// first, we need to get all the 'li' items:
var lis = document.querySelectorAll('ul > li'),
// find the relevant text-property for this browser:
textProp = 'textContent' in document ? 'textContent' : 'innerText',
// empty string variable to allow assessment of changes:
_newText = '';
// Remap the bullet list entries to a new (consistent) tag type (your choice – make it look pretty!).
// do this one yourself.
// a function to zero-pad the numbers (I believe a requirement of Dewey Decimal):
function leftPadNumber(num, numLength, padChar) {
var nString = num.toString(),
major = parseInt(num, 10),
minor = parseFloat(nString.substring(nString.indexOf('.'))),
diff = numLength - major.toString().length;
if (diff > 0) {
return new Array(diff + 1).join(padChar || 0) + (major + minor);
} else {
return num;
}
}
// For entries between 100 and 200, add 100 to the Dewey decimal number.
// For entries between 400 and 500, add 200 to the Dewey decimal number.
// Entries between 850 and 900 need to have 100 removed from the Dewey decimal number.
// Entries between 600 and 650 need to have 17 added to the Dewey decimal number
// note that I've taken a very literal interpretation of 'between' (amend if necessary):
function amendedDeweyDecimal(num) {
if (num > 100 && num < 200) {
num += 100;
} else if (num > 400 && num < 500) {
num += 200;
} else if (num > 850 && num < 900) {
num -= 100;
} else if (num > 600 && num < 650) {
num += 17;
}
// happens if num falls somewhere outside of the above constraints:
return num;
}
// iterates over each element in the 'lis' nodeList/collection:
[].forEach.call(lis, function (a) {
/* replaces the found numbers ('m') in the string, using the two
functions, above, and assigns those to the _newText variable:
_newText = a[textProp].replace(/(\d{3}\.\d{2})/, function (m) {
return leftPadNumber(amendedDeweyDecimal(parseFloat(m)).toFixed(2), 3);
});
// For items that get changed, append “changed” to the record.
// For items that do not get changed, append “no change” to the record.
// returns the original text to the element, along with '(no change)'
// (if 'a[textProp]' is exactly equal to '_newText') or with '(changed)'
// (if the two variables are not identical):
a[textProp] = _newText + ' (' + (_newText === a[textProp] ? 'no change' : 'changed') + ')';
});
// For records that are incorrect, append “invalid record” to the record
// I have absolutely no idea how to assess an 'incorrect' record.
JS Fiddle demo.
References:
Array.prototype.forEach().
document.querySelectorAll().
Number.toFixed().
Number.toString().
String.parseFloat().
String.parseInt().
String.replace().
try jQuery .each
$('li').each(function(index, value) {
var val = $(this).text().split(','); //split into array
if (index >= 100 && index < 200) {
//do stuff
}
if (index >= 400 && index < 500) {
//do stuff
}
//etc
});
Regardless if you want to solve this using pure JavaScript or a helper library (like jQuery for example), i would suggest to disassemble your problem into smaller tasks and solve them one by one. At the end they will fit one into another and will build the complete solution. I would have started with three simple functions (reading your description they will be needed often):
the ability to list all LI elements separately
extract the number from the LI content
check if the number in in a given range
The code can look like this:
// count of all LI items
var elements = 0;
// fetch LI item one at a time
var element = document.getElementById(elements+1);
while (element != undefined) {
// get the number
var number = Number(getNumber(element.innerHTML));
// do something with number and or LI element
if (inRange(number, 100, 200)) { /* add 100 ...*/ } // and so on
// go to next element
elements++;
element = document.getElementById(elements+1);
}
function getNumber(elementContent) {
return elementContent.split(",")[0]; // TODO error handling
}
function inRange(number, min, max) {
return (number >= min) && (number <= max);
}
You can introduce simple objects and arrays to store information and states to track the changes of your content.

Categories