Running same JQuery function on many elements with same id - javascript

I'm sure this is going to be simple well i hope it is. After racking my brain for days I have finally sorted my last problem thanks you someone on here, But now I have a new problem. I am dynamically creating blogs hundreds of them. I'm using JQuery to load a editor into a simple modal window like so
<a class="blog_btns" id="edit" data-id="$b_blog_id" href="">Edit</a>
then the JQuery
jQuery(function($) {
var contact = {
message: null,
init: function() {
$('#edit').each(function() {
$(this).click(function(e) {
e.preventDefault();
// load the contact form using ajax
var blogid = $(this).data('id');
$.get("../_Includes/edit.php?blogid=" + blogid, function(data) {
// create a modal dialog with the data
$(data).modal({
closeHTML: "<a href='#' title='Close' class='modal-close'>x</a>",
position: ["15%", ],
overlayId: 'contact-overlay',
containerId: 'contact-container',
onOpen: contact.open,
onShow: contact.show,
onClose: contact.close
});
});
});
});
},
open: function(dialog) {
dialog.overlay.fadeIn(200, function() {
dialog.container.fadeIn(200, function() {
dialog.data.fadeIn(200, function() {
$('#contact-container').animate({
height: h
}, function() {
$('#contact-container form').fadeIn(200, function() {
});
});
});
});
});
},
show: function(dialog) {
//to be filled in later
},
close: function(dialog) {
dialog.overlay.fadeOut(200, function() {
$.modal.close();
});
},
};
contact.init();
});
the problem I have is i have hundreds of
<a class="blog_btns" id="edit" data-id="$b_blog_id" href="">Edit</a>
but I want the all to run the same jQuery function above.
Can anyone help? Is there a simple way of doing this?

...many elements with same id...
That's the problem, you can't have multiple elements with the same id.
You probably want to use a class:
<a class="blog_btns edit" data-id="$b_blog_id" href="">Edit</a>
<!-- Added ---------^ -->
Then:
$('.edit').each(...);
// ^---- ., not #, for class
But you probably don't want to use each, just do:
$('.edit').click(function(e) {
// ...
});
There's no need to loop through them individually.
Another approach you might consider is rather than hooking click on each individual "edit" link, you might want to use event delegation. With that, you hook the event on an element that contains all of these "edit" links (there's bound to be a reasonable one, body is always possible as a last resort), but tell jQuery not to notify you of the event unless it passed through one of these on its way to that element in the bubbling. That looks like this:
$("selector for the container").on("click", ".edit", function(e) {
// ...
});
Within the handler, this will still be the "edit" link.

Use class instead of id as according to HTML standards each element should have a unique id.
id: This attribute assigns a name to an element. This name must be unique in a document.
class: This attribute assigns a class name or set of class names to an
element. Any number of elements may be assigned the same class name or
names. Multiple class names must be separated by white space
characters.
http://www.w3.org/TR/html401/struct/global.html
so use class instead of id
<a class="blog_btns edit" data-id="$b_blog_id" href="">Edit</a>
and refer to it with $('.edit')

Related

jQuery .remove() does not work with div created inside the function

I've tried a couple of things since yesterday, but I can't achieve my goal.
The idea is :
When clicking on a character "Div", it appears a little menu to change a parameter inside my website. The problem is, I want to remove the "Class Picker", but it just does not work.
var CharacterClasses = [
{ id: 1, name: 'Warrior', cssClass: 'warrior'},
{ id: 2, name: 'Paladin', cssClass: 'paladin'},
...
]
$('.group_miniature').click( function(){
// Removing all existant class choices
$(".group-panel_class_picker").remove()
// Creating the class picker
var Panel = $("<div id=\"panel_class_picker\"></div>").addClass('group-panel_class_picker')
// Append the whole thing
$(this).append(Panel)
// Iterating each class to add a div
CharacterClasses.forEach( function(item){
// Creating the div
let btn_class = $("<div>&nbsp</div>").addClass( [item.cssClass,'group-btn_class'] )
Panel.append(btn_class)
Panel.on("click", ".group-btn_class", function(event){
$(this).parent().remove() // This is my problem, it does not remove the parent
console.log('Click :)') // This appears in my console
})
})
})
Panel.on("click", ".group-btn_class", function(event){
$(this).parent().hide()
event.stopPropagation()
console.log('Click criss')
})
I discovered that I had to add event.stopPropagation()
Now it works just fine ! :)

