How to know mouseLeave on two element - javascript

Im trying to create a drop down menu when hovering, something like the the following.
Under the header of a website.
Im doing so with jQuery, Im using the events mouseEnter and mouse leave.
with the following code.
var LastThis = null;
$(".divOpener, #floatingNewNav")
.mouseleave(function(event)
{
console.log(event);
if($(event.toElement).attr("id") != "floatingNewNav") // do not close since we leaved the element but we got on the floating nav.
{
$("#floatingNewNav").hide(0);
if(LastThis.attr("id") == "ShopByBrand")
{
LastThis.removeClass("NavSelected");
$("#"+LastThis.attr("id")+"_Nav").css("display","none");
}
if(LastThis.attr("id") == "ShopByCategory")
{
LastThis.removeClass("NavSelected");
$("#"+LastThis.attr("id")+"_Nav").css("display","none");
}
if(LastThis.attr("id") == "ShopByPrice")
{
LastThis.removeClass("NavSelected");
$("#"+LastThis.attr("id")+"_Nav").css("display","none");
}
}
});
$(".divOpener")
.mouseenter(function()
{
LastThis = $(this);
if($(this).attr("id") == "ShopByBrand")
{
$("#"+$(this).attr("id")+"_Nav").css("display","block");
$(this).addClass('NavSelected');
}
if($(this).attr("id") == "ShopByCategory")
{
$("#"+$(this).attr("id")+"_Nav").css("display","block");
$(this).addClass('NavSelected');
}
if($(this).attr("id") == "ShopByPrice")
{
$("#"+$(this).attr("id")+"_Nav").css("display","block");
$(this).addClass('NavSelected');
}
var DivPosition = $(this).parent().position();
var Position = $(this).position();
var curTop = DivPosition.top;
var curLeft = Position.left;
var curWidth = $(this).width();
var curHeight = $(this).parent().height();
var DivWidth = $(this).parent().width();
var WidthOfNav = 400;
var OffSetLeft = (curLeft+(curWidth/2)-(WidthOfNav/2)+WidthOfNav)-(DivPosition.left+DivWidth);
var OffSetLeft = (OffSetLeft>0?OffSetLeft:0);
$("#floatingNewNav").css("position","absolute");
$("#floatingNewNav").css("height","100px");
$("#floatingNewNav").css("top",(curTop+curHeight)+"px");
$("#floatingNewNav").css("left",((curLeft+(curWidth/2))-(WidthOfNav/2))-OffSetLeft+"px");
$("#floatingNewNav").css("width",WidthOfNav+"px");
$("#floatingNewNav").show(0);
});
Html
<div id="newNavDiv">
<span><form style="display: inline-block;" action="search.php" method="get"><input id="SearchBar" name="q" type="text"></form></span>
<div class="SearchButtonDiv"><input id="SearchButton" type="button" value="SEARCH"></div>
<span class="NewNavSeparator"></span>
<div id="Special" style="color: red;">
SPECIALS
</div>
<span class="NewNavSeparator"></span>
<div id="ShopByBrand" class="divOpener">
SHOP BY<br/>BRAND
</div>
<span class="NewNavSeparator"></span>
<div id="ShopByCategory" class="divOpener">
SHOP BY<br/>CATEGORY
</div>
<span class="NewNavSeparator"></span>
<div id="ShopByPrice" class="divOpener">
SHOP BY<br/>PRICE
</div>
</div>
<div id="floatingNewNav">
<div id="ShopByBrand_Nav"></div>
<div id="ShopByCategory_Nav"></div>
<div id="ShopByPrice_Nav"></div>
</div>
css
#WebsiteHeader
{
height: 170px;
background: url("Photo/header.png") no-repeat top;
background-size:100%;
}
#NewNavBar
{
height: 42px;
background: url("Photo/newNavigator.png") no-repeat top;
background-size:100%;
padding: 4px;
text-align: center;
}
#newNavDiv
{
display: inline-block;
width: 960px;
text-align: right;
}
#SearchBar
{
font-size: 16px;
color: grey;
width: 245px;
height: 24px;
padding-left: 5px;
background-color: #ffffff;
border-radius: 4px 4px 4px 4px;
-moz-border-radius: 4px 4px 4px 4px;
-webkit-border-radius: 4px 4px 4px 4px;
border: 1px solid #c7c7c7;
}
.SearchButtonDiv
{
display: inline-block;
}
#SearchButton
{
color:#ffffff;
font-size: 13px;
height: 30px;
background-color: red;
padding: 8px;
border-radius: 4px 4px 4px 4px;
-moz-border-radius: 4px 4px 4px 4px;
-webkit-border-radius: 4px 4px 4px 4px;
border: 0px solid;
}
#Special
{
vertical-align: middle;
width: 130px;
display: inline-block;
text-align: center;
color: #ffffff;
font-family: "Arial";/* for firefox*/
font-family: "Arial Black";/* if browser have the font it will overide arial*/
font-weight:900;/* for firefox*/
font-size: 13px;
font-style: italic;
}
.divOpener
{
vertical-align: middle;
width: 140px;
display: inline-block;
text-align: center;
color: #ffffff;
font-family: "Arial";/* for firefox*/
font-family: "Arial Black";/* if browser have the font it will overide arial*/
font-weight:900;/* for firefox*/
font-size: 13px;
font-style: italic;
}
.NewNavSeparator
{
border-right: 1px rgba(245, 245, 245, 0.70) solid;
margin-right: 5px;
margin-left: 6px;
height: 30px;
}
#MainPagesLinks
{
padding-bottom: 0;
}
#MainPagesLinks a
{
text-align: center;
color:#ffffff;
text-decoration: none;
font-size: 13px;
width: 75px;
display: inline-block;
background-color: red;
padding-left: 4px;
padding-right: 4px;
border-radius: 4px 4px 0px 0px;
-moz-border-radius: 4px 4px 0px 0px;
-webkit-border-radius: 4px 4px 0px 0px;
border-top: 1px solid rgba(255,240,240,0.4);
border-right: 1px solid rgba(255,240,240,0.4);
border-left: 1px solid rgba(255,240,240,0.4);
box-shadow:
inset 0 3px 2px rgba(255,255,255,.22),
inset 0 20px 10px rgba(255,255,255,.12),
0 0 4px 1px rgba(0,0,0,.1),
0 3px 2px rgba(0,0,0,.2);
/*border: 1px solid #000000;*/
}
#floatingNewNav
{
background-color: #aaaac6;
margin-top: 0px;
border-radius: 0px 0px 6px 6px;
-moz-border-radius: 0px 0px 6px 6px;
-webkit-border-radius: 0px 0px 6px 6px;
}
.NavSelected
{
color:black;
background-color: #aaaac6;
border-bottom: 0px #aaaac6 solid;
border-radius: 6px 6px 0px 0px;
-moz-border-radius: 6px 6px 0px 0px;
-webkit-border-radius: 6px 6px 0px 0px;
}
.divOpener class is the <a> Shop by category</a> and others links
#floatingNewNav
Here is the live example.
https://www.newyorkpowertools.com/Template/headerTemplate.html
You will see in that example that it works in chrome,Ie,safari But on firefox it doesn't work. beacause for some reason firefox dont return the object toElement in the event object..
My question
Is there a way I could create an event mouseEnter and mouseLeave with two element and fake that it is ONLY one element so I dont need to
if($(event.toElement).attr("id") != "floatingNewNav")
Thanks for the help, And Sorry for the confusing question,.

