chrome throwing Uncaught RangeError: Maximum call stack size exceeded - javascript

Am trying to build a simple widget using bootstrap popover
UW.UI.ProjectMember = {
dropdown: ".project-member-select-dropdown",
input: ".member-search-field",
options: {
container: $('.project-member-select'),
trigger: "click",
minChar: 2
},
renderTemplate: function() {
var template = '<div class="project-member-picker">'+
'<div class="project-member-search-box">'+
'<input type="text" class="member-search-field input-block-level" placeholder="Enter a name">'+
'<ul class="project-member-select-dropdown"></ul>'+
'</div>'+
'<div><p>You can invite your colleagues to use UberWork with you</p></div>'+
'</div>';
this.options.container.append(template);
return this;
},
initPopover: function() {
var _this = this;
$(".add-member-btn").popover({
html: true,
placement: "bottom",
trigger: _this.options.trigger,
container: '#window',
content: _this.build()
});
},
build: function() {
return $('.project-member-picker').html();
},
delegateEvents: function() {
var _this = this;
$(document).on("keydown",'.popover .member-search-field', function(event) {
_this.processInput(event, _this);
});
$(document).on("click", '.popover li.member', function(event) {
_this.addToken(event, _this);
});
$(document).on("click", '.popover .project-members ul li a.remove', function(event) {
_this.deleteToken(event, _this);
});
},
showDropdown: function() {
$(this.dropdown).css({
position: "absolute",
zindex: 999
}).show();
},
hideDropdown: function() {
$(this.dropdown).hide().empty();
},
processInput: function(event, that) {
var input = $(event.currentTarget),
inputValue = input.val(), timeout;
if(inputValue.length >= 1) {
that.showSearchActivity();
clearTimeout(timeout);
timeout = setTimeout(function() {
that.runSearch(inputValue.toLowerCase())
}, 300);
}
else {
that.hideDropdown();
}
},
showSearchActivity: function() {
$(this.dropdown).html('<p>Searching...</p>');
this.showDropdown();
},
runSearch: function(query) {
var results = $.grep(UW.Members, function (row) {
return[row.name].toString().toLowerCase().indexOf(query.toLowerCase()) > -1;
});
this.populateDropdown(query, results);
},
populateDropdown: function(query, results) {
var _this = this;
if(results && results.length) {
$(this.dropdown).empty();
this.hideDropdown();
$.each(results, function (index, value) {
if(value.photo == "")
var photo = UW.Constants.avatar;
else
var photo = value.photo;
var template = '<li class="member" data-id="'+value.user_id+'">'+
'<div class="member-avatar pull-left"><img src="'+photo+'"></div>'+
'<div class="member-name pull-left">'+value.name+'</div>'+
'</li>';
$(_this.dropdown).append(template);
});
this.showDropdown();
}else {
$(this.dropdown).html('<p>No results</p>');
this.showDropdown();
}
},
addToken: function(event, that) {
var el = $(event.currentTarget);
var id = el.attr('data-id');
var user = {
name: $(el).find('div.member-name').html(),
photo: $(el).find('div.member-avatar').find('img').attr('src')
};
//update member list
var members = this.options.container.find('div.project-members ul.member-avatars');
if(members.find('li[data-id="'+id+'"]').length == 0) {
members.append('<li data-id="'+id+'"><img src="'+user.photo+'" title="'+user.name+'"></li>');
}
//clear input
$(that.input).val('');
//Hide dropdown
this.hideDropdown();
},
deleteToken: function(event, that) {
event.preventDefault();
},
init: function() {
this.renderTemplate();
this.initPopover()
this.delegateEvents();
}
I know am posting alot of code, anyway i am instantiating the UW.UI.ProjectMember class from a backbone view.
When the $(".add-member-btn") element is clicked to trigger the popover, everything works fine for the first time but when element is clicked again to hide the popover the chrome console shows this error " Uncaught RangeError: Maximum call stack size exceeded".
What could i be doing wrong? Any help will be appreciated.

Related

Some troubles to custom jquery-ui Autocomplete combobox

I want use a autocomplete/ComboBox like a filter. I customize the code from jqueryUI to give same form like a selectMenu. And I want use select and change event and triger change event on Enter keypress.
Here my code :
$.widget("custom.TFOAutoCombo", {
_create: function () {
var nam = this.element.attr("id").split("lstFiltreAuto");
this.element.hide();
this.wrapper = $("<span>", { "class": "ui-state-default TFOcustom-combobox SizCol" + nam[1] }).appendTo($('#acc-container' + nam[1]));
this._createAutocomplete(nam[1]);
this._createShowAllButton(nam[1]);
},
_createAutocomplete: function (nam) {
var selected = this.element.children(":selected"),
value = selected.val() ? selected.text() : "";
this.input = $('<input class="ui-state-default TFOcustom-combobox-Input ui-corner-all" placeholder="TOUS">').appendTo(this.wrapper).val(value)
.autocomplete({ delay: 0, minLength: 0, source: $.proxy(this, "_source"), appendTo: '#acc-container' + nam })
.tooltip({ classes: { "ui-tooltip": "ui-state-highlight" } });
this._on(this.input, {
autocompleteselect: function (event, ui) { ui.item.option.selected = true; this._trigger("select", event, { item: ui.item.option }); },
autocompletechange: function (event, ui) { var ret = this._removeIfInvalid(event, ui); if (ret != null) { this._trigger("change", event, { item: ret }); } }
});
this.input.keypress(function (e,ui) {
if (e.which == 13) {
var ret = this._removeIfInvalid(e, ui); if (ret != null) { this._trigger("change", event, { item: ret }); }
}
});
},
_createShowAllButton: function (nam) {
var input = this.input, wasOpen = false;
$('<span class="ui-icon ui-icon-triangle-1-s TFOcustom-combobox-Fleche">').appendTo(this.wrapper)
.on("mousedown", function () { wasOpen = input.autocomplete("widget").is(":visible"); })
.on("click", function () {
input.trigger("focus");
if (wasOpen) { return; }// Close if already visible
input.autocomplete("search", "");// Pass empty string as value to search for, displaying all results
});
},
_source: function (request, response) {
var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i");
response(this.element.children("option").map(function () {
var text = $(this).text();
if (this.value && (!request.term || matcher.test(text))) return { label: text, value: text, option: this };
}));
},
_removeIfInvalid: function (event, ui) {
if (ui.item) { return null; }// Selected an item, nothing to do
// Search for a match (case-insensitive)
var value = this.input.val(), valueLowerCase = value.toLowerCase(), valid = false; var Koi = null;
this.element.children("option").each(function () { if ($(this).text().toLowerCase() === valueLowerCase) { this.selected = valid = true; Koi = this; return false; } });
if (valid) { return Koi; } // Found a match, nothing to do
// Remove invalid value
this.input.val("").attr("title", "Aucun enregistrement correspondant à " + value).tooltip("open");
this.element.val("");
this._delay(function () { this.input.tooltip("close").attr("title", ""); }, 2500);
this.input.autocomplete("instance").term = "";
return Koi;
},
_destroy: function () { this.wrapper.remove(); this.element.show(); }
});
TO create my custom autocomplete I use thsi function
function CustomComboAuto($r, q) {
var s = (q == null ? "select.TFOAutoCombo" : q); $r.find(s).TFOAutoCombo({
select: function (event, ui) {
alert("select:" + ui.item.value);
},
change: function (event, ui) {
alert("Change" + ui.item.value);
}
});
}
And my CSS:
.TFOcustom-combobox {
position: relative;
display: inline-block;
vertical-align:middle;
padding: 0 10px 0 0;
border:none !important;
background:none !important;
}
.TFOcustom-combobox-Fleche {
position:absolute;
right:0.5em;
top:50%;
margin-top:-8px;
z-index:100;
}
.TFOcustom-combobox-Input{
width:95%;
font-size:small !important;
padding:0.7em 0 0.7em 1em;
line-height:1.4;
}
And I've 2 Problems/
The first is when I select with mouse it's fired select event (good)
When I use up/down and press entrer to select an item, it's fired change event and after select event. And I just need change not the select)
The second problem and I want fire autocompletechange event when I write directly in my autocomplete and press enter key. I've capture the event enterkeypress but I can't fired the research properly.
If someone can help me. I work on that since 3 days, passed lot of problem but now I've no more idea to solve this 2 points.
Finnally I solved the first big part of problems.
$.widget("custom.TFOAutoCombo", {
_create: function () {
var nam = this.element.attr("id").split("lstFiltreAuto");
this.element.hide();
this.wrapper = $("<span>", { "class": "ui-state-default TFOcustom-combobox SizCol" + nam[1] }).appendTo($('#acc-container' + nam[1]));
this._createAutocomplete(nam[1]);
this._createShowAllButton(nam[1]);
},
_createAutocomplete: function (nam) {
var selected = this.element.children(":selected"),
value = selected.val() ? selected.text() : "";
var selectedName = '';
this.input = $('<input class="ui-state-default TFOcustom-combobox-Input ui-corner-all" placeholder="TOUS">').appendTo(this.wrapper).val(value)
.autocomplete({ delay: 0, minLength: 0, source: $.proxy(this, "_source"), appendTo: '#acc-container' + nam })
.keypress(function (e, ui) {
if (e.which == 13) {
e.preventDefault(); $(this).autocomplete("close"); var inputs = $(this).closest('body').find(':focusable'); inputs.eq(inputs.index(this) + 1).focus();
}
})
.tooltip({ classes: { "ui-tooltip": "ui-state-highlight" } });
this._on(this.input, {
autocompleteselect: function (event, ui) { if (selectedName === ui.item.value) { return; } else { selectedName = ui.item.value; ui.item.option.selected = true; this._trigger("select", event, { item: ui.item.option }); } },
autocompletechange: function (event, ui) { if (selectedName === this.input.val()) { return; } else { var ret = this._removeIfInvalid(event, ui); if (ret != null) { selectedName = this.input.val(); this._trigger("select", event, { item: ret }); } } }
});
},
_createShowAllButton: function (nam) {
var input = this.input, wasOpen = false;
$('<span class="ui-icon ui-icon-triangle-1-s TFOcustom-combobox-Fleche">').appendTo(this.wrapper)
.on("mousedown", function () { wasOpen = input.autocomplete("widget").is(":visible"); })
.on("click", function () {
input.trigger("focus");
if (wasOpen) { return; }// Close if already visible
input.autocomplete("search", "");// Pass empty string as value to search for, displaying all results
});
},
_source: function (request, response) {
var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i");
response(this.element.children("option").map(function () {
var text = $(this).text();
if (this.value && (!request.term || matcher.test(text))) return { label: text, value: text, option: this };
}));
},
_removeIfInvalid: function (event, ui) {
if (ui.item) { return null; }// Selected an item, nothing to do
// Search for a match (case-insensitive)
var value = this.input.val(), valueLowerCase = value.toLowerCase(), valid = false; var Koi = null;
this.element.children("option").each(function () { if ($(this).text().toLowerCase() === valueLowerCase) { this.selected = valid = true; Koi = this; return false; } });
if (valid) { return Koi; } // Found a match, nothing to do
// Remove invalid value
this.input.val("").attr("title", "Aucun enregistrement correspondant à " + value).tooltip("open");
this.element.val("");
this._delay(function () { this.input.tooltip("close").attr("title", ""); }, 2500);
this.input.autocomplete("instance").term = "";
return Koi;
},
_destroy: function () { this.wrapper.remove(); this.element.show(); }
});
The solution is simple, when I capture Enter KeyPress I close autocomplete and put focus otherthere :-) to trigger autocompletechange event.
Now JUST stay the problem of double fired event when I use up/down and selecting by EnterKeyPress on list
UPDATE
I change the _createAutocomplete with a variable to memorize the last value... Too simple that I can see it.
All Resolved. Enjoy a good autocomplete combobox seems selectmenu

