Jquery onmouseover() function on dynamic html images and span - javascript

I have some images and some span text on my page. Each image has his text and those elements are added dynamicaly with javascript.
Now, I would like to show the right message when mouseover on an image is detected.
It is not easy to explain, so here is the example:
var len = article_affiliations.length;
for (var affiliation_id = 0; affiliation_id < len; affiliation_id++)
{
$('#country_warning' + affiliation_id).mouseover(function () {
document.getElementById('country_warning_message' + affiliation_id)
.style.visibility = 'visible';
}).mouseout(function () {
document.getElementById('country_warning_message' + affiliation_id)
.style.visibility = 'hidden';
});
}
The problem is that when the onmouseover function will be called, the affiliation_id will have the maximum value and the message will be shown near the last image, and not near the clicked one.
Thank you very much for your help.

Closure should do the trick:
for(var affiliation_id=0; affiliation_id<article_affiliations.length; affiliation_id++) {
(function(i){
$('#country_warning'+i).mouseover(function() {
$('#country_warning_message'+i).css('visibility','visible');
}).mouseout(function(){
$('#country_warning_message'+i).css('visibility','hidden');
});
})(affiliation_id);
}

You'll need to bind your for loop in a closure for this to work. This way, all indices of #country_warning_i will be affected.
$(function () {
$.each(article_affiliations, function (i, v) {
$('#country_warning' + i).mouseover(function (affiliation_id, affiliation_iddddd) {
$('country_warning_message' + i).style.visibility = 'visible';
}).mouseout(function (i, affiliation_iddddd) {
$('country_warning_message' + i).style.visibility = 'hidden';
});
});
});
Enjoy and good luck!

You shouldn't do it with a loop that will just go through everyone of your elements. The best way of doing something like this is using the 'event.target'(built in jQuery) and 'this' objects.
Instead attach a mouseover event handler to the parent of your . The best is if your markup looks something like this:
<div class="item">
<img src="someimage.jpg" />
<span>some text</span>
</div>
<div class="item">
<img src="someimage.jpg" />
<span>some text</span>
</div>
<div class="item">
<img src="someimage.jpg" />
<span>some text</span>
</div>
That way you can use a script similar to this one:
$('.item').on('mouseover', function() {
$(this).find('span').show();
});
This will search for a span (every span) inside the element you attached the mouseover event to (for this ex the ).
Another way is to use simple css like this:
span {
visibility: hidden;
}
item:hover span {
visibility: visible;
}
This is an extremely simple solution and works beautifully, but unfortunately IE6 doesn't support hover on elements different from .

Related

JavaScript/jQuery code optimization

I'm learning JavaScript and jQuery and currently I'm dealing with following code:
$("#hrefBlur0").hover(function() {
$("#imgBlur0").toggleClass("blur frame");
});
$("#hrefBlur1").hover(function() {
$("#imgBlur1").toggleClass("blur frame");
});
$("#hrefBlur2").hover(function() {
$("#imgBlur2").toggleClass("blur frame");
});
$("#hrefBlur3").hover(function() {
$("#imgBlur3").toggleClass("blur frame");
});
$("#hrefBlur4").hover(function() {
$("#imgBlur4").toggleClass("blur frame");
});
$("#hrefBlur5").hover(function() {
$("#imgBlur5").toggleClass("blur frame");
});
$("#hrefBlur6").hover(function() {
$("#imgBlur6").toggleClass("blur frame");
});
$("#hrefBlur7").hover(function() {
$("#imgBlur7").toggleClass("blur frame");
});
The code is supposed to remove blur effect from an image while I hoover a cursor on a href link on the website. I'm wondering if I can do it faster, with fewer lines of code.
I tried:
for (var i = 0; i < 8; i++) {
$("#hrefBlur" + i).hover(function() {
$("#imgBlur" + i).toggleClass("blur frame");
});
}
But that code doesn't work.
Here's the JS fiddle: link
You can set a class to the elements and select that class, for example let's say you want to use "blurMeContainer" for the container, you can do something like this:
$(".blurMeContainer").hover(function(el){
$(this).find("img").toggleClass("blur frame");
});
The trick is that you must be aware that jQuery applies the events to the element, so inside the events function, the "this" accessor is the element involved in the event, than you can use the $ function in the selector in order to have his corrispective jQuery element, and then you can use "find" method to find any img tag inside the jQuery element. Obviously this could work only if you have a single image in the container, if you need to identify only one image in a set of images inside a single container, assign a class to that image (IE: "blurMe") and change the code in this way:
$(".blurMeContainer").hover(function(el){
$(this).find(".blurMe").toggleClass("blur frame");
});
Use attributeStartsWith selector , that Selects elements that have the specified attribute with a value beginning exactly with a given string:
$('a[id^="hrefBlur"]').hover(function() {
$(this).find('img').toggleClass("blur frame");
});
Here's working fiddle
Although doing what your after can be done with JQuery. I personally think it's the wrong tool for the Job.
CSS, will do all this for you, in a much simpler way. No Javascript needed. With the added benefit of the browser optimisations.
.blurme {
filter: blur(3px);
cursor: pointer;
transition: color 2s, filter 1s;
}
.blurme:hover {
filter: none;
color: red;
font-weight: bold;
}
<span class="blurme">One</span>
<span class="blurme">Two</span>
<span class="blurme">Three</span>
<span class="blurme">Four</span>
<span class="blurme">Five</span>
<span class="blurme">Six</span>
<br>
<img class="blurme" src="http://placekitten.com.s3.amazonaws.com/homepage-samples/96/139.jpg">
<img class="blurme" src="http://placekitten.com.s3.amazonaws.com/homepage-samples/96/139.jpg">
<img class="blurme" src="http://placekitten.com.s3.amazonaws.com/homepage-samples/96/139.jpg">

