Smooth Scroll plugin not working in Chrome - javascript

So I have come to the completion of my website, and have just discovered that the smooth scrolling JS I was using wont work in Chrome. It works perfectly in Safari, Firefox and I have tried others, but I can't seem to get them to recognise my anchors, or maintain the highlighted nav.
This is my nav:
<ul id="menu"><!-- BEGIN MENU -->
<li><img class="valigner">home</li>
<li><img class="valigner">about</li>
<li><img class="valigner">headshots</li>
<li><img class="valigner">fashion</li>
<li><img class="valigner">editorial</li>
<li><img src="img/logo.jpg" class="logo"/></li>
<li><img class="valigner">live</li>
<li><img class="valigner">events</li>
<li><img class="valigner">outside</li>
<li><img class="valigner">product</li>
<li><img class="valigner">contact</li>
</ul><!-- END MENU -->
this is the JS:
;(function( $ ){
var $scrollTo = $.scrollTo = function( target, duration, settings ){
$(window).scrollTo( target, duration, settings );
};
$scrollTo.defaults = {
axis:'xy',
duration: parseFloat($.fn.jquery) >= 1.3 ? 0 : 1
};
// Returns the element that needs to be animated to scroll the window.
// Kept for backwards compatibility (specially for localScroll & serialScroll)
$scrollTo.window = function( scope ){
return $(window)._scrollable();
};
// Hack, hack, hack :)
// Returns the real elements to scroll (supports window/iframes, documents and regular nodes)
$.fn._scrollable = function(){
return this.map(function(){
var elem = this,
isWin = !elem.nodeName || $.inArray( elem.nodeName.toLowerCase(), ['iframe','#document','html','body'] ) != -1;
if( !isWin )
return elem;
var doc = (elem.contentWindow || elem).document || elem.ownerDocument || elem;
return $.browser.safari || doc.compatMode == 'BackCompat' ?
doc.body :
doc.documentElement;
});
};
$.fn.scrollTo = function( target, duration, settings ){
if( typeof duration == 'object' ){
settings = duration;
duration = 0;
}
if( typeof settings == 'function' )
settings = { onAfter:settings };
if( target == 'max' )
target = 9e9;
settings = $.extend( {}, $scrollTo.defaults, settings );
// Speed is still recognized for backwards compatibility
duration = duration || settings.speed || settings.duration;
// Make sure the settings are given right
settings.queue = settings.queue && settings.axis.length > 1;
if( settings.queue )
// Let's keep the overall duration
duration /= 60000;
settings.offset = both( settings.offset );
settings.over = both( settings.over );
return this._scrollable().each(function(){
var elem = this,
$elem = $(elem),
targ = target, toff, attr = {},
win = $elem.is('html,body');
switch( typeof targ ){
// A number will pass the regex
case 'number':
case 'string':
if( /^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(targ) ){
targ = both( targ );
// We are done
break;
}
// Relative selector, no break!
targ = $(targ,this);
case 'object':
// DOMElement / jQuery
if( targ.is || targ.style )
// Get the real position of the target
toff = (targ = $(targ)).offset();
}
$.each( settings.axis.split(''), function( i, axis ){
var Pos = axis == 'x' ? 'Left' : 'Top',
pos = Pos.toLowerCase(),
key = 'scroll' + Pos,
old = elem[key],
max = $scrollTo.max(elem, axis);
if( toff ){// jQuery / DOMElement
attr[key] = toff[pos] + ( win ? 0 : old - $elem.offset()[pos] );
// If it's a dom element, reduce the margin
if( settings.margin ){
attr[key] -= parseInt(targ.css('margin'+Pos)) || 0;
attr[key] -= parseInt(targ.css('border'+Pos+'Width')) || 0;
}
attr[key] += settings.offset[pos] || 0;
if( settings.over[pos] )
// Scroll to a fraction of its width/height
attr[key] += targ[axis=='x'?'width':'height']() * settings.over[pos];
}else{
var val = targ[pos];
// Handle percentage values
attr[key] = val.slice && val.slice(-1) == '%' ?
parseFloat(val) / 100 * max
: val;
}
// Number or 'number'
if( /^\d+$/.test(attr[key]) )
// Check the limits
attr[key] = attr[key] <= 0 ? 0 : Math.min( attr[key], max );
// Queueing axes
if( !i && settings.queue ){
// Don't waste time animating, if there's no need.
if( old != attr[key] )
// Intermediate animation
animate( settings.onAfterFirst );
// Don't animate this axis again in the next iteration.
delete attr[key];
}
});
animate( settings.onAfter );
function animate( callback ){
$elem.animate( attr, duration, settings.easing, callback && function(){
callback.call(this, target, settings);
});
};
}).end();
};
// Max scrolling position, works on quirks mode
// It only fails (not too badly) on IE, quirks mode.
$scrollTo.max = function( elem, axis ){
var Dim = axis == 'x' ? 'Width' : 'Height',
scroll = 'scroll'+Dim;
if( !$(elem).is('html,body') )
return elem[scroll] - $(elem)[Dim.toLowerCase()]();
var size = 'client' + Dim,
html = elem.ownerDocument.documentElement,
body = elem.ownerDocument.body;
return Math.max( html[scroll], body[scroll] )
- Math.min( html[size] , body[size] );
};
function both( val ){
return typeof val == 'object' ? val : { top:val, left:val };
};
})( jQuery );
I believe it came from Ariel Flesler but his demo page and documentation just confused me more.

this work on all of browsers ,
$(document).ready(function () {
//run once
var el = $('#Container');
var originalelpos = el.offset().top; // take it where it originally is on the page
//run on scroll
$(window).scroll(function () {
var el = $('#Container'); // important! (local)
var elpos = el.offset().top; // take current situation
var windowpos = $(window).scrollTop();
var finaldestination = windowpos + originalelpos;
el.css('top', finaldestination);
//el.stop().animate({ 'top': finaldestination }, 1000);
});
});
I hope that will help , you can use animate for animating or .css for changing the top attr in style

This is a little more concise:
$(document).ready(function() {
$('#menu a').bind("click", function(e) {
var target = $(this).attr("href"); // Get the target element
var scrollToPosition = $(target).offset().top; // Position to scroll to
$('html /* For FF & IE */,body /* For Chrome */').animate({
'scrollTop': scrollToPosition
}, 500, function(target){
window.location.hash = target;
});
e.preventDefault();
});
});
See it in action!

Related

JQuery and JS NoConflict() Not Working

