Weird height doubling bug on mouseover with jQuery - javascript

i have used jquery and javascript to create some custom rollover button functionality and i am experiencing an issue where a variable is not be overwritten but added to. The basic function of my code is on mouseover of a link, i simply want the link to slide up and double in height so that the bottom 'on' portion of the graphic is showing (exactly like css sliding doors rollovers).
However the issue i am having is that the doubleHeight variable is cumulative so that every time you roll over the link the double height of the link is not reset each time, it just adds it to the last value. Weirdly this is only happening after a lightbox is triggered on the page, before that the functionality works just fine. Here is my javascript:
var heightVal, doubleHeight;
$('div.flex_rollover_btn p a').bind('mouseover', function() {
heightVal = $(this).css('height');
doubleHeight = heightVal.replace("px", "");
doubleHeight = doubleHeight * 2 + "px";
$(this).css({height: doubleHeight, top: '-' + heightVal});
});
$('div.flex_rollover_btn p a').bind('mouseout', function() {
heightVal = $(this).parent().css('height');
$(this).css({height: heightVal, top: '0'});
});
and here is the HTML code it is acting upon:
<div style="position: absolute; top: 322px; left: 13px; width: 139px; height: 79px; z-index: 3;" class="block item_3 flex_rollover_btn">
<p style="width: 75px; height: 53px;"><a style="width: 75px; height: 53px;" class="new_window" title="Flexible Size Rollover Test 2" href="http://doctype.tv"><img height="106" width="75" alt="Flexible Size Rollover Test 2" src="/cms/arcadiacorp_uk/repository/pages/static/static-0000006614/images/flex_rollover_2.gif"></a></p>
</div>
To see it in action go here scroll to the right and mouse over the red star thing, then open a lightbox (any of the links with the + symbol next to them) close it and mouseover the red star thing again and you will see what i mean.

In your mouseout handler function, you don't actually do anything. You get the heightVal (which was doubled earlier) and assign it back. The simple solution is to devide the value by two before assigning, just like you double it in the mouseover function.
The best way is to do it all with CSS classes. In CSS you specifiy all dimensions like height and then in JavaScript you can simply change the height by adding or removing a class.
Edit: I see in the mouseout handler function you look at the parent. Are you sure the parent isn't resized with the child element?

I know this isn't directly addressing your question, but don't do this:
doubleHeight = heightVal.replace("px", "");
doubleHeight = doubleHeight * 2 + "px";
Instead, do this:
doubleHeight = (2 * parseInt(heightVal, 10)) + px;

Related

Append(ajax -data) outside screen (left:100%;)

I'm trying to create a slider of posts. I charge the data using ajax and then I apply append to inject the content to a div (id=ajaxinserted1). But I don't want to add this data into screen. I want that data to be added outside of screen (left:100%), so then I can apply a CSS transition to get it on screen with a slide animation effect.
How could I append(data) into the DOM outside the screen?
Thanks
The below code should dynamically calculate the offset based on the width of the images returned from the request. The explanation is in-line. This also required the container to be positioned absolutely.
// Cache the element
var $container = $('.ajaxinserted1');
// Append the images to the container
$container.append(
'<img src="https://www.placehold.it/100">',
'<img src="https://www.placehold.it/100">',
'<img src="https://www.placehold.it/100">',
'<img src="https://www.placehold.it/100">'
)
// Store the offset value
var offsetLeft = 0;
// Loop over the images and update the offset value
$.each($container.children(), function(a, b) {
offsetLeft = offsetLeft - b.width;
})
// Set the offset for the container
$container.css('left', offsetLeft);
// Animation
$('.ajaxinserted1').animate({
left: "10px"
}, 500);
.ajaxinserted1 {
position: absolute;
}
.ajaxinserted1 img {
padding: 10px;
height: 100px;
width: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="ajaxinserted1"></div>
If I understand your question correctly, you just want to append your post under the existing ones and style it so it appears off screen so it can then slide in. So maybe something like...
1) Append your new post HTML into the content div with a class on it called 'new-post'
2) With CSS for new-post class...
.new-post {
position:relative;
left:100%;
}
3) Do your CSS transition to slide it back on screen and remove the class once finished.
Notes:
You may need to set the left attribute in absolute pixels, e.g. 600px, it depends on the layout of your page and where you want it to slide in from.
You could consider using opacity:0 and doing a fade in transition as well

