Not clear on this jQuery syntax: return !$() - boolean-logic

I saw this code and I'm not clear what the '!' does in this line of jQuery code on the return on the jQuery object:
$('#remove').click(function() {
return !$('#select2 option:selected').appendTo('#select1');
});
EDIT
What is a good case to do this?

It converts the result of $('#select2 option:selected').appendTo('#select1') to a boolean, and negates it.
However, as the result of appendTo is always a jQuery object, and an object (jQuery or not) is always truthy, the result of !$('#select2 option:selected').appendTo('#select1') is always false.
So what we have is effectively:
$('#remove').click(function() {
$('#select2 option:selected').appendTo('#select1');
return false;
});
Returning false in a jQuery event handler will stop the default event action occuring (e.g. the submission of a form/ navigation of a hyperlink) and stop the event propagating any further up the DOM tree.
So what we have is effectively:
$('#remove').click(function(e) {
$('#select2 option:selected').appendTo('#select1');
e.preventDefault();
e.stopPropagation();
});
Using return false instead of e.preventDefault(); e.stopPropagation(); is OK, but using the return !$(..) as a shortcut for the first example is ridiculous, and there is no need to do it.
Just to reiterate my point, the most important thing to note here is that there is never, ever a good reason/ case to do this.
Links:
Docs for bind() (alias for click())
Docs for preventDefault()
Docs for stopPropagation()

Related

Conditionally adding tags options parameter to select2

I have multiple elements on a page that are triggering a load of select2 to the element. I'm trying to conditionally check if the element has a certain class, and if so add the tag option; otherwise do not. I thought something like this would work, but it's not:
$('.element_to_add_select_two_on').select2({
tags:function(element) {
return (element.className === 'classname_i_am_targeting');
},
});
What am I missing here? I'm subjecting myself to the following buffoonery to get this to target and load:
$('.element_to_add_select_two_on').each((index,element) => {
let showTags = false;
if ($(element).attr('class').split(' ').includes('classname_i_am_targeting')) {
showTags = true;
}
$(element).select2({
tags:showTags,
});
});
There are a few problems with your first attempt. First, you are defining tags as a function when what you want is the result of the function, since tags needs to be defined as a boolean true or false. The other is that inside your .select2() call, you do not have access to the calling element $('.element_to_add_select_two_on') in the way that you think. It isn't an event that you are listening on, it's a function call that wants an object passed with its configuration.
You conveyed that your second method works, but it can be simplified with the jQuery hasClass() function:
$('.element_to_add_select_two_on').each((index, element) => {
$(element).select2({
tags: $(element).hasClass('classname_i_am_targeting'),
});
});
There is a much simpler way to do all of this, however, and it is much more flexible and already built into select2 via the way of data-* attributes (note, you need jQuery > 1.x). You can simply add data-tags="true" to any of your select elements with which you want tags enabled. These will override any configuration options used when initializing select2 as well as any defaults:
<select data-tags="true">
...
</select>

How to send a single request through p:commandButton inside p:dialog? [duplicate]

