Limit JavaScript function to specified screen width - javascript

Help guys...everything works until website goes to tablet/mobile widht...than JS start to act crazy. I understand that its because there is two actions under one funciton, but is there any way to separate this and/or to limit add/remove class .currentline to specified screen width.
When its in tablet/mobile size i have dropdown menu so i dont need animated lines from .lineparent
window.addEventListener('DOMContentLoaded', () => {
document.querySelector('#albmenu').addEventListener('click', (event) => {
if (event.target.tagName === 'A') {
document.querySelector('.current').classList.remove('current');
document.querySelector('.currentline').classList.remove('currentline');
let galleryName = event.target.getAttribute('data-gallery');
let lineName = event.target.getAttribute('data-line');
document.querySelector(`.${galleryName}`).classList.add('current');
document.querySelector(`.${lineName}`).classList.add('currentline');
}
});
});
.lineparent {
width: 35%;
height: 2px;
}
.line,
.line2,
.line3,
.line4,
.line5,
.line6 {
width: 100%;
height: 2px;
background-color: var(--textcol);
opacity: 0;
}
.currentline {
opacity: 1;
animation: linewidth 0.5s;
}
#keyframes linewidth {
from {
width: 0;
}
to {
width: 100%;
}
}
<div class="albmenu"id="albmenu">
<ul id="gallery-links">
<li><div class="lineparent"><div class="line currentline"></div></div>
All</li>
<li><div class="lineparent"><div class="line2"></div></div>
Weddings</li>
<li><div class="lineparent"><div class="line3"></div></div>
Business</li>
<li><div class="lineparent"><div class="line4"></div></div>
Sports</li>
</ul>
<div class="dropdown" id="dropdown">
<button onclick="myFunction()" class="dropbtn">Category</button>
<div id="myDropdown" class="dropdown-content">
<a value="Family" href="#gallery" data-gallery="grid">All</a>
<a value= "" href="#gallery" data-gallery="grid2">Weddings</a>
<a value= "" href="#gallery" data-gallery="grid3">Business</a>
<a value= "" href="#gallery" data-gallery="grid4">Sports</a>
</div>
</div>
</div>

If it is styling then you can use CSS media queries to handle that, and if it is some JavaScript then you can use the DOM APIs to detect the width of your viewport and have code executes or not based on the width.

I solved it myself with an innerWidth. I changed the code to this:
window.addEventListener('DOMContentLoaded', () => {
document.querySelector('#albmenu').addEventListener('click', (event) => {
if (event.target.tagName === 'A') {
document.querySelector('.current').classList.remove('current');
if ((window.innerWidth > 1024)) {document.querySelector('.currentline').classList.remove('currentline');
}
let galleryName = event.target.getAttribute('data-gallery');
let lineName = event.target.getAttribute('data-line');
document.querySelector(`.${galleryName}`).classList.add('current');
if ((window.innerWidth > 1024)) { document.querySelector(`.${lineName}`).classList.add('currentline');}
}
});
});

Related

How to load and unload a slider script when screen size changes?

