JavaScript undefined function external JavaScript file - javascript

I have loaded an external JavaScript file, and placed functions within it, but when running the functions, it says "undefined function", but when I place the functions within the index file, it works perfectly.
To debug this, I wrote alert('entered'); when entering the document, and reading content when running and document is ready. Both are executed.
The error U get with this is:
Uncaught ReferenceError: countdown is not defined
Uncaught ReferenceError: keepalive is not defined
How can I fix this?
Source:
// JavaScript Document
alert('entered js.js');
$(document).ready(function() {
alert('reading content');
function countdown() {
var ele = document.getElementsByClassName('countdown');
for (var i = 0; i < ele.length; ++i) {
var v = Math.floor(ele[i].getAttribute('ctime')) - 1;
if (v < 0) {
v = 0;
}
ele[i].setAttribute('ctime', v);
if (v > 86399) {
var sl = v;
d = parseInt(sl / 86400);
sl = sl % 86400;
h = parseInt(sl / 3600);
sl = sl % 3600;
m = parseInt(sl / 60);
s = parseInt(sl % 60);
var str = d + 'd ' + h + 't ' + m + 'm ' + s + 's';
} else if (v > 3599) {
var h = Math.floor(v / 60 / 60);
var m = Math.floor((v - (h * 3600)) / 60);
var s = v - (m * 60) - (h * 3600);
var str = h + 't ' + m + 'm ' + s + 's';
} else if (v > 59) {
var m = Math.floor(v / 60);
var s = v - (m * 60);
var str = m + 'm ' + s + 's';
} else if (v > 0) {
var str = v + 's';
} else {
var str = ele[i].getAttribute('ctext') || '0s';
}
if (v == 0) {
var act = ele[i].getAttribute('caction');
if (act != '') {
setTimeout(function() {
url(act);
}, 1000);
}
}
ele[i].innerHTML = str;
}
setTimeout('countdown()', 1000);
}
$( ".specialpost tr" ).click(function(e) {
var form = $(this).parents('form').attr('id');
var submitformId = $(this).data("submitid");
console.log(form);
console.log(submitformId);
$("#submitvalue").val(submitformId);
$( "#" + form ).submit();
});
(function ($) {
$.fn.countTo = function (options) {
options = options || {};
return $(this).each(function () {
// set options for current element
var settings = $.extend({}, $.fn.countTo.defaults, {
from: $(this).data('from'),
to: $(this).data('to'),
speed: $(this).data('speed'),
refreshInterval: $(this).data('refresh-interval'),
decimals: $(this).data('decimals')
}, options);
// how many times to update the value, and how much to increment the value on each update
var loops = Math.ceil(settings.speed / settings.refreshInterval),
increment = (settings.to - settings.from) / loops;
// references & variables that will change with each update
var self = this,
$self = $(this),
loopCount = 0,
value = settings.from,
data = $self.data('countTo') || {};
$self.data('countTo', data);
// if an existing interval can be found, clear it first
if (data.interval) {
clearInterval(data.interval);
}
data.interval = setInterval(updateTimer, settings.refreshInterval);
// initialize the element with the starting value
render(value);
function updateTimer() {
value += increment;
loopCount++;
render(value);
if (typeof(settings.onUpdate) == 'function') {
settings.onUpdate.call(self, value);
}
if (loopCount >= loops) {
// remove the interval
$self.removeData('countTo');
clearInterval(data.interval);
value = settings.to;
if (typeof(settings.onComplete) == 'function') {
settings.onComplete.call(self, value);
}
}
}
function render(value) {
var formattedValue = settings.formatter.call(self, value, settings);
$self.text(formattedValue);
}
});
};
$.fn.countTo.defaults = {
from: 0, // the number the element should start at
to: 0, // the number the element should end at
speed: 1000, // how long it should take to count between the target numbers
refreshInterval: 100, // how often the element should be updated
decimals: 0, // the number of decimal places to show
formatter: formatter, // handler for formatting the value before rendering
onUpdate: null, // callback method for every time the element is updated
onComplete: null // callback method for when the element finishes updating
};
function formatter(value, settings) {
return value.toFixed(settings.decimals);
}
}(jQuery));
function keepalive() {
$.ajax({
url : "http://www.smackface.net/check_user",
type : "POST",
dataType : 'json',
data : {
method : 'checkAlerts'
},
success : function(data, textStatus, XMLHttpRequest) {
var response = data;
if (!(response.login)) {
alert('You are now logging out');
} else {
if (response.messages > 0) {
$('#message_count').show().text(response.messages);
if ($('#message_count').text() != response.messages) {
$("#playsoundappend").html("<audio id=\"playsound\"><source src=\"http://soundbible.com/grab.php?id=1645&type=mp3\" type=\"audio/mpeg\"><source src=\"http://soundbible.com/grab.php?id=1645&type=mp3\" type=\"audio/mpeg\"></audio>");
document.getElementById('playsound').play();
$('title').text(response.notifications + " messages");
}
}
else {
$('#message_count').hide();
}
if (response.notifications > 0) {
$('#notification_count').show().text(response.notifications);
if ($('#notification_count').text() != response.notifications) {
$("#playsoundappend").html("<audio id=\"playsound\"><source src=\"http://soundbible.com/grab.php?id=1645&type=mp3\" type=\"audio/mpeg\"><source src=\"http://soundbible.com/grab.php?id=1645&type=mp3\" type=\"audio/mpeg\"></audio>");
document.getElementById('playsound').play();
$('title').text(response.notifications + " notifications");
}
}
else {
$('#notification_count').hide();
}
}
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
console.log(XMLHttpRequest.responseText);
}
});
setTimeout('keepalive()', 10000);
}
$("#notificationLink").click(function()
{
$("#notificationContainer").fadeToggle(300);
$("#notification_count").fadeOut("slow");
$.ajax({
url : "http://www.smackface.net/check_user",
type : "POST",
dataType : 'json',
data : {
method : 'loadNotifications'
},
success : function(data, textStatus, XMLHttpRequest) {
var tpl = $("#notes").html();
var notification = Handlebars.compile(tpl);
$("#notificationsBody").html('');
$("#notificationsBody").append(notification(data));
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
console.log(XMLHttpRequest.responseText);
}
});
return false;
});
$(document).click(function()
{
$("#notification_count").hide();
});
$("#notification_count").click(function()
{
return false;
});
keepalive();
countdown();
});

