0

I'm new with Ajax calls and now I'm facing a situation really confusing.

I have a script that I got from Tympanus Codrops which is the main structure of my website. On this script, for every page change, it calls a new JSON file. So I have a four page website, meaning that for every new section, the content is called from inside JSON file.

Below is the App.js file from this script:

/*    
      jQuery Setup                                                           
************************************************************************/ 
jQuery.ajaxSetup({
  cache: false
})

/*    
      ArticleAnimator Object                                                           
************************************************************************/ 
var ArticleAnimator = ArticleAnimator || {
  canScroll:          true,
  initialLoad:        false,
  animationDuration:  500,
  postCount:          4,
  currentPostIndex:   1,
  postCache:          {},
  pageTemplate:       null,
};

ArticleAnimator.load = function(){
  this.currentPostIndex = getURLIndex();
  this.makeSelections();

  $body.append( this.$current )
  $body.append( this.$next )

  var self = this;
  this.createPost({ type: 'current' }, function(){
    self.createPost({ type: 'next' }, function(){

      /* Selections. */
      self.refreshCurrentAndNextSelection();

      /* Push initial on to stack */
      history.pushState(pageState(), "", "#" + self.currentPostIndex)

      /* Bind to some events. */
      self.bindGotoNextClick();
      self.bindPopstate();
      self.bindWindowScroll();
    })
  })
}

ArticleAnimator.makeSelections = function(){
  this.$page         = $('.page');
  this.pageTemplate  = elementToTemplate( this.$page.clone() );
  this.$current      = this.currentElementClone();
  this.$next         = this.nextElementClone();
}

ArticleAnimator.getPost = function(index, callback){
  callback = callback || $.noop;

  if ( this.postCache[index] ){
    callback( this.postCache[index] );
    return;
  }

  var self = this;
  $.getJSON('data/post'+ index +'.json', function(d){
    self.postCache[index] = d;
    callback(d)
  });
} 

ArticleAnimator.nextPostIndex = function(index){
  return (index === this.postCount) ? 1 : index + 1 
}

ArticleAnimator.createPost = function(opts, callback){
  opts      = opts || {};
  var self  = this;
  var type  = opts['type'] || 'next';

  if ( opts['fromTemplate'] ){
    $body.append( this.nextElementClone() );
    this['$' + type] = $('.' + type)
  }

  var index = (type == 'next') ? this.nextPostIndex( this.currentPostIndex) : this.currentPostIndex;
  this.getPost(index, function(d){
    self.contentizeElement(self['$' + type], d);
    callback && callback();
  });

}

ArticleAnimator.contentizeElement = function($el, d){
  $el.find('.big-image').css({ backgroundImage: "url(" + d.image + ")" });
  $el.find('h1.title').html(d.title);
  $el.find('h2.description').html(d.title_secondary);
  $el.find('.content .text').html(d.content);
  $el.find('.content .text2').html(d.contentb);
  $el.find('.content .text').css({ width: d.contentcss1 });
  $el.find('.content .text2').css({ display: d.contentcss3 });
  $el.find('h3.byline time').html(d.date);
  $el.find('h3.byline .author').html(d.author);
}

ArticleAnimator.animatePage = function(callback){
  var self              = this;
  var translationValue  = this.$next.get(0).getBoundingClientRect().top;
  this.canScroll        = false;

  this.$current.addClass('fade-up-out');

  this.$next.removeClass('content-hidden next')
       .addClass('easing-upward')
       .css({ "transform": "translate3d(0, -"+ translationValue +"px, 0)" });

  setTimeout(function(){
      scrollTop();
      self.$next.removeClass('easing-upward')
      self.$current.remove();

      self.$next.css({ "transform": "" });
      self.$current = self.$next.addClass('current');

      self.canScroll = true;
      self.currentPostIndex = self.nextPostIndex( self.currentPostIndex );

      callback();
  }, self.animationDuration );
}

ArticleAnimator.bindGotoNextClick = function(){
  var self  = this;
  var e     = 'ontouchstart' in window ? 'touchstart' : 'click';

  this.$next.find('.big-image').on(e, function(e){
    e.preventDefault();
    $(this).unbind(e);

    self.animatePage(function(){
      self.createPost({ fromTemplate: true, type: 'next' });
      self.bindGotoNextClick();
      history.pushState( pageState(), '', "#" + self.currentPostIndex);
    });
  });
}

ArticleAnimator.bindPopstate = function(){
  var self = this;
  $window.on('popstate', function(e){
    if( !history.state || self.initialLoad ){
      self.initialLoad = false;
      return;
    }
    self.currentPostIndex = history.state.index;
    self.$current.replaceWith( history.state.current );
    self.$next.replaceWith( history.state.next );

    self.refreshCurrentAndNextSelection();
    self.createPost({ type: 'next' });
    self.bindGotoNextClick();

  });
}

