More Efficient Nav Effects - javascript

I just need to know if there is a more efficient way of writing this block of code for transition effects on my navigation menu. It's using ajax transitions if you're wondering why I don't just apply each class individually.
here's the javascript code:
var navA = $('#nav a'),
aboutBtn = $('#aboutBtn'),
portfolioBtn = $('#portfolioBtn'),
resumeBtn = $('#resumeBtn'),
photoBtn = $('#photoBtn');
navA.on('click', function(e) {
var $this = $(this);
e.preventDefault();
// if the resumeBtn is clicked
if ($this.attr('id') == 'resumeBtn') {
// Portfolio
portfolioBtn.removeClass('portfolioActive');
portfolioBtn.addClass('portfolio');
//About Me
aboutBtn.removeClass('aboutActive');
aboutBtn.addClass('about');
// Photo
photoBtn.removeClass('photoActive');
photoBtn.addClass('photo');
// Resume
resumeBtn.removeClass('resume');
resumeBtn.addClass('resumeActive');
}
// If portfolioBtn Is Clicked
else if ($this.attr('id') == 'portfolioBtn') {
// About
aboutBtn.removeClass('aboutActive');
aboutBtn.addClass('about');
// Resmue
resumeBtn.removeClass('resumeActive');
resumeBtn.addClass('resume');
// Photo
photoBtn.removeClass('photoActive');
photoBtn.addClass('photo');
// Portfolio
portfolioBtn.removeClass('portfolio');
portfolioBtn.addClass('portfolioActive');
}
// If photoBtn Is Clicked
else if($this.attr('id') == 'photoBtn') {
// About
aboutBtn.removeClass('aboutActive');
aboutBtn.addClass('about');
// Portfolio
portfolioBtn.removeClass('portfolioActive');
portfolioBtn.addClass('portfolio');
// Resume
resumeBtn.removeClass('resumeActive');
resumeBtn.addClass('resume');
// Photo
photoBtn.removeClass('photo');
photoBtn.addClass('photoActive');
}
// If aboutBtn is clicked
else if ($this.attr('id') == 'aboutBtn') {
// Portfolio
portfolioBtn.removeClass('portfolioActive');
portfolioBtn.addClass('portfolio');
// About Me
aboutBtn.removeClass('about');
aboutBtn.addClass('aboutActive');
// Resume
resumeBtn.removeClass('resumeActive');
resumeBtn.addClass('resume');
// Photo
photoBtn.removeClass('photoActive');
photoBtn.addClass('photo');
};
});
Html:
<div id="nav">
<a class="resume" href="resume.html" id="resumeBtn">Resume</a>
<a class="portfolio" href="portfolio.html" id="portfolioBtn">Portfolio</a>
<a class="photo" href="photos2.html" id="photoBtn">Photos</a>
<a class="aboutActive" href="index.html" id="aboutBtn">About Me</a>
</div>
The CSS classes uses images for the transitions, but either way. I just wanna know if there's a more efficient way to write my jQuery. I'm sure there is I'm just having a stupid moment. Thanks!
EDIT: I'm structuring the code differently in how it handles the panel switches and this section of code is just designed to handle the Nav transitions.
So essentially, I removed the bottom of eachIFstatement so it only handles the the nav transitions.

Well, if your panels have the same HTML structure as your navs, this will work:
$('#nav a').on('click', function (e) {
e.preventDefault();
//Buttons
$('#' + this.id).addClass('active').siblings().removeClass('active');
// Panels
$('#' + this.id.slice(0, this.id.lastIndexOf('Btn')) + 'Panel').show().siblings().hide();
notworkOn = false;
switch (this.id) {
case 'portfolioBtn':
handlePortfolio();
break;
case 'aboutBtn':
handleAbout();
break;
}
});
function handlePortfolio() { arrange(); }
function handleAbout() {
arrange();
$('#header .inner').animate({ width: '100%' }, 600);
}
That assumes your panels HTML structure is similar to your Buttons, and named resumePanel etc. Sample here: http://jsfiddle.net/9vwYm/1/
Edit: Your current code seems to have some inconsistencies in it, e.g. clicking the Photo button displays the Photo panel, and then when you click on About, the Photo panel is not hidden. Is this intentional?