Bootstrap-confirmation not respecting options

Just adding the bootstrap-confirmation extension for Bootstrap popover to some buttons on a project. I'm having issues with the options not being respected. I'm trying to get the popups to work as singletons and dismiss when the user clicks outside of them singleton and data-popout options, respectively - both set to true. I'm also not seeing any of my defined callback behavior happening.
I defined the options both in the HTML tags and in a function and neither works. Still getting multiple boxes and they don't dismiss as expected.
My JS is loaded after all other libraries and is in my custom.js file in my footer.
JS is as follows:
$(function() {
$('body').confirmation({
selector: '[data-toggle="confirmation"]',
singleton: true,
popout: true
});
$('.confirmation-callback').confirmation({
onConfirm: function() { alert('confirm') },
onCancel: function() { alert('cancel') }
});
});
An example of the box implemented on a button in my HTML is the following:
<a class="btn btn-danger" data-toggle="confirmation" data-singleton="true" data-popout="true"><em class="fa fa-trash"></em></a>
Any pointers would be appreciated. I even changed the default options in the bootstrap-confirmation.js file itself to what I want and still no luck.
Turns out I needed to rearrange a couple things to get this to work. I've left in the last_clicked_id etc stuff as I needed to add that to get the id value of what I'd just clicked.
// Product removal popup logic
var last_clicked_id = null;
var last_clicked_product = null;
$('.btn.btn-danger.btn-confirm').click(function () {
last_clicked_id = $(this).data("id");
last_clicked_product = $(this).data("product");
});
$('.btn.btn-danger.btn-confirm').confirmation({
singleton: true,
popout: true,
onConfirm: function () {
alert("DEBUG: Delete confirmed for id : " + last_clicked_product);
// TODO: Add AJAX to wipe entry and refresh page
},
onCancel: function () {
alert("DEBUG: Delete canceled for id : " + last_clicked_product);
}
});
I was a step ahead of myself with the callback logic which was not getting executed. Fixed by simply adding it to onConfirm: and onCancel: key values in the .confirmation() function. A bit of a RTFM moment there but this was unfortunately not very clear in the documentation.

Select2 Event for creating a new tag

