Two divs click event works only on one div - javascript

I'm using jquery and ajax to create a drawer (#DrawerContainer) and load content into it if I click a thumbnail in a gallery. My function is almost finished but I want to be able to close that drawer if I click again the opening button (now #current).
Here is a jsfiddle of my code: http://jsfiddle.net/RF6df/54/
The drawer element appears if you click a square/thumbnail, it's the blueish rectangle.
The current thumbnail is turned green.
I added a button in my drawer (not visible in the jsfiddle) to close it. I use this part of code for this purpose and it's working like a charm.
// Close the drawer
$(".CloseDrawer").click(function() {
$('#DrawerContainer').slideUp()
setTimeout(function(){ // then remove it...
$('#DrawerContainer').remove();
}, 300); // after 500ms.
return false;
});
Now I need my #current div to be able to close #DrawerContainer the same way .CloseDrawer does in the code above. Unfortunately adding a second trigger like this $("#current,.CloseDrawer").click(function() to my function isn't working... When clicking my "current" thumbnail, it just reopen the drawer instead of closing it...
How can I modify my code to close my #DrawerContainer with the "current" thumbnail?
Please keep in mind that I'm learning jquery, so if you can comment it could be of a great help. And please do not modify my markup or css, since everything works beside the closing part.

As per my understanding, you can use "toggle()" function which does exactly the same (i.e, toggle visiblity).
$('#DrawerContainer').toggle();
EDIT:
Updated the script to work.
$(document).ready(function() {
$.ajaxSetup({cache: false});
$('#portfolio-list>div:not(#DrawerContainer)').click(function() {
if ($(this).attr("id") != "current")
{
// modify hash for sharing purpose (remove the first part of the href)
var pathname = $(this).find('a')[0].href.split('/'),
l = pathname.length;
pathname = pathname[l-1] || pathname[l-2];
window.location.hash = "#!" + pathname;
$('#current').removeAttr('id');
$(this).attr('id', 'current');
// find first item in next row
var LastInRow = -1;
var top = $(this).offset().top;
if ($(this).next().length == 0 || $(this).next().offset().top != top) {
LastInRow = $(this);
}
else {
$(this).nextAll().each(function() {
if ($(this).offset().top != top) {
return false; // == break from .each()
}
LastInRow = $(this);
});
}
if (LastInRow === -1) {
LastInRow = $(this).parent().children().last();
}
// Ajout du drawer
var post_link = $(this).find('.mosaic-backdrop').attr("href");
$('#DrawerContainer').remove(); // remove existing, if any
$('<div/>').attr('id', 'DrawerContainer').css({display: 'none'}).data('citem', this).html("loading...").load(post_link + " #container > * ").insertAfter(LastInRow).slideDown(300);
return false; // stops the browser when content is loaded
}
else {
$('#DrawerContainer').slideUp(300);
$(this).removeAttr("id");
}
});
$(document).ajaxSuccess(function() {
Cufon('h1'); //refresh cufon
// Toggle/close the drawer
$("#current,.CloseDrawer").click(function() {
$('#DrawerContainer').slideToggle()
setTimeout(function(){ // then remove it...
$('#DrawerContainer').remove();
}, 300); // after 500ms.
return false;
});
});
//updated Ene's version
var hash = window.location.hash;
if ( hash.length > 0 ) {
hash = hash.replace('#!' , '' , hash );
$('a[href$="'+hash+'/"]').trigger('click');
}
});
Also, updated it here: Updated JS Fiddle
EDIT -2: Updated Link
Hope this Helps!!

Related

jQuery - To perform a search using submit button on a live search plugin?

