Unable to get proper element count on drop - javascript

I have noticed at several attempts to get a count of dropped elements it always returns one less than the number found, but if I try the same command via Chromes console I get the propper response.
I assume the DOM is not updated when this script runs so I threw a timeout/try again mechanism but still with no avail. What am I missing?
Expected Result size = 10
Actual Result size = 9
Code
var asmCount = 0;
function storeValues(values, tryNumber){
var size = values.length,
tryNumber = (!isNaN(tryNumber)) ? tryNumber : 1
;
console.log('full boat:' + size + ', try #'+ tryNumber + ' ' + typeof(tryNumber));
if(tryNumber > 60){
console.log('too many tries');
return;
}
if(size < 10){
console.log('missing entries');
tryNumber = tryNumber + 1;
setTimeout(storeValues($('.asm-ranking .receiver .asm-value'), tryNumber) , 500);
} else if(size > 10){
console.log('too many entries, something broke');
} else {
console.log('just right, lets do this shit.');
//$.each(values, function(k,v){ console.log($(v).data('id'));});
}
}
$('.asm-ranking .receiver').droppable({
drop: function(event,ui){
var _self = this,
receiverCount = $('.asm-ranking .receiver li').length
;
//console.log('event',event);
//console.log('ui', ui);
asmCount++;
console.log(asmCount + ' / ' + receiverCount);
if(receiverCount == asmCount){
storeValues($('.asm-ranking .receiver .asm-value'), 1); // give DOM time to catch up, then store
}
}
});

for some reason when I wrapped my jQuery notation in with document ready
$(document).ready(function{ ... })
it works as expected.

Related

Cursor moves to the last character every time I try to edit the text in textbox

