...

Hi! I’m Starx

experienced Software Developer. And this is my blog
Start Reading About me
Blog Page
April 29, 2012

How do I animate in jQuery without stacking callbacks?

Question by yuval

Let’s say I have three divs, and I’d like each to animate once the previous one is done. Currently, I write this:

$('div1').fadeOut('slow', function() {
    $('div2').fadeOut('slow', function() {
        $('div3').fadeOut('slow');
    });
});

Which is ugly, but manageable.

Now imagine I have 10 different animations that need to happen one after the other on different elements. Suddenly the code gets so clunky that it’s extremely hard to manage…

Here’s pseudocode for what I’m looking to do:

$('div1').fadeOut('slow' { delay_next_function_until_done: true } );
$('div2').fadeOut('slow' { delay_next_function_until_done: true } );
$('div3').animate({ top: 500 }, 1000 );

How do I achieve this?

Answer by Julian Aubourg

If you’re using a recent version of jQuery, use the animation promises:

$('div1').fadeOut('slow' ) ).promise().pipe(function() {
    return $('div2').fadeOut('slow' );
}).pipe(function() {
    return $('div3').animate({ top: 500 }, 1000 );
});

You can make it generic:

$.chain = function() {
    var promise = $.Deferred().resolve().promise();
    jQuery.each( arguments, function() {
        promise = promise.pipe( this );
    });
    return promise;
};

var animations = $.chain(function() {
    return $('div1').fadeOut('slow');
}, function() {
    return $('div2').fadeOut('slow');
}, function() {
    return $('div3').animate({ top: 500 }, 1000 );
});

$.when( animations ).done(function() {
    // ALL ANIMATIONS HAVE BEEN DONE IN SEQUENCE
});

Still a lot of function closures but that’s the very nature of Javascript. However, it’s much more natural and a lot more flexible using Deferreds/Promises since you avoid callbacks “inception”.

Answer by Starx

Callback is a friend, dont push it away. There are ways to simplify them. Here is one of them

$('div1').fadeOut('slow', div2)
function div3() { $('div3').fadeOut('slow'); }
function div2() { $('div2').fadeOut('slow', div3); }
Read more

Counting the number of DIVs placed into a DIV via drag and Drop

Question by Jiggles

I have had a look about the site and found some code and tried it out but its not working in any shape or form.

I am wanting to count the number of DIVs thats placed into another DIV by the user dragging and dropping but only to count the ‘correct’ ones then if all the correct ones are in the DIV display an alert saying well done then rest the ‘game’. Also need to show how many more is needed to go to ‘win’.

This is what I have so far:

JS:

    $('.drop').each(function(){ 
        var n = $(this).children('.draggable').length;
        $(".count").text("There are " + n + " divs inside parent box detail.");
        if(n == 2){
        alert("You got them all right! :)");
        }
        });

HTML:

    <div class="foods">
              <div class="draggable" id="draggable"><img src="images/fish.png" id="draggable"></div>

              <div class="draggable" id="draggable"><img src="images/stone.png"></div>

              <div class="wrong"><img src="images/tree.png"></div>
            </div>

<div class="foods">                
<div id="droppable" class="drop">
<p>Drop here</p>
</div>
</div>

<div class="foods">
        <span class="count"></span> 
</div>

JS Fiddle of the code: http://jsfiddle.net/JRLZK/

Thanks in advanced for any help!

Answer by 350_Design

This should do it with your logic.

 $(function() {
    var n = 0;
    $( ".draggable" ).draggable();
    $( ".wrong" ).draggable();

    $( "#droppable" ).droppable({    
        drop: function( event, ui) {
            console.log($(ui));
            if($(ui.draggable).hasClass("draggable")){
            $( this )
                .find( "p" )
                 .html( "Correct! :)" );
                n++;
        $(".count").text("There are " + n + " divs inside parent box detail.");
        if(n == 2){
        alert("You got them all right! :)");
        }

            } else {
                    $( this )
                    .find( "p" )
                    .html( "Wrong! :(" );
            }
        }
    });
});

Answer by Starx

The problem is the duplicate IDs you are giving. I used class instead of id, but you can apply your own logic there.

