miss button click event when button is added dynamically - javascript

have the following headache: there is a knockout viewmodel with initialize function
initialize: function () {
// bla bla
this.toolbar.addButton({ text: 'View All', label_key: 'view_all', click: 'viewAll' });
},
and some handler-functions
viewAll: function () {
this.toolbar.removeButton('#view_all');
this.toolbar.addButton({ text: 'View Users Projects', label_key: 'view_users_projects', click: 'viewUsersProjects' });
//some things to do
});
viewUsersProjects: function () {
localstorage.clear()// I need this here but this function doesn't work
this.toolbar.removeButton('#view_users_projects');
});
}
So, the problem is following - when button viewAll is clicked - the same function works BUT if button viewUsersProjects is clicked viewUsersProjects function doesn't work, it moves straight off to initialize, I even can delete viewUsersProjects function and nothing is changed but view_users_projects button is disappeared somehow... What I need actually to clear localstorage when view_users_projects button is clicked. Appreciate your answers.
the prototype functions for add/remove buttons:
_.extend(Toolbar.prototype, {
addButton: function (options) {
$('.navbar ul.nav:eq(0)').append(
'<li class="kkvw-button" id="' + options.label_key + '">' +
'<a data-bind="click: ' + options.click + '" href="">' +
'</a>' +
'</li>'
);
return this;
},
removeButton: function (text) {
$(text).remove();
},
});

Related

Summernote add text from dropdown at the end

I have a custom button in summernote that has a dropdown of items "one", "two", "three" when I click on for example the text "one" the text is added at the start which is fine. But then when I click on "two" afterwards the text is also added at the start which produces this result.
twoone
I would like to have the following result
one
two
Update when I use this line
context.invoke("editor.pasteHTML", context.modules.editor.$editable[0].innerText ? "<br>" + $(this).html() : $(this).html() );
instead of
context.invoke('editor.insertText', $(this).html());
I get the following result wihch is better but the order is still incorrect
two
one
Here you can fiddle with my code
https://stackblitz.com/edit/angular-summernote-demo-n7xn2n?file=src%2Fapp%2Fapp.component.ts
Otherwise here is my code for the button that inserts the text
function customButtonGenerator(lstQuoteComments, title) {
return function (context) {
const ui = ($ as any).summernote.ui;
var i;
var listHtml = '';
for (i = 0; i < lstQuoteComments.length; i++) {
listHtml += '<li>' + lstQuoteComments[i] + '</li>';
}
const button = ui.buttonGroup([
ui.button({
className: 'dropdown-toggle',
contents:
'<i class="fa fa-comments text-primary"/><span id="summernot-caret" class="caret text-primary"></span>',
//tooltip: 'Comments', //Not working when howver over it top is not defined
data: {
toggle: 'dropdown',
},
}),
ui.dropdown({
className: 'drop-default summernote-list',
contents:
'<div id="container-comentario"><div id="dialog" title="' +
title +
'" ><h1 class="header-comentario">' +
title +
'</h1><ul id="summernote-list"><ul>' +
listHtml +
'</ul></div></div>',
callback: function ($dropdown) {
$dropdown.find('li').each(function () {
$(this).click(function () {
context.invoke('editor.insertText', $(this).html());
});
});
},
}),
]);
return button.render();
};
}
Thank you for your help.
As far as I can see, these answer don't quite get the question right.
You should append the button content to the existing content like this:
Example blitz - https://stackblitz.com/edit/angular-summernote-demo-ycvten?file=src%2Fapp%2Fapp.component.ts
Main code snippet:
...
callback: function ($dropdown) {
$dropdown.find('li').each(function () {
$(this).click(function () {
let newHtml = context.modules.editor.$editable[0].innerHTML
if (newHtml !== '') {
newHtml += '<br>'
}
newHtml += $(this).html()
context.invoke('code', newHtml)
})
})
}
...
I'll have a look if there is a way to keep track of the current cursor position, I think there must be. I'l update if that's possible, rather than just adding to the end.
You can try to replace this line in customButtonGenerator function:
context.invoke('editor.insertText', $(this).html());
With:
context.invoke('editor.pasteHTML', $(this).html());
OR
context.invoke('editor.pasteHTML', '<div>' + $(this).html() + '</div>');
Replace this line
context.invoke('editor.insertText', $(this).html());
with
context.invoke("code", context.modules.editor.$editable[0].innerHTML + '<br>' + $(this).html());
This will solve the issue.

