views:

256

answers:

2

Hi everyone, I am trying to achieve this task using MooTools.

Description:

I attached an event listener to myButton link. A click on this link initiates an AJAX request and updates myDiv content based on the response text.

During this request a POST variable is being sent to "button.php", but it's not used at the moment..
(i wish to use it later)

OK, as a result, myDiv gets exactly the same link with the same ID (myButton) + a random number, so that we could see that each click generates a new number.

The problem:

After the first click on myButton, myDiv updates correctly, showing a random number. When I click myButton for the second time (this time in newly updated div), the div does not refresh anymore.

Please note that I need myButton to be inside myDiv, and myDiv must be updated (refreshed) after each click without having to refresh the entire page.

Can somebody show me how to achieve this task based on this simplified code example?


index.html

<html>
<head>
<script type="text/javascript" src="mootools-1.2.4-core-nc.js"></script>
<script>
window.addEvent('domready', function() {
  $('myButton').addEvent('click', function(e) {
    e.stop();
    var myRequest = new Request({
      method: 'post',
      url: 'button.php',
      data: {
        action : 'test'
      },
      onRequest: function() {
        $('myDiv').innerHTML = '<img src="images/loading.gif" />';
      },
      onComplete: function(response) {
        $('myDiv').innerHTML = response;
      }
    });
    myRequest.send();
    $('myButton').removeEvent('click');
  });
});
</script>
</head>
<body>
  <div id="myDiv">
    <a id="myButton" href="#">Button</a>
  </div>
</body>
</html>

button.php

<a id="myButton" href="#">Button</a> clicked <?php echo rand(1,100); ?>

+1  A: 

you are attaching an event to an element that you are replacing. the dom has no way of knowing that to you, the old and the new button are identical. The old button is deleted (and the event listener with it) and the new button created. So you need to re-attach the event to the new button.

That said: why does the button have to be inside the div? The mind boggles. You can always update the button text from javascript, there's no need to replace it and keep creating new listener objects.

seanizer
if you just want the loading thingy to display, add a div that contains the loading image and toggle it's visibility
seanizer
MooTools seems to have something kind-of like jQuery "delegate".
Pointy
I wish the button to be inside the div, because I need to place more buttons into this div for specific goals. The buttons will be called for ex. "Add", "Edit", "Remove". And each of them will load specific functionality into this div.
I would still do that programmatically through javascript. Keep a hash table of buttons. hide, create and show them dynamically. That way event listeners can be re-used.
seanizer
+2  A: 

Look at Element.Delegation to setup the event on the myDiv container one time, so you don't have to re-attach handlers each time the contents are updated. You need to include this MooTools-More extension in your scripts as it's not part of core yet, but will be starting from version 1.3.

$("myDiv").addEvent("click:relay(a)", function() {
    ...
);

If you have multiple <a> links inside, and you only want to delegate a specific subset of those, add a class or some other property to distinguish them. You can use almost any selector inside relay(..). Let's say all links had a class updateTrigger added to them:

<a class="updateTrigger" id="myButton" href="#">Button</a>

the syntax would then be:

$("myDiv").addEvent("click:relay(a.updateTrigger)", function() {
    ...
});

See this working example where links are replaced every 5 seconds. There is only one event setup on the myDiv container and it handles all clicks to all <a>s, even the dynamic ones.

Anurag
It works perfectly. Thank you very much!