jquery mouseleave causing other script to stop working? - hover

I am writing a rater script so items can be rated 1 through 5 stars. My script works at first, causing the stars to change from the current rating to whatever they are moused over, and then back to the current rating when they mouse out. But then, hovering back over the stars causes no change. (No clicks in the meantime.)
So hover works, then mouseleave works, then hover no longer works although mouseleave continues to work. Here is my code from the javascript file:
$(document).ready(function(){
$("img.rateImage").hover(function(){
$(this).attr("src","images/vote-star.png");
$(this).prevAll("img.rateImage").attr("src","images/vote-star.png");
$(this).nextAll("img.rateImage").attr("src","images/vote-star-off.png");
});
$("div#invRate").mouseleave(function(){
var rate = $(this).attr("ref");
var i = 1;
var imgs = "";
while (rate > 0){
imgs += "<img class=\"rateImage\" id=\"vote"+i+"\" src=\"images/vote-star.png\" alt=\""+i+"\" style=\"cursor:pointer;\" /> ";
i++;
rate--;
}
while (i < 6){
imgs += "<img class=\"rateImage\" id=\"vote"+i+"\" src=\"images/vote-star-off.png\" alt=\""+i+"\" style=\"cursor:pointer;\" /> ";
i++;
}
$(this).html(imgs);
});
});
And here is the div tag and code where all of this is happening:
<div style="display:block; text-align:center;" id="invRate" ref="<?= $curRate; ?>">
<?
while ($curRate > 0){?>
<img class="rateImage" id="vote<?= $i ?>" src="images/vote-star.png" alt="<?= $i ?>" style="cursor:pointer;" />
<? $i ++;
$curRate --;
}
while ($i < 6){?>
<img class="rateImage" id="vote<?= $i ?>" src="images/vote-star-off.png" alt="<?= $i ?>" style="cursor:pointer;" />
<? $i ++;
}
?>
</div>
Is there any reason the mouseleave event would cause the hover event to stop working? The html that the mouseleave event passes back to the div tag is the exact same html as what is there to begin with. So I'm kind of lost.
Thanks in advance for any suggestions and help.
EDIT
With Anthony's suggestions, I looked into live() but found that it was deprecated, and that I should use on(). The delegate method also suggested to use on(). So that's what I went with. After getting a couple errors, I realized that my jquery.js was just old, so I updated that and it worked like a charm. I only changed the first line inside of the ready(function(){}) to look like:
$("#invRate").on("hover","img.rateImage",function(){

Your mouseleave event handler function is replacing the HTML of the div, thereby creating new DOM elements that no longer have the hover event handler attached to them. You can use jQuery's live() method to automatically add the event handler to any newly created DOM elements that match the selector.

Related

JQuery populate div with link content but also need to move (like anchor link) to area where div located

I have unordered list of links. Using JQuery, when clicked, the link's contents (a div with image and text) are loaded into the section specified. This all works beautifully. But I'm wondering how to also get the onclick function to move the view to the div's location on the page similarly to how anchor tag works. Here is the site where you can see the div being populated, but not moving down to view it. https://www.thecompassconcerts.com/artists.php
My JQuery knowledge is not awesome (I'm being generous).
I followed Osama's suggestion to add event listener and I got almost correct results. Upon first click...contents are loaded but do not move. But on every successive click, it functions perfectly: Contents loaded and move to div (like an anchor link) works! BUT...not on Safari or Mobile Safari.
Here is my jQuery. I assume if first click is not working that I must add listener before the first click?? Can the event listeners be added on page load BEFORE the function to prevent default click, etc.?
<script>
// BEGIN FUNCTION TO CAPTURE AND INSERT CONTENT
$(document).ready(function () {
// PREVENT DEFAULT LINK ACTION
$('.bio').click(function (e) {
e.preventDefault();
// ADD LISTENER TO EACH ITEM BY CLASS
var list = document.getElementsByClassName("bio");
for (let i = 0; i < list.length; i++) {
list[i].onclick = moveToDiv;
}
// FUNCTION TO MOVE TO LOCATION
function moveToDiv() {
document.location = "#performbio";
}
// STORE the page contents
var link = $(this).attr("href");
// load the contents into #performbio div
$('#performbio').load(link);
});
});
</script>
Here is the HTML with links in unordered list
<!-- CONTRIBUTING ARTISTS LIST AND BIOS -->
<section id="artists">
<h2>Contributing Artists</h2>
<ul class="cols">
<li><a class="bio" href="performers/first-last.html">First Last</a></li>
<li><a class="bio" href="performers/first-last.html">First Last</a></li>
<li><a class="bio" href="performers/first-last.html">First Last</a></li>
</ul>
</section>
Here is HTML of Section where code is being inserted by function
<!-- Performer Bios Dynamically updated -->
<section id="performbio">
</section>
Here is div contents that are being inserted
<div class="artistbio">
<p class="artistname">First Last</p>
<img class="artistimg" src="performers/img/name.jpg">
<p>lots of text here</p>
</div>
If I understand it right, you want to scroll to the section where the details appear on clicking any item in the list but through js and not HTML. In that case, you would add an onclick listener on to the list elements like so:
listElement.onclick = moveToDiv;
The function:
function moveToDiv() {
document.location = "#performbio";
}
A simple way to add a listener to all of the elements:
var list = document.getElementsByClassName("bio");
for (let i = 0; i < list.length; i++) {
list[i].onclick = moveToDiv;
}
For the edited post, you need to move the function definition out of the document.ready function. you would change the script to:
// FUNCTION TO MOVE TO LOCATION
function moveToDiv() {
document.location = "#performbio";
}
$(document).ready(function () {
// PREVENT DEFAULT LINK ACTION
$('.bio').click(function (e) {
e.preventDefault();
// ADD LISTENER TO EACH ITEM BY CLASS
var list = document.getElementsByClassName("bio");
for (let i = 0; i < list.length; i++) {
list[i].onclick = moveToDiv;
}
// STORE the page contents
var link = $(this).attr("href");
// load the contents into #performbio div
$('#performbio').load(link);
});
});
Another Solution: Using scrollIntoView
First, get all the elements into a variable using querySelectorAll
var elements = document.querySelectorAll(".bio");
Then create a function, for the scrolling part:
function scroll(element) {
element.scrollIntoView();
}
Then just add the onclick listener:
for (let i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', function() {
scroll(elements[i]);
});
}
I found it very frustrating to try to accomplish these two tasks so instead of a jQuery solution I opted for a CSS solution.
I populated my DIV with all the php includes, gave them unique id's for the anchors to work and then used CSS to hide them by default until clicked and it works like a charm....shows only what I need to show and goes there like an anchor is supposed to.
I must thank Ghost for all of your help and efforts to try and solve this via jQuery. You were very kind and generous.
Here is the code I used:
My collection of links.
<li><a class="bio" href="#artist-name1">Name 1</a></li>
<li><a class="bio" href="#artist-name2">Name 2</a></li>
which anchors to these divs
<div class="bio-container" id="artist-name1">
<?php include('performers/name-lastname.html'); ?>
</div>
<div class="bio-container" id="artist-name2">
<?php include('performers/name-lastname.html'); ?>
</div>
Then I use this CSS to hide those divs until the anchors are clicked.
I'm using [id*="artist-"] to target only links with such text...very easy. Not ideal for a massive list...but mine is not so large so it will do for this situation.
[id*="artist-"] {display: none;}
[id*="artist-"]:target {display: block;}

How to remove blank image container?

How can I remove a blank image container if the image's source is unavailable please? I would only like the image to appear if its source is available. Otherwise, I don't want anything to appear, including the blank container.
HTML image syntax:
<img src="url" alt="some_text">
You are able to do this using JavaScript and the error event on the img tag.
For example:
<img src="url" alt="some_text" id="myimage">
<script>
var imgElement = document.getElementById('myimage');
imgElement.addEventListener('error', function()
{
this.parentNode.removeChild(this);
}, true);
</script>
(Oops, sorry #JosephSilber, modified my example to be a bit different ;-))
Your best bet would be using server-side processing if you know that your image isn't going to be available. If you're intentionally leaving the src blank, for example, you can do something like this in PHP:
<?php
$src = ''; // or something else
if (!empty($src)) { ?>
<img src="<?=$src?>" alt="some_text" />
<?php } ?>
Loop through your images, and bind onerror:
imgNode.onerror = function () {
this.parentNode.removeChild(this);
};

Jquery Slider and Jquery autocomplete

I Have Been working on a page the using a jquery autocomplete so that while your typing in a clients name its searching the databases for any macth containing that phrase. so using "LIKE" .
i have also put together a jquery silder so that it displays the records that are automaticly loaded from the database and when u click on one it will load more inofmation from the database..
indivaully thesse 2 pieces of code work fine so the jquery autocomplete on a serprate page just loading text enterys from a database.
and the jquery slider works fine with manually entered data and data loaded by php from a database..
but when i put them together the problem is it shows the record on the screen with the styling from the jquery slider but when u click the record it doesnt show anything so no slider (atm just manual html data in the slider for testing)
i have tried multipule tests such as running them serpeatre, placing them in different div tags. i have got it to work with a single sql query but it isnt what i need to do because i dont want the page to need to be refreshed for loading data.
i have placed my code from both files so th is first one is what calls the ajax request to create the records..
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
$(".recordrow").click(function() {
var divid = "details-" + $(this).attr('id').split("-")[1]; //Create the id of the div
$("#"+divid).show().animate({ "right": '0%'}); //Bring the div from right to left with 200px padding from the screen
});
$('#bt-close').click(function(){
$('.details').animate({right:-2000}, 500);
});
});
function getStates(value){
$.post("sql.php",{partialState:value},function(data){
$("#results").html(data);
});
}
</script>
<input type="text" onkeyup="getStates(this.value)"/>
<br />
<div id="results">
</div>
And this is the page which querys the database
<?php
if($_POST['partialState']){
mysql_connect("localhost","root")or die (mysql_error());
mysql_select_db("ict_devices") or die (mysql_error());
$test=$_POST['partialState'];
$text="... More details of the records";
$states = mysql_query("Select * from students Where FirstName LIKE '%$test%'");
while($state= mysql_fetch_array($states)){
echo '<div class="recordrow" id="row-$state["id"]">'.$state['FirstName'].'</div>';
echo '<div class="details" id="details-$state["id"]">'.$text.'Close</div>';
}
}
?>
any help would be greatly appricated
I think you need to bind a click function on "recordrow" div after you got it by ajax. In your code there are no "recordrows" on the moment a click event binds. So you need something like this:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
function getStates(value){
$.post("sql.php", function(data){
$("#results").html(data);
$('.recordrow').each(function() {
$(this).bind('click', function() {
var divid = "details-" + $(this).attr('id').split("-")[1]; //Create the id of the div
$("#"+divid).show().animate({ "right": '0%'}); //Bring the div from right to left with 200px padding from the screen
});
});
$('#bt-close').each(function() {
$(this).bind('click', function(){
$('.details').animate({right:-2000}, 500);
});
});
});
}
</script>
Your ajax is right and when you test slider recordrows already in DOM, click binds correcly. That is why it works by parts
EDIT: I test my code and add binding of bt-close event, it works for me, try it. It shows details when clicked and animation launches