$( "#droppable" ).droppable({    
    drop: function( event, ui) {
        if($(ui.draggable).hasClass("draggable")){
        $( this )
            .find( "p" )
                .html( "Correct! :)" );
        } else {
                $( this )
                .find( "p" )
                .html( "Wrong! :(" );
        }
    }
}); 

Demo


Update

Here is a workaround for the count

var div = $("<div />"); //a temp container
$( "#droppable" ).droppable({    
    drop: function( event, ui) {
        ui.draggable.clone().appendTo(div);
        if(div.children(".draggable").length == 2) {
            alert('correct');
        }
    }
}); 

Demo

Read more

Send variable to PHP and reload using jquery?

Question by Belhajio

I am completely new to all of this coding.. so I apologies for my ignorance in advance.

I have this jquery function (button) which changes the size of the table of where my Post.php is loaded, (to alternate between portrait and landscape). the function itself works great in changing the size however i am stuck in reloading the post.php page.

 $("#cSize").toggle(
 function () {
 $('#p_CWidth').animate({width:720});
 $('#p_SWidth').animate({width:110});
 }, function() {
     $('#p_CWidth').animate({width:520});
 $('#p_SWidth').animate({width:310});
 });

what i need to add to this code is away of changing the variable p_Type to true or false and reloading the post.php or the div p_Post

 <div id="p_Post">
 <? $p_type = true;
 include 'profile/post.php'; ?>
 </div>

post.php with the above code is loaded fine and i tested it by manually changing p_type to false/true and it loaded ok. But how can i get this automated with the jquery functoin above?

I have tried .load(‘profile/post.php’) however this brings me an error for db access!!

any help is really appreciated
AB

UPDATE

I have changed my php file to just a simple php without any link to mysql for testing, and i have tried the suggested code:

var p_type = false;
$("#cSize").toggle(function () {
   $("#p_post").load('profile/post.php',{ 'p_type' : p_type }, function { 
       p_type = !p_type; //toggle the value for automation
});

   $('#p_CWidth').animate({width:720});
   $('#p_SWidth').animate({width:110});

});

and sadly that doesnt seem to work?!!

but with some trial and error i have manged to get change in size working again, and the php reloaded for the first time with the new right variable (p_type), however for some reason the php file only loads once! so it doesnt go back to the normal size with (p_type as true after being set as false)??? here is the code:

   $("#cSize").toggle(
    function () {
  $('#p_CWidth').animate({width:720});
  $('#p_SWidth').animate({width:110});
  $("#p_Post").load('profile/p_post.php',{ p_type : false });
}, function() {
      $('#p_CWidth').animate({width:520});
  $('#p_SWidth').animate({width:310});
  $("#p_Post").load('profile/p_post.php',{ p_type : true });
   });

Thank you again in advance

ps. here is the toggle example i followed http://jsfiddle.net/6FMZY/

Answer by Starx

You can add additional data to your jQuery snippet like this

$("#p_post").load('profile/post.php',{ p_type : false });

But since you are trying to automate this, while relaoding

var p_type = false;
$("#p_post").load('profile/post.php',{ 'p_type' : p_type }, function(data) { 
    'p_type' = !p_type; //toggle the value for automation
});

Update:

Here is a simulation of sending the data on toggle

Read more

mysql join query with sum retuns null

Question by dr.linux

If makale_payments table is null the query returns null. How shoul i set the query yo get recors if doesnt exist in SUM(payment_total) like 0.00 ?

SELECT article_name,user_real_name,user_name,SUM(`article_payment`) as holding,paid
FROM makale_articles AS t1
JOIN makale_users ON (t1.article_name=makale_users.user_id) 
JOIN (SELECT user_id,SUM(`payment_total`) as paid FROM makale_payments GROUP BY user_id) AS t2 ON (t1.article_name=t2.user_id)
GROUP BY t2.user_id

Answer by user582118

MySQL does not return aggregate values for rows that return nulls, even if specifically testing for ISNULL. ISNULL is only to check if a column is null, not if the relation returns null. I did however find a (albeit very obscure) way to get around this limitation. The basic premise is to union all two sql statements and use the two unioned query as a subquery to select from.

