Disabling browser tooltips on links and <abbr>s - javascript

I want to suppress the web browser's default tooltip display when a user hovers over certain links and elements. I know it's possible but I don't know how. Can anyone help?
The reason for this is to suppress the tooltip for microformatted date-times. The BBC dropped support for hCalendar because the appearane of the machine-readable date was an accessibility issue for those with cognitive disabilities aswell as some screen reader users. http://www.bbc.co.uk/blogs/bbcinternet/2008/07/why_the_bbc_removed_microforma.html
EDIT:
I whipped up a jquery plugin along the same lines as Aron's suggestion...
// uFsuppress plugin v1.0 - toggle microformatted dates
(function($){
$.ufsuppress = function() {
$(".dtstart,.dtend,.bday").hover(function(){
$(this).attr("ufdata",$(this).attr("title"));
$(this).removeAttr("title");
},function(){
$(this).attr("title",$(this).attr("ufdata"));
$(this).removeAttr("ufdata");
});
}
})(jQuery);
// Usage
$.ufsuppress();

As far as I know it is not possible to actually suppress showing the title tag.
There are some workarounds however.
Assuming you mean you want to preserve the title property on your links and elements, you could use Javascript to remove the title property at onmouseover() and set it again at onmouseout().
// Suppress tooltip display for links that have the classname 'suppress'
var links = document.getElementsByTagName('a');
for (var i = 0; i < links.length; i++) {
if (links[i].className == 'suppress') {
links[i]._title = links[i].title;
links[i].onmouseover = function() {
this.title = '';
}
links[i].onmouseout = function() {
this.title = this._title;
}
}
}

Add this element to your html
onmouseover="title='';"
For example i have a asp.net checkbox I store a hidden variable but do not want the user to see on as the tooltip.

Ran across this thread when using the jQuery plugin timeago. Actually the solution is very simple using the CSS property pointer-events. Posting this for the benefit of people coming here through a search engine :)
.suppress {
pointer-events:none;
}
Note that you shouldn't use this for things like links that should click through to something. In this case use the accepted JS solution.

Something like this in prototype would blank all title attributes of datetime microformats with a class of 'dtstart':
$$('abbr.dtstart').each(function(abbr){abbr.title=' '})
Note I used a blank space, the Mozilla documentation for element.title states
According to bug 264001 , setting
title to the empty string triggers the
default inheriting behavior. To cancel
inheritance, title must be set to a
non-empty whitespace string.

This won't help with your problem but might be interesting nevertheless: There's another universal attribute apart from title which can be used to store data - lang!
Just convert the data you want to store to a continuous string and prefix it with 'x-' to declare private usage in accordance with RFC 1766.
In the comments, sanchothefat clarified that he wants to solve the usability-issues with the abbr-design-pattern in microformats. But there are other patterns which are as semantically meaningful (or, in my opinion even more so) than this pattern. What I'd do:
<p>
The party is at
<dfn class="micro-date">10 o'clock on the 10th
<var>20051010T10:10:10-010</var></dfn>.
</p>
together wtih these styles
dfn.micro-date {
font-weight: inherit;
font-style: inherit;
}
dfn.micro-date var {
display: none;
}
In my opinion, the semantically most correct way would be to use a dl definition list - which isn't allowed inside of paragraphs. This can be worked around with the following pattern:
<p>
The party is at <q cite="#micro-dates">10 o'clock on the 10th</q>.
</p>
<dl id="micro-dates">
<dt>10 o'clock on the 10th</dt>
<dd>20051010T10:10:10-010</dd>
</dl>
which requires a more sophisticated stylesheet:
q[cite='#micro-dates']:before {
content: '';
}
q[cite='#micro-dates']:after {
content: '';
}
dl#micro-dates {
display: none;
}

This is what i did.
$('.fancybox').hover(
function(){
$(this).attr('alt',$(this).attr('title'));
$(this).attr('title','');
},
function(){
$(this).attr('title',$(this).attr('alt'));
$(this).removeAttr('alt');
}
).click(function(){
$(this).attr('title',$(this).attr('alt'));
$(this).removeAttr('alt');
});

You can hook the 'mouseenter' event and return false which will stop the native tooltips from being displayed.
$(selector).on( 'mouseenter', function(){
return false;
});

