So I have this array:
Mike
Blue
Jakob
Red
Luis
Orange
executing with this JQuery code:
$.each( arr, function( index, value ){
$( ".div" ).append( "" + value + "" );
}
});
I would like the each loop to jump every second value. So that the loop would create something like:
Mike - Blue
Jakob - Red
Luis - Orange
Can anyone point me in the right direction?
Instead of using $.each, you can just use a normal for loop and increment by 2 instead of 1.
for(var i = 0; i < arr.length; i += 2){
$(".div").append(arr[i] + ' - ' + arr[i+1]);
}
You can use javascript's modulo (%) operator and jQuery's $.each's argument of index
$.each( arr, function( index, value ){
if (index%2 == 0) { //0, 2, 4 (mike, jacob, luis)
$( ".div" ).append( "" + value + "" );
}
});
Modulo gives the remainder when divided by the given number. For example, 6%2 does 6/2, then takes the remainder. Since 2 goes into six exactly 3 times, the modulo is 0, as there is no remainder.
Thus, any even number will return 0 from a modulo with 2. We can use this to check if the index is even (0, 2, 4, 6), which will be every other iteration
This should work
$.each( arr, function( index, value ){
var ival = index+1; // index always starts from 0 So we are adding 1 to start the counter from 1
if(ival%2 == 0){ // %2 is the modulus of 2, If the value is 0, The counter is now an even number, other wise its an odd number
$( ".div" ).append( " - " + value + "" );
}else{
$( ".div" ).append( "" + value + "" );
}
});
You could actually reverse your thinking, and append the result of a mapping
$( ".div" ).append(arr.map(function(x,i) {return i%2 ? x+' - '+arr[i-1] + '<br/>' : null}))
var arr = [
"Mike",
"Blue",
"Jakob",
"Red",
"Luis",
"Orange"
];
$( ".div" ).append(arr.map(function(x,i) { return i%2 ? x+' - '+arr[i-1] + '<br/>' : null }));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="div"></div>
Related
i would like to know if it's possible to do this in javascript or php or anything.
i want to make an invoice number that starts with 001000, now to get the next invoice number i need to increment it by adding 1, but when i tried to do it in php. it just converts it to a number, which is not good because i need the 00 prefix. and in javascript. it just add the 1 to the end.
i know it could be done using regex but i don't know how.
EDIT: here's the invoice sequence i want to achieve.
001000
001001
001002
and when it reached to 009999 it should be 010000
please help.
SOLVED:
i used str_pad as spencer said.
php
$last_invoice = Quote::all()->last()->invoice + 1; // to convert it to number.
str_pad( ($last_invoice, 6, '0', STR_PAD_LEFT); // fill 0 prefix.
You can store the invoice number as an actual number, not a string, in order to easily increment it. When you print the number for display, pass it with leading zeros.
You can use this logic
var currentNumber = "000100";
var nextNumber = "00" + String( Number( currentNumber ) + 1 ).slice( 0 , 6 );
console.log(nextNumber);
Convert this into a function
function nextInSequence( currentNumber )
{
return "00" + String( Number( currentNumber ) + 1 ).slice( 0 , 6 );
}
var currentNumber = "000100";
currentNumber = nextInSequence( currentNumber );
console.log( currentNumber )
currentNumber = nextInSequence( currentNumber );
console.log( currentNumber )
currentNumber = nextInSequence( currentNumber );
console.log( currentNumber )
i used str_pad as #spencermay said. php
$last_invoice = Quote::all()->last()->invoice + 1; // to convert it to number.
str_pad( ($last_invoice, 6, '0', STR_PAD_LEFT); // fill 0 prefix.
I im quite confused in the negation of the functionality of my function. The original function takes 9 elements starting at nth index and decrease their transform position.
function pushIt(max, target, index, count) {
if (count == max || count == img.children ) {
running = false;
return;
}
var tmp = target[index];
var matrix = window.getComputedStyle(tmp).getPropertyValue("transform");
var translate_left = matrix.split(",")[4];
var translate_top = matrix.split(",")[5].split(")")[0]-215;
tmp.style.transform = "translate3d(" + translate_left + "px," + translate_top + "px,0)";
setTimeout(function(){
pushIt( max, target, index + 1, count + 1 );
},50)
}
What i wanted to do is to negate its functionality , e.g it wont decrease but increase transform position of (nth * 3) - 1 element ( counting down 9 elements )
function pushItDOWN(max, target, index , count) {
if ( count == max || index < 0 ) {
running = false;
return;
}
console.log("down");
var tmp = target[index];
var matrix = window.getComputedStyle(tmp).getPropertyValue("transform");
var translate_left = matrix.split(",")[4];
var translate_top = matrix.split(",")[5].split(")")[0]+215;
tmp.style.transform = "translate3d(" + translate_left + "px," + translate_top + "px,0)";
setTimeout(function(){
pushItDOWN(max, target, index - 1, count + 1 );
},50)
}
}
What second function does is takes elements and set their transform to oblivion (e.g out of viewport) and somehow break the functionality of first function.
Did i overlook some key fact that is causing the problem , i seem to fail to find the root of the problem.
Live demo for better understanding
I'm not 100% sure, but most likely this is your error:
This will result in a string:
matrix.split(",")[5].split(")")[0]
Lets say it is "500", then
matrix.split(",")[5].split(")")[0] + 215
// equals
"500" + 215
// results in (because + is both used as string concatenation as addition)
"500215"
// - will work, because it only has one meaning
"500" - 215 // results in 285
Parse the value as an int (or float if necessary) before adding the 215:
parseInt(matrix.split(",")[5].split(")")[0]) + 215
I've rigged up a simple JS gallery to implement "deep linking" allowing a URL with a hash like #slide-3 to automatically load the gallery with the third slide active. There's an ad in the gallery every seventh slide. These ad slides aren't tracked so the hash becomes #slide-x followed by an image slide, i.e. #slide-7.]
I've created a helper function to convert the slide numbers from the hash into the 0-indexed slide number, taking into account these ads every seventh slide, but was curious if anyone could think of a more graceful way to calculate the proper index as my implementation looks way too complicated to my eye:
var slideNum = parseInt( window.location.hash.replace( '#slide-', '' ), 10 );
slideNum += Math.floor( ( slideNum + Math.floor( slideNum / 7 ) ) / 7 ) - 1;
return slideNum;
That works but having two floors seems like overkill. There must be a simpler way! I'm not sure of the algebraic rules that govern the floor operation however so I can't figure out how to expand/simplify myself. Any help would be appreciated.
I've included a basic JS fiddle which outputs values for the first 36 slides compared to their proper values. Feel free to change the testFunc with your solution and see if works!
var nums = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36];
var correct = [0,1,2,3,4,5,7,8,9,10,11,12,14,15,16,17,18,19,21,22,23,24,25,26,28,29,30,31,32,33,35,36,37,38,39,40];
var testFunc = function( n ) {
var offset = ( n + Math.floor( n / 7 ) ) / 7;
return n + Math.floor( offset ) - 1;
};
document.getElementById('text').innerHTML += 'Input Expected Output<br/>';
for( var i = 0; i < nums.length; i++ ) {
document.getElementById('text').innerHTML += nums[i] + ' ' + correct[i] + ' ' + testFunc( nums[i] ) + '<br/>';
if ( ( i + 1 ) % 6 === 0 ) {
document.getElementById('text').innerHTML += 'AD<br/>';
}
}
<div id="text"></div>
Yes, one integer division is enough:
var testFunc = function( n ) {
n = n - 1;
return Math.floor(n / 6) + n
};
Realized we have both indices on each slide element so I can simply select using the URL index and get the true slide index from the DOM. Still a fun problem to think about perhaps!?
I want to create a jQuery UI range slider where the set of values that the upper bound can be set to is different from the set of values that the lower bound can be set to. Essentially I want a slider where the range of possible values is [a, b] but the two handles "leapfrog" alternate values, so that the lower handle can only be set to the 1st, 3rd, 5th, etc., values in the range, and the upper handle can only be set to the 2nd, 4th, 6th, etc.
The simplest example would be: is it possible to create a range slider with values 1-10 where the lower handle can only be set to odd numbers and the upper handle can only be set to even numbers?
The use case is I have a slider for selecting time ranges in years. The lower bound should represent the beginning of a year and the upper bound the end of a year. So if you set lower bound to 2012 and upper bound also to 2012, this should mean "from beginning of 2012 to end of 2012".
I could make a slider with double the range and do some math to compute the underlying range (i.e., select 2012 for "beginning of 2012" and 2012.5 for "end of 2012" but hide this from the user), but the problem is that then the user could set the end to "beginning of 2012", which I don't want. The issue is that I actually want the visual UI to prevent the two handles from occupying the same positions, to prevent someone from choosing a range that is semantically invalid for my purposes.
I tried to get clever and use the "step" option while setting the initial upper/lower bounds to staggered values, but this doesn't work. It seems that the steps are not calculated relative to the current value, but rather the value is "snapped" to available step positions at each move. So if you have a 1-10 slider where the step size is 2 but the upper bound is set to 10, moving it down one will take it to 9, not 8. This is exactly what I don't want, because I want the two handles to have different, interleaved available values.
I'm open to solutions that use some widget set other than jQuery UI if that's easier, although I'd prefer a solution based on some reputable widget set. (That is, I'd rather have something that builds on existing range sliders, not a from-scratch implementation of a slider with this particular feature.)
You can cancel slide event by return false;.
See this link on jsfiddle.
function setValues(stepIncrease) {
return function (event, ui) {
var slider = $("#" + this.id);
var currentValues = slider.slider("values");
var step = slider.slider("option")["step"];
if ((Math.abs(ui.values[0] - currentValues[0]) % (stepIncrease * step) != 0 || Math.abs(ui.values[1] - currentValues[1]) % (stepIncrease * step) != 0)){
return false;
};
slider.slider("values", ui.values);
var currentValues = slider.slider("values");
$("#" + this.id + "-values").html(currentValues[0] + ' ' + currentValues[1]);
};
};
And in the slider:
$(function() {
$( "#slider-range-1-2" ).slider({
range: true,
min: 1,
max: 10,
step: 1,
values: [1, 10],
slide: setValues(2),
create: function(event, ui) {
var slider = $("#" + this.id);
var currentValues = slider.slider("values");
$("#" + this.id + "-values").html(currentValues[0] + ' ' + currentValues[1]);
}
});
});
UPD
This is function to handle keydown events
function eventHandlerKeydown(slider, stepIncrease) {
return function(event) {
var step, curVal, min, max, newVal, index = $( event.target ).data( "ui-slider-handle-index" );
switch (event.keyCode) {
case $.ui.keyCode.UP:
case $.ui.keyCode.RIGHT:
case $.ui.keyCode.DOWN:
case $.ui.keyCode.LEFT:
event.preventDefault();
if ( !slider.keySliding ) {
slider.keySliding = true;
$(event.target).addClass( "ui-state-active" );
}
break;
}
step = slider.slider("option")["step"];
max = slider.slider("option")["max"];
min = slider.slider("option")["min"];
curVal = slider.slider("values")[index];
switch ( event.keyCode ) {
case $.ui.keyCode.UP:
case $.ui.keyCode.RIGHT:
newVal = curVal + step * stepIncrease;
if ( newVal > max ) {
return;
}
slider.slider("values", index, newVal );
break;
case $.ui.keyCode.DOWN:
case $.ui.keyCode.LEFT:
newVal = curVal - step * stepIncrease;
if ( newVal < min ) {
return;
}
slider.slider("values", index, newVal );
break;
}
}
}
And in the slider:
$(function() {
var slider = $( "#slider-range" ).slider({
...
});
var handlers = slider.children("a");
$.each(handlers, function(index, handler) {
$(handler).off('keydown');
$(handler).on({keydown: eventHandlerKeydown(slider, 1)});
});
});
And the link to example.
P.S. I still think there is a easily solution for this.
If You want only choose beginning or end of the years I think #user568109 is right
function showValues(event, ui) {
var values;
if (!ui.values) {
values = $("#" + event.target.id).slider("values");
} else {
values = ui.values;
}
if (values[0] == values[1]) {
return false;
} else {
var periodFrom;
values[0] % 1 == 0 ? periodFrom = 'beginnig of the year' : periodFrom = 'year-end';
var periodTo;
values[1] % 1 == 0 ? periodTo = 'beginnig of the year' : periodTo = 'year-end';
$("#" + event.target.id + "-values").html('From ' + periodFrom + ' ' + parseInt(values[0]) + '<br />to ' + periodTo + ' ' + parseInt(values[1]));
}
}
$(function() {
$( "#slider" ).slider({
range: true,
min: 2010,
max: 2013.5,
step: 0.5,
values: [2010, 2013.5],
slide: showValues,
create: showValues,
change: showValues
});
});
Example there
I don't think the idea of having ranges different for upper and lower slider is totally sensible. You are confusing real numbers with date time ranges.
Number 2012 could mean start/end of the year but only for user. It should be clear in the code that it is either the start or the end. Usually it is the start of the year.
So 2012 - 2013 in actual real numbers would translate to beginning of 2012 to beginning of 2013. Or you could simply change the last term as beginning of x to end of x-1.
The only problem here is that you don't want the sliders to overlap. So just check for the values.
if (ui.values[ 1 ] === ui.values[ 0 ])
return false;
See the jsfiddle.
I am getting -1 from myarray.indexOf(element) even when element appears to be in myarray.
Here's some code snippets:
function createChangeRecord( old_array, new_array ) {
var nds = new_array.slice(0,new_array.length);
var el, idx;
if (...) {
...
} else if ( old_array.length==new_array.length ) {
for ( var i=0; i<old_array.length; i++ ) {
el = old_array[i];
idx = nds.indexOf(el);
if ( idx!=(-1) ) {
...
} else {
var a = "el: " + el + "; nds: " + nds + "; nds.indexOf(el): " + nds.indexOf(el);
alert( a );
...
}
}
...
}
...
}
The alert shows me that nds does indeed contain el but the alert should only fire when idx==-1, which should only be true when nds does not contain el.
I know I haven't given enough information to determine the specific issue in my case, but maybe someone can tell me some general reasons which might cause this behavior?
Responses to a similar question suggested using jQuery inArray() instead of indexOf, but I want to know why indexOf doesn't work. Others suggested that indexOf is for strings, not arrays, but that's not true from the online docs I can find.
Use
nds.indexOf(parseInt(el,10))
where nds is an array and el is a number (or supposed to be a number)
Edit:
From msdn:
JavaScript is a loosely typed language, which means you do not declare
the data types of variables explicitly. In many cases JavaScript
performs conversions automatically when they are needed. For example,
if you add a number to an item that consists of text (a string), the
number is converted to text.
And I guess such conversion was the reason of indexOf returning -1 because one of your array contained number and other contained string.
For example:
old_array = ["10", "20", "30"];
new_array = [10, 20, 30];
Below is my attempt to answer your questions:
Why indexOf() does not work?
It does work and I guess it worked in your case too.
It returned -1 when el string, e.g "100", was not found in an array of numbers, e.g. nds=[100,200] which is true. Because "100" string is not same as 100 number.
Does indexOf() work with strings, array, etc?
Yes, indexOf() works with array (of number, string, or any object), as well as with string. But you have to make sure to check with same types.
What does parseInt() do?
To avoid unintended comparison of a number with a string, we can use parseInt(), for example parseInt("123", 10) returns the number 123.
The second argument 10 is called radix. A number (from 2 to 36) that represents the numeral system to be used.
Summary:
> "javascript is awesome".indexOf('v')
2
> [10, 20, 30].indexOf("20")
-1
> [10, 20, 30].indexOf(20)
1
> [10, 20, 30].indexOf( parseInt("20", 10) )
1
> typeof (100)
number
> typeof ("100")
string
> typeof( parseInt( "100", 10))
number
> parseInt( "100", 10)
100
> parseInt("100", 2)
4
> parseInt(11.3, 10)
11
> parseInt(11.3, 2)
3
> [10.3, 11.3, 12.3, 11].indexOf( parseInt(11.3, 10) )
3
To see all of above in action:
check the below code snippet but be aware of alert(); and console.log(); when you run it.
function createChangeRecord( old_array, new_array ) {
var nds = new_array.slice( 0, new_array.length ); // this seems to be redundant
var el, idx, msg;
if ( old_array.length == new_array.length ) {
for ( var i=0; i<old_array.length; i++ ) {
el = old_array[i];
idx = nds.indexOf(el);
if ( idx != -1 ) {
msg = "Found: el: " + el + "; nds: " + nds + "; nds.indexOf(el): " + idx + "\n typeof el: " + (typeof el) + "; typepf nds[" + i + "]: " + (typeof nds[i]);
} else {
msg = "Not Found: el: " + el + "; nds: " + nds + "; nds.indexOf(el): " + idx + "\n typeof el: " + (typeof el) + "; typepf nds[" + i + "]: " + (typeof nds[i]);
}
console.log( msg );
alert( msg );
}
}
else {
var err = 'Array lengths are not same';
console.log( err );
alert( err );
}
}
// this will work
var old_array_g = [ 10, 20 ];
var new_array_g = [ 10, 20 ];
createChangeRecord( old_array_g, new_array_g );
// this will not work
var old_array_g = [ "10", "20" ];
var new_array_g = [ 10, 20 ];
createChangeRecord( old_array_g, new_array_g );
// Yes: indesOf works with strings too
var withStrings = "'javascript is awesome'.indexOf('v'): " + "javascript is awesome".indexOf('v');
console.log( withStrings );
alert( withStrings );
// parseInt() returns a number or say integer
var usingParse = "typeof(123): " + typeof( 123 ) + "; typeof( parseInt('123', 10) ): " + typeof ( parseInt('123', 10) ) + "; typeof ('123'): " + typeof('123');
console.log( usingParse );
alert( usingParse );
// parseInt() with base 2
var parseBase2 = "parseInt( '100', 2 ): " + parseInt('100', 2) + "; parseInt( '100' , 10): " + parseInt('100', 10);
console.log( parseBase2 );
alert( parseBase2 );
indexOf does work and does do what you say it does.
For example (to demonstrate from a console):
> a = [1,2,3,4,5,6,7,8];
[1, 2, 3, 4, 5, 6, 7, 8]
> b = a.slice(0,a.length);
[1, 2, 3, 4, 5, 6, 7, 8]
> b.indexOf(a[4])
4
If you're getting this error, it might mean you've mixed up source and destination (the array before the dot is the one being searched), or you have another subtle programming error (like you aren't comparing the array you think you're comparing).
When you use indexOf(value) on an Array, it returns you the index of the value in the array.
> var testArray = ["a","b","c"];
> testArray.indexOf(1)
-1
> testArray.indexOf("b")
1
> testArray.indexOf("c")
2
> testArray = [10,12,3];
> testArray.indexOf(12)
1
You should check what you get from el with a typeof(el)
Taking the top example:
where you have idx=nds.indexOf(el)
replace it with idx=nds.indexOf(''+el+'')
It solved a similar problem for me within the thing I'm working on, but I stumbled on it messing around looking for a solution.
Whether it's stable in all circumstances is something I can't answer.
If your search array contained numbers, and you want to search for items like 2 or "2"
nds = [1, 2, 3, 4, 5];
This works (Add plus)
nds.indexOf(+el)