-
Notifications
You must be signed in to change notification settings - Fork 281
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from agirton/master
Converted to a jQuery plugin
- Loading branch information
Showing
10 changed files
with
414 additions
and
79 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
|
||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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!); | ||
} | ||
}); | ||
```` |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 ); |
Oops, something went wrong.