It's possible to suppress this behaviour with jQuery
var tempTitle;
$('[title]').hover(
function(e) {
debugger;
e.preventDefault();
tempTitle = $(this).attr('title');
$(this).attr('title', '');
// add attribute 'tipTitle' & populate on hover
$(this).hover(
function() {
$(this).attr('tipTitle', tempTitle);
}
);
},
// restore title on mouseout
function() {
$(this).attr('title', tempTitle);
}
);
.progress3 {
position: relative;
width: 100px;
height: 100px;
background: red;
}
.progress3:hover:after {
background: #333;
background: rgba(0, 0, 0, .8);
border-radius: 5px;
bottom: 26px;
color: #fff;
content: attr(data-tooltip);
left: 20%;
padding: 5px 15px;
position: absolute;
z-index: 98;
width: 220px;
}
.progress3:hover:before {
border: solid;
border-color: #333 transparent;
border-width: 6px 6px 0 6px;
bottom: 20px;
content: "";
left: 50%;
position: absolute;
z-index: 99;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div title='abc' data-tooltip="This is some information for our tooltip." class="progress3">
title='abc' will not be displayed
</div>
fiddle

Related

JS Hover Over One Item to Make Another Move

I've got a simple text button with an image of an arrow next to it. I'm wanting the arrow image to move when someone hovers over the button.
I currently have this working in one instance with JS 'document.getElementById...', but I have several buttons across my site that I'd like to have the same behavior. My first thought would be to use a class instead of an id, and use the same functions.
For whatever reason, document.getElementsByClassName doesn't work - even in one instance.
Here's a simpler version to demonstrate - View on Codepen: https://codepen.io/sdorr/pen/JxYNpg
HTML
<HTML>
hover over me
<div id="block"></div>
hover over me
<div class="block"></div>
CSS
* {
margin: 0;
padding: 0;
}
.button {
color: #000000;
text-decoration: none;
background-color: cyan;
margin: 0;
display: block;
width: 300px;
padding: 20px;
text-align: center;
}
#block {
width: 30px;
height: 30px;
background-color: red;
}
.block {
width: 30px;
height: 30px;
background-color: green;
}
JS
function move() {
document.getElementById("block").style.marginLeft = "35px";
}
function moveBack() {
document.getElementById("block").style.marginLeft = "0px";
}
function moveAlt() {
document.getElementsByClassName("block").style.marginLeft =
"35px";
}
function moveBackAlt() {
document.getElementsByClassName("block").style.marginLeft =
"0px";
}
First off, why isn't the behavior with a class working but an id works fine?
Secondly, would a class solve this issue and be scalable across all buttons with the same two functions (onmouseover / onmouseout)?
If not, any ideas on a solution? I currently have a solution I found using jQuery that does work, but when hovering over one button, all arrow images move across the site. I don't necessarily mind this behavior because only one button is really in view at a time - but I'm trying to learn JS and solve problems with my own solutions!
I greatly appreciate your desire to learn on your own and not rely on premade solutions. Keep that spirit and you will go places!
When it comes to getElementsById, we know this should work for one element, since the function returns a single Element.
However, what does getElementsByClassName return?
(see: https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName)
It returns an HTMLCollection which you can iterate over to change an single element's style.
So, to get this to work with JavaScript you need to write a function that will be able to identify the particular div.block you want to move. But, this puts you back to where you started, needing some particular identifier, like an id or a dataset value to pass to the function.
Alternately, based on the HTML structure you provide, you could look for nextElementSibling on the a that get's clicked. But I would set up an eventListener rather than adding a JS function as a value to the onmouseenter property.
const btns = document.getElementsByTagName('a');
/*** UPDATE forEach is a NodeList method, and will fail on HTMLCollection ***/
/* this fails -> Sorry! ~~btns.forEach(button=>{~~
/* the following will work
/**********/
for (let i = 0; i < btns.length; i++){
btns[i].addEventListener('mouseenter', function(e) {
//we pass e to the function to get the event and to be able to access this
const block = this.nextElementSibling;
block.style.marginLeft = "35px";
})
btns[i].addEventListener('mouseleave', function(e) {
const block = this.nextElementSibling;
block.style.marginLeft = "0";
})
}
But with siblings, there is a CSS-only solution.
We can use the Adjacent Sibling Selector combined with the :hover state selector and no JavaScript is needed, if we are just moving back and forth.
.button:hover+.block {
margin-left: 35px;
}
See the Snipped Below
* {
margin: 0;
padding: 0;
}
.button {
color: #000000;
text-decoration: none;
background-color: cyan;
margin: 0;
display: block;
width: 300px;
padding: 20px;
text-align: center;
}
.block {
width: 30px;
height: 30px;
background-color: green;
}
.button:hover+.block {
margin-left: 35px;
}
hover over me
<div class="block"></div>
hover over me
<div class="block"></div>
As Vecta mentioned, getElementsByClassName returns an array-like. You'll need to do something like this to get the first element:
function moveAlt() {
document.getElementsByClassName("block")[0].style.marginLeft = "35px";
}
function moveBackAlt() {
document.getElementsByClassName("block")[0].style.marginLeft = "0px";
}
However a better solution might be to use document.querySelector, which operates similarly to jQuery's $() syntax:
function moveAlt() {
document.querySelector(".block").style.marginLeft = "35px";
}
function moveBackAlt() {
document.querySelector(".block").style.marginLeft = "0px";
}

