Attach material.io menu component to all elements with same class - javascript

I'm trying to figure out a way to attach the material.io menu across a webpage that has multiple menus. I tried to use jQuery each function but obviously the code does not work. Here is the original code suggested by material.io (works for one menu only)
var menu_element = document.querySelector('.obox-admin-menu') !== null;
if (menu_element) {
var menuEl = document.querySelector('.obox-admin-menu');
var menu = new mdc.menu.MDCMenu(menuEl);
var menuButtonEl = document.querySelector('.obox-admin-menu-btn');
menuButtonEl.addEventListener('click', function() {
menu.open = !menu.open;
});
}
And here is my attempt with jQuery but it failed.
$( '.mdc-menu-anchor' ).each(function() {
var menuEl = $( this ).find('.obox-admin-menu');
var menu = new mdc.menu.MDCMenu(menuEl);
var menuButtonEl = $( this ).find('.obox-admin-menu-btn');
$( document ).on( 'click', menuButtonEl, 'click', function() {
menu.open = !menu.open;
});
});
What I'm doing wrong here? I'm trying to make menu trigger for multiple elements with same class and markup, I thought that could be possible with a loop but I'm new to javascript.
UPDATE
based on comment by connexo I have now added the functionality I am looking for with this (hope this code approach is fine)
var list = document.querySelectorAll( '.mdc-menu-anchor' );
Array.prototype.forEach.call(list, function (item) {
var menuEl = item.querySelector('.obox-admin-menu');
let menu = new mdc.menu.MDCMenu(menuEl);
let menuButtonEl = item.querySelector('.obox-admin-menu-btn');
menuButtonEl.addEventListener('click', function() {
menu.open = !menu.open;
});
});

Related

Triggering fluffy.js

I'm trying to make a simple tumblr theme using the fluffy plugin (https://github.com/mzdr/fluffy.js) but I've ran into a problem. The plugin only executes once on page load. I'm trying to get it to work with the infinite scroll plugin (http://www.infinite-scroll.com/) and I need the fluffy plugin to trigger whenever new content loads.
I'm fairly new when it comes to JS so I appreciate any help I can get. Thanks.
Edit added code:
<script src="https://code.jquery.com/jquery-2.2.2.min.js"></script>
<script src="https://npmcdn.com/imagesloaded#4.1/imagesloaded.pkgd.min.js"></script>
<script src="http://static.tumblr.com/hpghjri/co2nfnr1j/infinitescroll.min.js"></script>
<script src="http://static.tumblr.com/nxwjyyg/XWUob8gtq/fluffy.min.js"></script>
<script>
$(function(){
app.initInfinite();
app.onImagesLoad();
}); //end document ready
var app = {
'initInfinite' : function() {
var $container = $('.page-index .posts');
$container.infinitescroll({
navSelector:".pagination",
nextSelector:".pagination-next",
itemSelector:".posts__container",
appendCallback:true,
loading:{
finishedMsg:" ",
img:"data:image/gif;base64,R0lGODlhAQABAHAAACH5BAUAAAAALAAAAAABAAEAAAICRAEAOw==",
msg:null,
msgText:" ",
selector:null,
finished:function() {
}
}
},
function(newElements) {
var $newElems = $(newElements).css({opacity:0});
var $newElemsIDs = $newElems.map(function() {
return this.id;
Tumblr.LikeButton.get_status_by_post_ids($newElemsIDs);
}).get();
$newElems.imagesLoaded(function() {
$newElems.animate({opacity: 1});
//what to do when new elems appended
// I need to trigger fluffy here
});
var $newElemsIDs = $newElems.map(function() {
return this.id;
}).get();
Tumblr.LikeButton.get_status_by_post_ids($newElemsIDs);
});
},
'onImagesLoad' : function() {
$('.content .posts').imagesLoaded()
.always( function( instance ) {
console.log('all images loaded');
$('.overlay').addClass('hide');
$('.overlay__preloader').attr('class', '');
})
.done( function( instance ) {
console.log('all images successfully loaded');
});
}
}
</script>
This is your lucky day! I just released v2.1.0 which fixes your problem. Now you can create Fluffy objects on the fly like that:
// Start automatic detection
Fluffy.detect();
// Or provide a DOM node for single creation
var myElement = document.querySelector('#what-ever-you-like');
Fluffy.create(myElement);
// Or use a selector to create one
Fluffy.create('[data-fluffy-container]');
Don't forget to check out the updated docs.

