Need help changing menu from hover to click - javascript

--- Original Hover code ---
function bind_dropdown() {
$('div#quick_nav div.search_dropdown').on('hover', function() {
var thisid = $(this).attr('id').split('_');
var this_action = thisid[1];
var this_width = 950;
var add_class = 'dropdown_full';
if(this_action == 4) {
this_width = 200;
add_class = 'dropdown_small';
}
if($('div#quick_nav div#dropdown_'+escape(this_action)).is(':visible')) {
$('div#quick_nav div#dropdown_'+escape(this_action)).addClass(add_class).slideUp(100);
}
else{
$('div#quick_nav div.dropdown').hide();
$('div#quick_nav div#dropdown_'+escape(this_action)).addClass(add_class).slideDown(100).width(this_width);
}
return false;
});
}
--- End Original Code ---
I did try and change hover to click. It works however to close the menu you now have to click on the menu icon again. Any help would be greatly appreciated. I would like to be able to click to show menu and when the mouse moves off the menu it would close automatically.
Thank you in advance
J

Use the below code
function bind_dropdown() {
$('div#quick_nav div.search_dropdown').on('click', function() {
var thisid = $(this).attr('id').split('_');
var this_action = thisid[1];
var this_width = 950;
var add_class = 'dropdown_full';
if(this_action == 4) {
this_width = 200;
add_class = 'dropdown_small';
}
if($('div#quick_nav div#dropdown_'+escape(this_action)).is(':visible')) {
$('div#quick_nav div#dropdown_'+escape(this_action)).addClass(add_class).slideUp(100);
}
return false;
}).on("mouseleave", function() {
var thisid = $(this).attr('id').split('_');
var this_action = thisid[1];
var this_width = 950;
var add_class = 'dropdown_full';
if(this_action == 4) {
this_width = 200;
add_class = 'dropdown_small';
}
$('div#quick_nav div.dropdown').hide();
$('div#quick_nav div#dropdown_'+escape(this_action)).addClass(add_class).slideDown(100).width(this_width);
});
}

Related

Div is placed outside the text-area when selected the scrolled text

In my scenario, I need to display a div (replace with stars) below the selected text. Here I am facing problem.
When the text area is scrolled and the scrolled text is selected (i.e; the text at the last of the text-area box), the div (replace with stars) is appeared out of the text-area. But, I need to display inside the text-area. It is working fine without scrolling.
JavaScript:
var edits = [""];
var interval = true;
var maxHistorySize = 10;
var saveInterval = 3000;
function undo(e) {
var evtobj = window.event ? window.event : e;
if (evtobj.keyCode == 90 && evtobj.ctrlKey) {
evtobj.preventDefault();
var txtarea = document.getElementById("mytextarea");
var previousText = edits.length === 1 ? edits[0] : edits.pop();
if (previousText !== undefined) {
txtarea.value = previousText;
}
}
}
$(document).ready(function () {
var replaceDiv = document.createElement('div');
replaceDiv.id = 'rplceTxtDiv';
document.getElementsByTagName('body')[0].appendChild(replaceDiv);
$('<div id="starsRplce"></div>').appendTo('#rplceTxtDiv');
$("#starsRplce").click(function () {
var txtarea = document.getElementById("mytextarea");
var start = txtarea.selectionStart;
var finish = txtarea.selectionEnd;
var allText = txtarea.value;
edits.push(allText);
if (edits.length > maxHistorySize) edits.shift();
var sel = allText.substring(start, finish);
sel = sel.replace(/[\S]/g, "*");
var newText = allText.substring(0, start) + sel + allText.substring(finish, allText.length);
txtarea.value = newText;
$('#rplceTxtDiv').offset({ top: 0, left: 0 }).hide();
});
replaceDiv.style.display = "none";
$('<span id="closePopUp">˟</span>').appendTo('#rplceTxtDiv');
$("#closePopUp").click(function () {
$('#rplceTxtDiv').offset({ top: 0, left: 0 }).hide();
})
var rplceTxtDiv = $('#rplceTxtDiv');
$('#mytextarea').on('select', function (e) {
replaceDiv.style.display = "block";
var txtarea = document.getElementById("mytextarea");
var start = txtarea.selectionStart;
var finish = txtarea.selectionEnd;
rplceTxtDiv.offset(getCursorXY(txtarea, start, 20)).show();
rplceTxtDiv.find('div').text('replace with stars');
}).on('input', function () {
if (interval) {
interval = false;
edits.push($(this).val());
if (edits.length > maxHistorySize) edits.shift();
setTimeout(() => interval = true, saveInterval);
}
});
document.onkeydown = undo;
});
var getCursorXY = function getCursorXY(input, selectionPoint, offset) {
var inputX = input.offsetLeft,
inputY = input.offsetTop;
var div = document.createElement('div');
var copyStyle = getComputedStyle(input);
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = copyStyle[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done) ; _iteratorNormalCompletion = true) {
var prop = _step.value;
div.style[prop] = copyStyle[prop];
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
var swap = '.';
var inputValue = input.tagName === 'INPUT' ? input.value.replace(/ /g, swap) : input.value;
var textContent = inputValue.substr(0, selectionPoint);
div.textContent = textContent;
if (input.tagName === 'TEXTAREA') div.style.height = 'auto';
if (input.tagName === 'INPUT') div.style.width = 'auto';
var span = document.createElement('span');
span.textContent = inputValue.substr(selectionPoint) || '.';
div.appendChild(span);
document.body.appendChild(div);
var spanX = span.offsetLeft,
spanY = span.offsetTop;
document.body.removeChild(div);
return {
left: inputX + spanX,
top: inputY + spanY + offset
};
};
Here is my plunker.
You need to take the amount by which the textarea content has been scrolled into account in your position calculation as well, via the scrollTop property:
var inputX = input.offsetLeft,
inputY = input.offsetTop,
inputScrollOffset = input.scrollTop;
.
return {
left: inputX + spanX,
top: inputY - inputScrollOffset + spanY + offset
};
https://plnkr.co/edit/7ScbeTL88tWDU3PqzGqY?p=preview

