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.
Related
I am looping over all elements on my page which is handled by pushState and preventing default behaviour. I assume my function is pretty expensive, so I tried different other solutions with eventlisteners which did not work as expected. This function is running on each link click after the readystate event of that xhr request. In the end I am changing the content of my element by xhr and run this function again.
I also tried to do it like this: https://gomakethings.com/why-event-delegation-is-a-better-way-to-listen-for-events-in-vanilla-js/
which adds a single listeners which looks where you clicked, but this end up showing me other elements I clicked and not my a-elements so this didn't work either.
var dragging = false;
function addPushStateActionToAllLinks() {
var e = Array.from(document.getElementsByTagName("a"));
for ( var i = 0; i < e.length; i++ ) {
e[i].ontouchmove = function () {
dragging = true;
};
e[i].ontouchstart = function () {
dragging = false;
};
e[i].onclick = function ( el ) {
el.preventDefault ? el.preventDefault() : (el.returnValue = false);
};
if(e[i].getAttribute('rel') !== 'noopener noreferrer' && e[i].getAttribute('href') != "" ) {
e[i].ontouchend = function ( el ) {
if ( dragging === true ) {
return;
}
loadInternalLinkByXhr( this, true );
el.preventDefault ? el.preventDefault() : (el.returnValue = false);
};
} else {
e[i].ontouchend = function ( el ) {
if ( dragging === true ) {
return;
}
loadExternalLink( this );
el.preventDefault ? el.preventDefault() : (el.returnValue = false);
};
}
}
}
EDIT:
I also tried this, works as expected but i assume click is slower on mobile devices:
function someFunction( ) {
var e = document.getElementsByTagName("a");
for ( var i = 0; i < e.length; i++ ) {
if(e[i].getAttribute('rel') !== 'noopener noreferrer' && e[i].getAttribute('href') != "" ) {
e[i].onclick = function ( el ) {
if(typeof window.navigator.vibrate !== 'undefined') {
window.navigator.vibrate( 1 );
}
loadInternalLinkByXhr( this, true );
el.preventDefault ? el.preventDefault() : (el.returnValue = false);
};
} else {
e[i].onclick = function ( el ) {
if(typeof window.navigator.vibrate !== 'undefined') {
window.navigator.vibrate( 1 );
}
loadExternalLink( this );
el.preventDefault ? el.preventDefault() : (el.returnValue = false);
};
}
}
}
I want the most performant best practice for doing this. Only parts of my site is changing when you click a link, navigation, header etc. stay like they are. I tried adding eventlisteners to each element and it end up firing multiple xhr requests which got more and more and I was unable to figure out why this happens, I also tried removing the eventlistener before adding a new, but it still seemed to add multiple to it. This only worked on full page-requests for me, which I want to prevent. However, my function works as expected, before I was using onclick only, now I am trying ontouchend with move prevention because it might react a tiny bit faster. This project is new, so I am open to modern browser features and vanilla js.
You can use a single function for each event without duplicating them if you use function declarations in your original design.
function ontouchmove () {
dragging = true;
};
function ontouchstart() {
dragging = false;
};
function onclick( el ) {
el.preventDefault ? el.preventDefault() : (el.returnValue = false);
};
for ( var i = 0; i < e.length; i++ ) {
e[i].ontouchmove = ontouchmove;
e[i].ontouchstart ontouchstart;
e[i].onclick = onclick;
if(e[i].getAttribute('rel') !== 'noopener noreferrer' && e[i].getAttribute('href') != "" ) {
e[i].ontouchend = function ( el ) {
if ( dragging === true ) {
return;
}
loadInternalLinkByXhr( this, true );
el.preventDefault ? el.preventDefault() : (el.returnValue = false);
};
} else {
e[i].ontouchend = function ( el ) {
if ( dragging === true ) {
return;
}
loadExternalLink( this );
el.preventDefault ? el.preventDefault() : (el.returnValue = false);
};
}
}
}
Else, using JQuery to select all your elements at once and setting the event on the whole selection makes better sense.
var allLinks = $('a');
allLinks.on('touchmove', function () {
dragging = true;
};)
allLinks.on('touchstart', function () {
dragging = false;
};)
allLinks.on('cick', function () {
this.preventDefault ? this.preventDefault() : (this.returnValue = false);
};)
You can use .each method to iterate your selection and perform actions based on attributes.
allLinks.each(function() {
if ($(this).attr('rel') !== 'noopener noreferrer' && $(this).attr('href') != "" ){
...
}
});
this code work perfectly but i can't able to select a item from the suggest list using keyboard up and down key only can select using mouse what's the problem?
please help someone :/ :/ :/
https://jsfiddle.net/g60wc776/
/********************************************************************************
/*
* triggeredAutocomplete (jQuery UI autocomplete widget)
* 2012 by Hawkee.com (hawkee#gmail.com)
*
* Version 1.4.5
*
* Requires jQuery 1.7 and jQuery UI 1.8
*
* Dual licensed under MIT or GPLv2 licenses
* http://en.wikipedia.org/wiki/MIT_License
* http://en.wikipedia.org/wiki/GNU_General_Public_License
*
*/
;(function ( $, window, document, undefined ) {
$.widget("ui.triggeredAutocomplete", $.extend(true, {}, $.ui.autocomplete.prototype, {
options: {
trigger: "#",
allowDuplicates: true
},
_create:function() {
var self = this;
this.id_map = new Object();
this.stopIndex = -1;
this.stopLength = -1;
this.contents = '';
this.cursorPos = 0;
/** Fixes some events improperly handled by ui.autocomplete */
this.element.bind('keydown.autocomplete.fix', function (e) {
switch (e.keyCode) {
case $.ui.keyCode.ESCAPE:
self.close(e);
e.stopImmediatePropagation();
break;
case $.ui.keyCode.UP:
case $.ui.keyCode.DOWN:
if (!self.menu.element.is(":visible")) {
e.stopImmediatePropagation();
}
}
});
// Check for the id_map as an attribute. This is for editing.
var id_map_string = this.element.attr('id_map');
if(id_map_string) this.id_map = jQuery.parseJSON(id_map_string);
this.ac = $.ui.autocomplete.prototype;
this.ac._create.apply(this, arguments);
this.updateHidden();
// Select function defined via options.
this.options.select = function(event, ui) {
var contents = self.contents;
var cursorPos = self.cursorPos;
// Save everything following the cursor (in case they went back to add a mention)
// Separate everything before the cursor
// Remove the trigger and search
// Rebuild: start + result + end
var end = contents.substring(cursorPos, contents.length);
var start = contents.substring(0, cursorPos);
start = start.substring(0, start.lastIndexOf(self.options.trigger));
var top = self.element.scrollTop();
this.value = start + self.options.trigger+ui.item.label+' ' + end;
self.element.scrollTop(top);
// Create an id map so we can create a hidden version of this string with id's instead of labels.
self.id_map[ui.item.label] = ui.item.value;
self.updateHidden();
/** Places the caret right after the inserted item. */
var index = start.length + self.options.trigger.length + ui.item.label.length + 2;
if (this.createTextRange) {
var range = this.createTextRange();
range.move('character', index);
range.select();
} else if (this.setSelectionRange) {
this.setSelectionRange(index, index);
}
return false;
};
// Don't change the input as you browse the results.
this.options.focus = function(event, ui) { return false; }
this.menu.options.blur = function(event, ui) { return false; }
// Any changes made need to update the hidden field.
this.element.focus(function() { self.updateHidden(); });
this.element.change(function() { self.updateHidden(); });
},
// If there is an 'img' then show it beside the label.
_renderItem: function( ul, item ) {
if(item.img != undefined) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + "<img src='" + item.img + "' /><span>"+item.label+"</span></a>" )
.appendTo( ul );
}
else {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( $( "<a></a>" ).text( item.label ) )
.appendTo( ul );
}
},
// This stops the input box from being cleared when traversing the menu.
_move: function( direction, event ) {
if ( !this.menu.element.is(":visible") ) {
this.search( null, event );
return;
}
if ( this.menu.first() && /^previous/.test(direction) ||
this.menu.last() && /^next/.test(direction) ) {
this.menu.deactivate();
return;
}
this.menu[ direction ]( event );
},
search: function(value, event) {
var contents = this.element.val();
var cursorPos = this.getCursor();
this.contents = contents;
this.cursorPos = cursorPos;
// Include the character before the trigger and check that the trigger is not in the middle of a word
// This avoids trying to match in the middle of email addresses when '#' is used as the trigger
var check_contents = contents.substring(contents.lastIndexOf(this.options.trigger) - 1, cursorPos);
var regex = new RegExp('\\B\\'+this.options.trigger+'([\\w\\-]+)');
if (contents.indexOf(this.options.trigger) >= 0 && check_contents.match(regex)) {
// Get the characters following the trigger and before the cursor position.
// Get the contents up to the cursortPos first then get the lastIndexOf the trigger to find the search term.
contents = contents.substring(0, cursorPos);
var term = contents.substring(contents.lastIndexOf(this.options.trigger) + 1, contents.length);
// Only query the server if we have a term and we haven't received a null response.
// First check the current query to see if it already returned a null response.
if(this.stopIndex == contents.lastIndexOf(this.options.trigger) && term.length > this.stopLength) { term = ''; }
if(term.length > 0) {
// Updates the hidden field to check if a name was removed so that we can put them back in the list.
this.updateHidden();
return this._search(term);
}
else this.close();
}
},
// Slightly altered the default ajax call to stop querying after the search produced no results.
// This is to prevent unnecessary querying.
_initSource: function() {
var self = this, array, url;
if ( $.isArray(this.options.source) ) {
array = this.options.source;
this.source = function( request, response ) {
response( $.ui.autocomplete.filter(array, request.term) );
};
} else if ( typeof this.options.source === "string" ) {
url = this.options.source;
this.source = function( request, response ) {
if ( self.xhr ) {
self.xhr.abort();
}
self.xhr = $.ajax({
url: url,
data: request,
dataType: 'json',
success: function(data) {
if(data != null) {
response($.map(data, function(item) {
if (typeof item === "string") {
label = item;
}
else {
label = item.label;
}
// If the item has already been selected don't re-include it.
if(!self.id_map[label] || self.options.allowDuplicates) {
return item
}
}));
self.stopLength = -1;
self.stopIndex = -1;
}
else {
// No results, record length of string and stop querying unless the length decreases
self.stopLength = request.term.length;
self.stopIndex = self.contents.lastIndexOf(self.options.trigger);
self.close();
}
}
});
};
} else {
this.source = this.options.source;
}
},
destroy: function() {
$.Widget.prototype.destroy.call(this);
},
// Gets the position of the cursor in the input box.
getCursor: function() {
var i = this.element[0];
if(i.selectionStart) {
return i.selectionStart;
}
else if(i.ownerDocument.selection) {
var range = i.ownerDocument.selection.createRange();
if(!range) return 0;
var textrange = i.createTextRange();
var textrange2 = textrange.duplicate();
textrange.moveToBookmark(range.getBookmark());
textrange2.setEndPoint('EndToStart', textrange);
return textrange2.text.length;
}
},
// Populates the hidden field with the contents of the entry box but with
// ID's instead of usernames. Better for storage.
updateHidden: function() {
var trigger = this.options.trigger;
var top = this.element.scrollTop();
var contents = this.element.val();
for(var key in this.id_map) {
var find = trigger+key;
find = find.replace(/[^a-zA-Z 0-9#]+/g,'\\$&');
var regex = new RegExp(find, "g");
var old_contents = contents;
contents = contents.replace(regex, trigger+'['+this.id_map[key]+']');
if(old_contents == contents) delete this.id_map[key];
}
$(this.options.hidden).val(contents);
this.element.scrollTop(top);
}
}));
})( jQuery, window , document );
$('#inputbox').triggeredAutocomplete({
hidden: '#hidden_inputbox',
source: [
"Asp",
"BASIC",
"COBOL",
"ColdFusion",
"Erlang",
"Fortran",
"Groovy",
"Java",
"JavaScript",
"Lisp",
"Perl",
"PHP",
"Python",
"Ruby",
"Scala",
"Scheme"
],
trigger: "#"
});
<textarea id='inputbox' style='width: 400px; height: 90px;'></textarea>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
Ok, so I've created my own parallaxing jQuery/JS script, but I just don't know how to target browsers that will support the following (needs the following):
Supports transition for background-position
The site (preview) I'm trying this at is:
My Test Site
How can I detect whether a browser will support this though?
Can I run media queries bases on window width?
Do I have to browser sniff?
I can't see anything on the WWW that gives me clues as to how I can feature-detect for this.
Any help would be greatly appreciated.
My JS code is here: (please feel free to use it if you like it)
var goTop = 0;
var thisGoTop = 0;
var thisHeight = 0;
var thisWinH = 0;
var bottomIntrusion = 0;
var thisMax = 0;
var bgPos = 0;
function parallax(){
goTop = $(window).scrollTop();
thisWinH = $(window).height();
$('div.para').each(function(){
thisGoTop = $(this).offset().top;
thisHeight = $(this).height();
thisMax = Math.floor(thisHeight * 0.3);
bottomIntrusion = (thisGoTop + (thisHeight / 2) - goTop) / thisWinH;
if (bottomIntrusion > 0) {
bgPos = 0 - (Math.floor(thisMax * bottomIntrusion));
$(this).css('background-position','center ' + bgPos + 'px');
}
});
}
parallax();
$(window).scroll(function(){
parallax();
});
Edit:
I've looked into the Modernizr library, and I haven't found anything that gives me clues about background-position transform support for CSS3. I'm getting real close to brower sniffing at this point, and I'd hate to go there.
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script>
$( document ).ready( function() {
var Compatibility = function()
{
var context = this;
context.TestObject = function( id )
{
function CreateObject( id )
{
$('body').prepend('<div id="CompatibilityTestObject_' + id + '"></div>');
}
// Constructor
CreateObject( id );
return {
GetObject: function( id )
{
try
{
// Fetch with raw Javascript so if the javascript method does not exist it will throw an error
var fetchedDomElement = document.getElementById( "CompatibilityTestObject_" + id );
return fetchedDomElement;
}
catch( e )
{
// Failed to fetch DOM Element
return false;
}
},
DeleteObject: function( id )
{
try
{
$( "#CompatibilityTestObject_" + id ).remove();
return true;
}
catch( e )
{
// Failed to remove object
return false;
}
}
}
}
context.Factory = function()
{
return {
CreateTestObject: function( id )
{
var m_TestObject = new context.TestObject( id );
return m_TestObject.GetObject( id );
},
DeleteTestObject: function( id )
{
return context.DeleteObject( id );
}
}
}();
var CSS = function()
{
return {
BackgroundPosition: function()
{
var testObject = context.Factory.CreateTestObject( "BackgroundPosition" );
try
{
// My first try at testing for background positioning
testObject.style.backgroundPosition = "center";
return true;
}
catch( e )
{
// Implement the handling of this error
//alert( "Does not support backgroundPosition: " + e.message );
return false;
}
}
}
}();
return {
CheckCSS: CSS
}
}();
} );
</script>
Take a copy of the above script... place it in your code there, then call upon it like so:
if( Compatibility.CheckCSS.BackgroundPostion() )
{
// Compatible browser
}
else
{
// Not compatible
}
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!
Why doesn't this code work in IE6 or IE7?
$('a').click(
function()
{
var urlIsExternal = true;
var urlMedicareDir = '/medicare/';
var urlMedicareHost = 'health.healthcare.com';
var urlMedicare = 'https://' + urlMedicareHost + urlMedicareDir;
var urlAppsHost = 'apps.healthcare.com';
var urlCurrent = String( window.location );
var urlCurrentPrefix = urlCurrent.substring( 0, urlMedicare.length );
var urlCurrentURL = $.url( urlCurrent );
var urlClicked = $(this).attr('href');
var urlClickedURL = $.url( $(this).attr('href') );
var urlHost = urlClickedURL.attr('host');
if( !urlHost.length )
{
urlHost = urlCurrentURL.attr('host');
}
var urlConfirmMessage = 'You are now leaving the Medicare website.';
if( urlCurrentPrefix == urlMedicare )
{
if( urlClicked.substring( 0, 1 ) == '/' ) // starts with slash
{
if( urlClicked.substring( 0, urlMedicareDir.length ) == urlMedicareDir )
{
urlIsExternal = false;
}
}
if( urlClicked.substring( 0, urlMedicare.length ) == urlMedicare )
{
urlIsExternal = false;
}
if (
urlClicked.substring( 0, 1 ) != '/' &&
urlClicked.substring( 0, 4 ) != 'http' &&
urlClicked.substring( 0, 4 ) != 'file'
)
{
urlIsExternal = false;
}
if( urlAppsHost == urlHost )
{
urlIsExternal = false;
}
if( urlClicked.substring(urlClicked.length-4) == '.pdf' )
{
urlIsExternal = false;
}
}
else
{
urlIsExternal = false;
}
if( urlIsExternal )
{
if( confirm( urlConfirmMessage ) )
{
window.open( urlClicked );
return false;
}
else
{
return false;
}
}
else
{
return true;
}
}
);
For some reason when the links are clicked in IE6 or IE7, they do not direct the user to the link and it does not prompt a confirm dialog. It should prompt a confirm dialog, but for some reason, it is not.
I don't think you're preventing the default action of the anchor ("a").
You should start $('a').click( function( event ) { so that when you get here:
if( urlIsExternal ) {
// This tells jQuery to NOT follow the hyperlink
event.preventDefault();
if( confirm( urlConfirmMessage ) ) {
window.open( urlClicked );
}
}
However, what's really missing is that this code needs to run after the document has loaded. So you just need to wrap your function with
$(document).ready(function(){
$('a').click( function( event ) {
/* your code */
}
});
Without the call to $(document).ready(), the JavaScript runs before the body of the document is rendered, so it doesn't find any <a> tags to which it can attach the click event.
It seems that if the user clicks on a link that has an href starting with some value other than the current host, you want offer a confirm dialog. That is a realy annoying strategy, why doesn't the user know before clicking on the link that it wil take them elsewhere?
Anyway, a simple version of what you are trying to do is:
function showPrompt() {
return confirm('Do you really want to leaving ' + window.location.host +
'?\nPress OK to continue or Cancel to stay on this page.');
}
window.onload = function() {
// The links collection is live and available as a property of window
var link, links = document.links;
// Include criteria for host, hostName, protocol, whatever as required
var re = new RegExp(window.location.host || 'no host');
for (var i=0, iLen=links.length; i<iLen; i++) {
link = links[i];
// Only add the listener to links that need it
if (!re.test(link.href)) {
// Add the listener however you want, this way is simple and robust
link.onclick = showPrompt;
}
}
}