I have a table that calculates a total depending on the input the user types. My problem is that the jquery code is calculating each key stroke and not "grabbing" the entire number once you stop typing. Code is below, any help woud be greatly appreciated.
$(document).ready(function() {
$('input.refreshButton').bind('click', EstimateTotal);
$('input.seatNumber').bind('keypress', EstimateTotal);
$('input.seatNumber').bind('change', EstimateTotal);
});
//$('input[type=submit]').live('click', function() {
function EstimateTotal(event) {
var tierSelected = $(this).attr('data-year');
var numberSeats = Math.floor($('#numberSeats_' + tierSelected).val());
$('.alertbox_error_' + tierSelected).hide();
if (isNaN(numberSeats) || numberSeats == 0) {
$('.alertbox_error_' + tierSelected).show();
} else {
$('.alertbox_error_' + tierSelected).hide();
var seatHigh = 0;
var seatLow = 0;
var seatBase = 0;
var yearTotal = 0;
var totalsArray = [];
var currentYear = 0;
$('.tier_' + tierSelected).each(function() {
seatLow = $(this).attr('data-seat_low');
firstSeatLow = $(this).attr('data-first_seat_low');
seatHigh = $(this).attr('data-seat_high');
seatBase = $(this).attr('data-base_cost');
costPerSeat = $(this).attr('data-cost_per_seat');
years = $(this).attr('data-year');
seats = 0;
if (years != currentYear) {
if (currentYear > 0) {
totalsArray[currentYear] = yearTotal;
}
currentYear = years;
yearTotal = 0;
}
if (numberSeats >= seatHigh) {
seats = Math.floor(seatHigh - seatLow + 1);
} else if (numberSeats >= seatLow) {
seats = Math.floor(numberSeats - seatLow + 1);
}
if (seats < 0) {
seats = 0;
}
yearTotal += Math.floor(costPerSeat) * Math.floor(seats) * Math.floor(years) + Math.floor(seatBase);
});
totalsArray[currentYear] = yearTotal;
totalsArray.forEach(function(item, key) {
if (item > 1000000) {
$('.totalCost_' + tierSelected + '[data-year="' + key + '"]').append('Contact Us');
} else {
$('.totalCost_' + tierSelected + '[data-year="' + key + '"]').append('$' + item);
}
});
}
}
You'll need a setTimeout, and a way to kill/reset it on the keypress.
I'd personally do something like this:
var calc_delay;
$(document).ready(function() {
$('input.refreshButton').bind('click', runEstimateTotal);
$('input.seatNumber').bind('keypress', runEstimateTotal);
$('input.seatNumber').bind('change', runEstimateTotal);
});
function runEstimateTotal(){
clearTimeout(calc_delay);
calc_delay = setTimeout(function(){ EstimateTotal(); }, 100);
}
function EstimateTotal() {
....
What this does is prompt the system to calculate 100ms after every keypress - unless another event is detected (i.e. runEstimateTotal is called), in which case the delay countdown resets.
Related
I have coded the below piece of code which handle the number bigger than 999 and add a comma to it. For example 1,000 and 1,000,000. Wheare as once the number increase the comma will be placed in the correct position. I used DRY principle and I feel still there is another easy way to handle it.
Now, I want to know if there is much better way than that I did.
Waiting for your opinion.
Thanks.
function seperate_num_by_comma() {
var num = '199228754645.25',
withOutComma = num.split('.'),
addNewCommaAfter = 3,
x = withOutComma[0].length % addNewCommaAfter,
lenOfWithOutComma_0 = withOutComma[0].length,
length_1 = withOutComma[0].length - x,
starter = 0,
wholeNumber = ' ';
for (var i = 0; i < lenOfWithOutComma_0; i++) {
function run_first_func() {
wholeNumber += withOutComma[0].substr(starter, addNewCommaAfter);
};
function run_second_fun() {
wholeNumber += withOutComma[0].substr(starter, addNewCommaAfter) + ",";
starter += addNewCommaAfter;
length_1 -= addNewCommaAfter;
};
if (x > 0) {
if (length_1 == 0) {
run_first_func();
break;
} else if (wholeNumber == ' ') {
wholeNumber += withOutComma[0].substr(starter, x) + ",";
length_1 -= addNewCommaAfter;
starter = x;
} else {
run_second_fun();
}
} else if (x == 0) {
if (length_1 == 3) {
run_first_func();
break;
}
run_second_fun();
}
}
console.log(wholeNumber + '.' + withOutComma[1]);
}
seperate_num_by_comma();
One Line:
165B minified version (no IE): seperate_by_comma=t=>(x=(""+t).split("."),z=x[0].replace(/((\d{3})*?)(\.|$)/,"|$1").split("|"),x[0]=z[0]+z[1].replace(/(.{3})/g,",$1").slice(!z[0].length),x.join("."))
OR 180B, IE-friendly: seperate_by_comma=function(t){x=(""+t).split(".");z=x[0].replace(/((\d{3})*?)(\.|$)/,"|$1").split("|");x[0]=z[0]+z[1].replace(/(.{3})/g,",$1").slice(!z[0].length);return x.join(".")}
Explanation:
seperate_num_by_comma = function(number){//12345678.9
var str = String(t);
var withoutDot = str.split("."); //["12345678", "9"]
var chunksOfThree = withoutDot[0].replace(/((\d{3})*?)(\.|$)/,"|$1");//"12|345678"
chunksOfThree = chunksOfThree.split("|");//["12", "345678"]
chunksOfThree[1] = chunksOfThree[1].replace(/(.{3})/g,",$1") //",345,678"
if(chunksOfThree[0].length==0){
chunksOfThree[1] = chunksOfThree[1].slice(1); //Fix for specific cases
}
withoutDot[0] = chunksOfThree[0] /*"12"*/ + chunksOfThree[1] /*",345,678"*/
return withoutDot.join(".") //"12,345,678.9"
}
I have been developing a site that will provide schedules created by people. I'm using Alienware to develop it and the ajax code works perfectly on the laptop all of the time. I am using IE. However, if I access my site on my Samsung Smart TV or my HTC U11 phone, Ajax isn't consistent. It displays the data I am requesting, however, when I sum up a total of hours for the week, it sometimes displays the correct hours, or sometimes shows 0 hours, when the user is scheduled for the week. Why is it inconsistent between devices? I know that Ajax is recommended for IE. As I said, though, it sometimes will display the correct total weekly hours, and other times it will just show zero. This issue isn't occurring on my Alienware.
I've already tried using onload instead of onreadystatechange. I've set the request to asynchronous and synchronous. Whether it's set to true or false, on my other devices, it fails to be consistent. I've tried it as a post and get method, and both also are inconsistent. What is wrong with my code?
function getThisWeek(str5) {
lastDate = new Date(str5);
// getting dates for this week to be displayed...
this.math = dayInput.length - 1;
this.math0 = 0 - new Date(str5).getDay();
// getting week total hour length, to determine how many times this code executes...
weekSum = 0;
totals = [];
for (this.i = 0; this.i < weekTotalHours.length; this.i++) {
str3 = this.i;
this.date = new Date(str5);
for (this.ii = (this.i * (7)) - new Date().getDay(); this.ii < (7 * (this.i + 1)) - new Date().getDay(); this.ii++) {
totalHours = 0;
this.date = new Date(str5);
this.date = new Date(this.date.setDate(this.date.getDate() + (this.ii)));
// which element position the total daily hours belongs to when displaying them...
this.pos = this.ii + new Date().getDay();
thisDayChart[this.pos].innerHTML = "";
// displaying the date
dayInput[this.pos].innerHTML = this.date.getDate();
// highlighting today's date...
if (this.date.getDate() == new Date(str5).getDate() && this.date.getMonth() == new Date().getMonth()) {
dayInput[this.pos].style.color = "white";
dayInput[this.pos].style.backgroundColor = "silver";
dayInput[this.pos].style.borderRadius = "0px";
thisDay[this.pos].style.border = "2px double lightblue";
} else {
dayInput[this.pos].style.color = "";
dayInput[this.pos].style.backgroundColor = "";
dayInput[this.pos].style.borderRadius = "";
thisDay[this.pos].style.border = "";
}
// getting schedule from database...
this.xmlhttp = new XMLHttpRequest();
this.xmlhttp.pos = this.pos;
this.xmlhttp.ipos = this.i;
this.xmlhttp.d = months[this.date.getMonth()] + " " + this.date.getDate() + ", " + this.date.getFullYear();
this.xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
//alert(this.responseText);
dayInput[this.pos].m = months[new Date(this.d).getMonth()];
dayInput[this.pos].weekDay = days[new Date(this.d).getDay()];
// how many weeks in the year is user...
this.islpyr = new Date(this.d);
this.islpyr = this.islpyr.setMonth(1);
this.islpyr = new Date(new Date(this.islpyr).setDate(29));
if (this.islpyr.getMonth() == 2) {
mlens[1] = 28;
} else {
mlens[1] = 29;
}
// getting total amount of days for the year...
this.yrlen = 0;
for (this.iii = 0; this.iii < mlens.length; this.iii++) {
this.yrlen += mlens[this.iii];
}
// getting total weeks
this.wklen = this.yrlen / 7;
this.wklen = Math.round(this.wklen);
this.week = 0;
for (this.iii = 0; this.iii < new Date(this.d).getMonth(); this.iii++) {
this.week += mlens[this.iii];
}
this.week += new Date(this.d).getDate();
this.week /= 7;
this.week = Math.round(this.week) + 1;
// rounding and displaying current week number...
if (new Date(this.d).getDay() == 0) {
myDayWrapper[this.ipos].weekLabel = "Week " + this.week + " of " + this.wklen;
}
if (this.pos == 0) {
weekDisplay[0].innerHTML = myDayWrapper[0].weekLabel;
}
// which day of the year it is... how many days in the year is the user...
this.yrpos = 0;
for (this.iv = 0; this.iv < new Date(this.d).getMonth(); this.iv++) {
this.yrpos += mlens[this.iv];
}
this.yrpos += new Date(this.d).getDate();
thisDayTitle[this.pos].innerHTML = "Day " + this.yrpos + " of " + this.yrlen;
totalHours = 0;
this.schedule = "" + this.responseText;
// if user is unscheduled, do this first... 'undefined' literally means there isn't a schedule for that specific day.
if (this.schedule.search("Undefined") >= 0) {
this.elem = document.createElement("div");
this.elem.setAttribute("class","not_scheduled");
this.elem.innerHTML = "Unscheduled";
thisDayChart[this.pos].appendChild(this.elem);
this.elem = document.createElement("div");
this.elem.setAttribute("class","pick_up_shift_btn");
this.elem.innerHTML = "Claim Shifts";
this.elem.i = this.pos;
this.elem.ipos = this.ipos;
this.elem.onclick = function() {
popUpWrap[1].style.display = "block";
this.datesd = [];
for (this.i = this.ipos * 7; this.i < 7 * (this.ipos + 1); this.i++) {
this.datesd.push(dayInput[this.i].innerHTML);
}
for (this.i = 0; this.i < 7; this.i++) {
shiftClaimDate[this.i].innerHTML = this.datesd[this.i];
popUpShiftDay[this.i].innerHTML = dayInput[this.i].weekDay;
this.strrr = "" + dayInput[this.i].m;
this.strrr = this.strrr.substring(0,3);
shiftClaimMonth[this.i].innerHTML = this.strrr;
}
}
thisDayChart[this.pos].appendChild(this.elem);
if (totals.length - 1 == this.pos) {
} else {
totals.push(0);
}
} else {
// getting daily total...
this.schedule = this.schedule.split(",");
for (this.iii = 0; this.iii < this.schedule.length; this.iii++) {
this.str = "" + this.schedule[this.iii];
this.str = this.str.split("=");
this.dateString = "December 22, 1991";
switch (this.str[0]) {
case "shift_start":
this.start = new Date(this.dateString + " " + this.str[1]);
this.end = this.schedule[this.schedule.length - 1] + "";
this.end = this.end.split("=");
this.end = new Date(this.dateString + " " + this.end[1]);
this.hours = (this.end.getHours() - this.start.getHours()) * 60;
this.hours = this.hours - (this.start.getMinutes() + this.end.getMinutes());
this.hours /= 60;
totalHours += this.hours;
weekSum += totalHours;
break;
case "break_start":
this.start = new Date(this.dateString + " " + this.str[1]);
this.end = this.schedule[this.iii + 1] + "";
this.end = this.end.split("=");
this.end = new Date(this.dateString + " " + this.end[1]);
this.hours = (this.end.getHours() - this.start.getHours()) * 60;
this.hours = this.hours - (this.start.getMinutes() + this.end.getMinutes());
this.hours /= 60;
weekSum -= this.hours;
totalHours -= this.hours;
this.s = "s";
if (totalHours == 1) {
this.s = "";
}
thisDayChart[this.pos].innerHTML = totalHours + " hour" + this.s;
break;
}
}
}
weekTotalHours[this.ipos].innerHTML = "Week Total: " + weekSum;
//alert(weekSum);
// displaying hour totals...
if (new Date(this.d).getDay() == 6) {
weekSum = 0;
}
totalHours = 0;
}
}
this.xmlhttp.open("GET","/js/data/schedule.html?date="+ months[this.date.getMonth()] + " " + this.date.getDate() + ", " + this.date.getFullYear(),false);
this.xmlhttp.send();
}
}
}
I expect every device to be consistent with the hour total it should be displaying, on every device that Ajax should work on.
I have to show Array values in circle kind of shape and it has to be run in a loop forever. Things are working fine when you rotate circle counter clockwise. But it has a problem in when we move circle in opposite direction.
I have an active element on the wheel. So when you user clicks on any other slide then active it calculates the difference between clicked slide and active slide then add and remove items in wheel accordingly.
So basically it picks the value from Array. if you move circle clockwise it picks values from the back of the Array and if you move it counterclockwise it starts picking up values from next available. If 11 items are rendered in first-page load then it will start taking values from 12 no index.
The problem occurs when you click the item which has above position from the active element and then you again rotates it counterclockwise.
Let say you click item no. 8 then you click item no.7. In this case item, no.2 should have been added into the wheel.
Here is fiddle.
var numberOfElement = [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];
var initialRender = numberOfElement.slice(0, 11);
var startPoint = initialRender.length;
var endPoint = numberOfElement.length;
function generateHtml() {
var html = '';
initialRender.forEach(function(item, index) {
var angle = 18 * (index);
var className = angle === 90 ? 'active' : '';
html += '<div class="shapes ' + className + '" data-deg="' + angle + '" style="--deg:' + angle + 'deg;"> <span class="set-pos">' + (item) + '</span> <span> ' + angle + ' deg </span></div>';
})
document.querySelector('#dynamic-html').innerHTML = html;
}
generateHtml();
$('#dynamic-html').on('click', '.shapes', function() {
var deg = 90;
var activeDeg = $('.active').data('deg');
var needToremoveElement = activeDeg;
var selectedElement = $(this).data('deg');
var degrees = deg - selectedElement;
var diff = Math.abs((activeDeg - selectedElement) / 18);
$('.shapes').removeClass('active');
$(this).addClass('active');
var movementCloseWise = degrees > ($('.circle').data('deg') || 0);
$('.circle').removeData('deg');
$('.circle').css({
'transform': 'rotate(' + degrees + 'deg)'
}).attr('data-deg', degrees);
if (movementCloseWise) {
var itemLength = $('.shapes').length;
$('.shapes:gt(' + ((itemLength - 1) - diff) + ')').remove()
var newItems = generateItem(getItemsFromBack(diff), true);
newItems = $(newItems).get().reverse();
$('#dynamic-html').prepend(newItems)
startPoint -= diff;
} else {
var newItems = generateItem(getItemFromStart(diff), false)
$('#dynamic-html').append(newItems)
$('.shapes:lt(' + (diff) + ')').remove()
endPoint += diff;
}
})
function getItemsFromBack(length) {
var values = [];
endPoint = endPoint - length;
if (endPoint < 0) {
endPoint = numberOfElement.length - Math.abs(endPoint)
var otherVal = 0;
if (endPoint + length >= numberOfElement.length) {
otherVal = (endPoint + length) - numberOfElement.length;
values = numberOfElement.slice(endPoint, numberOfElement.length)
}
if (otherVal > 0) {
values = values.concat(numberOfElement.slice(0, otherVal))
}
} else {
values = numberOfElement.slice(endPoint, endPoint + length)
}
var valuesCount = values.length;
return values.reverse();
}
function getItemFromStart(length) {
var values = numberOfElement.slice(startPoint, startPoint + length);
var valueCount = values.length;
startPoint += valueCount;
if (valueCount < length) {
startPoint = 0;
return values.concat(getItemFromStart(length - valueCount));
} else if (startPoint >= numberOfElement.length) {
startPoint = 0;
}
return values;
}
function generateItem(items, isClockWise) {
var html = "",
lastItemAngle;
if (isClockWise) {
lastItemAngle = $('#dynamic-html .shapes:first').data('deg');
} else {
lastItemAngle = $('#dynamic-html .shapes:last').data('deg');
}
items.forEach(function(item, index) {
if (isClockWise) {
var angles = lastItemAngle - (18 * (index + 1))
} else {
var angles = lastItemAngle + (18 * (index + 1))
}
html += '<div class="shapes" data-deg="' + (angles) + '" style="--deg:' + angles + 'deg;"> <span class="set-pos">' + (item) + '</span> <span> ' + angles + ' deg </span></div>';
});
return html;
}
I think your problem is just your endPoint initialization value. In your code, you initialize it as var endPoint = numberOfElement.length; which is wrong( I think) and it should be initialized by 0; I changed it and it worked:
var numberOfElement = [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];
var initialRender = numberOfElement.slice(0,11);
var startPoint = initialRender.length;
var endPoint = 0; /* here is the change */
function generateHtml(){
var html ='';
initialRender.forEach(function(item,index){
var angle = 18 * (index);
var className = angle === 90? 'active':'';
html+='<div class="shapes '+className+'" data-deg="'+angle+'" style="--deg:'+angle+'deg;"> <span class="set-pos">'+(item)+'</span> <span> '+angle+' deg </span></div>';
})
document.querySelector('#dynamic-html').innerHTML= html;
}
generateHtml();
$('#dynamic-html').on('click','.shapes',function(){
var deg = 90;
var activeDeg = $('.active').data('deg');
var needToremoveElement = activeDeg;
var selectedElement = $(this).data('deg');
var degrees = deg - selectedElement;
var diff = Math.abs((activeDeg - selectedElement) / 18);
$('.shapes').removeClass('active');
$(this).addClass('active');
var movementCloseWise = degrees > ($('.circle').data('deg') || 0);
$('.circle').removeData('deg');
$('.circle').css({'transform' : 'rotate('+ degrees +'deg)'}).attr('data-deg',degrees);
if(movementCloseWise){
var itemLength = $('.shapes').length;
$('.shapes:gt('+((itemLength-1)-diff)+')').remove()
var newItems = generateItem(getItemsFromBack(diff), true);
newItems = $(newItems).get().reverse();
$('#dynamic-html').prepend(newItems)
startPoint -= diff;
}else{
var newItems = generateItem(getItemFromStart(diff), false)
$('#dynamic-html').append(newItems)
$('.shapes:lt('+(diff)+')').remove()
endPoint += diff;
}
})
function getItemsFromBack(length) {
var values = [];
endPoint = endPoint - length;
if (endPoint < 0) {
endPoint = numberOfElement.length - Math.abs(endPoint)
var otherVal = 0;
if (endPoint + length >= numberOfElement.length) {
otherVal = (endPoint + length) - numberOfElement.length;
values = numberOfElement.slice(endPoint, numberOfElement.length)
}
if (otherVal > 0) {
values = values.concat(numberOfElement.slice(0, otherVal))
}
} else {
values = numberOfElement.slice(endPoint, endPoint + length)
}
var valuesCount = values.length;
return values.reverse();
}
function getItemFromStart(length) {
var values = numberOfElement.slice(startPoint, startPoint + length);
var valueCount = values.length;
startPoint += valueCount;
if (valueCount < length) {
startPoint = 0;
return values.concat( getItemFromStart(length - valueCount) );
} else if (startPoint >= numberOfElement.length) {
startPoint = 0;
}
return values;
}
function generateItem (items, isClockWise){
var html = "", lastItemAngle;
if(isClockWise){
lastItemAngle = $('#dynamic-html .shapes:first').data('deg');
}
else{
lastItemAngle = $('#dynamic-html .shapes:last').data('deg');
}
items.forEach(function(item,index){
if(isClockWise){
var angles = lastItemAngle - (18 * (index +1))
}
else{
var angles = lastItemAngle + (18 * (index +1))
}
html+='<div class="shapes" data-deg="'+(angles)+'" style="--deg:'+angles+'deg;"> <span class="set-pos">'+(item)+'</span> <span> '+angles+' deg </span></div>';
});
return html;
}
.main{
display: flex;
justify-content: center;
align-items: center;
height: 500px;
}
.pos{
height:150px;
width:150px;
position: relative;
}
.circle{
background: red;
height:150px;
width:150px;
border-radius: 50%;
transition: transform 0.3s ease-in-out;
}
.shapes{
position: absolute;
top:calc(50% - 75px);
left:calc(50% - 10px);
width: 20px;
height: 150px;
transform: rotate(var(--deg)) translate(0, 160px);
background: green;
text-align: center;
}
.fake-overlay{
position: absolute;
width: 203%;
height: 320%;
background: #fff;
top: -160px;
right: -148%;
display: none
}
.active{
background: red
}
.set-pos{
position: absolute;
bottom: 0
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main">
<div class="pos">
<div class="circle">
<div id="dynamic-html"></div>
</div>
<div class="fake-overlay"></div>
</div>
</div>
And here is Jsfiddle
I have fixed this by the following code.
function getItemsFromBack(length) {
var values = [];
if (endPoint > numberOfElement.length) {
var diff = endPoint - numberOfElement.length;
values = numberOfElement.slice(diff - length, diff)
endPoint = endPoint - length;
return values.reverse();
}
endPoint = endPoint - length;
if (endPoint < 0) {
endPoint = numberOfElement.length - Math.abs(endPoint)
var otherVal = 0;
if (endPoint + length >= numberOfElement.length) {
otherVal = (endPoint + length) - numberOfElement.length;
values = numberOfElement.slice(endPoint, numberOfElement.length)
}
if (otherVal > 0) {
values = values.concat(numberOfElement.slice(0, otherVal))
}
} else {
values = numberOfElement.slice(endPoint, endPoint + length)
}
var valuesCount = values.length;
return values.reverse();
}
I am checking if endPoint is greater then total Array length. Then endPoint- Array.length and using diff to get the element
Your CSS is awesome, but your JavaScript still has a bug. Try this:
click 7, then click 2
To fix it, I propose we simplify your logic a bit:
give meaningful ids to items so we can easily select them, compare them and deduce the item angle
do not use hard coded arrays (if you did it because of a code quality tool like jslint, consider telling it to tolerate for loops)
The complexity of your code was coming from the management of start and end points within a range of 1-30. This is now made easy by 1st point above.
I have not changed your code too much so you can recognize your working parts easily:
// Global variables
var numberOfItems = 30,
numberOfRenderedItems = 11,
firstItem = 0
;
function generateHtml(){
var html ='';
for (var item = 0; item < numberOfRenderedItems; item++) {
var angle = 18 * item,
className = angle === 90? 'active':'';
html +=
'<div class="shapes '+className+'" data-item="'+item+'" data-deg="'+angle+'" style="--deg:'+angle+'deg;">'+
' <span class="set-pos">'+(item+1)+'</span>'+
' <span>'+angle+' deg </span>'+
'</div>';
}
document.querySelector('#dynamic-html').innerHTML= html;
}
generateHtml();
$('#dynamic-html').on('click','.shapes',function(){
// Set clicked item active
$('.shapes').removeClass('active');
$(this).addClass('active');
var selectedItem = Number($(this).data('item')),
previousActiveItem = firstItem + Math.floor(numberOfRenderedItems/2),
diff = selectedItem - previousActiveItem,
selectedAngle = selectedItem * 18,
degrees = 90 - selectedAngle,
isClockWise = diff < 0;
// Rotate all items
$('.circle').removeData('deg');
$('.circle').css({'transform' : 'rotate('+ degrees +'deg)'}).attr('data-deg',degrees);
var items;
if (isClockWise)
items = getItemsFromBack(diff);
else
items = getItemsFromFront(diff);
// Remove items
items.toRemove.forEach( function (item) {
$(".shapes[data-item="+item+"]").remove();
});
// Add items
var newItems = items.toAdd.reduce( function (html, item) {
// Get item number between 1 and max
var itemNumber = getNumberInRange(item),
angle = 18 * item;
return html +
'<div class="shapes" data-item="'+item+'" data-deg="'+angle+'" style="--deg:'+angle+'deg;">'+
' <span class="set-pos">'+itemNumber+'</span>'+
' <span>'+angle+' deg </span>'+
'</div>';
}, '');
if (isClockWise)
$('#dynamic-html').append(newItems);
else
$('#dynamic-html').prepend(newItems)
})
function getItemsFromBack (diff) {
var items = {
toAdd: [],
toRemove: []
};
firstItem += diff;
for (var i = 0; i < Math.abs(diff); i++) {
items.toAdd.push(firstItem + i);
items.toRemove.push(firstItem + i + numberOfRenderedItems);
}
return items;
}
function getItemsFromFront (diff) {
var items = {
toAdd: [],
toRemove: []
};
for (var i = 0; i < Math.abs(diff); i++) {
items.toAdd.push(firstItem + i + numberOfRenderedItems);
items.toRemove.push(firstItem + i);
}
firstItem += diff;
return items;
}
function getNumberInRange (item) {
do {
item = (item + numberOfItems) % numberOfItems;
}
while (item < 0);
return item + 1;
}
Updated JSFiddle link is below
https://jsfiddle.net/dpvjtvjd/2/
When I run this through command line, it goes for an hour or two, and then command line spits out "Memory Exhausted". I can't figure out what's going on.
Also, some general advice about how to make this more readable or modifiable, since I'll be passing the project off in a month.
var fs = require('fs');
var currentPhysician = [];
var physicianData = [];
var permitMax = 99999;
var alreadyParsed = [];
var targetFile = "CMQphysicians.csv";
var startTime = new Date().getTime();
var permitNumber = -1;
var firstLicense = 0;
var utils = require('utils');
String.prototype.contains = function (s) {
return (this.indexOf(s) != -1);
}
var casper = require('casper').create({
verbose : true,
logLevel : "info",
pageSettings : {
loadImages : false, // do not load images
loadPlugins : false // do not load NPAPI plugins (Flash, Silverlight, ...)
}
});
function getPermitNumberString() {
var pn = permitNumber.toString();
var l = pn.length;
var i;
var leadingZeros = '';
for (i = 0; i < (5 - pn.length); i++) {
leadingZeros = leadingZeros + '0';
}
return leadingZeros + pn;
}
function getDetailsData() {
var details = document.querySelectorAll('#content-html > table.griddetails > tbody > tr > td');
return Array.prototype.map.call(details, function (e) {
return e.innerText;
});
}
function getPhysicianCount() {
return document.querySelectorAll("#GViewList > tbody > tr:nth-child(2) > td:nth-child(1) > a").length;
}
casper.on("resource.error", function (resourceError) {
if (!resourceError.url.contains('google')) {
this.echo("Resource error: " + "Error code: " + resourceError.errorCode + " ErrorString: " + resourceError.errorString + " url: " + resourceError.url + " id: " + resourceError.id, "ERROR");
}
while (resourceError.errorString.contains('undefined')) {}
});
casper.on('load.started', function () {
//casper.echo('load started');
});
casper.on('navigation.requested', function (url, navigationType, navigationLocked, isMainFrame) {
//casper.echo('navigation requested');
//casper.echo(navigationType);
});
casper.on('remote.message', function (msg) {
this.echo('from within remote page DOM' + msg);
});
casper.start('https://www.google.ca/?gws_rd=ssl', function () { // Loads the initial page.
casper.echo('Starting!');
});
casper.on('load.finished', function (status) {
//casper.echo('load finished');
var date = new Date();
var hours = date.getHours();
var minutes = date.getMinutes();
//casper.echo(hours.toString() + ':' + minutes.toString() + ' ' + this.getCurrentUrl().toUpperCase());
var urlPrefix = this.getCurrentUrl().substring(0, this.getCurrentUrl().indexOf('.aspx'));
if (urlPrefix.length == 0) {
casper.echo('undefined');
urlPrefix = 'https://www.google.ca/?gws_rd=ssl'.toUpperCase();
}
switch (urlPrefix.toUpperCase()) {
case 'https://www.google.ca/?gws_rd=ssl'.toUpperCase():
casper.echo('on google');
if (fs.exists('CMQphysicians.csv')) {
stream = fs.open('CMQphysicians.csv', 'r');
line = stream.readLine();
var i = 0;
while (line) {
if (i > 0) {
alreadyParsed.push(Number(line.substring(0, line.indexOf(','))));
}
line = stream.readLine();
i++;
}
stream.close();
permitNumber = Math.max.apply(null, alreadyParsed) + 1;
firstLicense = permitNumber;
casper.echo(permitNumber);
} else {
fs.write(targetFile, "\uFEFF" + 'Permit Number,Last Name,First Name,Gender,Permit,Status,Specialty,Activity,Authorization,Address,Phone\n', 'a');
}
casper.thenOpen('http://www.cmq.org/bottin/index.aspx?lang=en&a=1');
break;
case 'http://www.cmq.org/bottin/index'.toUpperCase():
casper.waitForSelector('#___gcse_0 > div > form > table.gsc-search-box > tbody > tr > td.gsc-search-button > input', function() {
var finishedSoFar = permitNumber - firstLicense;
var timeSoFar = new Date().getTime() - startTime;
var licensesToDo = permitMax - permitNumber;
var msPerLicense = timeSoFar / finishedSoFar;
var minutesToGo = (licensesToDo * msPerLicense) / 1000 / 60;
//casper.echo(licensesToDo + ' licenses to go. ' + msPerLicense.toString() + 'ms per license. ' + minutesToGo.toString() + ' minutes remaining.');
casper.echo('index stage');
permitNumber++;
if (permitNumber > permitMax) {
casper.echo('Permit number maxed out');
} else {
var permitNumberString = getPermitNumberString();
casper.echo('going to list');
casper.sendKeys('#txbNoPermis', permitNumberString);
//casper.wait(100);
casper.echo('sent keys, now clicking');
casper.thenClick('#btSubmit');
casper.echo('after the click');
}
});
break;
case 'http://www.cmq.org/bottin/list'.toUpperCase():
casper.waitForSelector('#___gcse_0 > div > form > table.gsc-search-box > tbody > tr > td.gsc-search-button > input', function() {
casper.echo('list stage');
// Three cases:
// No results, one result, many results
// No results: go back (00000)
// One result: go forward (82365)
// Many results: crash (?????)
a = casper.evaluate(getPhysicianCount);
if (a == 0) {
casper.echo('No physicians for license ' + getPermitNumberString());
casper.echo('going to index');
casper.thenClick('#btSubmit');
//casper.wait(1000);
} else if (a == 1) {
casper.echo('Physician exists for license ' + getPermitNumberString());
casper.echo('going to details');
casper.thenClick('#GViewList > tbody > tr:nth-child(2) > td:nth-child(1) > a');
//casper.wait(1000);
} else if (a > 1) {
casper.echo('a > 1 at ') + getPermitNumberString();
while(true){}
} else {
casper.echo('negative a at ') + getPermitNumberString();
while(true){}
}
// No results
});
break;
case 'http://www.cmq.org/bottin/details'.toUpperCase():
casper.waitForSelector('#___gcse_0 > div > form > table.gsc-search-box > tbody > tr > td.gsc-search-button > input', function() {
casper.echo('details stage');
var name = casper.getHTML('#content-html > table.griddetails > tbody > tr:nth-child(1) > th').substring(0, casper.getHTML('#content-html > table.griddetails > tbody > tr:nth-child(1) > th').indexOf('(')).trim().split(',');
tableData = (casper.evaluate(getDetailsData));
currentPhysician.push(tableData[4]);
currentPhysician.push(name[0].trim());
currentPhysician.push(name[1].trim());
for (i = 2; i < tableData.length; i++) {
if (i % 2 == 0 && i != 4) {
currentPhysician.push(tableData[i]);
}
}
for (i = 0; i < currentPhysician.length; i++) {
currentPhysician[i] = currentPhysician[i].replace(/,/g, ';').replace(/\n/g, ';');
}
var physicianString = currentPhysician.join(',') + '\n';
casper.echo('writing to file!');
fs.write(targetFile, physicianString, 'a');
currentPhysician = [];
casper.echo(casper.exists('#btNewsearch'));
casper.echo('going to index');
casper.thenClick('#btNewsearch');
//casper.wait(1000);
});
break;
default:
casper.echo("Wrong URL!");
casper.back();
break;
}});
casper.run(function () {
casper.echo('ending!');
casper.echo(physicianData.length);
});
Due to a bug:
https://bugs.webkit.org/show_bug.cgi?id=154452
Resolved by turning off image loading.
EDIT: seems to still be a problem. My guess is that it's because casperjs is outdated, so I'm abandoning it and using python.
In my project, users can add timecode in and out points for their project, and the project automatically figures out the total duration of the timecode. But I want to add a function that will take all the available timecode durations, convert them to seconds, add them together, then convert the final number back to timecode and put it in a text input.
This is my code, but I keep getting syntax errors:
function timeToSeconds(t) {
var tc = t.split(':');
return parseInt(tc[0])*3600 + parseInt(tc[1])*60 + parseInt(tc[2]);
}
function tcDuration(tcin, tcout) {
function z(n){return (n<10?'0':'') + n;}
var duration = timeToSeconds(tcout) - timeToSeconds(tcin);
var hoursmins = Math.floor(duration / 60);
return z(Math.floor(hoursmins/60)) + ':' + z(hoursmins % 60) + ':' + z(duration % 60);
}
// Run this function every time a film_tc_out cell is changed
function film_tc_Duration() {
if (document.getElementById("film_tc_in").value == '') {var film_tc_in = '00:00:00';} else { var film_tc_in = document.getElementById("film_tc_in").value;}
if (document.getElementById("film_tc_out").value == '') {var film_tc_out = '00:00:00';} else { var film_tc_out = document.getElementById("film_tc_out").value;}
document.getElementById("film_tc_duration").value = tcDuration(film_tc_in, film_tc_out);
}
// Run this function every time a src_tc_out cell is changed
function src_tc_Duration() {
if (document.getElementById("src_tc_in").value == '') {var src_tc_in = '00:00:00';} else { var src_tc_in = document.getElementById("src_tc_in").value;}
if (document.getElementById("src_tc_out").value == '') {var src_tc_out = '00:00:00';} else { var src_tc_out = document.getElementById("src_tc_out").value;}
document.getElementById("src_tc_duration").value = tcDuration(src_tc_in, src_tc_out);
}
// Run this function every time a src_wd_out cell is changed
function src_wd_Duration() {
if (document.getElementById("src_wd_in").value == '') {var src_wd_in = '00:00:00';} else { var src_wd_in = document.getElementById("src_wd_in").value;}
if (document.getElementById("src_wd_out").value == '') {var src_wd_out = '00:00:00';} else { var src_wd_out = document.getElementById("src_wd_out").value;}
document.getElementById("src_wd_duration").value = tcDuration(src_wd_in, src_wd_out);
}
function total_tc_Duration() {
var val = document.getElementsByClassName('.asset_src_tc_duration');
var total_tc = 0;
var v;
for (var i = 0; i < val.length; i++) {
v = timeToSeconds(val[i]);
if (!isNaN(v)) total_tc += v;
}
return (total_tc);
}
function updateAssetTimecode() {
document.getElementById("timecode_total").value = total_tc_Duration();
}
Update: I've rewritten the For Loop to see if that helps - it currently gives me an answer now, although the answer is always "0". It's not spitting out any errors but it seems to think the variable val isn't a number?
Your tcDuration function won't work like you expect. You don't subtract the already calculated hours before doing the minutes calculation and the same with seconds.
function tcDuration(tcin, tcout) {
function z(n){return (n<10?'0':'') + n;}
var duration = timeToSeconds(tcout) - timeToSeconds(tcin);
var hoursmins = Math.floor(duration / 60);
return z(Math.floor(hoursmins / 60)) + ":" + z(hoursmins % 60) + ":" + z(duration % 60);
}