Stop focusout when clicking search results div - javascript

This is in reference to the code at this fiddle: http://jsfiddle.net/x8whpx09/17/
I am trying to create a search box with a result list that pops up when the user enters something. The problem I am encountering is when the user clicks anywhere other than the input element the search result list will close. I have a focusout event attached to the parent DIV, but even if I attach it to the input I get the same behavior. What I want is for the user to be able to select the scroll bar on the list and not have the list disappear. If they click outside of the input, or the list then the list should close.
Right now it closes no matter where they click unless it is in the input.
EDIT: The performSearch function body is wrapped in an AJAX request.
SOLUTION: I finally figured out what is happening. You need to bind to the mousedown event and return false in order to allow selecting the scrollbar in the dropdown. This question finally gave me the solution.
$target.on('mousedown',function (event) {
return false;
});
Here is the code at the fiddle:
var search = {
closing: null,
performSearch: function(elem, e) {
var $this = $(elem);
var $target = $('#search-results');
if ($target.length === 0) {
$target = $('<div id="search-results" class="sb-list"></div>');
$target.insertAfter($this);
var p = $this.position();
$target.css('top', (p.top + $this.height() + 15) + 'px');
$target.css('width', ($this.width() + p.left + 10) + 'px');
$target.css('width', ($this.width() + 25) + 'px');
$target.css('left', (p.left) + 'px');
$target.slideDown('fast', function() {
$target.css('overflow', 'auto');
});
$target.on('mouseover', '.sb-row', function() {
$(elem).addClass('sb-active');
$('.sb-active').removeClass('sb-active');
});
$target.on('click', '.sb-row', search.click);
//$target.parent().on('focusin focusout', search.listFocus);
} else {
$target.empty();
$target.slideDown('fast', function() {
$target.css('overflow', 'auto');
});
}
for (i = 0; i < 40; i++) {
var html = [];
html.push('<div class="sb-row' + (i == 0 ? ' sb-active' : '') + '">');
html.push('test result' + i + '');
html.push('</div>');
var $out = $(html.join(''));
$target.append($out);
}
},
delayClose: function(e) {
console.log('delayClose');
var self = this;
console.log('results focused: ' + $('#search-results').is(':focus'));
console.log('div focused: ' + $('#parent').is(':focus'));
search.closing = window.setTimeout(function() {
search.close.apply(self, arguments);
}, 1000);
},
listFocus: function(e) {
console.log(e.type);
var self = this;
window.clearTimeout(search.closing);
},
click: function(e) {
console.log('clicked');
},
close: function(e) {
console.log('closing');
window.clearTimeout(search.closing);
var $this = $(this);
$('#search-results').slideUp('fast');
}
};
$(document).ready(function() {
$searchBox = $('#search');
$searchBox.on('focus', function(e) {
this.value = '';
this.select();
e.stopPropagation();
return false;
});
$searchBox.on('keyup', function(e) {
search.performSearch($searchBox[0], e);
});
$searchBox.parent().on('focusout', search.delayClose);
});
.sb-list {
position: absolute;
width: 250px;
top: 0;
left: 0;
height: 300px;
background: #FAFAFA;
border: solid 1px #999;
border-top: none;
display: none;
overflow: auto;
z-index: 92592;
-webkit-box-shadow: 0 2px 2px #999999;
-moz-box-shadow: 0 2px 2px #999999;
-ms-box-shadow: 0 2px 2px #999999;
box-shadow: 0 2px 2px #999999;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="parent">
<input type="text" id="search" />
</div>

You have some malfunctioning code here and multiple things to fix. If you inspect #search (the input box), you'll see that search results appear additively for every character entered. That is, you end up with multiple id="search-results" elements.
A very easy oneline solution for this single error is to add $('#search-results').remove(); to your performSearch handler function:
performSearch: function (elem, e) {
$('#search-results').remove();
// ...
}
I have created an updated JSFiddle to demonstrate its functioning and the additional inconveniences and errors this introduces, one of them being the lack of correct event handling when you click the #search-results dropdown itself.
I suggest you try and track the source of errors in the code of your search using Developer Tools or a Javascript debugger, because there are numerous sections in your code that would need either fixing, or rethinking; too much for a single answer.

Related

Javascript click event is doubling every click

Would be really grateful for some advice with this javascript issue I am having with a click event that seems to be doubling every time my slider is closed then reopened.
When you open the slider for the first time and click through the slides you can see in the console the clicks incrementing by 1 every time the 'btn--next' is clicked which is of course correct. When i then close the slider down and re-open it again when the 'btn--next' is clicked the clicks in the console are now incrementing by 2 every click. Close the slider again and re-open and then the 'btn--next' clicks in the console increment by 3 and so on every time the slider is re-loaded.
https://jsfiddle.net/95afhtx8/2/
var loadSlider = document.querySelector('.load__slider');
loadSlider.addEventListener('click', function() {
var slider = document.querySelector('.animal__slider');
var sliderSlide = document.querySelectorAll('.animal__slider__slide');
var nextSlide = document.querySelector('.btn--next');
var previousSlide = document.querySelector('.btn--previous');
var closeSlider = document.querySelector('.animal__slider__close');
var currentSlide = 0;
slider.classList.add('active');
setTimeout(function() {
slider.classList.add('active--show');
startSlide();
}, 100);
//Reset Slider
function resetSlides() {
for (var s = 0; s < sliderSlide.length; s++) {
sliderSlide[s].classList.remove('active--show');
sliderSlide[s].classList.remove('active');
}
}
//Start Slider
function startSlide() {
resetSlides();
sliderSlide[0].classList.add('active');
setTimeout(function() {
sliderSlide[0].classList.add('active--show');
}, 100);
}
//Previous slide
function slidePrevious() {
resetSlides();
sliderSlide[currentSlide - 1].classList.add('active');
setTimeout(function() {
sliderSlide[currentSlide].classList.add('active--show');
}, 100);
currentSlide--;
}
previousSlide.addEventListener('click', function() {
if (currentSlide === 0) {
currentSlide = sliderSlide.length;
}
console.log('click');
slidePrevious();
});
//Next slide
function slideNext() {
resetSlides();
sliderSlide[currentSlide + 1].classList.add('active');
setTimeout(function() {
sliderSlide[currentSlide].classList.add('active--show');
}, 100);
currentSlide++;
}
nextSlide.addEventListener('click', function() {
if (currentSlide === sliderSlide.length - 1) {
currentSlide = -1;
}
console.log('click');
slideNext();
});
closeSlider.addEventListener('click', function() {
slider.classList.remove('active--show');
slider.classList.remove('active');
resetSlides();
});
});
It's because every time you click on your slider toggle:
loadSlider[s].addEventListener('click', function () {
You're re-running code like this, which will add another click handler to the element:
nextSlide.addEventListener('click', function() {
You can add multiple event listeners to any object in the DOM. So you just keep adding more every time the slider opens.
You have three general options here.
Option 1: only set click handlers once
Don't re-add event handlers inside your loadSlider[s].addEventListener('click', function () { function. Do it outside so you aren't re-adding handlers.
Option 2: remove click handlers on close
You can remove the event listeners on close. To do this, you should store a reference to the function you make, so you can explicitly remove it later. You should do this for any handlers you add.
const nextClick = function () {
...
};
nextSlide.addEventListener('click', nextClick);
function resetSlides() {
nextSlide.removeEventListener('click', nextClick);
...
}
This way, when the slider is hidden, the click functionality will be turned off, and re-opening it will add new click handlers and the old ones won't fire because you removed them.
Option 3: Re-create the elements
If you remove an element from the DOM and make a completely new one, the new one won't have stale click handlers on it. This means you'll need to dynamically build your markup with Javascript (using document.createElement), not store it in the HTML page body.
I update your code to work properly (you need to close the anonymous function of the first event listener before you start declaring the others, otherwise you are copying them over and over and therefore the doubling/quadrupling etc...). I would also suggest to move DOM selectors outside of the event listener, they can evaluate only once:
var loadSlider = document.querySelector('.load__slider');
var slider = document.querySelector('.animal__slider');
var sliderSlide = document.querySelectorAll('.animal__slider__slide');
var nextSlide = document.querySelector('.btn--next');
var previousSlide = document.querySelector('.btn--previous');
var closeSlider = document.querySelector('.animal__slider__close');
var currentSlide = 0;
loadSlider.addEventListener('click', function() {
slider.classList.add('active');
setTimeout(function() {
slider.classList.add('active--show');
startSlide();
}, 100);
});
//Reset Slider
function resetSlides() {
for (var s = 0; s < sliderSlide.length; s++) {
sliderSlide[s].classList.remove('active--show');
sliderSlide[s].classList.remove('active');
}
}
//Start Slider
function startSlide() {
resetSlides();
sliderSlide[0].classList.add('active');
setTimeout(function() {
sliderSlide[0].classList.add('active--show');
}, 100);
}
//Previous slide
function slidePrevious() {
resetSlides();
sliderSlide[currentSlide - 1].classList.add('active');
setTimeout(function() {
sliderSlide[currentSlide].classList.add('active--show');
}, 100);
currentSlide--;
}
previousSlide.addEventListener('click', function() {
if (currentSlide === 0) {
currentSlide = sliderSlide.length;
}
console.log('click');
slidePrevious();
});
//Next slide
function slideNext() {
resetSlides();
sliderSlide[currentSlide + 1].classList.add('active');
setTimeout(function() {
sliderSlide[currentSlide].classList.add('active--show');
}, 100);
currentSlide++;
}
nextSlide.addEventListener('click', function() {
if (currentSlide === sliderSlide.length - 1) {
currentSlide = -1;
}
console.log('click');
slideNext();
});
closeSlider.addEventListener('click', function() {
slider.classList.remove('active--show');
slider.classList.remove('active');
resetSlides();
});
.animals {
text-align: center;
position: relative;
width: 80%;
height: 300px;
margin: 0 auto;
background-color: grey;
}
.load__slider {
text-align: center;
}
.animal__slider {
position: absolute;
width: 100%;
height: 100%;
text-align: center;
display: none;
}
.animal__slider.active {
display: block;
}
.animal__slider.active .animal__slider__close {
display: block;
}
.animal__slider.active+.animal__slider__open {
opacity: 0;
}
.animal__slider__slide {
display: none;
position: absolute;
width: 100%;
height: 100%;
}
.animal__slider__slide1 {
background-color: red;
}
.animal__slider__slide2 {
background-color: green;
}
.animal__slider__slide3 {
background-color: yellow;
}
.animal__slider__slide4 {
background-color: blue;
}
.animal__slider__slide.active {
display: block;
}
.btn {
color: black;
position: absolute;
bottom: 5px;
cursor: pointer;
}
.btn--previous {
right: 60px;
}
.btn--next {
right: 30px;
}
.animal__slider__close {
display: none;
position: absolute;
right: 0;
cursor: pointer;
}
.animal__slider__open {
display: block;
cursor: pointer;
}
<section class="animals">
<div class="animal__slider">
Slider
<div class="animal__slider__slide animal__slider__slide1">
slide 1
</div>
<div class="animal__slider__slide animal__slider__slide2">
slide 2
</div>
<div class="animal__slider__slide animal__slider__slide3">
slide 3
</div>
<div class="animal__slider__slide animal__slider__slide4">
slide 4
</div>
<span class="btn btn--previous">previous</span>
<span class="btn btn--next">next</span>
<span class="animal__slider__close">close slider</span>
</div>
<span class="animal__slider__open load__slider">open slider</span>
</section>
In your code, you call nextSlide.addEventListener(...) each time you open the slider, but you never remove that listener. you have to call the function nextSlide.removeEventListener(...) when you close the slider. You also can make sure to call addEventListener only when you open the slider the first time, or even before you open it, as the html element is never destroyed.
To be able to remove the listener, you have to make it accessible in your code when you close the slider. You can't use anonymous functions for this.
EDIT :
An other, simpler solution is to change
nextSlide.addEventListener('click', function(){...});
to:
nextSlide['onclick'] = function() {...};

Function compared width element

I am trying to retrieve the width of an element sidebar to compare it to an absolute value 250px to adapt my menu, but I'm not sure how to continue.
I need to know when my menu is open or close to delete items when it's closed.
Sorry for the little information given at the start.
Full Code JS
$(document).ready(function() {
function toggleSidebar() {
$(".button").toggleClass("active");
$(".sidebar").toggleClass("widthSidebarJs");
$(".sidebar-item").toggleClass("active");
}
$(".button").on("click tap", function() {
toggleSidebar();
});
var maxSizeSidebar = 250;
var widthSidebar = $(".sidebar").innerwidth();
function displayForXsSidebar(){
if (widthSidebar < maxSizeSidebar){
$(".displayForXs").toggleClass("displayXs");
}
}
$(document).keyup(function(e) {
if (e.keyCode === 27) {
toggleSidebar();
}
});
});
As I can guess, you need to add/remove displayXs-class on resize.
You can try to add resize() event listener.
Something like this:
$(window).on('resize', function(){
if (widthSidebar < maxSizeSidebar){
$(".displayForXs").addClass("displayXs");
} else {
$(".displayForXs").removeClass("displayXs");
}
})
But the better way is #media-queries in your css.
In you currently code, your function displayForXsSidebar() not will be run. but easily, try this, remove the function..
$(document).ready(function() { // when document ready, we calculate the width, is better.
var maxSizeSidebar = 250;
var widthSidebar = $(".sidebar").outerWidth();
alert('you widthSidebar value right now is ' + widthSidebar );
if (widthSidebar < maxSizeSidebar){
$(".displayForXs").addClass("displayXs");
} else {
$(".displayForXs").removeClass("displayXs");
}
});
live demo..
$(document).ready(function() {
var maxSizeSidebar = 250;
var widthSidebar = $(".sidebar").outerWidth();
if (widthSidebar < maxSizeSidebar){
$(".displayForXs").addClass("displayXs");
alert('you widthSidebar value right now is ' + widthSidebar + ' so we add class displayXs');
} else {
$(".displayForXs").removeClass("displayXs");
alert('you widthSidebar value right now is ' + widthSidebar + ' so we remove class displayXs');
}
});
.sidebar {
width: 240px; /* Change width here to 260px if you want */
}
.displayXs { background: #000; color: #fff; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<div class="sidebar">
MY SIDEBAR</div>
<div class="displayForXs">
My displayForXs element
</div>

How to prevent centered text in input button be moved when dynamically changed

I have an input button with a centered text. Text length is changing dynamically with a js (dots animation), that causes text moving inside the button.
Strict aligning with padding doesn't suit because the text in the button will be used in different languages and will have different lenghts. Need some versatile solution. The main text should be centered and the dots should be aligned left to the end of the main text.
var dots = 0;
$(document).ready(function() {
$('#payDots').on('click', function() {
$(this).attr('disabled', 'disabled');
setInterval(type, 600);
})
});
function type() {
var dot = '.';
if(dots < 3) {
$('#payDots').val('processing' + dot.repeat(dots));
dots++;
}
else {
$('#payDots').val('processing');
dots = 0;
}
}
<input id="payDots" type="button" value="Pay" class="button">
.button{
text-align: center;
width: 300px;
font-size: 20px;
}
https://jsfiddle.net/v8g4rfsw/1/ (button should be pressed)
The easiest as this is a value and extra elements can't be inserted, would be to just use leading spaces to make the text appear as it's always centered.
This uses the plugin I wrote for your previous question
$.fn.dots = function(time, dots) {
return this.each(function(i,el) {
clearInterval( $(el).data('dots') );
if ( time !== 0 ) {
var d = 0;
$(el).data('dots', setInterval(function() {
$(el).val(function(_,v) {
if (d < dots) {
d++;
return ' ' + v + '.';
} else {
d = 0;
return v.substring(dots, v.length - dots)
}
})
}, time));
}
});
}
$(document).ready(function() {
$('#payDots').on('click', function() {
$(this).val('Proccessing').prop('disabled',true).dots(600, 3);
});
});
.button{
text-align: center;
width: 300px;
font-size: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="payDots" type="button" value="Pay" class="button">
You can find updated code below
Click Here
HTML Code
<button id="payDots">
<span>Pay</span>
</button>
JS Code
var dots = 0;
$(document).ready(function() {
$('#payDots').on('click', function() {
$(this).attr('disabled', 'disabled');
setInterval(type, 600);
})
});
function type() {
$('button').css('padding-left','100px','important');
var dot = '.';
if(dots < 3) {
$('#payDots').text('processing' + dot.repeat(dots));
dots++;
}
else {
$('#payDots').text('processing');
dots = 0;
}
}
CSS Code
button{
text-align: left;
width: 300px;
font-size: 20px;
position:relative;
padding-left:130px;
}

MouseEnter and mouseleave does not work

I'm trying to use mouseenter and mouseleave to change the background of an icon, but it is really bugger. When I hover over the icon, the background changes, when I move my mouse out, the background should go back to normal, but sometimes it doesn't. Can anyone help?
My code:
catItem$.on('mouseenter', function (e) {
e.preventDefault();
var target$ = $(e.currentTarget),
newCategory = target$.attr('data-dest'),
newCategoryItem = this.categories[newCategory];
if (newCategory.isClicked) {
return;
}
target$.find('.cat-icon').addClass('is-selected');
target$.find('.cat-icon').css('background-image', 'url(' + newCategoryItem.lightIconImageURL + ')');
}.bind(this));
catItem$.on('mouseleave', function (e) {
e.preventDefault();
var target$ = $(e.currentTarget),
newCategory = target$.attr('data-dest'),
newCategoryItem = this.categories[newCategory];
if (!newCategoryItem.isClicked) {
target$.find('.cat-icon').removeClass('is-selected');
target$.find('.cat-icon').css('background-image', 'url(' + newCategoryItem.darkIconImageURL + ')');
}
}.bind(this));
I can't use CSS because the background image is dynamic on hover.
If you only want the background to change on hover, have you thought about doing this with CSS rather than with JavaScript?
#item {
background-image: url(someImage);
}
#item:hover {
background-image: url(someOtherImage);
}
Try this code without the conditions to maybe understand what's going wrong:
catItem$.on('mouseenter', function (e) {
e.preventDefault();
var target$ = $(e.currentTarget),
newCategory = target$.attr('data-dest'),
newCategoryItem = this.categories[newCategory];
target$.find('.cat-icon').addClass('is-selected');
target$.find('.cat-icon').css('background-image', 'url(' + newCategoryItem.lightIconImageURL + ')');
}.bind(this));
catItem$.on('mouseleave', function (e) {
e.preventDefault();
var target$ = $(e.currentTarget),
newCategory = target$.attr('data-dest'),
newCategoryItem = this.categories[newCategory];
target$.find('.cat-icon').removeClass('is-selected');
target$.find('.cat-icon').css('background-image', 'url(' + newCategoryItem.darkIconImageURL + ')');
}.bind(this));
Edit: assuming that sometimes your code works and sudden stops
EDIT2: Maybe, can be browser's cache, try:
var d = new Date();
var n = d.getTime();
target$.find('.cat-icon').css('background-image', 'url(' + newCategoryItem.lightIconImageURL + '?=' + d + ')');
Please see this example
var i = 0;
$(".overout")
.mouseover(function() {
i += 1;
$(this).find("span").text("mouse over x " + i);
})
.mouseout(function() {
$(this).find("span").text("mouse out ");
});
var n = 0;
$(".enterleave")
.mouseenter(function() {
n += 1;
$(this).find("span").text("mouse enter x " + n);
})
.mouseleave(function() {
$(this).find("span").text("mouse leave");
});
.out {
width: 40%;
height: 120px;
margin: 0 15px;
background-color: #d6edfc;
float: left;
}
.in {
width: 60%;
height: 60%;
background-color: #fc0;
margin: 10px auto;
}
p {
line-height: 1em;
margin: 0;
padding: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div class="out overout">
<span>move your mouse</span>
<div class="in">
</div>
</div>
<div class="out enterleave">
<span>move your mouse</span>
<div class="in">
</div>
</div>
</body>

Can't manage to close Coverpop popup

I'm using CoverPop to display a popup to my customers. Everything seems so easy but somehow I'm to dumb to make the popup closeable. I have inserted a "close" link, as described in the setup. However when I click on it, nothing happens.
Only way to close the popup is by pressing the escape key on my keyboard.
I know this must be ridiculous for some of you. I'd really appreciate some help though.
Thanks.
HTML
<script>
CoverPop.start({});
</script>
<div id="CoverPop-cover" class="splash">
<div class="CoverPop-content splash-center">
<h2 class="splash-title">Willkommen bei Exsys <span class="bold">Schweiz</span></h2>
<p class="splash-intro">Kunden aus Deutschland und anderen EU-Ländern wechseln bitte zu unserer <span class="bold">deutschen</span> Seite.</p>
<img src="{$ShopURL}/templates/xt_grid/img/shop-ch.png" title="EXSYS Online-Shop Schweiz" height="60" style="margin: 0 20px 0 0;" alt="Schweizer Exsys-Shop"/>
<img src="{$ShopURL}/templates/xt_grid/img/shop-de.png" height="60" alt="Shop Deutschland"/>
<p class="close-splash"><a class="CoverPop-close" href="#">Close</a></p>
</div><!--end .splash-center -->
</div><!--end .splash -->
CSS
.CoverPop-open,
.CoverPop-open body {
overflow: hidden;
}
#CoverPop-cover {
display: none;
position: fixed;
overflow-y: scroll;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
-webkit-animation: fade-in .25s ease-in;
-moz-animation-name: fade-in .25s ease-in;
-ms-animation-name: fade-in .25s ease-in;
-o-animation-name: fade-in .25s ease-in;
animation-name: fade-in .25s ease-in;
}
.CoverPop-open #CoverPop-cover {
display: block;
}
.splash {
background-color:rgba(47, 99, 135, 0.9);
}
.splash-center {
background-color: white;
border-right: 8px solid #007ec8;
border-bottom: 8px solid #007ec8;
border-left: 8px solid #007ec8;
margin: 15px;
text-align: center;
top: 7px;
width: 15%;
}
.splash-center p{
margin: 20px 10px;
}
.splash-center h2{
font-size:16px;
width: 100%;
background:#007ec8;
padding: 10px 0;
color:#FFF;
}
JS
(function (CoverPop, undefined) {
'use strict';
// set default settings
var settings = {
// set default cover id
coverId: 'CoverPop-cover',
// duration (in days) before it pops up again
expires: 30,
// close if someone clicks an element with this class and prevent default action
closeClassNoDefault: 'CoverPop-close',
// close if someone clicks an element with this class and continue default action
closeClassDefault: 'CoverPop-close-go',
// change the cookie name
cookieName: '_ExsPop',
// on popup open function callback
onPopUpOpen: null,
// on popup close function callback
onPopUpClose: null,
// hash to append to url to force display of popup
forceHash: 'splash',
// hash to append to url to delay popup for 1 day
delayHash: 'go',
// close if the user clicks escape
closeOnEscape: true,
// set an optional delay (in milliseconds) before showing the popup
delay: 2000,
// automatically close the popup after a set amount of time (in milliseconds)
hideAfter: null
},
// grab the elements to be used
$el = {
html: document.getElementsByTagName('html')[0],
cover: document.getElementById(settings.coverId),
closeClassDefaultEls: document.querySelectorAll('.' + settings.closeClassDefault),
closeClassNoDefaultEls: document.querySelectorAll('.' + settings.closeClassNoDefault)
},
/**
* Helper methods
*/
util = {
hasClass: function(el, name) {
return new RegExp('(\\s|^)' + name + '(\\s|$)').test(el.className);
},
addClass: function(el, name) {
if (!util.hasClass(el, name)) {
el.className += (el.className ? ' ' : '') + name;
}
},
removeClass: function(el, name) {
if (util.hasClass(el, name)) {
el.className = el.className.replace(new RegExp('(\\s|^)' + name + '(\\s|$)'), ' ').replace(/^\s+|\s+$/g, '');
}
},
addListener: function(target, type, handler) {
if (target.addEventListener) {
target.addEventListener(type, handler, false);
} else if (target.attachEvent) {
target.attachEvent('on' + type, handler);
}
},
removeListener: function(target, type, handler) {
if (target.removeEventListener) {
target.removeEventListener(type, handler, false);
} else if (target.detachEvent) {
target.detachEvent('on' + type, handler);
}
},
isFunction: function(functionToCheck) {
var getType = {};
return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
},
setCookie: function(name, days) {
var date = new Date();
date.setTime(+ date + (days * 86400000));
document.cookie = name + '=true; expires=' + date.toGMTString() + '; path=/';
},
hasCookie: function(name) {
if (document.cookie.indexOf(name) !== -1) {
return true;
}
return false;
},
// check if there is a hash in the url
hashExists: function(hash) {
if (window.location.hash.indexOf(hash) !== -1) {
return true;
}
return false;
},
preventDefault: function(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
},
mergeObj: function(obj1, obj2) {
for (var attr in obj2) {
obj1[attr] = obj2[attr];
}
}
},
/**
* Private Methods
*/
// close popup when user hits escape button
onDocUp = function(e) {
if (settings.closeOnEscape) {
if (e.keyCode === 27) {
CoverPop.close();
}
}
},
openCallback = function() {
// if not the default setting
if (settings.onPopUpOpen !== null) {
// make sure the callback is a function
if (util.isFunction(settings.onPopUpOpen)) {
settings.onPopUpOpen.call();
} else {
throw new TypeError('CoverPop open callback must be a function.');
}
}
},
closeCallback = function() {
// if not the default setting
if (settings.onPopUpClose !== null) {
// make sure the callback is a function
if (util.isFunction(settings.onPopUpClose)) {
settings.onPopUpClose.call();
} else {
throw new TypeError('CoverPop close callback must be a function.');
}
}
};
/**
* Public methods
*/
CoverPop.open = function() {
var i, len;
if (util.hashExists(settings.delayHash)) {
util.setCookie(settings.cookieName, 1); // expire after 1 day
return;
}
util.addClass($el.html, 'CoverPop-open');
// bind close events and prevent default event
if ($el.closeClassNoDefaultEls.length > 0) {
for (i=0, len = $el.closeClassNoDefaultEls.length; i < len; i++) {
util.addListener($el.closeClassNoDefaultEls[i], 'click', function(e) {
if (e.target === this) {
util.preventDefault(e);
CoverPop.close();
}
});
}
}
// bind close events and continue with default event
if ($el.closeClassDefaultEls.length > 0) {
for (i=0, len = $el.closeClassDefaultEls.length; i < len; i++) {
util.addListener($el.closeClassDefaultEls[i], 'click', function(e) {
if (e.target === this) {
CoverPop.close();
}
});
}
}
// bind escape detection to document
util.addListener(document, 'keyup', onDocUp);
openCallback();
};
CoverPop.close = function(e) {
util.removeClass($el.html, 'CoverPop-open');
util.setCookie(settings.cookieName, settings.expires);
// unbind escape detection to document
util.removeListener(document, 'keyup', onDocUp);
closeCallback();
};
CoverPop.init = function(options) {
if (navigator.cookieEnabled) {
util.mergeObj(settings, options);
// check if there is a cookie or hash before proceeding
if (!util.hasCookie(settings.cookieName) || util.hashExists(settings.forceHash)) {
if (settings.delay === 0) {
CoverPop.open();
} else {
// delay showing the popup
setTimeout(CoverPop.open, settings.delay);
}
if (settings.hideAfter) {
// hide popup after the set amount of time
setTimeout(CoverPop.close, settings.hideAfter + settings.delay);
}
}
}
};
// alias
CoverPop.start = function(options) {
CoverPop.init(options);
};
}(window.CoverPop = window.CoverPop || {}));
Additional information
I quickly checked my site and these are the sections I found where the click event is present. Honestly I have no idea how they do interfere with the popup.
// tabs
$('ul.tabs').each(function(){
var $active, $content, $links = $(this).find('a');
$active = $links.first().addClass('active');
$content = $($active.attr('rel'));
$links.not(':first').each(function () {
$($(this).attr('rel')).hide();
});
$(this).on('click', 'a', function(e){
$active.removeClass('active');
$content.hide();
$active = $(this);
$content = $($(this).attr('rel'));
$active.addClass('active');
$content.show();
e.preventDefault();
});
});
// track box clicks and route them to parent radio button
$('div.box-hover').click( function(e)
{
$(this).find("input[type=radio]").click();
});
$('input[type=radio]').click(function(e){
if (this.checked != true && $(this).hasClass('autosubmit')){
this.checked = true;
this.form.submit();
}
e.stopPropagation();
});
// track box clicks to show/hide some desc (shipping/payment)
$('div.box-hover').click( function(e)
{
// ok. wir wollen clicks auf shipping abfangen
// und - laut tmpl - kann nur EIN passendes kind da sein
// also geht das mit dem length check!
if( $(this).children('p.shipping-name').length > 0)
{
$('div.box-hover').children('p.shipping-desc').css('display','none');
$(this).children('p.shipping-desc').css('display','block');
}
if( $(this).children('p.payment-name').length > 0)
{
$('div.box-hover').children('p.payment-desc').css('display','none');
$(this).children('p.payment-desc').css('display','block');
}
});
// autosize the comment textarea
$('#comments').autosize();
// slide in/out guest account form
$("#guest").click( function(e){
$("#cust_info_customers_password").val('');
$("#cust_info_customers_password_confirm").val('');
$('#guest-account').slideUp(250);
});
$("#account").click( function(e){
$('#guest-account').slideDown(250);
});
});
#santadani, found there is a rule to follow due to the implmentation of CoverPop itself. from your production environment, could you move the <script type="text/javascript" src="http://www.exsys.ch/templates/xt_grid/javascript/CoverPop.js"></script> to the end of document, before the </body> tag and try again?
It is because i saw in the CoverPop source, it grabs the element upon the script is loaded
$el = {
html: document.getElementsByTagName('html')[0],
cover: document.getElementById(settings.coverId),
closeClassDefaultEls: document.querySelectorAll('.' + settings.closeClassDefault),
closeClassNoDefaultEls: document.querySelectorAll('.' + settings.closeClassNoDefault)
},
which then the document.querySelectorAll('.' + settings.closeClassDefault) will retrieve nothing (becasue the script was loaded before the DOM are ready, therefore i suggest to try to move the script tag down)

Categories