Rails: jQuery - page resets before event can complete - javascript

I have a webpage, and some jQuery that I wrote, and had working functionally until I brought it into my rails application. I'm not sure if this is some turbolink issue (like I've had before) or if its unrelated.
My jQuery script is for my custom dropdown menu, and while the clicking causes the dropdown to appear, the dropdown doesn't remain, and all the html is reset. I have a video: http://tinypic.com/r/35ml7jr/8 that shows what I am trying to explain.
jQuery
$(document).on("page:change", function() {
$(".navbar-link").on("click", function() {
var el = $(this);
var dd = el.siblings();
var loc = el.offset();
var left = loc.left;
var width = el.width();
var center = left + (0.5 * width);
var corrected_center = center - 5;
var isDown = dd.hasClass('down');
var numDown = $(document).find(".down").length;
var screenWidth = $( window ).width();
// check width to determine how to proceed
if ( screenWidth > 767 ) {
// if there ARE dropdowns present, quickly hide / show
if ( numDown > 0 ) {
$(".dropdown-nav").removeClass('down');
// if THIS dropdown is down, animate w/ slide
if (dd.css("display") === "block") {
$(".dropdown-nav").slideUp();
// if ANOTHER dropdown is down, switch quickly
} else {
$(".dropdown-nav").hide();
}
// display the clicked link
if (!isDown) {
dd.addClass('down');
dd.show();
}
// if there are NO dropdowns present, animate w/ slide
} else {
$(".dropdown-nav").removeClass('down');
// if THIS dropdown is down, animate w/ slide
if (dd.css("display") === "block") {
$(".dropdown-nav").slideUp();
// if ANOTHER dropdown is down, switch quickly
} else {
$(".dropdown-nav").hide();
}
if (!isDown) {
dd.addClass('down');
dd.slideDown();
$(".rest").animate({"top": "105px"});
}
}
var isActive = el.hasClass('activate');
$(".navbar-link").removeClass('activate');
$(".arrow-up").css("left", corrected_center);
if (isActive) {
$('.arrow-up').hide(400);
} else {
$('.arrow-up').show();
el.addClass('activate');
}
// for small screens
} else {
// if there ARE dropdowns present, quickly hide / show
if ( numDown > 0 ) {
$(".dropdown-nav").removeClass('down');
// if THIS dropdown is down, animate w/ slide
if (dd.css("display") === "block") {
$(".dropdown-nav").slideUp();
// if ANOTHER dropdown is down, switch quickly
} else {
$(".dropdown-nav").slideUp();
}
// display the clicked link
if (!isDown) {
dd.addClass('down');
dd.slideDown();
}
// if there are NO dropdowns present, animate w/ slide
} else {
$(".dropdown-nav").removeClass('down');
// if THIS dropdown is down, animate w/ slide
if (dd.css("display") === "block") {
$(".dropdown-nav").slideUp();
// if ANOTHER dropdown is down, switch quickly
} else {
$(".dropdown-nav").hide();
}
if (!isDown) {
dd.addClass('down');
dd.slideDown();
}
}
}
});
});

Instead of .on('click',function(){...})
Try using
.on('click',function(event){
event.preventDefault(); // This should prevent reloading
//YOUR CODE GOES HERE
return true; // It informs, that event has ended
})

Related

JS function only works properly after clicking on screen