JavaScript - Set function to return all items based on 1 or 2 selected tags (NO jQUERY)

I have some JavaScrip that is meant to check if there are any media tags selected or industry tags selected--this is so the portfolio items can be sorted and displayed accordingly in the browser.
What I have almost works 100%, but I can't figure out how to make it so that if only a media tag is selected or if only an industry tag is selected, the portfolio items should still be sorted accordingly. Currently, you have to select a media tag AND an industry tag, but I'd like users to be able to search using just a media tag OR just an industry tag.
Here is what I want to accomplish: If only a media tag is selected, then get all portfolio pieces that are associated with that media tag. If only an industry tag is selected, get all portfolio items that are associated with that industry tag. If a media tag AND industry tag are selected at the same time, get all portfolio items that are associated with BOTH.
Vanilla JS isn't my strong point so forgive me if this is a dumb question, but this has had me stumped for hours now.
No jQuery answers, please, as this whole page's functionality is built using JavaScript.
Here is the function:
var update = function () {
closeDrawer();
// update ui to reflect tag changes
// get our list of items to display
var itemsToDisplay = [];
var currentMediaTag = controlsContainer.querySelector('.media.selected');
var currentIndustryTag = controlsContainer.querySelector('.industry.selected');
if (currentMediaTag != "" && currentMediaTag != null) {
selectedMediaFilter = currentMediaTag.innerHTML;
}
if (currentIndustryTag != "" && currentIndustryTag != null) {
selectedIndustryFilter = currentIndustryTag.innerHTML;
}
if (selectedMediaFilter == "" && selectedIndustryFilter == "") {
itemsToDisplay = portfolioItems.filter(function (item) {
return item.preferred;
});
} else {
itemsToDisplay = portfolioItems.filter(function (item) {
var mediaTags = item.media_tags,
industryTags = item.industry_tags;
if(industryTags.indexOf(selectedIndustryFilter) < 0){
return false;
}
else if(mediaTags.indexOf(selectedMediaFilter) < 0){
return false;
}
else{
return true;
}
});
}
renderItems(itemsToDisplay);
}
Not entirely sure it's necessary but just in case, here is the complete JS file that handles the portfolio page:
(function ($) {
document.addEventListener("DOMContentLoaded", function (event) {
// for portfolio interaction
var portfolioGrid = (function () {
var gridSize = undefined,
parentContainer = document.querySelector('.portfolio-item-container');
containers = parentContainer.querySelectorAll('.view'),
drawer = parentContainer.querySelector('.drawer'),
bannerContainer = drawer.querySelector('.banner-container'),
thumbsContainer = drawer.querySelector('.thumbs-container'),
descriptionContainer = drawer.querySelector('.client-description'),
clientNameContainer = drawer.querySelector('.client-name'),
controlsContainer = document.querySelector('.portfolio-controls-container'),
selectedMediaFilter = "", selectedIndustryFilter = "";
var setGridSize = function () {
var windowSize = window.innerWidth,
previousGridSize = gridSize;
if (windowSize > 1800) {
gridSize = 5;
} else if (windowSize > 900) {
gridSize = 4;
} else if (windowSize > 600 && windowSize <= 900) {
gridSize = 3;
} else {
gridSize = 2;
}
if (previousGridSize != gridSize) {
closeDrawer();
}
};
var attachResize = function () {
window.onresize = function () {
setGridSize();
};
};
var getRowClicked = function (boxNumber) {
return Math.ceil(boxNumber / gridSize);
};
var getLeftSibling = function (row) {
var cI = row * gridSize;
return containers[cI >= containers.length ? containers.length - 1 : cI];
};
var openDrawer = function () {
drawer.className = 'drawer';
scrollToBanner();
};
var scrollToBanner = function () {
var mainContainer = document.querySelector('#main-container'),
mainBounding = mainContainer.getBoundingClientRect(),
scrollY = (drawer.offsetTop - mainBounding.bottom) - 10,
currentTop = document.body.getBoundingClientRect().top;
animate(document.body, "scrollTop", "", document.body.scrollTop, scrollY, 200, true);
};
var animate = function (elem, style, unit, from, to, time, prop) {
if (!elem) return;
var start = new Date().getTime(),
timer = setInterval(function () {
var step = Math.min(1, (new Date().getTime() - start) / time);
if (prop) {
elem[style] = (from + step * (to - from)) + unit;
} else {
elem.style[style] = (from + step * (to - from)) + unit;
}
if (step == 1) clearInterval(timer);
}, 25);
elem.style[style] = from + unit;
}
var closeDrawer = function () {
drawer.className = 'drawer hidden';
};
var cleanDrawer = function () {
bannerContainer.innerHTML = "";
clientNameContainer.innerHTML = "";
descriptionContainer.innerHTML = "";
thumbsContainer.innerHTML = "";
};
var resetThumbs = function () {
Array.prototype.forEach.call(thumbsContainer.querySelectorAll('.thumb'), function (t) {
t.className = "thumb";
});
};
var handleBannerItem = function (item) {
bannerContainer.innerHTML = "";
if (item.youtube) {
var videoContainer = document.createElement('div'),
iframe = document.createElement('iframe');
videoContainer.className = "videowrapper";
iframe.className = "youtube-video";
iframe.src = "https://youtube.com/embed/" + item.youtube;
videoContainer.appendChild(iframe);
bannerContainer.appendChild(videoContainer);
} else if (item.soundcloud) {
var iframe = document.createElement('iframe');
iframe.src = item.soundcloud;
iframe.className = "soundcloud-embed";
bannerContainer.appendChild(iframe);
} else if (item.banner) {
var bannerImage = document.createElement('img');
bannerImage.src = item.banner;
bannerContainer.appendChild(bannerImage);
}
};
var attachClick = function () {
Array.prototype.forEach.call(containers, function (n, i) {
n.querySelector('a.info').addEventListener('click', function (e) {
e.preventDefault();
});
n.addEventListener('click', function (e) {
var boxNumber = i + 1,
row = getRowClicked(boxNumber);
var containerIndex = row * gridSize;
if (containerIndex >= containers.length) {
// we're inserting drawer at the end
parentContainer.appendChild(drawer);
} else {
// we're inserting drawer in the middle somewhere
var leftSiblingNode = getLeftSibling(row);
leftSiblingNode.parentNode.insertBefore(drawer, leftSiblingNode);
}
// populate
cleanDrawer();
var mediaFilterSelected = document.querySelector('.media-tags .tag-container .selected');
var selectedFilters = "";
if (mediaFilterSelected != "" && mediaFilterSelected != null) {
selectedFilters = mediaFilterSelected.innerHTML;
}
var portfolioItemName = '';
var selectedID = this.getAttribute('data-portfolio-item-id');
var data = portfolioItems.filter(function (item) {
portfolioItemName = item.name;
return item.id === selectedID;
})[0];
clientNameContainer.innerHTML = data.name;
descriptionContainer.innerHTML = data.description;
var childItems = data.child_items;
//We will group the child items by media tag and target the unique instance from each group to get the right main banner
Array.prototype.groupBy = function (prop) {
return this.reduce(function (groups, item) {
var val = item[prop];
groups[val] = groups[val] || [];
groups[val].push(item);
return groups;
}, {});
}
var byTag = childItems.groupBy('media_tags');
if (childItems.length > 0) {
handleBannerItem(childItems[0]);
var byTagValues = Object.values(byTag);
byTagValues.forEach(function (tagValue) {
for (var t = 0; t < tagValue.length; t++) {
if (tagValue[t].media_tags == selectedFilters) {
handleBannerItem(tagValue[0]);
}
}
});
childItems.forEach(function (item, i) {
var img = document.createElement('img'),
container = document.createElement('div'),
label = document.createElement('p');
container.appendChild(img);
var mediaTags = item.media_tags;
container.className = "thumb";
label.className = "childLabelInactive thumbLbl";
thumbsContainer.appendChild(container);
if (selectedFilters.length > 0 && mediaTags.length > 0) {
for (var x = 0; x < mediaTags.length; x++) {
if (mediaTags[x] == selectedFilters) {
container.className = "thumb active";
label.className = "childLabel thumbLbl";
}
}
}
else {
container.className = i == 0 ? "thumb active" : "thumb";
}
img.src = item.thumb;
if (item.media_tags != 0 && item.media_tags != null) {
childMediaTags = item.media_tags;
childMediaTags.forEach(function (cMTag) {
varLabelTxt = document.createTextNode(cMTag);
container.appendChild(label);
label.appendChild(varLabelTxt);
});
}
img.addEventListener('click', function (e) {
scrollToBanner();
resetThumbs();
handleBannerItem(item);
container.className = "thumb active";
});
});
}
openDrawer();
});
});
};
var preloadImages = function () {
portfolioItems.forEach(function (item) {
var childItems = item.child_items;
childItems.forEach(function (child) {
(new Image()).src = child.banner;
(new Image()).src = child.thumb;
});
});
};
//////////////////////////////////// UPDATE FUNCTION /////////////////////////////////////
var update = function () {
closeDrawer();
// update ui to reflect tag changes
// get our list of items to display
var itemsToDisplay = [];
var currentMediaTag = controlsContainer.querySelector('.media.selected');
var currentIndustryTag = controlsContainer.querySelector('.industry.selected');
if (currentMediaTag != "" && currentMediaTag != null) {
selectedMediaFilter = currentMediaTag.innerHTML;
}
if (currentIndustryTag != "" && currentIndustryTag != null) {
selectedIndustryFilter = currentIndustryTag.innerHTML;
}
if (selectedMediaFilter == "" && selectedIndustryFilter == "") {
itemsToDisplay = portfolioItems.filter(function (item) {
return item.preferred;
});
} else {
itemsToDisplay = portfolioItems.filter(function (item) {
var mediaTags = item.media_tags,
industryTags = item.industry_tags;
if (industryTags.indexOf(selectedIndustryFilter) < 0) {
return false;
}
else if (mediaTags.indexOf(selectedMediaFilter) < 0) {
return false;
}
else {
return true;
}
});
}
renderItems(itemsToDisplay);
}
//////////////////////////////////// RENDERITEMS FUNCTION /////////////////////////////////////
var renderItems = function (items) {
var children = parentContainer.querySelectorAll('.view');
Array.prototype.forEach.call(children, function (child) {
// remove all event listeners then remove child
parentContainer.removeChild(child);
});
items.forEach(function (item) {
var container = document.createElement('div'),
thumb = document.createElement('img'),
mask = document.createElement('div'),
title = document.createElement('h6'),
excerpt = document.createElement('p'),
link = document.createElement('a');
container.className = "view view-tenth";
container.setAttribute('data-portfolio-item-id', item.id);
thumb.src = item.thumb;
mask.className = "mask";
title.innerHTML = item.name;
excerpt.innerHTML = item.excerpt;
link.href = "#";
link.className = "info";
link.innerHTML = "View Work";
container.appendChild(thumb);
container.appendChild(mask);
mask.appendChild(title);
mask.appendChild(excerpt);
mask.appendChild(link);
parentContainer.insertBefore(container, drawer);
});
containers = parentContainer.querySelectorAll('.view');
attachClick();
};
var filterHandler = function (linkNode, tagType) {
var prevSelection = document.querySelector("." + tagType + '.selected');
if (prevSelection != "" && prevSelection != null) {
prevSelection.className = tagType + ' tag';
}
linkNode.className = tagType + ' tag selected';
update();
};
var clearFilters = function (nodeList, filterType) {
Array.prototype.forEach.call(nodeList, function (node) {
node.className = filterType + " tag";
console.log("Clear filters function called");
});
}
var attachFilters = function () {
var mediaFilters = controlsContainer.querySelectorAll('.tag.media'),
industryFilters = controlsContainer.querySelectorAll('.tag.industry'),
filterToggle = controlsContainer.querySelectorAll('.filter-toggle');
// resets
controlsContainer.querySelector('.media-tags .reset')
.addEventListener('click',
function (e) {
e.preventDefault();
selectedMediaFilter = "";
clearFilters(controlsContainer.querySelectorAll('.media-tags a.tag'), "media");
update();
}
);
controlsContainer.querySelector('.industry-tags .reset')
.addEventListener('click',
function (e) {
e.preventDefault();
selectedIndustryFilter = "";
clearFilters(controlsContainer.querySelectorAll('.industry-tags a.tag'), "industry");
update();
}
);
Array.prototype.forEach.call(filterToggle, function (toggle) {
toggle.addEventListener('click', function (e) {
if (controlsContainer.className.indexOf('open') < 0) {
controlsContainer.className += ' open';
} else {
controlsContainer.className = controlsContainer.className.replace('open', '');
}
});
});
//Attaches a click event to each media tag "button"
Array.prototype.forEach.call(mediaFilters, function (filter) {
filter.addEventListener('click', function (e) {
e.preventDefault();
// var selectedMediaFilter = controlsContainer.querySelector('.media.selected');
//console.log("Media tag: " +this.innerHTML); *THIS WORKS*
filterHandler(this, "media");
});
});
Array.prototype.forEach.call(industryFilters, function (filter) {
filter.addEventListener('click', function (e) {
e.preventDefault();
// var selectedIndustryFilter = this.querySelector('.industry.selected');
// console.log("Industry tag: " +this.innerHTML); *THIS WORKS*
filterHandler(this, "industry");
});
});
};
return {
init: function () {
setGridSize();
attachResize();
attachClick();
preloadImages();
// portfolio page
if (controlsContainer) {
attachFilters();
}
}
};
})();
portfolioGrid.init();
});
}());
$ = jQuery.noConflict();
if(industryTags.indexOf(selectedIndustryFilter) < 0){
return false;
}
else if(mediaTags.indexOf(selectedMediaFilter) < 0){
return false;
}
That part is giving you headaches. Whenever no industry tag or media tag is selected this will exit the function.
Change to:
if(industryTags.indexOf(selectedIndustryFilter) < 0 && mediaTags.indexOf(selectedMediaFilter) < 0){
return false;
}
Now it will test if at least one tag is selected. If so then render items.
I made a change just to experiment with an idea, and this setup works:
if((selectedIndustryFilter !="" && industryTags.indexOf(selectedIndustryFilter) < 0) || (selectedMediaFilter !="" && mediaTags.indexOf(selectedMediaFilter) < 0)){
return false;
}
return true;
Not sure if it's the best solution ever but it seems to work and I'm not going to complain.