I have a website that uses smooth scroll which works great.. But once I added the following code:
var $ = jQuery.noConflict();
$(document).ready(function() {
$(function() {
var $ticker = $('#news-ticker'),
$first = $('.news-ticket-class li:first-child', $ticker);
// put an empty space between each letter so we can
// use break word
$('.news-ticket-class li', $ticker).each(function() {
var $this = $(this),
text = $this.text();
$this.html(text.split('').join('​'));
});
// begin the animation
function tick($el) {
$el.addClass('tick')
.one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function() {
$el.removeClass('tick');
var $next = $el.next('li');
$next = $next.length > 0 ? $next : $first;
tick($next);
});
}
tick($first);
});
});
It breaks the smooth scroll. I have tried using the noconflict and that doesn't help as you can see.
The template I use is here that has the smooth scrolling option.
I am stuck with either the above code or my menus working. If you have any other suggestions that mimic someone typing, like this website, please send over my way.
EDIT: This is the smooth scroll script:
//
// SmoothScroll for websites v1.4.0 (Balazs Galambosi)
// http://www.smoothscroll.net/
//
// Licensed under the terms of the MIT license.
//
// You may use it in your theme if you credit me.
// It is also free to use on any individual website.
//
// Exception:
// The only restriction is to not publish any
// extension for browsers or native application
// without getting a written permission first.
//
(function () {
// Scroll Variables (tweakable)
var defaultOptions = {
// Scrolling Core
frameRate : 150, // [Hz]
animationTime : 500, // [ms]
stepSize : 100, // [px]
// Pulse (less tweakable)
// ratio of "tail" to "acceleration"
pulseAlgorithm : true,
pulseScale : 4,
pulseNormalize : 1,
// Acceleration
accelerationDelta : 50, // 50
accelerationMax : 3, // 3
// Keyboard Settings
keyboardSupport : true, // option
arrowScroll : 50, // [px]
// Other
touchpadSupport : false, // ignore touchpad by default
fixedBackground : true,
excluded : ''
};
var options = defaultOptions;
// Other Variables
var isExcluded = false;
var isFrame = false;
var direction = { x: 0, y: 0 };
var initDone = false;
var root = document.documentElement;
var activeElement;
var observer;
var refreshSize;
var deltaBuffer = [];
var isMac = /^Mac/.test(navigator.platform);
var key = { left: 37, up: 38, right: 39, down: 40, spacebar: 32,
pageup: 33, pagedown: 34, end: 35, home: 36 };
/***********************************************
* INITIALIZE
***********************************************/
/**
* Tests if smooth scrolling is allowed. Shuts down everything if not.
*/
function initTest() {
if (options.keyboardSupport) {
addEvent('keydown', keydown);
}
}
/**
* Sets up scrolls array, determines if frames are involved.
*/
function init() {
if (initDone || !document.body) return;
initDone = true;
var body = document.body;
var html = document.documentElement;
var windowHeight = window.innerHeight;
var scrollHeight = body.scrollHeight;
// check compat mode for root element
root = (document.compatMode.indexOf('CSS') >= 0) ? html : body;
activeElement = body;
initTest();
// Checks if this script is running in a frame
if (top != self) {
isFrame = true;
}
/**
* Please duplicate this radar for a Safari fix!
* rdar://22376037
* https://openradar.appspot.com/radar?id=4965070979203072
*
* Only applies to Safari now, Chrome fixed it in v45:
* This fixes a bug where the areas left and right to
* the content does not trigger the onmousewheel event
* on some pages. e.g.: html, body { height: 100% }
*/
else if (scrollHeight > windowHeight &&
(body.offsetHeight <= windowHeight ||
html.offsetHeight <= windowHeight)) {
var fullPageElem = document.createElement('div');
fullPageElem.style.cssText = 'position:absolute; z-index:-10000; ' +
'top:0; left:0; right:0; height:' +
root.scrollHeight + 'px';
document.body.appendChild(fullPageElem);
// DOM changed (throttled) to fix height
var pendingRefresh;
refreshSize = function () {
if (pendingRefresh) return; // could also be: clearTimeout(pendingRefresh);
pendingRefresh = setTimeout(function () {
if (isExcluded) return; // could be running after cleanup
fullPageElem.style.height = '0';
fullPageElem.style.height = root.scrollHeight + 'px';
pendingRefresh = null;
}, 500); // act rarely to stay fast
};
setTimeout(refreshSize, 10);
addEvent('resize', refreshSize);
// TODO: attributeFilter?
var config = {
attributes: true,
childList: true,
characterData: false
// subtree: true
};
observer = new MutationObserver(refreshSize);
observer.observe(body, config);
if (root.offsetHeight <= windowHeight) {
var clearfix = document.createElement('div');
clearfix.style.clear = 'both';
body.appendChild(clearfix);
}
}
// disable fixed background
if (!options.fixedBackground && !isExcluded) {
body.style.backgroundAttachment = 'scroll';
html.style.backgroundAttachment = 'scroll';
}
}
/**
* Removes event listeners and other traces left on the page.
*/
function cleanup() {
observer && observer.disconnect();
removeEvent(wheelEvent, wheel);
removeEvent('mousedown', mousedown);
removeEvent('keydown', keydown);
removeEvent('resize', refreshSize);
removeEvent('load', init);
}
/************************************************
* SCROLLING
************************************************/
var que = [];
var pending = false;
var lastScroll = Date.now();
/**
* Pushes scroll actions to the scrolling queue.
*/
function scrollArray(elem, left, top) {
directionCheck(left, top);
if (options.accelerationMax != 1) {
var now = Date.now();
var elapsed = now - lastScroll;
if (elapsed < options.accelerationDelta) {
var factor = (1 + (50 / elapsed)) / 2;
if (factor > 1) {
factor = Math.min(factor, options.accelerationMax);
left *= factor;
top *= factor;
}
}
lastScroll = Date.now();
}
// push a scroll command
que.push({
x: left,
y: top,
lastX: (left < 0) ? 0.99 : -0.99,
lastY: (top < 0) ? 0.99 : -0.99,
start: Date.now()
});
// don't act if there's a pending queue
if (pending) {
return;
}
var scrollWindow = (elem === document.body);
var step = function (time) {
var now = Date.now();
var scrollX = 0;
var scrollY = 0;
for (var i = 0; i < que.length; i++) {
var item = que[i];
var elapsed = now - item.start;
var finished = (elapsed >= options.animationTime);
// scroll position: [0, 1]
var position = (finished) ? 1 : elapsed / options.animationTime;
// easing [optional]
if (options.pulseAlgorithm) {
position = pulse(position);
}
// only need the difference
var x = (item.x * position - item.lastX) >> 0;
var y = (item.y * position - item.lastY) >> 0;
// add this to the total scrolling
scrollX += x;
scrollY += y;
// update last values
item.lastX += x;
item.lastY += y;
// delete and step back if it's over
if (finished) {
que.splice(i, 1); i--;
}
}
// scroll left and top
if (scrollWindow) {
window.scrollBy(scrollX, scrollY);
}
else {
if (scrollX) elem.scrollLeft += scrollX;
if (scrollY) elem.scrollTop += scrollY;
}
// clean up if there's nothing left to do
if (!left && !top) {
que = [];
}
if (que.length) {
requestFrame(step, elem, (1000 / options.frameRate + 1));
} else {
pending = false;
}
};
// start a new queue of actions
requestFrame(step, elem, 0);
pending = true;
}
/***********************************************
* EVENTS
***********************************************/
/**
* Mouse wheel handler.
* #param {Object} event
*/
function wheel(event) {
if (!initDone) {
init();
}
var target = event.target;
var overflowing = overflowingAncestor(target);
// use default if there's no overflowing
// element or default action is prevented
// or it's a zooming event with CTRL
if (!overflowing || event.defaultPrevented || event.ctrlKey) {
return true;
}
// leave embedded content alone (flash & pdf)
if (isNodeName(activeElement, 'embed') ||
(isNodeName(target, 'embed') && /\.pdf/i.test(target.src)) ||
isNodeName(activeElement, 'object')) {
return true;
}
var deltaX = -event.wheelDeltaX || event.deltaX || 0;
var deltaY = -event.wheelDeltaY || event.deltaY || 0;
if (isMac) {
if (event.wheelDeltaX && isDivisible(event.wheelDeltaX, 120)) {
deltaX = -120 * (event.wheelDeltaX / Math.abs(event.wheelDeltaX));
}
if (event.wheelDeltaY && isDivisible(event.wheelDeltaY, 120)) {
deltaY = -120 * (event.wheelDeltaY / Math.abs(event.wheelDeltaY));
}
}
// use wheelDelta if deltaX/Y is not available
if (!deltaX && !deltaY) {
deltaY = -event.wheelDelta || 0;
}
// line based scrolling (Firefox mostly)
if (event.deltaMode === 1) {
deltaX *= 40;
deltaY *= 40;
}
// check if it's a touchpad scroll that should be ignored
if (!options.touchpadSupport && isTouchpad(deltaY)) {
return true;
}
// scale by step size
// delta is 120 most of the time
// synaptics seems to send 1 sometimes
if (Math.abs(deltaX) > 1.2) {
deltaX *= options.stepSize / 120;
}
if (Math.abs(deltaY) > 1.2) {
deltaY *= options.stepSize / 120;
}
scrollArray(overflowing, deltaX, deltaY);
event.preventDefault();
scheduleClearCache();
}
/**
* Keydown event handler.
* #param {Object} event
*/
function keydown(event) {
var target = event.target;
var modifier = event.ctrlKey || event.altKey || event.metaKey ||
(event.shiftKey && event.keyCode !== key.spacebar);
// our own tracked active element could've been removed from the DOM
if (!document.body.contains(activeElement)) {
activeElement = document.activeElement;
}
// do nothing if user is editing text
// or using a modifier key (except shift)
// or in a dropdown
// or inside interactive elements
var inputNodeNames = /^(textarea|select|embed|object)$/i;
var buttonTypes = /^(button|submit|radio|checkbox|file|color|image)$/i;
if ( inputNodeNames.test(target.nodeName) ||
isNodeName(target, 'input') && !buttonTypes.test(target.type) ||
isNodeName(activeElement, 'video') ||
isInsideYoutubeVideo(event) ||
target.isContentEditable ||
event.defaultPrevented ||
modifier ) {
return true;
}
// spacebar should trigger button press
if ((isNodeName(target, 'button') ||
isNodeName(target, 'input') && buttonTypes.test(target.type)) &&
event.keyCode === key.spacebar) {
return true;
}
var shift, x = 0, y = 0;
var elem = overflowingAncestor(activeElement);
var clientHeight = elem.clientHeight;
if (elem == document.body) {
clientHeight = window.innerHeight;
}
switch (event.keyCode) {
case key.up:
y = -options.arrowScroll;
break;
case key.down:
y = options.arrowScroll;
break;
case key.spacebar: // (+ shift)
shift = event.shiftKey ? 1 : -1;
y = -shift * clientHeight * 0.9;
break;
case key.pageup:
y = -clientHeight * 0.9;
break;
case key.pagedown:
y = clientHeight * 0.9;
break;
case key.home:
y = -elem.scrollTop;
break;
case key.end:
var damt = elem.scrollHeight - elem.scrollTop - clientHeight;
y = (damt > 0) ? damt+10 : 0;
break;
case key.left:
x = -options.arrowScroll;
break;
case key.right:
x = options.arrowScroll;
break;
default:
return true; // a key we don't care about
}
scrollArray(elem, x, y);
event.preventDefault();
scheduleClearCache();
}
/**
* Mousedown event only for updating activeElement
*/
function mousedown(event) {
activeElement = event.target;
}
/***********************************************
* OVERFLOW
***********************************************/
var uniqueID = (function () {
var i = 0;
return function (el) {
return el.uniqueID || (el.uniqueID = i++);
};
})();
var cache = {}; // cleared out after a scrolling session
var clearCacheTimer;
//setInterval(function () { cache = {}; }, 10 * 1000);
function scheduleClearCache() {
clearTimeout(clearCacheTimer);
clearCacheTimer = setInterval(function () { cache = {}; }, 1*1000);
}
function setCache(elems, overflowing) {
for (var i = elems.length; i--;)
cache[uniqueID(elems[i])] = overflowing;
return overflowing;
}
// (body) (root)
// | hidden | visible | scroll | auto |
// hidden | no | no | YES | YES |
// visible | no | YES | YES | YES |
// scroll | no | YES | YES | YES |
// auto | no | YES | YES | YES |
function overflowingAncestor(el) {
var elems = [];
var body = document.body;
var rootScrollHeight = root.scrollHeight;
do {
var cached = cache[uniqueID(el)];
if (cached) {
return setCache(elems, cached);
}
elems.push(el);
if (rootScrollHeight === el.scrollHeight) {
var topOverflowsNotHidden = overflowNotHidden(root) && overflowNotHidden(body);
var isOverflowCSS = topOverflowsNotHidden || overflowAutoOrScroll(root);
if (isFrame && isContentOverflowing(root) ||
!isFrame && isOverflowCSS) {
return setCache(elems, getScrollRoot());
}
} else if (isContentOverflowing(el) && overflowAutoOrScroll(el)) {
return setCache(elems, el);
}
} while (el = el.parentElement);
}
function isContentOverflowing(el) {
return (el.clientHeight + 10 < el.scrollHeight);
}
// typically for <body> and <html>
function overflowNotHidden(el) {
var overflow = getComputedStyle(el, '').getPropertyValue('overflow-y');
return (overflow !== 'hidden');
}
// for all other elements
function overflowAutoOrScroll(el) {
var overflow = getComputedStyle(el, '').getPropertyValue('overflow-y');
return (overflow === 'scroll' || overflow === 'auto');
}
/***********************************************
* HELPERS
***********************************************/
function addEvent(type, fn) {
window.addEventListener(type, fn, false);
}
function removeEvent(type, fn) {
window.removeEventListener(type, fn, false);
}
function isNodeName(el, tag) {
return (el.nodeName||'').toLowerCase() === tag.toLowerCase();
}
function directionCheck(x, y) {
x = (x > 0) ? 1 : -1;
y = (y > 0) ? 1 : -1;
if (direction.x !== x || direction.y !== y) {
direction.x = x;
direction.y = y;
que = [];
lastScroll = 0;
}
}
var deltaBufferTimer;
if (window.localStorage && localStorage.SS_deltaBuffer) {
deltaBuffer = localStorage.SS_deltaBuffer.split(',');
}
function isTouchpad(deltaY) {
if (!deltaY) return;
if (!deltaBuffer.length) {
deltaBuffer = [deltaY, deltaY, deltaY];
}
deltaY = Math.abs(deltaY)
deltaBuffer.push(deltaY);
deltaBuffer.shift();
clearTimeout(deltaBufferTimer);
deltaBufferTimer = setTimeout(function () {
if (window.localStorage) {
localStorage.SS_deltaBuffer = deltaBuffer.join(',');
}
}, 1000);
return !allDeltasDivisableBy(120) && !allDeltasDivisableBy(100);
}
function isDivisible(n, divisor) {
return (Math.floor(n / divisor) == n / divisor);
}
function allDeltasDivisableBy(divisor) {
return (isDivisible(deltaBuffer[0], divisor) &&
isDivisible(deltaBuffer[1], divisor) &&
isDivisible(deltaBuffer[2], divisor));
}
function isInsideYoutubeVideo(event) {
var elem = event.target;
var isControl = false;
if (document.URL.indexOf ('www.youtube.com/watch') != -1) {
do {
isControl = (elem.classList &&
elem.classList.contains('html5-video-controls'));
if (isControl) break;
} while (elem = elem.parentNode);
}
return isControl;
}
var requestFrame = (function () {
return (window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function (callback, element, delay) {
window.setTimeout(callback, delay || (1000/60));
});
})();
var MutationObserver = (window.MutationObserver ||
window.WebKitMutationObserver ||
window.MozMutationObserver);
var getScrollRoot = (function() {
var SCROLL_ROOT;
return function() {
if (!SCROLL_ROOT) {
var dummy = document.createElement('div');
dummy.style.cssText = 'height:10000px;width:1px;';
document.body.appendChild(dummy);
var bodyScrollTop = document.body.scrollTop;
var docElScrollTop = document.documentElement.scrollTop;
window.scrollBy(0, 3);
if (document.body.scrollTop != bodyScrollTop)
(SCROLL_ROOT = document.body);
else
(SCROLL_ROOT = document.documentElement);
window.scrollBy(0, -3);
document.body.removeChild(dummy);
}
return SCROLL_ROOT;
};
})();
/***********************************************
* PULSE (by Michael Herf)
***********************************************/
/**
* Viscous fluid with a pulse for part and decay for the rest.
* - Applies a fixed force over an interval (a damped acceleration), and
* - Lets the exponential bleed away the velocity over a longer interval
* - Michael Herf, http://stereopsis.com/stopping/
*/
function pulse_(x) {
var val, start, expx;
// test
x = x * options.pulseScale;
if (x < 1) { // acceleartion
val = x - (1 - Math.exp(-x));
} else { // tail
// the previous animation ended here:
start = Math.exp(-1);
// simple viscous drag
x -= 1;
expx = 1 - Math.exp(-x);
val = start + (expx * (1 - start));
}
return val * options.pulseNormalize;
}
function pulse(x) {
if (x >= 1) return 1;
if (x <= 0) return 0;
if (options.pulseNormalize == 1) {
options.pulseNormalize /= pulse_(1);
}
return pulse_(x);
}
/***********************************************
* FIRST RUN
***********************************************/
var userAgent = window.navigator.userAgent;
var isEdge = /Edge/.test(userAgent); // thank you MS
var isChrome = /chrome/i.test(userAgent) && !isEdge;
var isSafari = /safari/i.test(userAgent) && !isEdge;
var isMobile = /mobile/i.test(userAgent);
var isIEWin7 = /Windows NT 6.1/i.test(userAgent) && /rv:11/i.test(userAgent);
var isEnabledForBrowser = (isChrome || isSafari || isIEWin7) && !isMobile;
var wheelEvent;
if ('onwheel' in document.createElement('div'))
wheelEvent = 'wheel';
else if ('onmousewheel' in document.createElement('div'))
wheelEvent = 'mousewheel';
if (wheelEvent && isEnabledForBrowser) {
addEvent(wheelEvent, wheel);
addEvent('mousedown', mousedown);
addEvent('load', init);
}
/***********************************************
* PUBLIC INTERFACE
***********************************************/
function SmoothScroll(optionsToSet) {
for (var key in optionsToSet)
if (defaultOptions.hasOwnProperty(key))
options[key] = optionsToSet[key];
}
SmoothScroll.destroy = cleanup;
if (window.SmoothScrollOptions) // async API
SmoothScroll(window.SmoothScrollOptions)
if (typeof define === 'function' && define.amd)
define(function() {
return SmoothScroll;
});
else if ('object' == typeof exports)
module.exports = SmoothScroll;
else
window.SmoothScroll = SmoothScroll;
})();
I believe the purpose of noConflict is to relinquish control of the $ global variable for external libraries, so doing var $ = jQuery.noConflict(); just sets the global $ to what noConflict returns, which is the jQuery object. In other words, it doesn't buy you anything - it's simply setting $ to what $ would be, even without the noConflict() method.
Change the $ to $j like the following:
var $j = jQuery.noConflict();
$j(document).ready(function() {
$j(function() {
var $ticker = $j('#news-ticker'),
$first = $j('.news-ticket-class li:first-child', $ticker);
// put an empty space between each letter so we can
// use break word
$j('.news-ticket-class li', $ticker).each(function() {
var $this = $j(this),
text = $this.text();
$this.html(text.split('').join('​'));
});
// begin the animation
function tick($el) {
$el.addClass('tick')
.one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function() {
$el.removeClass('tick');
var $next = $el.next('li');
$next = $next.length > 0 ? $next : $first;
tick($next);
});
}
tick($first);
});
});

