Highlight the parent even when a child element is selected (opencart) - javascript

Last week I created an e-shop with opencart. Now I'm trying to customize the default top menu. What I want to do is to keep the parent highlighted even when a child element is selected
I highlight the current page with this js :
<script type="text/javascript" >
function extractPageName(hrefString)
{
var arr = hrefString.split('/');
return (arr.length < 2) ? hrefString : arr[arr.length-2].toLowerCase() + arr[arr.length-1].toLowerCase();
}
function setActiveMenu(arr, crtPage)
{
for (var i=0; i < arr.length; i++)
{
if(extractPageName(arr[i].href) == crtPage)
{
if (arr[i].parentNode.tagName != "DIV")
{
arr[i].className = "current";
arr[i].parentNode.className = "current";
}
}
}
}
function setPage()
{
hrefString = document.location.href ? document.location.href :document.location ;
if (document.getElementById("menu") !=null)
setActiveMenu(document.getElementById("menu").getElementsByTagName("a"),extractPageName(hrefString));
}
window.onload=function()
{
setPage();
}
</script>
Any help would be greatly appreciated.
p.s. sorry for my English, if you can't understand what I want to make.

I figured it out. Tooraj gives me the idea. Here is my code :
<script type="text/javascript" >
function extractPageName(hrefString)
{
var arr = hrefString.split('/');
return (arr.length < 2) ? hrefString : arr[arr.length-2].toLowerCase() + arr[arr.length-1].toLowerCase();
}
function setActiveMenu(arr, crtPage)
{
for (var i=0; i < arr.length; i++)
{
if(extractPageName(arr[i].href) == crtPage)
{
if (arr[i].parentNode.parentNode.parentNode.parentNode.tagName != "DIV",
arr[i].parentNode.tagName != "DIV")
{
arr[i].className = "current";
arr[i].parentNode.parentNode.parentNode.parentNode.className = "current";
arr[i].parentNode= "current";
}
}
}
}
function setPage()
{
hrefString = document.location.href ? document.location.href :document.location ;
if (document.getElementById("menu") !=null)
setActiveMenu(document.getElementById("menu").getElementsByTagName("a"),extractPageName(hrefString));
}
window.onload=function()
{
setPage();
}
</script>

Related

Creating and calling helper / reusable functions

Here is my code, simply I am retrieving an array from the back end, and displaying in a select element, and just checking if an attribute is true then I show an input of expiry date, else I hide it
this is working code...all I need to do is just simplify, just need to create 2 helper/ reusable functions so I can call them ... because as you can see, there is repetitive code...
I tried splitting them to two functions, one to search if this item actually exists and if so it returns the item, if not it returns false...and the other will check if that item actually expires and if it does, it shows the form input of expiry date, else it hides it
any help would be appreciated. Thanks,
$(document).ready(function() {
$('#expiryDate_input').hide();
var allItems = {!! json_encode($items->toArray()) !!};
var arrayItemId = $('#item').val();
for (i=0; i < allItems.length; i++) {
var selectedItemid = allItems[i].id;
if (selectedItemid == arrayItemId){
if(allItems[i].expires) {
$('#expiryDate_input').show();
}
else {
$('#expiryDate_input').hide();
}
}
}
$("#item").change(function() {
var currentItemId = $(this).val();
if (currentItemId == '') {
$('#expiryDate_input').hide();
}
for (i=0; i < allItems.length; i++) {
var arrayItemId = allItems[i].id;
if (currentItemId == arrayItemId){
if(allItems[i].expires) {
$('#expiryDate_input').show();
}
else {
$('#expiryDate_input').hide();
}
}
}
});
});
function search(id) {
for (i=0; i < allItems.length; i++) {
var arrayItemId = allItems[i].id;
if (currentItemId == arrayItemId){
} return allItems[i];
else { return false
}
}
}
function showHide(item) {
if(item.expires) {
$('#expiryDate_input').show();
}
else {
$('#expiryDate_input').hide();
}
}
}
$(document).ready(function() {
function showHide(item) {
if(item.expires) {
$('#expiryDate_input').show();
}
else {
$('#expiryDate_input').hide();
}
}
function search(id) {
for (i=0; i < allItems.length; i++) {
var arrayItemId = allItems[i].id;
if (id == arrayItemId){
showHide( allItems[i]);
}
}
}
$('#expiryDate_input').hide();
var allItems = {!! json_encode($items->toArray()) !!};
var arrayItemId = $('#item').val();
search(arrayItemId);
}
$("#item").change(function() {
var currentItemId = $(this).val();
if (currentItemId == '') {
$('#expiryDate_input').hide();
}
search(currentItemId);
});
});

How to make an event for elements selection in DOM based on event.shiftKey?