To create a drop-down menu that appears on hover, like the one in your example, I would use CSS. See example below:
HTML
<ul id="menu">
<li>Menu 1</li>
<li>Menu 2
<ul class="sub-menu">
<li>Sub Menu 1</li>
<li>Sub Menu 2</li>
<li>Sub Menu 3</li>
<li>Sub Menu 4</li>
</ul>
</li>
<li>Menu 3</li>
</ul>
CSS
#menu li ul {
display: none;
}
#menu li:hover ul {
display: block;
}

You can simply do this http://jsfiddle.net/aheLv/1/
$(".divOpener, #floatingNewNav").mouseenter(function () {
if (!$(this).is('#floatingNewNav')) {
LastThis = $(this);
}
$("#" + LastThis.attr("id") + "_Nav").css("display", "block");
LastThis.addClass('NavSelected');
var DivPosition = LastThis.parent().position();
var Position = LastThis.position();
var curTop = DivPosition.top;
var curLeft = Position.left;
var curWidth = LastThis.width();
var curHeight = LastThis.parent().height();
var DivWidth = LastThis.parent().width();
var WidthOfNav = 400;
var OffSetLeft = (curLeft + (curWidth / 2) - (WidthOfNav / 2) + WidthOfNav) - (DivPosition.left + DivWidth);
var OffSetLeft = (OffSetLeft > 0 ? OffSetLeft : 0);
$("#floatingNewNav").css("position", "absolute");
$("#floatingNewNav").css("height", "100px");
$("#floatingNewNav").css("top", (curTop + curHeight) + "px");
$("#floatingNewNav").css("left", ((curLeft + (curWidth / 2)) - (WidthOfNav / 2)) - OffSetLeft + "px");
$("#floatingNewNav").css("width", WidthOfNav + "px");
$("#floatingNewNav").show(0);
});
There are lot of things you can do to refactor this code. Actually there are some extra stuff in the fiddle that I am taking them out now, I will update soon
UPDATE:
here is the final code
var LastThis = null;
var openers = $(".divOpener, #floatingNewNav");
openers.mouseleave(function (event) {
$("#floatingNewNav").hide();
LastThis.removeClass("NavSelected");
$("#" + LastThis.attr("id") + "_Nav").hide();
});
openers.mouseenter(function () {
if (!$(this).is('#floatingNewNav')) {
LastThis = $(this);
}
$("#" + LastThis.attr("id") + "_Nav").show();
LastThis.addClass('NavSelected');
var DivPosition = LastThis.parent().position();
var Position = LastThis.position();
var curTop = DivPosition.top;
var curLeft = Position.left;
var curWidth = LastThis.width();
var curHeight = LastThis.parent().height();
var DivWidth = LastThis.parent().width();
var WidthOfNav = 400;
var OffSetLeft = (curLeft + (curWidth / 2) - (WidthOfNav / 2) + WidthOfNav) - (DivPosition.left + DivWidth);
var OffSetLeft = (OffSetLeft > 0 ? OffSetLeft : 0);
$("#floatingNewNav").css({
'position': 'absolute',
'height': '100px',
'top': (curTop + curHeight) + 'px',
'left': ((curLeft + (curWidth / 2)) - (WidthOfNav / 2)) - OffSetLeft + 'px',
'width': WidthOfNav + 'px'
}).show();
});
http://jsfiddle.net/aheLv/2/
As a suggestion, menus like these can be done in css only if you structure your html the right way. See Kevin's answer for the structure

