.on jquery only working on first element [duplicate] - javascript

This question already has answers here:
Events triggered by dynamically generated element are not captured by event handler
(5 answers)
Closed 8 years ago.
I am currently using the following code to tie in an event that limits input into a dynamicly created set of text boxes.
function createSomeTextBoxes() {
//code here to add text boxes
$('.PointerSPSLText').on('keyup', function() { charaterCount( $(this).attr('id'), 30 ) });
$('.SPSLText').on('keyup', function() { charaterCount( $(this).attr('id'), 30 ) });
}
The problem I am having is that these events only get tied to the first element of the class it finds, since there can be more than one of each, that is a problem. I used to use the .live event for this and I could declare it once when the DOM was loaded and jquery took care of the rest. Is there a way to mimic the .live event or what is the best way to achieve the results I need?

For dynamical created element, I think you must use event delegation like:
$("body").on("keyup", ".PointerSPSLText", function() {
charaterCount( $(this).attr('id'), 30 )
});
$("body").on("keyup", ".SPSLText", function() {
charaterCount( $(this).attr('id'), 30 )
});
More info at about on(): http://api.jquery.com/on/

Yeah right live is deprecated now,
You can use dynamic on version like this,
$('#some_static_parent_that_holds_PointerSPSLText').on('keyup','.PointerSPSLText', function(){});

New versions of jQuery use the on event instead of live to bind event handlers to dynamic elements.
function createSomeTextBoxes() {
//code here to add text boxes
$(document).on('keyup', '.PointerSPSLText', function() {
charaterCount( $(this).attr('id'), 30 )
});
$(document).on('keyup','.SPSLText', function() {
charaterCount( $(this).attr('id'), 30 )
});
}
Notice that the event handler is bound to the document instead of a selector for the elements. The selector is specified as the second argument to the on function. When an event is triggered it propagates to the document which then inspects if the target matches the selector supplied as the second argument. You can bind to a static parent instead of the document for better performance.

If you only want to limit the character length, why not use the "maxlength" attribute of the input/textarea element, provided you have access to the function that generates the dynamic elements?
<input type="text" name="usrname" maxlength="30">
<textarea maxlength="30">Enter text here...</textarea>

Related

How to undetect/ignore javascript events in a certain html element?

