Permalink
Browse files

Lazier image loading

(should make site much more responsive)
  • Loading branch information...
1 parent 95165a9 commit 6ec7bd7d75b619884540826df5344028da90da34 @bobthecow committed Feb 26, 2013
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
@@ -15,6 +15,9 @@ title: Genghis, the single-file MongoDB admin app.
<ul id="screenshots">
<% screenshots.each do |screen| %>
- <li<% if screen.identifier.include? "/mobile/" %> class="mobile"<% end %>><img src="<%= screen.path %>"></li>
+ <li<% if mobile? screen %> class="mobile"<% end %>>
+ <img class="lazy" src="/grey<% if mobile? screen %>-mobile<% end %>.png" data-original="<%= screen.path %>">
+ <noscript><img src="<%= screen.path %>"></noscript>
+ </li>
<% end %>
</ul>
View
@@ -1,12 +1,18 @@
<%= @items['/script/jquery/'].compiled_content %>
<%= @items['/script/jquery-shuffle/'].compiled_content %>
+<%= @items['/script/jquery-lazyload/'].compiled_content %>
<%= @items['/script/socialite/'].compiled_content %>
<%= @items['/script/socialite-github/'].compiled_content %>
jQuery(function($) {
+ $('html').addClass('js');
+
// shuffle the screenshots
$('#screenshots').shuffle();
+ // lazy load the screenshots
+ $('img.lazy').lazyload();
+
// load the sellout buttons
Socialite.load($('#share'));
@@ -0,0 +1,227 @@
+/*
+ * Lazy Load - jQuery plugin for lazy loading images
+ *
+ * Copyright (c) 2007-2013 Mika Tuupola
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * Project home:
+ * http://www.appelsiini.net/projects/lazyload
+ *
+ * Version: 1.8.4
+ *
+ */
+(function($, window, document, undefined) {
+ var $window = $(window);
+
+ $.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 = $(this);
+ if (settings.skip_invisible && !$this.is(":visible")) {
+ return;
+ }
+ if ($.abovethetop(this, settings) ||
+ $.leftofbegin(this, settings)) {
+ /* Nothing. */
+ } else if (!$.belowthefold(this, settings) &&
+ !$.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;
+ }
+
+ $.extend(settings, options);
+ }
+
+ /* Cache container as jQuery as object. */
+ $container = (settings.container === undefined ||
+ settings.container === window) ? $window : $(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 = $(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);
+ }
+ $("<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 = $.grep(elements, function(element) {
+ return !element.loaded;
+ });
+ elements = $(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() {
+ $(this).trigger("appear");
+ });
+ }
+ });
+ }
+
+ /* Force initial check if images should appear. */
+ $(window).load(function() {
+ update();
+ });
+
+ return this;
+ };
+
+ /* Convenience methods in jQuery namespace. */
+ /* Use as $.belowthefold(element, {threshold : 100, container : window}) */
+
+ $.belowthefold = function(element, settings) {
+ var fold;
+
+ if (settings.container === undefined || settings.container === window) {
+ fold = $window.height() + $window.scrollTop();
+ } else {
+ fold = $(settings.container).offset().top + $(settings.container).height();
+ }
+
+ return fold <= $(element).offset().top - settings.threshold;
+ };
+
+ $.rightoffold = function(element, settings) {
+ var fold;
+
+ if (settings.container === undefined || settings.container === window) {
+ fold = $window.width() + $window.scrollLeft();
+ } else {
+ fold = $(settings.container).offset().left + $(settings.container).width();
+ }
+
+ return fold <= $(element).offset().left - settings.threshold;
+ };
+
+ $.abovethetop = function(element, settings) {
+ var fold;
+
+ if (settings.container === undefined || settings.container === window) {
+ fold = $window.scrollTop();
+ } else {
+ fold = $(settings.container).offset().top;
+ }
+
+ return fold >= $(element).offset().top + settings.threshold + $(element).height();
+ };
+
+ $.leftofbegin = function(element, settings) {
+ var fold;
+
+ if (settings.container === undefined || settings.container === window) {
+ fold = $window.scrollLeft();
+ } else {
+ fold = $(settings.container).offset().left;
+ }
+
+ return fold >= $(element).offset().left + settings.threshold + $(element).width();
+ };
+
+ $.inviewport = function(element, settings) {
+ return !$.rightoffold(element, settings) && !$.leftofbegin(element, settings) &&
+ !$.belowthefold(element, settings) && !$.abovethetop(element, settings);
+ };
+
+ /* Custom selectors for your convenience. */
+ /* Use as $("img:below-the-fold").something() or */
+ /* $("img").filter(":below-the-fold").something() which is faster */
+
+ $.extend($.expr[':'], {
+ "below-the-fold" : function(a) { return $.belowthefold(a, {threshold : 0}); },
+ "above-the-top" : function(a) { return !$.belowthefold(a, {threshold : 0}); },
+ "right-of-screen": function(a) { return $.rightoffold(a, {threshold : 0}); },
+ "left-of-screen" : function(a) { return !$.rightoffold(a, {threshold : 0}); },
+ "in-viewport" : function(a) { return $.inviewport(a, {threshold : 0}); },
+ /* Maintain BC for couple of versions. */
+ "above-the-fold" : function(a) { return !$.belowthefold(a, {threshold : 0}); },
+ "right-of-fold" : function(a) { return $.rightoffold(a, {threshold : 0}); },
+ "left-of-fold" : function(a) { return !$.rightoffold(a, {threshold : 0}); }
+ });
+
+})(jQuery, window, document);
View
@@ -243,7 +243,8 @@ a.fork-me {
margin: @12px;
padding: 0;
display: inline-block;
- width: 240*@px;
+ width: 240*@px;
+ height: 192*@px;
.border-radius(@3px);
.box-shadow(0 @8px @8px rgba(0,0,0,.75), 0 0 @24px rgba(0,0,0,.5));
border-top: 1px solid #AAA;
@@ -279,10 +280,19 @@ a.fork-me {
.border-bottom-radius(@2px);
display: inline-block;
max-width: 100%;
+
+ &.lazy {
+ display: none;
+ width: 100%;
+ html.js & {
+ display: inline-block;
+ }
+ }
}
&.mobile {
- width: 105*@px;
+ width: 105*@px;
+ height: 160*@px;
.border-radius(@16px);
padding-bottom: @32px;
View
@@ -23,4 +23,8 @@ def changes
def version_hash(version)
version.gsub(/[^\w]+/, '_').sub(/^v?/, 'v')
-end
+end
+
+def mobile?(item)
+ item.identifier.include? '/mobile/'
+end

0 comments on commit 6ec7bd7

Please sign in to comment.