Just to throw out a different concept, your picture screams "jQuery tabs" :-), so I used simple tabs, and created a jQuery trigger event for each one.
FIDDLE
JS
$('.charts').tabs();
$('#firstone').mouseover(function(){
$(this).trigger('click');
});
$('#secondone').mouseover(function(){
$(this).trigger('click');
});
$('#thirdone').mouseover(function(){
$(this).trigger('click');
});
Not elegant, but I'll play with it some more and see if it can be 'elegantized'.

Seems like you're overcomplicating things..
How about just tracking the direction of the mouse, and if its headed downward, don't hide the menuitems below..
Check this fiddle..
http://jsfiddle.net/ReVLN/2/
Checked its working in Mozilla and chrome/etc..
var mY = 0;
$('div.menuItems').mousemove(function(e){
// moving upward
if (e.pageY < mY) {
flag = "upward";
} else {
flag = "downward";
}
// set new mY after doing test above
mY = e.pageY;
});
Thanks,
jf_it

Related

JS - How to autoresize textarea based on input text mirrored from other textarea input?

I am trying to achieve that textarea height is automatically adjusted based on length of text which is mirrored into in from input textarea. Can you please take a look where might be the issue? Thank you for your help.
http://jsfiddle.net/wshuni/vjwe39ah/93/
var titleInput = document.querySelector("#titleInput");
var bodyInput = document.querySelector("#bodyInput");
var title = document.querySelector("#title");
var body = document.querySelector("#body");
title.addEventListener('keydown', autosize);
body.addEventListener('keydown', autosize);
titleInput.addEventListener('keydown', autosize);
bodyInput.addEventListener('keydown', autosize);
function autosize(){
var el = this;
setTimeout(function(){
el.style.cssText = 'height:auto; padding:0';
// for box-sizing other than "content-box" use:
// el.style.cssText = '-moz-box-sizing:content-box';
el.style.cssText = 'height:' + el.scrollHeight + 'px';
},0);
}
var input = document.querySelector("#titleInput");
var mirror = document.querySelector("#title");
var bodyInput = document.querySelector("#bodyInput");
var bodyMirror = document.querySelector("#body");
input.addEventListener('input', function(event) {
mirror.innerText = event.target.value;
});
bodyInput.addEventListener('input', function(event) {
bodyMirror.innerText = event.target.value;
});
explanation - image
You can do this by setting styles for bodyMirror textarea in the same function you use to resize bodyInput textarea.
var bodyMirror = document.querySelector("#body");
function autosize(){
var el = this;
setTimeout(function(){
el.style.cssText = 'height:auto; padding:0';
el.style.cssText = 'height:' + el.scrollHeight + 'px';
bodyMirror.style.cssText = 'height:auto; padding:0';
bodyMirror.style.cssText = 'height:' + el.scrollHeight + 'px';
},0);
}
You should remove fixed height in body class and update the height of mirrored text area just after text is copied.
var titleInput = document.querySelector("#titleInput");
var bodyInput = document.querySelector("#bodyInput");
titleInput.addEventListener('keydown', autosize);
bodyInput.addEventListener('keydown', autosize);
function autosize(){
var el = this;
el.style.cssText = 'height:auto; padding:0';
// for box-sizing other than "content-box" use:
// el.style.cssText = '-moz-box-sizing:content-box';
el.style.cssText = 'height:' + el.scrollHeight + 'px';
}
var input = document.querySelector("#titleInput");
var mirror = document.querySelector("#title");
var bodyInput = document.querySelector("#bodyInput");
var bodyMirror = document.querySelector("#body");
input.addEventListener('input', function(event) {
mirror.innerText = event.target.value;
mirror.style.cssText = 'height:' + mirror.scrollHeight + 'px';
});
bodyInput.addEventListener('input', function(event) {
bodyMirror.innerText = event.target.value;
bodyMirror.style.cssText = 'height:' + bodyMirror.scrollHeight + 'px';
});
.frame {
width: 343px;
height: 114px;
background: rgb(255, 255, 255);
box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, 0.1),
0px 2px 5px 0px rgba(0, 0, 0, 0.15);
border-radius: 8px;
}
.title {
font-family: Inter-SemiBold;
position: relative;
font-size: 16px;
color: #21416C;
font-weight: 600;
height: 20px;
line-height: 20px;
width: 291px;
word-wrap: break-word;
border: none;
resize: none;
}
.body {
font-family: Inter-Regular;
position: relative;
font-size: 14px;
color: #5C7999;
font-weight: normal;
/*height: 16px;*/
line-height: 18px;
width: 311px;
word-wrap: break-word;
border: none;
resize: none;
}
.card {
/* Add shadows to create the "card" effect */
box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, 0.1),
0px 2px 5px 0px rgba(0, 0, 0, 0.15);
transition: 0.3s;
width: 343px;
border-radius: 8px;
background: #FFFFFF;
height: auto;
}
/* On mouse-over, add a deeper shadow */
.card:hover {
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2);
}
.containerTitle {
padding-top: 14px;
padding-right: 36px;
padding-bottom: 0px;
padding-left: 16px;
}
.containerBody {
padding-top: 2px;
padding-right: 16px;
padding-bottom: 16px;
padding-left: 16px;
}
i {
color: #1A67D2;
font-size: 24px !important; /* 24px preferred icon size */
position: absolute;
padding-top: 12px;
padding-right: 12px;
padding-bottom: 78px;
padding-left: 307px;
}
<body style="background-color:#1A67D2;">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons"
rel="stylesheet">
<div class="containerTitle">
<textarea id="titleInput" rows='1' type="text" class="title" placeholder="Add title text..."></textarea>
</div>
<div class="containerBody">
<textarea id="bodyInput" rows='1' type="text" class="body" placeholder="Add body text..."></textarea>
</div>
<div class="card">
<i class="material-icons">close</i>
<div class="containerTitle">
<textarea id="title" disabled rows='1' type="text" class="title" placeholder="Mirrored text - title..."></textarea>
</div>
<div class="containerBody">
<textarea id="body" disabled rows='1' type="text" class="body" placeholder="Mirrored text - body..."></textarea>
</div>
</div>
</body>

