Skip to content

Commit

Permalink
Merge pull request #11 from agirton/master
Browse files Browse the repository at this point in the history
Converted to a jQuery plugin
  • Loading branch information
jordansinger committed Apr 19, 2013
2 parents 2863fcf + c881455 commit 7bc1f81
Show file tree
Hide file tree
Showing 10 changed files with 414 additions and 79 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

.DS_Store
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
Hook.js
=======

Pull to refresh. For the web. This rewrite is a work in progress and has only been tested on the latest Safari, Chrome, and Firefox. There are a few bugs that I'm currently working through with Firefox.

##Dependency
* Needs mousewheel.js, however will most likely change this to an option in future commits.

##There are 9 settings and 1 callback. Which are the following;
* reloadPage: default is true, if false will reload element (note must also have reloadEl callback),
* dynamic: default is true, if false you will need your own html,
* textRequired: default is false, if true the dynamic text HTML will be added,
* swipeDistance: default is 50, the amount of swipe distance on touch devices to fire reload,
* loaderClass: default is hook-loader,
* spinnerClass: default is hook-spinner,
* loaderTextClass: default is hook-text,
* loaderText: default is 'Reloading..' is only set when you set 'textRequired'
* reloadEl: callback

##Outstanding issues:
* Firefox reload only appearing after first scrolling down.

##ToDo's:
* Convert from jQuery animate to css3 transitions for browsers that support it.

##Examples:
```` JS
// No options
$('#hook').hook();

// Callback
$('#hook').hook({
reloadPage: false,
reloadEl: function(){
console.log('Hello World!);
}
});
````
Binary file added hook-bgs.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added hook-spinner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added [email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
88 changes: 75 additions & 13 deletions hook.css
Original file line number Diff line number Diff line change
@@ -1,38 +1,100 @@
/**
* Hook
* Version: 1.0
* Author: Jordan Singer, Brandon Jacoby
* Version: 1.1
* Author: Jordan Singer, Brandon Jacoby, Adam Girton
* Copyright (c) 2013 - Hook. All rights reserved.
* http://www.usehook.com
*/

/* 'customizable' declares that a property can be customized without breaking functionality */
#hook * {
.hook * {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
margin: 0 auto;
}
#hook {

.hook {
display: none;
/* customizable */ height: 85px;
/* customizable */ background: url(hook-bg.png) repeat;
/* customizable */ box-shadow: 0px -9px 5px -5px #999 inset;
/* customizable */ background: url(hook-bgs.png) repeat;
/* customizable */ box-shadow: 0 -8px 5px -5px #999 inset;
clear: both;
position: relative;
width: 100%;
overflow: hidden;
text-align: center;
}
#hook span#hook-text {
.hook-text {
/* customizable */ font-size: 14px;
/* customizable */ font-family: Arial, Helvetica, sans-serif;
/* customizable */ color: #999;
/* customizable */ color: #666;
/* customizable */ font-weight: normal;
/* customizable */ text-shadow: 0px 1px #fff;
/* customizable */ text-shadow: 0 1px #fff;
}
#hook #loader {
padding: 10px 0;
.hook-loader {
padding: 25px 0;
}
#hook .spinner {
.hook-spinner {
display: block;
/* customizable */ background: url(hook-spinner.gif) no-repeat center;
/* customizable */ background: url(hook-spinner.png) no-repeat center;
/* customizable */ width: 32px;
/* customizable */ height: 32px;
-webkit-animation: spin 1s linear infinite both;
-moz-animation: spin 1s linear infinite both;
-o-animation: spin 1s linear infinite both;
animation: spin 1s linear infinite both;
}
.hook-with-text .hook-loader{
padding: 10px 0;
}

@media
only screen and (-webkit-min-device-pixel-ratio: 2),
only screen and ( min--moz-device-pixel-ratio: 2),
only screen and ( -o-min-device-pixel-ratio: 2/1),
only screen and ( min-device-pixel-ratio: 2),
only screen and ( min-resolution: 192dpi),
only screen and ( min-resolution: 2dppx) {

.hook-spinner {
background: url([email protected]) no-repeat center;
background-size: 32px 32px;
}
}

@-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
}
}

@-moz-keyframes spin {
0% {
-moz-transform: rotate(0deg);
}
100% {
-moz-transform: rotate(360deg);
}
}

@-o-keyframes spin {
0% {
-o-transform: rotate(0deg);
}
100% {
-o-transform: rotate(360deg);
}
}

