Triggering multiple popups generated by loop - javascript

I want to display an alert message inside a loop fetching records from the database. The problem is, the popup only works for one item and the other item shows no popup.
What's going wrong?
PHP:
$query = "SELECT * FROM discount
WHERE consecutivedays <= DATEDIFF('$date2','$date1')
AND idbeach = '$idbeach'
ORDER BY consecutivedays desc
LIMIT 1";
$results = mysqli_query($conn, $query);
while($row = $results->fetch_assoc()){
$reserved= $row['discountperc'];
if ($reserved=="yes") {
$getbooking = new WA_MySQLi_RS("getbooking",$sis,1);
$getbooking->setQuery("SELECT `name`,
CONCAT(`datein`,' - ',`dateout`) AS dates,
price,discount,comment
FROM booking
where idseatbeach = '$idseatbeach'
order by datein limit 1");
$getbooking->execute();
$name=$getbooking->getColumnVal("name");
$dates=$getbooking->getColumnVal("dates");
$price=$getbooking->getColumnVal("price");
$discount=$getbooking->getColumnVal("discount");
$comment=$getbooking->getColumnVal("comment");
$message = "Booked by: $name\n
Date range: $dates\n
Price :$price\n
Discount :$discount\n
Comment :$comment";
?>
<div class="item" >
<div class="popup" onclick="myFunction()">
<span class="popuptext" id="myPopup"><?php echo $message;?></span>
<img src="images/umbrelladisactive.png" width="35" height="35"
alt="<?php echo $nameseat; ?> "/>
<p style="margin-right: 0px; color: blue;">Currently Booked</p>
</div>
</div>
<?php
}
}
JavaScript:
var stile = "top=10, left=10, width=450, height=350,
status=no, menubar=no, toolbar=no scrollbars=no";
function myFunction() {
var popup = document.getElementById("myPopup");
popup.classList.toggle("show");
}
CSS:
.item {
width: 100px;
text-align: center;
display: block;
background-color: transparent;
border: 1px solid transparent;
margin-right: 10px;
margin-bottom: 1px;
float: left;
}
#index-gallery {
width: 50px;
}
/* Popup container */
.popup {
position: relative;
display: inline-block;
cursor: pointer;
}
/* The actual popup (appears on top) */
.popup .popuptext {
visibility: hidden;
width: 160px;
background-color: #555;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 8px 0;
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -80px;
}
/* Popup arrow */
.popup .popuptext::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: #555 transparent transparent transparent;
}
/* Toggle this class when clicking on the popup container (hide and show the popup) */
.popup .show {
visibility: visible;
-webkit-animation: fadeIn 1s;
animation: fadeIn 1s
}
/* Add animation (fade in the popup) */
#-webkit-keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}

An ID in HTML must be unique to the document, meaning that you can't repeat it in a loop. I recommend using a class instead, so it can be repeated.
You'll need to popup the element that's associated with (nested inside) whichever element was clicked. I recommend adding an event listener to each .popop that will fire a handler function upon click. The function should find the popup text within the clicked element by using querySelector and toggle its "show" class.
Here's an rudimentary example:
// define a function to show a popup's popuptext.
function popItUp() {
this.querySelector('.popuptext').classList.toggle("show");
}
// define all popup elements.
let popups = document.querySelectorAll('.popup');
// add listener to each popup element, which binds handler function to click event.
popups.forEach(
popup => popup.addEventListener('click', popItUp)
);
/*
// The arrow function above is equivalent to:
popups.forEach(function(popup){
popup.addEventListener('click', popItUp);
});
*/
.item {
width: 100px;
text-align: center;
display: block;
background-color: transparent;
border: 1px solid transparent;
margin: 80px 0 0 50px;
float: left;
}
.popup {
position: relative;
cursor: pointer;
}
.popup .popuptext {
visibility: hidden;
width: 160px;
background-color: #555;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 8px 0;
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -80px;
}
.popup .popuptext::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: #555 transparent transparent transparent;
}
.popuptext.show {
visibility: visible;
-webkit-animation: fadeIn 1s;
animation: fadeIn 1s
}
#-webkit-keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
<div class="item">
<div class="popup">
<span class="popuptext">Popup Message 1</span>
<p>Currently Booked</p>
</div>
</div>
<div class="item">
<div class="popup">
<span class="popuptext">Popup Message 2</span>
<p>Currently Booked</p>
</div>
</div>
<div class="item">
<div class="popup">
<span class="popuptext">Popup Message 3</span>
<p>Currently Booked</p>
</div>
</div>
There are likely some other layout issues with the CSS, but this might give you an idea of the JavaScript implementation.
For reference:
The id global attribute defines an identifier (ID) which must be unique in the whole document.
The Document method querySelectorAll() returns a static (not live) NodeList representing a list of the document's elements that match the specified group of selectors.
The EventTarget method addEventListener() sets up a function that will be called whenever the specified event is delivered to the target.
The querySelector() method of the Element interface returns the first element that is a descendant of the element on which it is invoked that matches the specified group of selectors.
Incidentally, I also notice that your query includes LIMIT 1, so the while loop will not iterate more than once. You may want to remove (or increase) that limit:
$query = "SELECT * FROM discount
WHERE consecutivedays <= DATEDIFF('$date2','$date1')
AND idbeach = '$idbeach'
ORDER BY consecutivedays desc;";