A bit messy, but twice as short and wo/ repetitive error-prone parts.
var pages = [
{ title: 'about',
showPanel: aboutPanel,
dontHidePanels: [photoPanel, resumePanel],
extracode: function() {
notworkOn = false;
arrange();
$('#header .inner').animate({
width: '100%'
}, 600);
}
},
{ title: 'protfolio',
showPanel: horizon,
dontHidePanels: [resumePanel],
extracode: function() {
arrange()
notworkOn = false;
}
},
{ title: 'resume',
showPanel: resumePanel,
dontHidePanels: [servicesPanel],
extracode: function() {
notworkOn = false;
}
},
{ title: 'photo',
showPanel: photoPanel,
dontHidePanels: [resumePanel],
extracode: function() {
notworkOn = false;
}
}
];
var panels = [ aboutPanel, horizon, photoPanel, resumePanel, servicesPanel];
$('#nav a').on('click', function(e) {
e.preventDefault();
var curPageTitle = this.id.match(/(\w+)Btn/)[1];
var p = null;
for (var i = 0; i < pages.length; i++) {
if (pages[i].title == curPageTitle) {
$('#' + pages[i].title + 'Btn')
.removeClass(pages[i].title + 'Active')
.addClass(pages[i].title);
p = pages[i];
} else {
$('#' + pages[i].title + 'Btn')
.removeClass(pages[i].title)
.addClass(pages[i].title + 'Active');
}
}
for (var i = 0; i < panels.length; p++) {
if (panels[i] == p.showPanel) {
panels[i].css('display', 'block');
} else if ($.inArray(panels[i], p.dontHidePanels) != -1) {
panels[i].css('display','none');
}
}
p.extracode();
});

I would change your class structure to use a separate active class:
<div id="nav">
<a class="resume" href="resume.html" id="resumeBtn">Resume</a>
<a class="portfolio" href="portfolio.html" id="portfolioBtn">Portfolio</a>
<a class="photo" href="photos2.html" id="photoBtn">Photos</a>
<a class="about active" href="index.html" id="aboutBtn">About Me</a>
</div>
And then do this with the script (EDIT missed the fact that your header animation was only for the about, so changed that below):
$('#nav a').on('click', function(e) {
var $this = $(this);
e.preventDefault();
//Toggle active
$this.parent().find('.active').toggleClass('active');
$this.toggleClass('active');
//Hide All Panals
horizon.css('display','none');
aboutPanel.css('display','none');
photoPanel.css('display', 'none');
resumePanel.css('display', 'none');
//Show Correct Panel
switch($this.id){
case 'resumeBtn':
resumePanel.css('display', 'block');
break;
case 'portfolioBtn':
horizon.css('display','block');
break;
case 'photoBtn':
photoPanel.css('display','block');
arrange();
break;
case 'aboutBtn':
aboutPanel.css('display','block');
arrange();
$('#header .inner').animate({
width: '100%'
},600);
break;
}
notworkOn = false;
};
});

Related

Item soft rejected due to Proper Event Binding issue

