How to toggle JQueryUI Draggable on/off in an if statement - javascript

I wrote a block of code (below) that toggles JQuery Draggable on/off on an element.
In short , when you click a div called button it toggles the draggable effect on/off on another div called dragBlock
This took me awhile but I finally got it working. The question I have is I don't understand why the code below doesn't work with only one Draggable instance. Mainly the one that uses the state argument.
$(dragBlock ).draggable(state);
Instead it only works when I use this:
$(dragBlock ).draggable(state);
$(dragBlock ).draggable(); // This line is needed for the code to work. Why?
This isn't a big issue but I would like to know why this is and I figure someone here might be able to explain it. JSfiddle is here:
And the code is below:
$(document).ready(function() {
var state = "disable";
var button = document.getElementById("button");
var dragBlock = document.getElementById("dragBlock");
var toggle = function() {
if (state==="enable") {
state = "disable";
}
else if(state==="disable") {
state = "enable";
}
$(dragBlock ).draggable(state);
$(dragBlock ).draggable(); // This line is needed for the code to work. Why?
console.log(state);
};
button.addEventListener("click", toggle, false);
});

You should really have the .draggable() outside the event handler, and only the .draggable(state) inside.
Calling .draggable() is how you initially setup the draggable functionality on the element.
Calling .draggable('enable') or .draggable('disable') is a way to enable or disable an already-configured draggable element. It's a way to interact with a draggable element that you've already setup.
Note though, that by calling draggable() outside the event handler your default initial state will now be enabled. You need to either disable it immediately or change your initial value for the state variable.
You can initialize the draggable and leave it disabled with this (outside the event handler)
('#dragBlock').draggable({disabled: true});
And then you'll only need the .draggable(state) inside the event handler.

Related

Why is my element.classList.add working but toggle is not working?

I need to add/remove a class upon button click. For some reason, classList.toggle will not work but classList.add works fine.
document.querySelectorAll('.view-now').forEach( function (){
this.addEventListener('click', function(e) {
const property = e.target.closest('.property');
property.classList.toggle('expand');
});
});
Could you please change the this in the forEach since its referring to the document context instead of the specific a tag. In the original code, the page was listening for a click on the entire page, which was causing the issue you were facing.
/**** Your JS Here ****/
//define DOM element
//this makes whatver you click dissappear both boxes
document.querySelectorAll(".view-now").forEach(function(item) {
item.addEventListener("click", function(e) {
const property = e.target.closest(".property");
property.classList.toggle("expand");
});
});
Codepen

How to use MDC-Web methods (e.g. MDCIconButtonToggle)

I'm having trouble getting the MDC-Web methods/ framework methods to work. Specifically I'm trying to get the MDCIconButtonToggle to work. I have an icon button that can change when clicked. I thought the way I set it up was correct, but it won't toggle when clicked.
import {MDCIconButtonToggle} from '#material/icon-button';
import {MDCIconButtonToggleFoundation} from '#material/icon-button';
const iconButtonRipple = new MDCRipple(document.querySelector('.mdc-icon-button'));
iconButtonRipple.unbounded = true;
function handleToggleButtonClick(){
console.log("clicked");
const toggleBtn = new MDCIconButtonToggleFoundation(expBtn);
toggleBtn.handleClick();
}
var expBtn = document.getElementById("config-audio-button");
expBtn.addEventListener("click", handleToggleButtonClick);
When I run this, every time I click the button "clicked" is displayed in the console, as expected, but the icon doesn't change/ toggle. If I change MDCIconButtonToggleFoundation to MDCIconButtonToggle, I get an error message in console, but the button toggles.
The error message claims that either expBtn.addEventListener is not a function, or that handleClick is undefined.
I've looked through the main docs, and this, but haven't been able to figure out what I'm doing wrong.
Well done on finding a work-around this.
But for someone else that might be stuck with the same problem, here's the clear cut on how you can properly listen to events directly on a component,a button as an example:
Assume we have a button below:
const someButton = new MDCIconButtonToggle(document.querySelector('.someButton'));
We want to alert("yes") when it's clicked. We would the register the event as follows:
someButton.listen('click', ()=> { alert("yes"); });
Note:
The event name is a normal javascript event like "abort", "scroll", "change" etc.
So after even more searching around I found a listen() method in the MDC Dialog documentation. Just ctrl+f for listen and you will find a few examples.
For whatever reason this is the first and only place I've found a listen() method mentioned. If anyone knows where listen() is explicitly documented, I'd be happy to have a link to it to learn more about it.
Below is my solution. I first get an HTML collection of all the toggle-able elements. Then I iterate over them, and add the listen() event listener method to listen for a change event. Once the change event occurs, the buttons will execute handleClick()/ toggle on/off.
// Get "array" of toggle-able arrow dropdowns.
var expandableArrowButtons = document.getElementsByClassName("mdc-icon-button add-margin-bottom");
// Iterate over all 3 expandable arrow icon buttons, and listen for a change event.
[].forEach.call(expandableArrowButtons, function(element){
const toggleBtn = new MDCIconButtonToggle(element);
toggleBtn.listen('MDCIconButtonToggle:change', function(){
console.log("clicked");
const tb = new MDCIconButtonToggleFoundation(toggleBtn);
tb.handleClick();
});
});

