I have a bootstrap popover for my django website that opens when a button is clicked. Inside this popover is another button. I am currently doing this by putting HTML in the 'data-content' of the popover, seen below:
<a tabindex="0" id="{{prod.title}}" value="{{prod.id}}" type="button"
class="btn btn-secondary btn-light mt-3 mb-0"
data-toggle="popover"data-trigger="focus" data-html="true" data-content="
<div class='btn-group-vertical'>
<a type='button' data-show-value='{{prod.id}}' id='{{prod.id}}'
class='btn btn-secondary btn-pop wish'>Add to Wishlist</a>
</div>"
>More Options</a>
I need to get the 'data-show-value' in jQuery, and I am currently using the following which triggers when this button is clicked:
$(document).on('click', '.wish', function () {
var thisButton = $(this)[0]
console.log(thisButton);
var prodID = $(this).data("show-value");
}
However, all this does is return 'undefined'.
I used console.log(thisButton) to see what the button code is displaying as, and it is this:
<a id=10 class='btn btn-secondary btn-pop wish'>Add to Wishlist</a>
This explains why the 'data-show-value' is returning as undefined, as the attribute itself is not rendering on the web page.
Why is this?
.wish is a class and there may be a lot of elements that has this class you need to specify an id instead:
$(document).on('click', '.wish', function () {
var thisId = $(this).attr('id');
console.log(thisId); //check if this is the id of the element you want to trigger
var prodID = $('#'+thisId).data("show-value");
}
Related
I have a button with an id that sets a global variable like this:
<div class="mybuttons"
<button id="mapOne" data-toggle="modal" data-target="#map-1-scene-1">Scene</button>
<button class="no-click-span" id="mapOneCurrent" data-toggle="modal" data-target="#map-1-scene-1"><i class="fas fa-charging-station fa2x"></i> Current</button>
</div>
Then in JS:
var mapNumber;
const mybuttons = document.querySelectorAll('.mybuttons button');
mybuttons.forEach(mybutton => {
mybutton.addEventListener('click', processClick);
});
function processClick() {
window.mapNumber = this.id; // the id of the clicked button
}
The second button in the div with the id #mapOneCurrent just reopens the modal without refreshing the data.
What I would like to happen, is if the second button is pushed (eg #mapOneCurrent) that the variable mapNumber just remains as mapOne (without the word "Current" at the end of it). So it would almost be as if the other button had been pushed.
Is this possible to do in this type of scenario?
This should do what you want:
var mapNumber;
const mybuttons = [...document.querySelectorAll('.mybuttons button')];
mybuttons.forEach(mybutton=>{
mybutton.addEventListener('click',function() {
window.mapNumber = this.id.replace("Current",""); // the id of the clicked button
console.log(mapNumber);
});
})
<div class="mybuttons">
<button id="mapOne" data-toggle="modal" data-target="#map-1-scene-1">Scene</button>
<button class="no-click-span" id="mapOneCurrent" data-toggle="modal" data-target="#map-1-scene-1"><i class="fas fa-charging-station fa2x"></i>Current</button>
</div>
However, you could simplify it by using "delegated event listening" to:
var mapNumber;
document.querySelector('.mybuttons').addEventListener('click',function(ev){
if (ev.target.tagName==="BUTTON") {
window.mapNumber = ev.target.id.replace("Current","");
console.log(mapNumber);
}
})
<div class="mybuttons">
<button id="mapOne" data-toggle="modal" data-target="#map-1-scene-1">Scene</button>
<button class="no-click-span" id="mapOneCurrent" data-toggle="modal" data-target="#map-1-scene-1"><i class="fas fa-charging-station fa2x"></i>Current</button>
</div>
In this snippet the event is listening to clicks on the wrapper container .mybuttobs but will trigger actions only if an inside BUTTON was clicked.
first of all, thank you for your time to read this question, and two things, I'm using ES5 and I don't use jQuery.
Right now I'm struggling a lot to figure what's the correct solution for the addEventListener, because for some reason it does not trigger for the second button which is only for the mobile screen dimensions, the problem is that the second button have the same id but different class, for example this:
<div class="product-bg-container product-general-info variation-info">
<input type="hidden" name="sku" value="Something-15892290" id="selected-option">
{/* Desktop screen button */}
<button id="buy-now" class="btn btn-lg hidden-sm-down btn-primary">
Add to Cart
</button>
{/* Mobile screen button */}
<button id="buy-now" class="btn btn-lg hidden-md-up btn-primary">
Add to Cart
</button>
</div>
Where I am trying to trigger the second button but it does not where I don't understand why it does, if the id is the same, should not matter, so I'm trying to figure how to trigger from the first button if it's clicked and also with the second if it's clicked, but I'm out of ideas...
var button = document.getElementById('buy-now');
if (!button) {
return;
}
button.addEventListener('click', function trackAddToCart() {
// more code for the event
}
I thought an idea to capture the attribute of the button, but it works in the first button but not for the second one:
var button = document.getElementById('buy-now');
var att = button.getAttribute('class');
button.addEventListener('click', function() {
console.log('class ' + att); //shows: class: btn btn-lg hidden-sm-down btn-primary
console.log('button class? '+ button); //shows: button element: [object HTMLButtonElement]
});
But when I click the second button... does not trigger or happening nothing, not sure why... and I can't change the id value (which it should be easy but I can't "company standard")
Can anyone help me to have an idea how to capture and trigger the event for the second button ??
The attribute id must be unique in a document. You can use attributeStartsWith selector or class with querySelectorAll(). Then loop through all the button to attach the event (click) individually:
//var button = document.querySelectorAll('.btn.btn-primary');
var button = document.querySelectorAll('[id^=buy-now]');
button.forEach(function(btn){
btn.addEventListener('click', function() {
console.log('class ' + this.classList);
console.log('button class? '+ this.id);
});
});
<div class="product-bg-container product-general-info variation-info">
<input type="hidden" name="sku" value="Something-15892290" id="selected-option">
<button id="buy-now" class="btn btn-lg hidden-sm-down btn-primary">
Add to Cart
</button>
<button id="buy-now2" class="btn btn-lg hidden-md-up btn-primary">
Add to Cart
</button>
</div>
nextElementSibling seems working in this case.
var btn1 = document.getElementById("btn");
var btn2 = btn1.nextElementSibling;
btn1.addEventListener("click",function(e){
console.log("btn1");
});
btn2.addEventListener("click",function(e){
console.log("btn2");
});
<div>
<button id="btn" class="btn1">butotn 1</button>
<button id="btn" class="btn2">butotn 2</button>
</div>
I'm having trouble changing a button value in bootstrap. I can change it using jQuery, but i'm changing it from a modal dialog. I looked elsewhere on SO but I couldn't find anything that seemed to match my specific issue?
Steps:
Click button. Change button text on main html form. Upon clicking the
button it changes the text, closes the modal, and then immediately
the text changes back to what it was originally. It should just change the text and stay that way, obviously.
$("#validate-rv-button").click(function () {
$("#review-history-validate").val("Review History");
});
HTML
<input id="review-history-validate" type="button" class="rvButtons btn btn-outline-warning btn-sm" data-toggle="modal" data-target="#review-history" value="Validate" />
Any help would be much appreciated.
Another way to do it with <button></button>
<button id="review-history-validate" type="button" class="rvButtons btn btn-outline-warning btn-sm" data-toggle="modal" data-target="#review-history" />Validate</button>
in jquery:
$("#validate-rv-button").click(function () {
$("#review-history-validate").text("Review History");
});
I believe you got the naming wrong.
This works:
$("#review-history-validate").click(function () {
document.getElementById("review-history-validate").value = "My value";
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="review-history-validate" type="button" class="rvButtons btn btn-outline-warning btn-sm" data-toggle="modal" data-target="#review-history" value="elo" />
Or jQuery only as your question:
$("#review-history-validate").click(function () {
$("#review-history-validate").val("My value");
});
I have a modal with a grid of buttons representing different html components. When one of the buttons is pressed, some html is supposed to be injected into the page once the modal closes. However, I'm having trouble targeting the specific column where the html is to be injected. Here's my code:
<div class="row" id="newRow">
<div class="col-md-12 column">
<button class="btn addElement" href="#" data-toggle="modal" data-target="#add-element"><i class="fa fa-plus fa-3x add-item"></i></button>
</div>
</div>
And in my js file I have some code to assign an id to the column div (since there could potentially be many columns with this addElement button) that looks like this:
...
$(this).parent().next().children().find('.column').assignId();
...
Up to this point, everything works well. I'm having no trouble getting the column a unique id (defined in my assignId() function).
As I mentioned, the addElement button gets clicked, opening a modal which is when this code is executed:
$(document).on('click', 'button.addElement', function (e) {
e.preventDefault();
$('#add-element').modal('show').draggable();
var col = $('button.addElement').parent();
// debugging in the browser verifies that the colId
// successfully stores the id attribute for the column
var colId = col.attr('id');
addElements(colId);
});
...
function addElements(colId) {
$('#insert-paragraph').on('click', function () {
var html_content = '<div class="box" data-type="paragraph">...</div>';
$("#newRow").find("#"+colId).html(html_content)
$('#add-element').modal('hide');
});
}
It's on this line: $("#newRow").find(colId).html(html_content); that I'm having the issue. My guess is that the formatting for find(...) is wrong and that I can't just insert a variable like that, but I've tried a few different things and nothing seems to be working.
Any help is very much appreciated.
Thanks!
UPDATE:
#juvian suggested writing a few of the variables' values to the console:
console.log(colId);
console.log($("#newRow")).length;
console.log($("#newRow").find("#"+colId).length);
console.log($("#newRow").find("#"+colId).html());
I logged these values twice. First, just before passing colId into the addElements function and in the addElements function immediately after $(#newRow").find("#"+colId).html(html_content); The results of those two tests are as follows:
Values prior to running addElements:
console.log(colId); = 8153-1076-641d-3840
console.log($("#newRow")).length; = Object[div#newRow.row.clearfix]
console.log($("#newRow").find("#"+colId).length); = 1
console.log($("#newRow").find("#"+colId).html()); = <button class="btn addElement"...>...</button>
Values after the insert-paragraph button is pressed:
console.log(colId); = 8153-1076-641d-3840
console.log($("#newRow")).length; = Object[div#newRow.row.clearfix]
console.log($("#newRow").find("#"+colId).length); = 1
console.log($("#newRow").find("#"+colId).html()); = <div class="box box-element" data-type="paragraph">...</div>
Interestingly enough, it appears like everything is working like I'd expect it to, however, when it's all said and done, the addElement button remains and the page still renders this:
<div id="newRow" class="row clearfix">
<div id="32aa-ab91-f50d-c3b3" class="col-md-12 column ui-sortable">
<button class="btn addElement" data-target="#add-element" data-toggle="modal" href="#">
<i class="fa fa-plus fa-3x add-item"></i>
</button>
</div>
</div>
.find as most jquery functions, takes a css selector as parametre. Unfortunately, colId is just a string, so it matches no elements (unless colId is html, span or something like that)
You are just missing adding the id selector at the beginning to do an id match:
.find("#"+colId)
I guess The parent of button is a div here which has no id.
var col = $('button.addElement').parent();
thus var colId is getting no value.give that div an id and it should be fine.
Is it possible to have a custom bootstrap popover?
I mean I want to be able to use
$('#example').popover(options)
So on click of an element #example, I'll pass some text (which would be shown in editable textarea);
I am using bootstrap 2.3.2
I dont think the links in the comments completely answers the question. Here is a 2.3.2 example, working with multiple links / elements, that passes text() from the element to a textarea on the popover, and back to the element upon "submit" :
awesome user
Use popovers template feature to customize the popover (adding buttons), set a <textarea> as content, inject the text of the link / element to the textarea on the shown event :
$("[rel=comments]").popover({
trigger : 'click',
placement : 'top',
html: 'true',
content : '<textarea class="popover-textarea"></textarea>',
template: '<div class="popover"><div class="arrow"></div>'+
'<h3 class="popover-title"></h3><div class="popover-content">'+
'</div><div class="popover-footer"><button type="button" class="btn btn-primary popover-submit">'+
'<i class="icon-ok icon-white"></i></button> '+
'<button type="button" class="btn btn-default popover-cancel">'+
'<i class="icon-remove"></i></button></div></div>'
})
.on('shown', function() {
//hide any visible comment-popover
$("[rel=comments]").not(this).popover('hide');
var $this = $(this);
//attach link text
$('.popover-textarea').val($this.text()).focus();
//close on cancel
$('.popover-cancel').click(function() {
$this.popover('hide');
});
//update link text on submit
$('.popover-submit').click(function() {
$this.text($('.popover-textarea').val());
$this.popover('hide');
});
});
see fiddle -> http://jsfiddle.net/e4zMu/ here with three editable links / elements :
In the event you want to use RAZOR or HTML actually be used as the template for the popover (rather than injecting it through the attribute in JS):
In the following example, we were building a bootstrap Breadcrumb control with a popover that contained a list of values that might be selected to change the value of a breadcrumb.
we were using razor to create the HTML TEMLPLATE for the popover-content.
This is how the popover used HTML for its 'content':
<script type='text/javascript'>
$(function () {
$('a[data-toggle="popover"]').popover({
html: true,
content: function () {
return $($(this).data('contentwrapper')).html();
}
});
});
</script>
What this did was for the content attribute, we used jquery to search for a data-contentwrapper within this breadcrumb.
We used Razor to create each breadcrumb element (using orderlist / listitem) and a div containing the proper id to be used in our data-toggle.
<ol class="breadcrumb">
#foreach (var segment in Model.Segments)
{
var selectedChild = segment.SelectedChild;
var popoverId = segment.Id + "_breadcrumb_popover";
var longCaption = segment.Caption;
var shortCaption = segment.Id;
var childType = segment.ChildType;
if (segment.SelectedChild != null)
{
shortCaption = segment.SelectedChild.Id;
}
else
{
// if the selected child is null, then we want the text to show 'select ' _grandchildType is
shortCaption = string.Format("Select {0} ?", segment.ChildType);
}
var listItemClassString = (segment.Children.Any()) ? "" : "hidden";
<!-- THIS IS THE BREADCRUMB ELEMENT -->
<li class="#listItemClassString">
<small>#childType</small>
<a href="javascript: void(0)" tabindex="0" rel="popover" data-container="body"
data-html="true" data-toggle="popover" data-placement="bottom"
data-animation="true" data-trigger="focus" title="Choose #childType" data-contentwrapper="##popoverId" >#shortCaption</a>
<i class="glyphicon glyphicon-chevron-right"></i>
</li>
<!-- THIS IS THE TEMPLATE DROPDOWNLIST FOR THe above list item -->
<div role="tooltip" title="FROM TEMPLATE" class="popover breadcrumb hidden" id="#popoverId">
<div class="arrow"></div>
#*<h3 class="popover-title"></h3>*#
<div class="popover-content" class='panel clearfix hidden' style='padding-right: 10px;'>
<ul class="list-group">
#foreach (var option in segment.Children)
{
<li class="list-group-item">
#{
var url = new UrlHelper(ViewContext.RequestContext, RouteTable.Routes).RouteUrl("DefaultWithBreadcrumb",
new
{
action = parentRouteData.Values["action"] as String,
controller = parentRouteData.Values["controller"] as String,
breadcrumbPath = option.Url
});
}
#option.Caption
</li>
<!-- class='col-md-3 col-sm-4'-->
}
#{ tabIndex++;}
</ul>
</div>
</div>
}
</ol>
Hope this helps someone who would like to combine serverside MVC with clientside bootstrap popover html content.