Open specific accordion tab using external link and hash

hi to all I'm new in js sorry for what I ask here now I know its a basic one, I'm working now with accordion plugin that collects all the article that users want to put in accordion and view it in accordion my question is how to open specific tab when is have dynamic id per article inside a item of accordion.. im trying to hook the item using link, http//:example.com#id to open specific tab in accordion here s the plugin code.
hook inside the code and trigger the click event to open the specific the in the accordion plugin
!(function($){
$.fn.spAccordion = function(options){
var settings = $.extend({
hidefirst: 0
}, options);
return this.each(function(){
var $items = $(this).find('>div');
var $handlers = $items.find('.toggler');
var $panels = $items.find('.sp-accordion-container');
if( settings.hidefirst === 1 )
{
$panels.hide().first();
}
else
{
$handlers.first().addClass('active');
$panels.hide().first().slideDown();
}
$handlers.on('click', function(){
if( $(this).hasClass('active') )
{
$(this).removeClass('active');
$panels.slideUp();
}
else
{
$handlers.removeClass('active');
$panels.slideUp();
$(this).addClass('active').parent().find('.sp-accordion-container').slideDown();
}
event.preventDefault();
});
});
};
})(jQuery);
A little thing is, you can use .children('div') instead of .find('>div').
But if you want to get what the hash is set to you can use window.location.hash. By default this is used to identify element IDs. So ideally you could get the element you want to show by doing
if (window.location.hash) {
var $selected = $('#'+window.location.hash);
if ($selected.length) {
// Do what you need to show this element
}
}

How to toggle svg properties using Raphaeljs and jQuery

I'm making a sidebar with sliding, accordion-like areas, so that when you click on a heading the associated content toggles visibility, as per the portion of code below. The initAccordion function also appends an svg "+" to the headings to indicate their action.
The final task is getting the svg held in the cross variable to rotate by 45 degrees on each click - which is where I'm having trouble.
Obviously, the two statements in the makeButtons function aren't accessible outside their containing function. I've tried to re-factor the code, but it ends up being a jumbled mess and I can't help thinking there must be a simple solution.
toggleContent : function(){
this.toggleClass('on').next().slideToggle(200);
cross.transform("r45");
},
makeButtons : function(el) {
var btn = Raphael(el,15,15);
var cross = btn.path(".....");
},
initAccoridon : function(){
$('#eventSideBar').find('h3').each(function(){
var btn = $('<div/>', {
class : 'sideBarBtn'
});
btn.appendTo(this);
var btnContainer = btn.get(0),
$this = $(this);
sidebar.makeButtons(btnContainer);
$this.on('click', function(){
sidebar.toggleContent.call($this);
});
});
}
I'm not sure if this is better suited to the code-review section of SO - apologies if it is; I can move it on request.
Fiddle here...
Edit: I've managed to get part of the way there, although with multiple elements, I can't get the corresponding svg to rotate; just the last one. Fiddle here, and updated code:
makeSvg : function(el) {
this.btn = Raphael(el,15,15);
this.cross = this.btn.path(".....");
return {
btn : this.btn,
cross : this.cross
};
},
toggleContent : function(){
if (this.hasClass('on')) {
sidebar.cross.transform("r0");
} else {
sidebar.cross.transform("r45");
};
this.toggleClass('on');
},
initAccordion : function(){
$('body').find('h3').each(function(){
var btn = $('<div/>', {
class : 'sideBarBtn'
});
btn.appendTo(this);
var btnContainer = btn.get(0),
$this = $(this);
sidebar.makeSvg(btnContainer);
$this.on('click', function(){
sidebar.toggleContent.call($this);
});
});
}
You will need to pass a parameter of the relevant element or capture it somehow. This example should work for multiple objects, you'll just need to add the reverse action.
jsfiddle
Relevant bit...
var sidebar = {
makeSvg : function(el) {
var btn = Raphael(el,15,15);
return btn.path(pathString).attr({fill:"#fff",stroke:"none"});
},
toggleContent : function( myCross ){
this.toggleClass('on');
myCross.transform("r45");
},
initAccordion : function(){
$('body').find('h3').each(function(){
var btn = $('<div/>', {
class : 'sideBarBtn'
});
btn.appendTo(this);
var btnContainer = btn.get(0),
$this = $(this);
var myCross = sidebar.makeSvg(btnContainer);
$this.on('click', function(){
sidebar.toggleContent.call($this, myCross);
});
});
}
};