I am using a responsive slider from http://sachinchoolur.github.io/lightslider/, which implemented the JS, and some CSS. Works great!
My Problem: I have 3 Content-Boxes which show as normal boxes when above 1024px screen width - next to each other. So far so good...
I only want to launch the slider script when the screen size is mobile, below 1024px, and unload it when the screen is resized bigger. But it launches always and I'm also stuck at unloading the script when the screen size changes...
I've attempted several things, but can't achieve that. My JS is not the best tbh...
My current script is the following:
<script>
jQuery(document).ready(function() {
jQuery("#content-slider").lightSlider({
loop:true,
keyPress:true,
item: 1,
enableTouch:true,
enableDrag:true,
freeMove:true,
swipeThreshold: 40,
onSliderLoad: function ($el) {
jQuery(window).on('load', function () {
var windowSize = jQuery(window).width();
if(windowSize <= 1024){
console.log("kleiner 1024");
} else if (windowSize > 1024) {
console.log("größer 1024");
$el.lightSlider = null;
return false;
}
});
jQuery(window).on('resize', function () {
var windowSize = jQuery(window).width();
if(windowSize <= 1024){
console.log("kleiner 1024");
} else if (windowSize > 1024) {
console.log("größer 1024");
$el.lightSlider = null;
return false;
}
});
}
});
});
</script>
The slider has several options to set, shown here in the "Play with settings" section. I thought it would be wise to use the "onSliderLoad" function and check then for screen size. In my script the line with "$el.lightSlider = null;" - i've tried unload, destroy, false, and so on, but i can't get rid of the slider when the screen size changes... not sure if that's even possible meanwhile...
Slider options like mentioned here:
onSliderLoad: function (el) {},
onBeforeSlide: function (el) {},
onAfterSlide: function (el) {},
onBeforeNextSlide: function (el) {},
onBeforePrevSlide: function (el) {}
Also it seems the load-event is not being triggered, as i don't see my console.log...
Would appreciate any help!
Thx & best regards
You can't unload scripts
When a script is loaded/executed, the function definitions are added to the global window object. Unless you assign to a variable then delete it.
Also, if the responsiveness is your problem, there is another solution:
You can set multiple layouts. You can add as many breakpoints as you want.
$('#responsive').lightSlider({
item:4,
loop:false,
slideMove:2,
easing: 'cubic-bezier(0.25, 0, 0.25, 1)',
speed:600,
responsive : [
{
breakpoint:800,
settings: {
item:3,
slideMove:1,
slideMargin:6,
}
},
{
breakpoint:480,
settings: {
item:2,
slideMove:1
}
}
]
});
Doesn't look like there is a built in method for doing that, but you can wrap it in a little class that just manually puts it back the way it originally is. Here, play with these buttons for an example.
class LSWrapper {
constructor() {
this.markup = $('#lightSlider').parent().html();
this.isInit = false;
}
init() {
if (this.isInit) return false;
this.isInit = true;
$('#lightSlider').lightSlider({
gallery: true,
item: 1,
loop: true,
slideMargin: 0,
thumbItem: 9
});
}
destroy() {
if (!this.isInit) return false;
this.isInit = false;
$('#lightSlider').parent().html(this.markup);
$(".lSGallery").remove();
}
}
var slideshow = new LSWrapper();
document.getElementById('init').onclick = () => slideshow.init();
document.getElementById('destroy').onclick = () => slideshow.destroy();
.demo {
width: 420px;
}
ul {
list-style: none outside none;
padding-left: 0;
margin-bottom: 0;
}
li {
display: block;
float: left;
margin-right: 6px;
cursor: pointer;
}
img {
display: block;
height: auto;
max-width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lightslider/1.1.3/js/lightslider.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/lightslider/1.1.3/css/lightslider.min.css" />
<button id=init>Create</button>
<button id=destroy>Destroy</button>
<div class="demo">
<ul id="lightSlider">
<li data-thumb="http://sachinchoolur.github.io/lightslider/img/thumb/cS-1.jpg">
<img src="http://sachinchoolur.github.io/lightslider/img/cS-1.jpg" />
</li>
<li data-thumb="http://sachinchoolur.github.io/lightslider/img/thumb/cS-2.jpg">
<img src="http://sachinchoolur.github.io/lightslider/img/cS-2.jpg" />
</li>
<li data-thumb="http://sachinchoolur.github.io/lightslider/img/thumb/cS-3.jpg">
<img src="http://sachinchoolur.github.io/lightslider/img/cS-3.jpg" />
</li>
<li data-thumb="http://sachinchoolur.github.io/lightslider/img/thumb/cS-4.jpg">
<img src="http://sachinchoolur.github.io/lightslider/img/cS-4.jpg" />
</li>
<li data-thumb="http://sachinchoolur.github.io/lightslider/img/thumb/cS-5.jpg">
<img src="http://sachinchoolur.github.io/lightslider/img/cS-5.jpg" />
</li>
<li data-thumb="http://sachinchoolur.github.io/lightslider/img/thumb/cS-6.jpg">
<img src="http://sachinchoolur.github.io/lightslider/img/cS-6.jpg" />
</li>
<li data-thumb="http://sachinchoolur.github.io/lightslider/img/thumb/cS-7.jpg">
<img src="http://sachinchoolur.github.io/lightslider/img/cS-7.jpg" />
</li>
<li data-thumb="http://sachinchoolur.github.io/lightslider/img/thumb/cS-8.jpg">
<img src="http://sachinchoolur.github.io/lightslider/img/cS-8.jpg" />
</li>
<li data-thumb="http://sachinchoolur.github.io/lightslider/img/thumb/cS-9.jpg">
<img src="http://sachinchoolur.github.io/lightslider/img/cS-9.jpg" />
</li>
<li data-thumb="http://sachinchoolur.github.io/lightslider/img/thumb/cS-10.jpg">
<img src="http://sachinchoolur.github.io/lightslider/img/cS-10.jpg" />
</li>
<li data-thumb="http://sachinchoolur.github.io/lightslider/img/thumb/cS-11.jpg">
<img src="http://sachinchoolur.github.io/lightslider/img/cS-12.jpg" />
</li>
<li data-thumb="http://sachinchoolur.github.io/lightslider/img/thumb/cS-13.jpg">
<img src="http://sachinchoolur.github.io/lightslider/img/cS-13.jpg" />
</li>
</ul>
</div>

Close menu when clicking anywhere in the document body, except the menu itself

I have a menu that opens when the user clicks the icon. I want the menu to close when the user clicks anywhere else on the page, but I'm having trouble finishing the function. Below is my html and functions:
<div id="header">
<div id="menu">
<div class="menu-container" id="myLinks">
<?php wp_nav_menu(array('container_class' => 'hike-menu', 'theme_location' => 'home-top')); ?>
<?php wp_nav_menu(array('container_class' => 'hike-menu', 'theme_location' => 'hike')); ?>
<?php wp_nav_menu(array('container_class' => 'primary-menu', 'theme_location' => 'primary')); ?>
</div>
<a href="javascript:void(0);" class="icon" onclick="myToggleFunction()" id="toggle-menu">
<span></span>
</a>
</div>
</div>
function myToggleFunction() {
var element = document.getElementById("toggle-menu");
element.classList.add("active");
var x = document.getElementById("myLinks");
if (x.style.width === "290px") {
x.style.width = "0px";
element.classList.remove("active");
} else {
x.style.width = "290px";
}
}
jQuery(document.body).click(function(e) {
if (jQuery("#toggle-menu").hasClass("active") && jQuery("#myLinks").css("width", "290px")) {
jQuery("#myLinks").css("width", "0px");
jQuery("#toggle-menu").removeClass("active");
}
});
When the user clicks on "toggle-menu", the menu opens. The myToggleFunction() works great, but it's getting the menu to close when I click anywhere outside of it that's the problem. Does anyone know how I can rework my function to achieve this?
Check the event.target to determine whether the menu should be closed or not.
$(function() {
$("html").on("click", function(e) {
let $t = $(e.target),
$myLinks = $("#myLinks"),
$toggleMenu = $("#toggle-menu");
if ($t.is($myLinks) || $myLinks.has($t).length) {
//clicked in the menu. do nothing
} else if ($t.is($toggleMenu) || $toggleMenu.has($t).length) {
$myLinks.toggleClass("open");
} else {
$myLinks.removeClass("open");
}
})
});
html,
body {
margin: 0;
min-height: 100%;
background: #eee;
}
#myLinks {
background: #ccc;
max-height: 0px;
height:auto;
overflow: hidden;
transition: max-height 0.4s;
}
#myLinks.open {
max-height: 200px;
}
#myLinks a {
display: block;
margin: 10px;
}
#toggle-menu {
background: pink;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="header">
<div id="menu">
<div class="menu-container" id="myLinks">
menu
items
here
</div>
<a href="#" class="icon" id="toggle-menu">
<span>toggle menu</span>
</a>
</div>
</div>
you can set the your close menu function on body and set e.stopPropagation() on menu itself