@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
233 changes: 167 additions & 66 deletions hook.js
Original file line number Diff line number Diff line change
@@ -1,70 +1,171 @@
$(function () {
window.loadheight = $('#hook').height();
window.hidden = $("#hook").animate("marginTop", "-" + loadheight + "px");
window.visible = $("#hook").animate("marginTop", "0px");
$("#hook").css("marginTop", "-" + loadheight + "px")
});
$(function hook() {
var loadheight = $('#hook').height();
$(window).scroll(function (event) {
var st = $(window).scrollTop();
if (st <= 0) {
$("#hook").animate({
"marginTop": "0px"
}, 200);
$("#hook").delay(500).slideUp(200, function () {
window.location.reload()
})
}
if ($.browser.webkit) {
if (st == 0) {
$('body').css('overflow', 'hidden')
/**
* Hook
* Version: 1.1
* Author: Jordan Singer, Brandon Jacoby, Adam Girton
* Copyright (c) 2013 - Hook. All rights reserved.
* http://www.usehook.com
*/

;(function ( $, window, document, undefined ) {
var win = $(this),
st = win.scrollTop() || window.pageYOffset,
called = false;

var hasTouch = function() {
return !!('ontouchstart' in window) || !!('onmsgesturechange' in window);
};


var methods = {

init: function(options) {

return this.each(function() {
var $this = $(this),
settings = $this.data('hook');

if(typeof(settings) === 'undefined') {

var defaults = {
reloadPage: true, // if false will reload element
dynamic: true, // if false Hook elements already there
textRequired: false, // will input loader text if true
scrollWheelSelected: false, // will use scroll wheel events
swipeDistance: 50, // swipe distance for loader to show on touch devices
loaderClass: 'hook-loader',
spinnerClass: 'hook-spinner',
loaderTextClass: 'hook-text',
loaderText: 'Reloading...',
reloadEl: function() {}
};

settings = $.extend({}, defaults, options);

$this.data('hook', settings);
} else {

settings = $.extend({}, settings, options);
}

if(settings.dynamic === true) {
var loaderElem = '<div class=' + settings.loaderClass + '>';
loaderElem += '<div class='+ settings.spinnerClass + '/>';
loaderElem += '</div>';
var spinnerTextElem = '<span class='+ settings.loaderTextClass + '>' + settings.loaderText + '</span>';

$this
.append(loaderElem);

if (settings.textRequired === true) {
$this.addClass('hook-with-text');
$this.append(spinnerTextElem);
}
}

if(!hasTouch()) {
if(settings.scrollWheelSelected === true){
win.on('mousewheel', function(event, delta) {
methods.onScroll($this, settings, delta);
});
} else {
win.on('scroll', function() {
methods.onScroll($this, settings);
});
}
} else {
var lastY = 0,
swipe = 0;
win.on('touchstart', function(e){
lastY = e.originalEvent.touches[0].pageY;
});

win.on('touchmove', function(e) {
swipe = e.originalEvent.touches[0].pageY + lastY;
st = $(this).scrollTop();

if(swipe < settings.swipeDistance) {
e.preventDefault();
}

if(swipe > settings.swipeDistance && lastY <= 40) {
methods.onSwipe($this, settings);
}
});

win.on('touchend', function(){
swipe = 0;
});
}

});
},

onScroll: function(el, settings, delta) {
st = win.scrollTop();

if(settings.scrollWheelSelected === true && (delta >= 150 && st <= 0)) {
if(called === false) {
methods.reload(el, settings);
called = true;
}
}

if(settings.scrollWheelSelected === false && st <= 0) {
if(called === false) {
methods.reload(el, settings);
called = true;
}
}
})
});


//Browser detection, unsupported in jQuery latest.
(function () {
var matched, browser;
jQuery.uaMatch = function (ua) {
ua = ua.toLowerCase();
var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || /(webkit)[ \/]([\w.]+)/.exec(ua) || /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || /(msie) ([\w.]+)/.exec(ua) || ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || [];
return {
browser: match[1] || "",
version: match[2] || "0"
}
},

onSwipe: function(el, settings) {
if(st <= 0) {
methods.reload(el, settings);
}
},

reload: function(el, settings) {
el.show();
el.animate({
"marginTop": "0px"
}, 200);
el.delay(500).slideUp(200, function () {
if(settings.reloadPage) {
window.location.reload(true);
}

called = false;
});

if(!settings.reloadPage) {
settings.reloadEl();
}
},

destroy: function() {
return $(this).each(function(){
var $this = $(this);

$this.empty();
$this.removeData('hook');
});
}
};
matched = jQuery.uaMatch(navigator.userAgent);
browser = {};
if (matched.browser) {
browser[matched.browser] = true;
browser.version = matched.version
}
if (browser.chrome) {
browser.webkit = true
} else if (browser.webkit) {
browser.safari = true
}
jQuery.browser = browser;
jQuery.sub = function () {
function jQuerySub(selector, context) {
return new jQuerySub.fn.init(selector, context)

$.fn.hook = function () {
var method = arguments[0];

if(methods[method]) {
method = methods[method];
arguments = Array.prototype.slice.call(arguments, 1);
} else if (typeof(method) === 'object' || !method) {
method = methods.init;
} else {
$.error( 'Method ' + method + ' does not exist on jQuery.pluginName' );
return this;
}
jQuery.extend(true, jQuerySub, this);
jQuerySub.superclass = this;
jQuerySub.fn = jQuerySub.prototype = this();
jQuerySub.fn.constructor = jQuerySub;
jQuerySub.sub = this.sub;
jQuerySub.fn.init = function init(selector, context) {
if (context && context instanceof jQuery && !(context instanceof jQuerySub)) {
context = jQuerySub(context)
}
return jQuery.fn.init.call(this, selector, context, rootjQuerySub)
};
jQuerySub.fn.init.prototype = jQuerySub.fn;
var rootjQuerySub = jQuerySub(document);
return jQuerySub
}
})();

return method.apply(this, arguments);
};

})( jQuery, window, document );
Loading

0 comments on commit 7bc1f81

Please sign in to comment.