Using .getElementsByClassName to access multiple popups

I am attempting to use the following javascript to create various popups.Image popups when text is clicked. The problem is that when I click any of the text containers, all of the popup images appear. I know I am missing something obvious. Any help would be much appreciated. Here is the JS code:
function myFunction() {
var popup = document.getElementsByClassName("myPopup");
for(var i=0; i<popup.length; i++) {
popup[i].classList.toggle('show');
}
}
HTML:
<div class="popup" onclick="myFunction()"><span class="castName">Viola,</span>
<span class="popuptext myPopup"><img src=Viola_1.jpg
style="width:300px;height:100%;" alt="Viola"><p>Miss Ellen Terry as Viola, mid
to late 19th century</p></span></div>
Your function gets a list of elements and toggle the class 'show' to every element instead of the element you want. You have to pass in the element to the function.
You can change the onclick event for each div from:
<div class="popup" onclick="myFunction()">
to:
<div class="popup" onclick="myFunction(this)">
Then in your javascript
function myFunction(element){
if (element){ //If the element is passed into this function
element.getElementsByClassName("myPopup")[0].toggle('show');
}
}
Thum, this was very helpful. I ended up changing the HTML as you suggested and did the following to the javascript, which worked perfectly:
function myFunction(element) {
var popup = element.getElementsByClassName('myPopup');
var i;
for( i=0; i<popup.length; i--) {
popup[i].classList.toggle('show');
}
}

When one is clicked, disable the other

