I'm having an issue with special characters triggering events in jQuery. I've got a div containing some text, when it's hovered I call a hover function, when it's "unhovered" I call another function. This works fine if I don't have any quotations: ' or " in the div contents, but causes the unhover event to trigger prematurely if those characters are in the div.
That is to say, the unhover event is being called when I'm still mousing over the div. I've tried using htmlentities, htmlspecialchars on the text in the div, but neither seem to help. Any ideas?
$('#elementID').hover(hoverIn, hoverOut);
EDIT: I should add that the div's contents are being passed to it by php via a TWIG template variable.
It sounds weird. Content should not affect the hover event. It sounds like the div you are asigning the hover function doesn't cover the whole area and possibly another element inside is breaking your code, but without ckecking the actual code is hard to tell what's wrong.
Related
I have a slider and I've organized it into a <ul> with the <li>s as the individual items to cycle through. Only the second <li> is visible, and if you scroll left, it takes the last <li> and removes it, puts it on the front, and vice versa if you scroll right.
Here's the Code Pen: http://codepen.io/anon/pen/kGBcr
The slider is on the right side, under "More Influencers." The problem is when I click on the 'follow' link, it changes the CSS and text like I want only until it gets to a <li> that has been removed and placed on the other end. It doesn't prevent the default link, and just reloads the page.
Thanks for any help!
The functions that rotate the slider are on lines 120 and 135. The function that changes the text and CSS background color is on line 78.
Whenever you remove an element with remove(), it loses its bindings, and you need to re-bind event listeners.
However, if you use appendTo() instead to move it, the event listeners will stick around.
Another alternative is using the detach() function:
var objectWithEvents = $('#old').detach();
$('#new').append(objectWithEvents);
Your situation is even worse than just removing, since you're using:
html = $('element').html();
newHtml = someEl.append('<li>'+html+'</li>');
Around line 127. This makes it even worse because not only you're deleting the element, but taking its html content making it even more difficult to keep event listeners associated with it.
Here's an example http://jsbin.com/ukoqud/3/edit
If you click on a red box, you'll get an alert.
If you click on a link, everything in a blue box will be replaced with just a red box. Link will disappear and if you click on a red box then, you'll get no alert.
Why this happens?
Is it related to innerHTML?
Does it work the same way in all browsers?
Here's one more example http://jsbin.com/ukoqud/1/edit In this one you'll get an alert after clicking on a link. Things happen in a quite similar way, but result is different.
I would like to understand the reason, there's no need to fix my code.
When you call $(".red"), it returns a collection of DOM elements that exist at that moment. So $(".red").click(function...) just binds a handler to the click event on those elements. If you later create new elements with the same class, they weren't in this collection, so they don't have the handler bound to them. jQuery doesn't watch the DOM for changes and update the handlers dynamically -- the bindings are just on the elements you matched at the time you called click().
You either need to bind the handler again after adding the new HTML, or use delegation with .on():
$(".blue").on("click", ".red", function(){
alert('click on a red box detected');
});
This works by binding a handler to $(".blue"), which doesn't change dynamically. The handler checks whether the element you clicked on matches the ".red" selector, so it's able to handle dynamically-added elements without requiring rebinding.
I think the reason why it works in your second example is because the red block isn't inside the blue box to start. When you move it inside, jQuery reuses the same DOM elements, so the bindings go along with it. In the first example, the red box starts out inside the blue box. When you do $('.red').parent().html(...), the first thing it does is empty $('.red').parent() (the blue box), so the original red element is removed from the DOM, and its bindings are lost.
We need to understand how setting html of an element works. Then you will figure out your answer yourself.
Take a look at this bin Updated Bin
When we set HTML of an element, it first removes all the elements inside it.
Those elements are not removed from memory depending upon whether they are garbage collected or not.
If any of the child is having a reference, then that particular child won't be garbage collected.
In your case, we are having a reference to red element so it is still present in memory but not a part of document.
When we say blue.html(red) in my example, red element becomes a part of document again but this time there won't be any handlers on it So your click does not work.
While in your example2,
red element is always a part of document hence no handlers were lost when red element is moved inside blue element.
I hope this will help.
because when u click the link, you delete everything on screen and create everything from a scratch and event binding goes away. so you should use this
$(".blue").on("click", ".red", function(){
alert('');
});
this way, binding is done differently. it doesnt bind it statically
I'm creating a web-app interface which will allow users to construct sentences by clicking on words/phrases. Each word of phrase will be contained in its own page element, eg. a <div>. So the div class would need to allow:
dragging into a different order relative to the other divs/words (ie. sorting)
an X (only visible when hovering over) in the top right corner of its box to remove it completely upon clicking
changing of font/text upon click actions
be inserted into the page when the user wishes to add another word
For instance, imagine this is the page (quote marks denote an element):
"Hi, my name is" [Textbox] "I work at..." "and I was born in" [Combobox]
The phrase in italics is 'inactive' and not part of the sentence, but if the user clicked it then it would change to "I work at" [Textbox] and a new div would be added eg. "And also at..." to allow further expansion. The phrases in bold would have a close button /clickable action to get rid of them or make them inactive again. Also they would be draggable to change the order. As you can see I would also need to dynamically insert new textboxes and comboboxes to accommodate more phrases requiring input.
Could somebody give me a brief run down on what steps I need to take? I've seen sortable list elements in JQuery eg. http://jsfiddle.net/ctrlfrk/A4K4t/ which is a start. Would I just need to spruce this up with some basic JavaScript and CSS? Or would I need to use server-side scripting to dynamically add more page content?
To summarize, I need the div to change font/text upon clicking, have a hover-over close button, remove and be inserted upon simple click events, and be sortable by dragging. I also need comboboxes/textboxes to be added/removed in parallel.
Any tips would be greatly appreciated.
You don't need the server for new content unless it is stored or generated there.
Not having done this exact thing before I don't see any grand scheme to implement, I would just add the features incrementally until you get where you need to go. You may have to refactor things a bit along the way, but I probably don't have to tell you that. ;)
One thing you will have to do when you add or delete elements is to rebind the jQuery functions, it won't enough to just call them when the document loads. So put them in a function and call it whenever you add or remove an element.
Regarding your description of the UI behavior, you say that inactive elements can be dragged and that they can be made active by clicking on them. You can do this (just see if the thing has been dragged or not on mouseup to know whether it was drag or a click) but it might not be the best UI design choice, IMO. It wouldn't be the worst thing in the world, but I find it a little frustrating when the wrong thing happens when I try to do something. Of course, implementing and seeing for yourself is probably best.
Sorting:
I would implement the phrases in an unordered list (ul) which makes it as simple as
$("#ulId").sortable();
You can make ul/li items stack next to each other in a similar manner to how you make horizontal navigation menus out of ul elements.
A destrunction button:
Just use a template li similar to this
<li id="text1Wrapper">
<span id="text1"
onmouseover="javascript:$('text1Remove').fadeIn();"
onmouseout="javascript:$('text1Remove').fadeOut();"
onclick="javascript:$('text1Content').
replaceWith(
$(document.createElement('input'))
.attr('type','text')
.val($('text1Content').text())
);">
<span id="text1Content">Text Here</span>
<img id="text1Remove"
style="display: none;"
src="./x.jpg" alt="Remove"
onclick="javascript:$(this).parent().remove();"
/>
</span>
</li>
A quick description:
The span mouse over event tells jquery to fade in the remove button (so when you hover, the remove button becomes available).
The span mouse out event tells jquery to fade out the remove button when it's no longer needed (so when you move the mouse off the li, the remove button is no longer visible)
The onclick of the span replaces the span with a text box containing the content of the span. I will leave the "save changes" as an excercise for the reader, since it's essentially the same but in reverse.
Img tag style has display: none to hide it initially. This is essentially the end product of a fadeOut() but without the fade.
The on click event of the remove button gets the parent (the li) and removes it, and all children from the dom.
Note that the events are only put here because it seemed the logical place to explain it. All events in the outer SPAN tag are a useless waste of space, as they will all be overridden when we clone the node in the next section.
Insertion into the page:
All you have to do now is
var cloneLi = $('#text1Wrapper').clone();
cloneLi.attr('id', 'text2Wrapper');
var cloneSpan = cloneLi.children('#text1').attr('id', 'text2');
var cloneContent = cloneSpan.children('#text1Content').attr('id', 'text2Content');
var cloneRemove = cloneSpan.children('#text1Remove').attr('id', 'text2Remove');
You will then need to change the mouseover, mouseout and onclick functions of the outer span using jquery events:
cloneSpan.mouseover(function(e) {
// Insert functionality from template here
});
cloneSpan.mouseout(function(e) {
// Insert functionality from template here
});
cloneSpan.click(function(e) {
// Insert functionality from template here
});
I have a weird kind of problem.I have hover event on DIV .On run time i have to insert some elements in to DIV .Hover event should not happen after inserting div elements.But problem is if i hover on DIV before inserting elements in to the DIV .Hover event is getting carried after inserting the elements.I tried removing attribute its not working for me...
Please let me know If you have a solution
As gmcalab said, please provide some code.
But, a wild shot from here. Since a class is always applied to an element, no matter the state of that element. Maybe you can write a little javascript to change the class of the DIV after you're done.
<div id="yourdiv" class="foo">
You do your things and finally call:
document.getElementById('yourdiv').className = 'bar';
Then in css something like
.bar:hover { background:#EDEDED; or-whatever-styling:you-need;}
But then again, without a codesample it's a hard guess...
Say i have 10 small images that i want to use as tooltips.
Im assinging them all the same class, '.helper'
Im selecting helper, then calling
mouseenter(function() { $(".helper").stop(false,true).fadeIn(); })
I then want a div to popup, containing some text. This works fine if there's only one tooltip on the page, but as soon as there is more than one, whenever i hover over one, they all appear at the same time.
Have i got something fundamentally wrong?
Comments appreciated.
Thx
Use this as the selector inside instead of the .helper selector again:
$('.helper').mouseenter(function() {
// "this" now refers to the image that is being hovered...
$(this).stop(false, true).fadeIn();
});
If you're wondering what the problem was, it was that when you called
$(".helper")
within your function, you were getting all the elements with class helper, in stead of just the single element you wanted.