Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Don't understand how this is calling the fadeIn method in Jquery

there is a line from a plugin that i'm using that im trying to understand:

$self.hide().attr("src", $self.data(settings.data_attribute))[settings.effect](settings.effect_speed);

self is a jquery object, which in this code is an img dom element, it hides it, then sets the src attribute of this img object to the html5 data-attribute. but now its accessing a property in the jquery object returned by .attr(, which is "fadeIn" in this. but i dont understand, do jquery objects have that built in where an effect property function is built into the jquery object? im confused how this is translates to calling .fadeIn( 900 ). i can't find this documented anywhere on the jquery website. if anyone can shed some light on this, thank you.

sorry, here is the full code, it is from mika tuupola's lazy loading jquery plugin:

(function($, window, document, undefined) {
var $window = $jq191(window);

$jq191.fn.lazyload = function(options) {
    var elements = this;
    var $container;
    var settings = {
        threshold       : 0,
        failure_limit   : 0,
        event           : "scroll",
        effect          : "show",
        container       : window,
        data_attribute  : "original",
        skip_invisible  : true,
        appear          : null,
        load            : null
    };

    function update() {
        var counter = 0;

        elements.each(function() {
            var $this = $jq191(this);
            if (settings.skip_invisible && !$this.is(":visible")) {
                return;
            }
            if ($jq191.abovethetop(this, settings) ||
                $jq191.leftofbegin(this, settings)) {
                    /* Nothing. */
            } else if (!$jq191.belowthefold(this, settings) &&
                !$jq191.rightoffold(this, settings)) {
                    $this.trigger("appear");
                    /* if we found an image we'll load, reset the counter */
                    counter = 0;
            } else {
                if (++counter > settings.failure_limit) {
                    return false;
                }
            }
        });

    }

    if(options) {
        /* Maintain BC for a couple of versions. */
        if (undefined !== options.failurelimit) {
            options.failure_limit = options.failurelimit; 
            delete options.failurelimit;
        }
        if (undefined !== options.effectspeed) {
            options.effect_speed = options.effectspeed; 
            delete options.effectspeed;
        }

        $jq191.extend(settings, options);
    }

    /* Cache container as jQuery as object. */
    $container = (settings.container === undefined ||
                  settings.container === window) ? $window : $jq191(settings.container);

    /* Fire one scroll event per scroll. Not one scroll event per image. */
    if (0 === settings.event.indexOf("scroll")) {
        $container.bind(settings.event, function(event) {
            return update();
        });
    }

    this.each(function() {
        var self = this;
        var $self = $jq191(self);

        self.loaded = false;

        /* When appear is triggered load original image. */
        $self.one("appear", function() {
            if (!this.loaded) {
                if (settings.appear) {
                    var elements_left = elements.length;
                    settings.appear.call(self, elements_left, settings);
                }
                $jq191("<img />")
                    .bind("load", function() {
                        $self
                            .hide()
                            .attr("src", $self.data(settings.data_attribute))
                            [settings.effect](settings.effect_speed);
                        self.loaded = true;

                        /* Remove image from array so it is not looped next time. */
                        var temp = $jq191.grep(elements, function(element) {
                            return !element.loaded;
                        });
                        elements = $jq191(temp);

                        if (settings.load) {
                            var elements_left = elements.length;
                            settings.load.call(self, elements_left, settings);
                        }
                    })
                    .attr("src", $self.data(settings.data_attribute));
            }
        });

        /* When wanted event is triggered load original image */
        /* by triggering appear.                              */
        if (0 !== settings.event.indexOf("scroll")) {
            $self.bind(settings.event, function(event) {
                if (!self.loaded) {
                    $self.trigger("appear");
                }
            });
        }
    });

    /* Check if something appears when window is resized. */
    $window.bind("resize", function(event) {
        update();
    });

    /* With IOS5 force loading images when navigating with back button. */
    /* Non optimal workaround. */
    if ((/iphone|ipod|ipad.*os 5/gi).test(navigator.appVersion)) {
        $window.bind("pageshow", function(event) {
            if (event.originalEvent.persisted) {
                elements.each(function() {
                    $jq191(this).trigger("appear");
                });
            }
        });
    }

    /* Force initial check if images should appear. */
    $jq191(window).load(function() {
        update();
    });

    return this;
};

/* Convenience methods in jQuery namespace.           */
/* Use as  $jq191.belowthefold(element, {threshold : 100, container : window}) */

$jq191.belowthefold = function(element, settings) {
    var fold;

    if (settings.container === undefined || settings.container === window) {
        fold = $window.height() + $window.scrollTop();
    } else {
        fold = $jq191(settings.container).offset().top + $jq191(settings.container).height();
    }

    return fold <= $jq191(element).offset().top - settings.threshold;
};

$jq191.rightoffold = function(element, settings) {
    var fold;

    if (settings.container === undefined || settings.container === window) {
        fold = $window.width() + $window.scrollLeft();
    } else {
        fold = $jq191(settings.container).offset().left + $jq191(settings.container).width();
    }

    return fold <= $jq191(element).offset().left - settings.threshold;
};

$jq191.abovethetop = function(element, settings) {
    var fold;

    if (settings.container === undefined || settings.container === window) {
        fold = $window.scrollTop();
    } else {
        fold = $jq191(settings.container).offset().top;
    }

    return fold >= $jq191(element).offset().top + settings.threshold  + $jq191(element).height();
};

$jq191.leftofbegin = function(element, settings) {
    var fold;

    if (settings.container === undefined || settings.container === window) {
        fold = $window.scrollLeft();
    } else {
        fold = $jq191(settings.container).offset().left;
    }

    return fold >= $jq191(element).offset().left + settings.threshold + $jq191(element).width();
};

$jq191.inviewport = function(element, settings) {
     return !$jq191.rightoffold(element, settings) && !$jq191.leftofbegin(element, settings) &&
            !$jq191.belowthefold(element, settings) && !$jq191.abovethetop(element, settings);
 };

/* Custom selectors for your convenience.   */
/* Use as $jq191("img:below-the-fold").something() or */
/* $jq191("img").filter(":below-the-fold").something() which is faster */

$jq191.extend($jq191.expr[':'], {
    "below-the-fold" : function(a) { return $jq191.belowthefold(a, {threshold : 0}); },
    "above-the-top"  : function(a) { return !$jq191.belowthefold(a, {threshold : 0}); },
    "right-of-screen": function(a) { return $jq191.rightoffold(a, {threshold : 0}); },
    "left-of-screen" : function(a) { return !$jq191.rightoffold(a, {threshold : 0}); },
    "in-viewport"    : function(a) { return $jq191.inviewport(a, {threshold : 0}); },
    /* Maintain BC for couple of versions. */
    "above-the-fold" : function(a) { return !$jq191.belowthefold(a, {threshold : 0}); },
    "right-of-fold"  : function(a) { return $jq191.rightoffold(a, {threshold : 0}); },
    "left-of-fold"   : function(a) { return !$jq191.rightoffold(a, {threshold : 0}); }
});

})($jq191, window, document);

like image 815
Masu Avatar asked Mar 30 '13 01:03

Masu


People also ask

How does fadeIn jQuery work?

The fadeIn() method gradually changes the opacity, for selected elements, from hidden to visible (fading effect). Note: Hidden elements will not be displayed at all (no longer affects the layout of the page). Tip: This method is often used together with the fadeOut() method.

Is an alias of jQuery?

Many JavaScript libraries use $ as a function or variable name, just as jQuery does. In jQuery's case, $ is just an alias for jQuery , so all functionality is available without using $ . If you need to use another JavaScript library alongside jQuery, return control of $ back to the other library with a call to $.


2 Answers

Remember, jQuery is just an object. That means all of the methods you can call with . notation, you can call with [] notation. Ergo, the two lines are functionally identical:

$("#foo").fadeIn(2000);
$("#foo")['fadeIn'](2000);

The other items, settings.effect and settings.effect_speed are likely being fed into the plugin via an object literal that carries options for the plugin.

var settings = {
    effect: 'fadeIn',
    effect_speed: 2000
}
like image 172
Sampson Avatar answered Oct 06 '22 00:10

Sampson


Here is why this works.

First, jQuery's .hide() method and its .attr(name,value) method each return this in the usual fashion of such jQuery methods, to allow chaining. But that also means we can remove those calls without affecting the question:

$self[settings.effect](settings.effect_speed);

Now it's simpler. settings.effect is the string "fadeIn", right?

Then the code is the same as:

$self["fadeIn"](settings.effect_speed);

In JavaScript, object["methodName"] means exactly the same thing as object.methodName. So the code is really the same as:

$self.fadeIn(settings.effect_speed);

and that's why it calls the fadeIn method.

like image 20
Michael Geary Avatar answered Oct 05 '22 23:10

Michael Geary