Issues with having two carousels on the same page with custom jQuery

I have some jQuery that works great when one carousel is on the page. I need to have two carousels in the same page and it's currently not working. Can someone please tell me how to make it work?
var Carousel = (function($) {
var $carousel = $('.carousel');
var activeItemIndex = 0;
var s;
return {
settings: {
delay: 10000,
items: $carousel.find('.carousel__item'),
totalItems: 0,
dots: $carousel.find('.carousel__dots'),
dotLinks: $carousel.find('.carousel__dot-link'),
timeout: 0,
},
init: function(args) {
if ($carousel.length) {
s = $.extend({}, this.settings, args);
s.totalItems = s.items.length;
if (s.totalItems > 1) {
this.setupDotsData();
this.activate();
this.eventListeners();
$carousel.addClass('active');
}
}
},
eventListeners: function() {
s.dotLinks.on('click', function() {
var index = $(this).data('index');
Carousel.stop();
Carousel.show(index);
});
},
setupDotsData: function() {
s.dots.each(function() {
$(this).find('li').each(function(index) {
$(this).data('index', index);
});
});
},
activate: function() {
if (s.totalItems > 1) {
Carousel.show(0);
} else {
s.items.eq(0).addClass('active');
}
},
show: function(index) {
s.items.removeClass('active');
s.dotLinks.removeClass('active');
s.items.eq(index).addClass('active');
s.dotLinks.filter(':nth-child(' + (index + 1) + ')').addClass('active');
activeItemIndex = index;
Carousel.play();
},
next: function(e) {
var nextItemIndex = activeItemIndex + 1 >= s.totalItems ? 0 : activeItemIndex + 1;
e && e.preventDefault();
Carousel.stop();
Carousel.show(nextItemIndex);
},
play: function() {
s.timeout = window.setTimeout(Carousel.next, s.delay);
},
stop: function() {
window.clearTimeout(s.timeout);
}
};
})(jQuery);
Carousel.init();
Example on JSFIDDLE
You need some modifications for handling multiple instance of Carousel:
https://jsfiddle.net/dmz7wk6f/7/
Try this (loop through each carousel, grab the id and initialize it):
Fiddle: https://jsfiddle.net/4o00o7n6/
$(".carousel").each(function(x){
var carouselId = $(this).attr('id');
var Carousel = (function($) {
'use strict';
//var wrap = $('.carousel');
var wrap = $('#' + carouselId);
var activeItemIndex = 0;
var s;
return {
settings: {
delay: 10000,
items: wrap.find('.carousel__item'),
totalItems: 0,
dots: wrap.find('.carousel__dots'),
dotLinks: wrap.find('.carousel__dot-link'),
timeout: 0,
},
init: function(args) {
if (wrap && wrap.length) {
s = $.extend({}, this.settings, args);
s.totalItems = s.items.length;
if (s.totalItems > 1) {
this.setupDotsData();
this.activate();
this.eventListeners();
wrap.addClass('active');
}
}
},
eventListeners: function() {
s.dotLinks.on('click', function() {
var index = $(this).data('index');
Carousel.stop();
Carousel.show(index);
});
},
setupDotsData: function() {
s.dots.each(function() {
$(this).find('li').each(function(index) {
$(this).data('index', index);
});
});
},
activate: function() {
if (s.totalItems > 1) {
Carousel.show(0);
} else {
s.items.eq(0).addClass('active');
}
},
show: function(index) {
s.items.removeClass('active');
s.dotLinks.removeClass('active');
s.items.eq(index).addClass('active');
s.dotLinks.filter(':nth-child(' + (index + 1) + ')').addClass('active');
activeItemIndex = index;
Carousel.play();
},
next: function(e) {
var nextItemIndex = activeItemIndex + 1 >= s.totalItems ? 0 : activeItemIndex + 1;
e && e.preventDefault();
Carousel.stop();
Carousel.show(nextItemIndex);
},
play: function() {
s.timeout = window.setTimeout(Carousel.next, s.delay);
},
stop: function() {
window.clearTimeout(s.timeout);
}
};
})(jQuery);
Carousel.init();
});