Click event defined in another function but when triggered in view it enters a loop on Backbone

I have a button on the header file that opens a popup and I'm using Backbone to generate the views. Problem is that in one of the views I have a button that I want it to have the exact same event but when it's triggered it enters an infinite loop and I can't really understando why...
Here's the click event for the header button:
$(function() {
.....
$dnaBtn.on('click', function() {
var $overlay = $('div.overlay#dnaForm'),
$activePane = $('div.pane.active', $lightbox),
$eq = $activePane.index(),
$shape = $('.shape img').eq(0),
$shapeActive = $('.shape .active'),
$torso = $('.torso .shape img').eq(0),
$torsoActive = $('.torso .shape .active');
console.log('d');
$lightbox.fadeIn(300, 'easeInOutCubic', function() {
var $ticks = $('div.tick', $pane.first()),
$count = 0;
.....
The view
var EndTourView = Backbone.View.extend({
el: "#ism-tour",
events:{
"click a.dna-btn":"showsmth"
},
initialize:function(){
this.$el.html('');
this.render();
},
render:function(){
var template = Handlebars.compile($("#end-tour-template").html());
this.$el.html(template());
return this;
},
showsmth:function(){
var $lightbox = $('div.lightbox'),
$padding = $('div.overlay#dnaForm div.padding', $lightbox),
$animator = $('div.animator', $padding),
$pane = $('div.pane', $animator);
console.log('dddd')
$(".dna-btn").click();
}
});
Thanks in advance
You are calling the function showsmth when you click .dna-btn and then within showmsth you are clicking .dna-btn. This will invoke the function again and it will keep repeating in an infinite loop.
If they are two different .dna-btn's the $(".dna-btn").click(); calls the click event on every instance of .dna-btn. If that is the case, you'll have to call them something different.

jQuery- Inserting GET data into div only works after second trigger

I am trying to use jQuery to fetch data and place it into a div after I hover over a link. It is working, but only on the second hover. The first hover instance does not do anything. Why?
jQuery(document).ready(function($){
$(".tiptrigger").hover(function() {
var s_href = $(this).attr('href');
var s_title = $(this).attr('title');
$(".tiptitle").empty().append(s_title); // Only working after second instance
var get_url = "/root/data.php"+s_href;
$.get( get_url, function( data ) {
var tip_content = data;
$("#tipcontent").empty().append(tip_content); // Only working after second instance
});
});
And the HTML:
<a class="tiptrigger" title="My Title" href="?s=something">Hover over me</a>
<div class="tipbox"><p class="tiptitle"></p><p id="tipcontent"></p></div>
And lastly, the PHP page that the GET request is being sent to:
<?php
if ($_GET['s'] == "something") {
echo "This should appear in the paragraph.";
}
?>
What am I doing wrong here?
Provide an empty stub function for the handlerOut() second handler of .hover(), you are just providing one handler, which is executed both when going over and out of the link, so do it like this:
$(".tiptrigger").hover(function() {
var s_href = $(this).attr('href');
var s_title = $(this).attr('title');
$(".tiptitle").empty().append(s_title); // Only working after second instance
var get_url = "/root/data.php"+s_href;
$.get( get_url, function( data ) {
var tip_content = data;
$("#tipcontent").empty().append(tip_content); // Only working after second instance
}
, function() {}); //PROVIDE EMPTY HANDLER FOR MOUSEOUT

Categories