Bootstrap table buttons firing onlick multiple times

Global.Js file
function operativeEvents() {
$('.tableButton').off().click(function (e) {
var $this = $(this),
tableId = $this.parents('table').attr('id'),
$table = $('#' + tableId),
index = $this.closest('tr').index(),
data = $table.bootstrapTable('getData');
//global variable to retrieve the data of the current row
window.currentRow = data[index];
buttonActions($this.attr('id'), $this.data('myid'));
});
The operativeEvents function binds when the bootstrap table body is rendered.
This is done with the onPostBody event. https://bootstrap-table.com/docs/api/events/
Local.cshtml
This contains a switch case to handle the button clicks
function buttonActions(id) {
switch (id) {
case 'bookButton':
bookMatch(currentRow.id);
break;
}
}
function bookMatch(currentRow) {
bootbox.dialog({
message: '<h4 class="text-center">Are you sure?</h4>',
buttons: {
cancel: {
label: 'Cancel',
className: "btn btn-danger"
},
confirm: {
label: 'Ok',
className: 'btn btn-success',
callback: function () {
alert('testing ' + currentRow);
return;
updateCall({
url: "/api/MatchesApi/BookMatch/" + currentRow.id,
tableRefresh: true,
serverSideMessaging: true,
});
}
}
},
});
}
For some reason when I click the button it opens the Bootbox.dialog multiple times.
I have tried using the off() method and also played around with event bubbling. Can someone please give me some advice? Thanks :)

Custom button for each event in ui-calendar fullcalendar

When you click on each button, it just calls a modal so you can edit or delete an event. I am having trouble passing in the event from the view.
This is in the controller:
$scope.eventRender = function (event, element, view) {
element.append(calendarEventService.formatWeekEvent(event));
$compile(element)($scope);
};
$scope.uiConfig = {
calendar:{
...,
eventRender: $scope.eventRender
}
};
This is the service the eventRender is calling:
app.service('calendarEventService', function () {
this.formatWeekEvent = function (event) {
return <a whole bunch of html to render the button> +
'<a ng-click="editActivityModal(event, $event)">Edit</a>' +
'<a ng-click="deleteActivityModal(event, $event)">Delete</a>'
};
});
The event itself gets passed into the service, but when the editActivityModal or deleteActivityModal gets called, the event is not being passed and I only get undefined, however, the $event is being passed (this is just to use the preventDefault and stopPropagation stuff)
Found a solution to this as follows:
In the returning html add a css class to bind a click event in the eventRender function:
app.service('calendarEventService', function () {
this.formatWeekEvent = function (event) {
return <a whole bunch of html to render the button> +
'<a class="editEvent">Edit</a>' +
'<a class="deleteEvent">Delete</a>';
};
});
In the eventRender function:
$scope.eventRender = function (event, element, view) {
element.append(calendarEventService.formatWeekEvent(event));
element.find(".editEvent").bind('click', function () {
$scope.editEvent(event);
return false;
});
element.find(".deleteEvent").bind('click', function () {
$scope.deleteEvent(event);
return false;
});
$compile(element)($scope);
};

Jquery Ajax : auto-refresh