How can I stop JS triggering when scrolling on touch devices

At the moment we are using the below script to create a lightweight lightbox for a wordpress site, which works perfectly on desktop, but the overlay is being triggered when just scrolling on a touch device if you scroll with your finger on one of the images, is there anyway to stop this happening?
<script>
var WHLightbox = {
settings: {
overlay: $('.portfolio-tile--overlay'),
imageCell: $('.cell-image, .portfolio-tile--image')
},
data: {
images: []
},
init: function() {
this.events();
this.buildImageData();
},
events: function() {
var self = this;
this.settings.imageCell.on('click touchend', function(e) {
e.preventDefault();
e.stopPropagation();
// set up the overlay
self._positionOverlay();
self._openOverlay();
self._preventScrolling();
// create the image slide
self._createImageSlide($(this));
});
this.settings.overlay.on('click touchend', function(e) {
e.preventDefault();
e.stopPropagation();
self._closeOverlay();
});
$('.portfolio-tile--overlay--controls--prev, .portfolio-tile--overlay--controls--next').on('click touchend', function(e) {
e.preventDefault();
e.stopPropagation();
});
$('.portfolio-tile--overlay--controls--prev').on('click touchend', function(e) {
e.preventDefault();
e.stopPropagation();
self.showPrev();
});
$('.portfolio-tile--overlay--controls--next').on('click touchend', function(e) {
e.preventDefault();
e.stopPropagation();
self.showNext();
});
},
// public functions
showPrev: function() {
var index = this.currentImageIndex();
if(index === 0) {
index = this.data.images.length;
}
this._createImageSlide(false, index-1);
},
showNext: function() {
var index = this.currentImageIndex();
if(index === this.data.images.length-1) {
// set to -1 because it adds 1 in the _createImageSlide call
index = -1;
}
this._createImageSlide(false, index+1);
},
currentImageIndex: function() {
if(this.settings.overlay.hasClass('open')) {
var imageUrl = $('.portfolio-tile--main-image').attr('src');
for(var i=0; i<this.data.images.length; i++) {
if(this.data.images[i].imageUrl === imageUrl) {
return i;
}
}
} else {
return false;
}
},
// image data
buildImageData: function() {
var self = this,
i = 0;
this.settings.imageCell.each(function() {
self.data.images[i] = {
imageUrl: self._getImagePath($(this))
}
i++;
});
},
// slide
_createImageSlide: function($el, index) {
var imagePath;
if(!$el) {
imagePath = this.data.images[index].imageUrl;
} else {
imagePath = this._getImagePath($el);
}
this.settings.overlay.find('.portfolio-tile--main-image').attr('src', imagePath);
},
_getImagePath: function($el) {
var imagePath,
spanEl = $el.find('span.js-cell-image-background'),
imgEl = $el.find('img.cell-image__image');
if(spanEl.length) {
imagePath = spanEl.css('backgroundImage');
imagePath = imagePath.replace('url(', '').replace(')', '');
} else if(imgEl.length) {
imagePath = imgEl.attr('src');
}
return imagePath;
},
// overlay
_positionOverlay: function() {
this.settings.overlay.css({
// position the overlay to current scroll position
top: $(window).scrollTop()
});
},
_openOverlay: function() {
this.settings.overlay.addClass('open');
},
_preventScrolling: function() {
$('html, body').addClass('no-scroll');
},
_reInitScrolling: function() {
$('html, body').removeClass('no-scroll');
},
_closeOverlay: function() {
this.settings.overlay.removeClass('open');
this._reInitScrolling();
}
};
WHLightbox.init();
</script>
You could use a library such as Modernizr to detect touch take a look at the answer to this question on detecting touch What's the best way to detect a 'touch screen' device using JavaScript?
With Modernizr only:
if (Modernizr.touch) {
alert('Touch Screen');
} else {
alert('No Touch Screen');
}
or with the use of jQuery & Modernizr you can do something like:
if($('html').hasClass('touch') === false) {
//run your code here
}
Thank you for your reply aharen, I managed to get it working by just changing touchend to tap and it seems to be working as intended now.