How did I break the auto resize feature of the Automatic Image Montage jQuery plugin?

Sorry in advance if this is confusing. I've incorporated the Automatic Image Montage jQuery plugin for a page I'm working on and seem to have broken the feature that automatically resizes images upon a window resize event. Everything else about the plugin is working as it should. What am I doing wrong?
I'm pretty inexperienced with jQuery and Javascript, but have only modified a few of the max/min image size options in the plugin's js file. The internal reference in the js file that seems related to this problem is 'smartresize.' If you don't want to download the demo from the link above I've included a de-minified version of the js file below. First, my relevant css and html are as follows:
CSS
/*=========================automontage==============================*/
.am-container {
margin-top:75px;
}
.am-wrapper{
float:left;
position:relative;
overflow:hidden;
}
.am-wrapper img{
position:absolute;
outline:none;
}
/*=========================automontage==============================*/
HTML
<div class="am-container" id="am-container">
<img src="img/265_s.jpg"></img>
<img src="img/mont1_cloud_s.jpg"></img>
<img src="img/san_diego_street.jpg"></img>
<img src="img/IMG_8576_s.jpg"></img>
<img src="img/IMG_9827_1_s.jpg"></img>
<img src="img/IMG_0999_s.jpg"></img>
<img src="img/Lake_pano_11.jpg"></img>
<img src="img/IMG_8967_s.jpg"></img>
<img src="img/IMG_1346_s.jpg"></img>
<img src="img/IMG_2450.jpg"></img>
</div>
In HTML script
<script type="text/javascript" src="js/jquery.montage.min.js"></script>
<script type="text/javascript">
/*automontage*/
$(function() {
var $container = $('#am-container'),
$imgs = $container.find('img').hide(),
totalImgs = $imgs.length,
cnt = 0;
$imgs.each(function(i) {
var $img = $(this);
$('<img/>').load(function() {
++cnt;
if( cnt === totalImgs ) {
$imgs.show();
$container.montage({
fillLastRow : true,
alternateHeight : true,
alternateHeightRange : {
min : 150,
max : 350
}
});
}
}).attr('src',$img.attr('src'));
});
});
</script>
jQuery Plugin File Code (de-minified)
/**
* jQuery Montage plugin
* http://www.codrops.com/
*
* Copyright 2011, Pedro Botelho
* Licensed under the MIT license.
* http://www.opensource.org/licenses/mit-license.php
*
* Date: Tue Aug 30 2011
*/
(function( window, $, undefined ) {
/*
* Array.max, Array.min
* #John Resig
* http://ejohn.org/blog/fast-javascript-maxmin/
*/
// function to get the Max value in array
Array.max = function( array ){
return Math.max.apply( Math, array );
};
// function to get the Min value in array
Array.min = function( array ){
return Math.min.apply( Math, array );
};
/*
* smartresize: debounced resize event for jQuery
*
* latest version and complete README available on Github:
* https://github.com/louisremi/jquery.smartresize.js
*
* Copyright 2011 #louis_remi
* Licensed under the MIT license.
*/
var $event = $.event, resizeTimeout;
$event.special.smartresize = {
setup: function() {
$(this).bind( "resize", $event.special.smartresize.handler );
},
teardown: function() {
$(this).unbind( "resize", $event.special.smartresize.handler );
},
handler: function( event, execAsap ) {
// Save the context
var context = this,
args = arguments;
// set correct event type
event.type = "smartresize";
if ( resizeTimeout ) { clearTimeout( resizeTimeout ); }
resizeTimeout = setTimeout(function() {
jQuery.event.handle.apply( context, args );
}, execAsap === "execAsap"? 0 : 50 );
}
};
$.fn.smartresize = function( fn ) {
return fn ? this.bind( "smartresize", fn ) : this.trigger( "smartresize", ["execAsap"] );
};
// ======================= imagesLoaded Plugin ===============================
// https://github.com/desandro/imagesloaded
// $('#my-container').imagesLoaded(myFunction)
// execute a callback when all images have loaded.
// needed because .load() doesn't work on cached images
// callback function gets image collection as argument
// `this` is the container
// original: mit license. paul irish. 2010.
// contributors: Oren Solomianik, David DeSandro, Yiannis Chatzikonstantinou
$.fn.imagesLoaded = function( callback ) {
var $images = this.find('img'),
len = $images.length,
_this = this,
blank = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==';
function triggerCallback() {
callback.call( _this, $images );
}
function imgLoaded() {
if ( --len <= 0 && this.src !== blank ){
setTimeout( triggerCallback );
$images.unbind( 'load error', imgLoaded );
}
}
if ( !len ) {
triggerCallback();
}
$images.bind( 'load error', imgLoaded ).each( function() {
// cached images don't fire load sometimes, so we reset src.
if (this.complete || this.complete === undefined){
var src = this.src;
// webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f
// data uri bypasses webkit log warning (thx doug jones)
this.src = blank;
this.src = src;
}
});
return this;
};
$.Montage = function( options, element ) {
this.element = $( element ).show();
this.cache = {};
this.heights = new Array();
this._create( options );
};
$.Montage.defaults = {
liquid : true, // if you use percentages (or no width at all) for the container's width, then set this to true
// this will set the body's overflow-y to scroll ( fix for the scrollbar's width problem )
margin : 1, // space between images.
minw : 70, // the minimum width that a picture should have.
minh : 20, // the minimum height that a picture should have.
maxh : 250, // the maximum height that a picture should have.
alternateHeight : false,// alternate the height value for every row. If true this has priority over defaults.fixedHeight.
alternateHeightRange : { // the height will be a random value between min and max.
min : 100,
max : 300
},
fixedHeight : null, // if the value is set this has priority over defaults.minsize. All images will have this height.
minsize : false,// minw,minh are irrelevant. Chosen height is the minimum one available.
fillLastRow : false // if true, there will be no gaps in the container. The last image will fill any white space available
};
$.Montage.prototype = {
_getImageWidth : function( $img, h ) {
var i_w = $img.width(), i_h = $img.height(), r_i = i_h / i_w;
return Math.ceil( h / r_i );
},
_getImageHeight : function( $img, w ) {
var i_w = $img.width(), i_h = $img.height(), r_i = i_h / i_w;
return Math.ceil( r_i * w );
},
_chooseHeight : function() {
// get the minimum height
if( this.options.minsize ) {
return Array.min( this.heights );
}
// otherwise get the most repeated heights. From those choose the minimum.
var result = {},
max = 0,
res, val, min;
for( var i = 0, total = this.heights.length; i < total; ++i ) {
var val = this.heights[i], inc = ( result[val] || 0 ) + 1;
if( val < this.options.minh || val > this.options.maxh ) continue;
result[val] = inc;
if( inc >= max ) {
max = inc; res = val;
}
}
for (var i in result) {
if (result[i] === max) {
val = i;
min = min || val;
if(min < this.options.minh)
min = null;
else if (min > val)
min = val;
if(min === null)
min = val;
}
}
if(min === undefined) min = this.heights[0];
res = min;
return res;
},
_stretchImage : function( $img ) {
var prevWrapper_w = $img.parent().width(),
new_w = prevWrapper_w + this.cache.space_w_left,
crop = {
x : new_w,
y : this.theHeight
};
var new_image_w = $img.width() + this.cache.space_w_left,
new_image_h = this._getImageHeight( $img, new_image_w );
this._cropImage( $img, new_image_w, new_image_h, crop );
this.cache.space_w_left = this.cache.container_w;
// if this.options.alternateHeight is true, change row / change height
if( this.options.alternateHeight)
this.theHeight = Math.floor( Math.random()*( this.options.alternateHeightRange.max - this.options.alternateHeightRange.min + 1 ) + this.options.alternateHeightRange.min );
},
_updatePrevImage : function( $nextimg ) {
var $prevImage = this.element.find('img.montage:last');
this._stretchImage( $prevImage );
this._insertImage( $nextimg );
},
_insertImage : function( $img ) {
// width the image should have with height = this.theHeight.
var new_w = this._getImageWidth( $img, this.theHeight );
// use the minimum height available if this.options.minsize = true.
if( this.options.minsize && !this.options.alternateHeight ) {
if( this.cache.space_w_left <= this.options.margin * 2 ) {
this._updatePrevImage( $img );
}
else {
if( new_w > this.cache.space_w_left ) {
var crop = { x : this.cache.space_w_left, y : this.theHeight };
this._cropImage( $img, new_w, this.theHeight, crop );
this.cache.space_w_left = this.cache.container_w;
$img.addClass('montage');
}
else {
var crop = { x : new_w, y : this.theHeight };
this._cropImage( $img, new_w, this.theHeight, crop );
this.cache.space_w_left -= new_w;
$img.addClass('montage');
}
}
}
else {
// the width is lower than the minimum width allowed.
if( new_w < this.options.minw ) {
// the minimum width allowed is higher than the space left to fill the row.
// need to resize the previous (last) item in that row.
if( this.options.minw > this.cache.space_w_left ) {
this._updatePrevImage( $img );
}
else {
var new_w = this.options.minw, new_h = this._getImageHeight( $img, new_w ), crop = { x : new_w, y : this.theHeight };
this._cropImage( $img, new_w, new_h, crop );
this.cache.space_w_left -= new_w;
$img.addClass('montage');
}
}
else {
// the new width is higher than the space left but the space left is lower than the minimum width allowed.
// need to resize the previous (last) item in that row.
if( new_w > this.cache.space_w_left && this.cache.space_w_left < this.options.minw ) {
this._updatePrevImage( $img );
}
else if( new_w > this.cache.space_w_left && this.cache.space_w_left >= this.options.minw ) {
var crop = {x : this.cache.space_w_left, y : this.theHeight};
this._cropImage( $img, new_w, this.theHeight, crop );
this.cache.space_w_left = this.cache.container_w;
// if this.options.alternateHeight is true, change row / change height
if( this.options.alternateHeight)
this.theHeight = Math.floor( Math.random()*( this.options.alternateHeightRange.max - this.options.alternateHeightRange.min + 1 ) + this.options.alternateHeightRange.min );
$img.addClass('montage');
}
else {
var crop = { x : new_w, y : this.theHeight};
this._cropImage( $img, new_w, this.theHeight, crop );
this.cache.space_w_left -= new_w;
$img.addClass('montage');
}
}
}
},
_cropImage : function( $img, w, h, cropParam ) {
// margin value
var dec = this.options.margin * 2;
var $wrapper = $img.parent('a');
// resize the image
this._resizeImage( $img, w, h );
// adjust the top / left values to slice the image without loosing the its ratio
$img.css({
left : - ( w - cropParam.x ) / 2 + 'px',
top : - ( h - cropParam.y ) / 2 + 'px'
});
// wrap the image in a <a> element
$wrapper.addClass('am-wrapper').css({
width : cropParam.x - dec + 'px',
height : cropParam.y + 'px',
margin : this.options.margin
});
},
_resizeImage : function( $img, w, h ) {
$img.css( { width : w + 'px', height : h + 'px' } );
},
_reload : function() {
// container's width
var new_el_w = this.element.width();
// if different, something changed...
if( new_el_w !== this.cache.container_w ) {
this.element.hide();
this.cache.container_w = new_el_w;
this.cache.space_w_left = new_el_w;
var instance = this;
instance.$imgs.removeClass('montage').each( function(i) {
instance._insertImage( $(this) );
});
if( instance.options.fillLastRow && instance.cache.space_w_left !== instance.cache.container_w ) {
instance._stretchImage( instance.$imgs.eq( instance.totalImages - 1 ) );
}
instance.element.show();
}
},
_create : function( options ) {
this.options = $.extend( true, {}, $.Montage.defaults, options );
var instance = this,
el_w = instance.element.width();
instance.$imgs = instance.element.find('img');
instance.totalImages= instance.$imgs.length;
// solve the scrollbar width problem.
if( instance.options.liquid )
$('html').css( 'overflow-y', 'scroll' );
// save the heights of all images.
if( !instance.options.fixedHeight ) {
instance.$imgs.each( function(i) {
var $img = $(this), img_w = $img.width();
// if images have width > instance.options.minw then "resize" image.
if( img_w < instance.options.minw && !instance.options.minsize ) {
var new_h = instance._getImageHeight( $img, instance.options.minw );
instance.heights.push( new_h );
}
else {
instance.heights.push( $img.height() );
}
});
}
// calculate which height to use for each image.
instance.theHeight = ( !instance.options.fixedHeight && !instance.options.alternateHeight ) ? instance._chooseHeight() : instance.options.fixedHeight;
if( instance.options.alternateHeight )
instance.theHeight = Math.floor( Math.random() * ( instance.options.alternateHeightRange.max - instance.options.alternateHeightRange.min + 1 ) + instance.options.alternateHeightRange.min );
// save some values.
instance.cache.container_w = el_w;
// space left to fill the row.
instance.cache.space_w_left = el_w;
// wrap the images with the right sizes.
instance.$imgs.each( function(i) {
instance._insertImage( $(this) );
});
if( instance.options.fillLastRow && instance.cache.space_w_left !== instance.cache.container_w ) {
instance._stretchImage( instance.$imgs.eq( instance.totalImages - 1 ) );
}
// window resize event : reload the container.
$(window).bind('smartresize.montage', function() {
instance._reload();
});
},
add : function( $images, callback ) {
// adds one or more images to the container
var $images_stripped = $images.find('img');
this.$imgs = this.$imgs.add( $images_stripped );
this.totalImages= this.$imgs.length;
this._add( $images, callback );
},
_add : function( $images, callback ) {
var instance = this;
$images.find('img').each( function(i) {
instance._insertImage( $(this) );
});
if( instance.options.fillLastRow && instance.cache.space_w_left !== instance.cache.container_w )
instance._stretchImage( instance.$imgs.eq( instance.totalImages - 1 ) );
if ( callback ) callback.call( $images );
},
destroy : function( callback ) {
this._destroy( callback );
},
_destroy : function( callback ) {
this.$imgs.removeClass('montage').css({
position : '',
width : '',
height : '',
left : '',
top : ''
}).unwrap();
if( this.options.liquid )
$('html').css( 'overflow', '' );
this.element.unbind('.montage').removeData('montage');
$(window).unbind('.montage');
if ( callback ) callback.call();
},
option : function( key, value ) {
// set options AFTER initialization:
if ( $.isPlainObject( key ) ){
this.options = $.extend( true, this.options, key );
}
}
};
// taken from jquery.masonry
// https://github.com/desandro/masonry
// helper function for logging errors
// $.error breaks jQuery chaining
var logError = function( message ) {
if ( this.console ) {
console.error( message );
}
};
// Structure taken from jquery.masonry
// https://github.com/desandro/masonry
// ======================= Plugin bridge ===============================
// leverages data method to either create or return $.Montage constructor
// A bit from jQuery UI
// https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js
// A bit from jcarousel
// https://github.com/jsor/jcarousel/blob/master/lib/jquery.jcarousel.js
$.fn.montage = function( options ) {
if ( typeof options === 'string' ) {
// call method
var args = Array.prototype.slice.call( arguments, 1 );
this.each(function() {
var instance = $.data( this, 'montage' );
if ( !instance ) {
logError( "cannot call methods on montage prior to initialization; " +
"attempted to call method '" + options + "'" );
return;
}
if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
logError( "no such method '" + options + "' for montage instance" );
return;
}
// apply method
instance[ options ].apply( instance, args );
});
}
else {
this.each(function() {
var instance = $.data( this, 'montage' );
if ( instance ) {
// apply options & reload
instance.option( options || {} );
instance._reload();
}
else {
// initialize new instance
$.data( this, 'montage', new $.Montage( options, this ) );
}
});
}
return this;
};
})( window, jQuery );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
Figured it out. Turns out that my jQuery plugin version, which I'd changed from 1.6.2 to 1.12.4, broke the plugin. I played with the plugin version until I found one that worked for the other plugins I'm using, too (magnific popup lightbox, automatic montage). Now all is working! 1.7.0 was what worked for all.

