Angular bootstrap popover disappears when the mouse enters it - javascript

I have an angular bootstrap popover on some text. In the popover, I show some link where the user can click on that link and go to that website. Presently, when the user is trying to go inside popover it disappears.
If I try to keep the popover open on click instead of hovering, it doesn't close when I go to another popover.
I have created a jsfiddle where you can see
<div popover="{{careerAttribute.value}}"
popover-append-to-body="true"
popover-title="{{careerAttribute.title}}"
popover-trigger="mouseenter"
popover-placement="right"> HP
</div>
I should be able to click on the link displayed in hover and at a time single hover should be open.

You can do this by removing the popover-append-to-body. This way it will append it to the current element. Now instead of using the default popover-trigger, we will manually open and close the element from the parent td. For this we need to set popover-trigger to none and then use ng-mouseenter and ng-mouseleave on the parent to manually trigger the popover using popover-is-open. You will need to use an array to track the open popovers. You will also have to sanitize the URL to be shown as HTML in the popover.
Here is a working example.
angular.module('myApp', ['ngAnimate', 'ngSanitize', 'ui.bootstrap'])
.controller('myCtrl', ['$scope', '$sce', ($scope, $sce) => {
$scope.isOpen = new Array(2).fill(false);
$scope.careerAttribute = {
'title': 'Here is The Title',
'value': $sce.trustAsHtml('<a target="_blank" href="https://www.google.com">Google</a>')
};
$scope.open = (popoverId) => {
$scope.isOpen[popoverId] = true;
}
$scope.close = (popoverId) => {
$scope.isOpen[popoverId] = false;
}
}]);
[uib-popover-html] {
margin: 25px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.7.5/angular-animate.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.7.5/angular-sanitize.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.5.0.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<div ng-app="myApp" ng-controller='myCtrl'>
<table>
<thead>
<tr>
<th>Name</th>
<th>Address</th>
</tr>
</thead>
<tr>
<td ng-mouseenter="open(0)" ng-mouseleave="close(0)">
<div uib-popover-html="careerAttribute.value" popover-title="{{careerAttribute.title}}" popover-is-open="isOpen[0]" popover-trigger="'none'" popover-placement="right">
Hover for Popup
</div>
</td>
<td>India</td>
</tr>
<tr>
<td ng-mouseenter="open(1)" ng-mouseleave="close(1)">
<div uib-popover-html="careerAttribute.value" popover-title="{{careerAttribute.title}}" popover-is-open="isOpen[1]" popover-trigger="'none'" popover-placement="right">
Hover for Popup
</div>
</td>
<td>India</td>
</tr>
</table>
</div>
Note: I'm not sure why clicking the link does not open it when using the code snippets on StackOverflow (it works on other online code editors) but you can right-click and open in a new tab to see that it works. This is clearly an issue with the snippets itself as even using the link in the HTML directly does not open the link.

Related

JavaScript doesn't work in Thymeleaf and Spring Boot [duplicate]

JavaScript doesn't work in thymeleaf.
In Spring Boot Thymeleaf, first thing can open modal. But second, third ... things can not open modal.
Every thing has className, but only first thing can open modal.
I think JavaScript works only the first thing, and doesn't work other things.
<tr th:each="board, i : ${boards}">
<th scope="row" th:text="${i.count}">1</th>
<td>
<p class="show" th:text="${board.title}">Title</p>
<div class="modal"> .... </modal>
</td>
<td th:text="${board.writer}">Son</td>
<td th:text="${board.createDate}">2022-02-01</td></p>
</tr>
js
function show() {
document.querySelector(".background").className = "background show";
}
function close() {
document.querySelector(".background").className = "background";
}
document.querySelector(".show").addEventListener("click", show);
document.querySelector(".close").addEventListener("click", close);
please help me
With your code you are only adding event listener to the first element of the class ".show". You should be adding event listeners to all members of the class. The following code should do the work:
document.querySelectorAll('.show').forEach(item => {
item.addEventListener('click', show);
})

adding a popup during a mouseover event for a dynamically generated table

Relatively new to javascript and jquery and I have a couple of questions on event listeners in jquery.
So I have an HTML form that dynamically generates a table.
The objective is to create an event such that when I hover over a certain cell, a popup will appear next to it.
I tried this:
HTML - The tag the JS is connected to
let td_inter = document.createElement('td')
td_inter.innerHTML = "test"
td_inter.classList = 'popover'
td_inter.setAttribute('data-html', 'test')
td_inter.setAttribute('data-position',"bottom left")
td_inter.setAttribute('data-variation',"very wide")
JS
$(document).on("mouseover", 'td.popover', function() {
$('td.popover')
.popup({
on: 'hover',
});
})
The reason why I tried this is that I have a previous static div above with the following code that worked.
HTML - The tag the JS is connected to
<div class='thirteen wide field'>
<div class='desc' id='test_desc' data-html="" data-position="bottom left" data-variation="very wide">
<label for="test">test label</label>
</div>
</div>
JS
$('div.desc')
.popup({
on: 'hover',
});
I realize I needed to use the .on to make it work for the dynamically generated table, but it seems not to be working. The event seems to work when I hover (I tried just to console.log) but I cant get the popup to show. Do I have to place it in a div?
additional background:
I am using semantic ui if that helps.
I also included these resources if this helps:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.js"></script>
can you just try below code in JS instead of using document.mouseover:
$('td.popover')
.popup({
on: 'hover',
});
To all those interested, I had to restructure my dynamic table to generate it into something like this:
HTML:
<table class="ui table">
<thead>
<tr>
<th class="one wide">Key</th>
<th class="two wide">Value</th>
</tr>
</thead>
<tbody>
<tr class="popover">
<td>1</td>
<td>Foo</td>
</tr>
<div class="ui popup mini transition hidden">Foo Longer</div>
</tbody>
</table>
JS:
$(document).on('mouseover', '.popover', function() {
$(this)
.popup({
popup: $('div.popup'),
inline:true,
on:'hover',
position: 'right center',
lastResort: 'right center',
}).popup('show');
});
div.popup is set to hidden and will become visible once the event is satisfied (mouseover in this case).
sample: https://jsfiddle.net/gr0e4cwt/11/

jQuery accordion menu, CSS HTML

what im trying to achieve is the following.
I have an accordion menu. Now I want to Build an accordion Menu(I call this now Top) inside an accordion Menu(I call this now Bottom).
Im doing this, to present loads of data from a database in a clean way.
Now im trying to adapt the accordion menu that I already got on this.
The data of both, top and bottom, are presented in tables. So first i builded tables inside tables.
If the users clicks on the first Element of each row, the “bottom” menu with the table should slide down.
HTML
<!-- 2016 -->
<div id="sh_details">
<div class="sh_wasserzeichen"></div>
<article>
<dl id="sh_accordion">
<dt id="sh_2016">Headline1</dt>
<dd><table>
<tr>
<th>Überschrift1</th>
<th>Überschrift2</th>
</tr>
<tr>
<td class="inhalt">Inhalt1</td>
<td>Inhalt2</td>
</tr>
<!-- Untertabelle1_1 -->
<td>
<table class="table2">
<tr>
<th>Sub_Überschrift1</th>
<th>Sub_Überschrift2</th>
</tr>
<tr>
<td>Sub_Inhalt1</td>
<td>Sub_Inhalt2</td>
</tr>
</table>
</td>
<tr>
<td class="inhalt">Inhalt3</td>
<td>Inhalt4</td>
</tr>
<!-- Untertabelle1_2 -->
<td>
<table class="table2">
<tr>
<th>Sub_Überschrift3</th>
<th>Sub_Überschrift4</th>
</tr>
<tr>
<td>Sub_Inhalt3</td>
<td>Sub_Inhalt4</td>
</tr>
</table>
</td>
</table></dd>
<dt id="sh_january">Headline2</dt>
<dd>125153226262</dd>
</dl>
</article>
</div>
CSS
/***************************************
************ Details *****************/
#sh_details {background-color:#fff;position: relative; top:0;left:0;width:100%; height: 100%; overflow:hidden;display:none;flex-direction: column;}
.table2 {display:none;}
/***************************************
************ Accordion *****************/
.sh_active {background-color:#ff6600; color:white;padding:0.7%; font-size:13px;}
article {position:absolute;color: black;width: 90%; height: auto;margin: 0 auto 0 auto;padding-top:75px;padding-left:75px;}
dt, dd {padding:0.5%;width: 50%; height:auto;float: left; margin:0;border-top:1px solid #222;}
dt {font-weight:bold;text-transform: uppercase; background-color:black; color:#ff6600; cursor:pointer;}
dt:first-child {border:none;}
dt:hover {background-color:#ff6600; color:white;padding:0.7%; font-size:13px;}
dd {background-color:#444; line-height:25px; word-spacing:3px;color:#999; display:none;}
**jQuery (only the accordion stuff) **
/*SUBTABLE*/ <<<---- not working
$(document).on('click', 'td', function (event) {
if($(this).hasClass('inhalt')) {
$(this).next('.table2').removeClass('table2');}
event.stopPropagation();
});
$('#sh_accordion dt').stop().click(function(){
<--- Working
if($(this).hasClass('sh_active')) {
$(this).removeClass('sh_active');
$(this).next().slideUp(300);
} else {
$(this).parent().children().removeClass('sh_active');
$(this).addClass('sh_active');
if($(this).next().is('dd')) {
$(this).parent().children('dd').slideUp(300);
$(this).next().slideDown(300);
}
}
});
https://jsfiddle.net/u4y2o270/1/ (dont know why the code is not working, i disabled the display:none's beacause of this)
So every "Sub..." Menu should be hidden by default. If i click on "Inhalt1", the first "bottom" menu should appear and so on.
Hide and Show the top Menu works fine (Headline1, Headline2), but not the bottom menu (table inside table)
Example: Default is this:
Headline1
Überschrift1 Überschrift2
Inhalt1 Inhalt2
Inhalt3 Inhalt4
User clicks "Inhalt1":
Headline1
Überschrift1 Überschrift2
Inhalt1 Inhalt2
Sub_Überschrift1 Sub_Überschrift2
Sub_Inhalt1 Sub_Inhalt2
Inhalt3 Inhalt4
//EDIT:
Start:
Everything is hidden, besides the Headlines (Headline1, Headline2) (this is already working, but not in the fiddle)+
It looks like this:
Headline1
Headline2
User is clicking on Headline1,
The user can only see the following:
Headline1
Überschrift1 Überschrift2
Inhalt1 Inhalt2
Inhalt3 Inhalt4
Headline2
The user is now clicking on "Inhalt1"
The user now sees this the following:
Headline1
Überschrift1 Überschrift2
Inhalt1 Inhalt2
Sub_Überschrift1 Sub_Überschrift2
Sub_Inhalt1_1 Inhalt2_2
Inhalt3 Inhalt4
Headline2
//EDIT2:
Updated the fiddle http://jsfiddle.net/u4y2o270/7/
This is what is working so far.
If the user is now under Headline1 clicking Inhalt1 the table under it should slideDown // should be showed, the table has the class .table2 which is by default on display:none to be hidden. My idea was, to find the next Item with class table2 and remove the class or slide it down. But its not working.
Same obv. for Inhalt3

Table expand & collapse not working in angular js

Below is the tabular structure for expand & collapse, i have done using table. Now i have used the below script for collapse & expand. But sometime i succeeded in expand & sometime don't.
What i did, when i got response from the api, i call this function :
$timeout(function (){
$scope.initExpandCollapse();
},1000);
$scope.initExpandCollapse = function () {
angular.element(document).on("click", ".table_exp", function(){
var TBODY = angular.element(this).parents(3);
if(TBODY.hasClass("open")){
TBODY.children("tr.expand-table-row").hide();
TBODY.removeClass("open");
return false;
}
TBODY.addClass("open");
TBODY.children("tr.expand-table-row").show();
});
}
If you guys, can help me out for this problem . Thanks.
CSS:
tr.expand-table-row {
display: none;
}
tr.expand-table-row.open {
display: initial;
}
Angular
$scope.expandCollapse = function expandCollapse (item) {
item.open = !item.open
}
HTML
<table>
<tbody>
<tr ng-repeat="item in items track by $index"">
<td ng-click="expandCollapse(item)">++++</td>
<td>
<table>
<tr ng-class="{'open': item.open}" class="expand-table-row open">
<td>{{item.name}}</td>
<td ng-repeat="data in item.options">{{data.name}}</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
You need nested tables so the click marker does not simply vanish with the rest, apart from that the salient point is the ng-class="{'open': item.open}" espression that sets the class open if the property open on item is set.
Try to use window.onload instead of $timeout, or add you script to the end of body tag.

Angular UI Popover close button

I've read Angular UI Bootstrap adding a close button and show hidden div on ng-click within ng-repeat. I'd like to use the solution from the latter article and apply it to the problem stated in the first article. In essence, I want to be able to close an Angular UI Bootstrap popover with ng-show or ng-click.
I have an example piece of code to illustrate this. This code just applies a CSS class to a particular element whenever it is clicked, and removes it when it is clicked again:
<div ng-class="{'gray-inset-border': style}">
<div ng-click="style=!style"></div>
</div>
Whenever an element containing a popover is clicked, a popover template is created. In the Chrome DOM inspector, the opening tag looks like this:
<div class="popover ng-isolate-scope right fade in"
tooltip-animation-class="fade" tooltip-classes=""
ng-class="{ in: isOpen() }" popover-template-popup="" title=""
content-exp="contentExp()" placement="right" popup-class="" animation="animation"
is-open="isOpen" origin-scope="origScope"
style="top: 317.5px; left: 541.8125px; display: block;">
Notice the ng-class="{in: isOpen()}". I am assuming that this controls whether the popover is open or not, and want to use the same ng-click method as in the example above, and apply it to a button within the popover. However, when I tried that, it didn't work. I also can't find the popover template anywhere in the ui-bootstrap-tpls.js code. As far as I know, popover creation is voodoo magic.
It's also frustrating that Angular UI Bootstrap doesn't have this functionality already. I've been trying to solve this problem off and on for over a week now, and every "solution" I have seen doesn't seem to work for me.
Am I understanding the ng-class="{in: isOpen()}" correctly? Where do I edit the popover template to add a close button?
This was solved by #ognus on a GitHub thread.
He stated:
I've found that using a simple custom directive worked best for my use case. I just want to be able to close the popover from within the popover template.
The directive exposes scope.toggle method that user custom trigger to open and close popover. I'm then using this method in the popover template.
There is a plnkr that I adapted to test my own issue. The solution involved creating a directive (of course).
HTML
<!DOCTYPE html>
<html ng-app="main">
<head>
<script data-require="angular.js#1.x" data-semver="1.4.1" src="https://code.angularjs.org/1.4.1/angular.js"></script>
<script data-require="ui-bootstrap#0.13.0" data-semver="0.13.0" src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.13.0.min.js"></script>
<link data-require="bootstrap-css#*" data-semver="3.3.1" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
<script src="popoverToggle.js"></script>
<script src="script.js"></script>
</head>
<body style="margin: 50px">
<!-- Show popover link -->
<a
href=""
popover-placement="bottom"
popover-trigger="open"
popover="Lorem ipsum dolor sit amet, consectetur."
popover-title="This is a title"
popover-toggle>
Show popover</a>
<div popover-placement="bottom" popover-trigger="open"
popover-template="'popover-template.html'" popover-toggle>Show Popover 2</div>
</body>
</html>
popoverToggle directive
angular.module('main')
.config(function($tooltipProvider) {
$tooltipProvider.setTriggers({'open': 'close'});
})
.directive('popoverToggle', function($timeout) {
return {
scope: true,
link: function(scope, element, attrs) {
scope.toggle = function() {
$timeout(function() {
element.triggerHandler(scope.openned ? 'close' : 'open');
scope.openned = !scope.openned;
});
};
return element.on('click', scope.toggle);
}
};
});
Popover template
<p>Are you sure you want to remove this item?</p>
<a href='' ng-click='remove(item)'>Yes</a>
<div ng-click='toggle()'>No</div>
app = angular.module('ui.bootstrap.demo', ['ui.bootstrap']);
app.controller(
'dataCtrl', function() {
var self = this;
self.data = [
{name: "one", num: 23},
{name: "two", num: 87},
{name: "three", num: 283}
]
return self;
}
)
app.controller(
'myPopoverCtrl', ['$scope',
function($scope) {
// query popover
$scope.myPopover = {
isOpen: false,
templateUrl: 'myPopoverTemplate.html',
open: function open( value ) {
$scope.myPopover.isOpen = true;
$scope.myPopover.data = "(" + value.num + ")";
},
close: function close() {
$scope.myPopover.isOpen = false;
}
};
}
]);
<body ng-app="ui.bootstrap.demo" class='container'>
<div ng-controller='dataCtrl as dc' >
<li ng-repeat="d in dc.data">
{{d.name}}
<a ng-controller="myPopoverCtrl"
popover-template="myPopover.templateUrl"
popover-title="This is a popover"
popover-placement="right"
popover-is-open="myPopover.isOpen"
ng-click="myPopover.open(d)">
pop
</a>
</li>
</div>
<script
type="text/ng-template"
id="myPopoverTemplate.html">
<h2 ng-bind="myPopover.data"/>
<button
class="btn btn-success"
ng-click="myPopover.close()">Close me!</button>
</script>
</body>
Link to the working example
This is solution using another controller for the popover.
this controller opens and closes the popover.
you can also write the directive instead of controller.
Its works fine if data is in repeat.

Categories

Resources