images overlap at initial page loading using isotope and knockout.js

On first load images and blocks overlap but after that it works fine
<div id="container" class="isotope" data-bind="isotope: bills, isotopeOptions: isotopeOptions ">
<div class="bill-subcategory-image"><img data-bind="style: { width: '100%'}, attr : { src: categoryimage() } " /></div>
Getting Data from Json and rendering at above divs
$(function (){
function Bill(id, billNo, votes, description, category, categoryimage, name, itemType) {
var self = this;
self.id = ko.observable(id);
self.billNo = ko.observable(billNo);
self.description = ko.observable(description);
self.votes = ko.observable(votes);
self.category = ko.observable(category);
self.categoryimage = ko.observable(categoryimage);
self.name = ko.observable(name);
self.itemType = ko.observable(itemType);
self.RandomHeight = ko.observable(Math.floor(Math.random() * 200) + 150);
self.voteFor = function () {
console.log("voting for: %s", self.billNo());
forUs.vote(self.id(), 'for').done(function (data, textStatus, jqXHR) {
console.log("you have voted for %s", self.billNo());
});
};
// values for isTracked and isShared is dynamic
self.isTracked = ko.observable(true);
self.isShared = ko.observable(true);
self.trackClass = ko.computed(function () {
if (self.isTracked()) {
return 'active';
}
else {
return 'inactive';
}
});
self.shareClass = ko.computed(function () {
if (self.isShared()) {
return 'active';
}
else {
return 'inactive';
}
});
self.voteAgainst = function () {
console.log("vote against: %s", self.billNo());
forUs.vote(self.id(), 'against').done(function (data, textStatus, jqXHR) {
console.log('you have voted against %s', self.billNo());
});
};
self.track = function () {
var identity = (self.billNo() || self.name());
forUs.track(self.id()).done(function (data, textStatus, jqXHR) {
self.isTracked(!self.isTracked());
console.log('you %s tracking %s', self.isTracked() ? 'are now' : 'stopped', identity);
});
};
self.share = function () {
var identity = (self.billNo() || self.name());
forUs.share(self.id()).done(function (data, textStatus, jqXHR) {
self.isShared(!self.isShared());
console.log('you %s sharing %s', self.isShared() ? 'are now' : 'stopped', identity);
});
};
self.billUrl = ko.computed(function () {
return "../Bill/" + self.billNo();
});
self.popupUrl = ko.computed(function () {
return "../" + self.itemType() + "/Popup/" + self.id();
});
//console.log(self.categoryimage());
};`
// getting records from JSON file
`function ViewModel() {
var self = this;
self.bills = ko.observableArray();
var $container = $('#container');
$container.bill-subcategory-image(function () {
$container.isotope({
itemSelector: '.item',
layoutMode: 'masonry'
});
});
self.isotopeOptions = {
itemSelector: '.item',
masonry: {
columnWidth: 280
}
};
self.count = 0;
$.getJSON(url + "1", function (json) {
for (var i = 0; i < json.length; i++) {
var bill = new Bill(
json[i].Id,
json[i].BillNo,
json[i].Votes,
json[i].Description,
json[i].Category,
json[i].CategoryImage,
json[i].Name,
json[i].ItemType
);
self.bills.push(bill);
}
});
self.Add = function (newData) {
var newItems = ko.utils.arrayMap(newData, function (item) {
return new Bill(item.Id, item.BillNo, item.Votes, item.Description, item.Category, item.CategoryImage, item.Name, item.ItemType);
});
self.bills.push.apply(self.bills, newItems);
self.count = self.count + newItems.length;
console.log("added " + newItems.length + " items! Total added since start = " + self.count);
};
};`
//if page scroll than more isotopes render
var vm = new ViewModel();
$(window).paged_scroll({
handleScroll: function (page, container, doneCallback) {
$.getJSON(url + page, function (json) {
//console.log("got data, adding...");
vm.Add(json);
//console.log("finished adding!");
doneCallback();
});
},
triggerFromBottom: '200px',
targetElement: $('#container'),
loader: '<div class="loader">Loading next page...</div>',
monitorTargetChange: false
});
//knockout binding
ko.applyBindings(vm, $('#container')[0]);
});
}
For images, try using imagesloaded.js
var $container = $('#container');
$container.bill-subcategory-image(function () {
$container.imagesLoaded( function(){
$container.isotope({
itemSelector: '.item',
layoutMode: 'masonry'
});
});
});

Rollover delay for Map markers

We had a developer work-up a piece of javascript for animating markers on a map for us. See http://luniablue.com/clients/endowment for it's current state.
The issue I'm having, is that the rollover is too sensitive and I want there to be a 1sec pause before executing the rollover function. From what I've read, I need to declare a setTimeout() function, but I'm not clear on where to insert that.
I have tried every place that I can see and I've had no luck except in breaking the script. I'm sure it's something stupid simple, but javascript isn't my stong point. Can anyone help me out?
Here's the code:
var firstEntry = true;
var lastOn = '';
function showAllPins() {
if ($('#communities').hasClass('theMouseIsOff')) {
var citiesArr = [];
$('.pin').each( function () {
citiesArr.push(this.id);
$('#'+this.id).hide();
});
var stillHidden = citiesArr.length;
while (stillHidden > 0) {
var a = Math.floor(Math.random()*citiesArr.length);
if ($('#'+citiesArr[a]).is(':hidden')) {
$('#'+citiesArr[a]).show().delay(Math.floor(Math.random()*900)).animate({
opacity: 1,
top: '+=40',
}, Math.floor(Math.random()*900), 'easeOutBounce');
stillHidden--;
}
}
firstEntry = true;
$('#communities').removeClass('theMouseIsOff');
}
}
function showPin(relid){
lastOn = relid;
if ($('#communities').hasClass('theMouseIsOff')) $('#communities').removeClass('theMouseIsOff');
if (firstEntry == true) {
$("#communities div[id!=" + relid + "].pin").animate({
opacity: 0,
top: '-=40',
}, 500);
firstEntry = false;
} else {
$("#communities div[id=" + relid + "].pin").animate({
opacity: 1,
top: '+=40',
}, 500, 'easeOutBounce');
}
}
function removeLastPin() {
$('#communities').addClass('theMouseIsOff');
$("#communities div[id=" + lastOn + "].pin").animate({
opacity: 0,
top: '-=40',
}, 500);
setTimeout('showAllPins()',600);
}
$(document).ready( function () {
$('.pin').mouseenter( function () {
relid = $(this).attr('rel');
showPin(relid);
}).mouseleave( function () { removeLastPin() });
});
$(document).ready(function() {
$('.pin').each(function() {
var selector = '#' + $(this).data('tooltip-id');
Tipped.create(this, $(selector)[0], { skin: 'light', hook: { target: 'topmiddle', tooltip: 'bottomleft'}});
});
});
Where you see:
$(document).ready( function () {
$('.pin').mouseenter( function () {
relid = $(this).attr('rel');
showPin(relid);
}).mouseleave( function () { removeLastPin() });
});
You can change it to:
$(document).ready( function () {
$('.pin').mouseenter( function () {
relid = $(this).attr('rel');
setTimeout(function(){showPin(relid)}, 1000);
}).mouseleave( function () { removeLastPin() });
});
By changing the showPin() function to execute after a timeout, the pin should appear after the specified interval.
Update:
If you would like the function only to run if the mouseleave hasn't occurred during the specified interval, you can clear the interval on mouseleave like this:
$(document).ready(function() {
$('.pin').mouseenter(function() {
relid = $(this).attr('rel');
var awaiting = setTimeout(function() {
showPin(relid)
}, 1000);
}).mouseleave(function() {
removeLastPin();
clearInterval(awaiting);
});
});

Categories