JS scroll after delay - javascript

I'm trying to make my website scroll to specific post that is on separate page. I figured the PHP part behind this to generate anchors for me however I'm stuck with JS part. I managed to make webpage start at position 0,0 and then to go to static anchor tag. What I struggle with is how do I make JS fetch anchor tag from current URL and then make it smoothly scroll to given tag after short delay.
My current code is:
$(document).ready(function() {
if (location.hash) {
window.scrollTo(0, 0);
}
});
setTimeout("window.location.hash = '#scroll';", 5000);
I found following snipped that fetches an anchor tag off URL but I'm not sure how can I make it execute after some delay.
$(document).ready(function() {
function filterPath(string) {
return string
.replace(/^\//,'')
.replace(/(index|default).[a-zA-Z]{3,4}$/,'')
.replace(/\/$/,'');
}
var locationPath = filterPath(location.pathname);
var scrollElem = scrollableElement('html', 'body');
$('a[href*=#]').each(function() {
var thisPath = filterPath(this.pathname) || locationPath;
if ( locationPath == thisPath
&& (location.hostname == this.hostname || !this.hostname)
&& this.hash.replace(/#/,'') ) {
var $target = $(this.hash), target = this.hash;
if (target) {
var targetOffset = $target.offset().top;
$(this).click(function(event) {
event.preventDefault();
$(scrollElem).animate({scrollTop: targetOffset}, 400, function() {
location.hash = target;
});
});
}
}
});
// use the first element that is "scrollable"
function scrollableElement(els) {
for (var i = 0, argLength = arguments.length; i <argLength; i++) {
var el = arguments[i],
$scrollElement = $(el);
if ($scrollElement.scrollTop()> 0) {
return el;
} else {
$scrollElement.scrollTop(1);
var isScrollable = $scrollElement.scrollTop()> 0;
$scrollElement.scrollTop(0);
if (isScrollable) {
return el;
}
}
}
return [];
}
});

I don't believe setTimeout accepts any old code passed as a string, only function names. Try using an anonymous function instead:
setTimeout(function() { window.location.hash = '#scroll'; }, 5000);

I managed to solve my problem using snippet that I found on CSS-Tricks forum. It scrolls to an anchor tag on page load, always starting from the very top of the page.
$(window).bind("ready", function() {
var urlHash = window.location.href.split("#")[1];
$('html,body').animate({scrollTop:$('a[href="#'+urlHash+'"]').offset().top}, 1500);
});

Related

Exit Intent in Mobile using javascrpt or jQuery

I tried modifying the plugin to show a modal popup when a website visitor leaves the page using haschange, but it still doesn't work. How to get it to work? I need help fixing it
$(document).ready(function(e) {
var exit_intent_popup_hash = 'b'
window.location.hash = exit_intent_popup_hash
window.history.back()
setTimeout(function() {
window.history.forward()
$('.fel-modal-parent-wrapper').each(function() {
var $this = $(this);
var tmp_id = $this.attr('id');
var popup_id = tmp_id.replace('-overlay', '');
var trigger_on = $this.data('trigger-on');
var exit_intent = $this.data('exit-intent');
if ('automatic' == trigger_on) {
if ('yes' == exit_intent && FelModalPopup_canShow(popup_id)) {
$(window).hashchange(function() {
if (window.location.hash !== `#${exit_intent_popup_hash}`) {
FelModalPopup_show(popup_id);
window.history.forward()
}
}, false);
}
}
});
}, 500);
});

Scroll to DIV using JQuery not working after page load

I am trying to scroll the page to DIV, whose ID is sent through QueryString. The HTML content of the page is loaded from the Server side in SharePoint 2010.
I have used setTimeout() to wait until the content is loaded on the page and after timeout I am applying logic to scroll to div. But The page is not scrolling. Code is as below:
ExecuteOrDelayUntilScriptLoaded(getThankyouMsg, 'sp.js');
function getThankyouMsg() {
var fid = getQueryStringParameter("fid");
setTimeout(function () {
//window.location.href = window.location.href.split('?')[0] + "#" + fid;
jQuery('html, body').animate({
scrollTop: jQuery("#" + fid).offset().top
}, 2000);
}, 7000);
}
function getQueryStringParameter(paramToRetrieve) {
var params = document.URL.split("?")[1].split("&");
for (var i = 0; i < params.length; i = i + 1) {
var singleParam = params[i].split("=");
if (singleParam[0] == paramToRetrieve)
return singleParam[1];
}
}
Can you please suggest what I am missing?
Thanks in advance.
I find solution for my question. We can use simple JavaScript instead of jQuery animate function.
ExecuteOrDelayUntilScriptLoaded(getThankyouMsg, 'sp.js');
function getThankyouMsg() {
var fid = getQueryStringParameter("fid");
setTimeout(function () {
location.hash = "#"+fid; //This line will navigates to Div ID
}, 7000);
}
function getQueryStringParameter(paramToRetrieve) {
var params = document.URL.split("?")[1].split("&");
for (var i = 0; i < params.length; i = i + 1) {
var singleParam = params[i].split("=");
if (singleParam[0] == paramToRetrieve)
return singleParam[1];
}
}
Location.Hash = "#divId"
will work to scroll down to particular div on the page.
There's no need to write your own function to wait for the page to load. There is a jQuery function for that: .ready()
Your scrolling code seems to work fine with dummy code. This might work a bit better for you:
$(document).ready(function() {
getThankyouMsg();
});
function getThankyouMsg() {
var fid = getQueryStringParameter("fid");
jQuery('html, body').animate({
scrollTop: jQuery("#" + fid).offset().top
}, 2000);
}
function getQueryStringParameter(paramToRetrieve) {
var params = document.URL.split("?")[1].split("&");
for (var i = 0; i < params.length; i = i + 1) {
var singleParam = params[i].split("=");
if (singleParam[0] == paramToRetrieve)
return singleParam[1];
}
}
That is assuming that getQueryStringParameter returns the correct value. There's no way for me to know this since it depends on your backend and the URL being used.

check if images not exist on load change src

I'm trying to change my image size with javascript to be 500x375 instead of 130x98. If there is no 500x37 for that image, than I would like it to fallback to 130x98.
So far, I have the code below. It changes my images to 500x375, but the ones that do not have that size it appears broken instead of falling back to 130x98. Any ideas on how to fix this?
function ImageExists(selector) {
var imageFound = $(selector);
if (imageFound.height() === 0) {
console.log('no height');
return false;
}
return true;
}
$('div.photo > a > img').each(function(k, v) {
var x = v.src;
v.src = x.replace('130x98', '500x375');
if (!ImageExists(v)) {
console.log(v.src);
v.src = x.replace('500x375', '130x98')
}
});
You can try this code
$(document).ready(function(){
var src1 = '130x98';
var src2 = '500x375';
$('div.photo > a > img').each(function(){
var changeSrc;
var Image = $(this);
var GetSrc = $(this).attr('src');
Image.error(function() {
if(GetSrc.indexOf(src1) !== -1 ){
changeSrc = GetSrc.replace(src1 , src2);
}else if(GetSrc.indexOf(src2) !== -1 ){
changeSrc = GetSrc.replace(src2 , src1);
}
Image.attr("src", changeSrc);
});
})
});
DEMO
Are you missing semicolon in v.src = x.replace('500x375', '130x98'):in this line??
try putting alert();function in which line you doubted... alert(); will not work if any previous line is in error
$('div.photo > a > img').each(function (k, v) {
var x = v.src;
v.src = x.replace('130x98', '500x375');
if (!ImageExists(v)) {
console.log(v.src);
v.src = x.replace('500x375', '130x98');
};
How about trying the on error event instead of your ImageExists method:
$("img").error(function () {
//load in your default image dimensions.
});
When there's an error loading the image this will be triggered.
You might also want to unbind this event the first time it us run in case it continuously loops.

Javascript Events using HTML Class Targets - 1 Me - 0

I am trying to create collapsible DIVs that react to links being clicked. I found how to do this using "next" but I wanted to put the links in a separate area. I came up with this which works...
JSFiddle - Works
function navLink(classs) {
this.classs = classs;
}
var homeLink = new navLink(".content-home");
var aboutLink = new navLink(".content-about");
var contactLink = new navLink(".content-contact");
var lastOpen = null;
$('.home').click(function() {
if(lastOpen !== null) {
if(lastOpen === homeLink) {
return; } else {
$(lastOpen.classs).slideToggle('fast');
}
}
$('.content-home').slideToggle('slow');
lastOpen = homeLink;
}
);
$('.about').click(function() {
if(lastOpen !== null) {
if(lastOpen === aboutLink) {
return; } else {
$(lastOpen.classs).slideToggle('fast');
}
}
$('.content-about').slideToggle('slow');
lastOpen = aboutLink;
}
);
$('.contact').click(function() {
if(lastOpen !== null) {
if(lastOpen === contactLink) {
return; } else {
$(lastOpen.classs).slideToggle('fast');
}
}
$('.content-contact').slideToggle('slow');
lastOpen = contactLink;
}
);​
I am now trying to create the same result but with a single function instead of one for each link. This is what I came up with....
function navLink(contentClass, linkClass, linkId) {
this.contentClass = contentClass;
this.linkClass = linkClass;
this.linkId = linkId;
}
var navs = [];
navs[0] = new navLink(".content-home", "nav", "home");
navs[1] = new navLink(".content-about", "nav", "about");
navs[2] = new navLink(".content-contact", "nav", "contact");
var lastOpen = null;
$('.nav').click(function(event) {
//loop through link objects
var i;
for (i = 0; i < (navsLength + 1); i++) {
//find link object that matches link clicked
if (event.target.id === navs[i].linkId) {
//if there is a window opened, close it
if (lastOpen !== null) {
//unless it is the link that was clicked
if (lastOpen === navs[i]) {
return;
} else {
//close it
$(lastOpen.contentClass).slideToggle('fast');
}
}
//open the content that correlates to the link clicked
$(navs[i].contentClass).slideToggle('slow');
navs[i] = lastOpen;
}
}
});​
JSFiddle - Doesn't Work
No errors so I assume that I am just doing this completely wrong. I've been working with Javascript for only about a week now. I've taken what I've learned about arrays and JQuery events and tried to apply them here. I assume I'm way off. Thoughts? Thanks
You just forgot to define navsLength:
var navsLength=navs.length;
Of course you could also replace it with a $().each loop as you're using jQuery.
[Update] Two other errors I corrected:
lastOpen=navs[i];
for(i=0; i < navsLength ; i++)
Demo: http://jsfiddle.net/jMzPJ/4/
Try:
var current, show = function(){
var id = this.id,
doShow = function() {
current = id;
$(".content-" + id).slideToggle('slow');
},
toHide = current && ".content-" + current;
if(current === id){ //Same link.
return;
}
toHide ? $(toHide).slideToggle('fast', doShow): doShow();;
};
$("#nav").on("click", ".nav", show);
http://jsfiddle.net/tarabyte/jMzPJ/5/

How to increase performance of this js script (function calls exponentially increasing)?

Any general tips how to increase a longish js code like this? It works great but sometimes it gets a little sluggish and all the drag/drop and ajax features slow down.
I know this code is a little longer so I am not looking for specific suggestions. Just your first thoughts after taking a quick glance at this code.
EDIT:
I have found a pretty scary thing. The calls to dragDrop() are exponentially increasing in the $('.folderListOnclick').click event. After each click dragDrop() is called 1 time, 2 times, 4 times, 8 times. That's what's slowing it down.
But I don't understand why it is happening.
<script type="text/javascript">
//<!--
$(document).ready(function() {
function in_array (needle, haystack, argStrict) {
var key = '', strict = !!argStrict;
if (strict) {
for (key in haystack) {
if (haystack[key] === needle) {
return true; }
}
} else {
for (key in haystack) {
if (haystack[key] == needle) {
return true;
}
}
}
return false;
}
var openedFolders = new Array();
var start = 0;
var stop = 0;
$('.drag').each(function() {
var draggables = $(this).parents('table').find('.drag');
var $next = draggables.filter(':gt(' + draggables.index(this) + ')').first();
var width = $(this).css('width');
var nextWidth = $next.css('width');
if (nextWidth > width /*&& 30 == parseInt(width)*/) {
$(this).removeClass('ordinaryFolderClosed');
$(this).removeClass('ordinaryFolderOpened');
if (in_array($(this).attr('rel'), openedFolders)) {
$(this).addClass('ordinaryFolderOpened');
} else {
$(this).addClass('ordinaryFolderClosed');
}
}
if (in_array($(this).attr('rel'), openedFolders)) {
start = 1;
}
if (1 == start && stop < 2) {
if (30 == parseInt(width)) {
stop++;
}
} else {
start = 0;
stop = 0;
if (parseInt(width) > 30) {
$(this).parent().parent().hide();
}
}
});
function dragDrop()
{
$('.folders .trow1').hover(
function () {
if ($(this).css('backgroundColor') != 'rgb(52, 108, 182)' && $(this).css('backgroundColor') != '#346cb6') {
$(this).css('background', "#C2E3EF");
}
},
function () {
if ($(this).css('backgroundColor') != 'rgb(52, 108, 182)' && $(this).css('backgroundColor') != '#346cb6') {
$(this).css('background', 'transparent');
}
}
);
$('.drag').click(function() {
if ($(this).hasClass('noclick')) {
$(this).removeClass('noclick');
} else {
var draggables = $(this).parents('table').find('.drag');
var $next = draggables.filter(':gt(' + draggables.index(this) + ')').first();
var width = $(this).css('width');
var nextWidth = $next.css('width');
if (nextWidth > width /*&& 30 == parseInt(width)*/) {
var isVisible = $next.is(':visible');
if (isVisible) {
$(this).removeClass('ordinaryFolderClosed');
$(this).removeClass('ordinaryFolderOpened');
$(this).addClass('ordinaryFolderClosed');
} else {
$(this).removeClass('ordinaryFolderClosed');
$(this).removeClass('ordinaryFolderOpened');
$(this).addClass('ordinaryFolderOpened');
}
clickedId = $(this).attr('rel');
clickedId = clickedId.split(',');
clickedType = clickedId[1];
clickedId = clickedId[0];
// $.ajax({
// type: 'POST',
// url: 'body/obsah/mediaManager/setOpenedFolder.php',
// data: 'id='+clickedId+'&type='+clickedType,
// success: function(msg){
// //alert(msg);
// }
// });
var start = 0;
var stop = 0;
var i = 0;
// close folder
if (isVisible) {
$('.drag').each(function() {
if (0 == start) {
iteratedId = $(this).attr('rel');
iteratedId = iteratedId.split(',');
iteratedId = iteratedId[0];
if (iteratedId == clickedId) {
start = 1;
}
}
if (1 == start && stop < 2) {
if ($(this).css('width') > width) {
$(this).parent().parent().hide();
if ($(this).hasClass('ordinaryFolderClosed') || $(this).hasClass('ordinaryFolderOpened')) {
$(this).removeClass('ordinaryFolderClosed');
$(this).removeClass('ordinaryFolderOpened');
$(this).addClass('ordinaryFolderClosed');
}
} else {
stop++;
}
}
i++;
});
}
// open folder
else {
$('.drag').each(function() {
if (0 == start) {
iteratedId = $(this).attr('rel');
iteratedId = iteratedId.split(',');
iteratedId = iteratedId[0];
if (iteratedId == clickedId) {
start = 1;
}
}
if (1 == start && stop < 2) {
if (parseInt($(this).css('width')) == parseInt(width)+5) {
$(this).parent().parent().show();
}
if (parseInt($(this).css('width')) == parseInt(width)) {
stop++;
}
}
i++;
});
}
}
}
});
var dragId = 0;
var dragType = 0;
var dropId = 0;
var dropType = 0;
var isFile = false;
$('.drag').draggable({
revert: true,
cursorAt: {top: 0, left: 0},
drag: function() {
if ($(this).attr('rel') !== undefined) {
dragId = $(this).attr('rel');
dragId = dragId.split(',');
dragType = dragId[1];
dragId = dragId[0];
}
isFile = false;
},
start: function(event, ui) {
$(this).addClass('noclick');
}
});
$('.drag2').draggable({
revert: true,
cursorAt: {top: 0, left: 0},
drag: function() {
if ($(this).attr('rel') !== undefined) {
dragId = $(this).attr('rel');
dragId = dragId.split(',');
dragType = dragId[1];
dragId = dragId[0];
}
isFile = true;
}
});
$('.drop').droppable({
tolerance: 'pointer',
drop: function() {
if ($(this).attr('rel') !== undefined) {
dropId = $(this).attr('rel');
dropId = dropId.split(',');
dropType = dropId[1];
dropId = dropId[0];
if (dropId != dragId) {
if (false == isFile) {
$.ajax({
type: 'POST',
url: 'body/obsah/mediaManager/folder_move.php',
data: 'nid='+dragId+'&pid='+dropId+'&ft='+dropType,
success: function(msg){
ajaxElementCall('left1', 'body/obsah/mediaManager/folder_list.php?type=1', 'right1', 'body/obsah/mediaManager/file_list.php?type=1&browse=0&assignType=0&CKEditorFuncNum=0&idFolder=0');
dragDrop();
}
});
} else if (true == isFile) {
$.ajax({
type: 'POST',
url: 'body/obsah/mediaManager/file_move.php',
data: 'fid='+dragId+'&did='+dropId+'&ft='+dropType,
success: function(msg){
ajaxElementCall('right1', 'body/obsah/mediaManager/file_list.php?type=1&browse=0&assignType=0&CKEditorFuncNum=0&idFolder=0&reloadTree=0');
dragDrop();
}
});
}
}
}
}
});
}
dragDrop();
$('.folderListOnclick').click(function() {
var append = 'idFolder='+$(this).attr('rel')+'&browse=0&assignType=0&CKEditorFuncNum=0&reloadTree=0';
ajaxElementCall('right1', 'body/obsah/mediaManager/file_list.php?type=1&'+append);
dragDrop();
$('.trow1').css('background', 'transparent');
$('.trow1').css('color', '#3e4245');
$(this).parent().css('background', "#346cb6 url('img/menuButtonOver.png') left top repeat-x");
$(this).parent().css('color', 'white');
});
$('.folderEditOnclick').click(function() {
var append = 'idFolder='+$(this).attr('rel')+'&browse=0&assignType=0&CKEditorFuncNum=0';
showModal('modal_div', 'Editácia adresára');
ajaxElementCall('modal_div', 'body/obsah/mediaManager/folder_edit.php?kam=edit1&'+append);
});
$('.folderDeleteOnclick').click(function() {
var append = 'idFolder='+$(this).attr('rel')+'&browse=0&assignType=0&CKEditorFuncNum=0';
showModal('modal_div', 'Vymazanie adresára');
ajaxElementCall('modal_div', 'body/obsah/mediaManager/folder_delete.php?kam=del1&'+append);
});
$('.addNewFolder').click(function() {
showModal('modal_div', 'Nový adresár');
var id = '0';
$('.folders .trow1').each(function() {
if ($(this).css('backgroundColor') == 'rgb(52, 108, 182)' || $(this).css('backgroundColor') == '#346cb6') {
id = $(this).attr('rel');
id = id.split(',');
id = id[0];
}
});
ajaxElementCall('modal_div', '/body/obsah/mediaManager/folder_add.php?type=1&kam=new1&idFolder='+id+'&browse=0&assignType=0&CKEditorFuncNum=0');
});
}); //-->
</script>
Well you have not posted any of your HTML markup, and you have not posted the details of what the "ajaxElementCall" function does. Therefore it's hard to say exactly how you should fix the problem. It is true however that on every "drop" event, you end up calling the "dragDrop()" setup function again. You say that "ajaxElementCall" reloads some portion of the page, but your "dragDrop()" code always installs new event handlers on all ".drag" and ".drop" elements on the page. If "ajaxElementCall" only updates part of the page, then all the unchanged ".drag" and ".drop" elements will get additional event handlers piled on.
When you call .click() or .hover() for some selector, jQuery adds the event handler you supply to the set of handlers already registered. Thus, because you register new event handlers every time "dragDrop()" is called, you'll get more and more piled up. When an event happens, all of those handlers will be run.
Probably what you need to do is change "dragDrop()" so that you can tell it to only operate on a particular fraction of the page. Either that, or else when it runs it should "mark" each element it affects and then check for that mark before applying new event handlers. That way it will only affect newly-loaded code. (It would be more efficient to narrow down the search, however; the expression $('.drag') may have to look through every DOM element on the page, so it would be preferable to use something more precise anyway.)
For one, all the $(this) should be changed to use a variable.
var me = $(this);
me.XXX
$(this) is a method call and its unnessesary to call it over and over again on the same object.
This needs to be done on a per block basis as this will be differet objects in every block ;)
Lookup operations like $(this) are pretty expensive. You'd better store and address object references instead; it helped me a lot in similar circumstances.
It won't make it that much faster, but this will speed it up a few milliseconds:
You should reuse a jquery instance instead of generating a new one (this costs some time).
Example: instead of
$(this).parent().css('background', "#346cb6 url('img/menuButtonOver.png') left top repeat-x");
$(this).parent().css('color', 'white');
use
var this_parent = $(this).parent();
this_parent.css('background', "#346cb6 url('img/menuButtonOver.png') left top repeat-x");
this_parent.css('color', 'white');
One thing that can significantly optimize the above code is replacing the in_array function and the openedFolders array a JS object that functions as a dictionary and is much more efficient.
Decleration:
openedFolders={};
Add a new folder to the opened folders object:
openedFolders[folderName]=valueRelatedToTheFolderIfYouHaveOneOrWhatEver; // :)
Search for an opened folder:
if(openedFolders.hasOwnProperty(folderName)){/*folderName is open*/}

Categories