Script execution times out in Internet Explorer - php

I incorporate javascript in my PHP program:
Try to check my codes.
It loops depend on the number of records in database.
for instance:
$counter = 0;
foreach($row_value as $data):
echo $this->javascript($counter, $data->exrate, $data->tab);
endforeach;
private function javascript($counter=NULL, $exrate=NULL, $tab=NULL){
$js = "
<script type='text/javascript'>
$(function () {
var textBox0 = $('input:text[id$=quantity{$counter}]').keyup(foo);
var textBox1 = $('input:text[id$=mc{$counter}]').keyup(foo);
var textBox2 = $('input:text[id$=lc{$counter}]').keyup(foo);
function foo() {
var value0 = textBox0.val();
var value1 = textBox1.val();
var value2 = textBox2.val();
var sum = add(value1, value2) * (value0 * {$exrate});
$('input:text[id$=result{$counter}]').val(parseFloat(sum).toFixed(2));
// Compute Total Quantity
var qtotal = 0;
$('.quantity{$tab}').each(function() {
qtotal += Number($(this).val());
});
$('#tquantity{$tab}').text(qtotal);
// Compute MC UNIT
var mctotal = 0;
$('.mc{$tab}').each(function() {
mctotal += Number($(this).val());
});
$('#tmc{$tab}').text(mctotal);
// Compute LC UNIT
var lctotal = 0;
$('.lc{$tab}').each(function() {
lctotal += Number($(this).val());
});
$('#tlc{$tab}').text(lctotal);
// Compute Result
var result = 0;
$('.result{$tab}').each(function() {
result += Number($(this).val());
});
$('#tresult{$tab}').text(result);
}
function add() {
var sum = 0;
for (var i = 0, j = arguments.length; i < j; i++) {
if (IsNumeric(arguments[i])) {
sum += parseFloat(arguments[i]);
}
}
return sum;
}
function IsNumeric(input) {
return (input - 0) == input && input.length > 0;
}
});
</script>
";
return $js;
}
When I running this on IE7 this message is always annoying me
Stop running this script?
A script on this page is causing your web browser to
run slowly. If it continues to run, your computer
might become unresponsive.
but in firefox it's functioning well.