jQuery Slider and Uncaught TypeError in Wordpress

I'm a bit clueless regarding my FullWidth Image Slider in combination with the Openstrap Wordpress theme.
When the function is loaded, I always get this error:
Uncaught TypeError: undefined is not a function
And I guess, this has something to do with the jquery functions loaded in the openstrap theme. I already removed the jQuery.noConflict();, but that did not work out.
This is the link to my test site where the error occurs:
https://dillan.de/bfm/texte/
The slider is loaded with this function:
<script type="text/javascript">
$(function() {
$('#ei-slider').eislideshow({
easing : 'easeOutExpo',
titleeasing : 'easeOutExpo',
titlespeed : 1200
});
});
</script>
And this is the .js:
(function( window, $, undefined ) {
/*
* smartresize: debounced resize event for jQuery
*
* latest version and complete README available on Github:
* https://github.com/louisremi/jquery.smartresize.js
*
* Copyright 2011 #louis_remi
* Licensed under the MIT license.
*/
var $event = $.event, resizeTimeout;
$event.special.smartresize = {
setup: function() {
$(this).bind( "resize", $event.special.smartresize.handler );
},
teardown: function() {
$(this).unbind( "resize", $event.special.smartresize.handler );
},
handler: function( event, execAsap ) {
// Save the context
var context = this,
args = arguments;
// set correct event type
event.type = "smartresize";
if ( resizeTimeout ) { clearTimeout( resizeTimeout ); }
resizeTimeout = setTimeout(function() {
jQuery.event.handle.apply( context, args );
}, execAsap === "execAsap"? 0 : 100 );
}
};
$.fn.smartresize = function( fn ) {
return fn ? this.bind( "smartresize", fn ) : this.trigger( "smartresize", ["execAsap"] );
};
$.Slideshow = function( options, element ) {
this.$el = $( element );
/***** images ****/
// list of image items
this.$list = this.$el.find('ul.ei-slider-large');
// image items
this.$imgItems = this.$list.children('li');
// total number of items
this.itemsCount = this.$imgItems.length;
// images
this.$images = this.$imgItems.find('img:first');
/***** thumbs ****/
// thumbs wrapper
this.$sliderthumbs = this.$el.find('ul.ei-slider-thumbs').hide();
// slider elements
this.$sliderElems = this.$sliderthumbs.children('li');
// sliding div
this.$sliderElem = this.$sliderthumbs.children('li.ei-slider-element');
// thumbs
this.$thumbs = this.$sliderElems.not('.ei-slider-element');
// initialize slideshow
this._init( options );
};
$.Slideshow.defaults = {
// animation types:
// "sides" : new slides will slide in from left / right
// "center": new slides will appear in the center
animation : 'sides', // sides || center
// if true the slider will automatically slide, and it will only stop if the user clicks on a thumb
autoplay : false,
// interval for the slideshow
slideshow_interval : 3000,
// speed for the sliding animation
speed : 800,
// easing for the sliding animation
easing : '',
// percentage of speed for the titles animation. Speed will be speed * titlesFactor
titlesFactor : 0.60,
// titles animation speed
titlespeed : 800,
// titles animation easing
titleeasing : '',
// maximum width for the thumbs in pixels
thumbMaxWidth : 150
};
$.Slideshow.prototype = {
_init : function( options ) {
this.options = $.extend( true, {}, $.Slideshow.defaults, options );
// set the opacity of the title elements and the image items
this.$imgItems.css( 'opacity', 0 );
this.$imgItems.find('div.ei-title > *').css( 'opacity', 0 );
// index of current visible slider
this.current = 0;
var _self = this;
// preload images
// add loading status
this.$loading = $('<div class="ei-slider-loading">Loading</div>').prependTo( _self.$el );
$.when( this._preloadImages() ).done( function() {
// hide loading status
_self.$loading.hide();
// calculate size and position for each image
_self._setImagesSize();
// configure thumbs container
_self._initThumbs();
// show first
_self.$imgItems.eq( _self.current ).css({
'opacity' : 1,
'z-index' : 10
}).show().find('div.ei-title > *').css( 'opacity', 1 );
// if autoplay is true
if( _self.options.autoplay ) {
_self._startSlideshow();
}
// initialize the events
_self._initEvents();
});
},
_preloadImages : function() {
// preloads all the large images
var _self = this,
loaded = 0;
return $.Deferred(
function(dfd) {
_self.$images.each( function( i ) {
$('<img/>').load( function() {
if( ++loaded === _self.itemsCount ) {
dfd.resolve();
}
}).attr( 'src', $(this).attr('src') );
});
}
).promise();
},
_setImagesSize : function() {
// save ei-slider's width
this.elWidth = this.$el.width();
var _self = this;
this.$images.each( function( i ) {
var $img = $(this);
imgDim = _self._getImageDim( $img.attr('src') );
$img.css({
width : imgDim.width,
height : imgDim.height,
marginLeft : imgDim.left,
marginTop : imgDim.top
});
});
},
_getImageDim : function( src ) {
var $img = new Image();
$img.src = src;
var c_w = this.elWidth,
c_h = this.$el.height(),
r_w = c_h / c_w,
i_w = $img.width,
i_h = $img.height,
r_i = i_h / i_w,
new_w, new_h, new_left, new_top;
if( r_w > r_i ) {
new_h = c_h;
new_w = c_h / r_i;
}
else {
new_h = c_w * r_i;
new_w = c_w;
}
return {
width : new_w,
height : new_h,
left : ( c_w - new_w ) / 2,
top : ( c_h - new_h ) / 2
};
},
_initThumbs : function() {
// set the max-width of the slider elements to the one set in the plugin's options
// also, the width of each slider element will be 100% / total number of elements
this.$sliderElems.css({
'max-width' : this.options.thumbMaxWidth + 'px',
'width' : 100 / this.itemsCount + '%'
});
// set the max-width of the slider and show it
this.$sliderthumbs.css( 'max-width', this.options.thumbMaxWidth * this.itemsCount + 'px' ).show();
},
_startSlideshow : function() {
var _self = this;
this.slideshow = setTimeout( function() {
var pos;
( _self.current === _self.itemsCount - 1 ) ? pos = 0 : pos = _self.current + 1;
_self._slideTo( pos );
if( _self.options.autoplay ) {
_self._startSlideshow();
}
}, this.options.slideshow_interval);
},
// shows the clicked thumb's slide
_slideTo : function( pos ) {
// return if clicking the same element or if currently animating
if( pos === this.current || this.isAnimating )
return false;
this.isAnimating = true;
var $currentSlide = this.$imgItems.eq( this.current ),
$nextSlide = this.$imgItems.eq( pos ),
_self = this,
preCSS = {zIndex : 10},
animCSS = {opacity : 1};
// new slide will slide in from left or right side
if( this.options.animation === 'sides' ) {
preCSS.left = ( pos > this.current ) ? -1 * this.elWidth : this.elWidth;
animCSS.left = 0;
}
// titles animation
$nextSlide.find('div.ei-title > h2')
.css( 'margin-right', 50 + 'px' )
.stop()
.delay( this.options.speed * this.options.titlesFactor )
.animate({ marginRight : 0 + 'px', opacity : 1 }, this.options.titlespeed, this.options.titleeasing )
.end()
.find('div.ei-title > h3')
.css( 'margin-right', -50 + 'px' )
.stop()
.delay( this.options.speed * this.options.titlesFactor )
.animate({ marginRight : 0 + 'px', opacity : 1 }, this.options.titlespeed, this.options.titleeasing )
$.when(
// fade out current titles
$currentSlide.css( 'z-index' , 1 ).find('div.ei-title > *').stop().fadeOut( this.options.speed / 2, function() {
// reset style
$(this).show().css( 'opacity', 0 );
}),
// animate next slide in
$nextSlide.css( preCSS ).stop().animate( animCSS, this.options.speed, this.options.easing ),
// "sliding div" moves to new position
this.$sliderElem.stop().animate({
left : this.$thumbs.eq( pos ).position().left
}, this.options.speed )
).done( function() {
// reset values
$currentSlide.css( 'opacity' , 0 ).find('div.ei-title > *').css( 'opacity', 0 );
_self.current = pos;
_self.isAnimating = false;
});
},
_initEvents : function() {
var _self = this;
// window resize
$(window).on( 'smartresize.eislideshow', function( event ) {
// resize the images
_self._setImagesSize();
// reset position of thumbs sliding div
_self.$sliderElem.css( 'left', _self.$thumbs.eq( _self.current ).position().left );
});
// click the thumbs
this.$thumbs.on( 'click.eislideshow', function( event ) {
if( _self.options.autoplay ) {
clearTimeout( _self.slideshow );
_self.options.autoplay = false;
}
var $thumb = $(this),
idx = $thumb.index() - 1; // exclude sliding div
_self._slideTo( idx );
return false;
});
}
};
var logError = function( message ) {
if ( this.console ) {
console.error( message );
}
};
$.fn.eislideshow = function( options ) {
if ( typeof options === 'string' ) {
var args = Array.prototype.slice.call( arguments, 1 );
this.each(function() {
var instance = $.data( this, 'eislideshow' );
if ( !instance ) {
logError( "cannot call methods on eislideshow prior to initialization; " +
"attempted to call method '" + options + "'" );
return;
}
if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
logError( "no such method '" + options + "' for eislideshow instance" );
return;
}
instance[ options ].apply( instance, args );
});
}
else {
this.each(function() {
var instance = $.data( this, 'eislideshow' );
if ( !instance ) {
$.data( this, 'eislideshow', new $.Slideshow( options, this ) );
}
});
}
return this;
};
})( window, jQuery );
The error is being caused by this line:
$(function() { // line 388
At this point in your code, jQuery is running in no conflict mode. This means it has renounced use of the dollar variable. AFAIK, this happens on most (all?) WordPress sites.
To solve this you can either change any occurence of $ to jQuery:
jQuery(function() {
jQuery('#ei-slider').eislideshow({
easing : 'easeOutExpo',
titleeasing : 'easeOutExpo',
titlespeed : 1200
});
});
or pass in a reference to the dollar variable as a parameter to the anonymous function. Within the anonymous function, you can then use $ as normal:
jQuery(function($) {
$('#ei-slider').eislideshow({
easing : 'easeOutExpo',
titleeasing : 'easeOutExpo',
titlespeed : 1200
});
});
This will make your slider work, as this demo shows.

Javascript: Detect a click on the scroll bar? [duplicate]

I'm trying to create custom events in JQuery that are supposed to detect when a scrollbar is clicked1.
I know there's lots of text, but all my questions are boldfaced and there's a JSFiddle example you can work on straight away.
Because I haven't found any built in functionality for this,
I had to create a hasScroll function, checking if the element has a scrollbar,
$.fn.hasScroll = function(axis){
var overflow = this.css("overflow"),
overflowAxis;
if(typeof axis == "undefined" || axis == "y") overflowAxis = this.css("overflow-y");
else overflowAxis = this.css("overflow-x");
var bShouldScroll = this.get(0).scrollHeight > this.innerHeight();
var bAllowedScroll = (overflow == "auto" || overflow == "visible") ||
(overflowAxis == "auto" || overflowAxis == "visible");
var bOverrideScroll = overflow == "scroll" || overflowAxis == "scroll";
return (bShouldScroll && bAllowedScroll) || bOverrideScroll;
};
and an inScrollRange function, checking if the click performed was within the scroll range.
var scrollSize = 18;
function inScrollRange(event){
var x = event.pageX,
y = event.pageY,
e = $(event.target),
hasY = e.hasScroll(),
hasX = e.hasScroll("x"),
rX = null,
rY = null,
bInX = false,
bInY = false
if(hasY){
rY = new RECT();
rY.top = e.offset().top;
rY.right = e.offset().left + e.width();
rY.bottom = rY.top +e.height();
rY.left = rY.right - scrollSize;
//if(hasX) rY.bottom -= scrollSize;
bInY = inRect(rY, x, y);
}
if(hasX){
rX = new RECT();
rX.bottom = e.offset().top + e.height();
rX.left = e.offset().left;
rX.top = rX.bottom - scrollSize;
rX.right = rX.left + e.width();
//if(hasY) rX.right -= scrollSize;
bInX = inRect(rX, x, y);
}
return bInX || bInY;
}
Are all scrollbar sizes uniform? E.g in Firefox and IE it's 18px.
Assuming there are no customized scrollbars, is there any extra padding or sizes in some browsers?
These functions all perform as intended (from what I can discern).
Making custom events was a bit trickier, but I got it to work somewhat. The only problem is that if the element clicked has a mousedown/up event attached to it, that will be triggered as well.
I can't seem to stop the other events from triggering while simultaneously triggering, what I call, the mousedownScroll/mouseupScroll events.
$.fn.mousedownScroll = function(fn, data){
if(typeof fn == "undefined" && typeof data == "undefined"){
$(this).trigger("mousedownScroll");
return;
}
$(this).on("mousedownScroll", data, fn);
};
$.fn.mouseupScroll = function(fn, data){
if(typeof fn == "undefined" && typeof data == "undefined"){
$(this).trigger("mouseupScroll");
return;
}
$(this).on("mouseupScroll", data, fn);
};
$(document).on("mousedown", function(e){
if(inScrollRange(e)){
$(e.target).trigger("mousedownScroll");
}
});
$(document).on("mouseup", function(e){
if(inScrollRange(e)){
$(e.target).trigger("mouseupScroll");
}
});
$("selector").mousedown(function(e){
console.log("Clicked content."); //Fired when clicking scroller as well
});
$("selector").mousedownScroll(function(e){
console.log("Clicked scroller.");
});
How do I stop the other "click" events from triggering?
While I'm asking, please feel free to optimize the code as much as possible.
Here's a JSFiddle to mess around with.
The reason I'm making this is because of a bigger plugin I'm developing. It's got a custom context menu that is showing up when I right click one of the scrollers. I don't want that. So I thought I should make an event that checks for scroll clicks (mouseup/downs) and then prevent the context menu from being displayed. In order to do that though, I need the scroll click to come before the normal click, and also, if possible, stop the normal clicks from firing.
I'm just thinking out loud here but maybe there's a way to get all the functions that are bound to the element and then switch the order in which they were added? I know that functions are executed in the order they were added (1st added 1st called), so, if I could tap into that process, perhaps the whole "registering" of the event to JQuery could just be inserted before the click events.
1 can only use mousedown/mouseup because click doesn't trigger when clicking on a scrollbar. If this is false, please provide a working example/code
Solved:
A shortest scrollbar click detection I could come up with, tested on IE, Firefox, Chrome.
var clickedOnScrollbar = function(mouseX){
if( $(window).outerWidth() <= mouseX ){
return true;
}
}
$(document).mousedown(function(e){
if( clickedOnScrollbar(e.clientX) ){
alert("clicked on scrollbar");
}
});
Working example:
https://jsfiddle.net/s6mho19z/
Use following solution to detect if user clicked mouse over element's scrollbar. Didn't test how it works with window's scrollbar. I guess Pete's solution works better with window scrolls.
window.addEventListener("mousedown", onMouseDown);
function onMouseDown(e) {
if (e.offsetX > e.target.clientWidth || e.offsetY > e.target.clientHeight)
{
// mouse down over scroll element
}
}
You may probably use this hack.
You could try hijacking the mousedown and mouseup events and avoiding them when click on a scrollbar with your custom powered function.
$.fn.mousedown = function(data, fn) {
if ( fn == null ) {
fn = data;
data = null;
}
var o = fn;
fn = function(e){
if(!inScrollRange(e)) {
return o.apply(this, arguments);
}
return;
};
if ( arguments.length > 0 ) {
return this.bind( "mousedown", data, fn );
}
return this.trigger( "mousedown" );
};
And the inverse for mousedownScroll and mouseupScroll events.
$.fn.mousedownScroll = function(data, fn) {
if ( fn == null ) {
fn = data;
data = null;
}
var o = fn;
fn = function(e){
if(inScrollRange(e)) {
e.type = "mousedownscroll";
return o.apply(this, arguments);
}
return;
};
if ( arguments.length > 0 ) {
return this.bind( "mousedown", data, fn );
}
return this.trigger( "mousedown" );
};
By the way, I think the scrollbar width is an OS setting.
Ensure that the content of your scollarea completely [over]fills the parent div.
Then, you can differentiate between clicks on your content and clicks on your container.
html:
<div class='test container'><div class='test content'></div></div>
<div id="results">please click</div>
css:
#results {
position: absolute;
top: 110px;
left: 10px;
}
.test {
position: absolute;
left: 0;
top: 0;
width: 100px;
height: 100px;
background-color: green;
}
.container {
overflow: scroll;
}
.content {
background-color: red;
}
js:
function log( _l ) {
$("#results").html( _l );
}
$('.content').on( 'mousedown', function( e ) {
log( "content-click" );
e.stopPropagation();
});
$('.container').on( 'mousedown', function( e ) {
var pageX = e.pageX;
var pageY = e.pageY;
log( "scrollbar-click" );
});
http://codepen.io/jedierikb/pen/JqaCb
I had the same problem in a previous project, and i recommend this solution. It's not very clean but it works and i doubt we can do much better with html. Here are the two steps of my solution:
1. Measure the width of the scrollbar on your Desktop environment.
In order to achieve this, at application startup, you perform the following things:
Add the following element to the body:
<div style='width: 50px; height: 50px; overflow: scroll'><div style='height: 1px;'/></div>
Measure the with of the inner div of the previously added element with jQUery's .width(), and store the width of the scrollbar somewhere (the width of the scollbar is 50 - inner div's with)
Remove the extra element used to measure scrollbar (now that you have the result, remove the element that you added to the body).
All these steps should not be visible by the user and you have the width of the scrollbar on your OS
For example, you can use this snippet:
var measureScrollBarWidth = function() {
var scrollBarMeasure = $('<div />');
$('body').append(scrollBarMeasure);
scrollBarMeasure.width(50).height(50)
.css({
overflow: 'scroll',
visibility: 'hidden',
position: 'absolute'
});
var scrollBarMeasureContent = $('<div />').height(1);
scrollBarMeasure.append(scrollBarMeasureContent);
var insideWidth = scrollBarMeasureContent.width();
var outsideWitdh = scrollBarMeasure.width();
scrollBarMeasure.remove();
return outsideWitdh - insideWidth;
};
2. Check if a click is on the scrollbar.
Now that you have the width of the scrollbar, you can with the coordinates of the event compute the coordinates of the event relative to the scrollbar's location rectangle and perfom awesome things...
If you want to filter the clicks, you can return false in the handler to prevent their propagation.
There are many answers here that involve event.clientX, element.clientHeight, etc. They are all wrong. Do not use them.
As has been discussed above, there are platforms where the overflow: scroll scrollbars appear as overlays, or you may have forced it with overflow: overlay.
Macs may switch scrollbars between persistent and overlay by plugging or unplugging a mouse. This shoots down the "measure on startup" technique.
Vertical scrollbars appear on the left side with right to left reading order. This breaks comparing client width unless you have a bunch of special logic for right to left reading order that I bet will break because you're probably not testing RTL consistently.
You need to look at event.target. If necessary, use an inner element that occupies all of the client area of the scroll element, and see if event.target is that element or a descendant of it.
It should be pointed out that on Mac OSX 10.7+, there are not persistant scroll bars. Scroll bars appear when you scroll, and disappear when your done. They are also much smaller then 18px (they are 7px).
Screenshot:
http://i.stack.imgur.com/zdrUS.png
I'll submit my own answer and accept Alexander's answer, because it made it work perfectly, and upvote Samuel's answer, because it correctly calculates the scrollbar width, which is what I needed as well.
That being said, I decided to make two independent events instead of trying to overwrite/override JQuery's mousedown event.
This gave me the flexibility I needed without messing with JQuery's own events, and was quite easy to do.
mousedownScroll
mousedownContent
Below are the two implementations using Alexanders, and my own.
Both work as I originally intended them to, but the former is probably the best.
Here's a JSFiddle that implements Alexander's answer + Samuel's answer.
$.fn.hasScroll = function(axis){
var overflow = this.css("overflow"),
overflowAxis;
if(typeof axis == "undefined" || axis == "y") overflowAxis = this.css("overflow-y");
else overflowAxis = this.css("overflow-x");
var bShouldScroll = this.get(0).scrollHeight > this.innerHeight();
var bAllowedScroll = (overflow == "auto" || overflow == "visible") ||
(overflowAxis == "auto" || overflowAxis == "visible");
var bOverrideScroll = overflow == "scroll" || overflowAxis == "scroll";
return (bShouldScroll && bAllowedScroll) || bOverrideScroll;
};
$.fn.mousedown = function(data, fn) {
if ( fn == null ) {
fn = data;
data = null;
}
var o = fn;
fn = function(e){
if(!inScrollRange(e)) {
return o.apply(this, arguments);
}
return;
};
if ( arguments.length > 0 ) {
return this.bind( "mousedown", data, fn );
}
return this.trigger( "mousedown" );
};
$.fn.mouseup = function(data, fn) {
if ( fn == null ) {
fn = data;
data = null;
}
var o = fn;
fn = function(e){
if(!inScrollRange(e)) {
return o.apply(this, arguments);
}
return;
};
if ( arguments.length > 0 ) {
return this.bind( "mouseup", data, fn );
}
return this.trigger( "mouseup" );
};
$.fn.mousedownScroll = function(data, fn) {
if ( fn == null ) {
fn = data;
data = null;
}
var o = fn;
fn = function(e){
if(inScrollRange(e)) {
e.type = "mousedownscroll";
return o.apply(this, arguments);
}
return;
};
if ( arguments.length > 0 ) {
return this.bind( "mousedown", data, fn );
}
return this.trigger( "mousedown" );
};
$.fn.mouseupScroll = function(data, fn) {
if ( fn == null ) {
fn = data;
data = null;
}
var o = fn;
fn = function(e){
if(inScrollRange(e)) {
e.type = "mouseupscroll";
return o.apply(this, arguments);
}
return;
};
if ( arguments.length > 0 ) {
return this.bind( "mouseup", data, fn );
}
return this.trigger( "mouseup" );
};
var RECT = function(){
this.top = 0;
this.left = 0;
this.bottom = 0;
this.right = 0;
}
function inRect(rect, x, y){
return (y >= rect.top && y <= rect.bottom) &&
(x >= rect.left && x <= rect.right)
}
var scrollSize = measureScrollWidth();
function inScrollRange(event){
var x = event.pageX,
y = event.pageY,
e = $(event.target),
hasY = e.hasScroll(),
hasX = e.hasScroll("x"),
rX = null,
rY = null,
bInX = false,
bInY = false
if(hasY){
rY = new RECT();
rY.top = e.offset().top;
rY.right = e.offset().left + e.width();
rY.bottom = rY.top +e.height();
rY.left = rY.right - scrollSize;
//if(hasX) rY.bottom -= scrollSize;
bInY = inRect(rY, x, y);
}
if(hasX){
rX = new RECT();
rX.bottom = e.offset().top + e.height();
rX.left = e.offset().left;
rX.top = rX.bottom - scrollSize;
rX.right = rX.left + e.width();
//if(hasY) rX.right -= scrollSize;
bInX = inRect(rX, x, y);
}
return bInX || bInY;
}
$(document).on("mousedown", function(e){
//Determine if has scrollbar(s)
if(inScrollRange(e)){
$(e.target).trigger("mousedownScroll");
}
});
$(document).on("mouseup", function(e){
if(inScrollRange(e)){
$(e.target).trigger("mouseupScroll");
}
});
});
function measureScrollWidth() {
var scrollBarMeasure = $('<div />');
$('body').append(scrollBarMeasure);
scrollBarMeasure.width(50).height(50)
.css({
overflow: 'scroll',
visibility: 'hidden',
position: 'absolute'
});
var scrollBarMeasureContent = $('<div />').height(1);
scrollBarMeasure.append(scrollBarMeasureContent);
var insideWidth = scrollBarMeasureContent.width();
var outsideWitdh = scrollBarMeasure.width();
scrollBarMeasure.remove();
return outsideWitdh - insideWidth;
};
Here's a JSFiddle of what I decided to do instead.
$.fn.hasScroll = function(axis){
var overflow = this.css("overflow"),
overflowAxis,
bShouldScroll,
bAllowedScroll,
bOverrideScroll;
if(typeof axis == "undefined" || axis == "y") overflowAxis = this.css("overflow-y");
else overflowAxis = this.css("overflow-x");
bShouldScroll = this.get(0).scrollHeight > this.innerHeight();
bAllowedScroll = (overflow == "auto" || overflow == "visible") ||
(overflowAxis == "auto" || overflowAxis == "visible");
bOverrideScroll = overflow == "scroll" || overflowAxis == "scroll";
return (bShouldScroll && bAllowedScroll) || bOverrideScroll;
};
$.fn.mousedownScroll = function(fn, data){
var ev_mds = function(e){
if(inScrollRange(e)) fn.call(data, e);
}
$(this).on("mousedown", ev_mds);
return ev_mds;
};
$.fn.mouseupScroll = function(fn, data){
var ev_mus = function(e){
if(inScrollRange(e)) fn.call(data, e);
}
$(this).on("mouseup", ev_mus);
return ev_mus;
};
$.fn.mousedownContent = function(fn, data){
var ev_mdc = function(e){
if(!inScrollRange(e)) fn.call(data, e);
}
$(this).on("mousedown", ev_mdc);
return ev_mdc;
};
$.fn.mouseupContent = function(fn, data){
var ev_muc = function(e){
if(!inScrollRange(e)) fn.call(data, e);
}
$(this).on("mouseup", ev_muc);
return ev_muc;
};
var RECT = function(){
this.top = 0;
this.left = 0;
this.bottom = 0;
this.right = 0;
}
function inRect(rect, x, y){
return (y >= rect.top && y <= rect.bottom) &&
(x >= rect.left && x <= rect.right)
}
var scrollSize = measureScrollWidth();
function inScrollRange(event){
var x = event.pageX,
y = event.pageY,
e = $(event.target),
hasY = e.hasScroll(),
hasX = e.hasScroll("x"),
rX = null,
rY = null,
bInX = false,
bInY = false
if(hasY){
rY = new RECT();
rY.top = e.offset().top;
rY.right = e.offset().left + e.width();
rY.bottom = rY.top +e.height();
rY.left = rY.right - scrollSize;
//if(hasX) rY.bottom -= scrollSize;
bInY = inRect(rY, x, y);
}
if(hasX){
rX = new RECT();
rX.bottom = e.offset().top + e.height();
rX.left = e.offset().left;
rX.top = rX.bottom - scrollSize;
rX.right = rX.left + e.width();
//if(hasY) rX.right -= scrollSize;
bInX = inRect(rX, x, y);
}
return bInX || bInY;
}
function measureScrollWidth() {
var scrollBarMeasure = $('<div />');
$('body').append(scrollBarMeasure);
scrollBarMeasure.width(50).height(50)
.css({
overflow: 'scroll',
visibility: 'hidden',
position: 'absolute'
});
var scrollBarMeasureContent = $('<div />').height(1);
scrollBarMeasure.append(scrollBarMeasureContent);
var insideWidth = scrollBarMeasureContent.width();
var outsideWitdh = scrollBarMeasure.width();
scrollBarMeasure.remove();
return outsideWitdh - insideWidth;
};
The only solution that works for me (only tested against IE11):
$(document).mousedown(function(e){
bScrollbarClicked = e.clientX > document.documentElement.clientWidth || e.clientY > document.documentElement.clientHeight;
});
I needed to detect scrollbar on mousedown but not on window but on div,
and I've had element that fill the content, that I was using to detect size without scrollbar:
.element {
position: relative;
}
.element .fill-node {
position: absolute;
left: 0;
top: -100%;
width: 100%;
height: 100%;
margin: 1px 0 0;
border: none;
opacity: 0;
pointer-events: none;
box-sizing: border-box;
}
the code for detect was similar to #DariuszSikorski answer but including offset and using the node that was inside scrollable:
function scrollbar_event(e, node) {
var left = node.offset().left;
return node.outerWidth() <= e.clientX - left;
}
var node = self.find('.fill-node');
self.on('mousedown', function(e) {
if (!scrollbar_event(e, node)) {
// click on content
}
});
Tested and working in chrome and firefox in ubuntu 21.10.
const isScrollClick =
e.offsetX > e.target.clientWidth || e.offsetY > e.target.clientHeight;
clickOnScrollbar = event.clientX > event.target.clientWidth || event.clientY > event.target.clientHeight;
tested on Chrome / Mac OS