An item I've submitted to themeforest.net got soft rejected with the following message:
PROPER EVENT BINDING: Consider using the preferred .on() method rather than .click(), .bind(), .hover(), etc. For best performance and concise code use event delegation whenever possible
I have no idea what to do actually and would appreciate some help.
This is my code (it’s quite long sorry):
jQuery(document).ready(function($) {
"use strict";
// PRELOADER
$(window).load(function() {
$('#preloader').fadeOut('slow', function() {
$(this).remove();
});
});
// NAV BR RESIZING
$(document).on("scroll", function() {
if ($(document).scrollTop() > 50) {
$("header").removeClass("large").addClass("small");
} else {
$("header").removeClass("small").addClass("large");
}
});
// MOBILE MENU TRIGGER
$('.menu-item').addClass('menu-trigger');
$('.menu-trigger').click(function() {
$('#menu-trigger').toggleClass('clicked');
$('.container').toggleClass('push');
$('.pushmenu').toggleClass('open');
});
// SEARCH
$('.search').click(function(e) {
$(".search-overlay").addClass("visible");
e.preventDefault();
});
$('.close-search').click(function(e) {
$(".search-overlay").removeClass("visible");
e.preventDefault();
});
// FOUNDATION INITIALIZER
$(document).foundation();
// LIGHTCASE
$('a[data-rel^=lightcase]').lightcase({
showSequenceInfo: false,
});
// CONTDOWN
$('[data-countdown]').each(function() {
var $this = $(this),
finalDate = $(this).data('countdown');
$this.countdown(finalDate, function(event) {
$this.html(event.strftime('' +
'<span class="time">%D <span>days</span></span> ' +
'<span class="time">%H <span>hr</span></span> ' +
'<span class="time">%M <span>min</span></span> ' +
'<span class="time">%S <span>sec</span></span>'));
});
});
// SCROLLDOWN BUTTON
$(".show-scrolldown-btn").append("<div class='scrolldown-btn reveal-from-bottom'></div>")
$('.scrolldown-btn').on('click', function() {
var ele = $(this).closest("div");
// this will search within the section
$("html, body").animate({
scrollTop: $(ele).offset().top + 70
}, 500);
return false;
});
// ISOTOPE MASONRY
$(window).load(function() {
var $container = $('.grid');
$container.isotope({
itemSelector: '.grid-item',
columnWidth: '.grid-sizer',
});
var $optionSets = $('.filter'),
$optionLinks = $optionSets.find('a');
$optionLinks.click(function() {
var $this = $(this);
if ($this.hasClass('active')) {
return false;
}
var $optionSet = $this.parents('.filter');
$optionSet.find('.active').removeClass('active');
$this.addClass('active');
// make option object dynamically, i.e. { filter: '.my-filter-class' }
var options = {},
key = $optionSet.attr('data-option-key'),
value = $this.attr('data-option-value');
value = value === 'false' ? false : value;
options[key] = value;
if (key === 'layoutMode' && typeof changeLayoutMode === 'function') {
changeLayoutMode($this, options);
} else {
$container.isotope(options);
}
return false;
});
});
//BACK TO TOP
var offset = 300,
offset_opacity = 1200,
scroll_top_duration = 700,
$back_to_top = $('.backtotop');
$(window).scroll(function() {
($(this).scrollTop() > offset) ? $back_to_top.addClass('is-visible'): $back_to_top.removeClass('is-visible fade-out');
if ($(this).scrollTop() > offset_opacity) {
$back_to_top.addClass('fade-out');
}
});
$back_to_top.on('click', function(event) {
event.preventDefault();
$('body,html').animate({
scrollTop: 0,
}, scroll_top_duration);
});
});
So you would change event listener assignments like the following:
$('.search').click(function(e) {
$(".search-overlay").addClass("visible");
e.preventDefault();
});
...to use the corresponding on method instead, passing the event name as an argument:
$('.search').on("click", function(e) {
$(".search-overlay").addClass("visible");
e.preventDefault();
});
Event delegation is avoiding adding several event listeners to specific nodes and instead adding a single event listener to a common parent element, which then looks to see which child element was clicked on.
There's a good article here:
https://www.google.co.uk/amp/s/davidwalsh.name/event-delegate/amp

Settings button become disabled after updating the page

Take a look at the settings button:
It is working properly, but after updating the page in WordPress, the settings button becomes Not clickable. Is this caused by js and some jQuery functions?
Here's the js code:
if(action === 'blog'){
var parentDiv = jQuery(this).parents('.dx-columns');
// Show hidden divs inside blog dialog
jQuery('#dx-blog-dialog').find('div').css('display', 'block');
if(parentDiv.find('.hidden').length){
jQuery('#dx_blog_posts_num').val(parentDiv.find('.hidden').html());
var images = parentDiv.attr('data-blog-image');
var excerpts = parentDiv.attr('data-blog-excerpt');
if(images=='true')
{
jQuery('#dx_blog_featured_image').attr('checked', true);
}
if(excerpts=='true')
{
jQuery('#dx_blog_excerpt').attr('checked', true);
}
}
jQuery('#dx-blog-dialog').dialog({
width: 500,
height: 230,
close: function( event, ui ) {
jQuery( this ).dialog( "destroy" );
// Make divs inside blog dialog hidden
jQuery('#dx-blog-dialog').find('div').css('display', 'none');
},
buttons: {
'Save': function () {
var num = $(document).find('#dx_blog_posts_num').val();
var image = $(document).find('#dx_blog_featured_image').is(':checked');
var excerpt = $(document).find('#dx_blog_excerpt').is(':checked');
parentDiv.attr('data-blog-image', image);
parentDiv.attr('data-blog-excerpt', excerpt);
avoidXSSNum = num.replace("script", "");
var check = parentDiv.find('.hidden').length;
if(!check) {
parentDiv.append('<div class="hidden">' + avoidXSSNum + '</div>');
}
else{
parentDiv.find('.hidden').html(avoidXSSNum);
}
jQuery(this).dialog('destroy');
// Make divs inside blog dialog hidden
jQuery('#dx-blog-dialog').find('div').css('display', 'none');
}
}
});
}
Or is it some WordPress bug? I'm not sure what is happening. Any help will be appreciated?. HTML for the button:
<i class="fa fa-cog pull-right dx-setting-column js-setting-column" title="Element Setting"></i>