So I have a mini slide menu in my website there is a menu you can choose what you want to read. There are points to click, when u clicked it the point get a red background.
But there is a problem.
When i click one point and then an other point the first clicked point have to lose his background.
Here is my HTML:
<div id="slide_button" onClick="clicked(this);"><dir class="button_1"></dir></div>
<div id="slide_button" onClick="clicked(this);"><dir class="button_2"></dir></div>
<div id="slide_button" onClick="clicked(this);"><dir class="button_3"></dir></div>
<div id="slide_button" onClick="clicked(this);"><dir class="button_4"></dir></div>
<div id="slide_button" onClick="clicked(this);"><dir class="button_5"></dir></div>
Here is my JS:
function clicked(slide_button) {
slide_button.getElementsByTagName("dir")[0].style.backgroundColor="red";
}
HERE IS AN EXAMPLE ON FIDDLE.
My "QUESTION IS" what i have to do to solve that?
What should I pay attention?
First you need to fix your HTML becaue your id values aren't unique. In fact, you don't even need id values, so you should use "slide_button" as a class. You can then use it to select all the buttons:
<div onClick="clicked(this);" class="slide_button"><dir></dir></div>
<div onClick="clicked(this);" class="slide_button"><dir></dir></div>
<div onClick="clicked(this);" class="slide_button"><dir></dir></div>
<div onClick="clicked(this);" class="slide_button"><dir></dir></div>
<div onClick="clicked(this);" class="slide_button"><dir></dir></div>
The CSS needs to be changed now so "slide_button" is a class selector, instead of an id selector:
.slide_button {
display: inline-block;
}
As for clearing the background, clear all of them before coloring the selected one red:
function clicked(slide_button) {
var buttons = document.getElementsByClassName('slide_button');
for(var i = 0; i < buttons.length; i++) {
buttons[i].getElementsByTagName('dir')[0].style.backgroundColor = '';
}
slide_button.getElementsByTagName('dir')[0].style.backgroundColor = 'red';
}
jsfiddle
This uses just JavaScript with no JQuery, but if you are using JQuery, you might as well use it here. The code is a lot shorter and easier to follow.
Here's a JQuery version:
$(function() {
$('.slide_button').click(function() {
var $button = $(this);
$button.children(':first').css({ backgroundColor: 'red' });
$button.siblings().children(':first').css({ backgroundColor: '' });
});
});
Note: This registers a click-handler, so you can get rid of the "onclick" attirbutes.
jsfiddle
You have to select all other points and set their background to none.
Or remeber which point is selected and on select another just remove background on last and remeber current point, then set its background to red.
See fiddle: http://fiddle.jshell.net/399Dm/5/
At first id should be unique per element.
<div class="slide_button"><dir class="button"></dir></div>
<div class="slide_button"><dir class="button"></dir></div>
<div class="slide_button"><dir class="button"></dir></div>
<div class="slide_button"><dir class="button"></dir></div>
<div class="slide_button"><dir class="button"></dir></div>
Second, you should store reference of clicked element if you want later remove background color, and instead of inline event handlers or binding all elements would be better if you use event delegation.
Demonstration
(function () {
"use strict";
// getting parent node of divs, due to bind click event. then
var ele = document.querySelector(".slide_button").parentNode,
prev = null; // store previous clicked element
ele.addEventListener("click", clickHandler); // event handler.
function clickHandler(e) {
var t = e.target; // get target of clicked element
// filter by target node name and class. edit: removed class checking
if (t.nodeName.toLowerCase() === "dir") {
// checking value of prev !== null and it's not same element.
if (prev && prev !== t) {
prev.style.backgroundColor = "";
}
prev = t; // store clicked element
t.style.backgroundColor = "red";
}
}
}());
I have fixed the fiddle so that it works hopefully as you plan.
http://jsfiddle.net/399Dm/8/ There you go!
var forEach = function(ctn, callback){
return Array.prototype.forEach.call(ctn, callback);
}
function clear(element, index, array) {
element.getElementsByTagName("dir")[0].style.backgroundColor="";
}
function clicked(slide_button) {
forEach(document.getElementsByClassName("slide_button"), clear);
//.style.backgroundColor="";
slide_button.getElementsByTagName("dir")[0].style.backgroundColor="red";
}
I had a slightly different method than #atlavis but a similar result.
http://fiddle.jshell.net/2AGJQ/
JSFIDDLE DEMO
jQuery
$('.slide_button').click(function(){
$('.slide_button dir').css("background-color", "inherit");
$(this).find('dir').css("background-color", "red");
});
HTML - Your markup is invalid because you have duplicate ids. Make them classes as below instead.
<div class="slide_button" >
<dir class="button_1"></dir>
</div>
<div class="slide_button">
<dir class="button_2"></dir>
</div>
<div class="slide_button">
<dir class="button_3"></dir>
</div>
<div class="slide_button">
<dir class="button_4"></dir>
</div>
<div class="slide_button">
<dir class="button_5"></dir>
</div>
CSS change
.slide_button {
display: inline-block;
}
If you can look at the following jsfiddle, I used jQuery to get what you want.

How to Reduce Size of This jQuery Script and Make it More Flexible?