I started using mark.js live search plugin, and I was able to modify it to automatically scroll to the text part that's being searched on the page.
Like this:
SEARCH BOX |_jklmno____| <-- User searches here
123
456
789
abcde
fghi
jklmno <--- Then the page will automatically scroll and stop here.
pqrst
-> Done, it found the text <-
The code works, how can I build a button that when submitted, the page will jump to the next result?
I tried using this to jump to the next result when the form is submitted:
$('html,body').animate({scrollTop: mark.eq(index).offset().top}, 500);
}
This too:
else if ('mark[data-markjs]').live("submit", function(e) {
e.mark();
$('html,body').animate(
{scrollTop: mark.offset().top -100}
, 200);
});
But it didn't work.
Here's the working fiddle **(In order to see the search field, you have to scroll the result tab a little bit)
And here's the jQuery:
$.noConflict()
jQuery(function($) {
var mark = function() {
// Read the keyword
var keyword = $("input[name='keyword']").val();
// Determine selected options
var options = {
"filter": function(node, term, counter, totalCounter){
if(term === keyword && counter >= 1){
return false;
} else {
return true;
}
},
done: function() {
var mark = $('mark[data-markjs]');
if (mark.length) {
$('html,body').animate({scrollTop: mark.eq(index).offset().top}, 500);
}
/*
else if ('mark[data-markjs]').live("submit", function(e) {
e.mark();
$('html,body').animate(
{scrollTop: mark.offset().top -100}
, 200);
});
*/
}
};
$("input[name='opt[]']").each(function() {
options[$(this).val()] = $(this).is(":checked"); });
// Mark the keyword inside the context
$(".context").unmark();
$(".context").mark(keyword, options);
};
$("input[name='keyword']").on("keyup", mark);
$("input[type='checkbox']").on("change", mark);
$("input[name='keyword']").on("submit", mark);
});
I played a while with your fiddle.
It's a cool problem.
I decided to use the up/down arrows to scroll to the prev/next result...
Instead of the enter key or a button.
Here is the main part that I changed:
$("input[name='keyword']").on("keyup", function(e){
if(e.which==40){ // 40 = down arrow
e.preventDefault();
arrowOffset++;
}
if(e.which==38){ // 38 = up arrow
e.preventDefault();
arrowOffset--;
if(arrowOffset<1){
arrowOffset=1;
}
}
mark(arrowOffset);
});
I did not found how to "un-highlight" the previous result...
But since arrows make it scroll to the right result, I think it is quite cool like this.
done: function() {
var mark = $('mark[data-markjs]').last(); // Scroll to last <mark>
if (mark.length) {
$('html,body').animate({scrollTop: mark.offset().top-90}, 500);
}
}
Have a look at my fiddle for the complete updated script.

How to give a div a higher z-index on click with JS?