How to shade an image and keep the value assigned in it in javascript?

I would like to know how I can click on an image like this
If I click on the BMW or Toyota logo then it shades the icon I have selected with CSS then keep that 'value' and save it in javascript variable so I can use later.
Let's say I have this
<ul class="car_types">
<li class="bmw"><img src="test/bmw.png"></li>
<li class="audi"><img src="test/audi.png"></li>
<li class="toyota"><img src="test/toyota.jpg"></li>
<li class="benz"><img src="test/benz.jpg">Discover</li>
</ul>
or i have
<table>
<tr>
<div class="car_types">
<img id="bmw" src="test/bmw.png">
<img id="audi" src="test/audi.png">
<img id="toyota" src="test/toyota.jpg">
<img id="benz" src="test/benz.jpg">
</div>
</tr>
</table>
or any other way of doing it.
Many thanks.
You need to add an event listener to each of your images, so that you can select which image should be highlighted.
Then, create a special css class which gives a special style to the selected image.
I've created a simple demo below:
Here, we have a listener that listens on the "click" event on the <li> elements inside of your .car_types list. When we do click on an image, we remove any elements that might have the shaded class (from a previous click), and then add the shaded class to the one we just clicked on.
The shaded class just gives a 50% brightness, instead of 100%.
$(".car_types li").on("click", function(){
$(".car_types li").each(function() {
$(this).removeClass("shaded");
});
$(this).addClass("shaded");
});
.car_types li {
display: inline-block;
}
.shaded {
filter: brightness(50%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="car_types">
<li class="bmw"><img src="http://via.placeholder.com/135x135"></li>
<li class="audi shaded"><img src="http://via.placeholder.com/135x135"></li>
<li class="toyota"><img src="http://via.placeholder.com/135x135"></li>
<li class="benz"><img src="http://via.placeholder.com/135x135"></li>
</ul>
If you want to be able to shade several logos at once, try this instead:
$(".car_types li").on("click", function(){
if($(this).hasClass("shaded")) {
$(this).removeClass("shaded");
} else {
$(this).addClass("shaded");
}
});
.car_types li {
display: inline-block;
}
.shaded {
filter: brightness(50%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="car_types">
<li class="bmw"><img src="http://via.placeholder.com/135x135"></li>
<li class="audi shaded"><img src="http://via.placeholder.com/135x135"></li>
<li class="toyota"><img src="http://via.placeholder.com/135x135"></li>
<li class="benz"><img src="http://via.placeholder.com/135x135"></li>
</ul>
Here it is with pure JS
HTMLCollection.prototype.each = function(cb) { for(var i = 0; i < this.length; i++) {
cb(this[i], i);
}
}
var imgs = document.getElementsByTagName('img');
imgs.each(function(img) {
img.addEventListener('click', function(ev) {
imgs.each(function(img) {
img.classList.remove('selected');
});
ev.target.classList.add('selected');
});
});
img {
opacity: .8;
}
.selected {
opacity: 1;
}
<ul class="car_types">
<li class="bmw"><img src="test/bmw.png"></li>
<li class="audi"><img src="test/audi.png"></li>
<li class="toyota"><img src="test/toyota.jpg"></li>
<li class="benz"><img src="test/benz.jpg">Discover</li>
</ul>
Considering you have added event listener like this,
Have a global variable in your js file and modify it on click event..
var selectedVal; //global variable for value
$(".car_types li").on("click", function(){
$(".car_types li").each(function() {
$(this).removeClass("shaded");
});
$(this).addClass("shaded");
selectedVal=$(this).data("val"); //modifying global variable
});
//access selectedVal anywhere
HTML:
<ul class="car_types">
<li class="bmw" data-val="bmw"><img src="test/bmw.png"></li>
<li class="audi" data-val="audi"><img src="test/audi.png"></li>
<li class="toyota" data-val="toyota"><img src="test/toyota.jpg"></li>
<li class="benz" data-val="benz"><img src="test/benz.jpg">Discover</li>
</ul>
CSS:
.shaded{
box-shadow:0px 0px 20px black;
}
Usually, you add a click listener to the image. This click listener then adds a selected class to the image. The image has styles which it applies when there is a .selected class on the image. These styles should then shade the image. The click listener also sets the JavaScript variable which you can then use.
Here is an example with plain JavaScript (no jQuery):
var selectedCar = 'no car selected';
var allCarTypes = document.querySelectorAll('.car_type');
allCarTypes.forEach(function (item) {
item.addEventListener('click', function (event) {
var selectedElement = event.target;
removeSelectedClassForAllElements();
selectedElement.classList.add('selected');
selectedCar = selectedElement.id;
});
});
function removeSelectedClassForAllElements () {
allCarTypes.forEach(function (item) {
item.classList.remove('selected');
});
}
.car_type {
width: 130px;
height: 130px;
position: relative;
cursor: pointer;
}
.car_type:after {
content: "";
position: absolute;
top: 0;
left: 0;
display: block;
height: 100%;
width: 100%;
background: rgba(0, 0, 0, 0.5);
transition: 0.3s ease all;
opacity: 0;
visibility: hidden;
}
.car_type.selected:after {
opacity: 1;
visibility: visible
}
<div class="car_types">
<img id="bmw" class="car_type" src="test/bmw.png">
<img id="audi" class="car_type" src="test/audi.png">
<img id="toyota" class="car_type" src="test/toyota.jpg">
<img id="benz" class="car_type" src="test/benz.jpg">
</div>
<!-- do not use 'onclick' -->
<button onclick="alert(selectedCar);">Which car is selected?</button>

Animated navigation-bar doesn't work

I have a problem with my navigation dropout-menu. My result should be that if I click on a div, that the dropout-menu continuously will vary from height (0px to 400px and back). This means that I have to use a if-statement. The problem is that the dropout-menu only works the first time, but I click again, the height stays at 400px, so the if-statement isn't correct I think.
HTML:
<div id="menuIcon" onclick="openMenu()">
<div id="bar"> </div>
<div id="bar"> </div>
<div id="bar"> </div>
<div id="bar"> </div>
</div>
<div id="dropBar">
<ul>
<li> Portfolio </li>
<li> About me </li>
<li> Contact </li>
</ul>
</div>
CSS:
#dropBar {
text-align: center;
width: 100%;
background-color: white;
height: 0px;
overflow-x: hidden;
transition: 0.3s;
}
JAVASCRIPT:
function openMenu() {
var x = document.getElementById('dropBar');
if (x.style.height = "0px") {
x.style.height = "400px";
} else {
x.style.height = "0px";
}
}
In if statement you shouldn't use single equality sign. Use === equality operator like this:
if (x.style.height === "0px") {
x.style.height = "400px";
}
With this little change, your function works:
https://jsfiddle.net/rgbgtL08/
First of all, with a single = you're assigning not comparing
Then you should use clientHeight instead of style.height which returns the CssStyleDeclaration
function openMenu() {
var x = document.getElementById('dropBar');
// double == for comparison
// clientHeight returns a number
if (x.clientHeight == 0) {
//do some
} else {
//dome sone else
}
}
note
clientHeight includes padding in the calc

Adding navigation buttons below my slider

I created a fade slider with images, text and links. I'd like to add some navigation bullets below it to control the images.
like this :
http://www.parallaxslider.com/preview_images/skins/bullets_skin.jpg
Here is the slider code:
html
<div class="slides">
<div class="slidiv">
<a href="..." ><img src="..." >
<span> text1 </span></a>
</div>
<div class="slidiv">
<a href="..." ><img src="..." >
<span> text2 </span></a>
</div>
<div class="slidiv">
<a href="..." ><img src="..." >
<span> text3 </span></a>
</div>
<div class="slidiv">
<a href="..." ><img src="...">
<span> text4 </span></a>
</div>
</div>
CSS
.slides {
overflow:hidden;
top:0;
position:relative;
width:100%;
height:206px;
z-index:920;
border-bottom:white 6px solid;
}
.slides img {
position:absolute;
left:0;
top:0;
}
.slides span {
position: absolute;
right: 100px;
top: 160px;
color:white !important;
font-size:20px;
}
Javascript
<script type="text/javascript">
$(function() {
$('.slides .slidiv:gt(0)').hide();
setInterval(function () {
$('.slides').children().eq(0).fadeOut(2000)
.next('.slidiv')
.fadeIn(2000)
.end()
.appendTo('.slides');
}, 6000); // 6 seconds
});
</script>
You have to define a unique id for each slide, then build html for circles (make sure you have a way of referencing which circle matches up to which slide). Then you capture the on click event, clear the interval, cycle forward until the slide in the "current" position matches the circle, then create the interval again. And of course every time it cycles forward you need to set a visual cue for the circle associated with the active slide.
(Demo)
HTML
<div class="slider">
<div class="slides">
<div class="slidiv" id="1">
<a href="...">
<img src="http://placehold.it/350x150/3296fa/ffffff">
<span>text1</span>
</a>
</div>
<div class="slidiv" id="2">
<a href="...">
<img src="http://placehold.it/350x150/fa9632/ffffff">
<span>text2</span>
</a>
</div>
<div class="slidiv" id="3">
<a href="...">
<img src="http://placehold.it/350x150/ff3399/ffffff">
<span>text3</span>
</a>
</div>
<div class="slidiv" id="4">
<a href="...">
<img src="http://placehold.it/350x150/33ff99/ffffff">
<span>text4</span>
</a>
</div>
</div>
<div class="circles">
</div>
</div>
CSS
.circles, .circle {
display: inline-block;
}
.circles {
position: relative;
left: 50%;
transform: translateX(-50%);
}
.circle {
padding: 5px;
border-radius: 100%;
border: 1px solid #444;
}
.active {
background: rgb(50, 150, 250);
}
JAVASCRIPT
$(function () {
$('.slides .slidiv:gt(0)').hide();
$.fn.setActive = function () {
if ($(this).hasClass("slider")) {
$(".active", $(this)).removeClass("active");
$("#circle-" + $(".slidiv:first-child", $(this),$(this)).attr("id"),$(this)).addClass("active");
return this;
}
return false;
}
$.fn.cycleFwd = function(rateStart,rateEnd) {
if ($(this).hasClass("slider")) {
$('.slides', $(this)).children()
.eq(0)
.fadeOut(rateStart)
.next('.slidiv')
.fadeIn(rateEnd)
.end()
.appendTo($('.slides', $(this)));
$(this).setActive($('.slidiv:first-child',$(this)).attr("id"));
return this;
}
return false;
}
$.fn.cycleFwdTo = function (id,rate) {
if($(this).hasClass("slider")) {
var current = $(".slidiv:first-child", $(this));
if(current.attr("id") === id) return true;
var count = id;
if(current.attr("id") > id) {
count = Number(current.nextAll().length) + Number(id) + 1;
}
if(count - current.attr("id") === 1) {
$(this).cycleFwd(rate,2000);
} else {
$(this).cycleFwd(rate,0);
$(this).cycleFwdTo(id,0);
}
return this;
}
return false;
}
$(".circle").on("click", function () {
clearInterval(window.interval);
var newFirst = $(this).attr("data-moveto");
$(this).parent().parent().cycleFwdTo(newFirst,2000);
var self = this;
window.interval = setInterval(function () {
$(self).parent().parent().cycleFwd(2000,2000);
}, 6000); // 6 seconds
});
$('.slider').each(function(){
var self = this;
window.interval = setInterval(function () {
$(self).cycleFwd(2000,2000);
}, 6000); // 6 seconds
});
});
EDIT:
This answer is not very good because it does not very well explain how it works, but this falls into "I could write a novel" explaining all of the different methods of doing what the OP has asked and how each method works. If someone else wanted to come along and offer better explanations of how this code works, I would approve.

Categories

Resources