The unioned queryies would be of the form:

   select column1, column2, SUM(column3) as payment from tablea, tableb where....
   union all
   select column1, column2, 0.00 as payment from tablea --notice no join, and a specified value and alias for aggregate column

With the above query, you will get two rows for every row that the relation is not null, and one row when it is. If you sum that rows and group by, then you should end up with the values you want. So you then create a query that uses the above as the table to select from and sums the aggregate column:

   select column1, column2, SUM(payment) from

   (select column1, column2, SUM(column3) as payment from tablea, tableb where....
   union all
   select column1, column2, 0.00 as payment from tablea) as b
   group by column1, column2

I am probably off on the syntax of the query, sorry, I don’t have MySQL here to test.

Answer by Starx

A simple WHERE wouldn’t have hurt I guess

WHERE SUM(`article_payment`) > 0
Read more
April 28, 2012

Dynamically add options to a list through a hidden iframe

Question by user1157439

I want to dynamically add options to a list through a hidden iframe; I suspect my mistake is in the PHP below:

<?php echo 'var oInner  = document.createTextNode("'.$donnees["name"].'");'; ?>

because my code works perfectly with:

<?php echo 'var oInner  = document.createTextNode("Newoption");'; ?>

I don’t know why createtextnode doesn’t want to take my PHP var… I thought it could be a same origin policy since the database is located on a server outside my website.

I don’t know.

You’ll find enclosed the complete code:

In my HTML I have:

//select or change a country will trigger the javascript part
<select name="countrym" id="countrym" onchange="validcountry();">
    <option value"France">France</option>
</select>

//Empty region list
<select name="regionm" id="regionm">
</select>

//My Iframe
<iframe name="upload_iframe2" id="upload_iframe2" frameborder="0"></iframe>

In my Javascript I have:

