Popover not showing on first click for dynamically generated content - javascript

I'm trying to get a popover for my webpage. It doesn't work for me on the first click but however works fine thereafter. I realize that it gets instantiated on the first click and therefore doesn't show up. Is there a better way to instantiate it, given that I'm using id's that are generated at runtime. I have looked at similar questions but they don't seem to work for me. Here is the code I have written,
<table id="userInfo">
<thead>
<tr>
<th>UserGroup</th>
</tr>
</thead>
<tbody>
<% #userdetails.each do |user| %>
<tr>
<td>
<a class='user_show_more' data-placement='left' id='<%= user %>'>[+]</a>
<!-- popover table starts here -->
<div id="<%= user %>_popover" style="display: none">
<table>
<thead>
<tr>
<th>UserNames</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<%= user['name'] %>
</td>
</tr>
</tbody>
</table>
</div>
<!-- popover ends here -->
<% user['group'] %>
</td>
</tr>
<% end %>
</tbody>
</table>
And my javascript code looks like this,
$('.user_show_more').on('click', function (e) {
var $this = $(this)
var popover_id = '#'+$this.attr("id");
$(popover_id).popover({
html : true,
content: function() {
var popover = '#'+$this.attr("id")+'_popover';
return $(popover).html();
}
});
});

You can add two click handlers to your popovers. The first one uses 'one' and the second one uses 'on'.
https://jsbin.com/kegovebufu/1/edit?html,js,console,output
HTML
<button type="button"
class="btn btn-lg btn-danger"
data-toggle="popover"
id="Temp"
>Stuff</button>
<script type="text/html" id="Temp_popover">
<div>
<table>
<thead>
<tr>
<th>UserNames</th>
</tr>
</thead>
<tbody>
<tr>
<td>blah</td>
</tr>
</tbody>
</table>
</div>
</script>
Javascript
function PopoverClick()
{
$(this).popover('toggle');
}
$('[data-toggle="popover"]').one('click',function(e){
console.log('once');
var _this = $(this);
_this.popover(
{
html:true,
content: function()
{
return $('#'+$(this).attr("id")+'_popover').html();
},
trigger: 'manual',
placement:'right'
}).popover('show');
_this.on('click',PopoverClick);
});

Related

display table or html SweetAlert 2.0

I am using SweetAlert2.0, This One
<script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
it is working fine, but now I want to display table or div or HTML element in this sweet alert.
var swal_html='<div class="panel" style="background:aliceblue;font-weight:bold"><div class="panel-heading panel-info text-center btn-info"> <b>Import Status</b> </div> <div class="panel-body"><div class="text-center"><b><p style="font-weight:bold">Total number of not inserted rows : add data</p><p style="font-weight:bold">Row numbers:Add data</p></b></div></div></div>';
swal({title:"Good Job!", content: swal_html, icon: "success"});
I have tried the above code just for testing, but it's not working.
I have read the documentation of this sweet alert that says, use code mentioned below.
swal("Write something here:", {
content: "input",
})
.then((value) => {
swal(`You typed: ${value}`);
});
but I want to display table div etc.where should I write my code?
I think problem on your version. Include the latest version from CDN here:
<script src="https://unpkg.com/sweetalert2#7.19.3/dist/sweetalert2.all.js"></script>
Also put HTML as a html: property not content, like following:
var swal_html = '<div class="panel" style="background:aliceblue;font-weight:bold"><div class="panel-heading panel-info text-center btn-info"> <b>Import Status</b> </div> <div class="panel-body"><div class="text-center"><b><p style="font-weight:bold">Total number of not inserted rows : add data</p><p style="font-weight:bold">Row numbers:Add data</p></b></div></div></div>';
swal({title:"Good Job!", html: swal_html});
try this
swal({
html: `<table id="table" border=1>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Salary</th>
<th>Country</th>
<th>City</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Dakota Rice</td>
<td>$36,738</td>
<td>Niger</td>
<td>Oud-Turnhout</td>
</tr>
<tr>
<td>2</td>
<td>Minerva Hooper</td>
<td>$23,789</td>
<td>CuraƧao</td>
<td>Sinaai-Waas</td>
</tr>
<tr>
<td>3</td>
<td>Sage Rodriguez</td>
<td>$56,142</td>
<td>Netherlands</td>
<td>Baileux</td>
</tr>
<tr>
<td>4</td>
<td>Philip Chaney</td>
<td>$38,735</td>
<td>Korea, South</td>
<td>Overland Park</td>
</tr>
</tbody>
</table>`
})

Change table header with response to button click ,where rows update using JSTL for loop