IE displays that message when it decides that a script is taking too long (actually other browsers have a similar warning, but they don't all calculate "too long" the same way and don't all run at the same speed).
You didn't actually ask a question, but I assume you want to know how to make your script more efficient so that it will (we hope) complete before that IE message is triggered?
I like jQuery a lot, but using it does involve a lot of function calls, including nested functions with callbacks, etc., and once you start putting these functions inside loops (in your case multiple loops) it can get quite inefficient. If you're only processing a small number of items this may not be noticeable to the user, but if you're processing a lot the first thing you could change that would definitely speed up your code would be changing the .each() loops to standard for loops:
// CHANGE
var qtotal = 0;
$('.quantity{$tab}').each(function() {
qtotal += Number($(this).val());
});
// TO
var qtotal = 0,
$q = $('#tquantity{$tab}');
for (i = 0; i < $q.length; i++)
qtotal += +$q[i].value;
Note that in the for loop I've used the DOM element's value property directly rather than using jQuery to retrieve it via .val() (which even within .each() you could've done with this.value rather than $(this).val()). I've also used the unary plus operator instead of Number(). This means no function calls at all on loop iterations, whereas your way had a call to Number(), $() and .val() (not even counting the additional processing that jQuery does behind the scenes within $() and .val()).
Make a similar change for all of your .each() loops (declare i at the beginning of your function and re-use it for each loop) and you should see some improvement.

Related

Processing json where the number of json array is dynamic

I have a json response from php to ajax. The thing is depending on the value entered in a text box the number of json arrays vary. Example: sometimes it may return {"count1":10, "ccc1":30} and sometimes like this {"count1":10, "ccc1":32, "count2":40, "ccc2":123,"count3":32,"ccc3":21}. I extract the value in jquery this way:
success: function(response){
var count = response.count1;
//do something
}
But now since the number of counts are different I used a loop. Question is I can figure out how many of them I am receiving but how can I process them? The var count = response.count needs to be specific right? I cannot just concate any strings like this:
var count = 0;
while(something){
count = count + 1;
var str = "count"+count;
var whatever = response.str;
}
So, can someone please help me with a suitable solution in this case?
You are on the right track there. Something like this should work for you.
var i = 1;
while(response['count' + i]) {
var count = response['count' + i++];
}
You can access the properties as if they were array indices. so response['count'+i] works.
Loop through all properties and add them in a variable like following.
var response = { "count1": 10, "ccc1": 32, "count2": 40, "ccc2": 123, "count3": 32, "ccc3": 21 };
var count = 0;
for (var prop in response) {
if (prop.startsWith('count'))
count += response[prop];
}
console.log(count);
To retrieve all values use jQuery $.each function.
var data_tmp = '{"count1":10, "ccc1":32, "count2":40, "ccc2":123,"count3":32,"ccc3":21}';
var data = $.parseJSON(data_tmp);
$.each(data, function(k,val){
if(k.toLowerCase().indexOf("count") >= 0){
$('.wr').append('<div>' + val + '</div>')
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="wr"></div>
success: function(response){
var count = response.count1;
var object = JSON.parse(response);
alert(object.length);
for (i = 0; i < object.length; i++) {
console.log(object[i]);
}
}

JS checkbox.checked vs manually checking

I have a page which is paginated to 100 results per page by php with checkboxes beside each. I have three functions: one to select all, one to save what was checked, and one to restore what was checked.
I don't understand why my toggle function does not work with the other two.
If I click select all (which performs a toggle()) the checked values are not saved;
however, if I click them by hand they do get saved across pagination.
I am assuming that I have to do something along the lines of persistCheckBox(checkboxes[i].checked) to the last line of my toggle function --which I tried and it did not work; Can someone explain why?
function toggle(source) {
checkboxes = document.getElementsByName('multi_mag[]');
for (var i = 0, n = checkboxes.length; i < n; i++) {
checkboxes[i].checked = source.checked;
}
}
function restorePersistedCheckBoxes() {
var aStatus = getPersistedCheckStatus();
for (var i = 0; i < aStatus.length; i++) {
var aPair = aStatus[i].split(':');
var el = document.getElementById(aPair[0]);
if (el) {
el.checked = aPair[1] == '1';
}
}
}
function persistCheckBox(el) {
var found = false;
var currentStateFragment = el.id + ':' + (el.checked ? '1' : '0');
var aStatus = getPersistedCheckStatus();
for (var i = 0; i < aStatus.length; i++) {
var aPair = aStatus[i].split(':');
if (aPair[0] == el.id) {
// State for this checkbox was already present; replace it
aStatus[i] = currentStateFragment;
found = true;
break;
}
}
if (!found) {
// State for this checkbox wasn't present; add it
aStatus.push(currentStateFragment);
}
// Now that the array has our info stored, persist it
setPersistedCheckStatus(aStatus);
}
Neither the click nor the change events are triggered when changing the checked value programmatically.
Since you tagged your question with jQuery, I will demonstrate using some jQuery code.
It is unclear from your code how you do your persistent storage or what is your HTML structure, so the code will show a general approach.
A word of advice, though: I strongly suggest that you remove styling code out of the structure and use CSS and avoid inline event handling. Pretty much everything that you want to accomplished can be done more cleanly from outside the HTML.
I will be suing a form with several checkboxes, the first of which will change the other checkboxes' state.
HTML:
<form id="boxes">
<input type="checkbox" id="all" name="all" />
<input type="checkbox" name="multi_mag[]" class="normal" />
...
<input type="checkbox" name="multi_mag[]" class="normal" />
</form>
Javascript:
In this example, all of the 'normal' checkboxes have some common property (in this case, I decided on a class), that allow event delegation.
$('#boxes').delegate('.normal', 'change', function (e) {
console.log('changed', e.target.checked);
});
This code sets a function to run every time a checkbox changes, corresponding to your persistCheckBox() method.
Next, the equivalent of your toggle() function:
$('#all').change(function (e) {
var checked = e.target.checked;
console.log('changed checkall box: ', checked);
checkboxes = document.getElementsByName('multi_mag[]');
for (var i = 0, n = checkboxes.length; i < n; i++) {
checkboxes[i].checked = checked;
$(checkboxes[i]).change();
}
});
It is executed whenever the "main" checbox changes its state. All of the checkboxes are iterated, their values are changed and the change event is triggered, which causes each to run the aforementioned function.
You can apply this method to your (cleaned) code, and the persistence should be maintained.
Example jsFiddle (check your console for the activity log).
This little piece of code can check / uncheck a checkbox, and will trigger any associated events.
$('input[type=checkbox]').trigger('click');
It could help maybe
I fixed this by adding I fixed this by adding "persistCheckBox(checkboxes[i]);" to the last line of the toggle() function. #MasterAM I appreciate your critiques and will be using them to optimize my code. I also appreciate the JQuery solution you provided.

Retrieving mysql data using ajax and then manipulating it

My question has part solutions on this site but not a complete answer.
On my wordpress homepage I display a counter of the number of questions answered within our webapp. This is displayed using jQuery and AJAX to retrieve the question count from a php file and works fine with this code.
jQuery(document).ready(function() {
function load() {
jQuery.get('/question_count.php', function(data) {jQuery('#p1').html( data ); });
}
load();
setInterval(load,10000);
});
Is there a way to display counting up to the new number retrieved rather than just immediately displaying it?
Something like this?
function countTo(n) {
var p = $("#p1"),
c = parseInt(p.html(), 10) || 0,
dir = (c > n ? -1 : 1); // count up or down?
if (c != n) {
p.html((c + dir) + "");
setTimeout(function() {
countTo(n);
}, 500);
}
}
Call it in your success handler
jQuery.get('/question_count.php', function(data) {
var n = parseInt(data, 10);
countTo(n);
});
Example
You will need to do a setInterval event so that the count up is visable to human eyes.
This may be a problem if you eventually reach enough questions where the count takes a long time to reach the end.
Code will look like this:
function load(){
jQuery.get('/question_count.php', function(data){
var curr = 0;
var max = parseInt(data);
var interval = setInterval(function(){
if(curr==max){
clearInterval(interval);
}
jQuery('#p1').html( curr );
curr+=1; //<-- if the number of questions gets very large, increase this number
},
10 //<-- modify this to change how fast it updates
});
}
}

Populate Select list Menu though Ajax Jquery

Before anybody says this is a duplicate of this and that question, let me assure you I have tried the solutions there and I have failed. I am using a solution offered in this website to come up with my solution and I believe I am 90% done except for one error. I want to display a list of all codes that have a certain common ID associated with them.
Here is my PHP code that I am using to get a list of codes
<?php
$budgetcode=$_POST['budgetcode'];
//$budgetcode=2102;
$selectcodes="SELECT * FROM tblbudget_codes WHERE T1 = $budgetcode";
$query=$connection->query($selectcodes);
$count=$query->num_rows;
if($count < 1)
{
die('0');
}
else{
while($row=$query->fetch_array()){
$T1=($row['T1']);
$T2=($row['T2']);
$T3=($row['T3']);
$T4=($row['T4']);
$optionValue = $T1."-".$T2."-".$T3."-".$T4;
echo json_encode("<option>$optionValue</option");
// echo json_encode('1');
}
}
?>
Here is the ajax call i am using to fetch the codes
$.post("Functions/getbudgetcodes.php",{budgetcode:budgetid},function(data){
if(data!='0')
{
$("#budgetcode").html(data).show();
$("#result").html('');
}
else{
$("#result").html('<em>No codes found. Contact Administrator</em>');
}
},'json')
//alert(budgetid);
})
The problem here is that jquery does not understand the data it is receiving if it is not numeric. E.g if I comment out the json_encode('1') and put random html code instead of data in my success part, I get results displayed in my browser. Can anybody tell me why jquery is only recognizing numeric values that are being echoed from PHP and not varchar values. Using jquery 1.4.2. Any help appreciated.
EDIT
I have managed upto some point and now i am stuck. I have used John's Answer and here is my jquery code. i just need to split the array and append each element to a variable one at a time like here
here is the code. Somebody please tell how I split (data). i can alert it but it is comma seperated. Just need to get the individual items append them to variable html and then display it.
$.post("Functions/getbudgetcodes.php",{budgetcode:budgetid},function(data){
if(!$.isEmptyObject(data))
{
//alert (data);
// alert(split (data))
var html = '';
var len = data.length;
for (var i = 0; i< len; i++) {
html += '<option>' +data+ '</option>';
}
$("#budgetcode").html(html).show();
$("#result").html('');
}
else{
$("#result").html('<em>No codes found. Contact Administrator</em>');
}
},'json')
I would skip JSON altogether:
PHP
echo "<option>$optionValue</option>";
Everything else should work.
Finally figured it out. Here is the php code
$selectcodes="SELECT * FROM tblbudget_codes WHERE T1 = $budgetcode";
$query=$connection->query($selectcodes);
$count=$query->num_rows;
if($count < 1)
{
die('0');
}
else{
while($row=$query->fetch_array()){
$data[] = $row;
}
echo json_encode($data);
}
?>
Here is the jquery code
$.post("Functions/getbudgetcodes.php",{budgetcode:budgetid},function(data){
if(!$.isEmptyObject(data))
{
//alert (data);
var html = '';
var joiner='';
var len = data.length;
for (var i = 0; i< len; i++) {
joiner=([data[i].T1,data[i].T2,data[i].T3, data[i].T4].join('-'));
//alert(joiner);
html += '<option>'+joiner+'</option>';
}
$("#budgetcode").html(html).show();
$("#result").html('');
}
else{
$("#result").html('<em>No codes found. Contact Administrator</em>');
}
},'json')
Had to use join to join the multiple codes using a dash. Hope this helps. The PHP part and part of the jquery was inspired by this question
FWIW, for populating select lists I usually use the following jQuery code:
// populates select list from array of items given as objects: {
name: 'text', value: 'value' }
function populateSelectList(parent, items) {
parent.options.length = 0;
if (parent.options.length === 0) {
parent.options[0] = new Option("Please select something...", "");
}
$.each(items, function (i) {
if (typeof (this) == 'undefined') { return; }
parent.options[el.options.length] = new Option(this.name, this.value);
});
}
and to call the above function i pass the results of an ajax call using the map method where #select is the selector for the parent select element. I am setting the Text property to the name and Value to the value but that should change according to the objects returned by the ajax call (e.g. assuming the returned objects have a Value and Text properties).
populateSelectList($('#select').get(0), $.map(results, function
(result) { return { name: result.Text, value: result.Value} }));

Jquery random number

I'm looking to create a simple jquery game.
It starts like this, the user enters a number in a text field.
<form>
<input type="text" id="MyNumber" value="" />
<button id="getit">Play</button>
</form>
<div id="randomnumber"></div>
After the click the play button, a series of numbers will appear in the div id randomnumber.
The objective is to click on the randomly rotating numbers in the div id randomnumber when they see the number they intered in the my number text field. If they click their number, they win.
The jquery script I have requires a button be pushed to generate the number, (I don't want a button pushed each time a new number should be generated.) The script also doesn't identify the number that was clicked, or send it to my checknumber.php page so I can store the number entered and the number picked in a database.
Any help?
this is the jquery script I have.
function IsNumeric(n){
return !isNaN(n);
}
$(function(){
$("#getit").click(function() {
var numLow = $("#lownumber").val();
var numHigh = $("#highnumber").val();
var adjustedHigh = (parseFloat(numHigh) - parseFloat(numLow)) + 1;
var numRand = Math.floor(Math.random()*adjustedHigh) + parseFloat(numLow);
if (IsNumeric(numLow)
&& IsNumeric(numHigh)
&& (parseFloat(numLow) <= parseFloat(numHigh))
&& (numLow != '')
&& (numHigh != ''))
{
$("#randomnumber").text(numRand);
} else {
$("#randomnumber").text("Careful now...");
}
return false;
});
$("input[type=text]").each(function(){
$(this).data("first-click", true);
});
$("input[type=text]").focus(function(){
if ($(this).data("first-click")) {
$(this).val("");
$(this).data("first-click", false);
$(this).css("color", "black");
}
});
});
The "Play" button is good to start the ball rolling (I'm not certain if you were thinking of removing it entirely). To generate numbers periodically, use setInterval.
$(function(){
var initialPeriod=500; // 0.5s
var generateNumIval;
function generateNum() {
var numLow = $("#lownumber").val();
var numHigh = $("#highnumber").val();
var adjustedHigh = (parseFloat(numHigh) - parseFloat(numLow)) + 1;
var numRand = Math.floor(Math.random()*adjustedHigh) + parseFloat(numLow);
if (IsNumeric(numLow)
&& IsNumeric(numHigh)
&& (parseFloat(numLow) <= parseFloat(numHigh))
&& (numLow != '')
&& (numHigh != ''))
{
$("#randomnumber").text(numRand);
} else {
$("#randomnumber").text("Careful now...");
}
}
function run(period) {
clearInterval(generateNumIval);
generateNumIval = setInterval(generateNum, period);
}
$("#getit").click(function() {
run(initialPeriod);
return false;
});
...
You can change the period (such as to increase the difficulty when the user clicks the correct number, or decreasing the difficulty when the user makes too many sequential mistakes) by calling run with a new period. If you want to change the period after generating each number, use setTimeout rather than setInterval.
To check a click on a number, register a click handler on #randomnumber that compares its val() to #MyNumber's val(). From there, take appropriate action as to whether it's a hit or miss. As Dan says, doing this for every click will create quite a bit of network traffic. Though only a small amount of data may be transmitted each time, the number of connections can cause a significant impact. Instead, have a "Stop" button and send the data if the user clicks it, or use an unload handler (one does not exclude the other).
Your server will crash and burn if you have more than a couple people playing this game. People can identify and click very fast (multiple times per second), but unless they live next to your server, you can't receive and respond to HTTP requests that fast, nor can your server handle hundreds or more per second from the multiple users.
Write the game in JavaScript and when they're done, send the totals (# of wrong clicks and # of right clicks, or whatever) to your server to save. Do your best to obfuscate how they're sent so that it's not trivial to make up scores.
There's a couple of things to look out for here. There's no reason why the random numbers can't be generated from the number the player has entered himself, or even better, a number generated by the game itself.
The way which you've done the placeholder text, using data and two event handlers is also somewhat messy. At a minimum you should be using .one to attach a one-time event handler for this, but it would be much better if you use the HTML5 placeholder attribute with a Javascript fallback.
Other than that, you're still missing significant amount of game logic in there. I won't advice you to work on this game for too long though - it's great as an exercise in working with JavaScript and jQuery, but otherwise not very worthwhile.
Oh, and just for fun, I also built my own version of this.
var hitCount = 0,
missCount = 0;
function IsNumeric(n) {
return !isNaN(n);
}
$("#getit").click(function() {
var li = [],
intervals = 0,
n = parseInt($('#MyNumber').val());
if (IsNumeric(n)) {
setInterval(function() {
li[intervals++ % li.length].text(Math.random() > .1 ? Math.floor(Math.random() * (10 + n) + (n / 2)) : n).attr('class', '');
}, 500);
}
$('#randomnumber').empty();
for (var i = 0; i < 5; i++) {
li.push($('<li />').click(function() {
var $this = $(this);
if (!$this.hasClass('clicked')) {
if (parseInt($this.text(), 10) === n) {
$this.addClass('correct');
$('#hitcount').text(++hitCount);
} else {
$this.addClass('wrong');
$('#misscount').text(++missCount);
}
}
$this.addClass('clicked');
}).appendTo('#randomnumber'));
}
return false;
});
Crude yes, but it sort of works. Have a look at it here: http://jsfiddle.net/DHPQT/
For fun..
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript">
var mainLoop;
$(function(){
$("#getit").click(function() {
if ($(this).attr('class') == 'start') {
$(this).attr('class','play');
$(this).html('STOP THE MADNESS!');
mainLoop = window.setInterval(function() {
var output = '';
for (var i = 0; i < 10; i++) {
var numLow = $("#lownumber").val();
var numHigh = $("#highnumber").val();
var adjustedHigh = (parseFloat(numHigh) - parseFloat(numLow)) + 1;
var numRand = Math.floor(Math.random()*adjustedHigh) + parseFloat(numLow);
output += '<div>'+numRand+'</div>';
}
$('#randomnumbers').html(output);
},250);
} else {
window.clearInterval(mainLoop);
var sweetWin = false;
$('#randomnumbers').children().each(function() {
var v = $(this).html();
if (v == $('#MyNumber').val()) {
alert('WIN!');
sweetWin = true;
$.post('127.0.0.1',{outcome:'win'});
}
});
if (!sweetWin) {
alert('FAIL!');
$.post('127.0.0.1',{outcome:'loss'});
}
$(this).attr('class','start');
$(this).html('Play');
}
});
});
</script>
</head>
<body>
Low: <input type="text" id="lownumber" value="0" />
High: <input type="text" id="highnumber" value="100" />
<input type="text" id="MyNumber" value="50" />
<button id="getit" class="start">Play</button>
<div id="randomnumbers"></div>
</body>
</html>

Categories