jQuery not working after executing once - javascript

As you can see here, my little jQuery script isn't working after running twice, and I'm getting a weird error. Do any of you happen to know what's going on/how to fix it? That would be fantastic if you did!
Thank you!
Connor

You are only binding the keypress event on the first .focus element. Once you remove it, it will no longer receive keypress events.
Change this line
$(".focus").keypress(function(event) {
To
$(".focus").live("keypress",function(event) {
jQuery .live() attaches a handler to the event for all elements which match the current selector, now and in the future.
Also, you need to add this after the line above below to prevent unexpected behavior:
if (event.which == '13') {
event.preventDefault(); < stop the enter keypress

You're removing the element for which you're adding the initial keypress event handler. A quick fix would be to take out the event handler into a function and reattach it to your newly added element:
function handleKeyPress(event) {
if (event.which == '13') {
var itemToAdd = $(".focus").val();
if (itemToAdd != ""){
$(this).remove();
$(".active-li").append(itemToAdd);
$("#wrapper ul").append("<li class='active'><input type='text' class='root focus' /></li>");
$(".active-li").removeAttr("class");
$(".active").removeClass("active").addClass("active-li");
$(".focus").keypress(handleKeyPress).focus();
}
}
}
$(".focus").keypress(handleKeyPress);
But I must say, this looks like a very inefficient way to achieve what you're trying to do here... Think of an alternative solution where you don't have to remove your input element (just insert the new <li> before it).

Related

Why is jQuery select event listener triggering multiple times?

Please run this sample in Google Chrome browser.
Stack Snippet
$(function() {
$(":input").select(function() {
$("div").text("Something was selected").show().fadeOut(1000);
alert("Selected");
});
$("button").click(function() {
$(":input").select();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<button>Click To Select</button>
<input type="text" value="Some text">
<div></div>
Here why jQuery select event listener is triggering multiple times? Does anyone know the reason behind this? And is there any workaround solution for this without using timeout?
The $(":input") selector is selecting the button too, so it causes recursion. Either use just $("input"), or $(":input:not(button)").
I noticed when the three events are fired, the first doesn't have originalEvent property, so we definitely can dismiss it, and the second two has very similar (however not identical) timestamp. You can store the last timestamp in some variable and in event listener compare it with the event's timestamp. If the rounded values of these two are the same, you can dismiss this event.
$(function() {
var lastTimeStamp;
$("input").select(function(event) {
if (!event.originalEvent ||
lastTimeStamp === Math.round(event.timeStamp)) return;
lastTimeStamp = Math.round(event.timeStamp);
$("div").text("Something was selected").show().fadeOut(1000);
alert("Selected");
});
$("button").click(function() {
$("input").select();
});
});
See updated JS Fiddle.
It appears the issue is a combination of:
the :input selector gets the input and the button, hence multiple events triggered.
even when using just input as the selector there is some odd event propagation being triggered on related elements which is raising the select event handler multiple times.
To avoid both of the above, use input as the selector and also use preventDefault() in the event handler. stopPropagation() may also be required, depending on your HTML stucture.
$(function() {
$('input').select(function(e) {
// e.stopPropagation(); // optional
e.preventDefault();
$('#message').text("Something was selected").show().fadeOut(1000);
console.log('Selected');
});
$('button').click(function() {
$('input').select();
});
});
Working example
UPDATE: We were all fooled. The select() function needs a prevent default.
Rory McCrossan figured it out. Well done mate.
Incidentally, I'm not sure what the benefit of select() actually is! Something like focus() or on('focus',) might make more sense. Not Sure what the context is however. The below still follows:
Why waste time using generalised tag/type selectors which may change? Use an ID, and pick out only the one you want.
If you want to detect multiple, use a class. If you want to use multiple, but figure out which one you clicked, use a class and an ID. Bind with the class, and identify using $this.attr('id').
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<button>Click To Select</button>
<input type="text" value="Some text" id="pick-me">
<div></div>
$(function() {
$("#pick-me").select(function(event) {
event.preventDefault();
$("div").text("Something was selected").show().fadeOut(1000);
alert("Selected");
});
$("button").click(function() {
$("#pick-me").select();
});
});

How can I return a href link to it's default behavior after using e.preventDefault();?

I updated my code and rephrased my question:
I am trying to create the following condition. When a link with an empty href attribute (for example href="") is clicked, a modal is launched and the default behavior of that link is prevented..
But when the href attribute contains a value (href="www.something.com") I would like for the link to work as it normally does using its default behavior.
For some reason my code isn't working. Any help is appreciated.
// Semicolon (;) to ensure closing of earlier scripting
// Encapsulation
// $ is assigned to jQuery
;(function($) {
// DOM Ready
$(function() {
// Binding a click event
// From jQuery v.1.7.0 use .on() instead of .bind()
$('.launch').bind('click', function(e) {
var attrId = $(this).attr('attrId');
if( $('.launch').attr('href') == '') {
// Prevents the default action to be triggered.
e.preventDefault();
// Triggering bPopup when click event is fired
$('div[attrId="' + attrId+'"]').bPopup({
//position: ['auto', 'auto'], //x, y
appendTo: 'body'
});
} else {
$(this).removeAttribute('attrId');
return true;
}
});
});
})(jQuery);
Your jQuery is... very wrong. $('href').attr('') is getting the empty attribute from an element <href>... Did you mean:
if( $(this).attr('href') == '')
A few things: event is undefined, as your event object is simply called e. Secondly, e.stopPropagation(); will not do what you want. stopPropagation simply prevents parent events from firing (eg: clicking a <td> will also fire click on the containing <tr> unless stopped).
Try just replacing your else statement with
return true;
Also your jQuery is incorrect (as stated in the other answer here).
This answer may help as well:
How to trigger an event after using event.preventDefault()
Good luck!

jquery - using event.stopPropagation()

When the document is ready, I'm fetching some datas from the server through post request and I'm filling it in the HTML as tags by append. When you click that tag, a comment textarea will be displayed. When you click in the document section, the textarea will be closed. The problem here is I can't enter the text in the textarea, when I click inside, it is hiding. I tried using event.stopPropagation() but no use.
Here is my jquery code:
$.post("/person/keywords/get/", function(data){
for(i=0; i<data.length; i++)
{
count = count + 1;
$(".keywords-set").append('<div class="keyword-item"><span class="keyword" id="keyword-'+count+'">'+data[i]+'</span><textarea class="comment" id="comment-'+count+'"></textarea></div>');
}
});
$(".keywords-set").on('click', "[id^=keyword]", function(event) {
event.preventDefault();
i = $(this).attr("id");
i = i.split('-').pop();
$("#comment-"+i).show();
return false;
});
$(".comment").click(function(event) {
event.stopPropagation();
});
$(document).click(function() {
$(".comment").hide();
});
For complete HTML and javascript code, please check here: https://gist.github.com/3024186
It is working in jsfiddle
but not in my localhost. Could you tell the reason, why is it so?
Thanks!
UPDATE
I've also tried this
$(".keywords_set").on('click', ".comment", function(event) {
event.stopPropagation();
});
event.stopPropagation() is not working for HTML elements updated through ajax. But is working for normal(already given) elements.
When doing this:
$(".keywords_set").on('click', ".comment", function(event) {
You must understand that you're catching the event in the element ".keywords_set", and there you will be checking if it bubbled up through ".comment"
This means that any other "click" events set between ".keywords_set" and ".comment" will also activate.
doing stop propagation or returning false will only take affect from the bubbling of ".keywords_set" to the document.
You can do this:
$(document).click(function() {
if($(".comment:hover").length==0){
$(".comment").hide();
}
});
Edit: reply to: "Hey, that code works, I don't know how you are doing it by mentioning .comment.length could you be more descriptive about that?"
When you do any jquery selector, an array is returned. so if you do $(".comment") all html nodes with the class ".comment" will be returned to you in a list [obj1, obj2, ..., objn]
When you do $(".comment:hover") you are asking jquery to select you any element with the class "comment" which also have the mouse currently on top of it. Meaning if the length of the list returned by $(".comment:hover") is bigger than zero, then you caught a bubble from a click in a ".comment".
Although either returning false or stoping propagation should also work. (dunno why in your case it is not working, although i didn't look much at the full code)
Edit 2:
i was lazy to read the full code. but when you are setting the click event for the comment, the comment doesn't exist yet. so the new comment you are adding will not be be caught by your click handler. add it inside the ajax callback and it will work :)
Edit 3: one more thing:
you are not getting side effects because the click even you are re-defining only has the the stop propagation, but you should add the stop propagation before returning false in the
$(".keywords_set").on('click', ".comment", function(event) {
because in practice all other comments you have will be proccessing N times the click event that you are adding to be processed multiple times
Since post method is a asynchronous. You are binding $(".comment") before it exist.
moving
$(".comment").click(function(event) {
event.stopPropagation();
});
after
$(".keywords-set").append('<div class="keyword-item"><span class="keyword" id="keyword-'+count+'">'+data[i]+'</span><textarea class="comment" id="comment-'+count+'"></textarea></div>');
should work.

How to simulate onclickout event with JavaScript

I'd like to somehow be able to define with JavaScript an onclickout event. That is something that happens when the user clicks anywhere else that the element in question.
I tried with onblur but it just don't seem to work :/
Is there any other way?
This uses the jQuery help, but the logic is the same if you prefer without it.
$(document).mouseup(function(event) {
var condition = $(event.target).parents(/* element_in_question */).length;
if (condition == 0) { // 0 means the event is not originated from the element in question
// Do what you need to do
}
}
});
document.getElementById('click').onclick = function(event) {
event.stopPropagation();
}
document.onclick = function() {
alert('click somewhere else');
}
jsFiddle.
This will send a click anywhere (except on #click) to the document.onclick handler, which will fire the alert().
You can set a variable, clickedin, on an element's click handler, and then have a click handler for the document that is checking if clickedin is true, and if it is, handle appropriately.
There may be a better way to accomplish the same end, though.

A quick question about keypress and jQuery

$(document).keydown(function(e) {
Well, that's my code - I was wondering if it is possible to have something like:
$(document).not('#pinkElephant').keydown(function(e) {
(Except, that doesn't work...)
Any Ideas?
Thanks very much!
p.s. All that function has inside it, is a switch statement.
[edit] Hey guys n gals - I cannot return false; because the element I need to type in is an <input> text, so the keyboard still needs to return here.
It's really confusing me :(
Here's an alternate way to do what you require by checking to see that the target element's id isn't pinkElephant. Since this doesn't use the universal selector '*' it should perform better:
$(document).keydown(function(e) {
if (e.target.id !== "pinkElephant") {
alert("I'm not pink!");
}
});
Here's a working example.
(updated from comment)
If you really want to bind a keydown event handler to all nodes in your markup, with the exception of #pinkElephant you need to do it like this:
$(document).find('*').not('#pinkElephant').keydown(function() ..
or short
$(':not(#pinkElephant').keydown(function() ...
which implicitly uses the universal selector *.
Note, that this is never ever any good in terms of performance. I don't know your markup but I hope it's not very crouded using that kind of selector.
update
inspired by a comment, you could also do it like:
$(document).click(function(event) {
if( event.target.id === 'pinkElephant' || $.contains($('#pinkElephant')[0], event.target) )
return false;
// ...
});
Last snippet checks whether #pinkElephant itself or a child node was clicked and prevents the propagation + the default action. This is done by invoking $.contains()help
I assume you don't want elements inside pinkElephant to trigger the keydown.
Place a handler on #pinkElephant that stops propagation of the event.
$('#pinkElephant').bind('keydown',false);
Note that passing false to .bind() requires jQuery 1.4.3 or later.
If you're using an older version, do this:
$('#pinkElephant').bind('keydown',function(){return false;});
Try this instead:
$(':not(#pinkElephant)').keydown(function(e) {
// ...
});

Categories

Resources