JQuery ready function problems - javascript

I am using the dropShadow plugin, and I have a problem with the JQuery ready function.
When I have my code like this:
$(document).ready(function() {
$('div#shadow').dropShadow();
$('#navigation li.mainmenu').bind('mouseover', navigation_open);
$('#navigation li').bind('mouseout', navigation_timer);
});
It will only make the shadow once the drop menu has come out, which is the second function. Any ideas why?
The full code for the JS is:
$(document).ready(
function()
{
$('#navigation li.mainmenu').bind('mouseover', navigation_open);
$('#navigation li').bind('mouseout', navigation_timer);
});
var timeout = 500;
var closetimer = 0;
var ddmenuitem = 0;
var highlightmenu = 0;
var returncolor = 0;
var textreturncolor = 0;
var height = 0;
var originaltop = 0;
var resettop = 0;
var top = 0;
var shadowExists = 0;
var dropshadow = 0;
function drawShadow(){
//draw the shadow only on mouse enter
dropshadow = $(this).find('ul').dropShadow({top: 4, opacity: 1});
$('.dropShadow').css('visibility','visible');
}
function navigation_open()
{ navigation_canceltimer();
navigation_close();
height = $(this).height();
ddmenuitem = $(this).find('ul');
//Double Liners are above 40 pixels
menu = ddmenuitem.find('li');
/*===Need to get the top pos. of the item and adjust it since it is absolute; relative does not work*/
top = ddmenuitem.position().top;
resettop = top;
if (height > 40){
top = top - 53;
}
else{
top = top - 35;
}
ddmenuitem.css('top', top.toString() + "px");
//---ADD A DROP SHADOW...USING JQUERY PLUGIN
ddmenuitem.dropShadow({top: 4, opacity: 1});
$('.dropShadow').css('visibility','visible');
ddmenuitem.css('visibility', 'visible');
returncolor = $(this).find('a#highlight').css('background-color');
textreturncolor = $(this).find('a#highlight').css('color');
highlightmenu = $(this).find('a#highlight').css('background-color','#6487ad');
highlightmenu.css('color','#ffffff');
highlightmenu.css('font-weight','bold');}
function navigation_close()
{ if(ddmenuitem){
ddmenuitem.css('visibility', 'hidden');
ddmenuitem.css('top',resettop);
ddmenuitem.removeShadow();
}
if(highlightmenu){ highlightmenu.css('background-color',returncolor);
highlightmenu.css('color',textreturncolor);
}
}
function navigation_timer()
{
closetimer = window.setTimeout(navigation_close, timeout);}
function navigation_canceltimer()
{ if(closetimer)
{
window.clearTimeout(closetimer);
closetimer = null;}}
document.onclick = navigation_close;
The HTML would be like this for static:
<div id="shadow">
//images here
</div>
I don't know if you need to see anymore, however the drop menu is just a list, but I want to be able to apply this to the static images and it won't until the drop menus come out.

The dropshadow plugin appears to be designed for stationary page elements. From the dropshadow js file:
"This jQuery plug-in adds soft drop shadows behind page elements. It is only intended for adding a few drop shadows to mostly stationary objects, like a page heading, a photo, or content containers"
EDIT: Perhaps you could achieve the effect you're looking for with css? http://robertnyman.com/2010/03/16/drop-shadow-with-css-for-all-web-browsers/