The image is not changing when it collapses back (jquery, css)

The image will change when it expands, but when it collapses back, it won't change, my code looks like below:
JS:
(function ($) {
$(document).ready(function () {
// Categories menu opening
$('.woocommerce.widget_product_categories .product-categories li.cat-parent').prepend('<div class="cat-menu-close"></div>');
$(document).on("click", ".woocommerce.widget_product_categories .product-categories li.cat-parent > .cat-menu-close", function (e) {
var $catParent = $(this).closest('li.cat-parent');
var state = $catParent.hasClass('close');
$catParent.toggleClass('opened', !state);
$(this).nextAll('ul.children:first').slideToggle(state);
});
});
})(jQuery);
CSS:
.woocommerce.widget_product_categories .product-categories li .cat-menu-close {
position: absolute;
right: 0;
line-height: 20px;
text-align: center;
cursor: pointer;
top: 4px;
width: 20px;
height: 20px;
}
.woocommerce.widget_product_categories .product-categories li > .cat-menu- close:hover {
opacity: 0.5;
}
.woocommerce.widget_product_categories .product-categories li > .cat-menu- close:after {
display: inline-block;
margin-left: 2px;
background: url("../img/arrow-right.svg") no-repeat center center;
background-size: 20px 20px;
width: 10px;
height: 20px;
content: "";
}
.woocommerce.widget_product_categories .product-categories li.opened > .cat- menu-close:after {
background: url("../img/arrow-down.svg") no-repeat center center;
background-size: 20px 20px;
}
Could someone help? I need to change the image when it expands and collapses, thank you and much appreciated.
the issue is that the category even after the SlideUp stays like this
class="cat-item cat-item-69 cat-parent opened"
instead of returning to it's original state that is
class="cat-item cat-item-69 cat-parent"
I am trying to find out the reason myself but I have too little experience with js so it's kinda hard to figure it out.
now if you remove the "!" from
$catParent.toggleClass('opened', !state);
the image will stop moving in general as it will not change the state.
edited answer bellow
Alright I have solved the riddle
After a bit of trial and error, I have your answer. In your code you have this:
var $catParent = $(this).closest('li.cat-parent');
var state = $catParent.hasClass('close');
$catParent.toggleClass('opened', !state);
this part of the code sets the starting state "close"
var state = $catParent.hasClass('close');
and when you click you get the state "opened" with the
$catParent.toggleClass('opened', !state);
This doesn't give you the option to change back to the original state onclick as the "opened" state is set to as important with the exclamation mark.
Now if you edit your code to set two variable states as opened and close. and then leave the toggleClass to change between the states you get the outcome you want. I am not sure if my explanation is correct but here is the code you need.
I have already tested it and I am using it on the webpage I am administrating if you want you can check it out
// Categories menu opening
$('.woocommerce.widget_product_categories .product-categories li.cat-parent').prepend('<div class="cat-menu-close"></div>');
$(document).on("click", ".woocommerce.widget_product_categories .product-categories li.cat-parent > .cat-menu-close", function(e) {
var $catParent = $(this).closest('li.cat-parent');
var state = 'close'
var state = 'opened'
$catParent.toggleClass(state);
$(this).nextAll('ul.children:first').slideToggle(state);
[Edit]
To anyone checking out this answer I would better recommend another plugin named 'WooCommerce Product Categories Selection' as it seems to be functioning way better.
I am using it on my websites now, the only downside is that it doesn't have icons for expand and collapse but it's really easy to add it, and if you do decide to go that way you may like find this solution helpfull

jQuery: using a div embedded in a JavaScript variable as a jQuery selector

I have a jQuery custom scrollbar, and I invoke it like this:
<script>
(function($){
$(window).on("load",function(){
$(".main_text,#C2,.png_container").mCustomScrollbar();
});
})(jQuery);
That works correctly for all of the page elements except .png_container, but unlike the other sections, that section is only used in a JavaScript variable that is used to substitute text in a placeholder ID, and I think that's where the problem is.
Here is how it's called from an "onclick" button event:
<div class="main_text">
<div id="C2">Main Text</div>
</div>
if (type == 101) {
var X = "<header>First Section</header><br>A classic example of good form/<br><br>More information<ul type=\"circle\"><li>Element Point 1<br></li><li>Element Point 1</li></ul><i><span class=\"span_01\">So much better</i></span><br><br><div class=\"png_container\"><img class=\"png_format\" src=\"images/Element 001.png\"></div>"}
document.querySelector("#C2").innerHTML = X;}
The png_container has a separate set of scroll bars, but they are not replaced by the custom scroll bars (the other page sections do get the custom scroll bars).
Here is the relevant css:
.png_container{
overflow: auto;
overflow-y: auto;
overflow-x: auto;
height: 400px;
width: 800px;
border: 2px solid;
border-color: green;
}
#C2{
color:#DBDBDB;
font-family: camphorW04-Thin,calibri,arial;
font-size: 14pt;
text-indent: 0px;
width: auto;
margin: auto;
margin-left: 20px;
margin-right: 250px;
}
So my question is: how can I replace the scroll bars on a section that is embedded in a JavaScript variable, as shown above?
My research has found some similar questions, but none that answer this specific question, so I hope somebody knows the answer. Thanks very much for any ideas.
You initialize the mCustomScrollbar plugin on load this way:
$(window).on("load",function(){
$(".main_text,#C2,.png_container").mCustomScrollbar();
});
The two first selectors have matching elements at this moment. But there is no existing element to match the last selector since .png_container is appended on click.
So you can safely remove .png_container from the load handler...
And initialise mCustomScrollbar on .png_container when it exists.
$(window).on("load",function(){
$(".main_text,#C2").mCustomScrollbar(); // Remove .png_container
});
$(".something").on("click",function(){
if (type == 101) {
var X = "<header>First Section</header><br>A classic example of good form/<br><br>More information<ul type=\"circle\"><li>Element Point 1<br></li><li>Element Point 1</li></ul><i><span class=\"span_01\">So much better</i></span><br><br><div class=\"png_container\"><img class=\"png_format\" src=\"images/Element 001.png\"></div>"}
document.querySelector("#C2").innerHTML = X;
$(".png_container").mCustomScrollbar(); // Add this.
}

show/hide div on click with JS and introduction

I'm fairly new to the front-end web developing sphere and I have only studied HTML/CSS for ~ a month and a half and just about 1 week or less into JS. Since I want to practice what I learn from different websites I make my own to test my knowledge. I want to apologize in advance if I am asking too many questions, but there aren't any people I know that I can share coding issues with.
So I wanted to make ( just for testing ) a show/hide div which is activated when you click a button with JS. I can make it show, but I wanted to try to make it hide/show with an "if/else" function. I thought my code was right but it doesn't seem to work and I can't find a solution. I'll share with you my code ( the part of it which I have problems with actually) and will be very grateful if you can help me find a solution.
HTML :
<button type="button" onclick="slide()" >Click Me</button>
<div class="divtest" id="dropdown">
<span>If you are seeing this, then your JS worked! </span>
</div>
The CSS ( some things are pointless, I just added them in to test a bit ):
.divtest {
position: absolute;
left: 25%;
bottom: 30px;
width: 50%;
height: 100px;
border: 2px solid black;
box-sizing: border-box;
box-shadow: 5px 5px 10px 3px;
text-align: center;
padding: 40px;
margin: 0 auto;
font-family: Cooper, sans-serif;
font-weight: 100;
transition: 1s ease;
background-color: limegreen;
color: black;
display: none;
}
button {
position: absolute;
width: 50%;
left: 25%;
bottom: 130px;
padding: 10px;
border: 2px solid black;
background-color: limegreen;
box-shadow: 5px 5px 50px 3px;
color: black;
cursor: pointer;
font-family: Cooper, sans-serif;
font-weight: 100;
}
the JS:
<script>
function slide() {
var drop = document.getElementById("dropdown"); // declares the element with id="dropdown" as a var
var dropSetting = drop.style.display; // declares that the variable "drop"'s display property is also a variable
if (dropSetting == "none") { // if the current value of display = "none" ( which it is as u can see in the CSS)
dropSetting == "block"; // Then set it to "block"
}
else { // if the value of display != none
dropSetting == "none"; // then set it to "none"
}
}
</script>
If you have any questions towards the code or anything, please feel free to ask as this is a separate feature contained in my test website so it is not connected in any way to other elements/attributes. I tried this code first in another way (without declaring dropSetting as a var, just adding in a few lines in the if/else function ) but it still did not work.I don't think JS recognizes the "style.display" as a property because Brackets doesn't highlight it. Thank you very much for your time in advance, and I hope that soon I too will be able to help some people out with what I know!
Also - a side question - What are your thoughts on treehouse? I have heard very good things about them and I'm thinking about signing up to further my knowledge.
Have a nice day!
For code compatibility, try to use methods, no shortcuts, for attributes use:
var drop = document.getElementById("dropdown");
drop.setAttribute('style', 'display: block');
var display = drop.getAttribute('display'); //Here is all the inline css, better do like below:
And it is much better for a clean and faster code, make all css clases you need:
.hide{
display:none;
}
JS:
drop.classList.add('hide');
drop.classList.remove('hide');
drop.classList.toggle('hide');
Never used Treehouse, but for myself the best teacher is a good IDE for web like Atom of VScode, google Chrome console (F12), and those are your books:
-http://www.w3schools.com/js/js_examples.asp
-https://developer.mozilla.org/en-US/docs/Web/API/Element
And this is your teacher for questions:
stackoverflow.com
You dont need anything more.
PD: Your logic is ok, just don't get used to code shortcuts, they may not work in all environments. (like elem.attribute instead of elem.getAttribute(''))
Your code doesn't works because you didn't assign display property to appropriate value (block / none). you have used comparison operator("==") instead of equals ("=").
if (dropSetting == "none") { // if the current value of display = "none" ( which it is as u can see in the CSS)
dropSetting = "block"; // Then set it to "block"
}
else { // if the value of display != none
dropSetting = "none"; // then set it to "none"
}
"==" operator in your code will just return true/false without changing display property of the div.
The problem is that your dropSetting is not an object, just string. When you change it (if change) you don't change the object (style in this case). Try something like this:
var drop = document.getElementById("dropdown"); //get reference to the object
drop.style.display = drop.style.display == 'none' ? 'block' : 'none'; //if(...){do something}else{do something else}
Another possibility:
var dropStyle = document.getElementById("dropdown").style;
if(dropStyle.display == 'none'){
dropStyle.display = 'block';
}else
dropStyle.display = 'none';

Highlight lines of text on mouseover [duplicate]

This question already has answers here:
How can I highlight the line of text that is closest to the mouse?
(3 answers)
Closed 8 years ago.
I'm currently working on a website which will feature a bunch of stories for people to read (basically a blog). I want to make them as easy to read as possible and I figured it would be useful to 'highlight' lines of text with the cursor. Kinda like following the lines of text with your finger when reading a book.
I stumbled upon this answer, however I can't seem to get it to work for my page. It's also a pretty old answer so maybe there's an improved version of this?
If anyone could help me out I'd be forever grateful!
Wrote some jQuery code that, atleast to me, both looks and works better than the code in the post that you are referring to. Hope it fits your needs :)
There's also a live demo up at http://jsfiddle.net/gFTrS/2/
HTML
<div class="textWrapper">
<div class="highlight"></div>
<p>Your text goes here</p>
</div>
CSS
.textWrapper
{
position: relative;
width: 600px;
padding: 0px 10px;
margin: 0 auto;
cursor: default;
}
.textWrapper p
{
font: normal 12px Arial;
color: #000000;
line-height: 18px;
padding: 0;
margin: 0;
}
.highlight
{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 18px;
background: yellow;
z-index: -1;
display: none;
}
jQuery
$(document).ready(function()
{
var lineHeight = 18;
$('.textWrapper').hover(function()
{
$('.highlight', this).show();
$(this).mousemove(function(e)
{
var relativePos = e.pageY - this.offsetTop;
var textRow = (Math.ceil(relativePos / lineHeight) * lineHeight) - lineHeight;
if (textRow => 0)
{
$('.highlight', this).css('top', textRow + 'px');
}
});
}, function()
{
$('.highlight', this).hide();
});
});
Most of the answers and suggestions in the older post on SO you reffered to try to manipulate the DOM by adding spans or divs for each line. But that's actually not a waterproof approach since it is not cross- browser compatble, especially not with mobile browsers. You should use a dynamically jquery controlled div that jumps behind the lines. The div should be dynamically be positioned with a jquery function triggered on mousemove calculating the div jumping on line-height depending on mouse cursor position

Categories