SitePoint Sponsor

User Tag List

Results 1 to 16 of 16
  1. #1
    SitePoint Member
    Join Date
    May 2013
    Posts
    6
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    How to trigger animation after user scroll to N points - jQuery waypoints with multip

    I need your help!

    Basic idea: I want when user scroll to one point (in the middle of the pages - let say it's 500px from top) then we have some animation, of course I won't ask how to do all the animation stuff, but I will need you to give me the basic idea about the callback

    Callbacks that I mean: after 1st animation, we get 2nd animation, then 3rd animation. How I approach this?

    SCENARIO:

    Let say we have 4 boxes, and they have color red, blue, orange and pink.
    After user scrolled to 500px from top - I want first red box fadein
    2 seconds from that, I want the red box fadeOut, and blue box will fadein.
    in my original idea, I will need them to rotate or some other animation - if you could do this too it will be great , please ignore this point if you think I'm asking too much
    TOOLS:

    jQuery waypoints http://imakewebthings.com/jquery-waypoints/
    maybe jQuery transit ? http://ricostacruz.com/jquery.transit/
    +1 for the right solutions, as I always appreciate all solutions, I will vote it up if it's works

    Thanks!

  2. #2
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,858
    Mentioned
    206 Post(s)
    Tagged
    12 Thread(s)
    Hi there,

    Welcome to the forums

    The first thing you need to do is to detect when the user has scrolled past a certain point. that's easy:

    Code JavaScript:
    $(window).on("scroll", function(){
      if($("body").scrollTop() === 500){
        $(window).off("scroll");
        // Do some stuff here ..
      }
    }

    This line:

    Code JavaScript:
    $(window).off("scroll");

    removes the scroll event handler, as I am assuming you only want this to fire once.

    Displaying the boxes is also relatively easy.
    If I was you I would create the boxes on your page, then hide them using CSS.
    Then once you have reached the correct scroll point, you can fade them in one after another, using setTimeout and by passing a callback to the fadeIn function.

    Code JavaScript:
    $(selector).fadeIn('slow', function() {
      // Animation complete
    });

    Something like this should work:

    Code:
    <!DOCTYPE HTML>
    <html>
      <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>Callback hell!</title>
        <script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
        <style>
          body{height:3000px;}
          #box1{display:none; width:200px; height:200px; background:red; position: fixed; top:0; right: 0;}
          #box2{display:none; width:200px; height:200px; background:blue; position: fixed; top:0; right: 0;}
          #box3{display:none; width:200px; height:200px; background:orange; position: fixed; top:0; right: 0;}
          #box4{display:none; width:200px; height:200px; background:pink; position: fixed; top:0; right: 0;}
        </style>
      </head>
      
      <body>
        <h1>Some heading</h1>
        <p>Some content</p>
        <div id="box1"></div>
        <div id="box2"></div>
        <div id="box3"></div>
        <div id="box4"></div>
        <script>
          $(window).on("scroll", function(){
            if($("body").scrollTop() === 500){
              $(window).off("scroll");
              $("#box1").fadeIn('slow', function(){
                setTimeout(function(){
                  $("#box1").fadeOut('slow');
                  $("#box2").fadeIn('slow');
                  setTimeout(function(){
                    $("#box2").fadeOut('slow');
                    $("#box3").fadeIn('slow');
                    setTimeout(function(){
                      $("#box3").fadeOut('slow');
                      $("#box4").fadeIn('slow');
                    }, 2000)
                  }, 2000)
                }, 2000);
              });
            };
          });
        </script>
      </body>
    </html>
    I didn't make the biggest effort with the boxes, as I'm not sure what kind of effect you are trying to achieve.
    Also, if you need any more callbacks than this, I would start looking for a more elegant solution, as nested callbacks are nasty!

    Nonetheless, this will hopefully give you something to go on.

  3. #3
    The CSS Clinic is open silver trophybronze trophy
    Paul O'B's Avatar
    Join Date
    Jan 2003
    Location
    Hampshire UK
    Posts
    40,269
    Mentioned
    179 Post(s)
    Tagged
    6 Thread(s)
    Quote Originally Posted by Pullo View Post

    Something like this should work:
    Forgive the question from a beginner with jquery but doesn't Firefox need $("html").scrollTop() as it registers only zero for $("body").scrollTop()? At least that was the problem I ran into recently and had to use something like:
    Code:
     var theTop = $('html').scrollTop();
        if (theTop == 0) {
            var theTop = $('body').scrollTop();
        }
    I also think that Firefox won't recognise 500 as it seems to jump over it and you may need to say greater than. Of course I may be out of my depth here and doing it all wrong

  4. #4
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,858
    Mentioned
    206 Post(s)
    Tagged
    12 Thread(s)
    Hey Paul,

    Oh my goodness, you are right on both accounts. What can I say? My shame knows no bounds

    Quote Originally Posted by Paul O'B View Post
    doesn't Firefox need $("html").scrollTop() as it registers only zero for $("body").scrollTop()?
    Yup. I did have a little snippet to address this which I found online (I can't remember where, but I didn't write it).

    Code JavaScript:
    function getScrollTop(){
      if(typeof pageYOffset!= 'undefined'){
        return pageYOffset;  // Most browsers
      } else{
        var b = document.body; //IE 'quirks'
        var d = document.documentElement; //IE with doctype
        d = (d.clientHeight)? d : b;
        return d.scrollTop;
      }
    }

    Quote Originally Posted by Paul O'B View Post
    I also think that Firefox won't recognise 500 as it seems to jump over it and you may need to say greater than.
    Yes indeed. Good catch!

    Of course I may be out of my depth here and doing it all wrong
    No comment

    Here's the updated code:

    Code:
    <!DOCTYPE HTML>
    <html>
      <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>Callback hell!</title>
        <script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
        <style>
          body{height:3000px;}
          #box1{display:none; width:200px; height:200px; background:red; position: fixed; top:0; right: 0;}
          #box2{display:none; width:200px; height:200px; background:blue; position: fixed; top:0; right: 0;}
          #box3{display:none; width:200px; height:200px; background:orange; position: fixed; top:0; right: 0;}
          #box4{display:none; width:200px; height:200px; background:pink; position: fixed; top:0; right: 0;}
        </style>
      </head>
      
      <body>
        <h1>Some heading</h1>
        <p>Some content</p>
        <div id="box1"></div>
        <div id="box2"></div>
        <div id="box3"></div>
        <div id="box4"></div>
        <script>
          function getScrollTop(){
            if(typeof pageYOffset!= 'undefined'){
              return pageYOffset;
            }
            else{
              var b = document.body; //IE 'quirks'
              var d = document.documentElement; //IE with doctype
              d = (d.clientHeight)? d : b;
              return d.scrollTop;
            }
          }    
              
          $(window).on("scroll", function(){
            if(getScrollTop() >= 500){
              $(window).off("scroll");
              $("#box1").fadeIn('slow', function(){
                setTimeout(function(){
                  $("#box1").fadeOut('slow');
                  $("#box2").fadeIn('slow');
                  setTimeout(function(){
                    $("#box2").fadeOut('slow');
                    $("#box3").fadeIn('slow');
                    setTimeout(function(){
                      $("#box3").fadeOut('slow');
                      $("#box4").fadeIn('slow');
                    }, 2000)
                  }, 2000)
                }, 2000);
              });
            };
          });
        </script>
      </body>
    </html>

  5. #5
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,858
    Mentioned
    206 Post(s)
    Tagged
    12 Thread(s)
    I found where I got the snippet from: http://stackoverflow.com/questions/8...browser-window

  6. #6
    The CSS Clinic is open silver trophybronze trophy
    Paul O'B's Avatar
    Join Date
    Jan 2003
    Location
    Hampshire UK
    Posts
    40,269
    Mentioned
    179 Post(s)
    Tagged
    6 Thread(s)
    Quote Originally Posted by Pullo View Post
    Hey Paul,

    Oh my goodness, you are right on both accounts. What can I say? My shame knows no bounds
    lol - no worries - it was just a lucky guess on my part.

    Thanks for the scrolltop snippet I'll keep that safe somewhere

  7. #7
    SitePoint Member
    Join Date
    May 2013
    Posts
    6
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Oh man, thank you very much for the code, I think I should try it first.
    Is it the best practices using a lot of nested code? Because in my plan, I will do around 5-8 animations, so if nested all of them, I'm afraid maybe it's not good?

    I know it should works, but is there any better way?
    Found this on stackoverflow here, the very first answer (voted)
    Could you help me to understand this code?

    I'm totally new in jQuery. sorry

  8. #8
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,858
    Mentioned
    206 Post(s)
    Tagged
    12 Thread(s)
    Hi,

    Quote Originally Posted by boedi7 View Post
    Is it the best practices using a lot of nested code? Because in my plan, I will do around 5-8 animations, so if nested all of them, I'm afraid maybe it's not good?
    There's nothing wrong with it, other than it is a nightmare to read, maintain and keep track of what is happening where.
    Apart from that, nested callbacks are great

    Quote Originally Posted by boedi7 View Post
    Found this on stackoverflow here, the very first answer (voted)
    Could you help me to understand this code?
    That's much nicer.

    What that code does, is use jQuery's implementation of the JavaScript Promise Pattern.

    This might be a bit tricky to get your head round if you are new to JavaScript, but a Promise is an object that represents a one-time event, typically the outcome of an async task like an AJAX call, or as in this case, an animation. You can attach callbacks to the Promise, which will fire when the Promise is resolved or rejected (i.e. when the operation completes or fails). This allows you to write clearer, shorter callbacks.

    If you're interested in finding out more, read this: http://net.tutsplus.com/tutorials/ja...uery-promises/

    Anyway, I've updated the code:

    Code:
    <!DOCTYPE HTML>
    <html>
      <head>
        <!--http://www.sitepoint.com/forums/showthread.php?1052208-How-to-trigger-animation-after-user-scroll-to-N-points-jQuery-waypoints-with-multip-->
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>Callback hell!</title>
        <script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
        <style>
          body{height:3000px;}
          #box1{display:none; width:200px; height:200px; background:red; position: fixed; top:0; right: 0;}
          #box2{display:none; width:200px; height:200px; background:blue; position: fixed; top:0; right: 0;}
          #box3{display:none; width:200px; height:200px; background:orange; position: fixed; top:0; right: 0;}
          #box4{display:none; width:200px; height:200px; background:pink; position: fixed; top:0; right: 0;}
        </style>
      </head>
      
      <body>
        <h1>Some heading</h1>
        <p>Some content</p>
        <div id="box1"></div>
        <div id="box2"></div>
        <div id="box3"></div>
        <div id="box4"></div>
        <script>
          $.chain = function() {
            var promise = $.Deferred().resolve().promise();
            jQuery.each( arguments, function() {
              promise = promise.pipe( this );
            });
            return promise;
          };  
            
          function scrollTop(){
            if(typeof pageYOffset!= 'undefined'){
              return pageYOffset;
            }
            else{
              var b = document.body; //IE 'quirks'
              var d = document.documentElement; //IE with doctype
              d = (d.clientHeight)? d : b;
              return d.scrollTop;
            }
          }    
              
          $(window).on("scroll", function(){
            if(scrollTop() >= 500){
            $(window).off("scroll");
              var animations = $.chain(function() {
                return $('#box1').fadeIn('slow').delay(2000).fadeOut('slow');
              }, function() {
                return $('#box2').fadeIn('slow').delay(2000).fadeOut('slow');
              }, function() {
                return $('#box3').fadeIn('slow').delay(2000).fadeOut('slow');
              }, function() {
                return $('#box4').fadeIn('slow');
              });
            };
          });
        </script>
      </body>
    </html>
    I'm sure you'll agree, that's a lot more readable.

  9. #9
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,858
    Mentioned
    206 Post(s)
    Tagged
    12 Thread(s)
    Just looking at the code from SO and realized that deferred.pipe() is deprecated as of jQuery 1.8.

    It might be a better idea to use deferred.then() instead:

    Code JavaScript:
    promise = promise.then(this);

  10. #10
    SitePoint Member
    Join Date
    May 2013
    Posts
    6
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi, thanks for you help
    will try to implement it

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

  11. #11
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,858
    Mentioned
    206 Post(s)
    Tagged
    12 Thread(s)
    Quote Originally Posted by boedi7 View Post
    Hi, thanks for you help. I will try to implement it but what is
    Code JavaScript:
    $.chain = function() {
    var promise = $.Deferred().resolve().promise();
    jQuery.each( arguments, function() {
    promise = promise.pipe( this );
    });
    return promise;
    };
    ?
    Maybe it'll help to remove the $.chain function for a minute.

    Another way of writing the same thing without this function would be:

    Code JavaScript:
    $('#box1').fadeIn('slow').delay(2000).fadeOut('slow').promise()
    .then(function(){ return $('#box2').fadeIn('slow').delay(2000).fadeOut('slow'); })
    .then(function(){ return $('#box3').fadeIn('slow').delay(2000).fadeOut('slow'); })
    .then(function(){ return $('#box4').fadeIn('slow'); });

    What we are doing here is selecting the <div> element with an id of "box1", fading it in, waiting two seconds then fading it out:

    Code JavaScript:
    $('#box1').fadeIn('slow').delay(2000).fadeOut('slow')

    Then we are using the promise() method to return a dynamically generated Promise that is resolved as soon as the fadeOut is complete.

    Code JavaScript:
    $('#box1').fadeIn('slow').delay(2000).fadeOut('slow').promise()

    We then use the .then() method to add more handlers to be called once the Promise has been resolved (immediately in this case).

    This means that the animations are carried out one after the other without the need for deeply nested callbacks we saw earlier.

    The $.chain() function from the SO post was just a means to tidy this code up a little further.

    Using this function, the code would become:

    Code JavaScript:
    $.chain(
      function(){ return $('#box1').fadeIn('slow').delay(2000).fadeOut('slow'); },
      function(){ return $('#box2').fadeIn('slow').delay(2000).fadeOut('slow'); },
      function(){ return $('#box3').fadeIn('slow').delay(2000).fadeOut('slow'); },
      function(){ return $('#box4').fadeIn('slow'); }
    );

    Removing the need for the .promise() method call and the .then() method calls.

    The way the $.chain() function works is as follows:

    Code JavaScript:
    var promise = $.Deferred().resolve().promise();

    This creates a new Deferred object, resolves it immediately, calls its promise() method and assigns the resultant Promise to a variable of the same name.

    Then we iterate over the arguments passed to the function using arguments, an array-like object which in out case will contain the four functions we passed in.

    As of jQuery 1.8 .pipe() is deprecated and we should use .then():

    Code JavaScript:
    jQuery.each( arguments, function() {
      promise = promise.then( this );
    });

    Here all we are doing is adding handlers to the Promise we created previously, before finally returning it.

    What I overlooked previously, was that the code on SO assigns the result of the call to $.chain() to a variable (animations), so that a final callback can be invoked once all of the animations have taken place (using $.when()).

    I've updated the code to reflect this:

    Code:
    <!DOCTYPE HTML>
    <html>
      <head>
        <!--http://www.sitepoint.com/forums/showthread.php?1052208-How-to-trigger-animation-after-user-scroll-to-N-points-jQuery-waypoints-with-multip-->
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>Callback hell!</title>
        <script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
        <style>
          body{height:3000px;}
          #box1{display:none; width:200px; height:200px; background:red; position: fixed; top:0; right: 0;}
          #box2{display:none; width:200px; height:200px; background:blue; position: fixed; top:0; right: 0;}
          #box3{display:none; width:200px; height:200px; background:orange; position: fixed; top:0; right: 0;}
          #box4{display:none; width:200px; height:200px; background:pink; position: fixed; top:0; right: 0;}
        </style>
      </head>
      
      <body>
        <h1>Some heading</h1>
        <p>Some content</p>
        <div id="box1"></div>
        <div id="box2"></div>
        <div id="box3"></div>
        <div id="box4"></div>
        <script>
          $.chain = function() {
            var promise = $.Deferred().resolve().promise();
            jQuery.each( arguments, function() {
              promise = promise.pipe( this );
            });
            return promise;
          };  
            
          function scrollTop(){
            if(typeof pageYOffset!= 'undefined'){
              return pageYOffset;
            }
            else{
              var b = document.body; //IE 'quirks'
              var d = document.documentElement; //IE with doctype
              d = (d.clientHeight)? d : b;
              return d.scrollTop;
            }
          }    
              
          $(window).on("scroll", function(){
            if(scrollTop() >= 500){
            $(window).off("scroll");
              var animations = 
                $.chain(
                  function(){ return $('#box1').fadeIn('slow').delay(2000).fadeOut('slow'); }, 
                  function(){ return $('#box2').fadeIn('slow').delay(2000).fadeOut('slow'); }, 
                  function(){ return $('#box3').fadeIn('slow').delay(2000).fadeOut('slow'); }, 
                  function(){ return $('#box4').fadeIn('slow'); }
                );
              
              $.when( animations ).done(function() {
                alert("All done!");
              });           
            };
          });
        </script>
      </body>
    </html>

  12. #12
    SitePoint Member
    Join Date
    May 2013
    Posts
    6
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hey, I very appreciate your answer and help!
    How can I say thanks in this forum? I can't find anything to voteup your reputation or etc.

    Okay, about the code. It's almost there!!!!! Without you, I couldn't make it man!
    But, now my HTML markup looks nasty with a lot of classes added
    Because I .addClass('FadeUp'); and etc to them, so how could I remove the class after they are animated?

  13. #13
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,858
    Mentioned
    206 Post(s)
    Tagged
    12 Thread(s)
    Quote Originally Posted by boedi7 View Post
    Hey, I very appreciate your answer and help!
    How can I say thanks in this forum? I can't find anything to voteup your reputation or etc.
    I'm afraid this is not currently possible.
    There is some talk of a system whereby people can "thank" each other, but this didn't get implemented yet.
    Thank you for asking, though.

    Quote Originally Posted by boedi7 View Post
    Okay, about the code. It's almost there!!!!! Without you, I couldn't make it man!
    But, now my HTML markup looks nasty with a lot of classes added
    Because I .addClass('FadeUp'); and etc to them, so how could I remove the class after they are animated?
    Shouldn't be too difficult.
    You could try jQuery's removeClass() method.

    Alternatively, post the code you have and maybe there's another way to go about things.

  14. #14
    SitePoint Member
    Join Date
    May 2013
    Posts
    6
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Pullo View Post
    I'm afraid this is not currently possible.
    There is some talk of a system whereby people can "thank" each other, but this didn't get implemented yet.
    Thank you for asking, though.



    Shouldn't be too difficult.
    You could try jQuery's removeClass() method.

    Alternatively, post the code you have and maybe there's another way to go about things.
    Ok, here is my code
    HTML Code:
    var howSection = $('div#how'),
          appIcon = $('img.m1'),
          motionOne = appIcon.width() / 2,
          motionTwo = $('.m2').width() / 2,
          pieTimer = $('#pietimer'),
          animationCollet1= $('.animation-collection-1')
          controlLeft = $('div.space-control-left'),
          controlRight = $('div.space-control-right'),
          fixCircle = $('.animate-fix-circle'),
          stepOne = $('.step-1'),
          stepTwo = $('.step-2'),
          stepThree = $('.step-3'),
          creditCard = $('.credit-card');
    
    // ............. start the animation and chaining
    
    var animation =
            $.chain(
              function(){ return  stepOne.addClass('animated anim05 fadeInLeft').delay(600); }, 
              function(){ return  pieTimer.polartimer('start').delay(2510); },  
              function(){ return  appIcon.addClass('animated anim1 bounce').delay(1000); }, 
              function(){ return  appIcon.addClass('fadeOutLeft').delay(800) }, 
              function(){ return  fixCircle.addClass('animated anim05 fadeOut').delay(200) },
              function(){ return  $('.animation-collection-1').addClass('animated anim1 fadeOut').delay(500) },
              function(){ return  stepOne.removeClass('active').delay(500) },
              function(){ return  stepTwo.addClass('animated anim05 fadeInRight active').delay(600); }, 
              function(){ return  $('.iphone-potrait').addClass('animated anim1 fadeInUp').delay(1100) },
              function(){ return  creditCard.addClass('animated anim1 fadeIn').delay(1200) },
              function(){ return  creditCard.addClass('rotate').delay(1200) },
              function(){ return  stepTwo.removeClass('active').delay(500) },
              function(){ return  stepThree.addClass('animated anim05 fadeInLeft active').delay(600); },
              function(){ return  stepThree.removeClass('active').delay(500) },
              function(){ return  $('.step-4').addClass('animated anim05 fadeInRight active').delay(600); }
              
              
            );

  15. #15
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,858
    Mentioned
    206 Post(s)
    Tagged
    12 Thread(s)
    Sorry, I meant the HTML, too.
    That way I can run it on my computer and see if any improvements can be made, for example to the way in which the script selects the elements to animate, which in turn would mean tidier HTML with less class names.

    What would be perfect would be if you could either post a link to a demo page, or use this template:

    Code:
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="utf-8">
    	
    <style>
    
    your CSS here
    
    </style>
    	
    </head>
    <body>
    
    your HTML here
    
    </body>
    
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
    <script>
    
    your JS here
    
    </script
    </html>

  16. #16
    SitePoint Member
    Join Date
    May 2013
    Posts
    6
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Pullo View Post
    Sorry, I meant the HTML, too.
    That way I can run it on my computer and see if any improvements can be made, for example to the way in which the script selects the elements to animate, which in turn would mean tidier HTML with less class names.

    What would be perfect would be if you could either post a link to a demo page, or use this template:

    Code:
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="utf-8">
    	
    <style>
    
    your CSS here
    
    </style>
    	
    </head>
    <body>
    
    your HTML here
    
    </body>
    
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
    <script>
    
    your JS here
    
    </script
    </html>
    will let you know when the website is up


Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •