2

I want to add a class to an object when I click on an div with the class "arrow right" or "arrow left". On http://jsfiddle.net/ does it work perfect. But on my Site it doesn't work :(

Can anyone help me?

jQuery:

var currentPage = 0;
var lastPage = ($(".post-preview > div").length)-1;
currentPage = $('.post-preview > div.show').attr('id');

$('.news > .right').stop().click(function() {
    if (currentPage == lastPage) {
            $('.post-preview > div#' + lastPage).hide();
            $('.post-preview > div#' + lastPage).removeClass('show');

        $('.post-preview > div#0').fadeIn(300);
        $('.post-preview > div#0').addClass('show');
        currentPage = 0;
    } else {
        $('.post-preview > div#'+currentPage).hide();
        $('.post-preview > div#'+currentPage).removeClass('show');
        currentPage++;
        var nextPage = currentPage;
        currentPage--;
        $('.post-preview > div#'+nextPage).fadeIn(300);
        $('.post-preview > div#'+nextPage).addClass('show');
        currentPage = nextPage;
    }
 });

 $('.news > .left').stop().click(function() {
     if (currentPage == 0) {
        $('.post-preview > div#0').hide();
        $('.post-preview > div#0').removeClass('show');

        $('.post-preview > div#' + lastPage).fadeIn(300);
        $('.post-preview > div#' + lastPage).addClass('show');
        currentPage = lastPage;
    } else {
        $('.post-preview > div#'+currentPage).hide();
        $('.rpost-preview > div#'+currentPage).removeClass('show');
        currentPage--;
        var nextPage = currentPage;
        currentPage++;
        $('.post-preview > div#'+nextPage).fadeIn(300);
        $('.post-preview > div#'+nextPage).addClass('show');
        currentPage = nextPage;
    }
});

CSS for show class:

.news > .post-preview > div.show    { display: inline-block !important; }

My HTML Code:

<div class="news">
<div class="arrow left"></div>
    <div class="post-preview">
        <div id="0" class='show'></div>
        <div id="1"></div>
        <div id="2"></div>

    </div>
<div class="arrow right"></div>
</div>
DerFuchs10
  • 135
  • 1
  • 2
  • 12
  • Did you import jQuery properly ? Did you put the script at the end of the body ? – Denys Séguret Feb 05 '13 at 14:12
  • 2
    You are likely executing the JavaScript too early, i.e. before the DOM is ready. Please read the [**jQuery tutorial**](http://docs.jquery.com/Tutorials:Getting_Started_with_jQuery), it tells you exactly how to setup jQuery. In order to help you or give a better suggestion, we really have to know what "it does not work" means. What is the behaviour you see and which behaviour do you expect? – Felix Kling Feb 05 '13 at 14:12
  • 3
    If you have a jsfiddle, you should better show a link to your code, not to jsfiddle home page. – Viktor S. Feb 05 '13 at 14:13
  • Just curious, but you do have your jQuery being fired on a `window.load` event, right? The DOM may not be built at time of script execution. – user17753 Feb 05 '13 at 14:14
  • 1
    You should be caching the return of your jquery selectors, not reselecting over and over on the same element. – jbabey Feb 05 '13 at 14:14
  • 1
    That logic of the ++ followed by the -- makes no sense. – epascarello Feb 05 '13 at 14:16
  • Does everything else works? How do you know that addClass does not work? What do you mean saying "it does not works"? – Viktor S. Feb 05 '13 at 14:19
  • I mean that the class "show" doesn't add to objects or remove from an object. – DerFuchs10 Feb 05 '13 at 14:38
  • "That logic of the ++ followed by the -- makes no sense." Yes, makes sense, because after the ++ I declare the variable nextPage. – DerFuchs10 Feb 05 '13 at 14:40
  • 1
    Here my jsfiddle link: http://jsfiddle.net/mD3sy/ – DerFuchs10 Feb 05 '13 at 14:51

1 Answers1

5

You are trying to access an element that probably does not exist at the time of the execution. This is why it doesn't work.

You need to wrap your code inside a $(function() { /* put code here */ } ); block.

The reason why it works on jsfiddle is because the site does it for you as convenience.

** Edit **

In JavaScript, it is a good (if not best) practice to enclose your code inside it's own context. Take a look at the jQuery, jQuery UI and many JavaScript widgets and libraries. For example :

(function($) {    // receive $ as parameter; a jQuery instance

    /* place code here

})(jQuery);   // invoke the function above with this instance of jQuery

The reason for this is

  1. If you need to use a different version of jQuery, or are using a library that overrides the $ variable, this function above will not get affected by the changes
  2. Every variables declared (ie. var x = "foo";) will not be available outside the function, so you are certain that you are not polluting the window (global) namespace and have the right value when you need it. (Expose a global object if you need access to something outside the function (Ex: window.someVar = localVar;)

However, the above function will get executed as it is loaded by the browser, and might get executed before any DOM element is inserted into the DOM tree. This can be a problem for scripts setting up event listeners and such. Thus, if you need the function to be executed only when the DOM element is completely loaded and ready to be used, enclose your code inside a jQuery onload callback :

jQuery(function() {

    /* place code here */

});

or even

(function($) {
    // executed right now

    $(function() {
        // executed only when the DOM is ready

        /* place code here */

    });

})(jQuery);

** Update **

After reading your code a little further, I can only see (as commented) some odd things.

  1. Your IDs are numeric. From the HTML specification,

    ID and NAME tokens must begin with a letter ([A-Za-z]) and may be followed by any number of letters, digits ([0-9]), hyphens ("-"), underscores ("_"), colons (":"), and periods (".").

    So you should a an id prefix... or base your selection on element indexes

  2. You can chain your queries instead of reparsing them all the time.

For example

jQuery(function() {

var firstPage = $(".post-preview > div:first").index(); // index of the first page
var lastPage = $(".post-preview > div:last").index(); // index of the last page
var currentPage = $('.post-preview > div.show').index() || firstPage;  // default to 0

$('.news > .right').stop().click(function() {
    if (currentPage == lastPage) {
        currentPage = $('.post-preview > div:eq(' + lastPage + ')')
           .hide()
           .removeClass('show')
           .siblings('div:first')  // first DIV
           .fadeIn(300)
           .addClass('show')
           .index();  // should be 0... but we never know
    } else {
        // note : will receive the next element index
        currentPage = $('.post-preview > div:eq(' + currentPage + ')')
           .hide()
           .removeClass('show')
           .next('div')             // get next DIV element
           .fadeIn(300)
           .addClass('show')
           .index();
    }
 });

 $('.news > .left').stop().click(function() {
     if (currentPage == firstPage) {
        currentPage = $('.post-preview > div:eq(' + currentPage + ')')
           .hide()
           .removeClass('show')
           .siblings('div:last')  // last DIV
           .fadeIn(300)
           .addClass('show')
           .index();
    } else {
        currentPage = $('.post-preview > div:eq(' + currentPage + ')')
           .hide()
           .removeClass('show')
           .prev('div')
           .fadeIn(300)
           .addClass('show')
           .index();
    }
});

});

And your HTML (no need for IDs anymore)

<div class="news">
<div class="arrow left"></div>
    <div class="post-preview">
        <div class='show'>Preview 1</div>
        <div>Preview 2</div>
        <div>Preview 3</div>
    </div>
</div>
</div>
Community
  • 1
  • 1
Yanick Rochon
  • 45,203
  • 21
  • 112
  • 182