I have written a code so it can count the characters inside the text box. The countting is working as expected but the problem is every time i move the cursor any where in the text box to change a word or add a word as soon as i press the first character curor moves to the end of the text.
Could you please help me edit the code:
function GetCountSms() {
ConvertGreek();
CounterSmsLen = $('#SndSms_Message').val().length;
GetAlhpa($('#SndSms_Message').val());
var i = 0;
while (i < String(Two).length) {
var oldindex = -1;
while (String($('#SndSms_Message').val()).indexOf(String(String(Two).charAt(i)), oldindex) > -1) {
//if ( String($('#SndSms_Message').val()).indexOf(String(String(Two).charAt(i))) > -1){
CounterSmsLen += 1;
oldindex = String($('#SndSms_Message').val()).indexOf(String(String(Two).charAt(i)), oldindex) + 1;
console.log(i);
}
i++;
}
if ($('#SndSms_Message').val().length == 0)
CounterSmsLen = 0;
$('#SndSms_Count').html(' ' + CounterSmsLen + ' Characters' + UniCodestring + ' <br /> ' + Math.ceil(CounterSmsLen / Countsms) + ' Sms');
countsmsnumber=Math.ceil(CounterSmsLen / Countsms);
}
PS.
I have added few lines of codes into the above code (i have mention in the code which lines are new) and its working but the problem is the typing speed when i try to type something it takes more seconds to show than a normal typing. (its like when i stop typing computer still type for 3-4 seconds after i stop):
function GetCountSms() {
//NEW CODES PART 1
document.getElementById('SndSms_Message').addEventListener('input', function (e) {
var target = e.SndSms_Message,
position = SndSms_Message.selectionStart;
//End OF NEW CODE
ConvertGreek();
CounterSmsLen = $('#SndSms_Message').val().length;
GetAlhpa($('#SndSms_Message').val());
var i = 0;
while (i < String(Two).length) {
var oldindex = -1;
while (String($('#SndSms_Message').val()).indexOf(String(String(Two).charAt(i)), oldindex) > -1) {
//if ( String($('#SndSms_Message').val()).indexOf(String(String(Two).charAt(i))) > -1){
CounterSmsLen += 1;
oldindex = String($('#SndSms_Message').val()).indexOf(String(String(Two).charAt(i)), oldindex) + 1;
console.log(i);
}
i++;
}
// NEW CODE PART 2
SndSms_Message.selectionEnd = position; // Set the cursor back to the initial position.
});

how do I cycle through background images by clicking a button?

I want to preview some backgrounds by using a button to cycle through them, just not very good at the js. I have them named "1"-"13". I wanted to step through them. When I get to "13" I want it to set it back to "1" when "next" is clicked and when "prev" is clicked when it gets to "1" to set it to "13". This is what I've tried but I know my syntax is wrong for the js.
HTML
<button id="n" class="b">NEXT</button>
<button id="p" class="b">PREV</button>
CSS
body {
background:black;
}
.b {
background:black;
color:white;
}
JS
$(document).ready(function(){
var i = 1;
$("#n").click(function() {
alert(i);
i++;
$('body').css("background-image", "url(../images/bg/ " + i + " .png)");
if (i===14){i=1;};
});
$("#p").click(function() {
alert(i);
i--;
$('body').css("background-image", "url(../images/bg/ " + i + " .png)");
if (i===0){i=13;};
});
});
Still working on it but some help would be nice getting it done faster.
http://jsfiddle.net/80nz56wy/ I guess a jsfiddle won't help much if I'm using local content.
You should also try this. Here conditions are written before setting CSS, which will check first and then assign the image path.
$(document).ready(function() {
var i = 0;
$("#n").click(function() {
i++;
if (i > 13){ i = 1; };
$('body').css('background-image', 'url(images/bg/' + i + '.png)');
//if (i === 13){ i = 1; };
});
$("#p").click(function() {
i--;
if (i <= 0) { i = 13; };
$('body').css('background-image', 'url(images/bg/' + i + '.png)');
//if (i === 1) { i = 13; };
});
});
Other wise you may get wrong image paths, something like:
images/bg/0.png
or
images/bg/-1.png
Change Your javascript coding as below..
var i = 1;
$("#n").click(function() {
$('body').css("background-image", "bg" + i +".png");
i=i+1;
if (i==13){i=1};
});
$("#p").click(function() {
$('body').css("background-image", "bg" + i +".png");
i=i-1;
if (i==1){i=13};
});
Here it is, not sure what I changed the 20 times I edited the same line over and over but I must have gone full retard earlier.
$(document).ready(function(){
var i = 0;
$("#n").click(function() {
i++;
if ( i > 13 ){ i = 1; };
$('body').css('background-image', 'url(images/bg/' + i + '.png)');
});
$("#p").click(function() {
i--;
if ( i <= 0 ){ i = 13; };
$('body').css('background-image', 'url(images/bg/' + i + '.png)');
});
});

Text pagination inside a DIV with image

I want to paginate a text in some div so it will fit the allowed area
Logic is pretty simple:
1. split text into words
2. add word by word into and calculate element height
3. if we exceed the height - create next page
It works quite good
here is JS function i've used:
function paginate() {
var newPage = $('<pre class="text-page" />');
contentBox.empty().append(newPage);
var betterPageText='';
var pageNum = 0;
var isNewPage = false;
var lineHeight = parseInt(contentBox.css('line-height'), 10);
var wantedHeight = contentBox.height() - lineHeight;
for (var i = 0; i < words.length; i++) {
if (isNewPage) {
isNewPage = false;
} else {
betterPageText = betterPageText + ' ' + words[i];
}
newPage.text(betterPageText + ' ...');
if (newPage.height() >= wantedHeight) {
pageNum++;
if (pageNum > 0) {
betterPageText = betterPageText + ' ...';
}
newPage.text(betterPageText);
newPage.clone().insertBefore(newPage)
betterPageText = '...';
isNewPage = true;
} else {
newPage.text(betterPageText);
}
}
contentBox.craftyslide({ height: wantedHeight });
}
But when i add an image it break everything. In this case text overflows 'green' area.
Working fiddle: http://jsfiddle.net/74W4N/7/
Is there a better way to paginate the text and calculate element height?
Except the fact that there are many more variables to calculate,not just only the word width & height, but also new lines,margins paddings and how each browser outputs everything.
Then by adding an image (almost impossible if the image is higher or larger as the max width or height) if it's smaller it also has margins/paddings. and it could start at the end of a line and so break up everything again.basically only on the first page you could add an image simply by calculating it's width+margin and height+margin/lineheight. but that needs alot math to get the wanted result.
Said that i tried some time ago to write a similar script but stopped cause of to many problems and different browser results.
Now reading your question i came across something that i read some time ago:
-webkit-column-count
so i made a different approach of your function that leaves out all this calculations.
don't judge the code as i wrote it just now.(i tested on chrome, other browsers need different prefixes.)
var div=document.getElementsByTagName('div')[0].firstChild,
maxWidth=300,
maxHeigth=200,
div.style.width=maxWidth+'px';
currentHeight=div.offsetHeight;
columns=Math.ceil(currentHeight/maxHeigth);
div.style['-webkit-column-count']=columns;
div.style.width=(maxWidth*columns)+'px';
div.style['-webkit-transition']='all 700ms ease';
div.style['-webkit-column-gap']='0px';
//if you change the column-gap you need to
//add padding before calculating the normal div.
//also the line height should be an integer that
// is divisible of the max height
here is an Example
http://jsfiddle.net/HNF3d/10/
adding an image smaller than the max height & width in the first page would not mess up everything.
and it looks like it's supported by all modern browsers now.(with the correct prefixes)
In my experience, trying to calculate and reposition text in HTML is almost an exercise in futility. There are too many variations among browsers, operating systems, and font issues.
My suggestion would be to take advantage of the overflow CSS property. This, combined with using em sizing for heights, should allow you to define a div block that only shows a defined number of lines (regardless of the size and type of the font). Combine this with a bit of javascript to scroll the containing div element, and you have pagination.
I've hacked together a quick proof of concept in JSFiddle, which you can see here: http://jsfiddle.net/8CMzY/1/
It's missing a previous button and a way of showing the number of pages, but these should be very simple additions.
EDIT: I originally linked to the wrong version for the JSFiddle concept
Solved by using jQuery.clone() method and performing all calculations on hidden copy of original HTML element
function paginate() {
var section = $('.section');
var cloneSection = section.clone().insertAfter(section).css({ position: 'absolute', left: -9999, width: section.width(), zIndex: -999 });
cloneSection.css({ width: section.width() });
var descBox = cloneSection.find('.holder-description').css({ height: 'auto' });
var newPage = $('<pre class="text-page" />');
contentBox.empty();
descBox.empty();
var betterPageText = '';
var pageNum = 0;
var isNewPage = false;
var lineHeight = parseInt(contentBox.css('line-height'), 10);
var wantedHeight = contentBox.height() - lineHeight;
var oldText = '';
for (var i = 0; i < words.length; i++) {
if (isNewPage) {
isNewPage = false;
descBox.empty();
}
betterPageText = betterPageText + ' ' + words[i];
oldText = betterPageText;
descBox.text(betterPageText + ' ...');
if (descBox.height() >= wantedHeight) {
if (i != words.length - 1) {
pageNum++;
if (pageNum > 0) {
betterPageText = betterPageText + ' ...';
}
oldText += ' ... ';
}
newPage.text(oldText);
newPage.clone().appendTo(contentBox);
betterPageText = '... ';
isNewPage = true;
} else {
descBox.text(betterPageText);
if (i == words.length - 1) {
newPage.text(betterPageText).appendTo(contentBox);
}
}
}
if (pageNum > 0) {
contentBox.craftyslide({ height: wantedHeight });
}
cloneSection.remove();
}
live demo: http://jsfiddle.net/74W4N/19/
I actually came to an easier solution based on what #cocco has done, which also works in IE9.
For me it was important to keep the backward compatibility and the animation and so on was irrelevant so I stripped them down. You can see it here: http://jsfiddle.net/HNF3d/63/
heart of it is the fact that I dont limit height and present horizontal pagination as vertical.
var parentDiv = div = document.getElementsByTagName('div')[0];
var div = parentDiv.firstChild,
maxWidth = 300,
maxHeigth = 200,
t = function (e) {
div.style.webkitTransform = 'translate(0,-' + ((e.target.textContent * 1 - 1) * maxHeigth) + 'px)';
div.style["-ms-transform"] = 'translate(0,-' + ((e.target.textContent * 1 - 1) * maxHeigth) + 'px)';
};
div.style.width = maxWidth + 'px';
currentHeight = div.offsetHeight;
columns = Math.ceil(currentHeight / maxHeigth);
links = [];
while (columns--) {
links[columns] = '<span>' + (columns + 1) + '</span>';
}
var l = document.createElement('div');
l.innerHTML = links.join('');
l.onclick = t;
document.body.appendChild(l)

Recursive loop in javascript with increment based on a link click

I'm populating form fields and prompting the user through them using a javascript recursive loop.
I'm having a problem with the recursion not working as expected.
I have a recursive loop that prompts a user through 6 input fields.
field1 and field2 populate as expected, but field3 and field4 fire off together and field5 and field6 fire off together.
I think it has something to do with global vs. local variables or possibly scoping inside the loop() function, but I'm struggling with figuring it out.
JSFiddle: http://jsfiddle.net/9QtDw/5/
Click on the "Save Data" button to fire off the loop and you can see the loop() function iterate with confirm popups guiding the user.
Any help pointing me in the right direction is greatly appreciated.
var x = 0;
var fieldnames = ["field1", "field2", "field3", "field4", "field5", "field6"]
function loop(y) {
i = y;
if (i >= fieldnames.length) { // check to see if loop has run through the number of elements in the fieldnames array
return;
}
confirm( 'Highlight the ' + fieldnames[i] + ' text' );
console.log("outside on click function i=" + i);
//function to be called when button is clicked
$("#text-submit").on("click", function(){
//fieldinfo = $("#cs-ResultText").text();
$('#' + fieldnames[i] + '').val('this is where i = ' + i);
// increment i and recall the loop function for the next field
if(i >= fieldnames.length - 1 ){ return false; }
i=i+1;
console.log(i);
console.log("inside on click function i=" + i);
return loop(i); // the recusive call back into the loop
});
return false;
}
// only fire off the loop call on the first run through, after that it's called on #text-submit click
if( x === 0 ){
loop(x);
}
try this instead:
var x = 0;
var fieldnames = ["field1", "field2", "field3", "field4", "field5", "field6"]
function loop(y) {
i = y;
if (i >= fieldnames.length) { return; }
confirm( 'Highlight the ' + fieldnames[i] + ' text' );
$('#' + fieldnames[i] + '').val('this is where i = ' + i);
return false;
}
$("#text-submit").on("click", function(e){
e.preventDefault();
if(i >= fieldnames.length - 1 ){ return false; }
i=i+1;
loop(i);
});
if( x === 0 ){
loop(x);
}
working fiddle here: http://jsfiddle.net/9QtDw/6/
I hope it helps.
You are not looping!!!
ya just loop for 2 time
you should change your loop function like this:
function loop(y) {
i = y;
if (i >= fieldnames.length) { // check to see if loop has run through the number of elements in the fieldnames array
return;
else
$("#text-submit").trigger('click')
}

Javascript/jQuery - Timezone Change Script with Multiple Fields

I have written a javascript for changing the "timezone" of a field on my website using a dropdown select menu.
You can see the script here: http://jsfiddle.net/dTb76/14/
However, I have reached the limits of what I know how to do - I need the script to modify several "time" fields, however, at the moment it can only work with one field.
I've been trying to figure out what changes to make for days, however I have not been having much luck. Best I can tell, I need some kind of "foreach" statement, telling it to store the original time for each field and then modify it by whatever is selected in the select, however I am not sure how to implement that in jQuery/javascript.
Would appreciate help.
You just need to use $.each JQuery function:
$('#modTime').change(function() {
var times = $('.time');
$.each(times, function(index, value) {
var curTime = $(value).text();
curTimeHH = parseInt(curTime.split(':')[0],10);
$(value).attr('originalTime', curTime);
var modifyBy = parseInt($('#modTime').val(),10);
curTimeHH = parseInt(curTime,10) + modifyBy;
if (curTimeHH === 0) {
$(value).text('24:00');
} else if (curTimeHH > 24) {
curTimeHH = curTimeHH - 24;
$(value).text('0'+curTimeHH + ':00');
} else if (curTimeHH < 0) {
curTimeHH = curTimeHH + 24;
$(value).text(curTimeHH + ':00');
} else {
$(value).text(curTimeHH + ':00');
}
});
});​
Edit:
To retrieve the 'original time' of every field, you could do something like:
var times = $('.time');
$.each(times, function(index, value) {
var originalTime = $(value).attr('originalTime');
...
});
You'll want to use jQuery's each() method to iterate through each of your .time elements. This will allow you to grab the current time for each specific element and do your calculations on a per-element basis; otherwise, $('.time').text() and things like that will always return the value of the first element selected, which is what you're seeing.
This should get you started:
$('#modTime').change(
function(){
var modifyBy = parseInt($(this).val(),10); // Here, this refers to your select element, the element whose change event handler we're now in
$('.time').each(function(){ // each() iterates through each .time element found in the DOM individually; that's what you'd like to do
var $this = $(this), // Refers to the current .time element
curTime = $this.text(),
curTimeHH = parseInt(curTime.split(':')[0],10),
curTimeHH = parseInt(curTime,10) + modifyBy;
$this.attr('originalTime',curTime);
if (curTimeHH == 0) {
$this.text('24:00');
} else if (curTimeHH > 24) {
curTimeHH = curTimeHH - 24;
$this.text('0'+curTimeHH + ':00');
} else if (curTimeHH < 0) {
curTimeHH = curTimeHH + 24;
$this.text(curTimeHH + ':00');
} else {
$this.text(curTimeHH + ':00');
}
});
});

Categories