I cannot understand how to make work event.shiftKey condition for elements selection from previous target element to the current target, that clicked after firstone... Other conditions are working perfect.
P.S.
DO NOT click on any element by shift+left_click, because you will crash the page!
function clickOnLi(event) {
var target = event.target;
var li = menu.querySelectorAll('li');
if (target.tagName != 'LI') return;
if (event.ctrlKey) {
if (target.className != 'greenLi') {
target.classList.add('greenLi');
} else if (target.className == 'greenLi') {
target.classList.remove('greenLi');
}
}
if (event.shiftKey){
target.className = 'greenLi';
for (var i = 0; i < li.length; i++) {
do {
li[i].className == 'greenLi';
} while (li[i] != target);
}
}
if (!event.ctrlKey && !event.shiftKey) {
target.className = 'greenLi';
for (var i = 0; i < li.length; i++) {
if (li[i] != target) {
li[i].className = '';
}
}
}
}
menu.addEventListener( 'click', clickOnLi );
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<style>
li {
cursor: pointer;
}
.greenLi {
background-color: green;
}
</style>
</head>
<body>
<ul id="menu">
<li>Крис</li>
<li>Робин</li>
<li>Бэтмен</li>
<li>Супермен</li>
<li>Халк</li>
</ul>
<script>
</script>
</body>
</html>
Your logic inside if (event.shiftKey) block is incorrect. Replace your:
if (event.shiftKey){
...
}
to
if (event.shiftKey){
target.className = 'greenLi';
let alreadySelectedLiIndex = -1;
let justSelectedLiIndex = -1;
for (var i = 0; i < li.length; i++) {
if (li[i].className == 'greenLi' && li[i] != target)
alreadySelectedLiIndex = i;
if (li[i] == target)
justSelectedLiIndex = i;
}
if (alreadySelectedLiIndex != -1){
for (var i = 0; i < li.length; i++) {
if (alreadySelectedLiIndex < i && i <= justSelectedLiIndex
|| justSelectedLiIndex <= i && i < alreadySelectedLiIndex){
li[i].classList.add('greenLi');
}
}
}
}
the shiftKey event is correct, the issue is with your do-while loop. You have 3 states that you need to check... target, classname with greenLi, and lastly everything else that is neither of the previous two.
Your IF block should look like the following:
if (event.shiftKey){
target.className = 'greenLi';
for (var i = 0; i < li.length; i++) {
if (li[i].className == 'greenLi') {
//do nothing
}else if(li[i] != target){
li[i].className = '';
}
}
}

How to display all child elements in JQuery/Javascript?

I am trying to display multiple child elements in jQuery but only the first child element gets displayed. I can force the browser to show all of them through Inspect and changing the css display from none to block. Can anyone help me find the problem in my code.I use Radio buttons, this is the code :
<script type="text/javascript">
$(document).ready(function () {
$('##radioButtonListSectionId input[type="radio"]
[checked="checked"]').each(function () {
ShowRadioButtonListDependentField(this, false);
});
});
$('##radioButtonListSectionId input[type="radio"]').change(function
() {
var result = $(this).val();
$('##uniqueID-hidden').val(result);
ShowRadioButtonListDependentField(this, false);
});
function ShowRadioButtonListDependentField(element, show) {
debugger;
var fieldKey = $(element).val(), children;
var currentId = element.attributes["currentid"].value;
if (currentId != 0) {
if ($('.main-dialogbox.modal.fade.in').length > 0)
children = $('.modal-body .control-group[parentid=' +
currentId + ']');
else if ($('.idea-task.open').length > 0)
children = $('.idea-task .control-group[parentid=' +
currentId + ']');
else
children = $('.control-group[parentid=' + currentId +
']');
if ($(element).is(":checked") && $(element).is(":visible"))
show = true;
else
show = false;
children.hide();
children.each(function () {
var keys =
this.attributes["parentOptionKey"].value.split("</br>");
var haschildren = this.attributes["haschildren"].value;
for (var i = 0; i < keys.length; i++) {
if (keys[i] == fieldKey) {
if (show) {
$(this).show();
show = false;
$(this.getElementsByClassName("ishidden")).val("False");
} else {
$(this).hide();
$(this.getElementsByClassName("ishidden")).val("True");
if (haschildren.toLowerCase() == "true") {
ShowCheckListDependentField(this,
false);
}
}
}
else {
$(this.getElementsByClassName("ishidden")).val("True");
}
}
});
}
}
</script>

Using THIS inside a click event managed by addEventListener