I am building a title generator with HTML, CSS and JavaScript. The following code is supposed to do this:
Enter Edit-Mode with pressing of the "Enter"-Key (works correctly)
Turning down the opacity of the top left and top right box by clicking on the red buttons (works)
Hiding both items when exiting Edit-Mode by pressing "Enter" again. (works)
Enter Edit-Mode again and showing both hidden div boxes with opacity set to 20% (does not work)
Only the first box that was clicked on shows up again. It seems like the class "deactivated" is not safed for the last item being clicked on as it disappears on step 3.
However it does work when I click somewhere on the document before going to step 3.
Any help appreciated!
Full version can be found here
/*Switch between Display and Edit Mode*/
function toggleHideUI() {
var HideUI = document.getElementById("hiddenUI");
if (HideUI.style.display === "block") {
hideHiddenElements();
HideUI.style.display = "none";
} else {
showHiddenElements();
HideUI.style.display = "block";
}
};
/* EventListener for "Enter" Keybind */
document.addEventListener("keydown", (e) => {
if (e.code == "Enter") {
toggleHideUI();
}
});
/*Hide hidden elements (class = "deactivated") for Display Mode */
function hideHiddenElements() {
var HiddenElements = document.getElementsByClassName("deactivated");
for (i = 0; i < HiddenElements.length; i++) {
HiddenElements.item(i).style.display = "none";
}
};
/*Show hidden elements (class = "deactivated") for Edit Mode */
function showHiddenElements() {
var HiddenElements = document.getElementsByClassName("deactivated");
for (i = 0; i < HiddenElements.length; i++) {
HiddenElements[i].style.display = 'block';
}
}
/*Toggle DB Logo in upper left corner*/
document.getElementById("hide-db-logo").onclick = function toggleDBLogo() {
document.getElementById("db-box").classList.toggle("deactivated");
}
/*Toggle Campus Logo in upper right corner*/
document.getElementById("hide-campus-logo").onclick = function toggleCampusLogo() {
document.getElementById("campus-box").classList.toggle("deactivated");
}
I have updated the working script as:
The problem is when you click enter when the element is in focus, the event is propagating back.
<script>
/*Switch between Display and Edit Mode*/
function toggleHideUI() {
let HideUI = document.getElementById("hiddenUI");
if (HideUI.style.display === "block") {
hideHiddenElements();
HideUI.style.display = "none";
} else {
showHiddenElements();
HideUI.style.display = "block";
}
};
/* EventListener for "Enter" Keybind */
document.addEventListener("keydown", (e) => {
if (e.code == "Enter") {
e.preventDefault(); //<--- notice here
toggleHideUI();
}
});
/*Hide hidden elements (class = "deactivated") for Display Mode */
function hideHiddenElements() {
let HiddenElements = document.getElementsByClassName("deactivated"); //<--- notice here use let instead of var
for (let j = 0; j < HiddenElements.length; j++) {
HiddenElements[j].style.display = "none";
}
};
/*Show hidden elements (class = "deactivated") for Edit Mode */
function showHiddenElements() {
let HiddenElements = document.getElementsByClassName("deactivated");
//<--- notice here use let instead of var
for (let i = 0; i < HiddenElements.length; i++) {
HiddenElements[i].style.display = 'block';
}
}
/*Toggle DB Logo in upper left corner*/
document.getElementById("hide-db-logo").onclick = function toggleDBLogo() {
document.getElementById("db-box").classList.toggle("deactivated");
}
/*Toggle Campus Logo in upper right corner*/
document.getElementById("hide-campus-logo").onclick = function toggleCampusLogo() {
document.getElementById("campus-box").classList.toggle("deactivated");
}
</script>
Good Luck!

jQuery: change jQuery based on window width

