I need to create popup language dropdown menu with country name, flag and link to the language version of the site. After user select menu item - it should take you to the needed url (language version of the page) and this choice should stay visible on the new page (after reload). Example of the menu - https://prnt.sc/sjumj8 (https://www.farfetch.com/shopping/women/items.aspx)
Here is an example of what I'm trying to create: https://jsfiddle.net/Okean/8x0atLpy/62/
<body>
<ul class="list-unstyled" id="select-lang">
<li class="init">[SELECT]</li>
<li data-value="value 1"> <img src="https://image.flaticon.com/icons/svg/197/197615.svg"> Language 1 </li>
<li data-value="value 2"> <img src="https://image.flaticon.com/icons/svg/197/197386.svg">Language 2 </li>
<li data-value="value 3"> <img src="https://image.flaticon.com/icons/svg/197/197484.svg">Language 3 </li>
<li data-value="value 4"> <img src="https://image.flaticon.com/icons/svg/197/197380.svg">Language 4 </li>
</ul>
</body>
<script>
$("ul").on("click", "li:not(.init)", function() {
allOptions.removeClass('selected');
$(this).addClass('selected');
$("ul").children('.init').html($(this).html());
allOptions.toggle();
});
window.onload = function() {
var selItem = sessionStorage.getItem("SelItem");
$('#select-lang').val(selItem);
}
$('#select-lang').change(function() {
var selVal = $(this).val();
sessionStorage.setItem("SelItem", selVal);
});
</script>
<style>
body{
padding:30px;
}
ul {
height: 30px;
width: 150px;
border: 1px #000 solid;
}
ul li { padding: 5px 10px; z-index: 2; }
ul li:not(.init) { float: left; width: 130px; display: none; background: #ddd; }
ul li:not(.init):hover, ul li.selected:not(.init) { background: #09f; }
li.init { cursor: pointer; }
a#submit { z-index: 1; }
li img {
width: 20px;
}
</style>
<ul> tag element won't ever trigger a .change event,
you can't even use li.val() as it doesn't have an actual value attribue.
So you need to workaround a little, something like this
$(document).ready(() => {
// cache selectors for better performance
const listItem = $("ul");
const listSelected = listItem.find('.init');
const allOptions = listItem.children('li:not(.init)');
listItem.on('click', '.init', () => {
listItem.children('li:not(.init)').toggle();
});
listItem.on('click', 'li:not(.init)', (e) => {
const that = $(e.target);
const setHTML = that.html();
allOptions.removeClass('selected');
that.addClass('selected');
listSelected.html(setHTML);
allOptions.toggle();
sessionStorage.setItem('SelItem', setHTML);
});
const selectItem = $("#select-lang");
const storedItem = sessionStorage.getItem('SelItem');
if (storedItem) {
listSelected.html(storedItem);
}
});
this should work as expected, storing target <li> HTML inside SelItem on sessionStorage
Related
I need to create popup language dropdown menu with country name, flag and link to the language version of the site. After user select menu item - it should take you to the needed url (language version of the page) and this choice should stay visible on the new page (after reload).
Example of the menu - https://prnt.sc/sjumj8 (https://www.farfetch.com/shopping/women/items.aspx)
Here is an example of what I'm trying to create: https://jsfiddle.net/Okean/8x0atLpy/62/
<ul class="list-unstyled" id="select-lang">
<li class="init">[SELECT]</li>
<li data-value="value 1"> <img src="https://image.flaticon.com/icons/svg/197/197615.svg"> Language 1 </li>
<li data-value="value 2"> <img src="https://image.flaticon.com/icons/svg/197/197386.svg">Language 2 </li>
<li data-value="value 3"> <img src="https://image.flaticon.com/icons/svg/197/197484.svg">Language 3 </li>
<li data-value="value 4"> <img src="https://image.flaticon.com/icons/svg/197/197380.svg">Language 4 </li>
</ul>
$("ul").on("click", ".init", function() {
$(this).closest("ul").children('li:not(.init)').toggle();
});
var allOptions = $("ul").children('li:not(.init)');
$("ul").on("click", "li:not(.init)", function() {
allOptions.removeClass('selected');
$(this).addClass('selected');
$("ul").children('.init').html($(this).html());
allOptions.toggle();
});
window.onload = function() {
var selItem = sessionStorage.getItem("SelItem");
$('#select-lang').val(selItem);
}
$('#select-lang').change(function() {
var selVal = $(this).val();
sessionStorage.setItem("SelItem", selVal);
});
body{
padding:30px;
}
ul {
height: 30px;
width: 150px;
border: 1px #000 solid;
}
ul li { padding: 5px 10px; z-index: 2; }
ul li:not(.init) { float: left; width: 130px; display: none; background: #ddd; }
ul li:not(.init):hover, ul li.selected:not(.init) { background: #09f; }
li.init { cursor: pointer; }
a#submit { z-index: 1; }
li img {
width: 20px;
}
You can use localStorage. Once user is selected an option, you can save it to browser's local storage where 'language' is your key and you can name it anything and where 'selectedOption' is the language user has selected.
// Set the preference
window.localStorage.setItem("language", selectedOption);
// Get the preference, anytime you want once set
window.localStorage.getItem("language")
Actually, I am trying to make a sub-menu where user hovers on the first menu its child list should appear one after one and same on the other menu.
I think it is working fine just a minor problem. I am going to the 2nd or 3rd menu before the complete appearing of the first menu's child. 2nd and 3rd are working fine but again if I hover on the first menu it still shows the remaining list (child) which was left to appear.
(function($) {
$.fn.animateOneByOne = function(params) {
params = $.extend({
css: '',
duration: 700,
interval: 300,
order: 'ASC',
callback: ''
}, params);
if (params.order == 'ASC') {
elements = $(this);
} else {
elements = $(this).get().reverse();
}
count = $(this).length - 1;
$(elements).each(function(id) {
setTimeout(function(element) {
if (id == count) {
$(element).animate(params.css, params.duration, params.callback);
} else {
$(element).animate(params.css, params.duration);
}
}, id * (params.interval + params.duration), $(this));
});
};
})(jQuery);
$('.srvs_dropdown').hover(function() {
$(this).find("ul li").animateOneByOne({
css: {
opacity: '1'
},
duration: 450,
interval: 100
});
return false;
},
function() {
$(this).find("ul li").css("opacity", 0);
});
.srvs_dropdown li {
opacity: 0;
}
a {
color: #fff;
}
.pi-mm-list {
padding-left: 20px;
background-color: #09142D;
width: 250px;
color: #fff;
}
.pi-mm-list li ul {
display: none;
position: absolute;
left: 180px;
width: 234px;
padding-top: 7px;
background-color: #09142D;
z-index: 999;
}
.pi-mm-list li:hover ul {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="pi-mm-list">
<li class="srvs_dropdown">Network Security
<ul>
<li>Firewall and VPN</li>
<li>Web Security</li>
<li>Application Security</li>
<li>Threat Detection & Response</li>
<li>Data Leakage Prevention</li>
<li>IPS</li>
</ul>
</li>
<li class="srvs_dropdown">Endpoint Security
<ul>
<li>Antivirus</li>
<li>DLP</li>
</ul>
</li>
<li class="srvs_dropdown">Wireless Security
<ul>
<li>Access Point</li>
<li>Controller</li>
</ul>
</li>
</ul>
As far as I have understood or observed your question and code, looks like it only works correctly when you hover over all links for the first time top to bottom but once you reach the last menu item in the first block and start hovering in reverse from bottom to top you will see that the submenu links start appearing in randomly, problem is the delay that you have used you just need a small fix i.e incremental delay which you were missing. The code below it works as you expect, observe the difference in the $(elements).each(function(id) { just replace the setTimeOut with delay and add the increment there and watch the difference, you can remove the interval param too see below code and working example, hope it solves the problem.
(function($) {
$.fn.animateOneByOne = function(params) {
params = $.extend({
css: '',
duration: 700,
order: 'ASC',
callback: ''
}, params);
if (params.order == 'ASC') {
elements = $(this);
} else {
elements = $(this).get().reverse();
}
count = $(this).length - 1;
$(elements).each(function(id) {
let isLastLi = id == count;
console.log('animate', id);
(isLastLi) ? $(this).delay((id + 1) * params.duration).animate(params.css, 0, params.callback): $(this).delay((id + 1) * params.duration).animate(params.css, 0);
});
};
})(jQuery);
$('.srvs_dropdown').hover(function() {
console.log('here');
$(this).find("ul li").animateOneByOne({
css: {
opacity: '1'
},
duration: 400
});
return false;
},
function() {
$(this).find("ul li").stop().css("opacity", 0);
});
.srvs_dropdown li {
opacity: 0;
}
a {
color: #fff;
}
.pi-mm-list {
padding-left: 20px;
background-color: #09142D;
width: 250px;
color: #fff;
}
.pi-mm-list li ul {
display: none;
position: absolute;
left: 180px;
width: 234px;
padding-top: 7px;
background-color: #09142D;
z-index: 999;
}
.pi-mm-list li:hover ul {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="pi-mm-list">
<li class="srvs_dropdown">Network Security
<ul>
<li>Firewall and VPN</li>
<li>Web Security</li>
<li>Application Security</li>
<li>Threat Detection & Response</li>
<li>Data Leakage Prevention</li>
<li>IPS</li>
</ul>
</li>
<li class="srvs_dropdown">Endpoint Security
<ul>
<li>Antivirus</li>
<li>DLP</li>
</ul>
</li>
<li class="srvs_dropdown">Wireless Security
<ul>
<li>Access Point</li>
<li>Controller</li>
</ul>
</li>
</ul>
The main idea is to cancel timed-out function when it doesn't need to execute. It looks that out part in .hover(in, out) is the best place to do it. But first we need a list of setTimeout handlers which are generated in the in part. Something like this.
(function($) {
$.fn.animateOneByOne = function(params) {
params = $.extend({
css: '',
duration: 700,
interval: 300,
order: 'ASC',
callback: ''
}, params);
if (params.order == 'ASC') {
elements = $(this);
} else {
elements = $(this).get().reverse();
}
count = $(this).length - 1;
var handlers = [];
$(elements).each(function(id) {
var handle = setTimeout(function(element) {
if (id == count) {
$(element).animate(params.css, params.duration, params.callback);
} else {
$(element).animate(params.css, params.duration);
}
}, id * (params.interval + params.duration), $(this));
handlers.push(handle);
});
return handlers;
};
})(jQuery);
$('.srvs_dropdown').hover(function() {
$(this).data('handler',
$(this).find("ul li").animateOneByOne({//returns the list of handlers
css: {
opacity: '1'
},
duration: 450,
interval: 100
}));
return false;
},
function() {
$(this).data('handler').forEach(function(handle) {
clearTimeout(handle); //cancel setTimeout if it didn't start yet
});
$(this).find("ul li").css("opacity", 0);
});
.srvs_dropdown li {
opacity: 0;
}
.pi-mm-list {
padding-left: 20px;
}
.pi-mm-list li ul {
display: none;
position: absolute;
left: 180px;
width: 234px;
padding-top: 7px;
background: #09142D;
z-index: 999;
}
.pi-mm-list li:hover ul {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="pi-mm-list">
<li class="srvs_dropdown">Network Security
<ul>
<li>Firewall and VPN</li>
<li>Web Security</li>
<li>Application Security</li>
<li>Threat Detection & Response</li>
<li>Data Leakage Prevention</li>
<li>IPS</li>
</ul>
</li>
<li class="srvs_dropdown">Endpoint Security
<ul>
<li>Antivirus</li>
<li>DLP</li>
</ul>
</li>
<li class="srvs_dropdown">Wireless Security
<ul>
<li>Access Point</li>
<li>Controller</li>
</ul>
</li>
</ul>
I got a variable that represents required number of items and counting of dropped items inside droppable area. You can view example here. So what I want is to pass a variable to javascript and then calculate the difference.
I put my variable into div:
<div id="numbr" >10</div>
And here is the js code which counts dropped items and displays the total:
var n = $(this).closest("div.proc").find(".dropClass").length -1;
$(this).closest("div.proc").find("div.dropped").text("Items Dropped: " + n + ".");
My goal is to find differences between <div class="numbr"> and n, and then display it. How can I achieve this in js?
It is just an example.In my system, the number is a php variable received from user's input. There could be more than 2 boxes: it depends on user's input.
Try the following in both the drop event and the click event:
var proc = $(this).closest("div.proc");
proc.find('.dif').text('Difference ' +(proc.find('.numbr').text() - n));
demo: https://jsfiddle.net/d1ddsj8m/2/
var itm = [];
$("#savebutton").click(function() {
LISTOBJ.saveList();
});
$("#myAccordion").accordion({
heightStyle: "content",
active: false,
collapsible: true
});
$("#myAccordion li").draggable({
appendTo: "body",
helper: "clone",
start: function(ev, ui) {
ui.helper.width($(this).width());
}
});
$(".projLeader ol").droppable({
tolerance: 'pointer',
hoverClass: 'highlight',
drop: function(ev, ui) {
var zz = ui.draggable.text()
var xyz = itm.includes(zz);
if (xyz === false) {
var item = ui.draggable;
if (!ui.draggable.closest('.placeholder').length) item = item.clone().draggable(); // if item was dragged from the source list - clone it
//this.innerHTML = ''; // clean the placeholder
item.addClass('dropClass').appendTo(this);
// append item to placeholder
//add to array
itm.push(zz);
var n = $(this).closest("div.proc").find(".dropClass").length;
$(this).closest("div.proc").find(".dropped").text("Items Dropped: " + n + ".");
$(this).closest("div.proc").find('.dif').text('Difference ' + ($(this).closest("div.proc").find('.numbr').text() - n));
} else {
alert('Name is Already Exist');
}
}
});
$(".projLeader").on('click', '.closer', function() {
var item = $(this).closest('.item');
var element = $("#myAccordion ul li").filter(function() {
return $(this).text() == item.text();
});
itm.splice(item);
var n = $(this).closest("div.proc").find(".dropClass").length - 1;
$(this).closest("div.proc").find("div.dropped").text("Items Dropped: " + n + ".");
$(this).closest("div.proc").find('.dif').text('Difference ' + ($(this).closest("div.proc").find('.numbr').text() - n));
item.fadeTo(200, 0, function() {
item.remove();
})
});
var LISTOBJ = {
saveList: function() {
var listCSV = "";
$(".projLeader li").each(function() {
if (listCSV === "") {
listCSV = $(this).text();
} else {
listCSV += ", " + $(this).text();
}
$("#output").text(listCSV);
$(".hiddenListInput").val(listCSV);
});
}
}
body {
font-family: verdana;
font-size: 12px;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
margin-bottom: 10px;
}
ol {
list-style-type: none;
}
.item {
height: 20px;
width: 180px;
margin: 5px;
padding: 5px;
border: 1px solid gray;
background-color: #cd8;
position: relative;
}
.item .closer {
position: absolute;
right: 5px;
top: 2px;
font: bold 14px arial;
color: #666;
padding: 1px 3px;
line-height: 1;
cursor: pointer;
display: none;
}
.item .closer:hover {
color: #000;
}
.placeholder {
height: 30px;
width: 195px;
margin: 5px;
background: #eee;
border: 1px dashed #999;
}
.placeholder .item {
margin: 0;
}
ol .item .closer {
display: block;
}
.highlight {
border: 1px solid red;
background: #fff;
}
.highlight .item {
opacity: 0.3;
}
.ui-draggable-dragging {
z-index: 99;
opacity: 1 !important;
}
.dropClass {
background-color: lightblue;
padding-left: 10px;
width: 180px;
border: 1px solid black;
border-radius: 8px;
margin-bottom: 5px;
}
.dropped {
display: inline;
}
.dif {
display: inline;
}
.numbr {
display: inline;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.12.0/jquery-ui.min.js" integrity="sha256-eGE6blurk5sHj+rmkfsGYeKyZx3M4bG+ZlFyA7Kns7E=" crossorigin="anonymous"></script>
<h1 class="ui-widget-header">Products</h1>
<div id="myAccordion">
<h3>T-Shirts</h3>
<div>
<ul>
<li class="item"><span class="closer">x</span>Lolcat Shirt</li>
<li class="item"><span class="closer">x</span>Cheezeburger Shirt</li>
<li class="item"><span class="closer">x</span>Buckit Shirt</li>
</ul>
</div>
<h3>Bags</h3>
<div>
<ul>
<li class="item"><span class="closer">x</span>Zebra Striped</li>
<li class="item"><span class="closer">x</span>Black Leather</li>
<li class="item"><span class="closer">x</span>Alligator Leather</li>
</ul>
</div>
<h3>Gadgets</h3>
<div>
<ul>
<li class="item"><span class="closer">x</span>iPhone</li>
<li class="item"><span class="closer">x</span>iPod</li>
<li class="item"><span class="closer">x</span>iPad</li>
</ul>
</div>
</div>
<div class='proc'><pre>
<br /></pre>
<div class="projLeader">
<label>Box1. Required number:
<div class="numbr">10</div>.
<div class="dropped"></div>
<div class="dif">Difference:</div>
</label>
<div class="ui-widget-content">
<ol>
<li class="placeholder" name="projLeader"></li>
<input type="hidden" name="projLeader" class="hiddenListInput1" />
</ol>
</div>
</div>
</div>
<div class='proc'><pre>
<br /></pre>
<div class="projLeader">
<label>Box2. Required number:
<div class="numbr">5</div>.
<div class="dropped"></div>
<div class="dif">Difference:</div>
</label>
<div class="ui-widget-content">
<ol>
<li class="placeholder" name="projLeader"></li>
<input type="hidden" name="projLeader" class="hiddenListInput1" />
</ol>
</div>
</div>
</div>
<br/>
<input type="submit" id="savebutton" class="button" value="Save" onclick="userSubmitted = true;" />
<div id="output"></div>
It looks like you are using jQuery, which makes it really easy to manipulate the DOM dynamically.
Here is what I would do. First, add a difference div which will hold the difference of n and numbr:
<div id="numbr">10</div>
<div id="difference"></div>
And in your JS, calculate the difference and add it to the div:
var n = $(this).closest("div.proc").find(".dropClass").length - 1;
var difference = parseInt($('#numbr').text(), 10) - n;
if (difference >= 0) {
$('#difference').text('Difference ' + difference);
}
Do you mean that you can use a PHP variable in javascript. If that's the case, this is probably what you are looking for:
<?php
$myVariable = 200;
?>
<script type="text/javascript">
$(document).ready(function () {
var myvar = <?= $myVariable; ?>;
$(document).on('change', '.numbr', function () {
var number = parseInt($(this).text(), 10);
var difference = myvar - number;
$('.somediv').text($difference);
});
});
</script>
<div class="numbr">20</div>
To get the dropClass content, use the text() method. length will give you the number of nodes for the given selector, it's not what you want here.
You can get the numbr and dropClass content with the text() method.
Try this(added some html for the snippet to work):
inner = $('#innerproc').closest("div.proc");
numbr = $('#numbr').text();
n = inner.find(".dropClass").text();
inner.find("div.dropped").text("Items Dropped: " + (n - numbr) + ".");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="numbr">10</div>
<div class="proc">
<div id="innerproc"></div>
<div class="dropClass">21</div>
<div class="dropped"></div>
</div>
How can I get each menu item highlighted to it's own color as I scroll to it's section in my WordPress site?
Eg: If I scroll down to about section, the about menu item should change color. If I scroll to contacts section, the menu item should change to a different color and obviously ABOUT should dehighlight immediately.
At the moment, when I scroll down 150px, the menu get fixed to the top. Then as I scroll down to about section, the menu item gets bold, when go to another section, the respective menu item will turn bold immediately and obviously the about menu item dehighlights.
var num = 150; //number of pixels before modifying styles
$(window).bind('scroll', function () {
if ($(window).scrollTop() > num) {
$('nav#site-navigation').addClass('fixed');
} else {
$('nav#site-navigation').removeClass('fixed');
}
});
$("nav ul li a").addClass("marker");
var navLinks = $('nav ul li a'),
navH = $('nav').height(),
section = $('section'),
documentEl = $(document);
documentEl.on('scroll', function() {
var currentScrollPos = documentEl.scrollTop();
section.each(function() {
var self = $(this);
if (self.offset().top < (currentScrollPos + navH ) && (currentScrollPos + navH) < (self.offset().top + self.outerHeight())) {
var targetClass = '.' +self.attr('class') + 'marker';
navLinks.removeClass('active');
$(targetClass).addClass('active');
}
});
});
Now for the colors, I added this snippet to the first function but the colors only change when I click on each menu item more than once.
$("a.marker.active:contains(About)").addClass('item-2');
$("a.marker.active:contains(Products)").addClass('item-3');
$("a.marker.active:contains(Scent)").addClass('item-4');
$("a.marker.active:contains(Clients)").addClass('item-5');
$("a.marker.active:contains(Contact)").addClass('item-6');
Any different way of solving this?
$(window).bind('scroll', function() {
$('.toggle-menu').each(function() {
var post = $(this);
var position = post.position().top - $(window).scrollTop();
if (position <= 0) {
post.addClass('selected');
var theID = $(this).attr('id');
$('nav li a').removeClass('active');
$('#nav-'+theID).addClass('active');
} else {
post.removeClass('selected');
}
});
});
.active {
color: red;
}
#nav-about.active {
color: green;
}
#nav-products.active {
color: gray;
}
#nav-scent.active {
color: yellow;
}
header {
position: relative;}
nav {
position: absolute;
display:block;
top:0;
left:0;
width:100%;
}
nav ul {
list-style: none;}
nav li {
display: inline-block;
padding: 5px 10px;}
section {
padding:150px;
border-top:1px solid red;}
.selected {
font-weigt: 600;
color:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header>
<nav>
<ul>
<li><a class="active" id="nav-about" href="#about">About</a></li>
<li><a id="nav-products" href="#products">Products</a></li>
<li><a id="nav-scent" href="#scent">Scent</a></li>
<li><a id="nav-clients" href="#clients">Clients</a></li>
</ul>
</nav>
</header>
<section class="toggle-menu" id="about">
<div class="wrap">
About
</div>
</section>
<section class="toggle-menu" id="products">
<div class="wrap">
Products
</div>
</section>
<section class="toggle-menu" id="scent">
<div class="wrap">
Scent
</div>
</section>
<section class="toggle-menu" id="clients">
<div class="wrap">
Clients
</div>
</section>
Something like this?
i want to have functionality such as that of select box, when using select box, if we type some keyword and that keyword happens to match in that select box, the pointer moves to the specified text, i want to achieve similar functionality here, following is my HTML
Get Value
<ul>
<li class="init">SELECT</li>
<li data-value="value 1">1</li>
<li data-value="value 2">2</li>
<li data-value="value 3">3</li>
</ul>
Following is my JS
$("ul").on("click", ".init", function() {
$(this).closest("ul").children('li:not(.init)').toggle();
});
var allOptions = $("ul").children('li:not(.init)');
$("ul").on("click", "li:not(.init)", function() {
allOptions.removeClass('selected');
$(this).addClass('selected');
$("ul").children('.init').html($(this).html());
allOptions.toggle();
});
$("#submit").click(function() {
alert("The selected Value is "+ $("ul").find(".selected").data("value"));
});
Following is my CSS
ul {
height: 30px;
width: 150px;
border: 1px #000 solid;
}
ul li { padding: 5px 10px; z-index: 2; }
ul li:not(.init) { float: left; width: 130px; display: none; background: #ddd; }
ul li:not(.init):hover, ul li.selected:not(.init) { background: #09f; }
li.init { cursor: pointer; }
a#submit { z-index: 1; }
Fiddle
http://jsfiddle.net/Starx/a6NJk/2/
Check out something like chosen or selectize. Download their files and add them to your site. if you go with Chosen you can initialize the plugin by adding .chosen-select to your form element:
<select class="chosen-select">
<option>Hello</option>
<option>Whats Up</option>
<option>How Are You</option>
<option>Nice to See You</option>
<option>Goodbye</option>
</select>
EXAMPLE