My app has a swipe to display hidden action on a list where users can decide to delete items in the list.
It uses HammerJS to handle swipe events and SweetAlert2 to confirm the action.
The issue is when the SweetAlert popup is dismissed. Once the user clicks on cancel and the modal close, all the buttons are suddenly visible. The whole document move to the left.
I created a JSFiddle that reproduce it.
Steps to reproduce:
Swipe right-to-left on one of the items to display the action;
Click on the "x" to delete the item;
Click Cancel.
I will also paste the content of the code below for reference:
HTML:
<div ng-app="app" ng-controller="mainCtrl" class="wrapper">
<div class="items" swipe>
<div ng-repeat="item in items" class="item">
<div>
<div class="item-wrapper">
<div class="logo">
<img src="http://2.bp.blogspot.com/-Y2XrnrXJmXs/Uf5Y_bfr4jI/AAAAAAAAALk/ydouC9lEmDE/s1600/Logogap+Logobb.jpg" />
</div>
<div class="info">
<div class="title">
{{item.title}}
</div>
<div class="description">
{{item.description}}
</div>
</div>
</div>
<div class="offset-action">
<button ng-click="delete()">
X
</button>
</div>
</div>
</div>
</div>
</div>
CSS:
body {
overflow: hidden;
}
.wrapper {
border: 1px solid grey;
min-width: 350px;
max-width: 800px;
}
.items {
overflow: hidden;
position: relative;
}
.item {
padding: 10px 15px;
position: relative;
transition: transform 250ms ease-in-out;
}
.item.show-actions {
transform: translateX(-70px);
}
.item-wrapper {
align-items: center;
display: flex;
}
.logo {
width: 80px;
}
.logo img {
margin: auto;
width: 80px;
height: auto;
}
.offset-action {
align-items: center;
background: #B11A1F;
display: flex;
position: absolute;
top: 0;
bottom: 0;
text-align: center;
right: -70px;
width: 70px;
}
button {
background: transparent;
border: none;
color: white;
width: 100%;
height: 100%;
}
Javascript:
angular.module('app', [])
.controller('mainCtrl', function($scope) {
$scope.items = [
{title: 'Lorem Ipsum', description: 'Consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore.'},
{title: 'Lorem Ipsum', description: 'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'},
{title: 'Lorem Ipsum', description: 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.'},
{title: 'Lorem Ipsum', description: 'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'}
];
$scope.delete = function() {
swal({
title: 'Lorem Ipsum',
text: 'Dolor sit amet?',
type: 'error',
showCancelButton: true
}).then(function(action) {
if (action.value) {
console.log('success');
} else {
swal.noop;
}
})
}
})
.directive('swipe', function() {
return function(scope) {
scope.$watch('items', function() {
var $items = $('.item');
var show_action = 'show-actions';
function hideActions() {
$items.removeClass(show_action);
}
$items.each(function() {
var $item = $(this);
$item.hammer().on('swipeleft', function() {
var $this = $(this);
$items.removeClass(show_action);
if (!$this.hasClass(show_action)) {
$this.addClass(show_action);
}
});
$item.hammer().on('tap', hideActions);
});
});
};
});
There is a conflict between SweetAlert CSS styles and your CSS styles causing this problem.
A simple fix would be adding this CSS to the end of your CSS file:
.offset-action {
display: none;
}
.show-actions .offset-action {
display: flex;
}
https://jsfiddle.net/saeedahmadi/1L7zc25b/
Also Razvan's answer will do the job by getting rid of focus after closing the modal:
https://stackoverflow.com/a/52028143/5939933
"adding document.activeElement.blur(); at the top of your delete() method"
Add document.activeElement.blur(); before calling swal().
https://jsfiddle.net/yd3gpsvL/
It looks to be caused by focus returning to the button after the popup closes. There's a discussion about it here.
Alternatively, you can use a div instead of a button (optionally with role="button") to avoid button's focus functionality.
Your JavaScript needs to a little brush up and document.activeElement.blur(); at the top of your delete() method:
angular.module('app', [])
.controller('mainCtrl', function($scope) {
$scope.items = [
{title: 'Lorem Ipsum', description: 'Consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore.'},
{title: 'Lorem Ipsum', description: 'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'},
{title: 'Lorem Ipsum', description: 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.'},
{title: 'Lorem Ipsum', description: 'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'}
];
$scope.delete = function() {
document.activeElement.blur();
swal({
title: 'Lorem Ipsum',
text: 'Dolor sit amet?',
type: 'error',
showCancelButton: true
}).then(function(action) {
if (action.value) {
console.log('success');
} else {
swal.noop;
}
})
}
})
.directive('swipe', function() {
return function(scope) {
scope.$watch('items', function() {
var $items = $('.item');
var show_action = 'show-actions';
function showActions() {
var $this = $(this);
$items.removeClass(show_action);
if (!$this.hasClass(show_action)) {
$this.addClass(show_action);
}
}
function hideActions() {
$items.removeClass(show_action);
}
$items.each(function() {
var $item = $(this);
$item.hammer().on('swipeleft', showActions);
$item.hammer().on('tap', hideActions);
});
});
};
});
Here is an update to your jsFiddle.
Once the user clicks on cancel and the modal close, all the buttons are suddenly visible...
In order to overcome this point i suggest to remove the class only when the swal closes:
remove this line: $item.hammer().on('tap', hideActions);
add index parameter to the delete call: ng-click="delete($index)" in your html and $scope.delete = function (idx) { in your js
remove class on swal close after a few milliseconds:
setTimeout(function(){
$('.item').eq(idx).removeClass('show-actions');
}, 200);
The updated fiddle
UPDATE
Thanks for your answer, unfortunately I need the tap to hide the button
I updated the fiddle removing jQuery and jQuery for Hammer.
In order to hide the buttons on swal close I hide the current button on tap and show again on swipeleft.
angular.module('app', []).controller('mainCtrl', function ($scope) {
$scope.items = [{title: 'Lorem Ipsum', description: 'Consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore.'},
{title: 'Lorem Ipsum', description: 'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'},
{title: 'Lorem Ipsum', description: 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.'},
{title: 'Lorem Ipsum', description: 'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'}];
$scope.delete = function () {
swal({
title: 'Lorem Ipsum',
text: 'Dolor sit amet?',
type: 'error',
showCancelButton: true
}).then(function (action) {
if (action.value) {
console.log('success');
} else {
swal.noop;
}
})
}
}).directive('swipe', function () {
return function (scope) {
scope.$watch('items', function () {
document.querySelectorAll('.item').forEach(function (ele, idx) {
var mc = new Hammer(ele);
mc.on("swipeleft", function (e) {
e.target.closest('.item').classList.add('show-actions');
e.target.closest('.item').querySelector('.offset-action').style.display = '';
}).on("tap", function (e) {
e.target.closest('.item').classList.remove('show-actions');
e.target.closest('.item').querySelector('.offset-action').style.display = 'none';
});
});
});
};
});
body {
overflow: hidden;
}
.wrapper {
border: 1px solid grey;
min-width: 350px;
max-width: 800px;
}
.items {
overflow: hidden;
position: relative;
}
.item {
padding: 10px 15px;
position: relative;
transition: transform 250ms ease-in-out;
}
.item.show-actions {
transform: translateX(-70px);
}
.item-wrapper {
align-items: center;
display: flex;
}
.logo {
width: 80px;
}
.logo img {
margin: auto;
width: 80px;
height: auto;
}
.offset-action {
align-items: center;
background: #B11A1F;
display: flex;
position: absolute;
top: 0;
bottom: 0;
text-align: center;
right: -70px;
width: 70px;
}
button {
background: transparent;
border: none;
color: white;
width: 100%;
height: 100%;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/7.26.11/sweetalert2.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/7.26.11/sweetalert2.all.js"></script>
<div ng-app="app" ng-controller="mainCtrl" class="wrapper">
<div class="items" swipe>
<div ng-repeat="item in items" class="item">
<div>
<div class="item-wrapper">
<div class="logo">
<img src="http://2.bp.blogspot.com/-Y2XrnrXJmXs/Uf5Y_bfr4jI/AAAAAAAAALk/ydouC9lEmDE/s1600/Logogap+Logobb.jpg"/>
</div>
<div class="info">
<div class="title">
{{item.title}}
</div>
<div class="description">
{{item.description}}
</div>
</div>
</div>
<div class="offset-action">
<button ng-click="delete()">
X
</button>
</div>
</div>
</div>
</div>
</div>
Related
I want to create a navigation menu that must be scroll horizontally. But this navigation should be display when the user scroll down the window in the browser (Mobile+Desktop).
I have tried out this code so that the navigation menu display after scroll bottom but its item does not scroll horizontally. When removing position: fixed then it's item scroll horizontally.
So I want both functionalities scrollable navigation horizontal+display navigation menu bar when the user scrolls down the window.
window.onscroll = function() {
scrollFunction()
};
function scrollFunction() {
if (document.body.scrollTop > 150 || document.documentElement.scrollTop > 150) {
document.getElementById("navigation").style.top = "0";
} else {
document.getElementById("navigation").style.top = "-150px";
}
}
#navigation {
top: -50px;
position: fixed;
}
.nav-header {
background: #002347;
color: #ffffff;
}
.nav-header a {
color: #ffffff;
}
.nav-header nav {
width: 100%;
}
.itemlist {
padding: 6px 12px;
}
.itemlist:not(:last-child) {
border-right: 1px solid #ece4e4;
}
.itemlist {
font-size: 17px;
font-weight: bold;
}
.itemlist,
.center {
cursor: pointer;
vertical-align: middle;
display: inline-block;
}
.scrolltab {
overflow-x: auto;
white-space: nowrap;
-webkit-overflow-scrolling: touch;
-ms-overflow-style: -ms-autohiding-scrollbar;
}
.scrolltab::-webkit-scrollbar {
display: none;
}
<div id="navigation" class="nav-header">
<nav class="center scrolltab">
<span class="itemlist"> About us </span>
<span class="itemlist">Web Solution</span>
<span class="itemlist">Web Application</span>
<span class="itemlist">Scripting Language</span>
<span class="itemlist">Andriod Application</span>
<span class="itemlist">Contact</span>
</nav>
</div>
<div style="padding:15px 15px 2500px;font-size:30px">
<p>Lorem ipsum dolor dummy text sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute
irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
To make the navigation bar scroll horizontally you need to give the containing element a width. i.e. add
#navigation {
width:100%;
}
also, you have
.scrolltab::-webkit-scrollbar {
display: none;
}
I am not sure whether you needed this for some reason, but on Microsoft Edge and Chrome at least it causes the scroll bar not to appear. Removing it renders the menu scrollable.
I have been trying to create a pop-up window on the page with changing content depending on which trigger is clicked on.
Unfortunately, the JS code just keeps adding the created elements to the pop-up div, which works fine on the first click but then it overruns the container.
Is there a better way to create a pop-up window with dynamic content that displays the corresponding content to each trigger?
I also created a Codepen here: https://codepen.io/lisaschumann/pen/eYOZoMW.
When I create a single pop-up with the HTML code already in the index.html file and just change the 'display: none;' and 'display: block;' properties with JS it works fine. But if I want to create a pop-up with different content from an array depending on which trigger, it gets really confusing.
// I'm trying to avoid jQuery for this one as the code needs to be implemented into a WordPress page and any additional jQuery code has caused issues with the rest of the template.
Any help would be massively appreciated!
HTML
<div class="trigger" id="profile-one">
<span>Click here for Profile Dan</span>
</div>
<div class="trigger" id="profile-two">
<span>Click here for Profile Tom</span>
</div>
<div class="pop-up">
<div class="close-button"></div>
</div>
CSS
.pop-up {
display: none;
border: 2px solid #000;
border-radius: 5px;
height: 300px;
width: 700px;
background: #fff;
transition: all 0.3s linear;
position: absolute;
top: 15%;
left: 32%;
}
.pop-up p {
font-family: sans-serif;
margin: 40px;
}
.pop-up h4{
margin: 32px 0 20px 40px;
}
.bio {
display: flex;
padding: 0 80px 40px 40px;
font-size: 16px;
}
.bio img {
width: 25%;
height: 170px;
margin: 10px 30px 0 0;
}
.close-button {
position: absolute;
right: 32px;
top: 32px;
width: 32px;
height: 32px;
cursor: pointer;
padding: 10px;
}
.close-button:before, .close-button:after {
position: absolute;
right: 30px;
top: 10px;
content: ' ';
height: 33px;
width: 3px;
background-color: #333;
}
.close-button:before {
transform: rotate(45deg);
}
.close-button:after {
transform: rotate(-45deg);
}
.trigger {
border: 2px solid #000;
border-radius: 5px;
background: #fff;
position: absolute;
text-align: center;
padding: 10px;
}
#profile-one {
top: 15%;
left: 10%;
}
#profile-two {
top: 55%;
left: 10%;
}
JS
const triggerOne = document.querySelector('.trigger#profile-one');
const triggerTwo = document.querySelector('.trigger#profile-two');
const popUp = document.querySelector('.pop-up')
const close = document.querySelector('.close-button');
const profile = [{
name: 'Dan',
src: 'https://lisaschumann.github.io/resources/images/mark-basarab-157610-unsplash.jpg',
alt: 'Dan Profile Pic',
bio: 'Bio Dan: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.'
},
{
name: 'Tom',
src: 'https://lisaschumann.github.io/resources/images/osteopathy.jpg',
alt: 'Tom Profile Pic',
bio: 'Bio Tom: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.'
}
];
function profileOne() {
var divMain = document.createElement("div");
var titleProfile = document.createElement("h4");
var nodeTitle = document.createTextNode(profile[0].name);
var imgProfile = document.createElement("img");
imgProfile.src = profile[0].src;
imgProfile.alt = profile[0].alt;
var paraProfile = document.createElement("p");
var nodePara = document.createTextNode(profile[0].bio);
titleProfile.appendChild(nodeTitle);
paraProfile.appendChild(nodePara);
divMain.appendChild(imgProfile);
divMain.appendChild(paraProfile);
divMain.classList.add("bio");
popUp.appendChild(titleProfile);
popUp.appendChild(divMain);
};
function profileTwo() {
var divMain = document.createElement("div");
var titleProfile = document.createElement("h4");
var nodeTitle = document.createTextNode(profile[1].name);
var imgProfile = document.createElement("img");
imgProfile.src = profile[1].src;
imgProfile.alt = profile[1].alt;
var paraProfile = document.createElement("p");
var nodePara = document.createTextNode(profile[1].bio);
titleProfile.appendChild(nodeTitle);
paraProfile.appendChild(nodePara);
divMain.appendChild(imgProfile);
divMain.appendChild(paraProfile);
divMain.classList.add("bio");
popUp.appendChild(titleProfile);
popUp.appendChild(divMain);
}
if(triggerOne){
triggerOne.addEventListener('click', function(){
popUp.style.display = 'block';
profileOne();
});
}
if(triggerTwo){
triggerTwo.addEventListener('click', function(){
popUp.style.display = 'block';
profileTwo();
});
}
// Pop-Up window close
const invisible = e =>{
popUp.style.display = 'none';
}
if(close){
close.addEventListener('click', invisible);
}
I am creating some cards with dynamic data using jquery. There is a description property that either fits on the card or not. When it does not fit, i would like to keep the card the same size as the others but add a "show more/less" button that would expand the card to show the rest of the description.
I have created a fiddle showing the card creation as well as what i have tried so far.
At this point i have a function checkTruncation that will check if the text would fit in its container or not. The issue seems to rely on the fact that the elements are not yet rendered so their width is 0 which makes the function return always true.
The function is as this:
let checkTruncation = function (jqueryElement) {
var $element = jqueryElement;
if ($element) {
var $c = $element
.clone()
.css({ display: 'inline', width: 'auto', visibility: 'hidden' })
.appendTo('body');
let truncated = $c.width() > $element.width()
console.log($c.width(), $element.width(), $c.width() > $element.width())
$c.remove();
return truncated;
}
return false;
}
Also, instead of me reinventing the wheel, is there any suggested library that could achieve this functionality? I know i have seen such behavior, but cannot remember where.
UPDATE
In the fiddle above, i am just calling the getCard function, which is responsible to provide the template for the card, twice just to show some sample. In the real life situation i am getting data through ajax and populating the cards using the following when a user clicks on a button:
$('.fetchButton').on('click', function(){
$.get(url, filter)
.done(function (data) {
jQuery.each(data, function (index, item) {
$('.container').append(getCard(item));
})
}
})
UPDATE 2
With the help of #LGSon i have come to this scenario which is mostly using CSS to achieve what i need. Still the answer given is valid and did solve my issue so i will keep it as an answer.
In addition to given answer, which explained why the original code didn't work, here is a different approach, showing how one can use CSS to show/hide a "Read more..." button
With absolute: position and overflow: hidden we can hide a "button" at the bottom of a "text" element, and when that element reach the "wrapper's" height, the hidden "button" becomes visible.
I also made use of a pseudo element and data-* attribute to keep "button text" in the markup, and the CSS attr() to toggle it when showing/hiding the text.
Stack snippet
document.querySelectorAll('.readmore').forEach( function(link) {
link.addEventListener('click', function() {
this.closest('.wrapper').classList.toggle('show');
});
});
.wrapper {
height: 70px;
border: 1px solid gray;
overflow: hidden;
}
.wrapper.show {
height: auto;
}
.text {
position: relative;
overflow: hidden;
}
.readmore {
position: absolute;
width: 100%;
top: 52px;
left: 0;
background: white;
color: red;
cursor: pointer;
}
.readmore::before {
content: attr(data-more)
}
.wrapper.show .readmore {
position: relative;
top: auto;
display: block;
}
.wrapper.show .readmore::before {
content: attr(data-less)
}
<div class="wrapper">
<div class="text">
Some smaller dummy text here
<span class="readmore" data-more="Show more..." data-less="Show less..."></span>
</div>
</div>
<div class="wrapper">
<div class="text">
Some bigger dummy text here <br>
Some bigger dummy text here <br>
Some bigger dummy text here <br>
Some bigger dummy text here <br>
Some bigger dummy text here <br>
<span class="readmore" data-more="Show more..." data-less="Show less..."></span>
</div>
</div>
If possible, the "Show more/less..." text can of course be set in the CSS, to simplify maintenance and have it in one place.
document.querySelectorAll('.readmore').forEach( function(link) {
link.addEventListener('click', function() {
this.closest('.wrapper').classList.toggle('show');
});
});
.wrapper {
height: 70px;
border: 1px solid gray;
overflow: hidden;
}
.wrapper.show {
height: auto;
}
.text {
position: relative;
overflow: hidden;
}
.readmore {
position: absolute;
width: 100%;
top: 52px;
left: 0;
background: white;
color: red;
cursor: pointer;
}
.readmore::before {
content: 'Show more...'
}
.wrapper.show .readmore {
position: relative;
top: auto;
display: block;
}
.wrapper.show .readmore::before {
content: 'Show less...'
}
<div class="wrapper">
<div class="text">
Some smaller dummy text here
<span class="readmore"></span>
</div>
</div>
<div class="wrapper">
<div class="text">
Some bigger dummy text here <br>
Some bigger dummy text here <br>
Some bigger dummy text here <br>
Some bigger dummy text here <br>
Some bigger dummy text here <br>
<span class="readmore"></span>
</div>
</div>
Updated based on a comment
Here is an updated Stack snippet version of your Fiddle/Codepen sample's
let getCard = function(options) {
let item = options.data;
let $parent = options.parent;
let outerDiv = $('<div>').addClass('shops-content-right');
let boxDiv = $('<div>').addClass('boxes-right row');
let shopDiv = $('<div>').addClass('one-shop-box col-md-6 offset-md-3');
let cubeDiv = $('<div>').addClass('cube text-center');
let wrapperDiv = $('<div>').addClass('wrapper');
let textDiv = $('<div>').addClass('text');
let descriptionP = $('<p>').addClass('text-disc').text(item.description);
let loadMoreP = $('<span>More >').addClass('readmore');
textDiv.append([descriptionP, loadMoreP]);
wrapperDiv.append(textDiv);
cubeDiv
.append(wrapperDiv);
shopDiv.append(cubeDiv);
boxDiv.append(shopDiv);
outerDiv.append(boxDiv);
$parent.append(outerDiv);
loadMoreP.on('click', function() {
if (wrapperDiv.hasClass('collapsed')) {
wrapperDiv.removeClass('collapsed');
loadMoreP.text("More >");
} else {
wrapperDiv.addClass('collapsed');
loadMoreP.text("Less <");
}
})
return outerDiv;
}
$('.fetchButton').on('click', function() {
getCard({
data: {
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum'
},
parent: $('.container'),
lines: 3
})
getCard({
data: {
description: 'Lorem ipsum dolor sit amet, consectetur'
},
parent: $('.container'),
lines: 3
})
})
.row {
background: #f8f9fa;
margin-top: 20px;
}
.col {
border: solid 1px #6c757d;
padding: 10px;
}
.one-shop-box {
border: 1px solid;
}
.shops-content-right .one-shop-box .cube p.text-disc {
font-size: 16px;
/*height: 50px;*/
overflow: hidden;
}
.wrapper {
height: 90px;
overflow: hidden;
}
.wrapper.collapsed {
height: auto;
}
.text {
position: relative;
overflow: hidden;
}
.readmore {
position: absolute;
width: 100%;
top: 72px;
left: 0;
background: white;
color: red;
}
.wrapper.collapsed .readmore {
position: relative;
top: auto;
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!--
Bootstrap docs: https://getbootstrap.com/docs
-->
<div class="container">
<button class="fetchButton">
Fetch Data
</button>
</div>
This happens beacuse you doesn't append your element to document, so its width is 0. So, update your code as the following:
let checkTruncation = function($element) {
if ($element) {
var $c = $element
.clone()
.css({ display: 'inline', width: 'auto', visibility: 'hidden' })
.appendTo('body');
let truncated = $c.width() > $element.width();
// console.log($c.width(), $element.width(), $c.width() > $element.width());
$c.remove();
return truncated;
}
return false;
};
let baseUrl ='';
let getCard = function(item, $parent) {
let outerDiv = $('<div>').addClass('shops-content-right');
let boxDiv = $('<div>').addClass('boxes-right row');
let shopDiv = $('<div>').addClass('one-shop-box col-md-6 offset-md-3');
let cubeDiv = $('<div>').addClass('cube text-center');
let descriptionP = $('<p>').addClass('text-disc').text(item.description).addClass('collapsed');
let loadMoreP = $('<p>').css({ 'font-size': '16px', 'cursor': 'pointer' }).text("More >");
cubeDiv.append(descriptionP).append(loadMoreP);
shopDiv.append(cubeDiv);
boxDiv.append(shopDiv);
outerDiv.append(boxDiv);
$parent.append(outerDiv);
loadMoreP.on('click', function () {
if (descriptionP.hasClass('collapsed')) {
descriptionP.removeClass('collapsed');
loadMoreP.text("Less <");
} else {
descriptionP.addClass('collapsed');
loadMoreP.text("More >");
}
});
if (checkTruncation(descriptionP)) {
loadMoreP.show();
} else {
loadMoreP.hide();
}
};
const $container = $('.container');
getCard({
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum'
}, $container);
getCard({
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit'
}, $container);
.row {
background: #f8f9fa;
margin-top: 20px;
}
.col {
border: solid 1px #6c757d;
padding: 10px;
}
.one-shop-box {
border:1px solid;
}
.shops-content-right .one-shop-box .cube p.text-disc {
font-size: 16px;
height: 50px;
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<div class="container"></div>
I pass to the function getCard() the container element, and it append the new element to it before it calls to the function checkTruncation().
And update your code that calls getCard() as follows:
const $container = $('.container');
$('.fetchButton').on('click', function() {
$.get(url, filter).done(function(data) {
$.each(data, function(index, item) {
getCard(item, $container);
});
});
});
I am trying to make this code I made into a library:
$.fn.boxify = function() {
var imageSliding = $('.box > .img');
$(this).click(function() {
$('.backdrop, .box').animate({
'opacity': '.50'
}, 300, 'linear');
$('.box').animate({
'opacity': '1.00'
}, 300, 'linear');
$('.backdrop, .box').css('display', 'block');
});
$('.close').click(function() {
close_box();
});
$('.backdrop').click(function() {
close_box();
});
function close_box() {
$('.backdrop, .box').animate({
'opacity': '0'
}, 300, 'linear', function() {
$('.backdrop, .box').css('display', 'none');
});
}
/* Slider */
var speed = 100;
$(".prev").click(function() {
var gallery = $(this).closest('.box').find("ul.gallery"),
now = gallery.children(":visible"),
last = gallery.children(":last"),
prev = now.prev();
prev = prev.index() == -1 ? last : prev;
now.fadeOut(speed, function() {
prev.fadeIn(speed);
});
});
$(".next").click(function() {
var gallery = $(this).closest('.box').find("ul.gallery"),
now = gallery.children(":visible"),
first = gallery.children(":first"),
next = now.next();
next = next.index() == -1 ? first : next;
now.fadeOut(speed, function() {
next.fadeIn(speed);
});
});
$(".gallery li").click(function() {
var first = $(this).parent().children(':first'),
next = $(this).next();
next = next.index() == -1 ? first : next;
$(this).fadeOut(speed, function() {
next.fadeIn(speed);
});
});
};
$( "a" ).boxify(); // Makes all the links green.
body {
font-family: Helvetica, Arial;
}
.backdrop {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
background: #000;
opacity: .0;
filter: alpha(opacity=0);
z-index: 50;
display: none;
}
.box {
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
left: 50%;
background: black;
text-align: left;
z-index: 51;
padding: 0;
margin: 0;
display: none;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
-moz-box-shadow: 0px 0px 5px #444444;
-webkit-box-shadow: 0px 0px 5px #444444;
box-shadow: 0px 0px 5px #444444;
border: 10px solid #000;
color: white;
width: 40%;
}
#media (min-width: 320px) and (max-width: 900px) {
.box {
width: 98%;
}
}
#media (min-width: 901px) and (max-width: 1200px) {
.box {
width: 60%;
}
}
#media (min-width: 1201px) {
.box {
width: 48%;
}
}
.box img {
width: 100%;
}
.caption {
padding-top: 10px;
font-size: 15px;
}
.prev,
.next {
position: relative;
padding: 3px;
cursor: pointer;
float: right;
border: 1px solid black;
}
.prev:active,
.next:active {
background-color: white;
color: black;
}
.gallery li {
display: none;
list-style: none;
margin-left: -40px;
}
.gallery li:first-child {
display: block;
}
.gallery img {
max-height: 550px;
}
.slideButtons {
position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container-fluid">
<h1>Welcome Within</h1>
Open Lightbox
<div class="backdrop"></div>
<div class="box">
<ul class="gallery" id="olympGallery">
<li><img src="http://urbanphenomena.net/imgs/trabzoni/trabzoni1.png" alt="" title="" /></li>
<li><img src="http://urbanphenomena.net/imgs/trabzoni/trabzoni2.png" alt="" title="" /></li>
<li><img src="http://urbanphenomena.net/imgs/trabzoni/trabzoni3.png" alt="" /></li>
</ul>
<div class="slideButtons">
<span class="next">Next</span>
<span class="prev">Previous</span>
</div>
<div class="caption">
<p>This thing is called 'Caption'. Let me tell you:</p>
<hr />
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis
aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
</div>
You see that .box class? As a user I wanna infinitely add more box containing different images and captions!
When I added another <a> which is the Lightbox link to the box, the both boxes display on the same time. I know that the same code is reused this way, but that's what I'm trying to do:
Somehow keep the same code without adding more and more code. Yet, when I add more boxes they are completely different from the others (different images)
You can modify your .click function to use this one:
$(this).click(function(event) {
var lightBoxes = $('a.lightbox'); //Retrieves all a.lightboxes of the page
for (var i = 0; i < lightBoxes.length; i++) {
if (lightBoxes[i] == event.target) { //Checks the clicked element position in the array
//Displays the common .backdrop div
$('.backdrop').animate({
'opacity': '.50'
}, 300, 'linear').css('display', 'block');
//Displays the 'i' .box div
$('.box').eq(i).animate({
'opacity': '1.00'
}, 300, 'linear').css('display', 'block');
break;
}
}
});
This code will check all the 'a' elements with the .lightbox class and will check which one was clicked. Knowing the index (i) of the 'a' element clicked, then the 'i' .box element will display.
Note that the .backdrop element should be unique in the HTML and don't need to be repeated. In the HTML you just need to add a new a href element and a new div .box for each a.
Open Lightbox 2
<div class="box">
<ul class="gallery" id="olympGallery">
<li><img src="http://urbanphenomena.net/imgs/trabzoni/trabzoni1.png" alt="" title="" /></li>
<li><img src="http://urbanphenomena.net/imgs/trabzoni/trabzoni2.png" alt="" title="" /></li>
<li><img src="http://urbanphenomena.net/imgs/trabzoni/trabzoni3.png" alt="" /></li>
</ul>
<div class="slideButtons">
<span class="next">Next</span>
<span class="prev">Previous</span>
</div>
<div class="caption">
<p>This thing is called 'Caption'. Let me tell you:</p>
<hr />
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis
aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
</div>
Hope this is what you need!
Here is what im working on... A maximizable and minimizable pop-up that is called by an hyperlink.
<html>
<style type="text/css">
.pop_out {
background: #333;
border-radius: 5px 5px 0 0;
box-shadow: 0px 0px 10px #000;
}
.minimized {
display: inline-block;
margin-right: 10px;
bottom: 0;
width: 250px;
height: 60px;
overflow: hidden;
}
.maximized {
top: 0;
position: fixed;
display: block;
width: auto;
height: auto;
/* Whatever styling you want when maximized, as long as you add the same styling to minimized class to change it back */
}
.close_pop {
cursor: pointer;
color: #fff;
}
.close_pop:hover {
color: red;
}
.expand_collapse {
margin-right: 10px;
cursor: pointer;
color: #fff;
height: 3px;
}
.expand_collapse:hover {
color: #ccc;
}
a {
position: fixed;
top: 150;
}
</style>
<script type="text/javascript">
var max = true;
function expand_collapse(elem) {
var top_div = elem.parentNode.parentNode.parentNode;
if (max === false) {
elem.innerHTML = "▼";
top_div.classList.toggle("minimized", false);
top_div.classList.toggle("maximized", true);
max = true;
} else if (top_div.classList.contains("maximized")) {
elem.innerHTML = "▲";
top_div.classList.toggle("minimized", true);
top_div.classList.toggle("maximized", false);
max = false
}
}
function close_pop(elem) {
var top_div = elem.parentNode.parentNode.parentNode;
top_div.style.display = 'none';
if (top_div.classList.contains("maximized")) {
max = false;
}
}
</script>
CLICK HERE<!--Right Here -->
<div style="position:fixed;bottom:0px;">
<div class="pop_out maximized">
<div style="padding:2px;position:relative;"> <span style="margin-left:10px;">Tab 1</span>
<span style="position:absolute;right:15px;">
<span class="expand_collapse" onclick="expand_collapse(this);">▼</span>
<span class="close_pop" onclick="close_pop(this);">×</span></span>
</div>
<div style="background:white;font-size:15px;padding:2px;">The standard Lorem Ipsum passage, used since the 1500s "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est
laborum.</div>
</div>
</div>
But the pop up opens with the page and i want the pop up to only be opened when the hyperlink commented is clicked and not when the page is loaded. Any help will be much appreciated. I have tried different methods on the hyperlink but to no avail.
Please check the link below
$(document).ready(function() {
$('.show-popup').on('click', function() {
$('.popup').fadeIn();
});
$('.close_pop').on('click', function() {
$('.popup').fadeOut();
});
});
.popup {
display: none;
}
.pop_out {
background: #333;
border-radius: 5px 5px 0 0;
box-shadow: 0px 0px 10px #000;
}
.minimized {
display: inline-block;
margin-right: 10px;
bottom: 0;
width: 250px;
height: 60px;
overflow: hidden;
}
.maximized {
top: 0;
position: fixed;
display: block;
width: auto;
height: auto;
/* Whatever styling you want when maximized, as long as you add the same styling to minimized class to change it back */
}
.close_pop {
cursor: pointer;
color: #fff;
}
.close_pop:hover {
color: red;
}
.expand_collapse {
margin-right: 10px;
cursor: pointer;
color: #fff;
height: 3px;
}
.expand_collapse:hover {
color: #ccc;
}
a {
position: fixed;
top: 150;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<a class="show-popup" href="#">CLICK HERE</a>
<!--Right Here -->
<div class="popup" style="position:fixed;bottom:0px;">
<div class="pop_out maximized">
<div style="padding:2px;position:relative;"> <span style="margin-left:10px;">Tab 1</span>
<span style="position:absolute;right:15px;">
<span class="expand_collapse" onclick="expand_collapse(this);">▼</span>
<span class="close_pop">×</span></span>
</div>
<div style="background:white;font-size:15px;padding:2px;">The standard Lorem Ipsum passage, used since the 1500s "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est
laborum.
</div>
</div>
</div>
The pop-up element isn't being hidden on initial page load.
Add style to the pop-up element in CSS.
display:none
Give the pop-up element an ID attribute for easier Javascript targeting
id="pop1"
Add attribute to the hyperlink
onclick="open_pop('#pop1')"
Add javascript function
function open_pop(elem)
{
elem.style.display = 'block';
}
Or to synchronise more effectively with your code, give the pop-up one of your custom classes to modify the display style.
I would also consider using ID's for Javascript selection as opposed to crawling through parents which could break the code if children elements or added or removed from the tree.
in simple code,
html
<div id="welcomeDiv" style="display:none;" class="answer_list" > WELCOME</div>
<input type="button" name="answer" value="Show Div" onclick="showDiv()" />
javascript
function showDiv() {
document.getElementById('welcomeDiv').style.display = "block";
}
I could not share my jsfiddle link. so this helps you i guess.
OR
Just make the div style = "display:none" on mouse click toggle the display.