I have this line of code $('#tbl-purchase-list').on( 'keyup change', 'input[type="text"]' that detects the input of all input[type="text"] field. However, I have an input field that I dont want to be detected when inputting a text on the keyboard or make any changes on it.<input type="text" class="form-control purchase-freight-charge" id="purchase-freight-charge" value="" />. Is there a way in javascript that ignores certain events for a certain element? Something like this $("#purchase-freight-charge").ignoreEvents();? Please help. Thanks a lot.
Ofcourse there is a :not() Pseudo selector:
$('#tbl-purchase-list').on('keyup change',
'input[type="text"]:not(#purchase-freight-charge)',
...);
It will not add the target element in the matched set of selectors. So, there won't be any event for that element which is inside :not().
Event this can also be done:
$('#tbl-purchase-list').on('keyup change', 'input[type="text"]',function(ev){
if(this.id === "purchase-freight-charge"){
this.value = "";
}
});
You can use jQuery's event.stopImmediatePropagation():
$("#purchase-freight-charge").on('keyup change', function( event ) {
event.stopImmediatePropagation();
});
// Future event bindings won't be executed for #purchase-freight-charge
// ...

jquery bind event to new elements [duplicate]

This question already has answers here:
Jquery how to bind click event on dynamically created elements?
(2 answers)
Closed 8 years ago.
JAVA SCRIPT
$(document).ready(function() {
$(".group").click(groupFile);
function groupFile(){
alert('clicked!');
}
});
function insert()
{
$("body").append("<div class='group' ></div>");
}
HTML
<div class='group' >
</div>
<input type="button" value="insertNewElement" id="insert" onclick="insert()"/>
when page loaded,on click div.group works well and fire groupFile and alert to me.
but when inserted the new div.group.onclick div.group function groupFile does not worked?
please help me
You can use jQuery on() method to delegate the events to a static ancestor as shown below:
$(document).ready(function() {
$(document).on("click",".group",groupFile);
function groupFile(){
alert('clicked!');
}
});
read more about event delegation
For dynamic elements you need to bind to event on the body:
$("body").on("click", ".group", function(e){
alert('clicked');
});
You should delegate event to BODY (or document or 'usually' better to the closest static parent element) level. Using .on(), pass selector param as it:
$('body').on('click', 'div.group', function(){
//...
});
See explanation

Using .on() and targeting elements with a specific attribute

I understand you can use .on() to attach a single click event to an element and then specify which child elements receive the click. So, for example:
$(this.el).on("click", "span", function () {
alert("Bloop!");
});
I need to be a bit more specific and target selectors with a particular attribute, like this:
$(this.el).on("click", "span[data-placeholder]", function () {
alert("Bloop!");
});
That doesn't seem to work, though. As soon as I add the attribute it stops working. No errors, just doesn't seem to find the elements.
Is that the expected behavior? Is there a way around it?
CLARITY
$(this.el) is just a div that contains a number of elements, some of which are <span data-placeholder="First Name"></span> tags. There could be dozens of those <span> tags and I didn't want that many event listeners, so I thought I'd use .on() to add the click to the parent container.
Here's JSFiddle showing your example working, with both existing <span>s and with newly created ones.
Just to be clear, this will work with your event delegation:
var span = $('<span>Test</span>');
span.attr('data-placeholder', 'test'); // declare as an attribute
$(this.el).append(span);
span.click();
This will not:
var span = $('<span>Test</span>');
span.data('placeholder', 'test'); // declare with .data()
$(this.el).append(span);
span.click();
jQuery's .data() method will read properties from data attributes if declared, but does not store them as attributes on the element when adding data.
Here's another JSFiddle.
try
$("span[data-placeholder]", this.el).on("click", function () {
alert("Bloop!");
});
You can choose to filter your spans
$('span', this.el).filter(function() {
return $(this).hasAttr('data-placeholder');
}).on('click', function() {
//This is for all the spans having data-placeholder
//...
});
Or if the placeholder is set via data api:
$(this.el).filter(function() {
return $(this).data('placeholder') != 'undefined';
}).on('click', function() {
//This is for all the spans having data-placeholder
//...
});
This functions above select those elements specifically, if event delegation on the OP is needed, then you can do the following:
$('span', this.el).on('click', 'span', function() {
if($(this).data('placeholder') != 'undefined') {
alert('bloop');
}
});
add a id to your span and pin point it using # tag

Retrieving previously focused element

I would like to find out, in Javascript, which previous element had focus as opposed to the current focus. I've been looking through the DOM and haven't found what I need, yet. Is there a way to do this any help would be much appreciated
Each time an element is focused, you'd have to store which one it was. Then when another element is focused, you could retrieve the variable for the previous focused element.
So basically, your single focus handler would do 2 things:
Check if previousFocus is defined. If it is, retrieve it.
Set previousFocus to the currently focused element.
Here is a quick demo with jQuery (you can use raw JS too... just fewer lines w jQuery, so it's easier to understand imo):
// create an anonymous function that we call immediately
// this will hold our previous focus variable, so we don't
// clutter the global scope
(function() {
// the variable to hold the previously focused element
var prevFocus;
// our single focus event handler
$("input").focus(function() {
// let's check if the previous focus has already been defined
if (typeof prevFocus !== "undefined") {
// we do something with the previously focused element
$("#prev").html(prevFocus.val());
}
// AFTER we check upon the previously focused element
// we (re)define the previously focused element
// for use in the next focus event
prevFocus = $(this);
});
})();
working jsFiddle
Just found this question while solving the exact same problem and realised it was so old the jQuery world has moved on a bit :)
This should provide a more effective version of Peter Ajtais code, as it will use only a single delegated event handler (not one per input element).
// prime with empty jQuery object
window.prevFocus = $();
// Catch any bubbling focusin events (focus does not bubble)
$(document).on('focusin', ':input', function () {
// Test: Show the previous value/text so we know it works!
$("#prev").html(prevFocus.val() || prevFocus.text());
// Save the previously clicked value for later
window.prevFocus = $(this);
});
JSFiddle: http://jsfiddle.net/TrueBlueAussie/EzPfK/80/
Notes:
Uses $() to create an empty jQuery object (allows it to be used immediately).
As this one uses the jQuery :input selector it works with select & button elements as well as inputs.
It does not need a DOM ready handler as document is always present.
As the previously focused control is required "elsehere" is is simply stored on window for global use, so it does not need an IIFE function wrapper.
Well depending on what else your page is doing, it could be tricky, but for starters you could have a "blur" event handler attached to the <body> element that just stashes the event target.
To me this seems a slight improvement on Gone Coding's answer:
window.currFocus = document;
// Catch focusin
$(window).on( 'focusin', function () {
window.prevFocus = window.currFocus;
console.log( '£ prevFocus set to:');
console.log( window.currFocus );
window.currFocus = document.activeElement;
});
... there's no stipulation in the question that we're talking exclusively about INPUTs here: it says "previous elements". The above code would also include recording focus of things like BUTTONs, or anything capable of getting focus.
document.getElementById('message-text-area').addEventListener('focus',
event => console.log('FOCUS!')
);
event.relatedTarget has all the data about the previously focused element.
See also https://developer.mozilla.org/en-US/docs/Web/API/Event/Comparison_of_Event_Targets
Here is a slightly different approach which watches both focusin and focusout, in this case to prevent focus to a class of inputs:
<input type="text" name="xyz" value="abc" readonly class="nofocus">
<script>
$(function() {
var leaving = $(document);
$(document).on('focusout', function(e) {
leaving = e.target;
});
$( '.nofocus' ).on('focusin', function(e) {
leaving.focus();
});
$( '.nofocus' ).attr('tabIndex', -1);
});
</script>
Setting tabIndex prevents keyboard users from "getting stuck".

Issue with selectors & .html() in jquery?

The function associated with the selector stops working when I replace it's contents using .html(). Since I cannot post my original code I've created an example to show what I mean...
Jquery
$(document).ready(function () {
$("#pg_display span").click(function () {
var pageno = $(this).attr("id");
alert(pageno);
var data = "<span id='page1'>1</span><span id='page2'> 2</span><span id='page3'> 3</span>";
$("#pg_display").html(data);
});
});
HTML
<div id="pg_display">
<span id="page1">1</span>
<span id="page2">2</span>
<span id="page3">3</span>
</div>
Is there any way to fix this??...Thanks
Not sure I understand you completely, but if you're asking why .click() functions aren't working on spans that are added later, you'll need to use .live(),
$("#someSelector span").live("click", function(){
# do stuff to spans currently existing
# and those that will exist in the future
});
This will add functionality to any element currently on the page, and any element that is later created. It keeps you have having to re-attach handlers when new elements are created.
You have to re-bind the event after you replace the HTML, because the original DOM element will have disappeared. To allow this, you have to create a named function instead of an anonymous function:
function pgClick() {
var pageno = $(this).attr("id");
alert(pageno);
var data="<span id='page1'>1</span><span id='page2'> 2</span><span id='page3'> 3</span>";
$("#pg_display").html(data);
$("#pg_display span").click(pgClick);
}
$(document).ready(function(){
$("#pg_display span").click(pgClick);
});
That's to be expected, since the DOM elements that had your click handler attached have been replaced with new ones.
The easiest remedy is to use 1.3's new "live" events.
In your situation, you can use 'Event delegation' concept and get it to work.
Event delegation uses the fact that an event generated on a element will keep bubbling up to its parent unless there are no more parents. So instead of binding click event to span, you will find the click event on your #pg_display div.
$(document).ready(
function()
{
$("#pg_display").click(
function(ev)
{
//As we are binding click event to the DIV, we need to find out the
//'target' which was clicked.
var target = $(ev.target);
//If it's not span, don't do anything.
if(!target.is('span'))
return;
alert('page #' + ev.target.id);
var data="<span id='page1'>1</span><span id='page2'>2</span><span id='page3'>3</span>";
$("#pg_display").html(data);
}
);
}
);
Working demo: http://jsbin.com/imuye
Code: http://jsbin.com/imuye/edit
The above code has additional advantage that instead of binding 3 event handlers, it only binds one.
Use the $("#pg_display span").live('click', function....) method instead of .click. Live (available in JQuery 1.3.2) will bind to existing and FUTURE matches whereas the click (as well as .bind) function is only being bound to existing objects and not any new ones. You'll also need (maybe?) to separate the data from the function or you will always add new span tags on each click.
http://docs.jquery.com/Events/live#typefn

Categories

Resources