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

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();
});
});

Related

function handle jQuery event and parameter?

Take the following code,
// Update button clicked
function updateEntity(e) {
e.preventDefault();
var name = $(this).attr("name");
...
// some stuff
...
}
$(document).on("click", ".updateEntity", updateEntity);
Currently I have this for (go figure) updating an entity I've editted on button click. Now, its parameter is particularly expecting a jQuery event. However, I want to also be able to call this function (end goal: to minimize code) outside of a jQuery event. Like so,
// Do an update but then redirect to prevent adding the same estimate twice.
function createEstimate(e) {
updateEntity(e);
var link = $(this).attr("href");
window.location.href = link;
}
$(document).on("click", ".createEntity", createEstimate);
Question: How would I go about calling updateEntity or setting the function up, so that I can supply it to the click-event handler and call it like a function and still have it used correctly? Is this goal realistic or should I be structuring this differently if I want to achieve such a goal?
(Encase it is not obvious, my current problem is that on the function call updateEntity(e); $(this) becomes window instead of the clicked link.)
Use .call to set this correctly:
updateEntity.call(this, e);
Learn more about this.

Why is eventListener being removed after removing parent child

I have three different event listeners, one for opening a lightbox, one for closing lightbox, and one for adding a watch later feature.
So when after clicking the close button none of the eventListeners exist anymore. the basic code example:
var a ={
open_lightbox:function(ele){
ele.addEventListener('click',function(){
//code that creates dynamic html and so forth.
},false);
},
close_lightbox:function(){
var closer = a.get('.lightbox_close')[0];
closer.addEventListener('click',function(){
var p = this.parentNode.parentNode.parentNode;
p.parentNode.removeChild(p);
},false);
},
watch_later:function(ele){
ele.addEventListener('click',function(){
//uses localStorage to save data and then adds parameters
},false);
},
get:function(ele){ return document.querySelectorAll(ele); }
};
var lightbox = a.get('.lightbox_button'),i;
for(i=0;i<lightbox.length;i++){
a.open_lightbox(lightbox[i]);
}
Now when ever I click the main event open_lightbox, I can't reopen the lightbox nor click the watch_later element. All the original eventListeners are removed, is it because of the false use capture? I haven't tried changing false to true though I will. I just need an explanation to why this is happening as this is my first time in years ever running into this issue.
Testing that replicates the issue:
http://jsfiddle.net/ES5h2/
I did more testing and it's not on the click of the close button but after the first click of the element to open the lightbox.
i would try not to delete the element, but to hide it
you could use
p.style.display = "none";
instead of
p.parentNode.removeChild(p);
I'm not 100% sure why this was canceling the Event Listener on each event, though I did figure out a more semantic way. Which is just doing...
document.addEventListener('click',function(e){
if(/lightbox_btn/gi.test(e.target.className)){
//perform the code
}
},false);
So really I just took it and added the event Listener to the document instead of the element itself. It works fine now

Stop propagation for a specific handler