you can pass the function itself to setTimeout:
setTimeout(countdown, 1000);
setTimeout(keepAlive, 1000);
The way you wrote it, it will have to be 'eval'ed out of scope of $(document).ready(... . When you pass the function itself as the first argument, it is in scope.

Related

Trying to display and update map markers using Leaflet JS

I'm trying to display countdown timers until each of my markers disappear on my map. The markers disappear when their respective timers run out, but the timers themselves are not displaying below the markers themselves as they should. I checked the Developer Console and noticed there are a couple errors:
Uncaught TypeError: Cannot read property 'innerHTML' of null
Uncaught ReferenceError: component is not defined
This error count keeps increasing until it stops at a high number. I'm guessing this is when the particular timer runs out because after that number stops climbing the same error is logged again and the number starts from 1 and continues to climb.
L.HtmlIcon = L.Icon.extend({options: {},
initialize: function(options) {
L.Util.setOptions(this, options);
},
createIcon: function() {
//console.log("Adding pokemon");
var div = document.createElement('div');
div.innerHTML =
'<div class="displaypokemon" data-pokeid="' + this.options.pokemonid + '">' +
'<div class="pokeimg">' +
'<img src="data:image/png;base64,' + pokemonPNG[this.options.pokemonid] + '" />' +
'</div>' +
'<div class="remainingtext" data-expire="' + this.options.expire + '"></div>' +
'</div>';
return div;
},
createShadow: function() {
return null;
}
});
var map;
function deleteDespawnedPokemon() {
var j;
for (j in shownMarker) {
var active = shownMarker[j].active;
var expire = shownMarker[j].expire;
var now = Date.now();
if (active == true && expire <= now) {
map.removeLayer(shownMarker[j].marker);
shownMarker[j].active = false;
}
}
}
function createPokeIcon(pokemonid, timestamp) {
return new L.HtmlIcon({
pokemonid: pokemonid,
expire: timestamp,
});
}
function addPokemonToMap(spawn) {
var j;
var toAdd = true;
if (spawn.expiration_timestamp_ms <= 0){
spawn.expiration_timestamp_ms = Date.now() + 930000;
}
for (j in shownMarker) {
if (shownMarker[j].id == spawn.encounter_id) {
toAdd = false;
break
}
}
if (toAdd) {
var cp = new L.LatLng(spawn.latitude, spawn.longitude);
var pokeid = PokemonIdList[spawn.pokemon_id];
var pokeMarker = new L.marker(cp, {
icon: createPokeIcon(pokeid, spawn.expiration_timestamp_ms)
});
shownMarker.push({
marker: pokeMarker,
expire: spawn.expiration_timestamp_ms,
id: spawn.encounter_id,
active: true
});
map.addLayer(pokeMarker);
pokeMarker.setLatLng(cp);
}
}
//TODO:<--Timer Functions-->//
function calculateRemainingTime(element) {
var $element = $(element);
var ts = ($element.data("expire") / 1000 | 0) - (Date.now() / 1000 | 0);
var minutes = component(ts, 60) % 60,
seconds = component(ts, 1) % 60;
if (seconds < 10)
seconds = '0' + seconds;
$element.html(minutes + ":" + seconds);
}
function updateTime() {
deleteDespawnedPokemon();
$(".remainingtext, .remainingtext-tooltip").each(function() {
calculateRemainingTime(this);
});
}
setInterval(updateTime, 1000);
//<--End of timer functions-->//
Here is my JSFiddle for a full view of the situation.
Any idea what I'm doing wrong?
SolutionThanks to user T Kambi for pointing out the issue!
I forgot to include the component() function.
function component(x, v) {
return Math.floor(x / v);
}
After including this all works as intended.

Ajax call doesn't work after success

I have a problem with ajax call after success.
I am trying to call my following javascript codes:
function imgResize($, sr) {
var debounce = function(func, threshold, execAsap) {
var timeout;
return function debounced() {
var obj = this,
args = arguments;
function delayed() {
if (!execAsap)
func.apply(obj, args);
timeout = null;
};
if (timeout)
clearTimeout(timeout);
else if (execAsap)
func.apply(obj, args);
timeout = setTimeout(delayed, threshold || 100);
};
}
// smartresize
jQuery.fn[sr] = function(fn) {
return fn ? this.bind('resize', debounce(fn)) : this.trigger(sr);
};
};
//CALL ON PAGE LOAD OR ANY TIME YOU WANT TO USE IT
imgResize(jQuery, 'smartresize');
/* Wait for DOM to be ready */
// Detect resize event
$(window).smartresize(function() {
// Set photo image size
$('.photo-row').each(function() {
var $pi = $(this).find('.photo-item'),
cWidth = $(this).parent('.photo').width();
// Generate array containing all image aspect ratios
var ratios = $pi.map(function() {
return $(this).find('img').data('org-width') / $(this).find('img').data('org-height');
}).get();
// Get sum of widths
var sumRatios = 0,
sumMargins = 0,
minRatio = Math.min.apply(Math, ratios);
for (var i = 0; i < $pi.length; i++) {
sumRatios += ratios[i] / minRatio;
};
$pi.each(function() {
sumMargins += parseInt($(this).css('margin-left')) + parseInt($(this).css('margin-right'));
});
// Calculate dimensions
$pi.each(function(i) {
var minWidth = (cWidth - sumMargins) / sumRatios;
$(this).find('img')
.height(Math.floor(minWidth / minRatio))
.width(Math.floor(minWidth / minRatio) * ratios[i]);
});
});
});
/* Wait for images to be loaded */
$(window).load(function() {
$(".photo").each(function() {
var imgGrab = $(this).find('.photo-item');
var imgLength = imgGrab.length;
for (i = 0; i < imgLength; i = i + 3) {
imgGrab.eq(i + 1)
.add(imgGrab.eq(i + 1))
.add(imgGrab.eq(i + 2))
.wrapAll('<div class="photo-row"></div>');
}
$(this).find(".photo-item").each(function() {
if ($(this).parent().is(":not(.photo-row)")) {
$(this).wrap('<div class="photo-row"></div>');
}
});
// Store original image dimensions
$(this).find('.photo-item img').each(function() {
$(this)
.data('org-width', $(this)[0].naturalWidth)
.data('org-height', $(this)[0].naturalHeight);
});
});
$(window).resize();
});
And here is my ajax code for LOAD MORE POST
$('body').on("click",'.morep', function(event) {
event.preventDefault();
var ID = $(this).attr("id");
var P_ID = $(this).attr("rel");
var URL = $.base_url + 'more_post.php';
var dataString = "lastpid=" + ID + "&post_id=" + P_ID;
if (ID) {
$.ajax({
type: "POST",
url: URL,
data: dataString,
cache: false,
beforeSend: function() {
$("#more" + ID).html('<img src="loaders/ajaxloader.gif" />');
},
success: function(html) {
$("div.post-content").append(html);
$("#more" + ID).remove();
imgResize(jQuery, 'smartresize');
}
});
} else {
$("#more").html('FINISHED');
}
return false;
});
The ajax should call imgResize(jQuery, 'smartresize'); but it is not working. What I am missing here anyone can help me here ?

how to make synchronous call to json data from angularjs

I am calling some data from a JSON file in AngularJS but due to the asynchronous call the code is moving to other step before receiving the data so that is causing an error.
I used $http.get
$http.get('job.json').success(function (response) {
$scope.big = response;
});
Can you suggest some synchronous method to call json data which is
{
"days": [{
"dayname": "Sun,23 Aug 2015",
"date": "2015-08-23",
"hours": "hoursArray(array24)"
}, {
"dayname": "Mon,24 Aug 2015",
"date": "2015-08-24",
"hours": "hoursArray(array24)"
}, {
"dayname": "Tue,25 Aug 2015",
"date": "2015-08-25",
"hours":"hoursArray(array24)"
}, {
"dayname": "Wed,26 Aug 2015",
"date": "2015-08-26",
"hours": "hoursArray(array24)"
}]
}
this is the jquery file i am using
(function($) {
$.fn.schedule = function(options) {
var methods = {
init : function(ele, opt) {
//methods.currentdate = methods.now.getFullYear() + "Engine Change" + methods.now.getMonth() + "Engine Change" + methods.now.getDate();
methods.currentdate = methods.now.getFullYear() + "-" + methods.now.getMonth() + "-" + methods.now.getDate();
// $("#scheduleAllDays > *").each(function(){
// var item = $(this);
// $("#scheduleAllDays").width($("#scheduleAllDays").width()+item.width());
// });
// $("#scheduleAllDays").width($("#scheduleAllDays").width());
ele.find("[data-row]").each(function() {
var drow = $(this), drowset = $("[data-row='" + drow.data("row") + "']");
var maxheight = methods.elesMaxHeight(drowset);
drowset.height(maxheight);
});
methods.allocateDurations(ele);
$("#scheduleContentInner", ele).css("min-height", $(".schedule-drag-wrap", ele).innerHeight());
},
elesMaxHeight : function(ele) {
var heights = $(ele).map(function() {
return $(this).height();
}).get();
return Math.max.apply(null, heights);
},
allocateDurations : function(ele) {
methods.flightdata = {
routes : {}
};
ele.find("[data-flight-row]").each(function(i, ival) {
var flight = $(this);
methods.flightdata.routes["row" + i] = [];
flight.find("[data-flight-record]").each(function() {
var currentFlight = $(this), flightrecord = methods.makeStringToObject(currentFlight.data("flight-record"));
flightrecord.element = currentFlight;
methods.flightdata.routes["row" + i].push(flightrecord);
});
});
methods.positionSet(ele);
},
positionSet : function(ele) {
var dayelement = $("#scheduleAllDays > *", ele);
var totaldaywidth = $("#scheduleAllDays").width() + 30;
var totaldays = dayelement.size();
var totalSeconds = (((totaldays * 24) * 60) * 60);
var perSecondsWidth = Number(totaldaywidth / totalSeconds);
var divider = $(".schedule-h-divider");
dayelement.each(function(i, ival) {
var dayele = $(this), dividerele = divider.eq(i);
dividerele.css({
top : $("#scheduleAllDays").height(),
left : dayele.offset().left - 104
});
});
for (var i in methods.flightdata.routes) {
var iobj = methods.flightdata.routes[i];
for (var j in iobj) {
var jobj = iobj[j];
var duration = jobj.duration, width = Number(methods.hmtosec(duration, ".") * perSecondsWidth);
var parent = jobj.element.parent();
jobj.element.css({
// position : "relative",
width : width + "px",
overflow : "hidden",
"white-space" : "nowrap"
}).parent().css({
// width : width+"px",
// overflow : "hidden"
// position:"absolute",
left : (j==0)?0:parent.prev().position().left+parent.prev().width()
});
}
}
methods.dragInit(ele);
},
setCurrentTimeMarker : function(ele) {
var marker = $(".schedule-current-time-marker");
var markerpills = $(".schedule-time-marker-pills");
var dayelement = $("#scheduleAllDays > *", ele);
var totaldaywidth = $("#scheduleAllDays").width() + 30;
var totaldays = dayelement.size();
var totalSeconds = (((totaldays * 24) * 60) * 60);
var perSecondsWidth = Number(totaldaywidth / totalSeconds);
var currentdate = new Date();
var format = currentdate.getFullYear() + "Engine Change" + currentdate.getMonth() + "Engine Change" + currentdate.getDate();
var currentdateele = $("#scheduleAllDays").find("[data-date='" + format + "']");
var days = (currentdateele.index()), seconds = ((days * 24) * 60) * 60;
seconds = seconds + methods.hmtosec(currentdate.getHours() + "." + currentdate.getMinutes(), ".");
marker.stop().animate({
top : $("#scheduleAllDays",ele).height()-53,
left : (seconds * perSecondsWidth) - (marker.width() / 2)
}, 1000, "swing");
markerpills.html(currentdate.getHours() + ":" + currentdate.getMinutes());
methods.markermove = setInterval(function() {
currentdate = new Date();
marker.css({
left : marker.position().left + perSecondsWidth
}, "fast", "swing");
markerpills.html(methods.makezerodigit(currentdate.getHours()) + " : " + methods.makezerodigit(currentdate.getMinutes()));
// methods.schedulemove(ele,perSecondsWidth);
}, 1000);
},
schedulemove : function(ele,seconds) {
var dragwrap = ele.find(".schedule-drag-wrap");
var routewidth = $(".schedule-route:eq(0)").width() + $(".schedule-route:eq(1)").width();
var maxleft = -(dragwrap.width() - ($(window).width() - routewidth));
if (Math.abs(dragwrap.position().left) < Math.abs(maxleft)) {
dragwrap.css({
left : (dragwrap.position().left - (dragwrap.width)) + "px"
});
}
},
makezerodigit : function(digit) {
return (String(digit).match(/^[0-9]$/)) ? "0" + digit : digit;
},
dragInit : function(ele) {
var currentdaycol = $("[data-date='" + methods.currentdate + "']");
ele.find(".schedule-drag-wrap").css({
left : -(currentdaycol.position().left - 50) + "px"
}).animate({
left : -currentdaycol.position().left - 0 + "px"
}, 1000, "swing", function() {
methods.drag(ele);
methods.setCurrentTimeMarker(ele);
});
},
drag : function(ele) {
methods.move = null;
$(".schedule-drag-wrap", ele).on("mousedown", function(e) {
var dragele = $(this), position = dragele.position();
methods.move = {
x : e.pageX,
y : e.pageY,
left : position.left
};
}).on("mouseup mouseleave", function(e) {
var dragele = $(this);
if (methods.move) {
methods.move = null;
dragele.removeClass("userselect-none cursor-move");
}
}).on("mousemove", function(e) {
var dragele = $(this), position = dragele.position(), movedx, drag = true;
if (methods.move) {
methods.curmove = {
x : e.pageX,
y : e.pageY
};
var routewidth = $(".schedule-route:eq(0)").width() + $(".schedule-route:eq(1)").width();
var maxleft = -(dragele.width() - ($(window).width() - routewidth));
var xcondition = (methods.move.x > methods.curmove.x);
dragele.addClass("userselect-none cursor-move");
if (position.left <= maxleft && xcondition) {
drag = false;
dragele.css({
left : maxleft
});
}
if (position.left > -10 && !xcondition) {
drag = false;
dragele.css({
left : 0
});
}
if (drag) {
//if direction right to left
movedx = methods.move.left + (methods.curmove.x - methods.move.x);
dragele.css({
left : movedx
});
}
}
});
},
now : new Date(),
currentdate : "",
hmtosec : function(hours, identy) {
var s = (hours.match(/\./)) ? hours.split(identy) : [hours, 0], h = s[0], m = s[1];
h = (Number(h)) ? (h * 60) * 60 : 0;
m = (m == 0) ? 0 : m * 60;
return Number(h + m);
},
makeStringToObject : function(string) {
var loc_string = String(string).split("|");
var output = {};
for (var i in loc_string) {
var keyvalue = loc_string[i].split("~");
output[keyvalue[0]] = keyvalue[1];
}
return output;
}
};
return this.each(function() {
methods.init($(this), $.extend({}, $.fn.schedule.setting, options));
});
};
$.fn.schedule.setting = {};
})(jQuery);
and this is the error i am getting
Uncaught TypeError: Cannot read property 'left' of undefined
In service: var deferred = $q.defer();
$http.get('job.json')
.success(function(response) {
defer.resolve(response);
}).error(function(error){
console.log(error);
})
return deferred.promise;
In controller:
var p=<serviceCall>
p.then(function(s){
$scope.ans=s;
})
The $q is used for getting synchronous response.for more details:https://docs.angularjs.org/api/ng/service/$q
You can't do a synchronous HTTP request, since the reponse (in your case it is the JSON file) can not be loaded instantly. However, $http.get returns a promise which is resolved when the request completes. You should do everything you want to do as soon as the JSON file has loaded inside the then-block of the promise.
$http.get('job.json').then(function (response) {
$scope.big = response;
// Do anything else you need to after JSON has been loaded.
});
Using promise.then you can update your value.
var promise=$http.get('job.json');
promise.then(function(result){
$scope.big=response;
});
alternative way
function getObj(callback){
$http.get('job.json').success(callback);;
}
getObj(function(result){
console.log(result)
// add your jquery code
})

$.each not updating css width

So I have a loop, which performs an ajax call on each iteration and I want to set the progress bar updated.. But it is not updating, it goes to 100% directly when ending...
I've tried to put the bar update call outside the success action (inside the loop directly) but it isn't working either..
$('button.page').on('click', function(e){
var $userList = textArray($('#page-userlist').val().replace('http://lop/', '').split(/\n/));
var $proxyList = textArray($('#page-proxylist').val().replace('http://', '').split(/\n/));
var $question = $('#page-question').val();
var data = {
question: $question,
users: $userList,
proxies: $proxyList
};
var i = 0, p = 0, max = data.proxies.length, totalusers = data.users.length, percent = 0;
$('#log').append("\n" + moment().calendar() + "\n");
var progressbar = $('#page-progress');
$.each(data.users, function(k, u){
if(typeof(p) !== 'undefined' && p !== null && p > 0)
{
if(i % 10 == 0 && i > 1) p++;
if(p == max) return false;
}
var proxy = data.proxies[p];
percent = Math.round((i / totalusers) * 100);
$.ajax({
type: "POST",
url: Routing.generate('viral_admin_bot_page'),
data: {question: $question, user: u, proxy: proxy},
success: function(result) {
$('#log').append("\nAtacado usuario " + u + " con proxy: " + proxy + "\n");
$(progressbar).width(percent + "%");
},
error: function(error) {
$('#log').append(error);
}
});
i++;
});
});
If i do console.log(percent); it is updating perfectly on each iteration, so I don't know where can be the problem.
Here is my code (without the ajax call because it isn't the problem) http://jsfiddle.net/dvo1dm03/20/
it will output to console the percentage, the objetive is to update the bar to the percentage completed in each loop, so it goes in "realtime" with loop.
Ok, here's how to do it asynchrounously.
var speed = 75;
var number_of_calls_returned = 0; // add number_of_calls_returned++ in your ajax success function
var number_of_total_calls;
var loaded = false;
function processUserData(){
if( number_of_calls_returned < number_of_total_calls){
setTimeout(function(){processUserData();}, 200);
}
else{
//received all data
// set progressbar to 100% width
loaded = true;
$("#page-progress").animate({width: "100%"},500);
$("#page-proxylist").val("Received data");
}
}
function updateProgress(percent, obj){
setTimeout(function(x){
if(!loaded)
$(obj).width(x + "%");
}, percent*speed, percent);
}
$('button.page').on('click', function (e) {
var $userList = textArray($('#page-userlist').val().replace('http://lop/', '').split(/\n/));
var $proxyList = textArray($('#page-proxylist').val().replace('http://', '').split(/\n/));
var $question = $('#page-question').val();
var data = {
question: $question,
users: $userList,
proxies: $proxyList
};
var i = 0,
p = 0,
max = data.proxies.length,
totalusers = data.users.length,
percent = 0;
//$('#log').append("\n" + moment().calendar() + "\n");
var progressbar = $('#page-progress');
number_of_total_calls = totalusers;
$.each(data.users, function (k, u) {
if (typeof (p) !== 'undefined' && p !== null && p > 0) {
if (i % 10 == 0 && i > 1) p++;
if (p == max) return false;
}
var proxy = data.proxies[p];
percent = (i / totalusers) * 100; //much smoother if not int
updateProgress(percent, progressbar);
i++;
// simulate ajax call
setTimeout(function(){number_of_calls_returned++;}, Math.random()*2000);
});
//callback function
setTimeout(function(){processUserData();}, 200);
});
var textArray = function (lines) {
var texts = []
for (var i = 0; i < lines.length; i++) {
// only push this line if it contains a non whitespace character.
if (/\S/.test(lines[i])) {
texts.push($.trim(lines[i]));
}
}
return texts;
}
Check it out here! jsFiddle (really cool!)
Your problem is cause by the fact that you have a closure for your success function and every success function shares the same percent variable. You can fix it like this:
success: function(percent, result) {
$('#log').append("\nAtacado usuario " + u + " con proxy: " + proxy + "\n");
$(progressbar).width(percent + "%");
}.bind(percent),
Where you'll need to shim bind in older browsers, or like this, which is a little uglier, but should work everywhere without a shim:
success: (function(percent) { return function(result) {
$('#log').append("\nAtacado usuario " + u + " con proxy: " + proxy + "\n");
$(progressbar).width(percent + "%");
}; }( percent ),
if what you want is to increase the update bar with each success of AJAX calls I'd suggest an easier solution (I've simplified the js code for clarity's sake):
$('button').click(function (e) {
var i = 0,
cont = 0,
totalusers = 100,
percent = 0;
var progressbar = $('#page-progress');
for (; i < totalusers; i++) {
$.ajax({
type: "POST",
url: '/echo/json/',
data: {
question: 'something',
user: 1,
proxy: 2
},
success: function (result) {
cont += 1;
percent = Math.round((cont / totalusers) * 100);
progressbar.width(percent + "%");
},
error: function (error) {
$('#log').append(error);
}
});
};
});
You can see it in action in this fiddle.
Hope this helps or at least give you some ideas.
Update the progress bar using setTimeout method.
it will wait for some time and then update the width of progressbar.
myVar = setTimeout("javascript function",milliseconds);
Thanks,
Ganesh Shirsat
I would like to make a recommendation of trying to make a self contained example that doesn't rely on the post so that it is easier for you or us to solve the problem
As well, you can console log elements so you could try logging the progressbar element, percent and the response of the ajax request
(This code is to replace the javascript sections of the fiddler)
var i = 0;
moveProgress();
function moveProgress(){
if(i < 10000)
{
setTimeout(function(){
$('#page-progress').width((i / 1000) * 100);
moveProgress();
},2);
i++;
}
}
The reason that it wasn't working was because the loop ran so fast that it was loaded by the time the script loaded it, the timeout allows you to delay the execution a bit(Though not necessarily recommended to use because of potential threading issues.

uncaught TypeError: Cannot read property "top" of null

I got a pretty annoying javascript error. The world famous:
uncaught TypeError: Cannot read property "top" of null
Here is the code:
$(function() {
var setTitle = function(title, href) {
title = 'Derp: ' + title;
href = href || '';
history.pushState({id: href}, title, href.replace('#', '/'));
document.title = title;
},
scroll = function(url, speed) {
var href = typeof url == 'string' ? url : $(this).attr('href'),
target = $(href),
offset = target.offset(),
title = target.find('h1').text();
if(typeof url == 'number') {
target = [{id:''}];
offset = {top: url};
}
// And move the element
if(offset.top) {
// Set the new URL and title
setTitle(title, href);
// Make sure we're not moving the contact panel
if(target[0].id != 'contact') {
$('html, body').animate({scrollTop: offset.top}, speed);
}
}
return false;
};
// Handle existing URL fragments on load
if(location.pathname.length > 1) {
scroll(location.pathname.replace('/', '#'), 0);
}
$('a#logo').click(function() {
$('html,body').animate({scrollTop: 0});
return false;
});
// Handle internal link clicks
$('a[href^=#]:not(#logo)').click(scroll);
// Close the "Get In Touch" box
var box = $('#contact'),
moveBox = function() {
var closing = $(this).attr('class') == 'close',
amount = closing ? -(box.height() + 20) : 0,
cb = closing ? '' : function() { box.animate({marginTop: -10}, 150); };
box.animate({marginTop: amount}, cb);
};
box.css('margin-top', -(box.height() + 20));
$('#contact a.close, #get-in-touch').click(moveBox);
// Nasty little fix for vertical centering
$('.vertical').each(function() {
$(this).css('margin-top', -($(this).height() / 2));
});
// Work panels
var parent = $('#work'),
panels = parent.children('div');
panels.each(function() {
$(this).css('width', 100 / panels.length + '%');
})
parent.css('width', (panels.length * 100) + '%');
// Bind the keyboards
$(document).keyup(function(e) {
var actions = {
// Left
37: function() {
var prev = panels.filter('.active').prev().not('small');
if(prev.length > 0) {
prev.siblings().removeClass('active');
setTitle(prev.find('h1').text(), prev[0].id);
setTimeout(function() {
prev.addClass('active');
}, 250);
parent.animate({left: '+=100%'}).css('background-color', '#' + prev.attr('data-background'));
}
},
// Right
39: function() {
var next = panels.filter('.active').next();
if(next.length > 0) {
next.siblings().removeClass('active');
setTitle(next.find('h1').text(), next[0].id);
setTimeout(function() {
next.addClass('active');
}, 250);
parent.animate({left: '-=100%'}).css('background-color', '#' + next.attr('data-background'));
}
},
// Down
40: function() {
var w = $(window),
height = w.height() * panels.children('div').length,
h = w.height() + w.scrollTop();
if(h < height) {
scroll(h);
}
},
// Up
38: function() {
var w = $(window);
$('html,body').animate({scrollTop: w.scrollTop() - w.height()});
}
};
// Call a function based on keycode
if(actions[e.which]) {
actions[e.which]();
}
e.preventDefault();
return false;
});
// Fix crazy resize bugs
$(window).resize(function() {
var m = $(this),
h = m.height(),
s = m.scrollTop();
if((h - s) < (h / 2)) {
m.scrollTop(h);
}
//$('html,body').animate({scrollTop: s});
});
// slideshow
var woof = function() {
var slides = $('#molly li'),
active = slides.filter('.active');
if(!active.length) {
active = slides.last();
}
active.addClass('active');
var next = active.next().length ? active.next() : slides.first();
next.css('opacity', 0).addClass('active').animate({opacity: 1}, function() {
active.removeClass('active last-active');
});
};
setInterval(woof, 3000);
// easing
$.easing.swing = function(v,i,s,u,a,l) {
if((i /= a / 2) < 1) {
return u / 2 * (Math.pow(i, 3)) + s;
}
return u / 2 * ((i -= 2) * i * i + 2) + s;
};
// Change the default .animate() time: http://forr.st/~PG0
$.fx.speeds._default = 600;
});
try{Typekit.load()}catch(e){}
Sorry for this long monster but I thought it could be useful for you to see the whole thing. The Error warning shows up in this part:
// And move the element
if(offset.top) {
Uncaught TypeError: Cannot read property 'top' of null
It's line 23 in the code.
That's it. Could you give me a hint on how to solve this problem?
Thank you!
var href = typeof url == 'string' ? url : $(this).attr('href'),
target = $(href), //line 2
offset = target.offset(), //line 3
I believe this must have something to do with line 2, target should be null when error occurs
According to jQuery source, jQuery.fn.offset only returns null if:
the first element in the set doesn't exist (empty set) or
its ownerDocument is falsy (I don't know when that would happen, sorry).
The first option seems more likely, so you should check if target.length > 0 before calling target.offset() and handle the alternative.

Categories