I have some jQuery that I want to change based on screen width. When the page loads, I want the script to determine the window width, var = width, and choose a set of functions based on that width. BUT, if the user were to resize the screen, I want the script to redefine width and choose which set of functions again.
jQuery
$(document).ready(function () {
var width = $( window ).width();
// Should I use this commented-out function below somehow???
// $(window).resize(function() {
// width = $( window ).width();
// });
// Navbar functionality
// for large screens
if ( width > 767 ) {
$(".navbar-link").on("click", function() {
var el = $(this);
var dd = el.siblings();
var loc = el.offset();
var left = loc.left;
var width = el.width();
var center = left + (0.5 * width);
var corrected_center = center - 5;
var isDown = dd.hasClass('down');
var numDown = $(document).find(".down").length;
// if there ARE dropdowns present, quickly hide / show
if ( numDown > 0 ) {
$(".dropdown-nav").removeClass('down');
// if THIS dropdown is down, animate w/ slide
if (dd.css("display") === "block") {
$(".dropdown-nav").slideUp();
// if ANOTHER dropdown is down, switch quickly
} else {
$(".dropdown-nav").hide();
}
// display the clicked link
if (!isDown) {
dd.addClass('down');
dd.show();
}
// if there are NO dropdowns present, animate w/ slide
} else {
$(".dropdown-nav").removeClass('down');
// if THIS dropdown is down, animate w/ slide
if (dd.css("display") === "block") {
$(".dropdown-nav").slideUp();
// if ANOTHER dropdown is down, switch quickly
} else {
$(".dropdown-nav").hide();
}
if (!isDown) {
dd.addClass('down');
dd.slideDown();
console.log($(".rest").css("top"));
$(".rest").animate({"top": "105px"});
}
}
var isActive = el.hasClass('activate');
$(".navbar-link").removeClass('activate');
$(".arrow-up").css("left", corrected_center);
if (isActive) {
$('.arrow-up').hide(400);
} else {
$('.arrow-up').show();
el.addClass('activate');
}
});
// For small screens
} else {
$(".navbar-link").on("click", function() {
var el = $(this);
var dd = el.siblings();
var isDown = dd.hasClass('down');
var numDown = $(document).find(".down").length;
$(".dropdown-nav").removeClass('down');
// if there ARE dropdowns present, quickly hide / show
if ( numDown > 0 ) {
$(".dropdown-nav").removeClass('down');
// if THIS dropdown is down, animate w/ slide
if (dd.css("display") === "block") {
$(".dropdown-nav").slideUp();
// if ANOTHER dropdown is down, switch quickly
} else {
$(".dropdown-nav").slideUp();
}
// display the clicked link
if (!isDown) {
dd.addClass('down');
dd.slideDown();
}
// if there are NO dropdowns present, animate w/ slide
} else {
$(".dropdown-nav").removeClass('down');
// if THIS dropdown is down, animate w/ slide
if (dd.css("display") === "block") {
$(".dropdown-nav").slideUp();
// if ANOTHER dropdown is down, switch quickly
} else {
$(".dropdown-nav").hide();
}
if (!isDown) {
dd.addClass('down');
dd.slideDown();
}
}
});
}
});
I found the easiest way to address this was to get the screen width AFTER the click event. Click -> get width -> if screen > 767 do {}, else do {}. This can be seen below.
$(document).ready(function () {
$(".navbar-link").on("click", function() {
var el = $(this);
var dd = el.siblings();
var loc = el.offset();
var left = loc.left;
var width = el.width();
var center = left + (0.5 * width);
var corrected_center = center - 5;
var isDown = dd.hasClass('down');
var numDown = $(document).find(".down").length;
var screenWidth = $( window ).width();
// check width to determine how to proceed
if ( screenWidth > 767 ) {
// if there ARE dropdowns present, quickly hide / show
if ( numDown > 0 ) {
$(".dropdown-nav").removeClass('down');
// if THIS dropdown is down, animate w/ slide
if (dd.css("display") === "block") {
$(".dropdown-nav").slideUp();
// if ANOTHER dropdown is down, switch quickly
} else {
$(".dropdown-nav").hide();
}
// display the clicked link
if (!isDown) {
dd.addClass('down');
dd.show();
}
// if there are NO dropdowns present, animate w/ slide
} else {
$(".dropdown-nav").removeClass('down');
// if THIS dropdown is down, animate w/ slide
if (dd.css("display") === "block") {
$(".dropdown-nav").slideUp();
// if ANOTHER dropdown is down, switch quickly
} else {
$(".dropdown-nav").hide();
}
if (!isDown) {
dd.addClass('down');
dd.slideDown();
console.log($(".rest").css("top"));
$(".rest").animate({"top": "105px"});
}
}
var isActive = el.hasClass('activate');
$(".navbar-link").removeClass('activate');
$(".arrow-up").css("left", corrected_center);
if (isActive) {
$('.arrow-up').hide(400);
} else {
$('.arrow-up').show();
el.addClass('activate');
}
// for small screens
} else {
// if there ARE dropdowns present, quickly hide / show
if ( numDown > 0 ) {
$(".dropdown-nav").removeClass('down');
// if THIS dropdown is down, animate w/ slide
if (dd.css("display") === "block") {
$(".dropdown-nav").slideUp();
// if ANOTHER dropdown is down, switch quickly
} else {
$(".dropdown-nav").slideUp();
}
// display the clicked link
if (!isDown) {
dd.addClass('down');
dd.slideDown();
}
// if there are NO dropdowns present, animate w/ slide
} else {
$(".dropdown-nav").removeClass('down');
// if THIS dropdown is down, animate w/ slide
if (dd.css("display") === "block") {
$(".dropdown-nav").slideUp();
// if ANOTHER dropdown is down, switch quickly
} else {
$(".dropdown-nav").hide();
}
if (!isDown) {
dd.addClass('down');
dd.slideDown();
}
}
}
});
});

Toggle mobile navigation depending on scroll direction