I'm using the jQuery Select2 (v4) plugin for a tag selector.
I want to listen for when a new tag is created in the select element and fire an ajax request to store the new tag. I discovered there is the createTag event but this seems to fire every time a letter is entered into the select2 element. As shown in my fiddle: http://jsfiddle.net/3qkgagwk/1/
Is there a similar event that only fires when the new tag has finished being entered? I.e. it's enclosed by a grey box enclosing it.
I can't find any native method unfortunately. But if you're interested in simple "workarounds", maybe this get you closer:
$('.select2').select2({
tags: true,
tokenSeparators: [",", " "],
createTag: function (tag) {
return {
id: tag.term,
text: tag.term,
// add indicator:
isNew : true
};
}
}).on("select2:select", function(e) {
if(e.params.data.isNew){
// append the new option element prenamently:
$(this).find('[value="'+e.params.data.id+'"]').replaceWith('<option selected value="'+e.params.data.id+'">'+e.params.data.text+'</option>');
// store the new tag:
$.ajax({
// ...
});
}
});
DEMO
[EDIT]
(Small update: see #Alex comment below)
The above will work only if the tag is added with mouse. For tags added by hitting space or comma, use change event.
Then you can filter option with data-select2-tag="true" attribute (new added tag):
$('.select2').select2({
tags: true,
tokenSeparators: [",", " "]
}).on("change", function(e) {
var isNew = $(this).find('[data-select2-tag="true"]');
if(isNew.length && $.inArray(isNew.val(), $(this).val()) !== -1){
isNew.replaceWith('<option selected value="'+isNew.val()+'">'+isNew.val()+'</option>');
$.ajax({
// ... store tag ...
});
}
});
DEMO 2
The only event listener that worked for me when creating a new tag was:
.on("select2:close", function() {
(my code)
})
This was triggered for new tags and selecting from the list. change, select2:select, select2:selecting and any others did not work.
One more simple check will be this based on the difference in the args of the event .....
While I was dealing with this situation, I had seen this difference; that when the new element is created the event args data does not have an element object but it exists when selecting an already available option...
.on('select2:selecting', function (e) {
if (typeof e.params.args.data.element == 'undefined') {
// do a further check if the item created id is not empty..
if( e.params.args.data.id != "" ){
// code to be executed after new tag creation
}
}
})
Another workaround. Just insert it to the beginning:
}).on('select2:selecting', function (evt) {
var stringOriginal = (function (value) {
// creation of new tag
if (!_.isString(value)) {
return value.html();
}
// picking existing
return value;
})(evt.params.args.data.text);
........
It relies on underscore.js for checking if it's string or not. You can replace _.isString method with whatever you like.
It uses the fact that when new term is created it's always an object.

Redefining a jQuery dialog button

In our application we use a general function to create jQuery dialogs which contain module-specific content. The custom dialog consists of 3 buttons (Cancel, Save, Apply). Apply does the same as Save but also closes the dialog.
Many modules are still using a custom post instead of an ajax-post. For this reason I'm looking to overwrite/redefine the buttons which are on a specific dialog.
So far I've got the buttons, but I'm unable to do something with them. Is it possible to get the buttons from a dialog (yes, I know) but apply a different function to them?
My code so far:
function OverrideDialogButtonCallbacks(sDialogInstance) {
oButtons = $( '#dialog' ).dialog( 'option', 'buttons' );
console.log(oButtons); // logs the buttons correctly
if(sDialogInstance == 'TestInstance') {
oButtons.Save = function() {
alert('A new callback has been assigned.');
// code for ajax-post will come here.
}
}
}
$('#dialog').dialog({
'buttons' : {
'Save' : {
id:"btn-save", // provide the id, if you want to apply a callback based on id selector
click: function() {
//
},
},
}
});
Did you try this? to override button's callback based on the need.
No need to re-assign at all. Try this.
function OverrideDialogButtonCallbacks(dialogSelector) {
var button = $(dialogSelector + " ~ .ui-dialog-buttonpane")
.find("button:contains('Save')");
button.unbind("click").on("click", function() {
alert("save overriden!");
});
}
Call it like OverrideDialogButtonCallbacks("#dialog");
Working fiddle: http://jsfiddle.net/codovations/yzfVT/
You can get the buttons using $(..).dialog('option', 'buttons'). This returns an array of objects that you can then rewire by searching through them and adjusting the click event:
// Rewire the callback for the first button
var buttons = $('#dialog').dialog('option', 'buttons');
buttons[0].click = function() { alert('Click rewired!'); };
See this fiddle for an example: http://jsfiddle.net/z4TTH/2/
If necessary, you can check the text of the button using button[i].text.
UPDATE:
The buttons option can be one of two forms, one is an array as described above, the other is an object where each property is the name of the button. To rewire the click event in this instance it's necessary to update the buttons option in the dialog:
// Rewire the callback for the OK button
var buttons = $('#dialog').dialog('option', 'buttons');
buttons.Ok = function() { alert('Click rewired!'); };
$('#dialog').dialog('option', 'buttons', buttons);
See this fiddle: http://jsfiddle.net/z4TTH/3/
Can you try binding your new function code with Click event of Save?
if(sDialogInstance == 'TestInstance') {
$('#'+savebtn_id).click(function() {
alert('A new callback has been assigned.');
// code for ajax-post will come here.
});
}

Calling a JavaScript function inside a jQuery generated <a href...>

I have a problem with this piece of code:
$(document).ready(function() {
$('.notActiveId').change(function() {
if ($(this).attr('value').length === 0 ) {
$("#notActiveButton").html('');
} else {
$("#notActiveButton").html('<a href="javascript:void(0)" onClick="setStatus(' + $(this).attr('value') + ', activate)" class="operationUnlock" >Activate</a>');
}
});
});
I'm calling with $(this).attr('value') a value from a select list named notActiveId. But the problem is how to write $(this).attr('value') in setStatus() function, because value of my select is in this form: RZT_83848Rer (so it consists of characters, underline and numbers).
If I try to write it as above, then I get a JavaScript error.
Instead of using an old-school "onclick", why not add your element via jQuery?
$('#notActiveButton').empty().append($('<a/>', {
href: '#', // the "javascript:" thing is basically bogus and unnecessary
click: function () {
setStatus(this.value, activate);
},
class: 'operationUnlock',
text: 'Activate'
}));
Now, all this assumes that your "notActiveButton" element is some sort of legitimate container for your <a> tag. But anyway, doing it this way you get to write plain JavaScript without having to worry about the mess of quoting etc.

Categories