I asked this question yesterday hopefully this one is clearer as I've now provided a working example of my store.
I'm developing a Shopify Theme. I've been using Timber as my base and I'm currently having a problem with my Quick Cart and Quick Shop/View drawers.
I have 2 drawers on the right of my site, 1 for the cart and 1 for the product quick view option. The drawers currently slide open - #PageContainer moves to the left on click to reveal each drawer.
As they are currently sitting on top of each other I need to alter the JS so that on click the z-index changes so that the correct drawer being called is highest in the stack.
I'm not great with JS so not sure if this is a simple task?
Here is a link to my Dev Store
JS:
timber.Drawers = (function () {
var Drawer = function (id, position, options) {
var defaults = {
close: '.js-drawer-close',
open: '.js-drawer-open-' + position,
openClass: 'js-drawer-open',
dirOpenClass: 'js-drawer-open-' + position
};
this.$nodes = {
parent: $('body, html'),
page: $('#PageContainer'),
moved: $('.is-moved-by-drawer')
};
this.config = $.extend(defaults, options);
this.position = position;
this.$drawer = $('#' + id);
if (!this.$drawer.length) {
return false;
}
this.drawerIsOpen = false;
this.init();
};
Drawer.prototype.init = function () {
$(this.config.open).on('click', $.proxy(this.open, this));
this.$drawer.find(this.config.close).on('click', $.proxy(this.close, this));
};
Drawer.prototype.open = function (evt) {
// Keep track if drawer was opened from a click, or called by another function
var externalCall = false;
// Prevent following href if link is clicked
if (evt) {
evt.preventDefault();
} else {
externalCall = true;
}
// Without this, the drawer opens, the click event bubbles up to $nodes.page
// which closes the drawer.
if (evt && evt.stopPropagation) {
evt.stopPropagation();
// save the source of the click, we'll focus to this on close
this.$activeSource = $(evt.currentTarget);
}
if (this.drawerIsOpen && !externalCall) {
return this.close();
}
// Add is-transitioning class to moved elements on open so drawer can have
// transition for close animation
this.$nodes.moved.addClass('is-transitioning');
this.$drawer.prepareTransition();
this.$nodes.parent.addClass(this.config.openClass + ' ' + this.config.dirOpenClass);
this.drawerIsOpen = true;
// Run function when draw opens if set
if (this.config.onDrawerOpen && typeof(this.config.onDrawerOpen) == 'function') {
if (!externalCall) {
this.config.onDrawerOpen();
}
}
if (this.$activeSource && this.$activeSource.attr('aria-expanded')) {
this.$activeSource.attr('aria-expanded', 'true');
}
// Lock scrolling on mobile
this.$nodes.page.on('touchmove.drawer', function () {
return false;
});
this.$nodes.page.on('click.drawer', $.proxy(function () {
this.close();
return false;
}, this));
};
Drawer.prototype.close = function () {
if (!this.drawerIsOpen) { // don't close a closed drawer
return;
}
// deselect any focused form elements
$(document.activeElement).trigger('blur');
// Ensure closing transition is applied to moved elements, like the nav
this.$nodes.moved.prepareTransition({ disableExisting: true });
this.$drawer.prepareTransition({ disableExisting: true });
this.$nodes.parent.removeClass(this.config.dirOpenClass + ' ' + this.config.openClass);
this.drawerIsOpen = false;
this.$nodes.page.off('.drawer');
};
return Drawer;
})();
Update
As instructed by Ciprian I have placed the following in my JS which is making the #CartDrawer have a higher z-index. I'm now unsure how I adapt this so that it knows which one to have higher dependant on which button is clicked. This is what I've tried:
...
Drawer.prototype.init = function () {
$(this.config.open).on('click', $.proxy(this.open, this));
$('.js-drawer-open-right-two').click(function(){
$(this).data('clicked', true);
});
if($('.js-drawer-open-right-two').data('clicked')) {
//clicked element, do-some-stuff
$('#QuickShopDrawer').css('z-index', '999');
} else {
//run function 2
$('#CartDrawer').css('z-index', '999');
}
this.$drawer.find(this.config.close).on('click', $.proxy(this.close, this));
};
...
The approach would be like this:
$('.yourselector').css('z-index', '999');
Add it (and adapt it to your needs) inside your onclick() function.
if you need to modify the z-index of your div when clicking a buton, you shoud put in this code on your onclick() function, else if you need to activate it when you looding the page you shoud put it on a $( document ).ready() function , the code is :
$('#yourID').css('z-index', '10');
You can use:
document.getElementById("your-element-id").style.zIndex = 5;
It's pure Javascript and sets the z-index to 5. Just bind this to onClick event!

How can I retain the scroll position of a scrollable area when pressing back button?