//My function triggering the PHP through the Iframe
function validcountry() {
var countrym = document.getElementById('countrym');
    var choixco = countrym.options[countrym.selectedIndex].value;
    document.getElementById('upload_iframe2').src = 'region.php?choix='+choixco;

In my PHP region.php file, I have:

<?php

// Get my choice
$codepays = $_GET['choix'];

//Retrieve the regions corresponding to the country
$pdo_options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;
$bdd = new PDO(XXX);
$req = $bdd->prepare('SELECT name FROM regions WHERE country = :country');
$req->execute(array('country' => $codepays));
$donnees = $req->fetch();

while($donnees)
   {   
// I checked the format of the data (no problem so far)
echo var_dump ($donnees['name']);
?>

//I add an option through Javascript
<script language="JavaScript" type="text/javascript">
var oOption = document.createElement("option");

//Here is my big issue:
<?php echo 'var oInner  = document.createTextNode("'.$donnees["name"].'");'; ?>

oOption.value = "none";
oOption.appendChild(oInner);
var parDoc = window.parent.document;
var regionm = parDoc.getElementById("regionm");
regionm.appendChild(oOption);
</script> 

<?php
$donnees = $req->fetch();
}
$req->closeCursor();
exit();
?>

Answer by Starx

I am suspecting that the indexed element cannot be found. But is all cases, this below should work.

<?php echo 'var oInner  = document.createTextNode("'. (isset($donnees["name"]) ? $donnees["name"] : '') .'");'; ?>
Read more

applying multiple limits

Question by Jacob K

I have a table that goes as follows:

content_id | contact_count
         1              23
         2               4
         3              89

I want to select the content_id with the highest contact_count from the last 25 rows of the table.

I’ve tried many different things such as:

select content_id from research_products_content
   where contact_count=(select max(contact_count)
        from research_products_content order by rating_total_id desc limit 25)
   order by rating_total_id desc limit 1

Answer by Shedal

In your example, limit 25 is applied after the result (max, which is a single row) is selected. Try this instead:

SELECT tmp.content_id FROM (
  SELECT *
  FROM research_products_content
  ORDER BY rating_total_id DESC
  LIMIT 25
  ) AS tmp
WHERE tmp.contact_count = (
  SELECT max(tmp2.contact_count)
  FROM (
    SELECT *
    FROM research_products_content
    ORDER BY rating_total_id DESC
    LIMIT 25
  ) AS tmp2
)
LIMIT 1

Answer by Starx

Since the column number will be the same use UNION

select content_id from research_products_content
   where contact_count=(select max(contact_count)
        from research_products_content order by rating_total_id desc limit 25)
UNION
select content_id from research_products_content
   where contact_count=(select max(contact_count)
        from research_products_content order by rating_total_id desc limit 1

You might want to implement caching along the way

Read more

table td is not taking its css when created dynamically

Question by prerna

var $imageicon = $('<image/>');
 $imageicon.attr('src', '../../Content/images/ReplyIcon.png');
 $imageicon.addClass('replyIcon');
 var $table = $('<table/>').addClass('replyContent');
 $table.attr('id', 'replyArea');

 $table.append(
                         $('<tr>').append($('<td>').append($imageicon).addClass('replyIcontd'), $('<td>').text('hii'))
      );
 $("#container").append(
               $('<div/>')
                  .attr('id', 'replytopost')
                  .append($table)
            );

css

.replyIcontd
{
   width:5%;

}

table is showing up but i waent to reduce space between hii and image I am trying to reduce the width to 5% but I am unable to do it
I the image hii is one td and ok is one td .I want both of them to come side by side

enter image description here

Answer by Starx

You forgot to give closing / on the elements you created dynamically.

 $('<tr />').append($('<td />').append($imageicon).addClass('replyIcontd'), $('<td />').text('hii'));

Update
I made some pretty big changes on your script, with a proper way to do this.

 var $imageicon = $('<img />', {
     'src' : '../../Content/images/ReplyIcon.png',
     'class' : 'replyIcon'
 });

 var $table = $('<table/>', {
     "class" : "replyContent",
     "id" : "replayArea",
     'html' : $('<tr />', {
                 'html' :  $('<td />', {
                     'class': 'replyIcontd',
                     'html' : $imageicon
                 }).html()+$("<td />", {
                     'text' : 'hii'
                 }).html()                     
              })

 });

Demo

Read more

Why margin:0 auto is not aligning to center

Question by Mj1992

Several times I get this problem.Whenever I try to center something using margin:0 auto.
Sometimes i succeed and sometimes not. So my questions are.

  1. Why the #PostWrapper in the below example is not getting centered inside the innerWrapper.
  2. When does margin:0 auto works and when it doesn’t.What are the causes.

CSS:

#container #Post{

    background:#FFFFFF;
    border-radius:10px;
    margin-top:20px;
    overflow:auto;
}

#container #Post #InnerWrapper{
        margin:10px;
}

#container #Post #InnerWrapper #SubjectWrapper{
    overflow:auto;
}

#container #Post #InnerWrapper #SubjectWrapper #SubjectText{
    font:30px "Palatino Linotype", "Book Antiqua", Palatino, serif;
    font-style:italic;
    font-weight:bold;
    float:left;
}

#container #Post #InnerWrapper #SubjectWrapper #SubjectBox{
        float:left;
        margin-left:2px;
}

#container #Post #InnerWrapper #PostWrapper{
     margin:0 auto;
     border:3px solid #000;
     display:inline-block;
}

#container #Post #InnerWrapper #PostWrapper #PostText{
     font:30px "Palatino Linotype", "Book Antiqua", Palatino, serif;
     font-style:italic;
     font-weight:bold;
}

#container #Post #InnerWrapper #PostWrapper #PostBox{
}

HTML:

    <div id="Post">
     <div id="InnerWrapper">
    <div id="SubjectWrapper">
           <div id="SubjectText">Subject:</div>
               <div id="SubjectBox"><input type="text" class="text_box" /></div>
           </div>

        <div id="PostWrapper">
           <div id="PostText"><?php if($PageType=='and'){ echo 'Add new Deal:';}else{ echo 'Edit Company History:';}?></div>

           <div id="PostBox"><textarea rows="20" cols="103" id="PostEditor" /></div>
       </div>
    </div>

Answer by Shomz

In short: It depends on the position, width and display attributes of elements.
Try putting position: relative; to them and also set their width.

Child divs always have a 100% width which makes centering useless, so defining width and position makes use of it. Also, you can’t use display: inline-block, but display: block.

EDIT

Here is the code sample of your div using margin: auto: http://jsfiddle.net/vnAvk/