I have following jQuery code to prevent double clicking a button. It works fine. I am using Page_ClientValidate() to ensure that the double click is prevented only if the page is valid. [If there are validation errors the flag should not be set as there is no postback to server started]
Is there a better method to prevent the second click on the button before the page loads back?
Can we set the flag isOperationInProgress = yesIndicator only if the page is causing a postback to server? Is there a suitable event for it that will be called before the user can click on the button for the second time?
Note: I am looking for a solution that won't require any new API
Note: This question is not a duplicate. Here I am trying to avoid the use of Page_ClientValidate(). Also I am looking for an event where I can move the code so that I need not use Page_ClientValidate()
Note: No ajax involved in my scenario. The ASP.Net form will be submitted to server synchronously. The button click event in javascript is only for preventing double click. The form submission is synchronous using ASP.Net.
Present Code
$(document).ready(function () {
var noIndicator = 'No';
var yesIndicator = 'Yes';
var isOperationInProgress = 'No';
$('.applicationButton').click(function (e) {
// Prevent button from double click
var isPageValid = Page_ClientValidate();
if (isPageValid) {
if (isOperationInProgress == noIndicator) {
isOperationInProgress = yesIndicator;
} else {
e.preventDefault();
}
}
});
});
References:
Validator causes improper behavior for double click check
Whether to use Page_IsValid or Page_ClientValidate() (for Client Side Events)
Note by #Peter Ivan in the above references:
calling Page_ClientValidate() repeatedly may cause the page to be too obtrusive (multiple alerts etc.).
I found this solution that is simple and worked for me:
<form ...>
<input ...>
<button ... onclick="this.disabled=true;this.value='Submitting...'; this.form.submit();">
</form>
This solution was found in:
Original solution
JS provides an easy solution by using the event properties:
$('selector').click(function(event) {
if(!event.detail || event.detail == 1){//activate on first click only to avoid hiding again on multiple clicks
// code here. // It will execute only once on multiple clicks
}
});
disable the button on click, enable it after the operation completes
$(document).ready(function () {
$("#btn").on("click", function() {
$(this).attr("disabled", "disabled");
doWork(); //this method contains your logic
});
});
function doWork() {
alert("doing work");
//actually this function will do something and when processing is done the button is enabled by removing the 'disabled' attribute
//I use setTimeout so you can see the button can only be clicked once, and can't be clicked again while work is being done
setTimeout('$("#btn").removeAttr("disabled")', 1500);
}
working example
I modified the solution by #Kalyani and so far it's been working beautifully!
$('selector').click(function(event) {
if(!event.detail || event.detail == 1){ return true; }
else { return false; }
});
Disable pointer events in the first line of your callback, and then resume them on the last line.
element.on('click', function() {
element.css('pointer-events', 'none');
//do all of your stuff
element.css('pointer-events', 'auto');
};
After hours of searching i fixed it in this way:
old_timestamp = null;
$('#productivity_table').on('click', function(event) {
// code executed at first load
// not working if you press too many clicks, it waits 1 second
if(old_timestamp == null || old_timestamp + 1000 < event.timeStamp)
{
// write the code / slide / fade / whatever
old_timestamp = event.timeStamp;
}
});
you can use jQuery's [one][1] :
.one( events [, data ], handler ) Returns: jQuery
Description: Attach a handler to an event for the elements. The handler is executed at most once per element per event type.
see examples:
using jQuery: https://codepen.io/loicjaouen/pen/RwweLVx
// add an even listener that will run only once
$("#click_here_button").one("click", once_callback);
using count,
clickcount++;
if (clickcount == 1) {}
After coming back again clickcount set to zero.
May be this will help and give the desired functionality :
$('#disable').on('click', function(){
$('#disable').attr("disabled", true);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="disable">Disable Me!</button>
<p>Hello</p>
We can use on and off click for preventing Multiple clicks. i tried it to my application and it's working as expected.
$(document).ready(function () {
$("#disable").on('click', function () {
$(this).off('click');
// enter code here
});
})
This should work for you:
$(document).ready(function () {
$('.applicationButton').click(function (e) {
var btn = $(this),
isPageValid = Page_ClientValidate(); // cache state of page validation
if (!isPageValid) {
// page isn't valid, block form submission
e.preventDefault();
}
// disable the button only if the page is valid.
// when the postback returns, the button will be re-enabled by default
btn.prop('disabled', isPageValid);
return isPageValid;
});
});
Please note that you should also take steps server-side to prevent double-posts as not every visitor to your site will be polite enough to visit it with a browser (let alone a JavaScript-enabled browser).
The absolute best way I've found is to immediately disable the button when clicked:
$('#myButton').click(function() {
$('#myButton').prop('disabled', true);
});
And re-enable it when needed, for example:
validation failed
error while processing the form data by the server, then after an error response using jQuery
Another way to avoid a quick double-click is to use the native JavaScript function ondblclick, but in this case it doesn't work if the submit form works through jQuery.
One way you do this is set a counter and if number exceeds the certain number return false.
easy as this.
var mybutton_counter=0;
$("#mybutton").on('click', function(e){
if (mybutton_counter>0){return false;} //you can set the number to any
//your call
mybutton_counter++; //incremental
});
make sure, if statement is on top of your call.
If you are doing a full round-trip post-back, you can just make the button disappear. If there are validation errors, the button will be visible again upon reload of the page.
First set add a style to your button:
<h:commandButton id="SaveBtn" value="Save"
styleClass="hideOnClick"
actionListener="#{someBean.saveAction()}"/>
Then make it hide when clicked.
$(document).ready(function() {
$(".hideOnClick").click(function(e) {
$(e.toElement).hide();
});
});
Just copy paste this code in your script and edit #button1 with your button id and it will resolve your issue.
<script type="text/javascript">
$(document).ready(function(){
$("#button1").submit(function() {
$(this).submit(function() {
return false;
});
return true;
});
});
</script
Plain JavaScript:
Set an attribute to the element being interacted
Remove the attribute after a timeout
If the element has the attribute, do nothing
const throttleInput = document.querySelector('button');
throttleInput.onclick = function() {
if (!throttleInput.hasAttribute('data-prevent-double-click')) {
throttleInput.setAttribute('data-prevent-double-click', true);
throttleInput.setAttribute('disabled', true);
document.body.append("Foo!");
}
setTimeout(function() {
throttleInput.removeAttribute('disabled');
throttleInput.removeAttribute('data-prevent-double-click');
}, 3000);
}
<button>Click to add "Foo"!</button>
We also set the button to .disabled=true. I added the HTML Command input with type hidden to identify if the transaction has been added by the Computer Server to the Database.
Example HTML and PHP Commands:
<button onclick="myAddFunction(<?php echo $value['patient_id'];?>)" id="addButtonId">ADD</button>
<input type="hidden" id="hasPatientInListParam" value="<?php echo $hasPatientInListParamValue;?>">
Example Javascript Command:
function myAddFunction(patientId) {
document.getElementById("addButtonId").disabled=true;
var hasPatientInList = document.getElementById("hasPatientInListParam").value;
if (hasPatientInList) {
alert("Only one (1) patient in each List.");
return;
}
window.location.href = "webAddress/addTransaction/"+patientId; //reloads page
}
After reloading the page, the computer auto-sets the button to .disabled=false. At present, these actions prevent the multiple clicks problem in our case.
I hope these help you too.
Thank you.
One way I found that works is using bootstrap css to display a modal window with a spinner on it. This way nothing in the background can be clicked. Just need to make sure that you hide the modal window again after your long process completes.
so I found a simple solution, hope this helps.
all I had to do was create a counter = 0, and make the function that runs when clicked only runnable if the counter is = 0, when someone clicks the function the first line in the function sets counter = 1 and this will prevent the user from running the function multiple times when the function is done the last line of the code inside the function sets counter to 0 again
you could use a structure like this, it will execute just once:
document.getElementById('buttonID').addEventListener('click', () => {
...Do things...
},{once:true});

jQuery livequery plug equivalent in jQuery 1.7+

Is there the equivalent of the jQuery livequery plugin for jQuery 1.7+ ?
I'm trying to dynamically bind events, reading the events a DOM element should bind on based on data-* elements.
Test 1
Test 2
.. etc ..
I want to bind all elements with class .js-test but only on the events listed in their data-events attribute.
jQuery.on/live/bind/delegate all require the events to be passed in as params.
This is find for DOM elements that exist on the page when document.ready, however as I update the DOM (AJAX, JS, etc.) I want any new elements with class .js-test to have its events bound as well.
The livequery plugin (which is old, from jQuery 1.3 times) seems to allow this, as it simple requires a selector and a function to run against anything that matches the selector.
As of jQuery 1.7 the on method, supercedes the live method. While it doesn't have an easy method of passing in or matching selectors like you describe, it is possible to accomplish this by passing in the dynamic value of data-events in place of the event type, as long as the data-event value matches that event.
However, since the argument passed into the on method's event parameter -- the first parameter -- is taken from each data-events attribute, from each element in the set of matched elements, we must loop through the collection of matched elements so that we access each elements' individual data-events attribute value separately:
$('.js-test').each(function() {
$(this).on( $(this).attr("data-events"), function() {
// event pulled from data-events attribute
alert("hello - this event was triggered by the " + $(this).attr("data-events") + " action.");
});
});
I want all events to be mapped to the same function, but have different events trigger the function call for different DOM elements.
Since you want to map all of the events to a single function, this solution meets your specific requirements, and solves your problem.
However, should your requirements change and you find you need to map a collection of function events to match each event type, this should get you started:
var eventFnArray = [];
eventFnArray["click"] = function() {
alert("click event fired - do xyz here");
// do xyz
};
eventFnArray["mouseover"] = function() {
alert("mouseover fired - do abc here");
// do abc
};
$('.js-test').each( (function(fn) {
return function() {
$(this).on( $(this).attr("data-events"), function() {
alert("hello - this is the " + $(this).attr("data-events") + " event");
// delegate to the correct event handler based on the event type
fn[ $(this).attr("data-events") ]();
});
}
})(eventFnArray)); // pass function array into closure
UPDATE:
This has been tested and does indeed work for new elements added to the div#container. The problem was in the way the on method functions. The delegating nature of on only works if the parent element is included in the selector, and only if a selector is passed into the second parameter, which filters the target elements by data-events attribute:
HTML:
<div id="container">
Test 1
Test 2
</div>
JavaScript:
$(document).ready(function() {
$('.js-test').each(function() {
var _that = this;
alert($(_that).attr("data-events"));
$(this).parent().on(
$(_that).attr("data-events"),
'.js-test[data-events="'+ $(_that).attr("data-events") +'"]',
function() {
// event pulled from data-events attribute
alert("hello - this event was triggered by the " + $(_that).attr("data-events") + " action.");
}
);
}
);
});
Additionally, use the following jQuery to add an item to the container to test it:
$('#container')
.append("<a href='#' class='js-test' data-events='mouseover'>Test 3</a>");
Try it out:
Here is a jsfiddle that demonstrates the tested and working functionality.

jQuery datepicker won't work on a AJAX added html element

I have a jQuery datepicker function bound to the "birthday" input html element, written in the page header:
<script type="text/javascript">
$(function() {
$( "#birthday" ).datepicker();
});
</script>
Next, I have some AJAX functionality - it adds new input html element to the page. That element is:
<input type="text" id="birthday" value="" class="detail-textbox1" />
Clicking on that birthday element does not pop up the date picker below the text field. I expected this, as the element is added after the page is loaded, thus it isn't in relation with the function provided in the header.
How can I make it work? I tried moving the script from the header to the body, but nothing seems to work. Thanks.
P.S. If I create an input html element with id="birthday" in the page body, everythig works as expected. It appears that only the elements added through AJAX are dysfunctional.
I'm a bit late to the party, but for thoroughness - and with the .live() function being deprecated from jQuery 1.7 onwards - I thought I'd provide an updated solution based on my experiences, and from all the help I got from other answers on StackOverflow!
I had a situation where I needed to add the datepicker functionality to input fields that were being added to the DOM through AJAX calls at random, and I couldn't modify the script making the AJAX calls to attach the datepicker functionality, so I opted for the new shiny .on() function with its delegation features:
// do this once the DOM's available...
$(function(){
// this line will add an event handler to the selected inputs, both
// current and future, whenever they are clicked...
// this is delegation at work, and you can use any containing element
// you like - I just used the "body" tag for convenience...
$("body").on("click", ".my_input_element", function(){
// as an added bonus, if you are afraid of attaching the "datepicker"
// multiple times, you can check for the "hasDatepicker" class...
if (!$(this).hasClass("hasDatepicker"))
{
$(this).datepicker();
$(this).datepicker("show");
}
});
});
I hope this helps someone, and thanks for all the answers so far that led me to this solution that worked for me! :)
You need to use .live() so that any newly added elements have the event handler attached: http://api.jquery.com/live/
$('#birthday').bind('load', function() {
$(this).datepicker();
});
EDIT
.live() documentation states, that it is a bit out of date. With new versions of jquery (1.7+) use .on().
Boris, JK: This was super helpful for me. I have also found that you can use the following for AJAX html if you want to use Datepicker's date range selection:
$('#groundtransporation').live('focus', function() {
var gt = $( "#rentalPickUp, #rentalDropOff" ).datepicker({
defaultDate: "+1w",
changeMonth: true,
numberOfMonths: 2,
onSelect: function( selectedDate ) {
var option = this.id == "rentalPickUp" ? "minDate" : "maxDate",
instance = $( this ).data( "datepicker" ),
date = $.datepicker.parseDate(
instance.settings.dateFormat ||
$.datepicker._defaults.dateFormat,
selectedDate, instance.settings );
gt.not( this ).datepicker( "option", option, date );
}
});
});
I got another case.
My script is copying last table elements including datepicker.
The jquery will not working because the copied element has mark that it "hasDatepicker".
To activate datepicker in new element, remove that class name and the initiate it, like this.
$("#yournewelementid").attr("class","your-class-name");
$("#yournewelementid").datepicker();
your issue is always happens when elements don't exist when you try to initialize it.
When you use $(function(){/** some code **/}); elements must exsit on the document, it means that has to be on the html so you could can create a function to initialize the component or initialize it on the success event after been add it to the document.
Is important to first add the external html load in the ajax request to the document before you try to initialize it or it won't be initialize at all.
Example:
$.ajax({
url:"ajax_html.html",
dataType:"html"
}).done(function(html){
$("#selector").html(html)
init();
});
function init(){
$(".birthday").datepicker({});
}
You could initialize the date picker for the newly added element within your ajax success callback:
$.ajax({
...
success: function(response) {
if(response.success) {
$(body).append(response.html);
$("#birthday").datepicker();
}
}
});

How to do callback + update div tag in javascript

I have an ASP.NET MVC application with pages where the content is loaded into divs from client via JavaScript/jQuery/JSON. The loaded content contains a-tags with references to a function that updates server side values, then redirects to reload of entire page even though.
I wish to replace the a-tags with 'something' to still call a server-side function, then reload the div only.
What is the 'right' way of doing this?
All comments welcome.
This is as far as I got so far. getResponseCell() returns a td-tag filled with a-tag.
I've mangled Glens suggestion into the .click() addition, but it just calls the onClickedEvent...
Code sample:
onClickedEvent=function()
{
return false;
}
getResponseCell=function(label, action, eventId)
{
tmpSubSubCell=document.createElement("td");
link = document.createElement("A");
link.appendChild( document.createTextNode( label));
link.setAttribute("href", "/EventResponse/"+ action + "/" + eventId);
//link.setAttribute("href", "#divContentsEventList");
//link.setAttribute("onclick", "onClickedEvent(); return false;");
link.setAttribute("className", "eventResponseLink");
link.click(onClickedEvent());
// link=jQuery("<A>Kommer<A/>").attr("href", "/EventResponse/"+ action + "/" + eventId).addClass("eventResponseLink");
// link.appendTo(tmpSubSubCell);
tmpSubSubCell.appendChild(link);
return tmpSubSubCell;
}
And the solution that worked for me looks like this:
onClickedEvent=function(event, actionLink)
{
event.preventDefault();
$("eventListDisplay").load(actionLink);
refreshEventList();
return false;
}
getResponseCell=function(label, action, eventId)
{
tmpSubSubCell=document.createElement("td");
link = document.createElement("A");
link.setAttribute("id",action + eventId);
link.appendChild( document.createTextNode( label));
actionLink = "/EventResponse/"+ action + "/" + eventId;
link.setAttribute("href", actionLink);
className = "eventResponseLink"+ action + eventId;
link.setAttribute("className", className);
$('a.'+className).live('click', function (event)
{
onClickedEvent(event,$(this).attr('href'));
});
tmpSubSubCell.appendChild(link);
return tmpSubSubCell;
}
Without really seeing more information.....
If you're a's are being added to the DOM after the initial page load, you cannot use the usual click() or bind() methods in jQuery; this is because these methods only bind the events to those elements that are registered in the DOM at the time the methods are called. live() on the other hand, will register the event for all current, and future elements (using the event bubbling mechanism in Javascript).
$(document).ready(function () {
$('a.eventResponseLink').live('click', function (event) {
var self = $(this);
self.closest('div').load('/callYourServerSideFunction.asp?clickedHref=' + self.attr('href'));
event.preventDefault();
});
});
We're using event.preventDefault() to prevent the default action of the a-tag being executed; e.g. reloading or changing page.
Edit: The issue won't be caused by that. That's the power of jQuery; being able to bind the same event to multiple elements. Check your HTML; maybe you're missing a closing </a> somewhere? Maybe your binding the event in a location that gets called multiple times? Each time .live() gets called, it will add ANOTHER event handler to all matched elements. It only needs to be bound once on page load.
jQuery provides loads of way for you to select the elements; check out the list. Looking at your link variable, it looks like all your links have a href starting with /EventResponse/; so you can use $('a[href^=/EventResponse/]') as the selector instead.
We need code to give you a proper answer, but the following code will catch the click of an a-tag, and reload the div that it's inside:
$(document).ready(function() {
$("a").click(function() {
//call server-side function
var parentDiv = $(this).parents("div:first");
$(parentDiv).load("getContentOfThisDiv.asp?id=" + $(parentDiv).attr("id"));
});
});
In the above code, when a link is clicked, the div that this the link is inside will be loaded with the response of the call to the asp file. The id of the div is sent to the file as a parameter.