I have a long list of links inside a big scrollable div. Each time when a user click on a link then click the back button, it starts at the very top of the div. It is not user friendly to our users. Any ways to let the browser scroll to the previous position when pressing the back button?
Thank you very much!
During page unload, get the scroll position and store it in local storage. Then during page load, check local storage and set that scroll position. Assuming you have a div element with id element. In case it's for the page, please change the selector :)
$(function() {
$(window).unload(function() {
var scrollPosition = $("div#element").scrollTop();
localStorage.setItem("scrollPosition", scrollPosition);
});
if(localStorage.scrollPosition) {
$("div#element").scrollTop(localStorage.getItem("scrollPosition"));
}
});
I think we should save scroll data per page, also we should use session storage instead of local storage since session storge effects only the current tab while local storage shared between all tabs and windows of the same origin
$(function () {
var pathName = document.location.pathname;
window.onbeforeunload = function () {
var scrollPosition = $(document).scrollTop();
sessionStorage.setItem("scrollPosition_" + pathName, scrollPosition.toString());
}
if (sessionStorage["scrollPosition_" + pathName]) {
$(document).scrollTop(sessionStorage.getItem("scrollPosition_" + pathName));
}
});
I had the same problem with a simple user interface consisting of a fixed menu div and a scrolling document div ("pxeMainDiv" in the code example below). The following solution worked for me in Chrome 47.0.2526.106 m and in Firefox 43.0.3. (My application is for use in-house and I did not need to cater for old versions of IE).
$(document).ready(function(){
if (history.state) {
$("#pxeMainDiv").scrollTop(history.state.data);
}
$("#pxeMainDiv").scroll(function() {
var scrollPos = $("#pxeMainDiv").scrollTop();
var stateObj = { data: scrollPos };
history.replaceState(stateObj, "");
});
});
On the div scroll event, the scroll position of the div is stored in the state object inside the browser history object. Following a press of the Back button, on the document ready event, the scroll position of the div is restored to the value retrieved from the history.state object.
This solution should work for the reverse navigation of an arbitrarily long chain of links.
Documentation here: https://developer.mozilla.org/en-US/docs/Web/API/History_API
When using window.history.back(), this is actually default browser functionality as user SD. has pointed out.
On a site I am currently building, I wanted the logo of the company to backlink to the index page. Since jQuery 3, $(window).unload(function() should be rewritten to $(window).on('unload', function(). My code looks like this (using Kirby CMS' php syntax):
<?php if ($page->template() == 'home'): ?>
<script>
$(function() {
$(window).on("unload", function() {
var scrollPosition = $(window).scrollTop();
localStorage.setItem("scrollPosition", scrollPosition);
});
if(localStorage.scrollPosition) {
$(window).scrollTop(localStorage.getItem("scrollPosition"));
}
});
</script>
For anyone coming from react or anything similar to react router, here are two simple functions:
export function saveScrollPosition(context: any) {
let path = context.router.route.location.pathname;
let y = window.scrollY;
sessionStorage.setItem("scrollPosition_" + path, y.toString());
}
export function restoreScrollPosition(context: any) {
let path = context.router.route.location.pathname;
let y = Number(sessionStorage.getItem("scrollPosition_" + path));
window.scrollTo(0, y);
}
If a back button is kind of history back button window.history.back() Then what you are seeking for, is a default browser functionality. So you don't have to worry about it.
If your back button actually point to some URL in your application via link or form, then you have to take care that manually.
For solution you may use cookies to store your page scroll value. Each time user scroll on your page, do save scroll value for that page to cookie. Extra work is applied to manual cookie management.
window.onScroll = function(){
document.cookie="pageid=foo-"+window.scrollY+";";
}
This cookie value can be use to set scroll value of the page on page visit.
window.scroll(0,cookievalue);
With History api you can utilize scrollRestoration and stop browser from resetting scroll position.
Read it here. https://developers.google.com/web/updates/2015/09/history-api-scroll-restoration
/* Use the below code to restore the scroll position of individual items and set focus to the last clicked item. */
(function ($)
{
if (sessionStorage)
$.fn.scrollKeeper = function (options)
{
var defauts =
{
key: 'default'
};
var params = $.extend(defauts, options);
var key = params.key;
var $this = $(this);
if (params.init === true)
{
var savedScroll = sessionStorage.getItem(key);
if (typeof savedScroll != 'undefined')
{
var int_savedScroll = parseInt(savedScroll);
if (int_savedScroll > 0)
$this.scrollTop(int_savedScroll);
setTimeout(function ()
{
var selectorFocus = sessionStorage.getItem(key + "-focus");
if (selectorFocus && selectorFocus != "")
$(document.querySelector(selectorFocus)).focus();
}, 100, key);
}
}
window.addEventListener("beforeunload", function ()
{
sessionStorage.setItem(key, $this.scrollTop());
if (document.activeElement)
{
var selectorFocus = elemToSelector(document.activeElement);
if (selectorFocus)
sessionStorage.setItem(key + "-focus", selectorFocus);
else
sessionStorage.setItem(key + "-focus", "");
}
else
sessionStorage.setItem(key + "-focus", "");
});
};
function elemToSelector(elem) /* written by Kévin Berthommier */
{
const {
tagName,
id,
className,
parentNode
} = elem;
if (tagName === 'HTML') return 'HTML';
let str = tagName;
str += (id !== '') ? `#${id}` : '';
if (className)
{
const classes = className.split(/\s/);
for (let i = 0; i < classes.length; i++)
{
if(typeof classes[i] === 'string' && classes[i].length > 0)
str += `.${classes[i]}`;
}
}
let childIndex = 1;
for (let e = elem; e.previousElementSibling; e = e.previousElementSibling)
{
childIndex += 1;
}
str += `:nth-child(${childIndex})`;
return `${elemToSelector(parentNode)} > ${str}`;
}
})(jQuery);
/*
Usage:
$('#tab1div').scrollKeeper({ key: 'uniq-key1', init: true });
If you don't need to restore the scroll positions (for example for restart), and you need just to save the scroll positions for the next time, use:
$('#tab1div').scrollKeeper({ key: 'uniq-key1', init: false });
*/

If/Else Statement showing differently on Click.

http://bvh.delineamultimedia.com/?page_id=2 -> if you click the first image there is a gallery in the dropdown… which is what I want. But, if you close it and re-open it. it goes to a static image.
So there is a function statement in this js I'm working with and can't seem to figure it out what the problem is. http://bvh.delineamultimedia.com/wp-content/themes/bvh/js/portfolio/superbox.js
Here is the function...
$('.superbox').on('click', '.superbox-list', function (e) {
//allows for superbox to work inside of quicksand
$('ul.filterable-grid').css({
overflow: 'visible'
});
var currentimg = $(this).find('.superbox-img');
// cleanup
superbox.find('.title').remove();
superbox.find('.description').remove();
superbox.find('.royalSlider').appendTo(superboximg);
//superbox.find('.royalSlider').appendTo($(this)); // remove the slider from previous events
//superbox.find('.royalSlider').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
var sliderData = currentimg.siblings('.royalSlider'); // grab the slider html that we want to insert
if (sliderData.length > 0) { // show the slider if there is one
superbox.append(sliderData); // clone the element so we don't loose it for the next time the user clicks
superboximg.css('display', 'none');
} else { // if there is no slider proceed as before
if (imgData.img) {
superboximg.attr('src', imgData.img);
superboximg.css('display', 'block');
}
}
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');
});
If you re-open the page, the browser will just load the url (http://bvh.delineamultimedia.com/?page_id=2 ) again from scratch. If you want to re-display something, you have to change the url and make sure that JavaScript picks it up. This is commonly done with window.location.hash.

How to switch a div display on first click?

html head:
<script type="text/javascript" language="JavaScript">
function getStyle() {
var temp = document.getElementById("cont").style.display;
return temp;
}
function switch01() {
var current = getStyle();
if (current == "none") {
document.getElementById("cont").style.display = "block";
}
else {
document.getElementById("cont").style.display = "none";
}
}​
</script>
body:
CONTENT
CSS:
#cont{
display: none;
}
After loading the page - first click doesn't work. After the first click - everything works.
Also, How could I show/hide the div slowly (with sliding effect, not momentally) ?
The value you get for the first time is "undefined".
You can:
1) Set the value via javascript when page loads;
document.getElementById("cont").style.display = "none";
or
2) decode "undefined" value to none, because you know that at first the value will be none;
var temp = document.getElementById("cont").style.display;
if (temp == "undefined")
temp = "none";
return temp;
both pretty ugly solutions, but they work.
If it must be inline you need to do this DEMO
CONTENT
and this (reversing the test for none to be a test for not block)
<script type="text/javascript" language="JavaScript">
function switch01(objId) {
var current = document.getElementById(objId).style.display;
document.getElementById(objId).style.display=(current!="block")?"block":"none";
return false
}
</script>
The above ANSWERS your question
UPDATE: Since it seems you would like jQuery instead, here is how you need to code that - notice the return false which Michal missed.
CONTENT
$(function() { // wait for the page to load
$('#toggle').on("click",function(e) { // when link clicked
$('#cont').slideToggle(); // slide open or closed
return false; // or e.preventDefault(); // stop the click executing the href
});​
});​
If you want the slide effect, my recommendation is using jQuery:
$('#toggle').click(function() {
$('#cont').slideToggle();
});​
See this DEMO.
For changing the sliding speed and more information see documentation.
For hiding the div.. you can take a look at
$('cont').hide(); function.
More relevant Information is available here :
http://api.jquery.com/hide/
http://api.jquery.com/show/
And for sliding effect Jquery is top notch in this department. You just have to pass the argument as given below.. and it does the work.
$("cont").click(function () {
$(this).hide("slide", { direction: "down" }, 1000);
});
FYI : http://docs.jquery.com/UI/Effects/Slide

Categories

Resources