I just created script that shows/hides (toggles) block of HTML. There are four buttons that each can toggle its HTML block. When any HTML block is opened, but user has been clicked on other button than that HTML block's associated button... it hides that HTML block and shows new one.
Here is what I have at the moment:
$('.btn_add_event').click( function() {
$('.block_link, .block_photos, .block_videos').hide();
$('.block_event').toggle();
});
$('.btn_add_link').click( function() {
$('.block_event, .block_photos, .block_videos').hide();
$('.block_link').toggle();
});
$('.btn_add_photos').click( function() {
$('.block_event, .block_link, .block_videos').hide();
$('.block_photos').toggle();
});
$('.btn_add_videos').click( function() {
$('.block_event, .block_link, .block_photos').hide();
$('.block_videos').toggle();
});
Any ideas how to reduce code size? Also, this script isn't very flexible. Imagine to add two new buttons and blocks.
like Sam said, I would use a class that all the blocks share, so you never have to alter that code. Secondly, you can try 'traversing' to the closest block, therefore avoiding it's name. That approach is better than hard coding each specific block, but if the html dom tree changes you will need to refactor. Last, but best, you can pass in the class name desired block as a variable to the function. Below is something you can copy paste that is close to what you started with.
$('.myAddButtonClass').click( function() {
$('.mySharedBlockClass').filter(':visible').hide();
//find a good way to 'traverse' to your desired block, or name it specifically for now.
//$(this).closest(".mySharedBlockClass").show() complete guess
$('.specificBlockClass').show();
});
I kept reading this "When any HTML block is opened, but user has been clicked on other button than that HTML block's associated button" thinking that my eyes were failing me when Its just bad English.
If you want to make it more dynamic, what you can do is add a common class keyword. Then
when the click event is raise. You can have it loop though all the classes that have the
keyword and have it hide them all (except the current one that was clicked) and then show the current one by using the 'this' keyword.
you can refer below link,
http://chandreshmaheshwari.wordpress.com/2011/05/24/show-hide-div-content-using-jquery/
call function showSlidingDiv() onclick event and pass your button class dynamically.
This may be useful.
Thanks.
try this
$('input[type=button]').click( function() {
$('div[class^=block]').hide(); // I resumed html block is div
$(this).toggle();
});
Unfortunatly I couldn't test it, but if I can remember right following should work:
function toogleFunc(clickObject, toogleTarget, hideTarget)
{
$(clickObject).click(function()
{
$(hideTarget).hide();
$(toogleTarget).toggle();
});
}
And the call:
toogleFunc(
".btn_add_videos",
".block_videos",
".block_event, .block_link, .block_photos"
);
and so far
Assuming the buttons will only have one class each, something like this ought to work.
var classNames = [ 'btn_add_event', 'block_link', 'block_photos', 'block_videos' ];
var all = '.' + classNames.join(', .'); // generate a jquery format string for selection
$(all).click( function() {
var j = classNames.length;
while(j--){
if( this.className === classNames[j] ){
var others = classNames.splice(j, 1); // should leave all classes but the one on this button
$('.' + others.join(', .')).hide();
$('.' + classNames[j]).toggle();
}
}
}
All the buttons have the same handler. When the handler fires, it checks the sender for one of the classes in the list. If a class is found, it generates a jquery selection string from the remaining classes and hides them, and toggles the one found. You may have to do some checking to make sure the strings are generating correctly.
It depends by how your HTML is structured.
Supposing you've something like this
<div class="area">
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
</div>
...
<div class="sender">
<a class="one"></a>
<a class="two"></a>
<a class="three"></a>
</div>
You have a class shared by the sender and the target.
Your js would be like this:
$('.sender > a').click(function() {
var target = $(this).attr('class');
$('.area > .' + target).show().siblings().hide();
});
You show your real target and hide its siblings, which aren't needed.
If you put the class postfixes in an array, you can easily make this code more dynamic. This code assumed that it doesn't matter in which order toggle or hide are called. If it does matter, you can just remember the right classname inside the (inner) loop, and toggle that class after the loop.
The advantage to this approach is that you can extend the array with an exta class without needing to modifying the rest of the code.
var classes = new Array('videos', 'event', 'link', 'photos');
for (var i = 0; i < classes.length; ++i)
{
$('.btn_add_' + classes[i]).click(
function()
{
for (var j = 0; j < classes.length; ++j)
{
if (this.hasClass('btn_add_' + classes[j]))
{
$('.block_' + classes[j]).toggle();
}
else
{
$('.block_' + classes[j]).hide();
}
}
});
}
You could make this code more elegant by not assigning those elements classes like btn_add_event, but give them two classes: btn_add and event, or even resort to giving them id's. My solution is based on your description of your current html.
Here is what I think is a nice flexible and performant function. It assumes you can contain your links and html blocks in a parent, but otherwise it uses closures to precalculate the elements involved, so a click is super-fast.
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" ></script>
<script type="text/javascript">
// Enables show/hide functionality on click.
// The elements within 'container' matching the selector 'blocks' are hidden
// When elements within 'container' matching the selector 'clicker' are clicked
// their attribute with the name 'clickerAttr' is appended to the selector
// 'subject' to identify a target, usually one of the 'blocks'. All blocks
// except the target are hidden. The target is shown.
//
// Change clickerAttr from 'linkTarget' to 'id' if you want XHTML compliance
//
// container: grouping of related elements for which to enable this functionality
// clicker: selector to element type that when clicked triggers the show/hide functionality
// clickerAttr: name of the DOM attribute that will be used to adapt the 'subject' selector
// blocks: selector to the html blocks that will be shown or hidden when the clicker is clicked
// subject: root of the selector to be used to identify the one html block to be shown
//
function initToggle(container,clicker,clickerAttr,blocks,subject) {
$(container).each(
function(idx,instance) {
var containerElement = $(instance);
var containedBlocks = containerElement.find(blocks);
containerElement.find(clicker).each(function(idxC, instanceClicker) {
var tgtE = containerElement.find(subject+instanceClicker.getAttribute(clickerAttr));
var clickerBlocks = containedBlocks.not(tgtE);
$(instanceClicker).click(function(event) {
clickerBlocks.hide();
tgtE.toggle();
});
});
// initially cleared
containedBlocks.hide();
}
);
}
$(function() {
initToggle('.toggle','a.link','linkTarget','div.block','div.');
});
</script>
</head>
<body>
Example HTML block toggle:
<div class="toggle">
a <br />
b <br />
c <br />
<div class="A block"> A </div>
<div class="B block"> B </div>
<div class="C block"> C </div>
</div> <!-- toggle -->
This next one is not enabled, to show scoping.
<div class="toggle2">
a <br />
<div class="A block">A</div>
</div> <!-- toggle2 -->
This next one is enabled, to show use in multiple positions on a page, such as in a portlet library.
<div class="toggle">
a <br />
<div class="A block">A</div>
</div> <!-- toggle (2) -->
</body>
</html>

how to make div click-able?

<div><span>shanghai</span><span>male</span></div>
For div like above,when mouse on,it should become cursor:pointer,and when clicked,fire a
javascript function,how to do that job?
EDIT: and how to change the background color of div when mouse is on?
EDIT AGAIN:how to make the first span's width=120px?Seems not working in firefox
Give it an ID like "something", then:
var something = document.getElementById('something');
something.style.cursor = 'pointer';
something.onclick = function() {
// do something...
};
Changing the background color (as per your updated question):
something.onmouseover = function() {
this.style.backgroundColor = 'red';
};
something.onmouseout = function() {
this.style.backgroundColor = '';
};
<div style="cursor: pointer;" onclick="theFunction()">
is the simplest thing that works.
Of course in the final solution you should separate the markup from styling (css) and behavior (javascript) - read on it on a list apart for good practices on not just solving this particular problem but in markup design in general.
The simplest of them all:
<div onclick="location.href='where.you.want.to.go'" style="cursor:pointer"></div>
I suggest to use jQuery:
$('#mydiv')
.css('cursor', 'pointer')
.click(
function(){
alert('Click event is fired');
}
)
.hover(
function(){
$(this).css('background', '#ff00ff');
},
function(){
$(this).css('background', '');
}
);
I suggest to use a CSS class called clickbox and activate it with jQuery:
$(".clickbox").click(function(){
window.location=$(this).find("a").attr("href");
return false;
});
Now the only thing you have to do is mark your div as clickable and provide a link:
<div id="logo" class="clickbox"></div>
Plus a CSS style to change the mouse cursor:
.clickbox {
cursor: pointer;
}
Easy, isn't it?
add the onclick attribute
<div onclick="myFunction( event );"><span>shanghai</span><span>male</span></div>
To get the cursor to change use css's cursor rule.
div[onclick] {
cursor: pointer;
}
The selector uses an attribute selector which does not work in some versions of IE. If you want to support those versions, add a class to your div.
As you updated your question, here's an obtrustive example:
window.onload = function()
{
var div = document.getElementById("mydiv");
div.style.cursor = 'pointer';
div.onmouseover = function()
{
div.style.background = "#ff00ff";
};
}
<div style="cursor: pointer;" onclick="theFunction()" onmouseover="this.style.background='red'" onmouseout="this.style.background=''" ><span>shanghai</span><span>male</span></div>
This will change the background color as well
If this div is a function I suggest use cursor:pointer in your style like style="cursor:pointer" and can use onclick function.
like this
<div onclick="myfunction()" style="cursor:pointer"></div>
but I suggest you use a JS framework like jquery or extjs

Categories