<div class="btn-group" >
<button type="submit" onclick="display">DISPLAY SCHEDULE</button>
<button type="submit" onclick="open" >OPEN SCHEDULE</button>
</div>
<table class="table table-striped responsive">
<!-- column headers -->
<% Result result = (Result)request.getAttribute("result");%>
<thead>
<tr>
<th id="change"> Transfer Switch </th>
</tr>
</thead>
<!-- column data -->
<tbody>
<c:forEach var="row" items="${result.rows}">
<tr>
<td>
<c:out value="${row.Schedule_ID}"/>
</td>
</tr>
</c:forEach>
</tbody>
</table>
I am trying to change my table header name with button click, so what i did was added a simple java script as follows.
<script>
function display(){
document.getElementById("change").innerHTML="display"
}
function open(){
document.getElementById("change").innerHTML="open"
}
</script>
but since my JSTL result row gets updated for every loop my header changed too thus ending myself with the same header Transfer switch.
Can i solve this using Jquery on load ??, not sure how to use it.
I heard of solutions to make 2 tables but that's not the solution i am looking for since the table is responsive uses bootstrap and also has some buttons in its rows .
Two things I have changed from your code, now it looks fine,
Don't use the JS reserved keyword(s) like open. Use openSchedule() instead.
For better practice, Use span tag for change the text instead of giving id to th.
Your HTML with rendered table rows (Assume I could not able to reproduce jsp values here.)
<div class="btn-group" >
<button type="button" onclick="displaySchedule()">DISPLAY SCHEDULE</button>
<button type="button" onclick="openSchedule()" >OPEN SCHEDULE</button>
</div>
<table class="table table-striped responsive">
<thead>
<tr>
<th><span id="change">Transfer Switch</span></th>
</tr>
</thead>
<tbody>
<!-- Here I assumed two rows, since It's JSP value I couldn't reproduce -->
<tr>
<td>Text1</td>
</tr>
<tr>
<td>Text2</td>
</tr>
</tbody>
</table>
Your Script,
window.displaySchedule = function(){
document.getElementById("change").innerHTML="display";
}
window.openSchedule = function(){
document.getElementById("change").innerHTML="open";
}
See fiddled demo here for live sample.

jsViews - re-evaluate 'if' tag on root property change

