0

In an attempt to make a swipe-able slideshow for many images, I am attempting to stitch together two plugins, Swipe.js and lazyloader.js. I want to have the slideshow timer event from the Swipe plugin call the update function inside of Lazyloader. From researching, it seems my problem appears to be one of namespace; that is, Swipe doesn't know about the stuff inside Lazyloader, and therefore cannot call the function.

  1. Given the following code, am I understanding my problem correctly?
  2. If so, how can I get Swipe to access Lazyloader's functions?

Thank you.

FOLLOW UP: After Q&A with Cheeso, I see now that I was asking the wrong question in regard to what I ultimately needed to happen. I add this comment to avoid having any future readers getting confused because of my bad question. This is not about namespace or even about accessing a private function, which shouldn't be done. This thread is utimately about how inadvisable it may be to try and frankenstein libraries together if you don't really know what you're doing. ; ) END FOLLOW UP

The callback in swipe.js:

this.callback = this.options.callback || function() {

the script called inside the html:

<script src="js/jquery.js" type="text/javascript"></script>
<script src="js/jquery.lazyload.js" type="text/javascript"></script>
<script src='js/swipe.js' type="text/javascript"></script>

<script type="text/javascript">$(document).ready(function() {


    function myAlert(){
        //call a function from inside jquery.lazyload.js
        alertMe();
    }

    //instantiate a swipe object and pass in a bunch of 
    //options, especially "callback" which fires on every slide change
    window.mySwipe = new Swipe(document.getElementById('slider1'), {
        startSlide: 0,
        speed: 1000,
        auto: 5000,
        callback: function(){
            myAlert();
        }
    });
    // run lazyload on every VISIBLE image with the class "lazy" on load, and on every click
    $("img.lazy").lazyload({event: "click", effect : "fadeIn", threshold: 0,});
    }); 
</script>

jquery.lazyloader.js:

 //outside of the container below, I can be called by myAlert()
 function alertMe() {
        alert("it worked!");
    }


(function($, window) {

    $window = $(window);

    $.fn.lazyload = function(options) {

    ///
    ///Here be a bunch of lazyloader stuff
    ///

    //I work when above, but once I am inside this container, I cannot be called by myAlert(), 
    //and I will error as 'not a valid function'
    function alertMe() {
        alert("it worked! Even inside of this container! ");
    }


})(jQuery, window);
Community
  • 1
  • 1
mbuckl1
  • 3
  • 5
  • Code dumps like this are most of the time, not useful. I suggest you reduce your question to the actual problem and outline the solution that you have tried so far. That way more people will be able to help or care. – elclanrs Apr 26 '12 at 00:43
  • My apologies. When looking at other questions, I assumed that including the complete code was better etiquette. I will edit this down and show what I have tried, as you have suggested. Thanks. – mbuckl1 Apr 26 '12 at 00:47

1 Answers1

2

Could be as simple as this: to set the callback option on the Swipe instance to point to a function that does LazyLoader things. This is just a guess, because I don't know swipe, but I looked at the code dump and saw that callback function; it appears to be the key point of extension for Swipe.

If I'm correct, then it's not a namespace issue at all. It's just what you said - knitting together disparate libraries or modules. Typically a js module will have an extension point or two that allows this. I'm guessing Swipe's extension point is that callback.

Maybe something like this:

function myFn() {
  // do whatever lazyload thing you want to do, here. 
}

$(document).ready(function() { 
    var slider1 = new Swipe(document.getElementById('slider1'),
                            {startSlide: 0,
                             speed: 1000,
                             auto: 10000,
                             callback:myFn}); 
    $("img.lazy").lazyload({event: "click"}); 
}); 

You may have to refactor to make either slider1 or some other variables global, so they are accessible outside of the doc.ready function.

FOLLOWUP

You have this:

<script type="text/javascript">
    $(document).ready(function() {   
        function myAlert(){   
            //call a function from inside jquery.lazyload.js   
            alertMe();   
        }   

        //instantiate a swipe object and pass in a bunch of    
        //options, especially "callback" which fires on every slide change   
        window.mySwipe = new Swipe(document.getElementById('slider1'), {   
            startSlide: 0,   
            speed: 1000,   
            auto: 5000,   
            callback: function(){   
                myAlert();   
            }   
        });   
        $("img.lazy").lazyload({event: "click", effect : "fadeIn", threshold: 0,});   
    });    
</script>   

There are several problems with that code. It should be closer to this:

<script type="text/javascript">
    function myThing(){   
        // ** Do something useful here. This may involve calling
        // ** other functions.  Those functions need not be defined
        // ** within jquery.lazyload.js.
    }   

    $(document).ready(function() {   
        //instantiate a swipe object and pass in a bunch of    
        //options, especially "callback" which fires on every slide change.

        // ** There is no need, as far as I can tell, to assign the
        // ** output to a global variable. (window.mySwipe).  In fact, given
        // ** the code you have, there is no need to retain the output at all. 
        new Swipe(document.getElementById('slider1'), {   
            startSlide: 0,   
            speed: 1000,   
            auto: 5000,   
            // ** Just use the function name. You don't need to define
            // ** a new anonymous function to wrap around it. 
            callback: myThing
        });   
        $("img.lazy").lazyload({event: "click", effect : "fadeIn", threshold: 0,});   
    });    
</script>   

MORE

I suppose that what you want is to lazily load the "next few" images so that they are available as the user swipes through a list. From what I read (briefly), you need to call lazyload() only once, for all images on the page. If your images are inside a "container", then specify the container option on lazyload. (See http://www.appelsiini.net/projects/lazyload) The plugin then monitors the viewport for that container and loads images as necessary. There is no need to call "lazyload" again, no need for a callback.

If this is not working, then Swipe and jquery.lazyload.js may not be usable together, because of assumptions made in lazyload. In that case, you can still get lazy-loading, but you need to do it yourself.

To do that, eliminate lazyload.js completely. Then, in the Swipe callback, do what you would like lazyload to have done: set the src attribute on the "next" image. Setting the attribute will cause the webpage to load the image. To get lazy loading, in the original state the src attributes on all images must be blank, or set to some fixed image URL, before the swiping begins. Now, you may ask: in the callback how will you know which image to load? And which URL to set into the src attribute? That is up for you to determine. I presume there is some way to get the appropriate information from Swipe in that callback.

If you don't understand this, then you need some instruction or some further reading to establish the basic understanding of how browsers handle images. From my reading, you do not need Swipe to call lazyload's update().

Some general suggestions:

  • for any module, you should not try to call functions defined internal to that module. They are internal for a reason.

  • for any module, you should not modify its source code unless you are very certain you know what you are doing. If you are poking around and trying things, put the code in your own module. Your own javascript code belongs in the web page, or in a separate module referenced by the webpage.

  • you should probably not be defining functions within $(document).ready() unless you have a good reason.

  • read the documentation. I had never heard of Swipe or lazyload before today. The suggestions I made here about them - specifically, regarding the callback on Swipe, and the container option on lazyload - came from me reading the doc for how to use them.

Cheeso
  • 189,189
  • 101
  • 473
  • 713
  • The `callback` was a revelation to me. With the above hint, I was able to call (using a `Swipe` event as I had hoped) a test function `myFn()` from inside `lazyloader`--as long as it resided _outside_ of the `(function($, window) `. Because of my profound ignorance, I do not know how to target/path to/call `myFn()` once it is inside this container. And so now am I back to my "namespace" issue? – mbuckl1 Apr 26 '12 at 13:05
  • I don't know what you mean by *`myFn()` from inside `lazyloader` -- as long as it resided outside....* I don't get that. in general you should not modify the .js of external modules. Use them as is. It is not a namespace issue. It is simply a matter of mechanics. I'm guessing you are not a javascript expert and are just struggling with the mechanics of how and where to declare a fn and how to call it. Maybe you can modify your post to show what you tried, what you mean. What was wrong with what I wrote above, anyway? Why can you not declare `myFn` just above `$(document).ready()`? – Cheeso Apr 26 '12 at 13:21
  • You are right on all counts: I am not an expert, and your code was flawless. I am expressing myself poorly and will modify my post as you suggest. – mbuckl1 Apr 26 '12 at 13:37
  • O.P. modified per Cheeso and elclanrs suggestions. – mbuckl1 Apr 26 '12 at 15:08
  • First: *do not modify* jquery.lazyloader.js. There should be no need and unless you are certain, you should stay out of that code. Second: clarify what you want your logic to do. I suspect it is not "pop an alert box". What, really, are you trying to do, and when, under what circumstances. Be clear: *When the swipe finishes, then....????* What? Finally, I have made some further comments in my answer. – Cheeso Apr 26 '12 at 15:50
  • I will have a slider with (eventually) hundreds of images. I want these images to load lazily, as the user swipes/scrolls/waits for the images to enter the viewport. And that is my problem: I need an event to fire off lazyload (ie. "okay, I'm ready to load the next image") whether the slider is doing it's thing automatically (via a timer) or manually (via a user click or swipe). What I really want to call is `update`, not the test alert, as you have noted. – mbuckl1 Apr 26 '12 at 15:58
  • What I really want is for a Swipe event to call `update`, a Lazyloader function. I want Swipe to be the master and Lazyloader to do its bidding. As for tinkering with another's module, I quite agree. I'm just profoundly ignorant, as I mentioned above. – mbuckl1 Apr 26 '12 at 16:08
  • It appears that I need to properly extend Lazyload to be triggered by swipe, or (as you suggest) write my own Lazyload plugin. At any rate, I've got some [remedial reading](http://docs.jquery.com/Plugins/Authoring#Namespacing) to do. **Thank you** for your help and patience thus far. – mbuckl1 Apr 26 '12 at 16:27
  • What you want is simple enough that I would not advise "extending" lazyload to do it. If lazyload does it, use lazyload. If not, just do it yourself, and eliminate the lazyload.js module. It's only a few lines of js. It's not "a plugin". – Cheeso Apr 26 '12 at 16:32
  • I see what you mean. Thanks again. – mbuckl1 Apr 26 '12 at 16:51
  • Cheeso said: *in the Swipe callback, do what you would like lazyload to have done: set the src attribute on the "next" image. Setting the attribute will cause the webpage to load the image. To get lazy loading, in the original state the src attributes on all images must be blank, or set to some fixed image URL* **So simple and elegant! Thank you!** – mbuckl1 Apr 26 '12 at 16:58