In my Ajax success function i created button and on click i am calling a function.
The problem:
The page reloads based on the timer in set interval but when i click the button it will call the function based on the number of times the page reloaded.
For example:
If page reloads 5 times and then i call a function on clicking that button-it will call that function 5 times.
if it reloads 10 times then function call is for 10 times.
Please advice what i am doing wrong?
Here is the code:
$(document).ready(
function() {
setInterval(function() {
$.ajax({
type: 'GET',
url: 'Refresh',
success: function(data) {
var trHTML = '';
$.each(data, function(i, item) {
var buttonVar = ('<button id="bt21" class="btn121">' + "STOP" + '</button>');
trHTML += '<tr><td>'+buttonVar+'</td></tr>'
});
$('#test1').append(trHTML);
$(document).on('click','#bt21', function(event) {
var rownum1 = $(this).closest('tr').index();
stopTest(data[rownum1].process_id);
});
}
});
}, 5000);
});
You have set the AJAX call to be made every 5 seconds. Each time time this function is called, you are also attaching the click event on the button you append. So there will be multiple event handlers attached to the same element. You need to clear any existing event handlers on that element before you attach another if you want to stick to your current code. Here's how to do it:
$(document).off('click', '#bt21');
$(document).on('click','#bt21', function(event) {
var rownum1 = $(this).closest('tr').index();
stopTest(data[rownum1].process_id);
});
Each time the page is refreshed from your ajax call a new event listener is bound to the button in memory. You need to clear the event listeners then create a new one.
$(some element).unbind().on(...........);
I always unbind event listeners created in an ajax call if anything to keep the browser memory from being over loaded or to prevent the issue you are having.
$(document).ready(
function() {
setInterval(function() {
$.ajax({
type: 'GET',
url: 'Refresh',
success: function(data) {
var trHTML = '';
$.each(data, function(i, item) {
var buttonVar = ('<button id="bt21" class="btn121">' + "STOP" + '</button>');
trHTML += '<tr><td>'+buttonVar+'</td></tr>'
});
$('#test1').append(trHTML);
$(document).unbind().on('click','#bt21', function(event) {
var rownum1 = $(this).closest('tr').index();
stopTest(data[rownum1].process_id);
});
}
});
}, 5000);
});
First you are appending buttons on refresh that have the same id attribute so that's going to cause you issues at some point.
What you need to do is move your click event outside of the interval function and ajax callback. Add the process id to the button in a data attribute and delegate a click event to the button so it will work even though the elements haven't been created in the DOM when the page loads.
Here's an example although I'm not sure if it works (can't really simulate this easily):
$(document).ready(function() {
setInterval(function() {
$.ajax({
type: 'GET',
url: 'Refresh',
success: function(data) {
var trHTML = '';
$.each(data, function(i, item) {
var buttonVar = '<button class="btn" data-process-id="' + item.process_id + '">' + "STOP" + '</button>');
trHTML += '<tr><td>'+buttonVar+'</td></tr>'
});
$('#test1').append(trHTML);
}
});
}, 5000);
$('#test1').on('click', '.btn', function() {
stopTest( $(this).data('process_id') );
});
});

Prevent content to be duplicated when clicking multiple times with Jquery/javascript

This is an extension to this question How to get value from nested HTML tag with Jquery/Javascript
When I execute the following script after the first time, the <h2>-tags get duplicated multiple, though I only want the three values displayed...
so my question is, what is going wrong here?
$(document).ready(function () {
$('.submit').on('click', function () {
$('#newLoanDiv').append('<div id="test"></div>');
$('.results-page').contents().appendTo($('#test'));
setTimeout( function(){
$('.submit').removeAttr('disabled');
$('.sums').find('dl').each(function () {
$('<h2 class="value">' + $(this).find('dd').text() + '</h2>').insertBefore('#test');
});
}, 100 );
});
});
Any help is appreciated...
Try the following. Try $('#test').empty(); to clear data of the #test on every click.
$('.submit').on('click', function () {
$('#newLoanDiv').append('<div id="test"></div>');
$('#test').empty();
$('.results-page').contents().appendTo($('#test'));
setTimeout( function(){
$('.submit').removeAttr('disabled');
$('.sums').find('dl').each(function () {
$('<h2 class="value">' + $(this).find('dd').text() + '</h2>').insertBefore('#test');
});
}, 100 );
});

Categories