Question on element alignment and how cursor is able to stay flush with the text in this editable code textarea?

Looking at this codepen, most of it I grok. But a couple of things I don't understand:
How does the <code> element stay perfectly on top of the <textarea>? I would expect it to be below the textarea looking at the HTML code.
How is the cursor staying so well-aligned with the text such that it functions like the type of cursor in a word document? The cursor even aligns well with the text when I copy and paste the text. Is it the emmet dependency that's helping?
Here is the code:
HTML
<div class="editor-holder">
<ul class="toolbar">
<li><i class="fa fa-indent"></i></li>
<li><i class="fa fa-expand"></i></li>
</ul>
<div class="scroller">
<textarea class="editor allow-tabs"><div class="Editable Textarea">
<h1>This is a fully editable textarea which auto highlights syntax.</h1>
<p>Type or paste any code in here...</p>
<div>
<?php
var simple = "coding";
?>
<script>
with = "Tab or double space functionality";
</script></textarea>
<pre><code class="syntax-highight html"></code></pre>
</div>
</div>
(S)CSS
html, body{
margin: 0;
padding: 0;
height: 100%;
width: 100%;
position: relative;
background: rgb(114, 195, 195);
}
.editor-holder{
width: 800px;
height: 500px;
margin-top: 50px;
border-radius: 3px;
position: relative;
top: 0;
margin-left: -400px;
left: 50%;
background: #1f1f1f !important;
overflow: auto;
box-shadow: 5px 5px 10px 0px rgba(0, 0, 0, 0.4);
transition: all 0.5s ease-in-out;
&.fullscreen{
width: 100%;
height: 100%;
margin: 0;
left: 0;
}
.toolbar{
width: 100%;
list-style: none;
position: absolute;
top: -2px;
margin: 0;
left: 0;
z-index: 3;
padding: 8px;
background: #afafaf;
li{
display: inline-block;
}
a{
line-height: 20px;
background: rgba(144, 144, 144, 0.6);
color: grey;
box-shadow: inset -1px -1px 1px 0px rgba(0,0,0,0.28);
display: block;
border-radius: 3px;
cursor: pointer;
&:hover{
background: rgba(144, 144, 144, 0.8);
}
&.active{
background: rgba(144, 144, 144, 0.8);
box-shadow: none;
}
}
i{
color: #565656;
padding: 8px;
}
}
textarea, code{
width: 100%;
height: auto;
min-height: 450px;
font-size: 14px;
border: 0;
margin: 0;
top: 46px;
left: 0;
padding: 20px !important;
line-height: 21px;
position: absolute;
font-family: Consolas,Liberation Mono,Courier,monospace;
overflow: visible;
transition: all 0.5s ease-in-out;
}
textarea{
background: transparent !important;
z-index: 2;
height: auto;
resize: none;
color: #fff;
text-shadow: 0px 0px 0px rgba(0, 0, 0, 0);
text-fill-color: transparent;
-webkit-text-fill-color: transparent;
&::-webkit-input-placeholder{
color: rgba(255, 255, 255, 1);
}
&:focus{
outline: 0;
border: 0;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}
}
code{
z-index: 1;
}
}
pre {
white-space: pre-wrap;
white-space: -moz-pre-wrap;
white-space: -pre-wrap;
white-space: -o-pre-wrap;
word-wrap: break-word;
code{
background: #1f1f1f !important;
color: #adadad;
.hljs {
color: #a9b7c6;
background: #282b2e;
display: block;
overflow-x: auto;
padding: 0.5em
}
.hljs-number,
.hljs-literal,
.hljs-symbol,
.hljs-bullet {
color: #6897BB
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-deletion {
color: #cc7832
}
.hljs-variable,
.hljs-template-variable,
.hljs-link {
color: #629755
}
.hljs-comment,
.hljs-quote {
color: #808080
}
.hljs-meta {
color: #bbb529
}
.hljs-string,
.hljs-attribute,
.hljs-addition {
color: #6A8759
}
.hljs-section,
.hljs-title,
.hljs-type {
color: #ffc66d
}
.hljs-name,
.hljs-selector-id,
.hljs-selector-class {
color: #e8bf6a
}
.hljs-emphasis {
font-style: italic
}
.hljs-strong {
font-weight: bold
}
}
}
JavaScript
var tabCharacter = " ";
var tabOffset = 2;
$(document).on('click', '#indent', function(e){
e.preventDefault();
var self = $(this);
self.toggleClass('active');
if(self.hasClass('active'))
{
tabCharacter = "\t";
tabOffset = 1;
}
else
{
tabCharacter = " ";
tabOffset = 2;
}
})
$(document).on('click', '#fullscreen', function(e){
e.preventDefault();
var self = $(this);
self.toggleClass('active');
self.parents('.editor-holder').toggleClass('fullscreen');
});
/*------------------------------------------
Render existing code
------------------------------------------*/
$(document).on('ready', function(){
hightlightSyntax();
emmet.require('textarea').setup({
pretty_break: true,
use_tab: true
});
});
/*------------------------------------------
Capture text updates
------------------------------------------*/
$(document).on('ready load keyup keydown change', '.editor', function(){
correctTextareaHight(this);
hightlightSyntax();
});
/*------------------------------------------
Resize textarea based on content
------------------------------------------*/
function correctTextareaHight(element)
{
var self = $(element),
outerHeight = self.outerHeight(),
innerHeight = self.prop('scrollHeight'),
borderTop = parseFloat(self.css("borderTopWidth")),
borderBottom = parseFloat(self.css("borderBottomWidth")),
combinedScrollHeight = innerHeight + borderTop + borderBottom;
if(outerHeight < combinedScrollHeight )
{
self.height(combinedScrollHeight);
}
}
// function correctTextareaHight(element){
// while($(element).outerHeight() < element.scrollHeight + parseFloat($(element).css("borderTopWidth")) + parseFloat($(element).css("borderBottomWidth"))) {
// $(element).height($(element).height()+1);
// };
// }
/*------------------------------------------
Run syntax hightlighter
------------------------------------------*/
function hightlightSyntax(){
var me = $('.editor');
var content = me.val();
var codeHolder = $('code');
var escaped = escapeHtml(content);
codeHolder.html(escaped);
$('.syntax-highight').each(function(i, block) {
hljs.highlightBlock(block);
});
}
/*------------------------------------------
String html characters
------------------------------------------*/
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
/*------------------------------------------
Enable tabs in textarea
------------------------------------------*/
$(document).delegate('.allow-tabs', 'keydown', function(e) {
var keyCode = e.keyCode || e.which;
if (keyCode == 9) {
e.preventDefault();
var start = $(this).get(0).selectionStart;
var end = $(this).get(0).selectionEnd;
// set textarea value to: text before caret + tab + text after caret
$(this).val($(this).val().substring(0, start)
+ tabCharacter
+ $(this).val().substring(end));
// put caret at right position again
$(this).get(0).selectionStart =
$(this).get(0).selectionEnd = start + tabOffset;
}
});
How does code and textarea elements stay aligned?
They are aligned because in the CSS they both use the same style which outlines the positioning of both elements. They both use position: absolute and the same top and left properties so stay in the same position.
See here https://www.w3schools.com/css/css_positioning.asp
In terms of the z-axis you can see that code has a z-index of 1 while textarea has 2 so text area stays on top.
How is the cursor staying aligned with the text?
There is no javascript acting on the cursor here. If you were to have any textarea in html the cursor would align with the text.

Javascript - I have two event listeners which run the same global scope function, but one of them isn't working...why?

For a bit of context, I'm currently new to Javascript and programming in general. I'm currently making a to-do list using vanilla javascript.
I want the user to be able to add an entry by either clicking on the "+" button, or by pressing the enter key in the input field.
Definitions:
let count = 0;
let getAdd = document.getElementById('add')
let getBackground = document.getElementById('background')
let getInputs = document.getElementsByClassName('input')
let getItems = document.getElementsByClassName('item')
let getName = document.getElementById('name')
The "keypress" event listener is working, but the "click" event listener is not. Here's the part in question:
function addevent() {
if (document.getElementById('name').value === '') {
alert("You need to type something in the input field first!")
return
}
if (getItems.length == 0) {
count += 1;
getBackground.innerHTML = ''
getBackground.style = null;
getBackground.innerHTML += '<div class="item"><div class="column input"></div><div id="spacer" class="column"></div><div id="bin" class="bin column row">X</div></div>'
getInputs[count - 1].innerHTML = document.getElementById('name').value
let heightplus = getBackground.offsetHeight;
getBackground.style.height = parseInt(heightplus + 35) + "px"
document.getElementById('name').value = ''
}
else {
count += 1
getBackground.innerHTML += '<div class="item"><div class="column input"></div><div id="spacer" class="column"></div><div id="bin" class="bin column row">X</div></div>'
getInputs[count - 1].innerHTML = document.getElementById('name').value
let heightplus = getBackground.offsetHeight;
getBackground.style.height = parseInt(heightplus + 35) + "px"
document.getElementById('name').value = ''
}
}
getAdd.addEventListener("click", addevent(), false);
getName.addEventListener("keypress", function enter(e) {
if (e.keyCode === 13) {
addevent();
}
}, false);
What am I missing here?
If you need any further info, let me know.
let count = 0;
let getAdd = document.getElementById('add')
let getBackground = document.getElementById('background')
let getInputs = document.getElementsByClassName('input')
let getItems = document.getElementsByClassName('item')
let getName = document.getElementById('name')
function noitems() {
if (count == 0) {
getBackground.innerHTML = '<div class="start">Click on the <strong>+</strong> button to get started</div>'
}
else if (count == -1) {
getBackground.innerHTML = '<div class="end">No more tasks? Happy days!</div>'
count += 1
}
getBackground.style.paddingTop = "0px"
getBackground.style.boxShadow = "0px 0px 0px 0px"
getBackground.style.backgroundColor = "white"
}
window.onload = noitems();
function addevent() {
if (document.getElementById('name').value === '') {
alert("You need to type something in the input field first!")
return
}
if (getItems.length == 0) {
count += 1;
getBackground.innerHTML = ''
getBackground.style = null;
getBackground.innerHTML += '<div class="item"><div class="column input"></div><div id="spacer" class="column"></div><div id="bin" class="bin column row">X</div></div>'
getInputs[count - 1].innerHTML = document.getElementById('name').value
let heightplus = getBackground.offsetHeight;
getBackground.style.height = parseInt(heightplus + 35) + "px"
document.getElementById('name').value = ''
}
else {
count += 1
getBackground.innerHTML += '<div class="item"><div class="column input"></div><div id="spacer" class="column"></div><div id="bin" class="bin column row">X</div></div>'
getInputs[count - 1].innerHTML = document.getElementById('name').value
let heightplus = getBackground.offsetHeight;
getBackground.style.height = parseInt(heightplus + 35) + "px"
document.getElementById('name').value = ''
}
}
getAdd.addEventListener("click", addevent(), false);
getName.addEventListener("keypress", function enter(e) {
if (e.keyCode === 13) {
addevent();
}
}, false);
function doSomething(e) {
if (e.target.id === "bin") {
if (getItems.length == 1) {
let clickeditem = e.target
getBackground.removeChild(clickeditem.parentNode)
count -= 2
noitems();
}
else {
let clickeditem = e.target
getBackground.removeChild(clickeditem.parentNode)
let heightminus = getBackground.offsetHeight;
getBackground.style.height = parseInt(heightminus - 75) + "px"
count -= 1
}
}
e.stopPropagation();
}
getBackground.addEventListener("click", doSomething, false)
#import url('https://fonts.googleapis.com/css2?family=Roboto:wght#100&display=swap');
body {
font-family: 'Roboto', sans-serif;
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Old versions of Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none; /* Non-prefixed version, currently
supported by Chrome, Opera and Firefox */
}
#title {
font-size: 32px;
margin-top: 1em;
border: 5px;
border-style: solid;
border-color: #001F5F;
width: 9em;
margin-left: calc(50% - 4.6em);
margin-right: calc(50% - 4.5em);
text-align: center;
}
#inputfield {
overflow: hidden;
padding-top: 5px;
padding-bottom: 5px;
margin-top: 50px;
margin-bottom: 10px;
}
::placeholder {
color: #E7E6E6;
opacity: 0.8;
}
#name {
height: 35px;
width: 813px;
outline: none;
background-color: #001F5F;
color: #E7E6E6;
text-align: left;
vertical-align: middle;
font-size: 22px;
box-shadow: 1px 2px 4px 2px darkgray;
margin-right: 10px;
border: 5px;
border-color: #E7E6E6;
float: left;
border-radius: 5px 5px 5px 5px;
}
#add {
height: 35px;
width: 35px;
background-color: #E7E6E6;
color: #001F5F;
font-size: 32px;
font-style: bold;
text-align: center;
vertical-align: middle;
line-height: 35px;
cursor: pointer;
box-shadow: 1px 2px 4px 2px darkgray;
float: left;
border-radius: 5px 5px 5px 5px;
}
#add:hover {
background-color:#001F5F;
color: #E7E6E6;
}
#background {
box-shadow: 0px 2px 4px 2px darkgray;
width: 900px;
height: 0px;
background-color: #E7E6E6;
padding-top: 20px;
border-radius: 5px 5px 5px 5px;
}
.start, .end {
text-align: center;
margin-top: 250px;
font-size: 32px;
padding: 0px;
vertical-align: middle;
}
#spacer {
width: 10px;
height: 35px;
background-color:#E7E6E6;
}
.input {
height: 35px;
width: 808px;
background-color:#001F5F;
padding-left: 5px;
border: 0px;
font-size: 22px;
color: #E7E6E6;
text-align: left;
vertical-align: middle;
outline: none;
box-shadow: 0px 2px 4px 2px darkgray;
border-radius: 5px 5px 5px 5px;
}
.bin {
width: 35px;
height: 35px;
font-size: 24px;
font-style: normal;
background-color: #E7E6E6;
color:#001F5F;
text-align: center;
vertical-align: middle;
line-height: 35px;
cursor: pointer;
border-radius: 5px 5px 5px 5px;
}
.bin:hover {
background-color:#001F5F;
color: #E7E6E6;
box-shadow: 0px 2px 4px 2px darkgray;
}
.item {
margin-left: 32px;
display: table;
table-layout: fixed;
width: 858px;
margin-bottom: 20px;
}
.column {
display: table-cell;
}
.thelist {
margin-left: calc(50% - 450px);
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Oliver's To-Do List</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<h1 id="title">Oliver's To-Do List</h1>
<body>
<div class="thelist">
<div id="inputfield">
<input type="text" placeholder="Start typing here..."id="name">
<div id="add">+</div>
</div>
<div id="background">
</div>
</div>
<script src="main.js"></script>
</body>
</html>
Thanks!
getAdd.addEventListener("click", addevent(), false);
should be
getAdd.addEventListener("click", addevent, false);
As per this example from https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener :
// Function to change the content of t2
function modifyText() {
const t2 = document.getElementById("t2");
if (t2.firstChild.nodeValue == "three") {
t2.firstChild.nodeValue = "two";
} else {
t2.firstChild.nodeValue = "three";
}
}
// Add event listener to table
const el = document.getElementById("outside");
el.addEventListener("click", modifyText, false);
Ok so I found out that within the getAdd event listener, the problem was the pair of brackets after the function name; once these are removed, it works just fine!
If anyone reading wants to add to this with their wisdom, knowledge and experience, or perhaps suggest any other improvements, please do!
Thanks!
Oh, you solved it. I just tried it out and modified something in the index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Oliver's To-Do List</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<h1 id="title">Oliver's To-Do List</h1>
<body>
<div class="thelist">
<div id="inputfield">
<input type="text" placeholder="Start typing here..."id="name">
<div id="add" onclick="addevent()">+</div>
</div>
<div id="background">
</div>
</div>
<script src="main.js"></script>
</body>
</html>
I added onclick="addevent()" , and It works

Move the menu to the right of the page

This code is in the default setting, the list opens to the right, but I want to open this list to the left and move the menu to the right of the page.
When you click on the word file, the menu list gets collated and when you click on the new word, a new list opens. I want to open this new list to the left.
what's the solution?
The Code:
var MainMenu = function () {
var activated = false;
var settings = {
disabledClass: 'disabled',
submenuClass: 'submenu'
}
var mask = '<div id="menu-top-mask" style="height: 2px; background-color: #fff; z-index:1001;"/>';
var timeOut;
this.init = function (p) {
$.extend(settings, p);
$mask = $('#menu-top-mask');
$('ul.main-menu > li').click(function (event) {
var target = $(event.target);
if (target.hasClass(settings.disabledClass) || target.parents().hasClass(settings.disabledClass) || target.hasClass(settings.submenuClass)) {
return;
}
toggleMenuItem($(this));
});
$('ul.main-menu > li > ul li').click(function (event) {
// Prevent click event to propagate to parent elements
event.stopPropagation();
// Prevent any operations if item is disabled
if ($(this).hasClass(settings.disabledClass)) {
return;
}
// If item is active, check if there are submenus (ul elements inside current li)
if ($(this).has( "ul" ).length > 0) {
// Automatically toggle submenu, if any
toggleSubMenu($(this));
}
else{
// If there are no submenus, close main menu.
closeMainMenu();
}
});
$('ul.main-menu > li').mouseenter(function () {
if (activated && $(this).hasClass('active-menu') == false) {
toggleMenuItem($(this));
}
});
$('ul.main-menu > li > ul li').mouseenter(function (e) {
// Hide all other opened submenus in same level of this item
$el = $(e.target);
if ($el.hasClass('separator')) return;
clearTimeout(timeOut);
var parent = $el.closest('ul');
parent.find('ul.active-sub-menu').each(function () {
if ($(this) != $el)
$(this).removeClass('active-sub-menu').hide();
});
// Show submenu of selected item
if ($el.children().size() > 0) {
timeOut = setTimeout(function () { toggleSubMenu($el) }, 500);
}
});
$('ul.main-menu > li > ul li').each(function () {
if ($(this).children('ul').size() > 0) {
$(this).addClass(settings.submenuClass);
}
});
$('ul.main-menu li.' + settings.disabledClass).bind('click', function (e) {
e.preventDefault();
});
//#region - Toggle Main Menu Item -
toggleMenuItem = function (el) {
// Hide all open submenus
$('.active-sub-menu').removeClass('active-sub-menu').hide();
$('#menu-top-mask').remove();
var submenu = el.find("ul:first");
var top = parseInt(el.css('padding-bottom').replace("px", ""), 10) + parseInt(el.css('padding-top').replace("px", ""), 10) +
el.position().top +
el.height();
submenu.prepend($(mask));
var $mask = $('#menu-top-mask');
var maskWidth = el.width() +
parseInt(el.css('padding-left').replace("px", ""), 10) +
parseInt(el.css('padding-right').replace("px", ""), 10);
$mask.css({ position: 'absolute',
top: '-1px',
width: (maskWidth) + 'px'
});
submenu.css({
position: 'absolute',
top: top + 'px',
left: el.offset().left + 'px',
zIndex: 100
});
submenu.stop().toggle();
activated = submenu.is(":hidden") == false;
!activated ? el.removeClass('active-menu') : el.addClass('active-menu');
if (activated) {
$('.active-menu').each(function () {
if ($(this).offset().left != el.offset().left) {
$(this).removeClass('active-menu');
$(this).find("ul:first").hide();
}
});
}
}
//#endregion
//#region - Toggle Sub Menu Item -
toggleSubMenu = function (el) {
if (el.hasClass(settings.disabledClass)) {
return;
}
var submenu = el.find("ul:first");
var paddingLeft = parseInt(el.css('padding-right').replace('px', ''), 10);
var borderTop = parseInt(el.css('border-top-width').replace("px", ""), 10);
borderTop = !isNaN(borderTop) ? borderTop : 1;
var top = el.position().top - borderTop;
submenu.css({
position: 'absolute',
top: top + 'px',
left: el.width() + paddingLeft + 'px',
zIndex: 1000
});
submenu.addClass('active-sub-menu');
submenu.show();
//el.mouseleave(function () {
// submenu.hide();
//});
}
//#endregion
closeMainMenu = function () {
activated = false;
$('.active-menu').find("ul:first").hide();
$('.active-menu').removeClass('active-menu');
$('.active-sub-menu').hide();
};
$(document).keyup(function (e) {
if (e.keyCode == 27) {
closeMainMenu();
}
});
$(document).bind('click', function (event) {
var target = $(event.target);
if (!target.hasClass('active-menu') && !target.parents().hasClass('active-menu')) {
closeMainMenu();
}
});
}
}
$(document).ready(function () {
new MainMenu().init();
});
#menu-bar
{
}
ul.main-menu
{
list-style-type: none;
margin: 0px 0px 10px 0px;
padding: 0px;
}
ul.main-menu > li
{
margin: 0;
display: inline;
list-style-type: none;
padding: 6px 4px 6px 6px;
line-height: 28px;
vertical-align: middle;
cursor: default;
outline: none;
border-style: solid;
border-width: 1px 1px 0 1px;
border-color: transparent;
}
ul.main-menu > li.active-menu
{
background-color: #fff;
border-color: #ccc;
-webkit-box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2);
-moz-box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2);
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2);
}
ul.main-menu ul li a
{
color: #000;
text-decoration: none;
display: block;
white-space: nowrap;
}
ul.main-menu li ul li a span
{
font-size: 11px;
color: #999;
float:right;
right: 10px;
left: auto;
position: absolute;
}
/* SUBMENU */
ul.main-menu > li ul
{
list-style-type: none;
padding: 0;
margin: 0;
display: none;
border-width:1px;
border-style: solid;
border-color: #ccc;
background-color: #fff;
-webkit-box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2);
-moz-box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2);
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2);
}
ul.main-menu li ul li
{
display:list-item;
margin: 0;
line-height: 26px;
padding-right: 40px;
min-width: 100px;
cursor: pointer;
text-indent: 30px;
white-space:nowrap;
}
ul.main-menu a:hover{
background-color: #ff4718;
color: #FFFFFF;
}
ul.main-menu li:hover
{
background-color: #ff4718;
color: #FFFFFF;
}
ul.main-menu li.active-menu:hover
{
background-color: #ff4718;
color: #FFFFFF;
}
ul.main-menu li ul li.disabled, ul.main-menu li ul li.disabled:hover, ul.main-menu li ul li.disabled:hover a
{
cursor:default;
background-color: #ff4718;
color: #FFFFFF;
}
ul.main-menu li.separator
{
border-top: 1px solid #ddd;
margin-top: 5px;
margin-bottom: 5px;
}
.submenu
{
background-image: url(../images/menu-right-arrow.png);
background-repeat: no-repeat;
background-position: right center;
}
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<div id="menu-bar">
<ul class="main-menu">
<li>
File
<ul>
<li>
<li>New
<ul>
<li>Data</li>
<li>Storage</li>
<li>Network</li>
</ul>
</li>
</li>
<ul>
<li>Google search (opens in new tab)</li>
<li>Product</li>
<li>Document</li>
<li>Client</li>
</ul>
</li>
<!--<li class="separator"></li>-->
<li>Save<span>Ctrl+S</span></li>
<li>Import</li>
<li>Export</li>
<li>Print<span>Ctrl+P</span></li>
<li>Logout</li>
</ul>
</li>
</ul>
<!-- end mainmenu -->
</div>
If you update this css:
#menu-bar {
justify-content: flex-end;
display: flex;
}
and update this JS:
submenu.css({
position: 'absolute',
top: top + 'px',
left: 'auto',
right: '0'
zIndex: 100
});
I believe it should do the trick.
Edit: I added right: '0'.
ul {
position: fixed; right: 0; top:0;
}