In HTML, the id attribute was designed to be unique in a document. document.getElementById() will always only return one element.
One way to solve your problem is to give each popup a unique id, and pass this id on to myFunction() so it knows which popup to display (I've removed all the in-between lines of code for the sake of brevity).
I assume your database records have some unique identifier along with name, dates, price, discount and column but since you haven't selected it in your current code I don't know for sure. If it doesn't, one alternative is to keep track of a unique counter yourself, such as $id here:
$id = 0;
while($row = $results->fetch_assoc()){
$id++;
Then you can send that $id value on to your function and your popup id attribute to help Javascript figure out what you want:
<div class="popup" onclick="myFunction('myPopup<?php echo $id; ?>')">
<span class="popuptext" id="myPopup<?php echo $id; ?>"><?php echo $message;?></span>
Your function should then be modified to understand that change:
function myFunction(elementId) {
var popup = document.getElementById(elementId);
popup.classList.toggle("show");
}

Related

Css Popup alert in button, instead input text

How do i customize css so the popup alert just like this but instead alert popup focus in a button.
i have use this kind of validation on text box
<div class="form-group">
<label class="control-label col-sm-3" for="judul_laporan">Judul Laporan </label>
<div class="col-sm-5">
<input type="email" class="form-control" id="judul_laporan" >
<span style="color: red" id="warnlaporan"></span>
</div>
</div>
<button type="button" id="save_laporan"></button>
JQuery
$("#save_laporan").click(function(){
var judul_laporan = $('input[name="judul_laporan"]');
if(judul_laporan.val() == ''){
judul_laporan.parent().parent().addClass('has-error');
$('#warnlaporan').text("Judul Laporan Belum Ada");
judul_laporan.focus();
result
}else{
judul_laporan.parent().parent().removeClass('has-error');
$('#warnlaporan').text("");
}
But i dont know how to make a popup alert likes the image ( and it should be button )
You can see the x3schools' documentation. It gives you a sample popup at the top of a div.
This code opens a popup:
// When the user clicks on <div>, open the popup
function myFunction() {
var popup = document.getElementById("myPopup");
popup.classList.toggle("show");
}
/* Popup container */
.popup {
position: relative;
display: inline-block;
cursor: pointer;
}
/* The actual popup (appears on top) */
.popup .popuptext {
visibility: hidden;
width: 160px;
background-color: #555;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 8px 0;
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -80px;
}
/* Popup arrow */
.popup .popuptext::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: #555 transparent transparent transparent;
}
/* Toggle this class when clicking on the popup container (hide and show the popup) */
.popup .show {
visibility: visible;
-webkit-animation: fadeIn 1s;
animation: fadeIn 1s
}
/* Add animation (fade in the popup) */
#-webkit-keyframes fadeIn {
from {opacity: 0;}
to {opacity: 1;}
}
#keyframes fadeIn {
from {opacity: 0;}
to {opacity:1 ;}
}
<div class="popup" onclick="myFunction()" style="left: 35px; top: 60px">Click me!
<span class="popuptext" id="myPopup">Popup text...</span>
</div>
You also can use microtip, it is a pretty library witch give you the opportunity to create simply popup. This is the only declaration: <button aria-label="Hey tooltip!" data-microtip-position="top-left" role="tooltip">. However, you have to download a package (just 1kb) with rpm in your server.

Is there a way to trigger a JavaScript onclick event on an element that has pointer-events set to none?

I have an element that has pointer events set to none, this is so hover styles for child elements don't show.
However when this element is clicked on I want to do something with JavaScript. Using an onclick event in JavaScript does not seem to work because pointer-events is set to none.
Is there a way around this so that I can have an element with no pointer events that can still trigger a JavaScript event?
[data-drawer="open"] {
.site-drawer {
transform: translateX(0);
transition: all .2s ease;
}
.site-container {
transform: translateX(-27.5rem);
// Disabling pointer events disables styles hover styles on below elements
// But also disables clicking on container to remove it.
pointer-events: none;
transition: all .2s ease;
&:after {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: rgba(0,0,0,.75);
content: "";
}
}
}
JavaScript:
this.siteContainer.addEventListener('click', (e) => {
console.log('site container clicked');
if(document.body.hasAttribute('data-drawer')) {
document.body.removeAttribute('data-drawer');
}
});
Cheers
You can use this work around. Set pointer-events: none to the element that has the hover effects, And add a wrapper div to the elements that still needs to be triggered on click.
$(".cant-click-this").on("click", function(ev) {
console.log("You cant trigger the element, and it has no hover effects.");
});
$(".click-me-instead").on("click", function(ev) {
console.log("You can trigger click through the wrapper.");
});
.cant-click-this {
pointer-events: none;
}
.cant-click-this:hover {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="click-me-instead">
<button class="cant-click-this"> Try to click me</button> <br>Hovering is futile.
</div>
As I mentioned in the comments, you can achieve this by adding a non-clickable overlay on top of your content using pseudo-elements and z-index
Essentially you have four layers.
the content of the website (white)
the overlay that covers the content of the website while the modal
is open (grey)
the modal (red)
the layer that covers the modal contents. (transparent)
Result: user can't click inside the modal but can click outside anywhere on layer #2
Rough example:
.modal {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
opacity: 0;
pointer-events: none;
background: rgba(0, 0, 0, .5)
}
.close {
top: 0;
right: 0;
bottom: 0;
left: 0;
opacity: 0;
display: none;
z-index: 1;
position: fixed;
cursor: default;
}
.modal-content:after {
content: "";
left: 0;
position: absolute;
top: 0;
width: 100%;
height: 100%;
z-index: 2;
}
.modal:target {
opacity: 1;
pointer-events: auto;
}
.modal:target>.close {
display: block;
}
.modal>div {
width: 300px;
text-align: center;
padding: 40px;
z-index: 2;
position: relative;
background: red;
}
.wrap,
.modal {
display: flex;
align-items: center;
justify-content: center
}
<div class="wrap">
<button>You can click me!</button>
<div id="M" class="modal">
<div class="modal-content">
<button>But not me!</button>
</div>
</div>
</div>

Understanding a template to modify it

I don't seem to understand the Russian Doll philosophy of html and thus, I fail to correctly apply css to the desired container.
Here are two templates I'd like to use simultaneously :
http://tympanus.net/Tutorials/AnimatedBorderMenus/index5.html
http://tympanus.net/Development/SectionSeparators/
And my problem is that the result is this :
First everything seems all right :
Then I click on the hamburger to open the menu :
The problem is that the portion of code which does the border the overlay applies on <nav> and it doesn't seem to affect the <section> but it does affecter the <header> and <footer> (you can't see the later on the screenshots).
Here is the portion of code :
.bt-menu.bt-menu-open {
height: 100%;
border-width: 30px 30px 30px 90px;
background-color: rgba(0,0,0,0.3);
transition: border-width 0.3s, background-color 0.3s;
}
I reached this conclusion by doing this :
And also adding the above css to my sections inline. It did what I would expect by opening the menu.
So, why doesn't it affect my section?
Here is my html if it can prove useful : http://pastebin.com/g7Exx64f
Weave: http://kodeweave.sourceforge.net/editor/#89d761c4072d7ae653f1a8205392074a
I skimmed through the CSS from the pen you linked some have a z-index which means it's stacked above your element.
Plus your container is probably not set to position: fixed; so your content will scroll with you.
In addition you can toggle the display of the social network icons in pure css. You will need an input[type=checkbox] with a unique id. Say #callmenu. Then you need a label[for=callmenu]. For is used trigger the checkbox when clicked.
Say you want to toggle the display of .social. To do this with the checkbox you set what you want the css of .social to be before it's checked.
.social {
visibility: hidden;
}
Then you set what you want it to look like when the checkbox is checked...
#callmenu:checked ~ .social {
visibility: hidden;
}
The snippet below is a simple example of what I believe you'd like to achieve.
You can view this weave which utilizes the pen you linked and font-awesome.
/* Border Menu */
#callmenu {
visibility: hidden;
position: fixed;
top: 0;
left: 0;
}
label[for=callmenu] {
cursor: pointer;
position: fixed;
top: 0;
left: 0;
z-index: 2;
font-size: 2.6752em;
margin: 0.2em 0.7488em;
color: #666;
}
.bgoverlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: #000;
opacity: .3;
z-index: 1;
}
.icon-menu {
position: fixed;
top: 0;
left: 0;
bottom: 0;
background: #3a3a3a;
z-index: 1;
}
.icon-menu ul {
list-style: none;
padding: 2.576em 0;
text-align: center;
}
.icon-menu li {
font-size: 0;
padding: 0;
margin: 0;
}
.icon-menu li a {
color: #999;
padding: 1.12em;
transition: all ease-in 150ms;
}
.icon-menu li a:hover {
color: #cecece;
}
/* When menu is checked */
#callmenu:checked ~ .icon-menu li {
font-size: 1.76em;
margin: 0.768em 0;
}
#callmenu:checked ~ label[for=callmenu] {
color: #d5ebe4;
}
<input type="checkbox" id="callmenu">
<div class="bgoverlay"></div>
<div class="icon-menu">
<ul>
<li>
<a href="javascript:void(0)">
Twitter
</a>
</li>
<li>
<a href="javascript:void(0)">
G+
</a>
</li>
<li>
<a href="javascript:void(0)">
Facebook
</a>
</li>
</ul>
</div>
<label for="callmenu">
menu
</label>