Change color tr onclick

I have this code, when the row is clicked the row is changed to 'selected_row'. When clicked again it´s supposed to change back to '$class', but it doesn't. What is causing the trouble and how can I solve this?
$class = ($class == 'even') ? 'odd' : 'even';
echo '<tr class="'.$class.'" onclick="this.className=this.className==\'selected_row\'? '.$class.' :\'selected_row\';">
You forgot a closing quote behind the last $class.
I think these kind of syntax errors should show up when you use FireBug or similar debugging tools.
Hi you could try this, simply place the function below within the section of your html code.
<script type="text/javascript">
function toggleClass(ele,customClass)
{
ele.className=ele.className=='selected_row' ? customClass:'selected_row';
}
</script>
Then change your existing syntax from:
echo '<tr class="'.$class.'" onclick="this.className=this.className==\'selected_row\'? '.$class.' :\'selected_row\';">
To:
echo '<tr class="'.$class.'" onclick="toggleClass(this,\''.$class.'\');"><td>apple</td></tr>';
Hope this helps.

Changing the BG Color of a selected link

I have a menu that I am using and it will change the background color when I hover using a:hover but I want to know how to change the class=line so that it sticks.
So from the home if they click contacts the home pages
from (a href="#" class="clr") to (a href="#")
and Contacts would change
from (a href="#") to (a href="#" class="clr")
any help?
JD
I believe you are wanting to highlight the navigational item that you're on. My answer here is fairly valid in this question as well, I believe:
It's a better semantic match and likely an easier variable to set to keep the navigation using the same classes or ids everywhere and only alter the body element's id to match:
<li id="homeNav">home</li>
<li id="blogNav">blog</li>
and then on each page...
<body id="home">
<body id="blog">
And in the css:
#home #homeNav {background-image:url(homeNav-on.jpg);}
#blog #blogNav {background-image:url(blogNav-on.jpg);}
The way to change class (I assume you're talking of the DOM), in javascript is:
document.getElementById("element").className='myClass';
Hope this helps.
The mechanism we use frequently is by having a few generic event listeners on the body and have all required events bubble up. Once caught, we check for a certain className (or className pattern) on the triggering element. If such a className is found, we consider it a state identifier, and we trigger behavior based on such states.
For instance, we have defined className pairs (such as "selected" and "unselected") with the default behavior of toggling. Or make them exclusive by giving the parent element the className "exclusive-selected".
A simple mechanism like that can be extended to your liking and can be very powerful.
Allow me to post a simple demonstration. Non-generic, but it is just to illustrate the inner workings of such a mechanism. For this example I consider the className pair "selected" and "unselected" to be exclusive.
<html>
<head>
<script>
document.onclick = function(evt) {
var el = window.event? event.srcElement : evt.target;
if (el && el.className == "unselected") {
el.className = "selected";
var siblings = el.parentNode.childNodes;
for (var i = 0, l = siblings.length; i < l; i++) {
var sib = siblings[i];
if (sib != el && sib.className == "selected")
sib.className = "unselected";
}
}
}
</script>
<style>
.selected { background: #f00; }
</style>
</head>
<body>
One
Two
Three
</body>
</html>
It ought to work on IE, Firefox and other browsers. Of course this mechanism can be made generic and have all kinds of className states and behaviors implemented.
This may not apply to you, but it may lead you down the right path. If you are using PHP, stick this in your head before the doctype declaration or the (x)html tag:
<?php
// Get current page file name
$url = Explode('/', $_SERVER["PHP_SELF"]);
$page = $parts[count($url) - 1];
?>
Then, in your menu item where you would like the class designation, place the following, but change "index.php" to the name of the page:
<?php if ($page == "index.php") echo ' class="current"' ?>
So ultimately your menu should look similar to this:
<div id="navigation">
<ul>
<li><a href="index.php"<?php if ($page == "index.php") echo ' class="current"' ?>>Home</a></li>
<li><a href="page1.php"<?php if ($page == "page1.php") echo ' class="current"' ?>>Resume</a></li>
<li><a href="page2.php"<?php if ($page == "page2.php") echo ' class="current"' ?>>Photography</a></li>
</ul>
</div>
Last step is adding the CSS:
#navigation ul li a.current {
background-color: #FFF;
}
Hope this helps.
You may want to check out jQuery (jquery.com).
Using jQuery, you would change the class (and stick it) like this:
$('#link-id').addClass('your-class');
You could bind the code to the links like this:
$('#link-id').mouseover(
function(){
$(this).addClass('your-class');
}
);
http://docs.jquery.com/Attributes