can't get value of dynamic remove/edit HTML table using javascript - javascript

I'm trying to write a piece of code that can handle remove or editing of dynamic HTML table. I've googled and stackoverflow this problem, I see many samples but none of them worked properly.
Here is my code:
server.js
router.get('/bookShow', (req, res) => {
bookModel.find({isDeleted : false}).sort('-pageCount').exec((err, data) => {
if (data) {
res.send(data);
}
});
});
BookModel in Database:
bookShow.html
<script>
$(document).ready(() => {
$.getJSON('/bookShow', (json) => {
var tr;
for (var i = 0; i < json.length; i++) {
tr = $('<tr/>');
tr.append("<td>" + "<button class='deleteButton'>" + "<i class='material-icons'>delete</i></button>" + "</td>");
tr.append("<td>" + "<button class='editButton'>" + "<i class='material-icons'>edit</i></button>" + "</td>");
tr.append("<td>" + json[i].pageCount + "</td>");
tr.append("<td>" + json[i].name + "</td>")
$('table').append(tr);
}
});
$(document).on('click', '.deleteButton', () => {
console.log($(this));
})
});
</script>
Problem: As it seen in bookShow.html, I've declared an eventlistener whenever .deleteButton clicked. But I can't access the other fields of that table row. for example when I click on delete button of Behzad, I can't be notified the book name and its page count.

By using ES6's Arrow function () => {} the this is not any more what you're used to like by using function. It's window, because of their nature of lexical scope binding. Not any more the jQuery's representation of the DOM Element "this".
$(this) =
jQuery.fn.init [Window] by usign Arrow function () => {}
jQuery.fn.init [button.deleteButton] by using Function function () {}
so your solution would be to use the standard $(document).on('click', '.deleteButton', function() {
or to add the click on button creation - which is doable by making your button an live in-memory jQuery element $('<button>', {on:{click(){}}, appendTo:'selector'}) instead of HTML string literal.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
Here's a remake:
const json = [ // You use getJSON, I'll use this for my demo
{"name": "King of the Jungle","pageCount": 543},
{"name": "The Things I've Done","pageCount": 198}
];
jQuery($ => {
// $.getJSON
$('table').append(json.map((book, i) =>
$('<tr>', {
html: `
<td>${i+1}</td>
<td>${book.name}</td>
<td>${book.pageCount}</td>
`,
append: [ // or use prepend
$('<td>', {
append: $('<button>', {
class: "buttonEdit",
html: "<i class='material-icons'>edit</i>",
on: {
click() { // Same as using `click: function () {`
console.log(`Editing ${book.name} by:`, this); // this = <button>
}
}
})
}),
$('<td>', {
append: $('<button>', {
class: "buttonDelete",
html: "<i class='material-icons'>delete</i>",
on: {
click() {
console.log(`Deleting ${book.name} by:`, this);
}
}
})
}),
]
})
));
// END $.getJSON
});
table {
width: 100%;
}
td {
border: 1px solid #ddd;
}
<table></table>
<script src="//code.jquery.com/jquery-3.1.0.js"></script>

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 :)

Swashbuckle/swagger, change displayed doc via jquery/javascript

I need to change active doc displayed by swagger with Jquery.
Detail:
My routes are separated into groups/version, so average api call looks like this: Api/{group}/{version}/Controller/Method
And my swagger docs are generated that way aswell. But I dont really like the way user selects active doc inside the UI. So I just added my own javascript to insert some inputs for this. What I dont know is hot to tell the swaggerUI to change to specific doc.
Here is my javascript:
(function (){
var DiscoveryUrlSelector = Backbone.View.extend({
render: function ()
{
// Nerenderuj opakovaně na reloadu
var defaultVal = this.$el.val()
if (!this.$el.find('#input_' + this.options.name).length) {
var select = $('<select id="input_' + this.options.name + '" name="' + this.options.name + '"></select>');
select
.css('margin', '0px 10px 0px 0px')
.css('border', '1px solid gray')
.css('padding', '3px')
.css('width', '100px')
.css('font-size', '0.9em');
_.each(this.options.discoveryPaths, function (path) {
var option = $('<option>' + path + '</option>');
select.append(option);
});
select.val(defaultVal);
select.change(SetVersionedGroup);
select.insertBefore('#input_username');
}
return this;
}
});
new DiscoveryUrlSelector(
{
el: $('#api_selector'),
name: 'Group',
rootUrl: swashbuckleConfig.rootUrl,
discoveryPaths: Array.from(new Set(swashbuckleConfig.discoveryPaths.map(x => x.substring(13, x.lastIndexOf("v")))))
}).render();
new DiscoveryUrlSelector(
{
el: $('#api_selector'),
name: 'Version',
rootUrl: swashbuckleConfig.rootUrl,
discoveryPaths: Array.from(new Set(swashbuckleConfig.discoveryPaths.map(x => x.substring(x.lastIndexOf("v"), x.length))))
}).render();
function SetVersionedGroup()
{
}
})();
And my Header looks like this:
Any ideas how to finish my SetVersionedGroup function?

miss button click event when button is added dynamically

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();
},
});

How to Show Dynamically Added Element

I'm trying to create tooltips with title attribute and jQuery but can't find method to show dynamically added element.
HTML
some page
CSS
.tooltip {
    …
display: none; /* I's needed for hard coded tooltips */
…
}
jQuery
$(function () {
if (window.matchMedia('(min-width: 980px)').matches) {
$('.dfn').hover(
function () {
var el = $(this);
var txtTitle = el.prop('title');
el.append('<p class="tooltip">' + txtTitle + '</p>');
                //That's it. My tooltip has been created, but it has not been shown
$(el + ' .tooltip').show('fast');
el.data('title', el.prop('title'));
el.removeAttr('title');
}, function () {
$(el + ' .tooltip').hide('fast').remove();
el.prop('title', el.data('title'));
}
);
}
});
As mentioned by others, $(el + ' .tooltip').show('fast'); is probably wrong.
The el is an object, not a string to concat', one way is to use el.find('.tooltip').show().
The other way is to use the context option: $('.tooltip', el).show();
You need to have correct code to find new element:
$('.tooltip', el).show('fast');
Your current one probably endup searching for something like [object] .tooltip or similar string depending on how JavaScript decides to convert HTML element to string.
As others have mentioned el.find('.tooltip').show() and el.find('.tooltip').hide().remove(); solve the problem.
Also, in HandlerOut function, you el was not declared. Fiddle here
$(function () {
//if (window.matchMedia('(min-width: 980px)').matches) {
$('.dfn').hover(
function () {
var el = $(this);
var txtTitle = el.prop('title');
el.append('<p class="tooltip">' + txtTitle + '</p>');
//That's it. My tooltip has been created, but it has not been shown
el.find('.tooltip').show()
el.data('title', el.prop('title'));
el.removeAttr('title');
}, function () {
var el = $(this);
el.find('.tooltip').hide().remove();
el.prop('title', el.data('title'));
}
);
//}
});

Categories