Mouse out event doesn't move back outside the button

I have a button and when you hover over it, it shows some text and 2 more buttons but when I move my mouse out of it, it still stays on the hover. How do I make my code work so that it works on mouse out?
This is my Javascript:
var option1Button_Mouseout = function() {
console.log('option1Button_Mouseout()');
$('laStyle-option1-button')[0].innerHTML = outputTag;
};
var attachOption1ButtonListeners = function() {
console.log($('laStyle-option1-button')[0]);
$('laStyle-option1-button')[0].addEventListener('mouseover', this.option1Button_Mouseover);
// When you mouse out of the button it brings it back to the original
$('laStyle-option1-button')[0].addEventListener('mouseout', this.option1Button_Mouseout);
};
window.onload = function() {
this.attachOption1ButtonListeners();
};
this is what it currently looks like:
https://media.giphy.com/media/9A6MoIdWBiZVFtcHyW/source.mp4
See when I hover over it it shows text and 2 buttons, when I mouse out it should go back to the picture of the hand.
Sind it is not clear what your methods are doing, consider this example:
HTML
<div id="myDiv">
<div id="myDiv1"/>
</div>
JavaScript
$('#myDiv').on("mouseover mouseenter ", function (e) {
$("#myDiv1").show();
});
$('#myDiv').on("mouseleave mouseout", function (e) {
$("#myDiv1").hide();
});
When entering the parent div the inner div will be shown. When leaving the parent div the inner div will be hidden. Also using .on as you are using jquery.
Here is the JSFiddle: https://jsfiddle.net/GR8sk/21/
Since you're already using jQuery I would use its Mouseenter and mouseleave events like so:
$("document").ready(function(){
$(".laStyle-option1-button img").mouseenter(function(){
$(this).attr('src','https://media.giphy.com/media/xUOwGdPZ0chBWiQ6Ri/giphy.gif');
});
$(".laStyle-option1-button img").mouseleave(function(){
$(this).attr('src','https://media.giphy.com/media/l4pTgiQB2e2dpuKs0/giphy.gif');
});
});
Couple things to note:
You did not add a '.' to the beginning of your jQuery reference to laStyle-option1-button (look at how the period goes before) because its a class attribute.
You are performing unnecessary event listener loading. While this can be helpful for binding to click events, I would just use the 'bind' method to bind functions to click events:
$( "#btnButton" ).bind( "click", myFunction);
You need to change either the 'src' attribute of the image, or just remove the button completely and replace with another one. The former is better performing.

Close popup div if element loses focus

