Materialize Datepicker Only Update if Done button clicked - javascript

I am using the materializecss Datepicker (https://materializecss.com/pickers.html), and this seems like it should be really straightforward so I'm losing my mind a bit over it. Put simply, I'm trying to trigger an event only if the "Ok" button is clicked, but cannot identify that in the onClose() function provided. If I try to listen for the specific button click, I lose all that comes with the onClose() function (which nicely packages up all the info I need on that event).
Is there any way, with the onClose() function, that I can identify which button caused that onClose() to fire?
I'm admittedly a novice when it comes to javascript and jquery, so any help is appreciated.
HTML
<input type="text" class="datepicker" value="8/4/2018" job="533">
Javascript Code to initialize the datepicker
$(document).ready(function(){
$('.datepicker').datepicker({
"format": "m/d/yyyy",
onClose() {
// only do something if this was fired from the "Done" button
}
})
});
Datepicker modal created
<div class="modal datepicker-modal" id="modal-a5a43c91-2426-5565-c216-1d8ccd0cfc1d" tabindex="0">
<div class="modal-content datepicker-container">
<div class="datepicker-date-display">
<span class="year-text">
</span>
<span class="date-text">
</span>
</div>
<div class="datepicker-calendar-container">
<div class="datepicker-calendar">
</div>
<div class="datepicker-footer">
<button class="btn-flat datepicker-clear waves-effect" style="visibility: hidden;" type="button">
</button>
<div class="confirmation-btns">
<button class="btn-flat datepicker-cancel waves-effect" type="button">
Cancel
</button>
<button class="btn-flat datepicker-done waves-effect" type="button">
Ok
</button>
</div>
</div>
</div>
</div>
</div>

This code below can help you get the right button you want to do some stuff with it. Add 2 listeners to the done and cancel buttons of that opened modal right in onOpen(), and remove listeners onClose().
This will work for you.
<script>
$(document).ready(function() {
function Cancel() {
if(!this.hasEvent) {
this.hasEvent = true;
console.log('Clicked on cancel btn:', this.cancelBtn);
}
}
function Done() {
if(!this.hasEvent) {
this.hasEvent = true;
console.log('Clicked on done btn:', this.doneBtn);
}
}
$('.datepicker').datepicker({
"format": "m/d/yyyy",
onOpen: function(e) {
var that = this;
that.hasEvent = false;
this.cancelBtn.addEventListener('click', Cancel.bind(that))
this.doneBtn.addEventListener('click', Done.bind(that))
},
onClose: function(e) {
var that = this;
this.cancelBtn.removeEventListener('click', Cancel.bind(that))
this.doneBtn.removeEventListener('click', Done.bind(that))
}
})
});
</script>

First you can initialize the Datepicker just by using vanillaJS, then if you check materialize.css file then you'll find the class name of Ok button, that is, .datepicker-done. You can attach addEventListener to this button and call any function you want.
document.addEventListener('DOMContentLoaded', function () {
var elems = document.querySelector('.datepicker');
var instance = M.Datepicker.init(elems);
var doneBtn = document.querySelector('.datepicker-done');
doneBtn.addEventListener('click', callThis); //Attaching a 'click' event to done button
function callThis() {
console.log('Done Button clicked only!'); //Checking the done button click
console.log(elems.getAttribute('job')); //To get the job attribute value
}
});

All of the responses were extremely helpful in figuring this out, thank you to those who contributed!
I don't know if this is the most elegant solution, but it is working for me. I kept the jquery call to initialize all of the datepickers on the page, then added the event listeners with a forEach loop. To get the values I wanted, I had to do that crazy looking series of .parent() calls, but it consistently gets me the right information. Hopefully this helps someone dealing with the same issue in the future (or it can help someone else provide a more effective answer!).
$(document).ready(function(){
$('.datepicker').datepicker({
"format": "m/d/yyyy",
})
});
document.addEventListener('DOMContentLoaded', function () {
var doneBtn = document.querySelectorAll('.datepicker-done');
doneBtn.forEach(function(elem) {
elem.addEventListener('click', callThis)
});
});
function callThis() {
var update = $(this).parent().parent().parent().parent().parent().siblings('input');
// do the thing I want with that input value
};

Related

Javascript event triggering creating multiple button .on('click)

I'm using HTML slim for the code below.
.page
.paper
button.button.js-copier I copy things
- content_for :js_includes do
javascript:
var startingHtml = $('.page').html();
function initializePlugin() {
$('.js-copier').each(function () {
$(this).on('click', function () {
$('.page').append(startingHtml);
$(document).trigger('page-refreshed');
});
});
}
// Run it right away
initializePlugin();
$(document).on('page-refreshed', initializePlugin);
Is there a way to fix the fact that when I click on the "I copy things" button, it creates multiple copies of the button as it is iterating over all the button from the button that was selected?
Also, is there a better way to write this code. All I'm trying to do is duplicate the button anytime I click on any buttons(first and any new button created buttons)
-Anthony
First change this:
$('.js-copier').each(function () {
$(this).on('click', function () {
...
to this:
$('.page').on('click', '.js-copier', function () {
...
Read this to understand https://learn.jquery.com/events/event-delegation/#event-propagation
Then remove the 'page-refreshed' event because you don't need it:
$(document).trigger('page-refreshed');
...
$(document).on('page-refreshed', initializePlugin);
Demo solution:
var startingHtml = $('.page').html();
function initializePlugin() {
$('.page').on('click', '.js-copier', function () {
$('.page').append(startingHtml);
});
}
// Run it right away
initializePlugin();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="page">
<div class="paper">
<button class="button js-copier"> I copy things</button>
</div>
</div>

How to do .click() on added class in JQuery?

I am trying to create a simple edit function on a button. When the user clicks the the Edit Button (containing the following classes btn btn-primary btn-edit change-btn), the text will change to "Save", the readonly attributes will be removed on the input elements, and will have a class btn-success save-btn at the same time removing the edit-btn btn-primary class. So that when the user clicks the button again, it will update and save the data. Although it removes and successfully changes the classes, the save-btn function wont work even with a simple "hello" alert. Here is my code:
$(document).ready( function() {
$('.save-btn').click(function () {
alert('hello');
});
$('.edit-btn').click(function () {
$('.change-btn').removeClass('btn-primary edit-btn').addClass('btn-success save-btn').text('Save');
$('#firstname, #lastname').removeAttr('readonly');
});
});
Is there something wrong of my execution of the javascript/jquery here?
It doesn't work because when you are adding the save-btn click handler that class isn't on the button yet. Try to use delegates.
$(document).ready( function() {
$(document).on('click', '.save-btn', function () {
alert('hello im clicked');
});
$(document).on('click', '.edit-btn', function () {
$('.change-btn').removeClass('btn-primary edit-btn').addClass('btn-success save-btn').text('Save');
$('#firstname, #lastname').removeAttr('readonly');
});
});
You can use the parent of the button instead of the document.

.hasClass on.click not registering for a function call until a second .click..ajax async?

Some checkbox buttons (using bootstrap) trigger an ajax get call on.click, and the activeness of the checked buttons serves a filtering mechanism.
Right now, why is the filtering only working correctly on.click of a second click event (if btn1 is clicked, the ajax runs, with /.one.two.three... and only when btn2 is subsequently clicked does it register as /.two.three.. and only when btn3 is subsequently clicked does it registers as /.three..? http://jsfiddle.net/ENJH9/2/
Alternatively, if the refreshData() call is preceded by removing the class on.click, the data is served correctly, but the view does not reflect the removeClass!? http://jsfiddle.net/ENJH9/3/
All the buttons start with an active class (http://getbootstrap.com/javascript/#buttons):
<div class="btn-group" data-toggle="buttons" id="theBtns">
<label class="btn btn1 active">
<input type="checkbox">one
</label>
<label class="btn btn2 active">
<input type="checkbox">two
</label>
<label class="btn btn3 active">
<input type="checkbox">three
</label>
<label class="btn btn4 active">
<input type="checkbox">four
</label>
</div>
Here's the .get Call that follows the .click event of each button:
function refreshData() {
console.log('started refreshData()')
URL = '';
var filtering = function() {
if($(".btn1").hasClass("active")) { URL += ".one"; }
if($(".btn2").hasClass("active")) { URL += ".two"; }
...
console.log('done filtering: ' + URL);
return URL;
};
$.when( filtering() ).done(function() {
console.log('now data refresh with %s filtering', URL)
$.ajax({
url:"http://localhost:4200/api/v1/data" + URL,
method:'get',
success: foundAllSuccess,
error: foundError
})
});
}
And here's the click event with the removeClass commented out (the buttons still remained visually active and the class still remained in the inspector, but the server accurately filters with this setup):
$( ".btn1" ).click(function() {
// if($(".btn1").hasClass("active")) {$(".btn1").removeClass("active"); console.log('hide btn1 data');}
// else {$(".btn1").addClass("active"); console.log('btn1 data active');}
refreshData();
}); // .btn1.click
Firstly, the main reason you are having a problem is that bootstrap and jQuery don't sit too comfortably together - at least not in this case. jQuery's click event is dispatched so early, it happens before bootstrap has toggled 'active'. Therefore refreshData() operates on the button state before the click, not after the click. This can be overcome with a timeout() to delay execution of refreshData() until after bootstrap has done its thing.
Secondly, you don't need to toggle active as bootstrap looks after that aspect.
Thirdly, the code can be written more efficiently by better leveraging jQuery.
function refreshData(e) {
var URL = $(e.target).closest(".btn-group").find("label").map(function (i) {
if ($(this).hasClass("active")) {
return ['.one', '.two', '.three', '.four'][i];
} else {
return null;
}
}).get().join(''); //.map() returns an array, .join() concatenates the strings in the array into a single string.
alert('now ajax call with filtering :' + URL);
}
$("#theBtns .btn").on('click', function (e) {
setTimeout(function () {
refreshData(e);
}, 0);
});
DEMO
Note that even a delay of zero is enough for our purpose, as code executed from a setTimeout will run in a separate event thread at the earliest opportunity after the current thread has run to completion.
There may be a more "bootstrapy" way to achieve the same end but I'm not about to wade through tons of bootstrap documentation to find out.

Remove Div on link click

I am doing a code in which I want to delete a div when its inner link("Delete") is clicked. I know this question might be repeating and I have tried so many methods but not working. I dont know what's the problem.
Here is my HTML Rendering Code:
<div id="ViewRows">
<br>
<div class="ViewRow"> NOS: FA Comment: finance
<a class="deleteViewRow" href="#">Delete</a>
<br>
</div>
<div class="ViewRow">
NOS: TPA Comment: Assistance
<a class="deleteViewRow" href="#">Delete</a>
<br>
</div>
</div>
Here is my javascript Code for removal of that div.
$("a.deleteViewRow").live("click", function () {
$(this).parents("div.ViewRow:first").remove();
return false;
});
I also tried following javascript:
$("#ViewRows").on("click", "a.deleteViewRow", function () {
$(this).closest("div.ViewRow").andSelf().remove();
return false;
});
I have tried same code on another page. It is working but when I applied the same logic in another page. It's not working. I know you all are right but I dont know whats problem. In firebug it's not even going into the function.
This should work:
$("#ViewRows").on("click", "a.deleteViewRow", function (e) {
// prevent browser from following link
e.preventDefault();
// ".andSelf()" can be skipped - once the parent div is removed, the link gets removed as well
$(this).closest("div.ViewRow").remove();
});
this simple yet efficient code works fine: http://jsfiddle.net/L2CsH/
$("#ViewRows").on("click", "a.deleteViewRow", function () {
$(this).parent().remove();
});
you need to prevent default action of link. event.preventDefault()
$("#ViewRows").on("click", "a.deleteViewRow", function (e) {
e.preventDefault();
$(this).closest("div.ViewRow").remove(); //.andSelf() is not needed here.
//return false;
});
Demo : Remove Div JSFiddle

How to execute .click() code when previous click binding finishes

I am trying to use a Twitter Bootstrap button group with data-toggle="buttons-radio" in my site. Bootstrap markup as follows.
<div class="btn-group program-status" data-toggle="buttons-radio">
<button class="btn">All</button>
<button class="btn">Active</button>
<button class="btn">Planning</button>
<button class="btn">End of Life</button>
<button class="btn">Cancelled</button>
</div>
I need to redirect to the same page with query depending on the pressed button. I tried to use following jQuery code to achieve this.
<script>
var sParamStr = '';
function addToParamStr(str) {
sParamStr += str;
}
function redirectToUpdatedLocation() {
$('.program-status > .btn.active').each(function () {
addToParamStr( '?status=' + $(this).text());
});
console.log(sParamStr);
window.location.href = "program" + sParamStr;
}
$document.ready(function () {
$('.program-status > .btn').on('click', function (e) {
redirectToUpdatedLocation();
});
});
</script>
But the browser always redirects to {site}/program without the query string. By commenting out window.location.href = "program" + sParamStr; line, I managed to observe that second click onwards, sParamStr getting appended properly.
It seems that, my code tries to read the text of the pressed button before, .button('toggle') method form bootstrap.js finished. Code worked as intended when I changed function as follows.
$document.ready(function () {
$( '.program-status > .btn').on('click', function (e) {
$(this).addClass('active');
redirectToUpdatedLocation();
});
});
While this method works for me right now, I would like to know the proper way to achieve this. i.e How to execute my code after previous click binding finishes?
UPDATE:
I found this link in the Twitter Bootstrap forum. Seems it is a known issue.
https://github.com/twitter/bootstrap/issues/2380
I'm not sure what Bootstrap's .toggle is doing exactly, but it seems like it does some sort of animation that completes with the setting of the active class. You can try enqueing your code instead:
$( '.program-status > .btn').on('click', function (e){
$(this).queue(function (next) {
redirectToUpdatedLocation();
next();
});
});
For example, click the div as it is being toggled: http://jsfiddle.net/9HwYy/
It also seems a bit silly to me to update every href instead of just the one you clicked on since you are changing the window location anyway.
try
$('.program-status > .btn.active').each(function(i,v){
v = $(v);
addToParamStr( '?status=' + v.text());
});
since im not sure "this" is working in your case.

Categories