I have created a table/grid using jsViews. Each row has an edit button which when clicked selects the row and shows input controls instead of text values.
If I show/hide the inputs using data-link="visible{:#parent.parent.data.selectedIndex!==#index}" then it works fine.
However, I was trying a different approach using {^{if #parent.parent.data.selectedIndex===#index}}...{{else}}...{{/if}} to show/hide the inputs and this doesn't work when selectedIndex changes on my data object.
I also tried with {^{if ~root.selectedIndex===#index}} but that didn't work either. Is it possible to do this with {{if}}? The reason I am trying this over the first method that worked was to avoid rendering lots of select boxes which will just be hidden anyway.
My data object looks like this:
app = {
data: [...],
selectedIndex: null,
select: function select(index) {
if (this.selectedIndex !== index) {
$.observable(this).setProperty("selectedIndex", index);
}
}
};
I link the template like this:
$.templates("#myTemplate").link("#divHolder", app)
.on("click", ".data .editButton", function() {
app.select($.view(this).index);
})
.on("click", ".data .saveButton", function() {
// save details
})
.on("click", ".transmittals .cancelButton", function() {
// reset values
app.select(null);
});
My template is like this:
<script id="myTemplate" type="text/x-jsrender">
<table id="tblData" class="data">
<thead>
<tr>
<th></th>
<th>A</th>
<th>B</th>
<th>C</th>
</tr>
</thead>
<tbody>
{^{for data}}
<tr class="item">
<td>
{{if #parent.parent.data.selectedIndex===#index}}
<span class="editItem">
<button class="cancelButton">Cancel</button></span>
{{else}}
<span class="viewItem">
<button class="editButton">Edit</button></span>
{{/if}}
</td>
<td>
{^{if #parent.parent.data.selectedIndex===#index}}
<span class="editItem"><input type="text" data-link="B" /></span>
{{else}}
<span class="viewItem" data-link="B"></span>
{{/if}}
</td>
<td>
{^{if #parent.parent.data.selectedIndex===#index}}
<span class="editItem"><input type="text" data-link="C" /></span>
{{else}}
<span class="viewItem" data-link="C"></span>
{{/if}}
</td>
</tr>
{{/for}}
</tbody>
</table>
</script>
When you add an {{if}} block, it is a nested view, so the button click is not getting you the item view with the index. You need to use $.view(this).parent.index - or, simpler, $.view(this).getIndex() - which automatically steps up through nested views (if any) to the item view and gets its index.
app.select($.view(this).getIndex());
(See discussion here: https://github.com/BorisMoore/jsrender/issues/173#issuecomment-11058106)
BTW here is a modified form of your sample, just to give you some ideas. It uses <button data-link="{on ~root.select #getIndex()}">Edit</button> to hook up the click handler on the button and call the select method directly, passing it the index:
<script id="myTemplate" type="text/x-jsrender">
<table id="tblData" class="data">
<thead>
...
</thead>
<tbody>
{^{for data}}
<tr class="item">
{^{if ~root.selectedIndex===#index}}
<td><button class="cancelButton" data-link="{on ~root.select null}">Cancel</button></td>
<td><input data-link="A" /></td>
<td><input data-link="B" /></td>
{{else}}
<td><button class="editButton" data-link="{on ~root.select #getIndex()}">Edit</button></td>
<td data-link="A"></td>
<td data-link="B"></td>
{{/if}}
</tr>
{{/for}}
</tbody>
</table>
</script>
<div id="divHolder"></div>
<script>
var app = {
data: [{A:"aa", B: "bb"},{A:"aa2", B: "bb2"}],
selectedIndex: null,
select: function(index) {
if (this.selectedIndex !== index) {
$.observable(this).setProperty("selectedIndex", index);
}
}
};
$.templates("#myTemplate").link("#divHolder", app);
</script>

setting viewmodel property to be an item from a list

ok so i have my view model
function viewModel(calendarData) {
var self = this;
self.Calendars = ko.mapping.fromJS(calendarData);
self.ViewedCalendar = {};//what can/should i set this to be on initial creation?
self.DisplayCalendar = function (calendar) {
self.ViewedCalendar = calendar;
};
};
I then have my html:
<div data-bind="visible: Calendars().length > 0">
<h2>You have <span data-bind="text: Calendars().length"></span> calendars</h2>
<table class="table">
<thead>
<tr>
<th>Calendars</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody data-bind="foreach: Calendars">
<tr>
<td data-bind="text: Name"></td>
<td><span data-bind="text: Events().length"></span> events</td>
<td><a href='#' data-bind='click: $root.DisplayCalendar'>View</a></td>
</tr>
</tbody>
</table>
</div>
<div data-bind="visible: ViewedCalendar() !== null">
Your are viewing <span data-bind="text: ViewedCalendar.Name"></span><br />
</div>
What I am trying to achieve is when the user clicks View for a given calendar, that via DisplayCalendar() I set the property ViewedCalendar to be set to the given calendar.
This then shows my div that contains the label stating what calendar is being viewed.
This is all rough code at the minute just to get the basic functionality in place but I'm new to knockout so could use some help.
I'm getting TypeError: ViewedCalendar is not a function or ViewedCalendar is undefined.
Any help would be much appreciated.
The ViewedCalendar property needs to be an observable for knockout to reach to changes in it's value. You defined it like this:
self.ViewedCalendar = {};
Which is an (empty) object literal and not a function (as the error message correctly stated). What you need is:
self.ViewedCalendar = ko.observable(); // empty () give you an empty observable - no calendar selected yet
And then you can update it in your click handler with:
self.ViewedCalendar(calendar);
Here's a working full example:
function viewModel(calendarData) {
var self = this;
self.Calendars = ko.mapping.fromJS(calendarData);
self.ViewedCalendar = ko.observable();
self.DisplayCalendar = function (calendar) {
self.ViewedCalendar(calendar);
};
};
ko.applyBindings(new viewModel([{Name:'some calendar', Events: []}, {Name:'another calendar', Events: []}]));
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<div data-bind="visible: Calendars().length > 0">
<h2>You have <span data-bind="text: Calendars().length"></span> calendars</h2>
<table class="table">
<thead>
<tr>
<th>Calendars</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody data-bind="foreach: Calendars">
<tr>
<td data-bind="text: Name"></td>
<td><span data-bind="text: Events().length"></span> events</td>
<td><a href='#' data-bind='click: $root.DisplayCalendar'>View</a></td>
</tr>
</tbody>
</table>
</div>
<div data-bind="with: ViewedCalendar">
Your are viewing <span style="font-weight: bold" data-bind="text: Name"></span><br />
</div>

Adding multiple attributes to Javascript/Jquery

I'm currently working on a set of tables and i've gotten them to expand and contract at the click of a button. I'm having problems however to create a button that expands all the tables at the same time. Please see my code.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head> <!--this first part is easy to implement-->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$(".toggler").click(function(e){
e.preventDefault();
$('.vis'+$(this).attr('vistoggle')).toggle();
});
});
</script>
</head>
<body>
Expand all <!--vistoggle needs to have values 1 and 2 in it-->
<table>
<tr>
<td>safeaef</td>
<td>asdfaef</td>
<td>asfead</td>
<td>Expand</td>
</tr>
<tr class="vis1" style="display:none">
<td>asdfae</td>
<td>zxcvry</td>
<td>rteyertr</td>
<td></td>
</tr>
<tr class='vis1' style='display:none'>
<td>tsersg</td>
<td>sdgfs</td>
<td>wregssdf</td>
<td></td>
</tr>
<tr class="vis1" style="display:none">
<td>sdfgrs</td>
<td>sgdfgsr</td>
<td>Cewret</td>
<td></td>
</tr>
</table>
<table>
<tr>
<td>cfasdfas</td>
<td>1adfaed</td>
<td>asdfasdfea</td>
<td>Expand</td>
</tr>
<tr class="vis2" style="display:none">
<td>asdfaefas</td>
<td>1asdf</td>
<td>Cisdfae</td>
<td>22fasdew</td>
</tr>
<tr class="vis2" style="display:none">
<td>asdfaef</td>
<td>1sefa0</td>
<td>Ciasdf 2</td>
<td></td>
</tr>
</table>
</body>
</html>
You could try building a selector like this:
$('tr[class^="vis"]')
it would select all elements, which class attributes begins with 'vis'.
But from what I see you want the first row to always stay visible, so I would propose to simply separate the table header and it's body like this:
<table>
<thead><tr>...</tr></thead>
<tbody id="table-one" class="vis">
<tr>...</tr>
<tr>...</tr>
</tbody>
</table>
<table>
<thead><tr>...</tr></thead>
<tbody id="table-two" class="vis">
<tr>...</tr>
<tr>...</tr>
</tbody>
</table>
and then you could use a simple:
$('tbody.vis').toggle();
to toggle all the tables, and for toggle`ing just one of them you can use:
$('tbody#tbody-one').toggle();
which is probably much better idea for performance reasons (ID is found much faster than classes).
The ID attribute of TBODY can be stored just like you store it right now (in a button's attribute).
Fiddle example:
http://jsfiddle.net/SL4UZ/3/
Edit
To make your HTML valid, you should use data-attributes or bind your events using javascript instead of simply adding customs attributes inside your button tags. For example:
<button data-toggle-id="tbody-one">Toggle</button>
I updated my fiddle.
You can check the attr that needs to be toggled and if it matches all open 1 and 2, this works if your table is not dynamic
Expand all
$(document).ready(function(){
$(".toggler").click(function(e){
e.preventDefault();
if($(this).attr('vistoggle') == "all"){
$('.vis1').toggle();
$('.vis2').toggle();
}else{
$('.vis'+$(this).attr('vistoggle')).toggle();
}
});
});
Fiddle : http://jsfiddle.net/6hpbq/
Separate your classes eg vis1 becomes vis one (two classes) Then do a conditional check on the value of the data attribute. If its set to all, toggle all elements with the class vis, else toggle the specific ones:
<script>
$(document).ready(function(){
$(".toggler").click(function(e){
e.preventDefault();
var vistog = $(this).attr('vistoggle');
if(vistog == 'all'){
$('.vis').toggle();
}else{
$('.vis.' + vistog).toggle();
}
});
});
</script>
</head>
<body>
Expand all <!--vistoggle set to all -->
<table>
<tr>
<td>safeaef</td>
<td>asdfaef</td>
<td>asfead</td>
<td>Expand</td>
</tr>
<tr class="vis one" style="display:none">
<td>asdfae</td>
<td>zxcvry</td>
<td>rteyertr</td>
<td></td>
</tr>
<tr class='vis one' style='display:none'>
<td>tsersg</td>
<td>sdgfs</td>
<td>wregssdf</td>
<td></td>
</tr>
<tr class="vis one" style="display:none">
<td>sdfgrs</td>
<td>sgdfgsr</td>
<td>Cewret</td>
<td></td>
</tr>
</table>
<table>
<tr>
<td>cfasdfas</td>
<td>1adfaed</td>
<td>asdfasdfea</td>
<td>Expand</td>
</tr>
<tr class="vis two" style="display:none">
<td>asdfaefas</td>
<td>1asdf</td>
<td>Cisdfae</td>
<td>22fasdew</td>
</tr>
<tr class="vis two" style="display:none">
<td>asdfaef</td>
<td>1sefa0</td>
<td>Ciasdf 2</td>
<td></td>
</tr>
</table>
</body>
</html>

Categories