I am trying to retrieve the width of an element sidebar to compare it to an absolute value 250px to adapt my menu, but I'm not sure how to continue.
I need to know when my menu is open or close to delete items when it's closed.
Sorry for the little information given at the start.
Full Code JS
$(document).ready(function() {
function toggleSidebar() {
$(".button").toggleClass("active");
$(".sidebar").toggleClass("widthSidebarJs");
$(".sidebar-item").toggleClass("active");
}
$(".button").on("click tap", function() {
toggleSidebar();
});
var maxSizeSidebar = 250;
var widthSidebar = $(".sidebar").innerwidth();
function displayForXsSidebar(){
if (widthSidebar < maxSizeSidebar){
$(".displayForXs").toggleClass("displayXs");
}
}
$(document).keyup(function(e) {
if (e.keyCode === 27) {
toggleSidebar();
}
});
});
As I can guess, you need to add/remove displayXs-class on resize.
You can try to add resize() event listener.
Something like this:
$(window).on('resize', function(){
if (widthSidebar < maxSizeSidebar){
$(".displayForXs").addClass("displayXs");
} else {
$(".displayForXs").removeClass("displayXs");
}
})
But the better way is #media-queries in your css.
In you currently code, your function displayForXsSidebar() not will be run. but easily, try this, remove the function..
$(document).ready(function() { // when document ready, we calculate the width, is better.
var maxSizeSidebar = 250;
var widthSidebar = $(".sidebar").outerWidth();
alert('you widthSidebar value right now is ' + widthSidebar );
if (widthSidebar < maxSizeSidebar){
$(".displayForXs").addClass("displayXs");
} else {
$(".displayForXs").removeClass("displayXs");
}
});
live demo..
$(document).ready(function() {
var maxSizeSidebar = 250;
var widthSidebar = $(".sidebar").outerWidth();
if (widthSidebar < maxSizeSidebar){
$(".displayForXs").addClass("displayXs");
alert('you widthSidebar value right now is ' + widthSidebar + ' so we add class displayXs');
} else {
$(".displayForXs").removeClass("displayXs");
alert('you widthSidebar value right now is ' + widthSidebar + ' so we remove class displayXs');
}
});
.sidebar {
width: 240px; /* Change width here to 260px if you want */
}
.displayXs { background: #000; color: #fff; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<div class="sidebar">
MY SIDEBAR</div>
<div class="displayForXs">
My displayForXs element
</div>
Related
I am currently creating my own website. I need code to allow users to change the position of some images by dragging them. I have written this HTML, CSS and JS in separate files.
The whole click and drag think works, when I click on the image and drag it on any side, it moves.
When I release the mouse button nothing happens. I have tried break and return, but they don't stop the function. Do you have any suggestions?
PS: I'm only a beginner in JS, so if you have any other advice about my code, go for it!
class img {
constructor(id, left, top) {
this.id = "#" + id;
this.left = parseInt(left, 10);
this.top = parseInt(top, 10);
};
};
$(".draggable").on("mousedown", function detectClick(focus) {
var stop = false;
var clickPos = [focus.pageX, focus.pageY];
var selected = new img($(this).attr('id'), $(this).css("left"), $(this).css("top"));
console.log(clickPos, selected);
$(selected.id).on("mousemove", function startMvt(move) {
var newPos = [move.pageX, move.pageY];
console.log(newPos);
$(selected.id).css("top", selected.top + newPos[1] - clickPos[1]);
$(selected.id).css("left", selected.left + newPos[0] - clickPos[0]);
$(selected.id).on("mouseup", function stop() {
var stop = true
console.log("stopped moving!");
return;
});
if (stop) {
return false;
};
});
if (stop) {
return false;
};
}).delay(5);
.draggable {
position: relative;
}
#img_1 {
top: 10%;
left: 20%;
z-index: 1;
cursor: move;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<img class="draggable" id="img_1" draggable="false" src="content/medium_im_test.jpg">
$(".draggable").on("mousedown",
you are only calling a function on the event of mousedown, you need a corresponding mouseup event handler.
how about adding
.mouseup(function(){
alert('up');
});
at the end or .delay(5);
like
$(".draggable").on("mousedown", function detectClick(focus) {
var stop = false;
var clickPos = [focus.pageX, focus.pageY];
var selected = new img($(this).attr('id'), $(this).css("left"), $(this).css("top"));
console.log(clickPos, selected);
$(selected.id).on("mousemove", function startMvt(move) {
var newPos = [move.pageX, move.pageY];
console.log(newPos);
$(selected.id).css("top", selected.top + newPos[1] - clickPos[1]);
$(selected.id).css("left", selected.left + newPos[0] - clickPos[0]);
$(selected.id).on("mouseup", function stop() {
var stop = true
console.log("stopped moving!");
return;
});
if (stop) {
return false;
};
});
if (stop) {
return false;
};
}).delay(5).mouseup(function(){
alert('up');
});
it worked for me!! I am also a beginner js programmer! so I don't fully understand your code, but I think you have to do something where I put alert('up')
I would like to detect a click outside of the menu class .tab-nav-menu, on the rest of the window and add an event to close the menu with similar animation of closing.
// Menu
jQuery(function($) {
$('.header-menu-toggle').on('click', function(e){
e.preventDefault();
$('.tab-nav-menu >ul >li').animate({
opacity: 0
}, 200).animate({
bottom: '-25px'
}, 50);
if($('.tab-nav-menu').hasClass('tab-invisible') ){
$('.tab-nav-menu').css({'right':'-1em'});
$('.tab-nav-menu').removeClass('tab-invisible').addClass('tab-visible');
$(this).find('.burg').addClass('activeBurg');
}
else{
$('.tab-nav-menu').css({'right':'-100%'});
$('.tab-nav-menu').removeClass('tab-visible').addClass('tab-invisible');
$(this).find('.burg').removeClass('activeBurg');
}
var delay = 600;
var duration = 400;
if( $(".header-navigation-menu").hasClass("strip-header-menu") ){
delay = 250;
}
$('.tab-nav-menu >ul >li').each(function(){
$(this).delay(delay).animate({
opacity: 1,
bottom: 0,
}, duration);
delay += 150;
});
})
});
Thanks for your help
A simplified "on outside click" jQuery script:
$(document).ready(function () {
$(document).on('click', function (e) {
var clickedEl = $(e.target);
var outsideClicker = $('#clicker');
if ( !(clickedEl.is(outsideClicker)
|| outsideClicker.has(clickedEl).length > 0) ) { // I flipped this so you can just omit the else
console.log('I clicked outside the target!'); // do whatever you need to do here-- maybe call a function that closes the menu...
} else {
console.log('all good'); // if you don't have an else just get rid of this
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<h1> A title </h1>
<p> A paragraph and a <b id="clicker">thing <span>to</span> click </b></p>
</div>
You can extrapolate this for your purposes.
My div goes right but when i click again should be back to its original location.....
i tried many stuff but not working.Here is my code...
How do i reverse it when clicked. on every click it should be the reverse of the previous action i.e.
if on click the div moves right then on next click at the same location it should move left similar to a pendulum
<html>
<head><title></title>
<script type="text/javascript" language="javascript">
//<![CDATA[
window.onload=function()
{
document.getElementById("d2").onclick = slideIt;
};
function slideIt()
{
var slidingDiv = document.getElementById("d1");
var stopPosition = 50;
if (parseInt(slidingDiv.style.left) < stopPosition )
{
slidingDiv.style.left = parseInt(slidingDiv.style.left) + 2 + "px";
setTimeout(slideIt, 1);
}
/*
if(parseInt(slidingDiv.style.left) > stopPosition )
{
slidingDiv.style.left = parseInt(slidingDiv.style.left) + 2 + "px";
setTimeout(slideIt, 1);
}*/
}
//]]>
</script>
</head>
<body>
<div id="d1" style="position:absolute; left:-131px;">
<div style=" float:left" >click here to slide the div</div>
<div id="d2" style=" float:left" >click here to slide the div</div> </div>
</body>
</html>
Change your JavaScript with this one
<script type="text/javascript" language="javascript">
$(document).ready(function(){ $("#d2").click(function(){
if($("#d1").css("left") <="-131px")
{
$("#d1").animate({left:'250px'});
}
else {
$("#d1").animate({left:'-131px'});
}
});
});
</script>
This will work fine
Good Luck..
Okay, so here's how I have done things...
DEMO: http://jsfiddle.net/xDDX8/2/
HTML
<div id="d1">
<div id="d2">click here to slide the div</div>
</div>
CSS
#d1 {
position: absolute;
border: 1px solid red;
cursor: pointer;
left: 0;
}
.moveLeft {
color: blue;
}
.moveRight {
color: lime;
}
Javascript
window.onload = bindEvents();
function bindEvents() {
document.getElementById('d2').onclick = slideIt;
}
// Global variables
var slidingDiv = document.getElementById('d1'); // Cache the element
var timeout = 0;
var minPosition = 0;
var maxPosition = 50;
function slideIt() {
// Work out current position
var currentPosition = slidingDiv.offsetLeft;
// Check which direction to move
if (hasClass(slidingDiv, 'moveRight'))
{
// Have we hit our movement limit?
if (currentPosition <= minPosition)
{
// remove all classes and set a class to move the other direction
slidingDiv.removeAttribute('class');
slidingDiv.setAttribute('class', 'moveLeft');
// Clear our timeout
clearTimeout(timeout);
}
else
{
// Still space to move so let's move a few pixels (-)
slidingDiv.style.left = (currentPosition - 2) + "px";
timeout = setTimeout(slideIt, 1);
}
}
else // all comments as above really
{
if (currentPosition >= maxPosition)
{
slidingDiv.removeAttribute('class');
slidingDiv.setAttribute('class', 'moveRight');
clearTimeout(timeout);
}
else
{
slidingDiv.style.left = (currentPosition + 2) + "px";
timeout = setTimeout(slideIt, 1);
}
}
}
// Function to test whether an element has a specific class
// https://stackoverflow.com/questions/5898656/test-if-an-element-contains-a-class
function hasClass(element, cls) {
return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1;
}
Sorry about the confusing title, I'll explain better.
I have a 20x20 grid of div's, so its 400 of them each with an id, going from 0 to 399.
Each div is given one of three random values - red, green or blue - and when a div is clicked, a function is run to check if the div to the left, right, over and under are of the same value, if it is of the same value it will be simulated a click and the same function will run again.
The problem, is that the function sets vars, so if it finds that the div below has the same value, it will overwrite the vars set by the first click, hence never click any of the others.
JSfiddle - http://jsfiddle.net/5e52s/
Here is what I've got:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>untiteled</title>
<style>
body {
width: 420px;
}
.box {
width: 19px;
height: 19px;
border: 1px solid #fafafa;
float: left;
}
.box:hover {
border: 1px solid #333;
}
.clicked {
background: #bada55 !important;
}
</style>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
$().ready(function(){
var colors = ['red', 'green', 'blue'];
var i = 0;
while(i<400){
var color = colors[Math.floor(Math.random() * colors.length)];
$('.test').append('<div class="box" id="'+i+'" value="'+color+'" style="background:'+color+';">'+i+'</div>');
i++;
}
$('.box').click(function(){
var t = $(this);
t.addClass('clicked');
id = t.attr('id');
val = t.attr('value');
//Set color
up = parseInt(id) - 20;
right = parseInt(id) + 1;
down = parseInt(id) + 20;
left = parseInt(id) - 1;
clickup = false;
clickdown = false;
if($('#'+down).attr('value') === val){
clickdown = true;
}
if(up > -1 && ($('#'+up).attr('value') === val)){
clickup = true;
}
if(clickdown == true){
$('#'+down).click();
}
if(clickup == true){
$('#'+up).click();
}
});
});
</script>
</head>
<body>
<div class="test">
</div>
</body>
I think the biggest root cause of your problem is you don't check if it already has class 'clicked' or not. That could make the infinite recursive. For example, if you click on the div#2 then the div#1 receives a simulated click, and div#2 receives a simulated click from div#1.
$('.box').click(function(){
var t = $(this);
if(t.hasClass('clicked')) {
return;
}
t.addClass('clicked');
var id = t.attr('id');
var val = t.attr('value');
//Set color
var up = parseInt(id) - 20;
var right = (id%20 != 19) ? ((0|id) + 1) : 'nothing' ;
var down = parseInt(id) + 20;
var left = (id%20 != 0) ? ((0|id) - 1) : 'nothing';
console.log(up, right, down, left);
if($('#'+down).attr('value') === val) {
$('#'+down).click();
}
if($('#'+right).attr('value') === val) {
$('#'+right).click();
}
if($('#'+up).attr('value') === val) {
$('#'+up).click();
}
if($('#'+left).attr('value') === val) {
$('#'+left).click();
}
});
You can schedule the clicks onto the event loop instead of calling them directly, eg:
if(clickdown == true){
setTimeout(function () {
$('#'+down).click();
});
}
I don't think that's your root cause though, it's probably a combination of global vars and scope issues. Try reformatting as such:
$('.box').click(function (event){
var t = $(this), id, val, up, right, down, left, clickup, clickdown;
//...
Your variables id and val are not in a var statement, thus are implicitly created as members of the window object instead of being scoped to the local function. Change the semicolon on the line before each to a comma so that they become part of the var statement, and your code should begin working.
So,
if($(this).hasClass('active')){
$(this).removeClass('active');
$(this).prev().addClass('active');
}
works fine, it adds the class "active" to this previous div of the same kind.
if($(this).hasClass('active')){
$(this).removeClass('active');
$(this).next().addClass('active');
}
However, adds the class to the next div (as i intend for it to do) for about 0.5 of a second BUT then removes it.
Here's ALL of the jQuery (as per your comments below) - Please do not comment on my horrible code organization
$(window).load(function () {
// Initial variables
var numberSlides = 0;
var currentSlide = 1;
var ready = true;
var pageWidthR = $(document).width() - 352;
var pageWidthL = $(document).width() - 352;
// Update number of slides by number of .slide elements
$('#features-slider .slide').each(function () {
numberSlides++;
});
// Go through each slide and move it to the left of the screen
var i = 0;
$($('#features-slider .slide').get().reverse()).each(function () {
if (i == 0) {
} else {
var newWidth = i * 115;
$(this).css('left', '-' + newWidth + '%');
}
i++;
});
// Animate the first slide in
$('#features-slider .slide:last-child').addClass('active').animate({
left: 0
}, 1500);
// Remove the loading message
$('#loading').fadeOut(1000, function () {
$('#loading').remove();
// Now that we're done - we can show it
$('#features-slider').show();
});
/***** Left and Right buttons *****/
/* Right */
$('#rightbutton').click(function () {
var numberSlides = 0;
$('#features-slider .slide').each(function () {
numberSlides++;
});
var index = $('.slide.active').index() + 1;
if (!$('.slide').is(':animated') && index != 1) {
$('#features-slider .slide').each(function () {
if ($(this).hasClass('active')) {
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft) + 115;
} else {
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft) + 115;
}
$(this).animate({
left: newLeft + '%'
}, 1500);
if ($(this).hasClass('active')) {
$(this).removeClass('active');
$(this).prev().addClass('active');
}
});
}
});
/* Left */
$('#leftbutton').click(function () {
var numberSlides = 0;
$('#features-slider .slide').each(function () {
numberSlides++;
});
var index = $('.slide.active').index() + 1;
if (!$('.slide').is(':animated') && index != numberSlides) {
$('#features-slider .slide').each(function () {
if ($(this).hasClass('active')) {
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft) - 115;
} else {
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft) - 115;
}
$(this).animate({
left: newLeft + '%'
}, 1500);
if ($(this).hasClass('active')) {
$(this).next().addClass('active');
$(this).removeClass('active').not($(this).next());
}
});
}
});
});
$(document).ready(function () {
// Hide the slider and show a loading message while we do stuff and the images / DOM loads - Also disable overflow on the body so no horizontal scrollbar is shown
$('body').css('overflow-x', 'hidden');
$('#features-slider').hide();
$('#loading').html('<center> <img id="loader" src="/wp-content/themes/responsive/library/images/ajax-loader.gif" /> Loading</center>');
});
RESOLVED
New left button function :
$('#leftbutton').click(function(){
var numberSlides = 0;
$('#features-slider .slide').each(function(){
numberSlides++;
});
var index = $('.slide.active').index()+1;
if( !$('.slide').is(':animated') && index != numberSlides ){
var done = false;
$('#features-slider .slide').each(function(){
if($(this).hasClass('active')){
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft)-115;
} else {
var currentLeft = $(this).css('left');
var newLeft = parseInt(currentLeft)-115;
}
$(this).animate({left: newLeft+'%'}, 1500);
if($(this).hasClass('active') && done == false){
$(this).next().addClass('active');
$(this).removeClass('active');
done = true;
}
});
});
If you're iterating forward through the elements, then it should be clear what's going on - you add the "active" class to the next element, and then the next iteration takes it away.
This is just a guess however as you did not post enough code for me (or anybody else) to be sure.
edit — ok now that you've updated the question, it's clear that the guess was correct. The .each() function will iterate forward through the elements. When an element has the "active" class, and the code removes it and adds it to the next element, then on the next iteration the work is undone.
Since you are referencing this and by the behavior you're describing, you are likely iterating a loop for a list of elements. As a result, you are completing the action you want but the next iteration is removing the previous changes due to your usage of removing a class and then adding the class back.
As it stands now, your code does not illustrate how this occurence can be happening.
Update:
As suspected, you seem to be looping as signified by: each(function(){. While iterating through your objects the class is being pushed forward and is not acting as desired. You are stating add the class to the next element, but remove it from the current element, and this behavior continues through your iteration.
On a side note, update your code to call removeClass() on the current object first, before adding it to the next object:
if ($(this).hasClass('active')) {
$(this).removeClass('active').next().addClass('active');
}