Javascript event issue - javascript

I am creating a link that changes text when it is clicked. I want the link text to change back to the original text after all the processing is complete. It was working fine, but the code was spread all over my js file, so I am trying to abstract it into a function. This is the function, textToggle. In the textToggle function we are publishing an event. This event is the one that I cannot get to fire off at the right time.
var textToggle = function(data) {
var original_text = $(data.element).text();
var id = data.id;
var $element = $(data.element);
$element.text(data.replacement_text);
$('body').on(data.event, function(e) {
e.preventDefault();
$this.text(original_text);
});
};
Here is the function that sets up the textToggle. At the end of the function, we are triggering another event `clinical.status'.
$('#clinicalPatients').on('click', '[data-role="auth-process"]', function(e) {
e.preventDefault();
var $this = $(this);
var _id = $target.attr('id');
textToggle({
id: _id,
element: $this,
replacement_text: "Processing...",
event: "clinical.status.finished"
});
$('#clinicalPatients').trigger('clinical.status', [{
id: _id,
target: $target,
action: _type
}]);
});
At the end of clinical.status is when I want to fire the event in toggleText, clinical.status.finished. This is the code for that event.
$('body').trigger('clinical.status.finished', [{
id: originalId
}]);
clinical.status.finished is not getting triggered at the right time. There is no other place in the code that is using this, so it has to be the way that I am setting it up. If I leaved that event out of the toggleText function, and drop it in the function where I set up the toggleText function, then everything works like it is supposed to. By putting on event into a separate function, will this cause issues. Please, any help will be appreciated. Thanks.

Related

How to get current record id in odoo 14 js

I save the current record using
$(".o_form_button_save").click();
Now I want to get the record id of this record. While printing "this", I am not able to find the id.
So for that you have to setup your event handler to call a function when event "click" arise . I think you should extend the FormView to do this in a clean manner.
Here is some pseudo code
FormView.extend({
events: {
'click #target button': 'button_clicked',
},
button_clicked: function(ev) {
//your logic
var field_values = this.get_fields_values();
var id = field_values['id']
});
Hope this helps, please inform me of the result !
For anyone who is looking for solution, try this :
var ExtendFormController = FormController.include({
events: {
"click.get_id_button": "getID",
},
getID: function (ev){
console.log('Button Clicked')
var recordID = Object.values(this.model.localData)[0]["data"]['id']
console.log(recordID)
},
});
reference in comments : https://www.youtube.com/watch?v=lLbjhlXqt98

Plugin opens only after two clicks

I have a custom made tooltip plugin which should be opened by another plugin. But the plugin opens only after the second click and I can't figure out what the problem is.
The whole thing can be tested under. You have to click on the second input Field.
https://codepen.io/magic77/pen/XWMeqrM
$.fn.packstationFinder = function (options) {
var settings = $.extend({
event: 'click.packstationFinder'
}, options);
this.bind(settings.event, function (e) {
if ($postalCode.val() === '') {
$('#packstation-number').tooltip();
return;
}
});
return this;
};
$('[rel~=packstationFinder]').packstationFinder();
I've checked the code in Codepen. The problem here is because in packstationFinder() you call the tooltip() function for the element. But as you can see inside the tooltip() you just bind the click event on the element and not trigger it. So by current code with a first click on the element (#packstation-number) you just bind the click event and really trigger the tooltip only by the second click. You can see that it work as it should by moving out the calling of tooltip() function from packstationFinder() and call it directly as in the code below:
$.fn.packstationFinder = function (options) {
var settings = $.extend({
event: 'click.packstationFinder'
}, options);
return this;
};
$('[rel~=packstationFinder]').packstationFinder();
$('#packstation-number').tooltip();

Prevent duplcate ajaxLoad event calls added with a click event

I am using MVC Razor - The overall goal is to create a "print view" pop-up page.
The print view button is on the parent page, when clicked, an ajax event is fired which will populate an empty div with the contents that are to be included in the print preview:
//from the view
#Ajax.ActionLink("prntPreview", "Display", new { ID = Model.Detail.ID }, new AjaxOptions { UpdateTargetId = "modal" }, new { #class = "btnPreview" })
then, using JavasScript/jQuery I clone the contents of that newly populated div and create a new window with the contents:
//in the scripts file
$('.btnPreview').on('click', function () {
$(document).ajaxStop(function () {
var pageData = $('#modal').html();
setTimeout( //add a slight delay
function () {
PopupPrint(pageData);
}, 300);
});
});
function PopupPrint(data) {
var mywindow = window.open('', '', 'height=500,width=800,resizable,scrollbars');
mywindow.document.write(data);
mywindow.focus();
//do some other stuff here
}
This is where I run into difficulty. The first time I click, everything is working as expected - however, if you do not navigate away from the parent page and try to use the print preview button a second time, the popup will be created twice, then three times etc. with each additional click.
I think that the problem is because each time the .btnPreview is clicked, a new $(document).ajaxStop event is being created, causing the event to fire multiple times.
I have tried to create the ajaxStop as a named function which is declared outside the scope of the click event and then clear it but this produces the same result:
var evnt = "";
$('.btnPreview').on('click', function () {
evnt =
$(document).ajaxStop(function () {
var pageData = $('#modal').html();
setTimeout( //add a slight delay
function () {
PopupPrint(pageData);
evnt = "";
}, 300);
});
});
I also have other ajaxStop events initialised so don't want to completely unbind the ajaxStop event. Is it possible to get the name or something from each ajax event so that I can clear just that event or similar?
You can prevent adding additional triggers by checking with a variable outside of scope like this:
(function() {
var alreadyAdded = false;
$('.btnPreview').on('click', function() {
if (!alreadyAdded) {
$('.eventTrigger').click(function() {
console.log('printing!');
});
alreadyAdded = true;
}
});
})();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="btnPreview">Add Event</button>
<button class="eventTrigger">Trigger</button>
Please note that the variable and function are encapsulated in a self-executing anonymous function and do not pollute global space.
The output of the sample can be seen in the developer console. If you remove the if-check then every click on the "Add Event" button produces an additional print statement on the "Trigger" button each time it is clicked (which is your problem). With the if, there will ever only be one event on the trigger button.
There were 2 issues which I needed to address.
The answer is to unbind the ajax event after it has checked that the request had completed and to unbind and reattach the button click trigger.
This is how I did it:
//in the scripts file
$('.btnPreview').off('click').on('click', function () {
$(document).ajaxComplete(function (e) {
var pageData = $('#modal').html();
setTimeout( //add a slight delay
function () {
PopupPrint(pageData);
}, 300);
$(this).off(e);
});
});
I unbound the click event by adding .off('click') before the .on. this is what stopped it popping up multiple times.
The other issue was that anytime any ajax event completed (triggered by something else) that would also create the popup - to get around that, I added $(this).unbind(e); to the end of the code block which removed the ajaxComplete binding which was being triggered each time any ajax event completed.

Meteor: instantiate a Session without the click event

Using Meteor 0.9+.
Is there a way to instantiate a session as soon as the page renders?
I have a dynamic list of names that display upon clicking a .li element using the click event. This is fine. But I would like the user now to see at least one list, i.e. as if they have already clicked one of the .li elements when they land on the page.
Template.nameList.events({
'click li.title': function(e) {
e.preventDefault();
Session.set('postId', this._id);
var selectedId = Session.get('postId');
}
});
You could use template.created or template.rendered callback:
Template.nameList.rendered = function() {
Session.set('postId', this.data.someId);
};
You could also use IR onBeforeAction callback:
NameListRouter = RouteController.extend({
onBeforeAction: function() {
Session.set('postId', this.params.someId);
};
});

Why does my jQuery event handler fail when attached to multiple elements?

I am using jquery to add mulitple new "addTask" form elements to a "ul" on the page every time a link is clicked.
$('span a').click(function(e){
e.preventDefault();
$('<li>\
<ul>\
<li class="sTitle"><input type="text" class="taskName"></li>\
<li><input type="button" value="saveTask" class="saveTask button"></li>\
</ul>\
</l1>')
.appendTo('#toDoList');
saveTask();
});
These new nested ul elements all have an button with the same class "saveTask". I then have a function that allows you to save a task by clicking on an button with the class "saveTask".
// Save New Task Item
function saveTask() {
$('.saveTask').click(function() {
$this = $(this);
var thisParent = $this.parent().parent()
// Get the value
var task = thisParent.find('input.taskName').val();
// Ajax Call
var data = {
sTitle: task,
iTaskListID: 29
};
$.post('http://localhost:8501/toDoLists/index.cfm/Tasks/save',
data, function(data) {
var newTask = '<a>' + task + '</a>'
thisParent.find('li.sTitle').html(newTask);
});
return false;
});
}
This essentially allows the user to enter some text into a form input, hit save, and then the task gets saved into the database using ajax, and displayed on the page using jQuery.
This works fine when there is only one element on the page with the class "saveTask", but if I have more than 1 form element with the class "saveTask" it stops functioning correctly, as the variable "var task" shows as "undefined" rather than the actual value of the form input.
Don't rely on the .parent() method. Use .closest('form') instead. So the following line:
var thisParent = $this.parent().parent()
should look something like this instead:
var thisParent = $this.closest('form');
EDIT:
Based on the updated information you provided, it looks like when you're trying to register the click event handler it's failing out for some reason. Try this javascript instead as it will make use of the live event so that all the newly added items on the page will automatically have the click event autowired to them.:
$(function(){
$('span a').click(function(e){
e.preventDefault();
$('<li>\
<ul>\
<li class="sTitle"><input type="text" class="taskName"></li>\
<li><input type="button" value="saveTask" class="saveTask button"></li>\
</ul>\
</l1>')
.appendTo('#toDoList');
});
$('.saveTask').live('click', function() {
$this = $(this);
var thisParent = $this.closest('ul');
// Get the value
var task = thisParent.find('input.taskName').val();
// Ajax Call
var data = {
sTitle: task,
iTaskListID: 29
};
$.post('http://localhost:8501/toDoLists/index.cfm/Tasks/save',
data, function(data) {
var newTask = '<a>' + task + '</a>'
thisParent.find('li.sTitle').html(newTask);
});
return false;
});
});
First turn the save task into a function:
(function($){
$.fn.saveTask= function(options){
return this.each(function(){
$this = $(this);
$this.click(function(){
var thisParent = $this.parent().parent()
//get the value
var task = thisParent.find('input.taskName').val();
// Ajax Call
var data = {
sTitle: task,
iTaskListID: 29
};
$.post('http://localhost:8501/toDoLists/index.cfm/Tasks/save', data, function(data){
var newTask = '<a>' + task + '</a>'
thisParent.find('li.sTitle').html(newTask);
});
});
});
return false;
})(jQuery)
When the app starts change the saveTask selector to this:
function saveTask(){
$('.saveTask').saveTask();
}
Then on your add function:
function addTask(){
$newTask = $("<div>Some Task stuff</div>");
$newTask.saveTask();
}
This code is written very quickly and untested but essentially create a jQuery extension that handles for data submission then when ever a task is created apply the save task extension to it.
I think you're looking for the live event.
Also, your code is a little awkward, since the click event is only added when the saveTask() function is called. In fact, the saveTask() function, doesn't actually save anything, it just adds the click event to the elements with the .saveTask class.
What is your HTML structure?
It looks like your code can't find the input.taskName element.
Try setting thisParent to something like $this.closest('form'). (Depending on your HTML)
You could try wrapping your click function in an each()
ie
function saveTask(){
$('.saveTask').each (function () {
$this = $(this);
$this.click(function() {
var thisParent = $this.parent().parent()
//get the value
var task = thisParent.find('input.taskName').val();
// Ajax Call
var data = {
sTitle: task,
iTaskListID: 29
};
$.post('http://localhost:8501/toDoLists/index.cfm/Tasks/save', data, function(data){
var newTask = '<a>' + task + '</a>'
thisParent.find('li.sTitle').html(newTask);
});
return false;
});
})
}
I find this helps sometimes when you have issues with multiple elements having the same class

Categories