Large gap between/after images in thumbnail scroll

With the use of the jQuery "Any List Scroller" I've added it to my site, however there seems to always be a large gap between some of the images, first 4 on this example link shows up fine but scroll (press the grey btn/image at the bottom right of the thumbnails) and you'll see the gap start to appear.
Can't see any immediate reason why it's got that. Any ideas? The containers arn't any bigger than they should be adding to any type of margin I can see.
Live URL: http://bit.ly/1bJMREc
<div class="als-container product-thumb-carousel" id="demo2">
<span class="als-prev"><img src="http://placehold.it/20x20" alt="prev" title="previous" style="z-index: 99999; position: absolute; left: 70px; top: 40px;" /></span>
<div class="als-viewport">
<ul class="als-wrapper">
<?php $i=0;
$rsThumb->data_seek(0);
if ($row_rsThumb){ while ($row_rsThumb = $rsThumb->get_row_assoc()){
$ww = $dimensions[$i][0];
$hh = $dimensions[$i][1];
if ($ww > $hh){
$dimm = 'width='.(70);
} else {
$dimm = 'height='.(70);
}
$i++;
?>
<div class="product-select">
<a class="thumb_button" id="thumb_<?php echo $i; ?>" href="<?php echo HTTP_HOST.'upload/full/'.$row_rsThumb['fileId'].'_'.$row_rsThumb['fileName']; ?>"><li class="als-item"><img id="img_<?php echo $i; ?>" <?php echo $dimm;?> src="<?php echo HTTP_HOST.'upload/340w/'.$row_rsThumb['fileId'].'_'.$row_rsThumb['fileName']; ?>" alt="<?php echo htmlentities(truncate($page->row['pageTitle'])); ?>" /></li></a>
</div>
<?php }
} ?>
</ul>
</div>
</div>
JavaScript
<script type="text/javascript">
$("#demo2").als({
visible_items: 4,
scrolling_items: 2,
orientation: "horizontal",
circular: "yes",
autoscroll: "no"
});
</script>
CSS
/*************************************
* generic styling for ALS elements
************************************/
.als-container {
position: relative;
width: 100%;
margin: 0px auto;
z-index: 0;
}
.als-viewport {
position: relative;
overflow: hidden;
margin: 0px auto;
}
.als-wrapper {
position: relative;
list-style: none;
}
.als-item {
position: relative;
display: block;
text-align: center;
cursor: pointer;
float: left;
}
.als-prev, .als-next {
position: absolute;
cursor: pointer;
clear: both;
}
/*************************************
* specific styling for #demo2
************************************/
#demo2 {
/* margin: 40px auto; */
}
#demo2 .als-item {
margin: 0px 5px;
padding: 4px 0px;
min-height: 120px;
min-width: 100px;
text-align: center;
}
#demo2 .als-item img {
display: block;
margin: 0 auto;
vertical-align: middle;
}
#demo2 .als-prev, #demo2 .als-next {
top: 40px;
}
#demo2 .als-prev {
left: 200px;
}
#demo2 .als-next {
right: 200px;
}
Looking at the generated source code, you will want to make the UL direct child elements valid list item elements, instead of what you have currently which is:
ul > div > a > li
when it should in fact be:
ul > li > a > span
I have swapped out the div for a span, as you shouldn't really be inserting block level elements (li) within an inline element (a). The order of nesting has been changed to ensure everything within your anchor is clickable, too.
When you have made these changes, lets see what it comes back with. =)
Because your top container div has an id of "demo2",
<div class="als-container product-thumb-carousel" id="demo2">
all of the elements inside the div are being styled with the "#demo2" section of your css file instead of the generic styling section.
For instance, als-item now gets width of 100px (which is too wide) from the '#demo2 als-item{' entry.
There are 4 thumbnails and the width is only 300px for four. The thumbnails are set at 72px but the 'li' element is 100px.
Math is off somewhere.
Try making these changes to your stylesheet.
div#content #details-2 #product .product-select {
height: 72px;
width: 72px;
}
#demo2 .als-item {
margin: 0;
min-height: 72px;
min-width: 72px;
padding: 0;
}