How to get a JS function to execute itself

I have a background image (width = 2000px, height = 400px) sitting behind a div with width and height equal to 400px. My image is split into 5 blocks, all with width and height equal to 400px. I want my image to shift by 400px each time the function is called to emulate a GIF image.
var imageWidth = $("#imageScroll").width();
console.log(imageWidth);
var timer = setInterval(function(){ shiftImage() }, 250);
function shiftImage(){
$("#imageScroll").mouseover (function(){
$("#imageScroll").css({"background-position-x": (imageWidth)});
});
};
});
This is my jQuery code, and I have tried and failed on a lot of different code. imageScroll is the ID of the div that I want the image to be pushed through.
you have to define css of the image so that it repeats itself on the x-axis.
<style>
#imageScroll{
height: 400px;
width: 500px;
background-image: url('./background.jpg');
background-repeat: repeat-x;
}
</style>
then, at the bottom of the page, or in body onload, you should execute the following instructions.
intervalFunc = setInterval(shiftImage, 250);
function shiftImage(){
var currentBackgroundX = $('#imageScroll').css('background-position-x');
split = currentBackgroundX.split("%");
currentBackgroundX = split[0];
currentBackgroundX = parseInt(currentBackgroundX);
$('#imageScroll').css({"background-position-x": (currentBackgroundX + 25) + '%'});
}
I didn't give too much though about the positioning part actually, since that is a completely different subject. But what i'm trying to do here is, change the background-position-x by 25% every 250 miliseconds. You can change the inner workings of the shiftImage function.
If you want to stop the animation at any point, just run
clearInterval(intervalFunc);
Hope this helps
Edit: jsFiddle
Edit 2: edited fiddle link
Edit 3: edited fiddle link

jQuery.clone() an element, then add dynamic styling to it

Let's say I have an image, cat.jpg, and when clicked I want to clone it.
$('img.cat').on("click", function() {
$(this).clone().appendTo('#container');
});
Upon duplication, however, I want the new cat.jpg to appear as half the size of the original. And I want this to continue happening each time a new cat.jpg is clicked.
Any ideas on how to go about accomplishing this? Is it even possible to inject new styling/classes/parameters via .clone()?
It sounds like the following is what you're after:
// If all images are within #container, use $("#container") instead:
$(document).on("click", "img.cat", function () {
var original = $(this);
original.clone().css({
width: original.width() / 2,
height: original.height() / 2
}).appendTo("#container");
});
Fiddle: http://jsfiddle.net/G6XTz/
Of course, you may have wanted the newly added image to be half the size of the last cat image, rather than the cat image clicked:
Fiddle2: http://jsfiddle.net/G6XTz/1/
Caveat:
The width and height can only divide so far; eventually you'll run into some problems. Better check the result of division first, and make a decision to do something else when it makes sense.
Just setting the width to half seems to be enough with an img element, the height gets set automatically in proportion to the width:
$('#container').on('click','img.cat', function() {
$(this).clone()
.appendTo('#container')
.width(function(i,v) { return v/2;});
});
Demo: http://jsfiddle.net/Mr2x8/
But if you find you need to set the width and the height here's one way to do it:
$('#container').on('click','img.cat', function() {
var $this = $(this);
$this.clone()
.appendTo('#container')
.width($this.width()/2)
.height($this.height()/2);
});
Demo: http://jsfiddle.net/Mr2x8/1/
id do this:
$(this).clone().addClass('small').appendTo('#container');
this adds the css class small to the clone of this.
Create a new class with the specific new styling you want to get changed dynamicaly in your CSS file.
.newClass {
//example green outline
outline: solid thin green;
}
And then modify your script:
$('img.cat').on("click", function() {
$(this).clone().addClass('newClass').appendTo('#container');
});
EDIT :
If the only thing you want to change is the size of the img for lets say 10% each click then:
$('img.cat').on("click", function() {
var width = $(this).width() * 0.9;
var height = $(this).height() * 0.9;
$(this).clone().css({"width":width+"px", "height":height+"px"}).appendTo('#container');
});
The above code will produce the same image but 10% smaller than the image clicked .
If you want to click only the initial image then simply put the width and height variable outside the click function and update them inside for each click.
NOTE :
In the css() you add +"px" if initial width is in px else you add +"%" if it is in percentage.