Toggle ".show" and ".hide" with a condition that always ".show" if browser viewport is at certain width or larger. (Responsive/Mobile Menu)

I have a responsive menu. When the menu reaches tablet/mobile width it turns into a mobile menu. In the menu are 2 special buttons. #toggleReg and #toggleLogin
When the menu dropdown is Open. #toggleReg and #toggleLogin are set to .show but when the menu dropdown is closed they are set to .hide ... simple enough.
But because this is part of a responsive menu. I need #toggleReg and #toggleLogin to always .show if the browser viewports width is above 768px;
How do I add a condition that will solve this problem for me. Since it is currently set to be hidden once reaching a width below 768px; via a media query and then told to display again if the mobile menu is "opened" via the js snippet below.
Here is my current code.
$.fn.menumaker = function(options) {
var cssmenu = $(this), settings = $.extend({
title: "Menu",
format: "dropdown",
sticky: false
}, options);
return this.each(function() {
cssmenu.prepend('<div id="menu-button">' + settings.title + '</div>');
$(this).find("#menu-button").on('click', function(){
$('#toggleReg').hide();
$('#toggleLogin').hide();
$(this).toggleClass('menu-opened');
var mainmenu = $(this).next('ul');
if (mainmenu.hasClass('open')) {
mainmenu.hide().removeClass('open');
}
else {
mainmenu.show().addClass('open');
$('#toggleReg').show();
$('#toggleLogin').show();
if (settings.format === "dropdown") {
mainmenu.find('ul').show();
}
}
});
I am working with cssmenumaker source file
Thanks for any help!
I think if you just handle the window size before your allow the click, you should be able to make sure the buttons show up. Then if the window is smaller, it will check for the button being pressed.
$.fn.menumaker = function(options) {
var cssmenu = $(this), settings = $.extend({
title: "Menu",
format: "dropdown",
sticky: false
}, options);
return this.each(function() {
cssmenu.prepend('<div id="menu-button">' + settings.title + '</div>');
//Add this clause
if($(window).width() >= 768){
$('#toggleReg').show();
$('#toggleLogin').show();
} else {
$(this).find("#menu-button").on('click', function(){
$('#toggleReg').hide();
$('#toggleLogin').hide();
$(this).toggleClass('menu-opened');
var mainmenu = $(this).next('ul');
if (mainmenu.hasClass('open')) {
mainmenu.hide().removeClass('open');
} else {
mainmenu.show().addClass('open');
$('#toggleReg').show();
$('#toggleLogin').show();
if (settings.format === "dropdown") {
mainmenu.find('ul').show();
}
}
}
});
}
This won't work on window resize though - only when the window loads.
UPDATE
This is how I would normally write it:
function menuState() {
var winW = $(window).width();
if(winW >= 768) {
//Handle Large Menu
$('#toggleReg').show();
$('#toggleLogin').show();
} else {
//Handle Mobile Menu
$('#toggleReg').hide();
$('#toggleLogin').hide();
$(document).on('click', '#menu-button', function() {
var menuClass = $(this).attr('class').split(" ")[1];
if(menuClass == "menu-opened") {
$(this).removeClass('menu_opened');
$(this).next('ul').removeClass('open');
} else {
$(this).addClass('menu-opened');
var mainMenu = $(this).next('ul');
if(mainMenu.hasClass('open')) {
mainMenu.hide().removeClass('open');
} else {
mainMenu.show().addClass('open');
$('#toggleReg').show();
$('#toggleLogin').show();
if (settings.format === "dropdown") {
mainmenu.find('ul').show();
}
}
}
});
}
}
$(document).ready(function(){
menuState();
});
$(window).resize(function(){
menuState();
});
You may be able to comment out the function and just plaster this in that javascript file.

JS if there is a slider show it

I'm no JS expert but I'm trying to alter this so that if there is a royalslider display it… if there isn't display the static image and the title and description. Any ideas as to why this isn't working? my head is currently spinning… I've left some space around the section I'm trying to add to the code under //royal slider fix and currently its just showing the title and description from the if statement. But, the markup is showing the slider div and outputting the code.
Any help would be very appreciated! You can preview this code and what I'm trying to do here... http://bvh.delineamultimedia.com/?page_id=2
;(function($) {
$.fn.SuperBox = function(options) {
var superbox = $('<div class="superbox-show"></div>');
var superboximg = $('<img src="" class="superbox-current-img">');
var superboxclose = $('<div class="superbox-close"></div>');
superbox.append(superboximg).append(superboxclose);
return this.each(function() {
$('.superbox').on('click', '.superbox-list', function() {
//allows for superbox to work inside of quicksand
$('ul.filterable-grid').css({overflow: 'visible'});
var currentimg = $(this).find('.superbox-img');
superbox.find('.title').remove();
superbox.find('.description').remove();
var imgData = currentimg.data();
superboximg.attr('src', imgData.img);
if (imgData.title) { superbox.append('<h3 class="title">'+imgData.title+'</h3>'); }
if (imgData.description) { superbox.append('<div class="description">' + imgData.description + '</div>'); }
//royal slider fix
superbox.find('.royalSlider').remove(); // remove the slider from previous events
var imgData = currentimg.data();
var sliderData = currentimg.next('.royalSlider'); // grab the slider html that we want to insert
superboximg.attr('src', imgData.img);
if (sliderData) { // show the slider if there is one
superbox.clone().append(sliderData); // clone the element so we don't loose it for the next time the user clicks
} else { // if there is no slider proceed as before
if (imgData.img) {
superbox.append(imgData.img);
}
if (imgData.title) {
superbox.append('<h3 class="title">' + imgData.title + '</h3>');
}
if (imgData.description) {
superbox.append('<div class="description">' + imgData.description + '</div>');
}
}
if($('.superbox-current-img').css('opacity') == 0) {
$('.superbox-current-img').animate({opacity: 1});
}
if ($(this).next().hasClass('superbox-show')) {
superbox.toggle();
} else {
superbox.insertAfter(this).css('display', 'block');
}
$('html, body').animate({
scrollTop:superbox.position().top - currentimg.width()
}, 'medium');
});
$('.superbox').on('hover', '.superbox-list', function(e) {
$(this).find('.overlay').stop()[(e.type == 'mouseenter') ? 'fadeIn' : 'fadeOut']('slow');
});
$('.superbox').on('click', '.superbox-close', function() {
$('.superbox-current-img').animate({opacity: 100}, 200, function() {
$('.superbox-show').slideUp();
});
});
});
};
})(jQuery);
This is only intended to be hints, not an attempt to solve the entire problem.
Try this:
var superbox = $('<div class="superbox-show"/>');
var superboximg = $('<img src="" class="superbox-current-img"/>');
var superboxclose = $('<div class="superbox-close"/>');
if (sliderData.length > 0)
Where is imgData.img getting its value?

Collapsible Panel from Right to Left

I am using a jQuery collapsible panel from Right to Left but it's not working properly, when clicking to close and Highlight the active Link...
Please, find the link :
http://jsfiddle.net/egUHv/
and the code is :
$(function() {
$('#nav').stop().animate({'marginRight':'-100px'},1000);
function toggleDivs() {
var $inner = $("#nav");
if ($inner.position().right == "-100px") {
$inner.animate({right: 0});
$(".nav-btn").html('<img src="images/slide-out.png" alt="open" />')
}
else {
$inner.animate({right: "100px"});
$(".nav-btn").html('<img src="images/slide-out.png" alt="close" />')
}
}
$(".nav-btn").bind("click", function(){
toggleDivs();
});
});
See this : http://jsfiddle.net/egUHv/5/
$(function() {
$('#nav').stop().animate({'margin-right':'-100px'},1000);
function toggleDivs() {
var $inner = $("#nav");
if ($inner.css("margin-right") == "-100px") {
$inner.animate({'margin-right': '0'});
$(".nav-btn").html('<img src="images/slide-out.png" alt="open" />')
}
else {
$inner.animate({'margin-right': "-100px"});
$(".nav-btn").html('<img src="images/slide-out.png" alt="close" />')
}
}
$(".nav-btn").bind("click", function(){
toggleDivs();
});
});
jQuery's .position() does not return an object with a right property so your current code always go in the else condition (since $inner.position().right === undefined !== '-100px').
.position() returns an object with left and top properties.
Here's a solution using class toggle on the #nav element to determine if the nav is closed/opened instead of checking the position of the element:
$(function() {
$('#nav')
.stop()
.animate({'marginRight':'-100px'},1000, function() { $(this).addClass('closed'); });
function toggleDivs() {
var $inner = $("#nav");
var $img = $(".nav-btn img", $inner);
if ($inner.hasClass('closed')) {
$inner.animate({ right: "100px" });
$img.attr('alt', 'close');
} else {
$inner.animate({ right: 0 });
$img.attr('alt', 'open');
}
$inner.toggleClass('closed');
}
$(".nav-btn").bind("click", function() {
toggleDivs();
});
});

Categories

Resources