Register a click except on a certain element - javascript

I have a javasccript function that shows or hides "spans" when I click an input to show hints when a user fills out forms:
function prepareInputsForHints() {
var inputs = document.getElementsByTagName("input");
for (var i=0; i<inputs.length; i++){
// test to see if the hint span exists first
if (inputs[i].parentNode.getElementsByTagName("span")[0]) {
// the span exists! on focus, show the hint
inputs[i].onfocus = function () {
this.parentNode.getElementsByTagName("span")[0].style.display = "inline";
}
// when the cursor moves away from the field, hide the hint
inputs[i].onblur = function () {
this.parentNode.getElementsByTagName("span")[0].style.display = "none";
}
}
}
}
My problem is that when I try to add a link to the hints text, the user cannot click it because it registers first with the onblur event and the hint dissapears, so I would like to know how to modify this function so that it does not hide when I click the hint.

You can use a boolean var to test if the user is with mouse over your hint, then if onblur and not mouseOver you hide your hint.
Something like this inside your loop:
var inputs = document.getElementsByTagName("input");
for (var i=0; i<inputs.length; i++){
(function(i) {
// Let the code cleaner :)
var span = inputs[i].nextElementSibling;
span.onmouseover = function() { this.isOver = true; }
span.onmouseout = function() { this.isOver = false; if(!inputs[i].isFocus) inputs[i].onblur(); }
// the span exists! on focus, show the hint
inputs[i].onfocus = function () {
this.isFocus = true;
span.style.display = "inline";
}
// when the cursor moves away from the field, hide the hint
inputs[i].onblur = function () {
this.isFocus = false;
if(!span.isOver) span.style.display = "none";
}
})(i);
}
I put a self executing function just to keep the var i scope, you don't have troubles onmouseout function.
EDIT: Updated the example
Your code for get the next span will not work, so I changed to nextElementSibling, because the example you put in the jsfiddler.

This is the new working code:
$(function(prepareInputsForHints) {
var inputs = document.getElementsByTagName("input");
for (var i=0; i<inputs.length; i++){
(function(i) {
// Let the code cleane
var span = inputs[i].nextElementSibling;
if(span instanceof HTMLSpanElement) {
if(span.className == "hint") {
span.onmouseover = function() { this.isOver = true; }
span.onmouseout = function() { this.isOver = false; if(!inputs[i].isFocus) inputs[i].onblur(); }
// the span exists! on focus, show the hint
inputs[i].onfocus = function () {
this.isFocus = true;
span.style.display = "inline";
}
// when the cursor moves away from the field, hide the hint
inputs[i].onblur = function () {
this.isFocus = false;
if(!span.isOver) span.style.display = "none";
}
}
}
})(i);
}
});

Related

How to tell Javascript what tab is active

Javascript
function openPage(pageName, elmnt) {
// Hide all elements with class="tabcontent" by default */
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
// Show the specific tab content
document.getElementById(pageName).style.display = "block";
}
document
list = document.querySelectorAll(".myTextInputID")
list[1].addEventListener("keyup", function (event) {
if (event.keyCode === 13) {
event.preventDefault();
var input = document.getElementsByClassName("myTextInputID")[0]
.value;
if (input.includes("https://www.amazon.co.uk/")) {
document.getElementsByClassName("containFORM")[0]
.insertAdjacentElement("beforeend", itemcont);
document.getElementById("prodcont")
.insertAdjacentElement("afterbegin", imgcont);
document.getElementsByClassName("containFORM")[0]
.style.backgroundColor = "white"
} else {
var URLerror = document.createElement("p");
URLerror.classList.add("error");
var urlerror = document.createTextNode("This is not an amazon url, please input an amazon url and press enter again.");
URLerror.appendChild(urlerror);
var cont = document.getElementsByClassName("myForm")[0];
cont.insertAdjacentElement("afterend", URLerror);
setTimeout(function() {
URLerror.remove();
}, 2000);
}
}
});
function newTab() {
var allTabs = document.getElementById("navigation2");
var tabList = document.createElement("li");
var error = document.createElement("p");
var eNode = document.createTextNode("You cant track this many products");
var button1 = document.getElementById("button1");
var tabButton = document.createElement("button");
tabButton.setAttribute("onclick", "openPage('1', this, 'red')")
error.classList.add("error");
tabList.classList.add("tabli");
tabButton.classList.add("tabs");
if (button1.offsetWidth < 190) {
error.appendChild(eNode);
document.getElementById("tabcon")
.insertAdjacentElement("afterend", error);
setTimeout(function() {
error.remove();
}, 2000);
} else {
tabList.appendChild(tabButton);
allTabs.insertAdjacentElement("beforebegin", tabList);
var newt = ("window.location.href=")+("\'")+("#")+("newtab")+("\'");
var newtab = document.createElement("div")
newtab.id="#newtab";
newtab.className="containFORM";
// true means clone all childNodes and all event handlers
document.getElementById("0").insertAdjacentElement("afterend", clone)
clone.id = "1";
}
}
When you press the new tab button it makes a new tab and creates a clone of a stored element, however with the class selector I can only put a number (0,1) but I need it so its some sort of variable(x), x being the number of the current tab. So when you click on one tab set x to that and then all logic will be performed on each tab, I can't think of a way to do this without copying what I've done multiple times and just changing the number myself, which doesn't feel very efficient.
I have found this piece of code in JQuery that might help you.
var activeTab = $(".tab-content").find(".active");
console.log(activeTab.context.URL);
If you try it while inspect this very page, you can check that the result is the URL of this page:
https://stackoverflow.com/questions/65886250/how-to-tell-javascript-what-tab-is-active