I am trying this very simple code to realize a TicTacToe in plain Javascript:
function inizializza()
{
var x = document.querySelectorAll(".riga div");
var i;
for (i = 0; i < x.length; i++) {
document.querySelectorAll(".riga div")[i].addEventListener("click",
cambia);
}
}
var segno = "X";
function cambia()
{
if (this.innerHTML != "")
{
alert("ERRORE!")
}
else
{
this.innerHTML = segno;
if (segno == "X")
segno = "O";
else
segno = "X";
}
}
Function inizializza() is called on body load.
When you click on a .riga div (a cell in my game table), the event click should change the text displayed in the cell: X or O. But this is not working, because I can't use "this" kewyword to retrieve clicked object properties.
How can I do it?
Thanks a lot!
Giancarlo
you can use closures here
check the following snippet
window.onload = function() {
inizializza();
}
function inizializza() {
var x = document.querySelectorAll(".riga div");
var i;
for (i = 0; i < x.length; i++) {
document.querySelectorAll(".riga div")[i].addEventListener("click",function(event){
cambia(this);
});
}
}
var segno = "X";
function cambia(obj) {
if (obj.innerHTML == "") {
alert("ERRORE!")
} else {
obj.innerHTML = segno;
if (segno == "X")
segno = "O";
else
segno = "X";
}
}
<div class="riga">
<div>1</div>
<div>2</div>
<div>3</div>
<div>X</div>
</div>
Hope it helps
You can use the event object passed as the first argument of the click event.
event.target will work for most of the browser and event.srcElement works with few old microsoft browsers.
function inizializza()
{
var x = document.querySelectorAll(".riga div");
console.log(x);
var i;
for (i = 0; i < x.length; i++) {
document.querySelectorAll(".riga div")[i].addEventListener("click",
cambia);
}
}
var segno = "X";
function cambia(event)
{
var element = event.target || event.srcElement;
if (target.innerHTML !== "")
{
alert("ERRORE!")
}
else
{
this.innerHTML = segno;
if (segno == "X")
segno = "O";
else
segno = "X";
}
}
Working example : https://plnkr.co/edit/NaTwU7XmmU9sLgNiFrjO?p=preview

curious css setting issue using setInterval

I'm trying to make a palindrome checker that changes the currently compared letters as it recurs.
Essentially, callback will do:
r aceca r
r a cec a r
ra c e c ar
rac e car
My JS Bin shows that the compared letters change green sometimes, but if you run it again, the letters won't change. Why is there a difference in results? It seems to sometimes run in Chrome, more often in FireFox, but it's all intermittent.
Code if needed (also available in JS Bin):
var myInterval = null;
var container = [];
var i, j;
var set = false;
var firstLetter, lastLetter;
$(document).ready(function(){
$("#textBox").focus();
$(document).click(function() {
$("#textBox").focus();
});
});
function pal (input) {
var str = input.replace(/\s/g, '');
var str2 = str.replace(/\W/g, '');
if (checkPal(str2, 0, str2.length-1)) {
$("#textBox").css({"color" : "green"});
$("#response").html(input + " is a palindrome");
$("#palindromeRun").html(input);
$("#palindromeRun").lettering();
if (set === false) {
callback(str2);
set = true;
}
}
else {
$("#textBox").css({"color" : "red"});
$("#response").html(input + " is not a palindrome");
}
if (input.length <= 0) {
$("#response").html("");
$("#textBox").css({"color" : "black"});
}
}
function checkPal (input, i, j) {
if (input.length <= 1) {
return false;
}
if (i === j || ((j-i) == 1 && input.charAt(i) === input.charAt(j))) {
return true;
}
else {
if (input.charAt(i).toLowerCase() === input.charAt(j).toLowerCase()) {
return checkPal(input, ++i, --j);
}
else {
return false;
}
}
}
function callback(input) {
$("#palindromeRun span").each(function (i, v) {
container.push(v);
});
i = 0;
j = container.length - 1;
myInterval = setInterval(function () {
if (i === j || ((j-i) === 1 && input.charAt(i) === input.charAt(j))) {
set = false;
window.clearInterval(myInterval);
container = [];
}
console.log(i + ' : ' + j);
$(container[i]).css({"color": "green"});
$(container[j]).css({"color": "green"});
i++;
j--;
}, 1000);
}
HTML:
<input type="text" id="textBox" onkeyup="pal(this.value);" value="" />
<div id="response"></div>
<hr>
<div id="palindromeRun"></div>
I directly pasted the jsLettering code in the JSBin, but here is the CDN if needed:
<script src="http://letteringjs.com/js/jquery.lettering-0.6.1.min.js"></script>
Change:
myInterval = setInterval(function () {
if (i === j) {
set = false;
window.clearInterval(myInterval);
container = [];
}
console.log(i + ' : ' + j);
to:
myInterval = setInterval(function () {
if (i >= j) {//Changed to prevent infinite minus
set = false;
window.clearInterval(myInterval);
container = [];
}
console.log(i + ' : ' + j);
demo

Categories