I have this navigation for mobile that i want to hide/show depending on which direction the viewport gets scrolled in. So if scrolling down i want it to hide, and scrolling up i want it to show.
My current code looks like this. It just toggles on scroll top. Anyone?
$(function() {
$(window).on("scroll touchmove", function () {
$('.mobile-nav').toggleClass('tiny', $(document).scrollTop() > 0);
});
});
Maybe something like this:
var menu_height = 80;
var menu_visible = true;
var old_scroll = $(window).scrollTop();
function checkMenu() {
new_scroll = $(window).scrollTop();
if (old_scroll < new_scroll && new_scroll > 0) {
// Scroll down
if (menu_visible == true) {
toggleMenu();
}
} else if (old_scroll > new_scroll) {
// Scroll up
if (menu_visible != true) {
toggleMenu();
}
}
old_scroll = new_scroll;
}
function toggleMenu() {
if (menu_visible == true) {
// Hide
$('#menu').animate({top: '-='+menu_height+'px'}, 200, function(){ $(this).css('display', 'none') });
menu_visible = false;
} else {
// Show
menu_visible = true;
$('#menu').css('display', 'block').animate({top: '+='+menu_height+'px'}, 200);
}
}
$(document).ready(function() {
// Show / hide menu on scroll
setInterval(checkMenu, 100);
});
Codepen: http://codepen.io/anon/pen/dPGggg

Paralax-style scrolling, user can scroll only one slide

I am using ScrollTo plugin to create a simple paralax-style page-changing. Here is what happens when you scroll
var location = window.location.hash;
if(location == '') { var location = '#home' } // Default location
slides = ['#home', '#about', '#characters']; // All the slides in an array
// Calculating previous and next slides
var currentEl = slides.indexOf(location);
var prevEl = currentEl - 1;
var nextEl = currentEl + 1;
if(delta > 0)
{
if(location != '#home')
{
gofor(slides[prevEl]); // Scrolling up
}
}
else
{
if(location != '#characters')
{
gofor(slides[nextEl]); // Scrolling down
}
}
});
And here is the gofor function itself.
function gofor(slide)
{
$(slide).clearQueue().ScrollTo({duration: 700}); // Scrolling to the given slide
$('.nav>a').removeClass('active'); // Removing all active classes
$(slide + '_nav').addClass('active'); // Updating the menu class with the _nav suffix id
window.location.hash = slide; // Updating the location.hash with the new position
}
This is working okay but when you scroll your wheel more than one step it goes more than one page forward. How can i stop the scrolling function for a certain amount of time (like 3 seconds) and then let the mouse regain its scrolling function again?
Thanks.

Drop down option not working in jQuery

I'm trying to build drop down options on mouse over and on click. The only problem I have with it, is when I put the mouse over an on child element, the menu gets hidden quickly.
jQuery code:
var navPos = $("#topNav").position().top; // ignore this line
// menu drop options
$('.repeat, .recitor, .volume, .bandwidthOption').bind('dropOption', function(e, force) {
var force = force || 'toggle';
if ($(this).hasClass('repeat'))
var optionName = 'repeat';
else if ($(this).hasClass('recitor'))
var optionName = 'recitor';
else if ($(this).hasClass('volume'))
var optionName = 'volume';
else if ($(this).hasClass('bandwidthOption'))
var optionName = 'bandwidthOption';
else
return;
var optionSubName = $(this).find('ul').attr('class');
var position = $(this).position();
position.top = navPos;
var isActive = $(this).hasClass('active');
if ((isActive && force != 'show') || (force && force == 'hide'))
{
$(this).removeClass('active');
$('.'+optionSubName).hide();
if (optionName == 'recitor') /* ie fix - z-index issue */
$('.logoBox').show();
}
else
{
$(this).addClass('active');
$('.'+optionSubName).show();
$('.'+optionSubName).css('left',position.left+'px');
if (optionName == 'recitor') /* ie fix - z-index issue */
$('.logoBox').hide();
}
});
$('.repeat, .recitor').click(function() {
$(this).trigger('dropOption');
return false;
});
$('.volume, .bandwidthOption').hover(function() {
$(this).trigger('dropOption', 'show');
},function() {
$(this).trigger('dropOption', 'hide');
});
Menu demo: http://jsbin.com/ozokir/2
The last bit is hiding the options:
$('.volume, .bandwidthOption').hover(function() {
$(this).trigger('dropOption', 'show');
},function() {
$(this).trigger('dropOption', 'hide');
});
Hover is only over the link option. To solve this you could use:
$('.volume, .bandwidthOption').mouseover(function() {
$(this).trigger('dropOption', 'show');
});
or click as you have in the previous line. Then you can hide with:
$('.dropOption').mouseout(function() {
$(this).trigger('dropOption', 'hide');
});

Categories

Resources