I have many input tags, and each input tag is having a ul from where a list element can be selected to insert value in to the input field

But the problem is when i have added onclick events to each input tag that close the ul on blur and open the ul on focus by using display none and block respectively. As i am blurring each time on input blur the event listener for ul is not working. here is the code.
var selectTime= document.querySelectorAll("input");
for( var i=0; i<selectTime.length; i++) {
selectTime[i].onfocus = function(event) {
var el = event.currentTarget;
el.nextElementSibling.style.display = "block";//ul is show
}
}
for( var i=0; i<selectTime.length; i++) {
selectTime[i].onblur = function(event) {
var el = event.currentTarget;
el.nextElementSibling.style.display = "none";//ul is none
}
}
for(i=0;i<ulElements.length;i++){
ulElements[i].onclick= function(event){
if (event.target.tagName === 'LI'){
console.log(event.target);
}
}
}
But the element selected from ul li is not displaying in console
here is an demo https://jsfiddle.net/fzbx36zf/
As click-event is invoked anywhere outside input element, onblur handler is invoked hence onclick on ul element is not being executed.
setTimeout inside onblur handler would help!
var ulClicked = false;
document.querySelector('input').onfocus = function() {
document.querySelector('ul').style.display = "block";
}
document.querySelector('input').onblur = function(e) {
setTimeout(function() {
if (!ulClicked) {
document.querySelector('ul').style.display = "none";
} else {
alert('UL clicked');
}
ulClicked = false;
}, 100);
}
document.querySelector('ul').onclick = function(event) {
ulClicked = true;
document.querySelector('input').value = event.currentTarget.textContent.trim();
}
<input/>
<ul style="display:none">
<li>tiger</li>
</ul>

can't uncheck the check box (hide content while checkbox is unchecked)