stand-alone lazy loading images (no framework based)

I look after a site which by nature has to load quite a lot of images and content on the page. We have decreased the number of elements and graphical layout images as much as we can, so we are now looking at ways to increase the page load in the browser.
Does anyone know any code for lazy loading images that doesn't require a framework such as jQuery?
Here is my own. Have Fun.
Tested: IE 5.5+, FF 2+, Chrome, Opera 9.6+
Usage:
your lazyloaded images should have their real src in a thumb attribute
Just include the javascript file inline or externally.
If you don't want to use it on your entire page, you can do:
LazyImg().destroy(); // stop global fetching
LazyImg("watch-only-this-div");
Note: when you include the file a global instance is already created watchin the whole document. You need to stop that first and start you own instance.
set a custom offset for prefetching (how far below the fold the image should be fetched)
// watch the whole document
// prefetch offset: 300px
LazyImg(document, 300);
Code:
//
// LAZY Loading Images
//
// Handles lazy loading of images in one or more targeted divs,
// or in the entire page. It also keeps track of scrolling and
// resizing events, and removes itself if the work is done.
//
// Licensed under the terms of the MIT license.
//
// (c) 2010 Balázs Galambosi
//
(function(){
// glocal variables
var window = this,
instances = {},
winH;
// cross browser event handling
function addEvent( el, type, fn ) {
if ( window.addEventListener ) {
el.addEventListener( type, fn, false );
} else if ( window.attachEvent ) {
el.attachEvent( "on" + type, fn );
} else {
var old = el["on" + type];
el["on" + type] = function() { old(); fn(); };
}
}
// cross browser event handling
function removeEvent( el, type, fn ) {
if ( window.removeEventListener ) {
el.removeEventListener( type, fn, false );
} else if ( window.attachEvent ) {
el.detachEvent( "on" + type, fn );
}
}
// cross browser window height
function getWindowHeight() {
if ( window.innerHeight ) {
winH = window.innerHeight;
} else if ( document.documentElement.clientHeight ) {
winH = document.documentElement.clientHeight;
} else if ( document.body && document.body.clientHeight ) {
winH = document.body.clientHeight;
} else { // fallback:
winH = 10000; // just load all the images
}
return winH;
}
// getBoundingClientRect alternative
function findPos(obj) {
var top = 0;
if (obj && obj.offsetParent) {
do {
top += obj.offsetTop || 0;
top -= obj.scrollTop || 0;
} while (obj = obj.offsetParent); //
return { "top" : top };
}
}
// top position of an element
var getTopPos = (function() {
var dummy = document.createElement("div");
if ( dummy.getBoundingClientRect ) {
return function( el ) {
return el.$$top || el.getBoundingClientRect().top;
};
} else {
return function( el ) {
return el.$$top || findPos( el ).top;
};
}
})();
// sorts images by their vertical positions
function img_sort( a, b ) {
return getTopPos( a ) - getTopPos( b );
}
// let's just provide some interface
// for the outside world
var LazyImg = function( target, offset ) {
var imgs, // images array (ordered)
last, // last visible image (index)
id, // id of the target element
self; // this instance
offset = offset || 200; // for prefetching
if ( !target ) {
target = document;
id = "$document";
} else if ( typeof target === "string" ) {
id = target;
target = document.getElementById( target );
} else {
id = target.id || "$undefined";
}
// return if this instance already exists
if ( instances[id] ) {
return instances[id];
}
// or make a new instance
self = instances[id] = {
// init & reset
init: function() {
imgs = null;
last = 0;
addEvent( window, "scroll", self.fetchImages );
self.fetchImages();
return this;
},
destroy: function() {
removeEvent( window, "scroll", self.fetchImages );
delete instances[id];
},
// fetches images, starting at last (index)
fetchImages: function() {
var img, temp, len, i;
// still trying to get the target
target = target || document.getElementById( id );
// if it's the first time
// initialize images array
if ( !imgs && target ) {
temp = target.getElementsByTagName( "img" );
if ( temp.length ) {
imgs = [];
len = temp.length;
} else return;
// fill the array for sorting
for ( i = 0; i < len; i++ ) {
img = temp[i];
if ( img.nodeType === 1 && img.getAttribute("thumb") ) {
// store them and cache current
// positions for faster sorting
img.$$top = getTopPos( img );
imgs.push( img );
}
}
imgs.sort( img_sort );
}
// loop through the images
while ( imgs[last] ) {
img = imgs[last];
// delete cached position
if ( img.$$top ) img.$$top = null;
// check if the img is above the fold
if ( getTopPos( img ) < winH + offset ) {
// then change the src
img.src = img.getAttribute("thumb");
last++;
}
else return;
}
// we've fetched the last image -> finished
if ( last && last === imgs.length ) {
self.destroy();
}
}
};
return self.init();
};
// initialize
getWindowHeight();
addEvent( window, "load", LazyImg().fetchImages );
addEvent( window, "resize", getWindowHeight );
LazyImg();
window.LazyImg = LazyImg;
}());
"thumb" does not validate when using XHTML. I changed it to "title" and it seems to be working ok.

Categories

Resources