delay in update of a javascript, when returning out of a function

I'm new to javascript so be gentle ;)
I wrote a script which (on a webpage) gets a song artist/title and find the albumart on last.fm ..
I use a return to exit (and restart) when the existing track name is the same as there is no need t go through the whole script when it is. I noticed however that often it appears that the script still seems to run through a number of these cycles before picking up on a new entry in the textfile it reads for the names of artist and title. Is there any way to prevent this or can I use a better way to exit or restart the function?
Not sure if I explained this correctly, but I hope you get it.. thanks
var jsnURL = "http://ws.audioscrobbler.com/2.0/?autocorrect=1&method=track.getinfo&api_key=[mykeyisprivate]&format=json&";
var playURL = "./data/nowplaying.txt";
var noImg = "./data/speaker.png";
var albumImage = noImg;
var oldtitle = "none";
var image;
var doMe = function(){
$(document).ready(function(){
$.get(playURL, function(sngPlaying){
/* console.log(sngPlaying); */
var artist = sngPlaying.split(" - ")[0];
var title = sngPlaying.split(" - ")[1];
if ((artist === "not running") || (title === oldtitle)) {
return;
};
oldtitle = title;
/*
console.log("Artist: "+artist);
console.log("Title: "+title);
*/
$.getJSON(jsnURL+"artist="+artist.replace("&","%26")+"&track="+title, function(data){
try{
albumImage = data.track.album.image[2]['#text'];
if (albumImage) {
/* console.log("Found Album Art: "+albumImage); */
}
else {
/* console.log("Did not Find Album Art, using generic image"); */
albumImage = noImg;
};
}
catch(err) {
/* console.log("Something went wrong, using generic image"); */
albumImage = noImg;
}
$("#albumArt").html('<img class="albumArt" src='+albumImage+'>');
$("#trackArtist").html('<span>'+artist+'</span>');
$("#trackTitle").html('<span>'+title+'</span>');
});
});
});
};
setInterval(doMe, 2000);
#import url(https://fonts.googleapis.com/css?family=PT+Sans+Caption:400,700);
#nwPlayContainer {
width: 450;
height: 50;
position: absolute;
top: 0;
left: 0;
overflow: hidden;
/*background-color: black;
*/font-family: 'PT Sans Caption';
}
#albumArt {
width: 46px;
height: 46px;
padding-left: 2px;
padding-top: 2px;
border-radius: 50%;
}
.albumArt {
border-radius: 50%;
width:46px;
height:46px;
}
#trackArtist {
width: 398px;
height: 20px;
position: absolute;
text-align: left;
top: 7px;
left: 55px;
color: white;
font-size: 12px;
text-shadow:
-1px -1px 0 #000,
1px -1px 0 #000,
-1px 1px 0 #000,
1px 1px 0 #000;
}
#trackTitle {
width: 398px;
height: 20px;
position: absolute;
text-align: left;
top: 25px;
left: 55px;
color: white;
font-size: 12px;
text-shadow:
-1px -1px 0 #000,
1px -1px 0 #000,
-1px 1px 0 #000,
1px 1px 0 #000;
}
<div id=nwPlayContainer>
<div id="albumArt"></div>
<div id="trackArtist"></div>
<div id="trackTitle"></div>
</div>

Categories

Resources