How to dynamically display position of a div on hover

Hi i am creating a website in wordpress,where i am using javascript to display a description div on hover a list of elements but my problem is according to screen size the description div must vary its position in order to display the content completely.I am not sure that i expressed my query clearly could anyone suggest me how can i get this.
jQuery:
(function($) {
$(document).ready( function() {
$('#linkcat-4 .xoxo li:nth-child(1)').mouseover(function(e) {
$('#text1').css(
'visibility' , 'visible'
);
$('#linkcat-4 .xoxo li:nth-child(1)').mouseout(function(e) {
$('#text1').css(
'visibility' , 'hidden'
);
});
});
});
})(jQuery);
HTML:
<ul class="xoxo blogroll">
<li>Admirality</li>
<li>Banking</li>
<li>Commercial</li>
<li>Contract</li>
<li>test</li>
<li>Corporate</li>
</ul>
<div class="desc-text" id="text1" style="visibility: hidden;">
<p>We represent protection and indemnity clubs that provide insurance
for many of the ships coming to Guyana. We deal with all the familiar
problems encountered by ships, both contentious and non-contentious,
including arrests arising from accidents and claims for wages and damaged
cargo. We advise masters, obtain surveys, note protests, negotiate
settlements and advise on or deal with stowaways and medical emergencies.
Our admiralty practice is the largest in Guyana.
</p>
</div>
CSS:
.desc-text {
position: absolute;
top: 12%;
left: 50%;
}
#text1 {
visibility:hidden;
background:#f1f1f1;
padding: 15px;
width: 150px;
}
You need to check the window.innerHeight and window.innerWidth properties before setting the top and left of your popup div. Here is a fiddle to get you started.
The important part is inside the .hover() call:
$( function() {
pop = $("#popup");
$(".item").hover( function() {
row = $(this);
pop.html(row.data("extra"))
.css("top", (function(r) {
if(r.offset().top > window.innerHeight - pop.height())
return window.innerHeight - pop.height();
else
return r.offset().top;
})(row))
.css("left", (function(r) {
if(r.offset().left + r.width() > window.innerWidth - pop.width())
return window.innerWidth - pop.width();
else
return r.offset().left + r.width();
})(row))
.show();
}, function() {
pop.hide();
});
});
Basically, .hover() takes two functions, one for mouseover and one for mouseout. On mouseout, I just hide the popup. On mouseover, I fill the popup div with content (here coming from the item's data-extra attribute, but it could come from anywhere) then decide where to put it based on the location of the item and the window bounds.
Hope that helps. Leave a comment if you need more.
Update
So, the short answer is to make your content fit a normal browser window. I have to maximize my browser to be able to see everything in that popup. It seems like important information, too. So maybe it deserves its own page? These are opinions, not facts, so I'll move on to the latest version of the fiddle which you can more easily look at here.
There were changes to make everywhere, in the CSS, HTML, and Javascript, to make this work. Probably the biggest issue is visibility:hidden. There might be a way to get jQuery to work with that, but I just use the default display:none, which is what .show() and .hide() toggle.
New css
#text1
{
display:none;
background:#f1f1f1;
padding: 15px;
width: 150px;
}
And I needed to wrap your ul with a div of id linkcat-4. Now for the new js. The most interesting change is that I realized we need to take the div's padding into account. Since the padding parameter applies to all sides, we actually need to double the padding and add that to our offset from the window bounds:
New javascript
(function($) {
$(document).ready( function() {
var pop = $("#text1");
$('#linkcat-4 .xoxo li:nth-child(1)').hover(function(e) {
var row = $(this);
pop.html(row.data("extra"))
.css("top", (function(r) {
if(r.offset().top > window.innerHeight - pop.height())
return window.innerHeight - pop.height() - parseInt(pop.css("padding"))*2;
else
return r.offset().top;
})(row))
.css("left", (function(r) {
if(r.offset().left + r.width() > window.innerWidth - pop.width())
return window.innerWidth - pop.width() - parseInt(pop.css("padding"))*2;
else
return r.offset().left + r.width();
})(row))
.show();
},
function(e) {
pop.hide();
});
});
})(jQuery);
Let me know if that works.

CSS: Child div overlapping parent

I have something vaguely like the following:
<div id="body">
surrounding text
<div id="pane" style="overflow: auto; height: 500px; width: 500px;">
lots and lots of text here
<span id="some_bit">tooltip appears below-right of here</span>
</div>
more surrounding text (should be overlapped by tooltip)
</div>
and:
<div id="tooltip" style="width: 100px; height: 100px;">Whee</div>
What I want to do is insert the tooltip such that it is positioned above the pane it's in. If it's attached to an element that's next to the pane boundary (like above), then it should be visible above the pane, and above the text surrounding the pane.
It should NOT a) extend the pane, such that you have to scroll down to see the tooltip (like in http://saizai.com/css_overlap.png), or b) be cut off, so you can't see all of the tooltip.
I'm inserting this with JS, so I can add a wrapper position:relative div or the like if needed, calculate offsets and make it position:absolute, etc. I would prefer to not assume anything about the pane's position property - the tooltip should be insertable with minimal assumptions of possible page layout. (This is just one example case.)
It's for a prototype tooltip library I'm writing that will be open source.
ETA: http://jsfiddle.net/vCb2y/5/ behaves visually like I want (if you keep re-hovering the trigger text), but would require me to update the position of the tooltip on all DOM changes and scrolling behavior. I would rather the tooltip be positioned with pure CSS/HTML so that it has the same visual behavior (i.e. it overlaps all other elements) but stays in its position relative to the target under DOM changes, scrolling, etc.
ETA 2: http://tjkdesign.com/articles/z-index/teach_yourself_how_elements_stack.asp (keep defaults except set cyan div 'a' to position:relative; imagine 'A' is the pane and 'a' the tooltip) seems to more closely behave as I want, but I've not been able to get it to work elsewhere. Note that if you make 'A' overflow: auto, it breaks the overlapping behavior of 'a'.
I can't think of a pure HTML/CSS solution for this.
The overflow declaration is the issue here. If the tooltip is in #pane:
you establish a positioning context within #pane, then the tooltip shows next to #some_bit (regardless of scrolling, etc.) but it gets cut-off.
you do not establish a positioning context, then the tooltip is not clipped but it has no clue where #some_bit is on the page.
I'm afraid you'll need JS to monitor where #some_bit is on the page and position the tooltip accordingly. You'd also need to kill that tooltip as soon as #some_bit is outside of the viewing area (not an issue if the trigger is mouseover).
Actually, if the trigger is mouseover then you may want to use the cursor coordinates to position the tooltip (versus calculating the position of #some_bit).
I would just put the tooltip outside of the #pane div and position it absolutely using JavaScript since you're using JS anyway.
I don't use Prototype so I don't know how it's done in Prototype, but in jQuery, you'd use $(element).position() to get the element position. If you have to do it manually, it's a little more complicated.
And you'll probably want to add a little extra logic to prevent the tooltip from extending outside of the document.
Edit: CSS used
#tooltip {
z-index: 9999;
display: none;
position: absolute;
}
JS used
Note: in jQuery, but it should be easy to change it to Prototype syntax.
$('#some_bit').hover(function() {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
// hovered element
var offset = $(this).offset();
var top = offset.top + docViewTop;
var left = offset.left;
var width = $(this).width();
var height = $(this).height();
var right = left + width;
var bottom = top + height;
// pane
var poffset = $('#pane').offset();
var ptop = poffset.top + docViewTop;
var pleft = poffset.left;
var pwidth = $('#pane').width();
var pheight = $('#pane').height();
var pright = pleft + pwidth;
var pbottom = ptop + pheight;
// tooltip
var ttop = bottom;
var tleft = right;
var twidth = $('#tooltip').width();
var theight = $('#tooltip').height();
var tright = tleft + twidth;
var tbottom = ttop + theight;
if (tright > pright)
tleft = pright - twidth;
if (tbottom > pbottom)
ttop = pbottom - theight;
if (tbottom > docViewBottom)
ttop = docViewBottom - theight;
$('#tooltip').offset({top: ttop, left: tleft});
$('#tooltip').css('display', 'block');
}, function() {
$('#tooltip').hide();
});
Edit: See it here.

Categories