I'm new to Dojo (quite experienced in jQuery) for a project, and am working on adding/removing some classes that will change styles for main navigation links and drop-downs.
Here is the code I've written:
dojo.addOnLoad(function() {
dojo.query('#primary-nav > ul > li > div').forEach(function(container) {
var hoverToggles = dojo.query('> a, > ul', container),
link = dojo.query('> a', container);
dojo.connect(link, 'onmouseover', function() {
dojo.addClass(hoverToggles, 'hover');
});
dojo.connect(link, 'onmouseout', function() {
dojo.removeClass(hoverToggles, 'hover');
});
});
});
No code placed into the event handlers is run (console.log, alert). Values for link and hoverToggles are correct.
Am I doing something wrong here?
Side question: Is there a more Dojo-idiomatic way of doing this?
dojo.query() returns a NodeList. dojo.addClass() and the rest work with DOM nodes.
Try something like that:
dojo.addOnLoad(function() {
dojo.query('#primary-nav > ul > li > div').forEach(function(container) {
var hoverToggles = dojo.query('> a, > ul', container),
link = dojo.query('> a', container);
link.onmouseover(function() {
hoverToggles.addClass('hover');
});
link.onmouseout(function() {
hoverToggles.removeClass('hover');
});
});
});
Related
I'm trying to transform a fieldset with one legend and one UL of checkboxes/radio as a select html element. I know, it sounds bad and doesn't really make sense, but let's just say I have to do it.
I have a jsfiddle https://jsfiddle.net/demj49st/
The problem is that I have some issues replicating the click behavior of the select element. I don't find the right selector to make it so a click on a checkbox wont make the fake select box disappear.
(function($) {
$(document).ready(function() {
$('fieldset legend').on('click', function() {
var $this = $(this);
$this.toggleClass('active');
$this.next().toggleClass('visible');
})
$(document).on('click', function (e) {
if($('ul').hasClass('visible') && !$('fieldset legend').is(e.target)) {
$('ul').removeClass('visible');
$('legend').removeClass('active');
}
});
})
})(jQuery);
$(document).ready(function() {
$('fieldset legend').on('click', function() {
var $this = $(this);
$this.toggleClass('active');
$this.next().toggleClass('visible');
});
$(document).on('click', function (e) {
if (!$("fieldset > ul , fieldset > legend").is(e.target) // if the target of the click isn't the container...
&& $("fieldset > ul , fieldset > legend").has(e.target).length === 0) // ... nor a descendant of the container
{
$('fieldset > ul').removeClass('visible');
}
});
});
DEMO
I'm having a bit of trouble with a dropdown menu that triggers fadeOut as soon as the mouse leaves the grandparent div, I've searched this problem to death and have yet to find an elegant solution. Here is my code : link
var main = function() {
$('nav').mouseenter(function() {
$('ul li ul').fadeIn('400');
});
$('nav ul li').mouseleave(function(){
$('ul li ul').fadeOut('400');
});
}
$(document).ready(main);
DEMO: MY FIDDLE
You need to specify what element(s) you are trying to attach the event to. By adding '>' youre forcing to only attach the event to that element's children. Try this:
var main = function() {
$('nav').mouseenter(function() {
$(this).find('ul').fadeIn('400');
});
$('nav>ul>li').mouseleave(function() {
$(this).find('ul').fadeOut('400');
});
};
FIDDLE
$(this).find('ul').fadeOut('400');
is correct as $('ul>li>ul').fadeOut('400'); Could not target specific (current) li.
Use following hierarchical flow of TAGS
var main = function() {
$('nav').mouseenter(function() {
$('ul li ul').fadeIn('400');
});
$('nav ul li').mouseleave(function() {
$(this).find('ul').fadeOut('400');
});
};
How can I do so that even "toggle_cart" is clickable in the same way as "clickerHeader"
but retains its hover effect (see arrow)?
please see http://jsfiddle.net/realitylab/STE48/3
$('.eventMenu > ul').toggleClass('no-js js');
$('.eventMenu .js ul').hide();
$(document).on("click", function(e) {
var $elem = $(e.target);
if ($elem.hasClass('clickerHeader')) {
$('.eventMenu .js ul').not($elem.next('ul')).hide();
$elem.next("ul").slideToggle();
} else if (!$($elem).parents('.contentHolderHeader').length) {
//} else {
$('.eventMenu .js ul').hide();
}
});
Just wrap both elements in a div ..
http://jsfiddle.net/STE48/5/
.
In the CSS add:
.eventMenu:hover .no-js .contentHolderHeader {
display: block;
}
Also add a display: none to div.eventMenu .contentHolderHeader.
Replace the JS with:
$('.eventMenu > ul').toggleClass('no-js js');
$(".toggle_cart").click(function(e){
$(".contentHolderHeader").slideToggle();
e.stopPropagation();
});
$(".eventMenu").click(function(e){
e.stopPropagation();
});
$(document).click(function(){
$(".contentHolderHeader").slideUp();
});
Remove the inner ul in the HTML.
Tested with/without JS: http://jsfiddle.net/vuF9n/2/
A minimal change to your existing code is to add the following two lines after the first line of your click function:
if ($elem.hasClass('toggle_cart'))
$elem = $elem.next();
In other words, if the span with the arrow is clicked, pretend that actually the anchor element was clicked. In context:
$(document).on("click", function(e) {
var $elem = $(e.target);
if ($elem.hasClass('toggle_cart'))
$elem = $elem.next();
if ($elem.hasClass('clickerHeader')) {
// etc.
Demo: http://jsfiddle.net/STE48/6/
My pjax is working fine, but I need to do different things on different pjax events. Here is my pjax:
//MainMenu
$(document).pjax('.menu li a', '.pjax_submenu', { fragment: '.pjax_submenu', timeout: 5000});
//SubMenu
$(document).pjax('.submenu li a', '.submenu', { fragment: '.submenu', timeout: 5000 });
Basicly I have these two menues and want to do stuff on pjax:start and pjax:end. Unfortunatly these events are always called. e.g.:
$("body").on("pjax_event", ".pjax_submenu", function(e, category){
$(document).on('pjax:start', function() {
if(category === 1){
$('.pjax_submenu').fadeOut(500);
} else{
$('.info').slideUp(500);
}
});
$(document).on('pjax:end', function() {
if(category === 1){
$('.pjax_submenu').hide().fadeIn(500);
} else{
$('.info').hide().slideDown(500);
}
});
});
$("body").on("click", ".menu li a", function() {
$(".pjax_submenu").trigger("pjax_event", 1);
});
$("body").on("click", ".submenu li a", function() {
$(".pjax_submenu").trigger("pjax_event", 2);
});
It doesn't matter if I click on a menu or a sub menu link, the result is the execution of all pjax code.
Even if I do it like this:
$("body").on("click", ".menu li a", function() {
$(document).on('pjax:start', function() { stuff }
$(document).on('pjax:end', function() { stuff }
});
$("body").on("click", ".submenu li a", function() {
$(document).on('pjax:start', function() { stuff }
$(document).on('pjax:end', function() { stuff }
});
It still executes >both< and I can't seem to get my head around a method to distinguish the pjax events on different clicked items.
What I want to do is fade content on a main menu point and use slideUp/Down for the sub menu info boxes.
Tell me if you need any additional information, every help is appreciated!
I wanted to share my solution, it's not too pretty - but it works marvelous! Also it's the only solution I found...
You will need the pjax version that's readable!
Search pjax.js for "pjax:end". Add the paragrpah below:
fire('pjax:end', [xhr, options])
if(options.menu == 'main'){
fire('pjax:main:end', [xhr, options])
}else if(options.menu == 'sub'){
fire('pjax:sub:end', [xhr, options])
}
same for pjax:start!
You can then declare your pjax links with:
//MainMenu
$(document).pjax('.menu li a', '.pjax_submenu', {menu: 'main',fragment:'.pjax_submenu', timeout: 5000});
//SubMenu
$(document).pjax('.submenu li a', '.submenu', { menu: 'sub',fragment: '.submenu', timeout: 5000 });
and voilĂ you have the separate events:
//... for Main Menu
$(document).on('pjax:main:start', function() {
console.log('pjax:main:start');
});
$(document).on('pjax:main:end', function() {
console.log('pjax:main:end');
});
//... for Sub Menu
$(document).on('pjax:sub:start', function() {
console.log('pjax:sub:start');
});
$(document).on('pjax:sub:end', function() {
console.log('pjax:sub:end');
$('.info') .slideDown(500);
});
Hope this helps someone in the future!
Cheers!
I have a code
var prev;
function addClass( classname, element ) {
prev = cn;
var cn = document.getElementById(element);
$(cn).addClass("selected");
}
The element in the dom look like this:
<div class="arrowgreen">
<ul>
<li>Manager</li>
<li>Planner</li>
<li>Administrator</li>
</ul>
</div>
For 'arrowgreen' I have a styling which changes the li styling on rollover and click.
When an element is clicked on, I want to apply the 'selected' classname to the element.
It does this for a split second and then reverts back.
The css looks like
.arrowgreen li a.selected{
color: #26370A;
background-position: 100% -64px;
}
Working jsFiddle Demo
In usage of $ in your code, I see that you are using jQuery.
There is no need to set onclick internally.
Let's jQuery handle it for you:
// wait for dom ready
$(function () {
// when user clicks on elements
$('.arrowgreen li a').on('click', function (e) {
// prevent default the behaviour of link
e.preventDefault();
// remove old `selected` classes from elements
$('.arrowgreen li a').removeClass('selected');
// add class `selected` to current element
$(this).addClass('selected');
});
});
Working JSFiddle
There was an error in your HTML, a " that opened a new string after onclick.
var prev;
function addClass(classname, element) {
var cn = document.getElementById(element);
prev = cn; //does nothing useful really
$(cn).addClass("selected");
}
<div class="arrowgreen">
<ul>
<li>Manager
</li>
<li>Planner
</li>
<li>Administrator
</li>
</ul>
</div>
Remember to include jQuery in your page!
There is a way to do this without jQuery anyway:
function addClass(classname, element) {
var cn = document.getElementById(element);
prev = cn; //does nothing useful really
cn.className += " " + classname;
}
Similar way to do it:
(function ($) {
$('.arrowgreen > ul > li > a').on('click', function (e) {
e.preventDefault();
$(this).addClass('selected').siblings().removeClass('selected');
});
}(jQuery));