I have the following scenario: On a label's mouseover event, I display a div. The div must stay open in order to make selections within the div. On the label's mouseout event, the div must dissappear. The problem is that when my cursor moves from the label to the div, the label's mouseout event is fired, which closes the div before I can get there. I have a global boolean variable called canClose which I set to true or false depending on the case in which it must be closed or kept open. I have removed the functionality to close the div on the label's mouseout event for this purpose.
Below is some example code.
EDIT
I have found a workaround to my problem, event though Alex has also supplied a workable solution.
I added a mouseleave event on the label as well, with a setTimeout function which will execute in 1.5 seconds. This time will give the user enough time to hover over the open div, which will set canClose to false again.
$("#label").live("mouseover", function () {
FRAMEWORK.RenderPopupCalendar();
});
$("#label").live("mouseout", function () {
setTimeout(function(){
if(canClose){
FRAMEWORK.RemovePopupCalendar();
}
},1500);
});
this.RenderPopupCalendar = function () {
FRAMEWORK.RenderCalendarEvents();
}
};
this.RenderCalendarEvents = function () {
$(".popupCalendar").mouseenter(function () {
canClose = false;
});
$(".popupCalendar").mouseleave(function () {
canClose = true;
FRAMEWORK.RemovePopupCalendar();
});
}
this.RemovePopupCalendar = function () {
if (canClose) {
if ($(".popupCalendar").is(":visible")) {
$(".popupCalendar").remove();
}
}
};
Any help please?
I would wrap the <label> and <div> in a containing <div> then do all you mouse/hide events on that.
Check out this fiddle example - http://jsfiddle.net/6MMW6/1
Give your popupCalendar an explicit ID instead of a class selector, e.g.
<div id="popupCalendar">
Reference it with #popupCalendar instead of .popupCalendar.
Now, remove() is quite drastic as it will completely remove the div from the DOM. If you wish to display the calendar again you should just .hide() it.
But your logic seems a bit overly complex, why not just .show() it on mouseenter and .hide() on mouseout events ?
This will close the entire tab page if the tab page loses focus.
How ever if you target it, it can work for something within the page too, just change the target codes.
JavaScript:
<script type="text/javascript" >
delay=1000 // 1 sec = 1000.
closing=""
function closeme(){
closing=setTimeout("self.close()",delay)
// self means the tab page close when losing focus, but you can change and target it too.
}
<!--// add onBlur="closeme()" onfocus="clearTimeout(closing)" to the opening BODY tag//-->
</script>
HTML:
<body onBlur="closeme()" onfocus="clearTimeout(closing)">

How do I unbind another jQuery function on .click()?

I have this script that run to fix my menu bar to the browser on scroll. Nothing really needs to change here (works as it should). However, you may need it...
var div = $('#wizMenuWrap');
var editor = $('#main_wrapper');
var start = $(div).offset().top;
$(function fixedPackage(){
$.event.add(window, "scroll", function() {
var p = $(window).scrollTop();
$(div).css('position',((p)>start) ? 'fixed' : 'static');
$(div).css('top',((p)>start) ? '0px' : '');
//Adds TOP margin to #main_wrapper (required)
$(editor).css('position',((p)>start) ? 'relative' : 'static');
$(editor).css('top',((p)>start) ? '88px' : '');
});
});
Now for the issue at hand. I have another script function that calls a modal pop-up (which again works as it should). However, it's not slick from a UI perspective when I scroll the page when the modals open. So I want to disable the script above when the modal script below is called. In other words, when I click to open the modal pop-up, the script above shouldn't work.
$(function () {
var setUp = $('.setupButton');
// SHOWS SPECIFIED VIEW
$(setUp).click(function () {
$('#setupPanel').modal('show');
//PREVENTS PACKAGE SELECT FIXED POSITION ON SCROLL
$(setUp).unbind('click',fixedPackage);
});
})
As you can see above, I tried to unbind the scroll function (the first code snippet), but this is not correct.
These two scripts are in two separate js libraries.
I strongly disagree that you ought to be binding and unbinding the event. There's no need! A little logic in your scroll event to check to see if the modal is open should take care of the issue:
$(function fixedPackage(){
$(window).bind("scroll", function() {
// if the modal is displayed, do nothing
if ($('#setupPanel').is(':visible'))
return;
// -- existing code here --
});
});
This way, if the modal element is visible, the code simply stops where it is. Once you hide the element, the code will continue to work as before without having to manage the state of event in some other script... confusing!
Also, as mentioned in some other comments, don't use $.event.add, use the public API method bind
Documentation
jQuery is - http://api.jquery.com/is/
jQuery visible selector - http://api.jquery.com/visible-selector/
jQuery bind - http://api.jquery.com/bind/
When you store a jquery object into a var you can call functions directly:
var setUp = $('.setupButton');
var div = $('#wizMenuWrap');
var editor = $('#main_wrapper');
setUp.click(...);
seTup.unbind(...);
editor.css(...);
div.css(...);
all you need to do is change your script to:
$(function () {
var setUp = $('.setupButton');
// SHOWS SPECIFIED VIEW
$(setUp).bind('click',function () {
$('#setupPanel').modal('show');
//PREVENTS PACKAGE SELECT FIXED POSITION ON SCROLL
$(setUp).unbind('click');
});
})
As explained in the jQuery Docs, Event handlers attached with .bind() can be removed with .unbind() . For more information about bind and unbind:
.bind()
.unbind()
try
$(setUp).unbind('click').die('click')

Categories