And here is with the inside elements also centerer (I think that’s what you’re after): http://jsfiddle.net/vnAvk/1/

And here’s with the whole thing centered: http://jsfiddle.net/vnAvk/2/

Answer by Starx

The problem is ambiguous selector, the selector chain you provided is invalid. Just use

#PostWrapper{
     margin:0 auto;
     border:3px solid #000;
     display:inline-block;
}

Demo

Read more

Parsing PHP Multidimensional Array

Question by avinash shah

Here (given below) is some very simple php parsing multidimensional array stuff I am doing. I am just searching for ‘highlighting’ key and then storing some key value pairs in another array. Is there any better way to achieve this (I mean with respect to performance), rather than have n foreach loops to get to what you want.

$json_O=json_decode(file_get_contents($url),true);
     foreach($json_O as $section1=>$items1){
        if($section1==highlighting){
            foreach($items1 as $section2=>$items2){
                    $key=$section2;
                    foreach($items2 as $section3=>$items3){
                        foreach ($items3 as $section4=>$items4){
                            $value=$items4;
                            $found[]=array('Key' => $key, 'Value' => $value);

Here is a sample php object I am trying to parse:

Array
(
    [responseHeader] => Array
        (
            [status] => 0
            [QTime] => 3
            [params] => Array
                (
                    [indent] => on
                    [start] => 0
                    [q] => russian
                    [fragsize] => 40
                    [hl.fl] => Data
                    [wt] => json
                    [hl] => on
                    [rows] => 8
                )

        )

    [response] => Array
        (
            [numFound] => 71199
            [start] => 0
            [docs] => Array
......
......
    [highlighting] => Array
        (
            [114360] => Array
                (
                    [Data] => Array
                        (
                            [0] => AMEki has done it better <em>russian</em>...

....
....

Two things now: 1)Can I do it quicker? 2)Can I design it better?

Answer by rambo coder

this seems unneccesary

 foreach($json_O as $section1=>$items1){
    if($section1==highlighting){
        foreach($items1 as $section2=>$items2){

you could simply do

        foreach($json_O['highlighting'] as $section2=>$items2){

simplifying the rest is also possible, although this is untested

$riter = new RecursiveArrayIterator($json_O['highlighting']);
$riteriter = new RecursiveIteratorIterator($riter, RecursiveIteratorIterator::LEAVES_ONLY);
$found = array();
foreach ($riteriter as $key => $value) {
    $key = $riteriter->getSubIterator($riteriter->getDepth() - 2)->key();
    $found[] = compact('key', 'value');
}

personally, I would just use the nested foreach loops though. It’s very easy to understand, while my creative use of recursive iterators is not.

Answer by Starx

Use foreach when you need to get to each and every item. If you want only highlighting, then just access it directly.

$higlighting = $json_0['highlighting'];
foreach($highlightis as $Key => $value) {
 //....
}
Read more

run/pause CSS animation with jQuery

Question by Ampersand

I would like to start with a paused CSS animation then use jQuery to run the animation for a second before pausing again.

The css is below:

#animation {
  -webkit-animation: one 5s infinite;
  -webkit-animation-play-state: paused;
}

@-webkit-keyframes one {
  0% { .... }
  .....
  100% { .... }
}

It has some complicated keyframes and the aim is that it would play for 1 second to the 20% position then stop.

I tried the jQuery below but it didn’t work:

 $("#click").click(function(){
     $("#animation").css("-webkit-animation-play-state", "running").delay(1000).css("-webkit-animation-play-state", "paused");          
 });

(#click is the div I want to use as the trigger for the animation)

If I remove the delay and subsequent pause it works fine but obviously continues looping.

eg:

 $("#click").click(function(){
     $("#animation").css("-webkit-animation-play-state", "running");            
 });

What would you fine people suggest?

Answer by Starx

jQuery delay() does not function when you are manipulating the css property. Use setTimeOut() instead

$("#click").click(function(){
     $("#animation").css("-webkit-animation-play-state", "running");
     setTimeout(function() { 
       $("#animation").css("-webkit-animation-play-state", "paused");
     }, 1000);
});
Read more
...

Please fill the form - I will response as fast as I can!