ArticleAnimator.bindWindowScroll = function(){
  var self = this;
  $window.on('mousewheel', function(ev){
    if ( !self.canScroll ) 
      ev.preventDefault()
  })
}

ArticleAnimator.refreshCurrentAndNextSelection = function(){
  this.$current      = $('.page.current');
  this.$next         = $('.page.next');
}

ArticleAnimator.nextElementClone = function(){
  return this.$page.clone().removeClass('hidden').addClass('next content-hidden');
}

ArticleAnimator.currentElementClone = function(){
  return this.$page.clone().removeClass('hidden').addClass('current');
}

/*    
      Helper Functions.                                                      
************************************************************************/ 
function elementToTemplate($element){
  return $element.get(0).outerHTML;
}

function scrollTop(){
  $body.add($html).scrollTop(0);
}

function pageState(){
  return { index: ArticleAnimator.currentPostIndex, current: elementToTemplate(ArticleAnimator.$current), next: elementToTemplate(ArticleAnimator.$next) }
}

function getURLIndex(){
  return parseInt( (history.state && history.state.index) ||window.location.hash.replace('#', "") || ArticleAnimator.currentPostIndex );
}


/*    
      Document ready.                                                         
************************************************************************/ 
$(document).ready(function(){

  /* A couple of selections. */
  $body         = $(document.body);
  $window       = $(window);
  $html         = $(document.documentElement);

  /* Let's get it started. */
  ArticleAnimator.load();

})



In the main page (index.html), I have a document.ready function that delegates a click function to an specific object inside one of my JSON files called from the script above. This click function uses an Ajax request to send emails, as shown below:

$(document).ready(function() {

   $(".content").delegate("#enviadepo","click",function() {
     var form = $('.depoform');
     $.ajax({
        async: false,
        url: "maildepo.php?ajax=true",
        cache: false,
        type: "post",
        data: form.serialize(),
        success: function(response){
           response = $.trim( response );
           if ( response == "success" ) {
            $('.depoform #nome').val("");
            $('.depoform #msg').val("");
           }
        }
      });
      return false;
   });

});



After implement this function at document.ready, the Ajax request to send emails only works when I refresh the page with CTRL+SHIFT+R with the JSON file already called and which contains the object mentioned on the click function.

So if I'm in the first or second JSON file, for example, and tries to reach the third JSON (which contains the object mentioned in the click function), it doesn't work at all..

The same situation happens when I refresh the page on the correct JSON file, deliver the message successfully, goes to next JSON file, returns to the previous file and attempt to hit again the "Send message" button.

I really get confused at this part. I don't know if I have to register the object called from JSON file as a Global object (in some way can I do that?) or if this issue has to solved on the main script mentioned above as the main structure JS.

I tried to put the click function inside the callback on the main script but nothing happens. The only certainty I have is that the click function works if I refresh the page inside the JSON file which contains the object pointed on delegation.

Some enlightenment?

Thanks in advance!

  • 1
    Are you getting any javascript errors in your console? Is it just that `$('.depoform')` doesn't exists during the times the button doesn't work (if so you could simply check for it, and if it's not there do a `setTimeout` to retrigger the click)? What version of jQuery are you using (`.delegate` should be `.on` in 1.7+)? What is `$messages`? and is it a global object? – Adam Merrifield Jun 09 '14 at 04:38
  • Hey Adam! I'm not getting any errors on console. I tried to put console.log to show on success and error after Ajax callback but nothing.. I'm using jQuery version 1.10.2. $messages var is a mistake, I already changed it. I created another $var to try noConflict.. I'll test your tip retriggering the click function. Thanks! – Igor Franco Jun 09 '14 at 13:55
  • Can you also try changing `#enviadepo` to `.enviadepo`? The problem may be that ID's must be unique. As in you can't have 2 `#enviadepo`. – Adam Merrifield Jun 09 '14 at 14:34
  • Adam, thanks so much for your help. Looking for trigger function here in Stack I found out this [article](http://stackoverflow.com/questions/13767919/jquery-event-wont-fire-after-ajax-call). I made a function of the click function using `on` instead of `delegate` as you told me. Put this function before the JSON callback and before the PopState. Works pretty fine! – Igor Franco Jun 09 '14 at 15:08
  • You're welcome! I've added an answer for you to accept so that we can close this question. – Adam Merrifield Jun 09 '14 at 16:04

1 Answers1

0

This question has been answered in the comments of the question itself. The answer was found by the following:

  • Changing the .delegate to .on and referencing to this SO answer
  • Placing/running the new .on function before the JSON callback
Adam Merrifield
  • 10,307
  • 4
  • 41
  • 58