I'd like to hide div content while checkbox is unchecked.
Here's my code
I've made almost the same function for the div with id "focus" (big grey frame):
document.getElementById("checkFocus").onchange = function() {
var one = document.getElementById("focus");
if (document.getElementById("checkFocus").checked === true) {
one.style.display = "block";
}
else one.style.display = "none";
}
And it works!
So, I don't understand why the next function doesn't works at all:
document.getElementById("checkMass").onchange = function() {
var elem = document.querySelector("PeriodicTable")
var mass = elem.querySelectorAll("div.element > div.mass");
if (document.getElementById("checkMass").checked === true) {
mass.style.display = "block";
}
else mass.style.display = "none";
}
What am I doing wrong?
elem.querySelectorAll("div.element > div.mass"); doesn't return a single element, it returns a collection of all matches.
That said you can't do mass.style.display on a array, only on a single element so you need to do
if (document.getElementById("checkMass").checked === true) {
for (var i = 0; i < mass.length; i++) {
mass[i].style.display = "block";
}
else {
for (var i = 0; i < mass.length; i++) {
mass[i].style.display = "none";
}
}
instead.
The querySelector("Any CSS rule") needs a rule, . signify class, # signify id, but you have querySelector("PeriodicTable"). Therefor you are looking for elements with tagname of PeriodicTable. Either use document.getElementById('PeriodicTable') or querySelector("#PeriodicTable")
https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector

How can setTimeout save and load data back to form inputs if browser crashes, and I visit that same page again?

How can setTimeout save and load data for select form inputs? I tried to get it working with event listeners. I checked the capture and bubble which I am still trying to wrap my head around.
I need it to set or get values assigned it to respective elements from the input field depending if there is changes such as focus or blur on the fields.
Is there a feature or step I missed and where should I start looking?
answers = document.getElementsByName('answers[]');
for(var i = 0; i < answers.length; i++) {
nodeIndex = 'answer' + i;
if(answers[i] == ''){
answers[i].addEventListener('blur', function(){
localStorage.setItem(nodeIndex, answers[i].value);
});
}
else {
answers[i].addEventListener('focus', function(){
answers[i].value = localStorage.getItem(nodeIndex);
localStorage.setItem(nodeIndex, answers[i].value);
});
answers[i].addEventListener('blur', function(){
localStorage.setItem(nodeIndex, answers[i].value);
answers[i].value = localStorage.getItem(nodeIndex);
});
} // end if
} // end forloop
REVISED
I noticed only the last element is affected. When I enter text in answers[0] to answers[14], their values are saved and set/copied to only the last element. How am I using this incorrectly? I read up and seem to follow the rules...
function processAnswers(i, answers) {
setTimeout(function() {
nodeIndex = 'answer' + i;
if(localStorage.getItem(nodeIndex) === null) {
answers[i].addEventListener('blur', function(){
localStorage.setItem(nodeIndex, answers[i].value);
});
} // end if
else {
answers[i].addEventListener('focus', function(){
answers[i].value = localStorage.getItem(nodeIndex);
localStorage.setItem(nodeIndex, answers[i].value);
});
answers[i].addEventListener('blur', function(){
localStorage.setItem(nodeIndex, answers[i].value);
answers[i].value = localStorage.getItem(nodeIndex);
});
} // end else
}, 100); // end setTimeout()
} // end processAnswers();
answers = document.getElementsByName('answers[]');
for(var i = 0; i < answers.length; i++) {
processAnswers(i, answers);
}
My code was getting out of hand. I decided to start over and keep it simple... and it worked!
var answers;
var clearAnswersBtn;
var clearAnswers;
var MainLoop = function MainLoopFunction(){
answers = document.getElementsByName('answers[]');
clearAnswersBtn = document.getElementsByTagName('body')[0];
clearAnswersBtn.innerHTML = clearAnswersBtn.innerHTML + '<button id="clearanswers" style="position:fixed;bottom:0;right:0;padding:5px;margin:0 10px 10px 0;z-index:99999">Clear Saved Answers</button>';
clearAnswers = document.getElementById('clearanswers');
clearAnswers.addEventListener("click", function(){
localStorage.clear();
alert("Answers Cleared!");
});
function saveAnswers(i, answer){
if(localStorage.getItem(i)) {
answer.value = localStorage.getItem(i);
}
else {
answer.addEventListener("blur", function(){
if(!localStorage.getItem(i)) {
localStorage.setItem(i, answer.value);
}
});
}
} // end saveAnswers()
setTimeout(function(){
for( var i = 0; i < answers.length; i++) {
saveAnswers(i, answers[i]);
}
}, 0)
}();

How to disable the hyperlinks in a div

How can I disable all hyperlinks in a div element? I don't want any active links in my div(editable).
jQuery:
$("#myEditableDiv a").click(function(e){ e.preventDefault(); });
Old and considered bad.
$("#myEditableDiv a").click(function(){ return false; });
using javascript you can write a simple method as given below -
function disableLinksByElement(el) {
if (document.getElementById && document.getElementsByTagName) {
if (typeof(el) == 'string') {
el = document.getElementById(el);
}
var anchors = el.getElementsByTagName('a');
for (var i=0, end=anchors.length; i<end; i++) {
anchors[i].onclick = function() {
return false;
};
}
}
}
//Call to function as
disableLinksByElement('mydiv');
First grab all the links.
var links = editable.getElementsByTagName('a'); // where "editable" is a var pointing to your div
Then set the onclick to false.
for (var i = 0; i < links.length; i++) {
var link = links[i];
link.onclick = function() { return false; };
}

Categories