Bootstrap Popup - Attach event to button for popover dynamically - javascript

I intend to use the Bootstrap Popover module as a confirmation for a delete event, such that when a <button> is clicked, instead of simply firing a function it opens a popup which let's the user confirm or dismiss the action.
It should be noted for context that the environment is a self-built, one-page ~mvc webapp, where the elements are added dynamically (I thus do not know the number of elements beforehand, nor can I hardcode the actions for each element)
In the current situation (without the popover) I do something similar to this to trigger the direct (non-conformation) action:
$view.on('click', '.deleteButton', function () {
var id = $(this).attr('data-id');
api.delete('someUrl' + id, successFunction);
}):
Where the button would have a markup similar to this:
<button class="deleteButton" data-id="2">Delete me!</button>
However, now I wish to add a confirmation step (e.g. "Are you sure you want to delete this magnificent button? (Y/N)"), and thought of using bootstrap popover.
After brainstorming a bit, what I came up with was a strategy like the following. It is not the optimal solution (the optimal solution would be to extend the popover module so that I would be able to pass in confirmationFunction and cancelFunction to the popover).
Firstly, I would have to initiate the popovers.
$view.find('.deleteButton').popover({
title: 'Are you sure?', //Example title
html: true, //Essential for the html to work as expected
selector: '.deleteButton', //Allow ajaxing in of new elements
container: '.viewName', //So that the popovers reside w/in the current view and thus can be bound to $view (a jQuery object for the view)
content: [...], //Two <button>s with a specified class, e.g. .viewName__deleteButton--popover
});
Secondly, I would bind an event to the buttons inside the popover
$view.on('click', '.viewName__deleteButton--popover', function () {
var id = ??; // Here comes the troubling part - how do I get the ID of the clicked button? How can I target the original button? If I can do that, I think it would solve everything.
api.delete('someUrl' + id, successFunction);
});
The problem that arises is how do I target the originally clicked button?
The only soultion which I can come up with, which isn't very neat at all is to do something like this:
var popoverId = $(this).parents('.popover').attr('id'); //returns popoverXXXXXX
var parentElement = $view.find('[aria-describedBy="' + popoverId + '"]');
It works, but it is a very dirty solution and does not feel 'nice' att all.
Is there any way this can be done in a neater manner? Preferably I would be able to define a general function such as $element.confirmationPopover({popoverSettings...}, confirmationFunction, declineFunction); which could be used in multiple cases.
(PS: I couldn't figure out a concise title for this Q, advice is as always appreciated!)

I solved it by creating an extension to jQuery, such that:
$.fn.confirmationPopover = function (passedInOptions) {
var $view = this;
var defaultOptions = {
confirmationLabel: 'Yes',
container: '.' + this.attr('class'),
declineLabel: 'No',
html: true,
placement: 'left', //top | left | right | bottom
rowClasses: false
};
if (!passedInOptions.declineClass) {
passedInOptions.declineClass = passedInOptions.selector + '__popover__decline';
}
var obj = {}; //Merged options
$.extend(true, obj, defaultOptions, passedInOptions);
var popoverContent = '<div class="row ' + (obj.rowClasses ? obj.rowClasses : 'tac') + '">' +
'<button class="button button--small ' + obj.confirmationClass + '">' + obj.confirmationLabel + '</button>' +
'<button class="button button--small button--outline ' + obj.declineClass + '">' + obj.declineLabel + '</button>' +
'</div>';
if (!obj.content) {
obj.content = popoverContent;
}
/* Initiate Popover */
$view.popover(obj);
/**
* Bind confirmation Button
*/
$view.on('click', '.' + obj.confirmationClass, function () {
var popoverId = $(this).parents('.popover').attr('id');
var $this = $view.find('[aria-describedBy="' + popoverId + '"]');
obj.confirmationFunction($this);
});
/**
* Bind decline button
*/
$view.on('click', '.' + obj.declineClass, function () {
var popoverId = $(this).parents('.popover').attr('id');
var $this = $view.find('[aria-describedBy="' + popoverId + '"]');
if (typeof obj.declineFunction === 'function') {
obj.declineFunction($this);
} else {
$this.popover('hide');
}
});
return this;
};

You can also use popoverX! . It's slightly modal-ish version of bootstrap popovers.

Related

jQuery $.load Not Executing

I am currently using jQuery on my Django site to reload a div once a user clicks a button.
$(document).ready(function(){
var post_list = Array.from(document.getElementsByClassName("post_container"))
for(var post in post_list){
post_list[post].id = 'post' + post;
}
var $arrows = $(".arrow");
$arrows.each(function(index){
var data = $(this).data();
var element = $(this);
element.on('click', function(event){
if(user_auth){
var currentParentElement = element.parent().parent().parent().get(0);
var id = $(currentParentElement).attr('id');
$(id).load(document.URL + ' ' + id);
}
})
})
});
From the console I can see that currentParentElement and id are pointing to the correct div to reload, but $(id).load() does not seem to be doing anything.
In the image linked below, the clicking the arrow buttons should make the green or red number change. The number does not change when the arrow is clicked, but it does change when I reload the entire page.
https://i.stack.imgur.com/T26wn.png
Your ID selector is missing the # symbol. For example, suppose the id of this target element is "myID":
var id = $(currentParentElement).attr('id');
Then the jQuery selector you're using is:
$('myID')
Which is looking for a <myID> element. There isn't one, so no matches are found, so there's nothing to call .load() on.
You could add the symbol to your selector:
$('#' + id).load(document.URL + ' #' + id);
(Note: The same correction was also made in the selector passed to load() for the same reason.)

ag-grid custom filter adding a clear filter button. JS not Angular

Using the example on the ag-grid site I have written a filter based on a RAG status. The vaules can be either Undefined, Red, Amber, Green, or Complete.
Using the PersonFilter example at https://www.ag-grid.com/javascript-grid-filter-component/, I am using an array to add clicked values to, to then filter the grid on. This works really well. However it is my intention to clear the filter via a clear button.
Here is the code I have so far:
RagFilter.prototype.setupGui = function (params) {
this.filterText = [];
this.gui = document.createElement('div');
this.gui.innerHTML =
'<div style="padding: 6px; width: 150px;">' +
'<div><h3>RAG Filter</h3></div>' +
'<div><span class="icon icon-rag-s-undefined" data-value="undefined"></span> ' +
'<span class="icon icon-rag-s-red" data-value="red"></span> ' +
'<span class="icon icon-rag-s-yellow" data-value="yellow"></span> ' +
'<span class="icon icon-rag-s-green" data-value="green"></span> ' +
'<span class="icon icon-rag-s-blue" data-value="blue"></span>' +
'CLEAR';
var that = this;
$('body').on('click', '.icon', function(e){
if (that.filterText.indexOf($(e.target).data('value'))) {
that.filterText.push($(e.target).data('value'));
}
params.filterChangedCallback();
});
$('body').on('click', '#clear_filter', function(e){
e.preventDefault();
var filter = $(this).data('filter');
var filterComponent = params.api.getFilterInstance(filter);
filterComponent.setModel(null);
this.filterText = null;
});
};
This method is taken from the example at https://www.ag-grid.com/javascript-grid-filter-component/ using the PersonFilter.
I have tried the click event handler for the button outside of the filter code as well:
$('body').on('click', '#clear_filter', function(e){
e.preventDefault();
var filter = $(this).data('filter');
var filterComponent = gridOptions.api.getFilterInstance(filter);
filterComponent.setModel(null);
});
and I consistently get an undefined error for the variable filterComponent. The variable filter is set to 'rag' which comes from the data-filter attribute on the clear button.
I keep going round and round with this and can't seem to find a clear tutorial or code example that does exactly what I want to achieve.
All help is greatly appreciated..
Cheers
After much fiddling around with the code I worked out that you actually need the colDef.colId value and not the field name as the documentation suggests:
$('body').on('click', '#clear_filter', function(e){
e.preventDefault();
var filterComponent = params.api.getFilterInstance(params.colDef.colId);
that.filterText = null;
params.api.onFilterChanged();
});

Hide/show function jquery or javascript calling more than one action, but not at the same time

So i want to make a remove player button, so that everytime i click it, it hides a images/button, the same for a add player function.
function addplayer(){
for (var i = 51; i <= 94; i++) {
if (i == 51 || i == 61 ||){
$("#" + "addplayer" + i).show();
}
}
}
This is my html caller
<button onclick="addplayer();"style="bottom:55;position:fixed;right:10;width:100;height:40px;background-color:#FFFFFF;">addplayer</button>
document.getElementById("addplayer2").onclick=function(){
document.getElementById("51Container").style.display="inline-block";
document.getElementById("52Container").style.display="inline-block";
document.getElementById("53Container").style.display="inline-block";
document.getElementById("54Container").style.display="inline-block";
}
document.getElementById("addplayer3").onclick=function(){
document.getElementById("61Container").style.display="inline-block";
document.getElementById("62Container").style.display="inline-block";
document.getElementById("63Container").style.display="inline-block";
document.getElementById("64Container").style.display="inline-block";
}
(i got 6 in total completly looking the same), just to illustrate, how it would work
Theese are my add player function, just on 5 different buttons, just to showcase that it is doing something, it doest seem to work for me, how do i do this, so that the same button will add (show), different object instead of the solution i got atm.
Hope somebody will help me.
If you want to invoke the function which is assigned to the addplayer# control, instead of calling $("#addplayer" + i).show() try calling $("#addplayer" + i).click() .. however, based on our back-and-forth, it seems that your i needs some attention.
As you said, your addplayer# controls are buttons, therefore, I suggest the following:
function addplayer(){
$("button[id^='addplayer']").each(function(i,e) { $(e).click(); });
}
This will invoke any click event function defined for any buttons whose id starts with addplayer.
See this fiddle for an example of how it works: https://jsfiddle.net/qhevn1x3/2/
Although I do not know your page's exact makeup, I would suggest something along these lines (if possible):
<div id='51Container'>some player</div>
<button class="addPlayer" data-id="51">Add Player</button>
<button class="removePlayer" data-id="51">Remove Player</button>
Then my JS would be something like:
// Page-level execution to assign my click events
$(function() {
$("button.addPlayer").on("click", function() {
var id = $(this).attr("data-id");
$("#" + id + "Container").css({'display':'inline-block'});
$("button.addPlayer[data-id='" + id + "']").toggle();
$("button.removePlayer[data-id='" + id + "']").toggle();
});
$("button.removePlayer").on("click", function() {
var id = $(this).attr("data-id");
$("#" + id + "Container").css({'display':'none'});
$("button.addPlayer[data-id='" + id + "']").toggle();
$("button.removePlayer[data-id='" + id + "']").toggle();
});
})();
This will wire up the add/remove buttons with the corresponding player. Then, if you wish to have a button to hide/show multiple, you need only select the appropriate add/remove buttons (by filtering by data-id) and invoke their click events.

Adding CR or LF in HTML attribute

To explain this shortly, I have an mouseenter Jquery event firing up an AJAX call. And a Jquery UI tooltip.
$(function()
{
$(document).tooltip({track:true});
$('#NewUser').mouseenter(function(){AJAXValidation("NewUser")});
});
Here is the call:
function AJAXValidation(section)
{
var request = $.ajax(
{
url: "ProcessJRT.php",
type: "POST",
contentType:"application/x-www-form-urlencoded;charset=UTF-8",
data:
{
validate:section
}
});
request.done(
function(message)
{
var div = document.createElement('div');
$(div).html(message);
$(div).children().each
(
function(i)
{
var title = '';
if($('#' + $(this).attr('id')).attr('title') != null)
{
title = $('#' + $(this).id).attr('title');
}
title += $(this).html() + '\r\n';
$('#' + $(this).id).attr('title', title);
}
);
});
}
What it does now is it take the <div>s from message and it place them in a parent <div>. (In my code the div already exist, I changed that part so the question would stay as short as possible).
I then take the text from those <div> and I want to place them in the corresponding <input/> title attribute.
Everything work just perfect here exepte this stupid little thing:
I am unable to add a LN or a CR in the title so all the texts from the divs would be on separate line...
I have tried adding a </br> inside the attribute like this:
function(i)
{
var title = '';
if($('#' + $(this).id).attr('title') != null)
{
title = $('#' + $(this).attr('id')).attr('title');
}
title += $(this).html() + '</br>';//<---See I added a BR here
$('#' + $(this).id).attr('title', title);
}
But it display the </br> as normal text. I than tried String.fromCharCode(13) but did'nt work, I tried jus '\n' or '\r\n' and still does work.
Can someone point out were I am derping on this one??
Thanks!
EDIT:
Changed the $('#' + $(this).attr('id')) to $('#' + $(this).id).
You can't format the title attribute in that way, it doesn't work, and will be different across different browsers.
Try the jquery plugin qTip to achieve what you want. (looks good too!)
http://craigsworks.com/projects/qtip/
Alternatively, you can cheat by using etc, to push the text to the next line. but this is flaky at best.
Here is how I resolve my problem with the idea that #crush gave me:
First:
I removed the tooltip initialization from the function that fire the event :
$(function()
{
$('#NewUser').mouseenter(function(){AJAXValidation("NewUser")});
});
Next:
I changed the "done" function so I would initialise a new tooltip each time with html content (FYI JQuery tooltip can format HTML)
Here what it look like now:
function(message)
{
var div = document.createElement('div');
$(div).html(message);
var title = '';
$(div).children().each
(
function(i)
{
if($('#' + $(this).id).attr('title') != null)
{
title = $('#' + $(this).id).attr('title');
}
title += $(this).html() + '</br>';
$(document).tooltip({content:title, items:('#' + $(this).id)});
}
);
}

Dynamic Button not refreshing CSS properties

First time posting = )
I have been searching for a little while and have tried many ('refresh').trigger , ('create') and markup answers other members have suggested or I have seen on other posts. I am pretty new to JS JQM but I am having troubles having my dynamically added buttons viewed with the CSS properties. I have tried other solutions posted on similar questions such as:
How to add dynamic jquery button?
Jquery Dynamically generated buttons no css
A few other posts too.
Sorry in advance if already answered, I could not find a solution.
Here is my code:
The Reason I made the button a variable was because of another form post suggested it then refreshing that way...
$( '#csvButton' ).on( 'click', function() {
$('#viewData').empty();
$('#testView').empty();
$.ajax( {
url: 'xhr/data.csv',
type: 'GET',
dataType: 'text',
success:function ( result ) {
//console.log(result);
var lines = result.split("\n");
//console.log(lines);
var dataRow = lines[0];
var dataCol = dataRow.split(",");
for (var lineNum = 1; lineNum < lines.length; lineNum++) {
var row = lines[lineNum];
var columns = row.split(",");
var thisButton = $("<a>").attr("href", "#").attr("data-role", "button").attr("data-theme", columns[1]).attr("data-icon", columns[2]).text(columns[0]);
thisButton.appendTo('#testView');
$('<ul>' + '<li><b>' + dataCol[0] + " " + columns[0] + '</b></li>' +
'<li>'+ dataCol[1] + " " + columns[1] + '</li>' +
'<li>'+ dataCol[2] + " " + columns[2] + '</li>' + '</ul>'
).appendTo('#testView');
}
}
});
});
return false;
});
I am having trouble with thisButton displaying properly with CSS properties. I am made it a link with data-role="button" and trying it as a
my CSV has button name "Settings", button theme "a", and button icon "gear" data.
Any help would be great. #testView was a temp I created to test ideas to get CSS properties to work.
Thanks in advance!
Well you're working on dynamic buttons so it seems it would be better if you set css to a class and then add class to button dynamicaly.
Try add class to your css code with parameters you need and then in your code put somewhere
$("#testView").addClass("name of your class");
I'm sorry but i can test this solution right away so i'm not sure if its working as you wish.
Good Luck :)
You can remove or put CSS properties with this:
E.g.:
$("#testView").class('display', 'none');
Look at this Porperty CSS documentation

Categories

Resources