generating a number of divs at a time in jQuery

I'm trying to make a game with jquery where bullets are appended using a function. So far bullets are generating whenever I press spacebar but I want to generate bullets like 3-5 stacks. 3-5 bullets will be generated and then a short break then again 3-5 bullets will be generated and the process continues. Bullets are appended as div element. Here are the codes,
function generateBullet() {
var Player = $('#player');
var PlayerLeft = Player.offset().left;
var PlayerTop = Player.offset().top - 50;
var appendingValue = "<div class='bulletID' style=' position: absolute; left: 250px; top: 250px;'></div>";
var appendSize = $('.bulletID').size();
if (appendSize >= 3) {
$('#content').delay(5000).append(appendingValue);
} else {
$('#content').append(appendingValue);
}
}
function animateBullet() {
var bulletID = $('.bulletID');
bulletID.each(function () {
var nowTop = $(this).offset().top;
$(this).css("top", nowTop - 25);
});
}
var keys = {}
$(document).keydown(function (e) {
keys[e.keyCode] = true;
});
$(document).keyup(function (e) {
delete keys[e.keyCode];
});
function shoot() {
var Player = $('#player');
for (var direction in keys) {
if (!keys.hasOwnProperty(direction)) continue;
if (direction == 32) {
generateBullet();
}
}
}
JSFIDDLE DEMO : http://jsfiddle.net/ygz5wo7r/1/
I'm not getting any more idea how to do this. Your help will be really appreciated. TnQ.
Try this
I added
return false;
after
if (appendSize >= 3) {
...
and
parseInt($(this).css("top"))< 0 && $(this).remove();
to animateBullet()
to remove the bullets when they leave the screen
you can count how many bullets you fired each chain, and block the gun if chain reaches 3-5 bullets. and then using a timeout you can unblock the gun. that way you have control over the interval between bullet chains:
Fixed Fiddle
var bullets_chain = 0;
var block_gun = false;
function generateBullet() {
if (block_gun == false) {
var Player = $('#player');
var PlayerLeft = Player.offset().left;
var PlayerTop = Player.offset().top - 50;
var appendingValue = "<div class='bulletID' style=' position: absolute; left: 250px; top: 250px;'></div>";
bullets_chain++;
if (bullets_chain >= 5) {
block_gun = true;
bullets_chain = 0;
setTimeout(function () {
block_gun = false;
}, 500);
}
$('#content').append(appendingValue);
}
}
function animateBullet() {
var bulletID = $('.bulletID');
bulletID.each(function () {
var nowTop = $(this).offset().top;
if (nowTop < 0) {
$(this).remove();
} else {
$(this).css("top", nowTop - 25);
}
});
}
var keys = {}
$(document).keydown(function (e) {
if (block_gun == false) {
keys[e.keyCode] = true;
}
});
$(document).keyup(function (e) {
delete keys[e.keyCode];
});
function shoot() {
var Player = $('#player');
for (var direction in keys) {
if (!keys.hasOwnProperty(direction)) continue;
if (direction == 32) {
generateBullet();
}
}
}
$(document).ready(function () {
setInterval(shoot, 50);
setInterval(animateBullet, 100);
});

Hover to click in wordpress menu

I used a theme that I changed to show sub menu horizontally, now I want to show sub menu onClick and not on hover, I'm not good at javascript but I think that this code is about the navigation menu:
var nav = {
init: function() {
// Add parent class to items with sub-menus
jQuery("ul.sub-menu").parent().addClass('parent');
var menuTop = 40;
var menuTopReset = 80;
// Enable hover dropdowns for window size above tablet width
jQuery("nav").find(".menu li.parent").hoverIntent({
over: function() {
if (jQuery('#container').width() > 767 || jQuery('body').hasClass('responsive-fixed')) {
// Setup menuLeft variable, with main menu value
var subMenuWidth = jQuery(this).find('ul.sub-menu').first().outerWidth(true);
var mainMenuItemWidth = jQuery(this).outerWidth(true);
var menuLeft = '-' + (Math.round(subMenuWidth / 2) - Math.round(mainMenuItemWidth / 2)) + 'px';
var menuContainer = jQuery(this).parent().parent();
// Check if this is the top bar menu
if (menuContainer.hasClass("top-menu")) {
if (menuContainer.parent().parent().parent().hasClass("top-bar-menu-right")) {
menuLeft = "";
} else {
menuLeft = "-1px";
}
menuTop = 30;
menuTopReset = 40;
} else if (menuContainer.hasClass("header-menu")) {
menuLeft = "-1px";
menuTop = 28;
menuTopReset = 40;
} else if (menuContainer.hasClass("mini-menu") || menuContainer.parent().hasClass("mini-menu")) {
menuTop = 40;
menuTopReset = 58;
} else {
menuTop = 44;
menuTopReset = 64;
}
// Check if second level dropdown
if (jQuery(this).find('ul.sub-menu').first().parent().parent().hasClass("sub-menu")) {
menuLeft = jQuery(this).find('ul.sub-menu').first().parent().parent().outerWidth(true) - 2;
}
jQuery(this).find('ul.sub-menu').first().addClass('show-dropdown').css('top', menuTop);
}
},
out:function() {
if (jQuery('#container').width() > 767 || jQuery('body').hasClass('responsive-fixed')) {
jQuery(this).find('ul.sub-menu').first().removeClass('show-dropdown').css('top', menuTopReset);
}
}
});
jQuery(".shopping-bag-item").live("mouseenter", function() {
var subMenuTop = 44;
if (jQuery(this).parent().parent().hasClass("mini-menu")) {
subMenuTop = 40;
}
jQuery(this).find('ul.sub-menu').first().addClass('show-dropdown').css('top', subMenuTop);
}).live("mouseleave", function() {
if (jQuery('#container').width() > 767 || jQuery('body').hasClass('responsive-fixed')) {
jQuery(this).find('ul.sub-menu').first().removeClass('show-dropdown').css('top', 64);
}
});
// Toggle Mobile Nav show/hide
jQuery('a.show-main-nav').on('click', function(e) {
e.preventDefault();
if (jQuery('#main-navigation').is(':visible')) {
jQuery('.header-overlay .header-wrap').css('position', '');
} else {
jQuery('.header-overlay .header-wrap').css('position', 'relative');
}
jQuery('#main-navigation').toggle();
});
jQuery(window).smartresize(function(){
if (jQuery('#container').width() > 767 || jQuery('body').hasClass('responsive-fixed')) {
var menus = jQuery('nav').find('ul.menu');
menus.each(function() {
jQuery(this).css("display", "");
});
}
});
// Set current language to top bar item
var currentLanguage = jQuery('li.aux-languages').find('.current-language span').text();
if (currentLanguage !== "") {
jQuery('li.aux-languages > a').text(currentLanguage);
}
},
hideNav: function(subnav) {
setTimeout(function() {
if (subnav.css("opacity") === "0") {
subnav.css("display", "none");
}
}, 300);
}
};
I tried to replace "hoverIntent" by "click" but it doesn't work, what can I do?
What's happening when someone currently hovers, it does one thing while hovering and when they leave it has to d a sort of cleanup which are the two functions within hoverintent, namely over and out so the code would need to be split into two event listeners one for click of the element and one for blur
I have chained the two listeners to the inital selector so it should all work.
var nav = {
init: function() {
// Add parent class to items with sub-menus
jQuery("ul.sub-menu").parent().addClass('parent');
var menuTop = 40;
var menuTopReset = 80;
// Enable click dropdowns for window size above tablet width
jQuery("nav").find(".menu li.parent").on('click', function (event) {
if($(event.target).parent().hasClass('menu-item-has-children')){
event.preventDefault();
};
if (jQuery('#container').width() > 767 || jQuery('body').hasClass('responsive-fixed')) {
// Setup menuLeft variable, with main menu value
var subMenuWidth = jQuery(this).find('ul.sub-menu').first().outerWidth(true);
var mainMenuItemWidth = jQuery(this).outerWidth(true);
var menuLeft = '-' + (Math.round(subMenuWidth / 2) - Math.round(mainMenuItemWidth / 2)) + 'px';
var menuContainer = jQuery(this).parent().parent();
// Check if this is the top bar menu
if (menuContainer.hasClass("top-menu")) {
if (menuContainer.parent().parent().parent().hasClass("top-bar-menu-right")) {
menuLeft = "";
} else {
menuLeft = "-1px";
}
menuTop = 30;
menuTopReset = 40;
} else if (menuContainer.hasClass("header-menu")) {
menuLeft = "-1px";
menuTop = 28;
menuTopReset = 40;
} else if (menuContainer.hasClass("mini-menu") || menuContainer.parent().hasClass("mini-menu")) {
menuTop = 40;
menuTopReset = 58;
} else {
menuTop = 44;
menuTopReset = 64;
}
// Check if second level dropdown
if (jQuery(this).find('ul.sub-menu').first().parent().parent().hasClass("sub-menu")) {
menuLeft = jQuery(this).find('ul.sub-menu').first().parent().parent().outerWidth(true) - 2;
}
jQuery(this).find('ul.sub-menu').first().addClass('show-dropdown').css('top', menuTop);
}
}).on('mouseleave',function () {
if (jQuery('#container').width() > 767 || jQuery('body').hasClass('responsive-fixed')) {
jQuery(this).find('ul.sub-menu').first().removeClass('show-dropdown').css('top', menuTopReset);
}
});
// Toggle Mobile Nav show/hide
jQuery('a.show-main-nav').on('click', function(e) {
e.preventDefault();
if (jQuery('#main-navigation').is(':visible')) {
jQuery('.header-overlay .header-wrap').css('position', '');
} else {
jQuery('.header-overlay .header-wrap').css('position', 'relative');
}
jQuery('#main-navigation').toggle();
});
jQuery(window).smartresize(function(){
if (jQuery('#container').width() > 767 || jQuery('body').hasClass('responsive-fixed')) {
var menus = jQuery('nav').find('ul.menu');
menus.each(function() {
jQuery(this).css("display", "");
});
}
});
// Set current language to top bar item
var currentLanguage = jQuery('li.aux-languages').find('.current-language span').text();
if (currentLanguage !== "") {
jQuery('li.aux-languages > a').text(currentLanguage);
}
},
hideNav: function(subnav) {
setTimeout(function() {
if (subnav.css("opacity") === "0") {
subnav.css("display", "none");
}
}, 300);
}
};
That seems overly complicated. Do you have a link to the live version?
Usually, when doing a click-to-see submenu with a clickable parent, I set a variable to see whether the menu is open, if not dont go to link. if so, go to link.
An example: http://codepen.io/jhealey5/pen/iLgom
var $handle = $('.sub-menu').prev();
var opened = 0;
$handle.on('click', function(e){
if (opened) {
window.location.href = $(this).attr('href');
} else {
e.preventDefault();
e.stopPropagation();
$('.sub-menu').slideToggle();
opened = 1;
}
});
$('html').on('click', function(){
if (opened) {
$('.sub-menu').slideToggle();
opened = 0;
}
});
Depending on that menu of yours, you could use something similar. But it's using a lot of code for a menu.

Get caret HTML position in contenteditable DIV

I am having troubles figuring out how to get caret position in a DIV container that contains HTML tags.
I am using this JavaScript function to do that:
function getCaretPosition()
{
if (window.getSelection && window.getSelection().getRangeAt)
{
var range = window.getSelection().getRangeAt(0);
var selectedObj = window.getSelection();
var rangeCount = 0;
var childNodes = selectedObj.anchorNode.parentNode.childNodes;
for (var i = 0; i < childNodes.length; i++)
{
if (childNodes[i] == selectedObj.anchorNode)
{
break;
}
if(childNodes[i].outerHTML)
{
rangeCount += childNodes[i].outerHTML.length;
}
else if(childNodes[i].nodeType == 3)
{
rangeCount += childNodes[i].textContent.length;
}
}
return range.startOffset + rangeCount;
}
return -1;
}
However, it finds a caret position of the text in my DIV container, when I need to find the caret position including HTML tags.
For example:
<DIV class="peCont" contenteditable="true">Text goes here along with <b>some <i>HTML</i> tags</b>.</DIV>;
(please note, that HTML tags are normal tags and are not displayed on the screen when the function is returning caret position)
If I click right between H and TML, the aforementioned function will find caret position without any problems. But I am getting the contents of DIV box in HTML format (including all tags), and if I want to insert something at that caret's position, I will be off by a few or many characters.
I went through many posts, but all I could find is either <TEXTAREA> caret postions, or functions similar to what I have posted. So far I still cannot find a solution to get a caret position in a text that has HTML formatting.
Can anyone help, please?
PS. Here's JQuery/Javascript code that I wrote for the link button:
$('#pageEditor').on('click', '.linkURL', function()
{
var cursorPosition;
cursorPosition = getCaretPosition();
var contentID = $(this).parent().parent().attr('id');
var userSelected = getSelectionHtml();
var checkLink = userSelected.search('</a>');
var anchorTag = 0;
if(checkLink == -1)
{
var currentContents = $('#'+contentID+' .peCont').html();
var indexOfSelection = currentContents.indexOf(userSelected);
var getPossibleAnchor = currentContents.slice(indexOfSelection, indexOfSelection+userSelected.length+6);
anchorTag = getPossibleAnchor.search('</a>');
}
if(checkLink > 0 || anchorTag > 0)
{
//alert(checkLink);
document.execCommand('unlink', false, false);
}
else
{
$('#'+contentID+' .peCont').append('<div id="linkEntry"><label for="urlLink">Please enter URL for the link:<label><input type="text" id="urlLink" /></div>');
$('#linkEntry').dialog({
buttons: {
"Ok": function()
{
var attribute = $('#urlLink').val();
var newContentWithLink = '';
if(attribute != '')
{
if(userSelected != '')
{
var currentContent = $('#'+contentID+' .peCont').html();
var replacement = ''+userSelected+'';
newContentWithLink = currentContent.replace(userSelected, replacement);
}
else
{
var currentTextContent = $('#'+contentID+' .peCont').html();
var userLink = ''+attribute+'';
if(cursorPosition > 0)
{
var contentBegin = currentTextContent.slice(0,cursorPosition);
var contentEnd = currentTextContent.slice(cursorPosition,currentTextContent.length);
newContentWithLink = contentBegin+userLink+contentEnd;
}
else
{
newContentWithLink = attribute+currentTextContent;
}
}
$('#'+contentID+' .peCont').empty();
$('#'+contentID+' .peCont').html(newContentWithLink);
}
$(this).dialog("close");
} },
closeOnEscape:true,
modal:true,
resizable:false,
show: { effect: 'drop', direction: "up" },
hide: { effect: 'drop', direction: "down" },
width:460,
closeText:'hide',
close: function()
{
$(this).remove();
}
});
$('#linkEntry').on('keypress', function(urlEnter)
{
if(urlEnter.which == 13)
{
var attribute = $('#urlLink').val();
var newContentWithLink = '';
if(userSelected != '')
{
var currentContent = $('#'+contentID+' .peCont').html();
var replacement = ''+userSelected+'';
newContentWithLink = currentContent.replace(userSelected, replacement);
}
else
{
var currentTextContent = $('#'+contentID+' .peCont').html();
var userLink = ''+attribute+'';
if(cursorPosition > 0)
{
var contentBegin = currentTextContent.slice(0,cursorPosition);
var contentEnd = currentTextContent.slice(cursorPosition,currentTextContent.length);
newContentWithLink = contentBegin+userLink+contentEnd;
}
else
{
newContentWithLink = attribute+currentTextContent;
}
}
$('#'+contentID+' .peCont').empty();
$('#'+contentID+' .peCont').html(newContentWithLink);
$(this).dialog("close");
}
});
}
});
I created a simple fiddle for you that does what you want.
This should work in recent versions of Firefox, Chrome and Safari.
It's your homework to add Opera and IE support if you need.

Categories

Resources