hi all im building a menu and im trying to put an hover effect on each menu item
but... when i hover everything is working great and i get the html i want and the menu item has a backgruond image.
but the unhover effect dosnt fire most of the times. i found out that if i move my mouse horziantly across the ul menu it works fine. but if my mouse does a vertical move across the li item it dosnt fire.
my code is this:
$("ul.menu li").hover(ChangeToHoverMenuItem, ChangeBackMenuItem);
function ChangeToHoverMenuItem()
{
var currLi = $(this);
lastLi = currLi;
var currMenuItemText = currLi.find("a").text();
currLi.html("");
currLi.append("<div style='float:right;'><div class='right_item_hov'></div>" +
"<a class='item_menu_hov'>" +
currMenuItemText +
"</a>" +
"<div class='left_item_hov'></div></div>");
}
function ChangeBackMenuItem ()
{
var currLi = $(this);
var currMenuItemText = currLi.find("a").text();
currLi.html("");
currLi.append("<a>" + currMenuItemText + "</a>");
}
<div class="menu_middle">
<ul class="menu">
<li>
<a>
main
</a>
</li>
<li>
<a>
gallery
</a>
</li>
<li>
<a>
event
</a>
</li>
<li>
<a>
about
</a>
</li>
<li>
<a>
contact
</a>
</li>
</ul>
</div>
thank you
The strange thing is, that there are two mouseenter() events on sibling elements without a mouseleave() event in between.
One idea is to register the mouseenter() and mouseleave() event instead of using hover(). hover() should do the same, but how knows. If this works, the problem lies in the implementation of hover() but I don't think so.
$("ul.menu li")
.mouseenter(ChangeToHoverMenuItem)
.mouseleave(ChangeBackMenuItem);
Another idea is to ensure that the mouseleave() code was executed. In your "doHover" handler you can check if there is anhoveredItem. If so, you can call the ChangeBackMenuItem function with the still hovered item as this. To ensure that the "unhover" handler is called when you leave your ul, you need a mouseleave event on this, that does the same. This solution relies on a working mouseleave on the ul element.
$(function() {
var hoveredItem = null;
function ChangeToHoverMenuItem()
{
if (hoveredItem) {
ChangeBackMenuItem.call(hoveredItem);
}
hoveredItem = this;
var currLi = $(this);
lastLi = currLi;
var currMenuItemText = currLi.find("a").text();
currLi.html("");
currLi.append("" +
"" +
currMenuItemText +
"" +
"");
}
function ChangeBackMenuItem ()
{
var currLi = $(this);
var currMenuItemText = currLi.find("a").text();
currLi.html("");
currLi.append("" + currMenuItemText + "");
hoveredItem = null;
}
$("ul.menu li").hover(ChangeToHoverMenuItem, ChangeBackMenuItem);
$("ul.menu").mouseleave(function() {
if (hoveredItem) {
ChangeBackMenuItem.call(hoveredItem);
hoveredItem = null;
}
});
});
Try giving a boundary to the li (using css 'border' property) and then add a console.log(firebug) statement in the beginning of 'ChangeBackMenuItem' to see if the function is called each time you un-hover.
Related
I have a problem when I am making the website for one gallery.
I made the code for the button that can show and hide multiple images.
I intend to make the button can place several images in randomly.
I write the code that can function for only one image.
Please tell me the code that functions as a button to place multiple images in a random location.
Users can hide images by pressing the button.
And when users press the button again, it places the images in another random location.
const btn = document.querySelector("button");
const height = document.documentElement.clientHeight;
const width = document.documentElement.clientWidth;
const box = document.getElementById("color");
btn.addEventListener("click", () => {
let randY = Math.floor((Math.random() * height) + 1);
let randX = Math.floor((Math.random() * width) + 1);
box.style.top = randY + "px";
box.style.right = randX + "px";
});
function showhide() {
var x = document.querySelectorAll("#color");
var i;
for (i = 0; i < x.length; i++) {
if (x[i].style.display === "block") {
x[i].style.display = "none";
} else {
x[i].style.display =
"block";
}
}
}
body {
height: 500px;
}
.random {
position: absolute;
}
<button onclick="showhide()" value="Zeige Features" id="button">click me</button>
<img id="color" style="display: none;" class="random" src="http://lorempixel.com/200/200/">
<img id="color" style="display: none;" class="random" src="http://lorempixel.com/200/200/">
You're doing the correct thing in showHide() when using querySelectorAll. You are then able to get all images.
You should never have elements with the same ids. They should be unique. So querySelectorAll("#color") works, but it's now how you should do. Do a querySelector on "img.random" instead.
getElementById only returns a single element, not like querySelectorAll. So you need to use querySelectorAll('img.random').
This might be beyond your knowledge, I don't think you should add the images in HTML, but in javascript code.
a) Add all image paths in an array: ['https://image.com/image.png', ...]
b) Add a single img element. <img id="template" class="random">
c) In javascript code, clone that element for each image path in the array. You can use cloneNode for this.
d) Randomize each position for each element, just like you have done now.
e) Add each element to the DOM through appendChild. Have a unique div that you append to. Be sure to clear it every time second time you hit the button.
f) Solve all bugs along the way. :P
The problem
The main issue here is that you're using getElementById to query #color
const box = document.getElementById("color");
Since getElementById only returns one element (but you have two in your DOM) and the style only applies to one element. That's why you're seeing only one element is randomly moving and the other just stay in the same place.
A side note here, id should be unique in a DOM.
You're in fact using the correct API for the job in the showhide function
var x = document.querySelectorAll("#color");
The fix:
To fix this, you need to query all images by their classname (as suggested in the side note, don't use id for the job)
const boxes = document.querySelectorAll(".random");
Now we have a node list, as you do in the showhide function, we need to loop thru it, I'm not using a for loop here, instead, a forEach loop, it's just more terser and a modern addition to the JS
// Since boxes are not array, we need to covert it to array so we can use that handy `.forEach` here:
Array.from(boxes).forEach(box => {
box.style.top = Math.floor((Math.random() * height) + 1) + "px";
box.style.right = Math.floor((Math.random() * width) + 1) + "px";
})
Now, this should fix your issue. See the complete code below.
const btn = document.querySelector("button");
const height = document.documentElement.clientHeight;
const width = document.documentElement.clientWidth;
const boxes = document.querySelectorAll(".random");
btn.addEventListener("click", () => {
Array.from(boxes).forEach(box => {
box.style.top = Math.floor((Math.random() * height) + 1) + "px";
box.style.right = Math.floor((Math.random() * width) + 1) + "px";
})
});
function showhide() {
var x = document.querySelectorAll(".random");
var i;
for (i = 0; i < x.length; i++) {
if (x[i].style.display === "block") {
x[i].style.display = "none";
} else {
x[i].style.display =
"block";
}
}
}
body {
height: 500px;
}
.random {
position: absolute;
}
<button onclick="showhide()" value="Zeige Features" id="button">click me</button>
<img id="color" style="display: none;" class="random" src="http://lorempixel.com/200/200/">
<img id="color" style="display: none;" class="random" src="http://lorempixel.com/100/100/">
I am sure this is rediculously simple, but I'm stumped.
Very simply, I want to create a text link that changes the width property of an image on mouse over, and on mouse out, return to the original.
The image I wish to change has an id 'photoimage'
Here's what I have, but it's not doing anything. Any ideas>
<a href="#" onmouseover="MM_changeProp('photoimage','','Width','10','IMG')">
photographs
</a>
Sorry here is the function
function MM_changeProp(objId,x,theProp,theValue) { //v9.0
var obj = null; with (document){ if (getElementById)
obj = getElementById(objId); }
if (obj){
if (theValue == true || theValue == false)
eval("obj.style."+theProp+"="+theValue);
else eval("obj.style."+theProp+"='"+theValue+"'");
}
Any help much appreciated
Javascript:
function setWidth( elementId, width ) {
var element = getElementById(elementId);
element.style.width = width;
}
<a href="#"
onmouseover="setWidth('photoimage','200px')"
onmouseout="setWidth('photoimage', '100px')"> photographs </a>
I'm trying to reveal content using hoverIntent without writing specific conditions for each id. I would like to have the id passed to the mouse in settings so I can reveal content selected by adding characters to the id + '-x'.
I have tried a few ways to get the div I'm hovering over but these usually end up returning all the information of all the divs with the class "box".
Is there a parent, child thing I should be doing? I don't understand it really but feel like this is the situation it would helpful in.
<div id="id-first-div" class="box">Trigger 1</div>
<div id="id-second-div" class="box">Trigger 2</div>
<div id="id-second-div-x" class="hide">Hidden Bullet 1</div>
<div id="id-first-div-x" class="hide">Hidden Bullet 2</div>
<script>
$(document).ready(function() {
$("#id-first-div").hoverIntent(slide_right_settings);
$("#id-second-div").hoverIntent(slide_right_settings);
});
var slide_right_settings={
sensitivity: 4,
interval: 1500,
timeout: 5000,
over: mousein_triger,
out: mouseout_triger
};
function mousein_triger(){
var id = this.id; // I'm pretty sure I'm going wrong here
$(id + '-x').addClass('reveal');
$(id + '-x').removeClass('hide');
}
function mouseout_triger() {
$(id +'-x').addClass('hide');
$(id +'-x').removeClass('reveal');
}
</script>
//hover intent opening and closing
var slide_right_settings={
over: mousein_triger,
out: mouseout_triger
};
//default id is home
var id = "home";
function mousein_triger(){
//updates id to the one triggering
id = $(this).attr('id');
$('#' + id + '-x').addClass('reveal');
$('#' + id + '-x').removeClass('hide');
}
function mouseout_triger() {
$('#' + id +'-x').addClass('hide');
$('#' + id +'-x').removeClass('reveal');
}
Still not sure if this is the best way to achieve this, but it's working.. I'm sure it could be improved a lot.
place the var id = this.id; outside the function
I have a question about a lightbox see my jsFiddle.
Clicking on one of the images opens a bigger version of the painting as a page overlay.
How to use the ESC key to close this page overlay?
And how to use the arrow keys to move to the next image?
What kind of jQuery plugin / javascript would I need to make this happen?
<ul class="lb-album">
<li>
<a href="#Fly-My-Pretties-Walled-Garden">
<img src="http://sandipa.com.au/images/works-for-sale/thumbs/Fly-my-Pretties-Walled-Garden-sm.jpg" alt="Fly My Pretties: Walled Garden">
<span>Fly My Pretties</span> </a>
<div class="lb-overlay" id="Fly-My-Pretties-Walled-Garden">
x Close
<img src="http://sandipa.com.au/images/2010-2011/1000px-wide/Fly-my-Pretties-Walled-Garden.jpg" alt="Fly My Pretties: Walled Garden">
<div>
<h3>Fly My Pretties: Walled Garden<span>mixed media on canvas</span></h3>
<p>72 x 137 cm</p>
Prev
Next
</div>
</div>
</li>
<li>
<a href="#Central-Highlands-Circle-of-Gold">
<img src="http://sandipa.com.au/images/works-for-sale/thumbs/Central-Highlands-Circle-of-Gold-sm.jpg" alt="Central Highlands: Circle of Gold">
<span>Circle of Gold</span> </a>
<div class="lb-overlay" id="Central-Highlands-Circle-of-Gold">
x Close
<img src="http://sandipa.com.au/images/works-for-sale/Central-Highlands-Circle-of-Gold.jpg" alt="Central Highlands: Circle of Gold">
<div>
<h3>Central Highlands: Circle of Gold<span>mixed media on canvas</span></h3>
<p>51 x 108 cm</p>
Prev
Next
</div>
</div>
</li>
</ul>
A full implementation of Pure Javascript Lightbox or Image Popup Modal is available in one my Answers at https://stackoverflow.com/a/67169851/8210884.
This Answer mentioned in the link above allows handling both the issues of Hiding Lightbox with ESC key as well as navigating through images in Lightbox using Left and Right arrow key.
Here are the Pieces of code from that Answer which will help us achieve these Two issues.
Hiding the Lightbox with ESC key :
if(event.keyCode==27){ // If ESC key is pressed
if(document.getElementById("lightbox-container").classList.contains("showcontainer")){ // LIGHTBOX ON
document.getElementById("lightbox-container").classList.remove("showcontainer");
}
}
Navigating through all the images on a Webpage in Lightbox with Left and Right Arrow key :
else if(event.keyCode==37) { // Left arrow key
if(document.getElementById("lightbox-container").classList.contains("showcontainer")){ // LIGHTBOX ON
// first get the URL of image displayed in the LIGHT BOX
var currimgsrc = document.getElementById("lightbox-cont-img").getAttribute("src");
// now match the sequence number in the array
var serialofarray = 0;
for(k=0;k<allimgurlarray.length;k++){
if(currimgsrc == allimgurlarray[k][2]){
serialofarray = allimgurlarray[k][0];
}
}
// with LEFT arrow, we are supposed to reduce the sequence and then use its ATTR SRC to LIGHT BOX
if(serialofarray<=0){
serialofarray = allimgurlarray.length - 1;
}
else {
serialofarray = serialofarray - 1;
}
console.log("Left Arrow : "+serialofarray);
document.getElementById("lightbox-cont-img").setAttribute("src", allimgurlarray[serialofarray][2]);
}
}
else if(event.keyCode==39) { // Right Arrow Key
if(document.getElementById("lightbox-container").classList.contains("showcontainer")){
// first get the URL of image displayed in the LIGHT BOX
var currimgsrc = document.getElementById("lightbox-cont-img").getAttribute("src");
// now match the sequence number in the array
var serialofarray = 0;
for(l=0;l<allimgurlarray.length;l++){
if(currimgsrc == allimgurlarray[l][2]){
serialofarray = allimgurlarray[l][0];
}
}
// with RIGHT arrow, we are supposed to increase the sequence and then use its ATTR SRC to LIGHT BOX
if(serialofarray>=allimgurlarray.length-1){
serialofarray = 0;
}
else {
serialofarray = serialofarray + 1;
}
console.log("Right Arrow : "+serialofarray);
document.getElementById("lightbox-cont-img").setAttribute("src", allimgurlarray[serialofarray][2]);
}
}
These conditional cases related to Key Pressing events are tackled in document.onkeydown = function(event).
This piece of code below is very important for disabling the default behaviours of Key pressing events on IMG tags as well as stacking up all the images on a webpage in an Array to allow Navigation in Lightbox with Left and Right arrow key.
// Select all A tags with IMG child nodes
var atagswithimgtag = document.querySelectorAll("a[href]");
// then prevent the default behaviour of A tags by preventing of opening new page by HREF
// as well as collect all the HREF of A tags with images to enable RIGHT and LEFT arrow key
var allimgurlarray = [];
for(i=0;i<atagswithimgtag.length;i++){
var childAIMGtag = atagswithimgtag[i].childNodes;
if (childAIMGtag[0].nodeType != Node.TEXT_NODE) // or if (el[i].nodeType != 3)
{
// this seems too be a A tag with IMG tag as Childnode
// first we need to prevent the default behaviour of opening the IMG in New Tab
atagswithimgtag[i].addEventListener("click", function(event){
event.preventDefault();
});
// second is when we need to fill image URL aray with A HREF
var listofnodes = atagswithimgtag[i];
allimgurlarray[i] = [];
allimgurlarray[i][0] = i;
allimgurlarray[i][1] = " Image URL is ";//listofnodes.getAttributeNode("title").value;
allimgurlarray[i][2] = listofnodes.getAttributeNode("href").value;
}
console.log(childAIMGtag[0].innerHTML);
}
I'm new to jQuery and i must admit that i've understood nothing yet, the syntax appears to me as an unknown language although i thought that i had my experiences with javascript.
Nevertheless i managed it to implement this menu in my asp.net masterpage's header.
Even got it to work that the content-page is loaded with ajax with help from here.
But finally i'm failing with the menu to disappear when the new page was loaded asynchronously. I dont know how to hide this accursed jQuery Menu.
Following the part of the js-file where the events are registered for hiding/disappearing. I dont know how to get the part that is responsible for it and even i dont know how to implement that part in my Anchor-onclick function where i dont have a reference to the jQuery Object.
buildmenu:function($, setting){
var smoothmenu=ddsmoothmenu
var $mainmenu=$("#"+setting.mainmenuid+">ul") //reference main menu UL
$mainmenu.parent().get(0).className=setting.classname || "ddsmoothmenu"
var $headers=$mainmenu.find("ul").parent()
$headers.hover(
function(e){
$(this).children('a:eq(0)').addClass('selected')
},
function(e){
$(this).children('a:eq(0)').removeClass('selected')
}
)
$headers.each(function(i){ //loop through each LI header
var $curobj=$(this).css({zIndex: 100-i}) //reference current LI header
var $subul=$(this).find('ul:eq(0)').css({display:'block'})
$subul.data('timers', {})
this._dimensions={w:this.offsetWidth, h:this.offsetHeight, subulw:$subul.outerWidth(), subulh:$subul.outerHeight()}
this.istopheader=$curobj.parents("ul").length==1? true : false //is top level header?
$subul.css({top:this.istopheader && setting.orientation!='v'? this._dimensions.h+"px" : 0})
$curobj.children("a:eq(0)").css(this.istopheader? {paddingRight: smoothmenu.arrowimages.down[2]} : {}).append( //add arrow images
'<img src="'+ (this.istopheader && setting.orientation!='v'? smoothmenu.arrowimages.down[1] : smoothmenu.arrowimages.right[1])
+'" class="' + (this.istopheader && setting.orientation!='v'? smoothmenu.arrowimages.down[0] : smoothmenu.arrowimages.right[0])
+ '" style="border:0;" />'
)
if (smoothmenu.shadow.enable){
this._shadowoffset={x:(this.istopheader?$subul.offset().left+smoothmenu.shadow.offsetx : this._dimensions.w), y:(this.istopheader? $subul.offset().top+smoothmenu.shadow.offsety : $curobj.position().top)} //store this shadow's offsets
if (this.istopheader)
$parentshadow=$(document.body)
else{
var $parentLi=$curobj.parents("li:eq(0)")
$parentshadow=$parentLi.get(0).$shadow
}
this.$shadow=$('<div class="ddshadow'+(this.istopheader? ' toplevelshadow' : '')+'"></div>').prependTo($parentshadow).css({left:this._shadowoffset.x+'px', top:this._shadowoffset.y+'px'}) //insert shadow DIV and set it to parent node for the next shadow div
}
$curobj.hover(
function(e){
var $targetul=$subul //reference UL to reveal
var header=$curobj.get(0) //reference header LI as DOM object
clearTimeout($targetul.data('timers').hidetimer)
$targetul.data('timers').showtimer=setTimeout(function(){
header._offsets={left:$curobj.offset().left, top:$curobj.offset().top}
var menuleft=header.istopheader && setting.orientation!='v'? 0 : header._dimensions.w
menuleft=(header._offsets.left+menuleft+header._dimensions.subulw>$(window).width())? (header.istopheader && setting.orientation!='v'? -header._dimensions.subulw+header._dimensions.w : -header._dimensions.w) : menuleft //calculate this sub menu's offsets from its parent
if ($targetul.queue().length<=1){ //if 1 or less queued animations
$targetul.css({left:menuleft+"px", width:header._dimensions.subulw+'px'}).animate({height:'show',opacity:'show'}, ddsmoothmenu.transition.overtime)
if (smoothmenu.shadow.enable){
var shadowleft=header.istopheader? $targetul.offset().left+ddsmoothmenu.shadow.offsetx : menuleft
var shadowtop=header.istopheader?$targetul.offset().top+smoothmenu.shadow.offsety : header._shadowoffset.y
if (!header.istopheader && ddsmoothmenu.detectwebkit){ //in WebKit browsers, restore shadow's opacity to full
header.$shadow.css({opacity:1})
}
header.$shadow.css({overflow:'', width:header._dimensions.subulw+'px', left:shadowleft+'px', top:shadowtop+'px'}).animate({height:header._dimensions.subulh+'px'}, ddsmoothmenu.transition.overtime)
}
}
}, ddsmoothmenu.showhidedelay.showdelay)
},
function(e){
var $targetul=$subul
var header=$curobj.get(0)
clearTimeout($targetul.data('timers').showtimer)
$targetul.data('timers').hidetimer=setTimeout(function(){
$targetul.animate({height:'hide', opacity:'hide'}, ddsmoothmenu.transition.outtime)
if (smoothmenu.shadow.enable){
if (ddsmoothmenu.detectwebkit){ //in WebKit browsers, set first child shadow's opacity to 0, as "overflow:hidden" doesn't work in them
header.$shadow.children('div:eq(0)').css({opacity:0})
}
header.$shadow.css({overflow:'hidden'}).animate({height:0}, ddsmoothmenu.transition.outtime)
}
}, ddsmoothmenu.showhidedelay.hidedelay)
}
) //end hover
}) //end $headers.each()
$mainmenu.find("ul").css({display:'none', visibility:'visible'})
}
one link of my menu what i want to hide when the content is redirected to another page(i need "closeMenu-function"):
<li>Delivery Control</li>
In short: I want to fade out the submenus the same way they do automatically onblur, so that only the headermenu stays visible but i dont know how.
Thanks, Tim
EDIT: thanks to Starx' private-lesson in jQuery for beginners i solved it:
I forgot the # in $("#smoothmenu1"). After that it was not difficult to find and call the hover-function from the menu's headers to let them fade out smoothly:
$("#smoothmenu1").find("ul").hover();
Regards,
Tim
Ok, I didn't read your whole post. But if you are using a jQuery Menu, that menu should having a container element like <div> or <ul> and they will either have a class or id
In case it is a id then do
$(document).ready(function() {
$("#myelementid").hide();
});
In case it has a class then do
$(document).ready(function() {
$(".myelementclass").hide();
});
Hope this helps
UPDATE
$("#mainmenu").children().hide(); // to hide all child elements
or
$(".submenu").hide(); //to hide every submenu