Let's say I have custom dropdown(). When the button is clicked I want to bring up the menu, and when the user clicks outside of the menu I want it to close. So I do something like this:
$(myDropDown).mousedown(dropDownMouseDown);
$("html").mousedown(htmlMouseDown,myDropDown);
function dropDownMouseDown(event) {
event.target.open();
event.stopPropagation();//I need this line or else htmlMouseDown will be called immediately causing the dropDown-menu to close right before its opened
}
function htmlMouseDown() {
this.close();
}
Well, this works. But what if I add two of these? If I click to open the first, then the same on the second then both will be open because dropDownMouseDown stops the propagation so that htmlMouseDown never gets called for the first.
How do I get around this?
If I only had these two then adding some logic for that would of course be easy, but if the quantity is dynamic? Also I might not want to call event.stopPropagation() because it will do strange stuff to other libraries I'm using which listen for that event too?
I also tried putting this line:
$("html").mousedown(htmlMouseDown,myDropDown)
inside the dropDownMouseDown-handler but it will be called immediately anyway once the bubbling reaches the html-element.
Assuming you have a selector for your dropdows, (let's say ".dropdown"), I would try to use '.not()'
$('.dropdown').mousedown(dropDownMouseDown);
$("html").on('mousedown', htmlMouseDown);
function dropDownMouseDown(event) {
event.target.open();
}
function htmlMouseDown(event) {
$('.dropdown').not($(event.target)).close();
}
Here is a fiddle in the same idea with css classes :
http://jsfiddle.net/eFEL6/4/
What about using a variable that contains the last openened one ? There are probably many other ways of doing this, but here is a way I could think of:
var lastOpened = null; // initially nothing is open (unless something is)
Then:
function dropDownMouseDown(event) {
if (lastOpened != null) { // if one is still open
lastOpened.close(); // close it
lastOpened = null; // nothing is open anymore
}
event.target.open();
lastOpened = event.target; // now this one is open
event.stopPropagation();
}
function htmlMouseDown() {
this.close();
lastOpened = null; // nothing is open
}
That should work in a way that the last opened one always close itself before opening a new one.
Thanks for the answers. They're really appreciated. I did figure out a way of doing it that I'm satisfied with. Here's how:
$(myDropDown).mousedown(dropDownMouseDown);
$("html").mousedown(myDropDown,htmlMouseDown);//Pass in the dropDown as the data argument, which can then be accessed by doing event.data in the handler
function dropDownMouseDown(event) {
event.target.open();
}
function htmlMouseDown(event) {
if (event.target!=event.data)//event.target is the element that was clicked, event.data is set to the dropdown that this handler was added for. Unless these two elements are the same then we can...
event.data.close();///close the dropdown this handler was added for
}
Can't believe I didn't think of that. In my case though the element that opens/closes has child-elements so event.target could be one of the child elements instead of the element that the handler was attached to. So I changed my html-element-handler to this:
function htmlMouseDown(event) {
var element=event.target;
while (element) {
if (element==event.data)
return;
element=element.parentElement;
}
event.data.hide();
}

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

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.

How defined in jQuery was it a regular click on the same element or double-click?

How can I define in jQuery was it a regular click on the same element or double-click?
For example we have element like this:
<div id="here">Click me once or twice</div>
And we need to perform different actions after regular click and double-click.
I tried something like this:
$("#here").dblclick(function(){
alert('Double click');
});
$("#here").click(function(){
alert('Click');
});
But, of course, it doesn't work, everytime works only 'click'.
Then, some people showed me this:
var clickCounter = new Array();
$('#here').click(function () {
clickCounter.push('true');
setTimeout('clickCounter.pop()', 50);
if (clickCounter.length > 2) {
//double click
clickCounter = new Array(); //drop array
} else {
//click
clickCounter = new Array(); //drop array !bug ovethere
}
});
Here we tried to set the interval between clicks, and then keep track of two consecutive events, but this have one problem.. it doesn't work too.
So, someone knows how to do this? or can someone share a link to the material, where I can read about it?
From QuirksMode:
Dblclick
The dblclick event is rarely used. Even when you use it, you should be
sure never to register both an onclick and an ondblclick event handler
on the same HTML element. Finding out what the user has actually done
is nearly impossible if you register both.
After all, when the user double–clicks on an element one click event
takes place before the dblclick. Besides, in Netscape the second click
event is also separately handled before the dblclick. Finally, alerts
are dangerous here, too.
So keep your clicks and dblclicks well separated to avoid
complications.
(emphasis mine)
What you are doing in your question, is exactly how it should be done.
$(".test").click(function() {
$("body").append("you clicked me<br />");
});
$(".test").dblclick(function() {
$("body").append("you doubleclicked me<br />");
});
It works and here is an demo for that.
Since, you want to detect separate single double click. There is a git project for this.
$("button").single_double_click(function () {
alert("Try double-clicking me!")
}, function () {
alert("Double click detected, I'm hiding")
$(this).hide()
})
It adds up events to detect single double clicks.
Hope it helps you now.

Categories