The problem lies within the CSS, when calling dropShadow() for the first time the css for class dropShadow is set to hiddent (this was placed there to make the dynamic pieces work in IE (all other browsers fine without it). In the javascript you can see this by the $('.dropShadow').css('visibility','visible'); being called.

Related

How to position divs on top ads on Amazon.com

I want to position some divs on top of all ads on Amazon.com like this:
This is for a project of mine. The above picture was achieved through getting the coordinates of the ads using getBoundingClientRect and creating divs, setting top and left based on these coordinates, and appending the divs to document.body. However, since they have absolute position and are children of document.body, they do not move with the ads. For example, if I resize the window, this happens
Also, in product pages, this happens without doing anything.
I have also tried appending the divs to the parents of the iframes/ads, but I can never seem to make them appear outside of their parent. I have tried suggestions from various links, such as making position:absolute, setting bottom or top, making the parents position:relative but nothing has worked. There has been one instance of the div appearing outside of the parent but it was in some random position above it like this.
I seriously don't know how to accomplish this. Ideally, the div would be a sibling of the iframe or something like that, so I don't have to deal with the divs not moving when the window resizes. I just can't seem to get anything work, though.
// Here is the code for appending to parent of iframes.
// The divs just end up overlaying the ad.
function setStyle(element, styleProperties) {
for (var property in styleProperties) {
element.style[property] = styleProperties[property];
}
}
// Regex for getting all the parents of all the iframes
var placements = document.querySelectorAll('div[id^=\'ape_\'][id$=\'placement\']');
for (var i = 0; i < placements.length; ++i) {
var placement = placements[i];
var iframe = placement.getElementsByTagName('iframe')[0];
var debugDiv = document.createElement('div');
debugDiv.id = iframe.id + '_debug_div';
setStyle(debugDiv, {
'backgroundColor': '#ff0000',
'height': '30px',
'display': 'block',
'position': 'absolute',
'top': '-30px',
'zIndex': '16777270',
});
alert(placement.id)
placement.style.position = 'relative'
placement.appendChild(debugDiv);
}
edit:
Here's the getBoundingClientRect code:
function setStyle(element, styleProperties) {
for (var property in styleProperties) {
element.style[property] = styleProperties[property];
}
}
function createDiv(iframeId, top, left, width) {
var div = document.createElement('div');
div.id = iframeId + '_debug_div';
setStyle(div, {
'backgroundColor': '#ccffff',
'backgroundColor': '#ff0000',
'height': '30px',
'width': width.toString() + 'px',
'display': 'block',
'position': 'absolute',
'top': (top - 30).toString() + 'px',
'left': left.toString() + 'px',
'zIndex': '16777270'
});
return div;
}
var placements = document.querySelectorAll('div[id^=\'ape_\'][id$=\'placement\']');
for (var i = 0; i < placements.length; ++i) {
var placement = placements[i];
var iframe = placement.getElementsByTagName('iframe')[0];
var iframeRect = iframe.getBoundingClientRect();
iframeWidth = iframeRect.right - iframeRect.left;
var debugDiv = createDiv(iframe.id, iframeRect.top, iframeRect.left, iframeWidth);
document.body.appendChild(debugDiv);
};
This doesn't work properly when the window is resized. It also does not work properly on product pages for some ads.
Try using the resize eventlistener, with a DOM MutationObserver:
var observeDOM = (function(){
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
return function( obj, callback ){
if( !obj || !obj.nodeType === 1 ) return; // validation
if( MutationObserver ){
// define a new observer
var obs = new MutationObserver(function(mutations, observer){
callback(mutations);
})
// have the observer observe foo for changes in children
obs.observe( obj, { childList:true, subtree:true });
}
else if( window.addEventListener ){
obj.addEventListener('DOMNodeInserted', callback, false);
obj.addEventListener('DOMNodeRemoved', callback, false);
}
}
})();
window.onchange = function(){
observeDOM(document.body, () => {
window.addEventListener('resize', () => {
var placements = document.querySelectorAll('div[id^=\'ape_\'] [id$=\'placement\']');
for (var i = 0; i < placements.length; ++i) {
var placement = placements[i];
var iframe = placement.getElementsByTagName('iframe')[0];
var iframeRect = iframe.getBoundingClientRect();
iframeWidth = iframeRect.right - iframeRect.left;
var debugDiv = createDiv(iframe.id, iframeRect.top, iframeRect.left, iframeWidth);
document.body.appendChild(debugDiv);
}
});
});
}
It's a start. I think the issue with the misplaced bars on the product pages may be fixed by using the onload listener too, although I can't reproduce those issues for whatever reason. If it's not matching some ads altogether, that's likely due to your query selector, but I can't help fix that unfortunately.
The code for the DOM observer is from here - it should detect changes more accurately than onchange, especially for things like flex, where elements can get reordered in the DOM on mobile view. You may also want to wrap this in document.addEventListener("DOMContentLoaded", ... to wait until everything's loaded (at the sacrifice of IE8), or just use jQuery's $(document).ready() (which is compatible with IE8) - however, if you're not already using jQuery, don't import it just for this one function!
Also, you may want to do something about the padding on the body, which may be the cause of the misalignment in some cases. You should probably get it using window.getComputedStyles, and compensate for it. Once again, however, I can't reproduce these errors.
I think, that you want to select the image of the ad.
const adImages = document.querySelectorAll('your ad images');
for (var i = 0; i < adImages.length; ++i) {
adImages[i].parent.insertAdjacentHTML('afterbegin', 'your html');
}
You basicaly set the first child of that parent element on the top.

Show one div when another div scrolls off screen. Getting unwanted flashes

I would like to show one div (.cu5-topbar) when another div (.cu5box-box) scrolls off screen. The problem is that the the .cu5-topbar div is showing up right as the .cu5box-box div is leaving the screen. That's also causing the .cu5-topbar to flashing for a few seconds while the two divs overlap each other. Here is my code so far:
var scroll_start = 0;
var startchange = jQuery('.cu5box-box');
var offset = startchange.offset();
if (startchange.length) {
jQuery(document).scroll(function () {
scroll_start = jQuery(this).scrollTop();
if (scroll_start > offset.top) {
jQuery('.cu5box-box').fadeOut(400);
jQuery('.cu5-topbar').fadeIn(400);
} else {
jQuery('.cu5box-box').fadeIn(400);
jQuery('.cu5-topbar').fadeOut(400);
}
});
}
https://jsfiddle.net/zgu70p4m/
I would like for the .cu5-topbar div to show up as soon the .cu5box-box div is completely off of the screen and I would like for the .cu5-topbar div to disappear as soon as the .cu5box-box div comes onto the screen.
Try the below, you had not included jQuery in your jsfiddle example.
You also needed to attach the scroll event to the window. Finally the offset needed the elements height added to the total to make sure you where getting the correct position of the end of the element.
var scroll_start = 0;
var startchange = jQuery('.cu5box-box');
var offset = startchange.offset();
if (startchange.length) {
$(window).scroll(function () {
scroll_start = $(this).scrollTop();
if (scroll_start > offset.top + startchange.height()) {
$('.cu5-topbar').fadeOut(400);
} else {
$('.cu5-topbar').fadeIn(400);
}
});
}

Synchronized scrolling using jQuery?

I am trying to implement synchronized scrolling for two DIV with the following code.
DEMO
$(document).ready(function() {
$("#div1").scroll(function () {
$("#div2").scrollTop($("#div1").scrollTop());
});
$("#div2").scroll(function () {
$("#div1").scrollTop($("#div2").scrollTop());
});
});
#div1 and #div2 is having the very same content but different sizes, say
#div1 {
height : 800px;
width: 600px;
}
#div1 {
height : 400px;
width: 200px;
}
With this code, I am facing two issues.
1) Scrolling is not well synchronized, since the divs are of different sizes. I know, this is because, I am directly setting the scrollTop value. I need to find the percentage of scrolled content and calculate corresponding scrollTop value for the other div. I am not sure, how to find the actual height and current scroll position.
2) This issue is only found in firefox. In firefox, scrolling is not smooth as in other browsers. I think this because the above code is creating a infinite loop of scroll events.
I am not sure, why this is only happening with firefox. Is there any way to find the source of scroll event, so that I can resolve this issue.
Any help would be greatly appreciated.
You can use element.scrollTop / (element.scrollHeight - element.offsetHeight) to get the percentage (it'll be a value between 0 and 1). So you can multiply the other element's (.scrollHeight - .offsetHeight) by this value for proportional scrolling.
To avoid triggering the listeners in a loop you could temporarily unbind the listener, set the scrollTop and rebind again.
var $divs = $('#div1, #div2');
var sync = function(e){
var $other = $divs.not(this).off('scroll'), other = $other.get(0);
var percentage = this.scrollTop / (this.scrollHeight - this.offsetHeight);
other.scrollTop = percentage * (other.scrollHeight - other.offsetHeight);
// Firefox workaround. Rebinding without delay isn't enough.
setTimeout( function(){ $other.on('scroll', sync ); },10);
}
$divs.on( 'scroll', sync);
http://jsfiddle.net/b75KZ/5/
Runs like clockwork (see DEMO)
$(document).ready(function(){
var master = "div1"; // this is id div
var slave = "div2"; // this is other id div
var master_tmp;
var slave_tmp;
var timer;
var sync = function ()
{
if($(this).attr('id') == slave)
{
master_tmp = master;
slave_tmp = slave;
master = slave;
slave = master_tmp;
}
$("#" + slave).unbind("scroll");
var percentage = this.scrollTop / (this.scrollHeight - this.offsetHeight);
var x = percentage * ($("#" + slave).get(0).scrollHeight - $("#" + slave).get(0).offsetHeight);
$("#" + slave).scrollTop(x);
if(typeof(timer) !== 'undefind')
clearTimeout(timer);
timer = setTimeout(function(){ $("#" + slave).scroll(sync) }, 200)
}
$('#' + master + ', #' + slave).scroll(sync);
});
This is what I'm using. Just call the syncScroll(...) function with the two elements you want to synchronize. I found pawel's solution had issues with continuing to slowly scroll after the mouse or trackpad was actually done with the operation.
See working example here.
// Sync up our elements.
syncScroll($('.scroll-elem-1'), $('.scroll-elem-2'));
/***
* Synchronize Scroll
* Synchronizes the vertical scrolling of two elements.
* The elements can have different content heights.
*
* #param $el1 {Object}
* Native DOM element or jQuery selector.
* First element to sync.
* #param $el2 {Object}
* Native DOM element or jQuery selector.
* Second element to sync.
*/
function syncScroll(el1, el2) {
var $el1 = $(el1);
var $el2 = $(el2);
// Lets us know when a scroll is organic
// or forced from the synced element.
var forcedScroll = false;
// Catch our elements' scroll events and
// syncronize the related element.
$el1.scroll(function() { performScroll($el1, $el2); });
$el2.scroll(function() { performScroll($el2, $el1); });
// Perform the scroll of the synced element
// based on the scrolled element.
function performScroll($scrolled, $toScroll) {
if (forcedScroll) return (forcedScroll = false);
var percent = ($scrolled.scrollTop() /
($scrolled[0].scrollHeight - $scrolled.outerHeight())) * 100;
setScrollTopFromPercent($toScroll, percent);
}
// Scroll to a position in the given
// element based on a percent.
function setScrollTopFromPercent($el, percent) {
var scrollTopPos = (percent / 100) *
($el[0].scrollHeight - $el.outerHeight());
forcedScroll = true;
$el.scrollTop(scrollTopPos);
}
}
If the divs are of equal sizes then this code below is a simple way to scroll them synchronously:
scroll_all_blocks: function(e) {
var scrollLeft = $(e.target)[0].scrollLeft;
var len = $('.scroll_class').length;
for (var i = 0; i < len; i++)
{
$('.scroll_class')[i].scrollLeft = scrollLeft;
}
}
Here im using horizontal scroll, but you can use scrollTop here instead. This function is call on scroll event on the div, so the e will have access to the event object.
Secondly, you can simply have the ratio of corresponding sizes of the divs calculated to apply in this line $('.scroll_class')[i].scrollLeft = scrollLeft;
I solved the sync scrolling loop problem by setting the scroll percentage to fixed-point notation: percent.toFixed(0), with 0 as the parameter. This prevents mismatched fractional scrolling heights between the two synced elements, which are constantly trying to "catch up" with each other. This code will let them catch up after at most a single extra step (i.e., the second element may continue to scroll an extra pixel after the user stops scrolling). Not a perfect solution or the most sophisticated, but certainly the simplest I could find.
var left = document.getElementById('left');
var right = document.getElementById('right');
var el2;
var percentage = function(el) { return (el.scrollTop / (el.scrollHeight - el.offsetHeight)) };
function syncScroll(el1) {
el1.getAttribute('id') === 'left' ? el2 = right : el2 = left;
el2.scrollTo( 0, (percentage(el1) * (el2.scrollHeight - el2.offsetHeight)).toFixed(0) ); // toFixed(0) prevents scrolling feedback loop
}
document.getElementById('left').addEventListener('scroll',function() {
syncScroll(this);
});
document.getElementById('right').addEventListener('scroll',function() {
syncScroll(this);
});
I like pawel's clean solution but it lacks something I need and has a strange scrolling bug where it continues to scroll and my plugin will work on multiple containers not just two.
http://www.xtf.dk/2015/12/jquery-plugin-synchronize-scroll.html
Example & demo: http://trunk.xtf.dk/Project/ScrollSync/
Plugin: http://trunk.xtf.dk/Project/ScrollSync/jquery.scrollSync.js
$('.scrollable').scrollSync();
If you don't want proportional scrolling, but rather to scroll an equal amount of pixels on each field, you could add the value of change to the current value of the field you're binding the scroll-event to.
Let's say that #left is the small field, and #right is the bigger field.
var oldRst = 0;
$('#right').on('scroll', function () {
l = $('#left');
var lst = l.scrollTop();
var rst = $(this).scrollTop();
l.scrollTop(lst+(rst-oldRst)); // <-- like this
oldRst = rst;
});
https://jsfiddle.net/vuvgc0a8/1/
By adding the value of change, and not just setting it equal to #right's scrollTop(), you can scroll up or down in the small field, regardless of its scrollTop() being less than the bigger field. An example of this is a user page on Facebook.
This is what I needed when I came here, so I thought I'd share.
From the pawel solution (first answer).
For the horizzontal synchronized scrolling using jQuery this is the solution:
var $divs = $('#div1, #div2'); //only 2 divs
var sync = function(e){
var $other = $divs.not(this).off('scroll');
var other = $other.get(0);
var percentage = this.scrollLeft / (this.scrollWidth - this.offsetWidth);
other.scrollLeft = percentage * (other.scrollWidth - other.offsetWidth);
setTimeout( function(){ $other.on('scroll', sync ); },10);
}
$divs.on('scroll', sync);
JSFiddle
An other solution for multiple horizontally synchronized divs is this, but it works for divs with same width.
var $divs = $('#div1, #div2, #div3'); //multiple divs
var sync = function (e) {
var me = $(this);
var $other = $divs.not(me).off('scroll');
$divs.not(me).each(function (index) {
$(this).scrollLeft(me.scrollLeft());
});
setTimeout(function () {
$other.on('scroll', sync);
}, 10);
}
$divs.on('scroll', sync);
NB: Only for divs with same width
JSFiddle

jQuery: Using scroll() and offset() to change background

I am designing a website where the background sits in a div that has a negative z-index with position:fixed. I then have section divs that scroll over it. My goal is to change the background image when each section's top position is passed by the scrollTop function. My jQuery code currently creates an array of each sections top position using:
var secTops = [];
$('section').each(function(i) {
var t = $(this).offset();
secTops.push(t.top);
});
I then thought I would create a variable upon scroll() that was the scrollTop() position like so:
$(window).scroll(function() {
var winTop = $(this).scrollTop();
});
But here is where I am stuck. The best I can come up with (which doesn't work right) is this:
for (i = 0; i < $('section').length; i++) {
var pos = secTops[i];
if (winTop < pos) {
$('#background').css('background', bgFront + (i+1) + bgBack);
} else {
$('#background').css('background', bgFront + (i+2) + bgBack);
};
};
But this isn't right. You can disregard the second half of my .css() function. I've created variables and labeled my images appropriately, so i know that works. Right now, the for loop runs through the entire iteration and is stuck at the full section.length and thus only flips between 2 background images. I need this to constantly check my winTop variable against the top positions of my sections and change the background accordingly. I could do this with a lot of if/then, or maybe even a lengthy switch, but there has to be a cleaner way to do this. Can anyone help me out here?
Here's a JSFiddle that uses colors instead of images but shows the same problems. http://jsfiddle.net/kyleshevlin/5N5WU/1/
this has no chance to work. you need to change it to something like this (this is kinda pseudocode, just to give you a picture:
sections = [];
$(document).ready(function() {
$('section').each(function() {
sections.push($(this))
});
})
$(window).scroll(function() {
var s = $(window).scrolTop();
var currentIndex;
for ( var i = 0; i < sections.length; i++) {
if (( s > sections[i].offset().top) && ( s <= sections[i+1].offset().top)) {
currentIndex = i;
}
}
$('#background').css('background', bgFront + (i+1) + bgBack);
})

Javascript for preventing "burn-in" problem on lcd screen

I'm building a non-public web app that will be used as info-monitor. As such, it will be running 24/7 on one LCD TV display.
Since this could produce a "burn-in color" error on the LCD I'm looking for a Javascript that will prevent/reduce this problem. I want to use something similar to those they use on airport displays (a line periodically moving from left to right and top to bottom and switching color).
Do you know any Javascript doing this? Thank you!
In case you were still interested: (uses jQuery)
var $burnGuard = $('<div>').attr('id','burnGuard').css({
'background-color':'#FF00FF',
'width':'1px',
'height':$(document).height()+'px',
'position':'absolute',
'top':'0px',
'left':'0px',
'display':'none'
}).appendTo('body');
var colors = ['#FF0000','#00FF00','#0000FF'], color = 0, delay = 5000, scrollDelay = 1000;
function burnGuardAnimate()
{
color = ++color % 3;
var rColor = colors[color];
$burnGuard.css({
'left':'0px',
'background-color':rColor,
}).show().animate({
'left':$(window).width()+'px'
},scrollDelay,function(){
$(this).hide();
});
setTimeout(burnGuardAnimate,delay);
}
setTimeout(burnGuardAnimate,delay);
Working example found here: http://www.jsfiddle.net/bradchristie/4w2K3/3/ (or full screen version)
I used Brad's script but unfortunately my page had a large HTMl table that extend outside the parent container. This made it so the pixel bar would only travel part way across the screen. Instead of altering my table I added a bounding box script to find the actual width of the html table and then used that to set the width in Brad's script.
var div = document.getElementById ("HtmlTable-ID");
if (div.getBoundingClientRect) {
var rect = div.getBoundingClientRect ();
w = rect.right - rect.left;
// alert (" Width: " + w );
}
var $burnGuard = $('<div>').attr('id','burnGuard').css({
'background-color':'#FF00FF',
'width':'1px',
'height':$(document).height()+'px',
'position':'absolute',
'top':'0px',
'left':'0px',
'display':'none'
}).appendTo('body');
var colors = ['#FF0000','#00FF00','#0000FF'], color = 0, delay = 5000, scrollDelay = 1000;
function burnGuardAnimate()
{
color = ++color % 3;
var rColor = colors[color];
$burnGuard.css({
'left':'0px',
'background-color':rColor,
}).show().animate({
'left': w +'px'
},scrollDelay,function(){
$(this).hide();
});
setTimeout(burnGuardAnimate,delay);
}
setTimeout(burnGuardAnimate,delay);

Categories

Resources