disable parent page on layer show

I have a hidden layer and when the user clicks a button the layer is set to show. How can I make the parent page become disabled/greyed out so the user cannot click anything on the parent page until the layer has been closed(set to hide)
similar to lightbox galleries
I call a function in the layer from the parent page from a button(edit) click
edit.onclick=function(){
edit_box('show');
}
then on the layer I call the show function
function edit_box(showhide)
{
if(showhide == "show")
{
document.getElementById('popupbox').style.visibility="visible";
}else if(showhide == "hide"){
document.getElementById('popupbox').style.visibility="hidden";
}
}
the css for the #popup is
#popupbox{
padding:0;
margin: 0px auto;
background:white;
border: solid #000000 1px;
z-index: 9000;
font-family: arial;
visibility: hidden;
}
and the html is
<div id="popupbox">
<div class="close"><a href="javascript:edit_box('hide');" >close</a></div>
any pointers greatly appreciated as I do not know where to start on this one and can only find code relivent to pop up boxes elsewhere online
why dont you try with jQuery, jQuery("#popupbox").hide();
Change your style to
#popupbox{
padding:0;
margin: 0px auto;
position:fixed;
top:0; left:0; right:0; bottom: 0;
display:none;
background: rgba(255,255,255,0.5);
border: solid #000000 1px;
z-index: 9000;
font-family: arial;
}
and your function to
function edit_box(showhide)
{
if(showhide == "show")
{
$('#popupbox').show();
} else if (showhide == "hide") {
$('#popupbox').hide();
}
}
if you want to support browsers that do not understand rgba colors then use a semi-transparent background .png image
ok sorted this out with
css on parent page
.black_overlay{
display: none;
position: absolute;
top: 0%;
left: 0%;
width: 100%;
height: 100%;
background-color: black;
z-index:1001;
-moz-opacity: 0.8;
opacity:.80;
filter: alpha(opacity=80);
}
css on layer page
.white_content {
display: none;
position: absolute;
top: 25%;
left: 25%;
width: 50%;
height: 50%;
padding: 16px;
border: 16px solid orange;
background-color: white;
z-index:1002;
overflow: auto;
}
then the js on parent page within function calling popup layer
document.getElementById('fade').style.display='block'
html div on parent page
<div id="fade" class="black_overlay"></div>
js on popup layer
function edit_box(showhide){
if(showhide == "show"){
document.getElementById('popupbox').style.display='block';
document.getElementById('popupbox').style.visibility="visible";
}else if(showhide == "hide"){
document.getElementById('popupbox').style.display='none';
document.getElementById('fade').style.display='none'
document.getElementById('popupbox').style.visibility="hidden";
}
}
and the html on the layer
<div id="popupbox" class="white_content">
<div class="close"><a href="javascript:edit_box('hide');" >close</a></div>
</div>

Categories

Resources