I am unable to see the contents of the image tool tip when focussed on it using keyboard. Below is a code example:
<img id= "id1" title ="title1" tabindex ="0" src="/images/home.gif" alt="title1" />
I am able to see the tool tip contents when hovered using mouse.
Short Answer
Don't use the title attribute, it doesn't serve any purpose that wouldn't be better suited as a caption under an image or a <label> on an <input> (please don't use a title on an input....even for a search box, even 'placeholder' text is preferable as at least some screen readers will read that and your touch screen users will still be able to read what the input is for).
Medium Answer
The title attribute has low support, offers very little to people in the modern age of touch screens (it is only sighted mouse users who don't use magnifiers or other assistive tech who gain anything from a title attribute) and in general is not a good idea for most use cases.
As a general rule if you do want to use it (so mouse users can see what an image is about) then make sure it is the same as the alt attribute so that you are providing the same information / experience to screen reader users as non screen reader users.
Long Answer
We played with this for a while, there are some circumstances where the title attribute (or at least the effect of revealing extra information about an image) can be useful. In the end we 'rolled our own' version of the title attribute that allowed us to have additional information about a picture, without interrupting the flow of a document with a caption.
In the example below (a stripped back version of what we use) we have:-
Made it accessible via keyboard and on hover.
Provided useful information to those who need it, that has the added benefit of being accessible (as title tooltips don't follow minimum sizing guidelines in some browsers and don't scale even if you change the font size settings in your browser).
Made it work on touch devices.
Designed to function like a plugin, in that you produce standard markup and a little bit of JavaScript and CSS magic does the rest.
It still isn't as good as simply providing a caption under the image but I believe it captures the spirit of what the 'title' attribute on an image is designed for, while accounting for accessibility and technology changes from when it was introduced.
Please Note - the first 80 or so lines of JavaScript are just a small helper library that allows jQuery style syntax, the relevant part starts at $("img").each(function(){.
//tiny replacement for jQuery - adapted version of ki.js
!function (b, c, d, e, f) {
f = b['add' + e]
function i(a, d, i) {
for(d = (a && a.nodeType ? [a] : '' + a === a ? b.querySelectorAll(a) : c), i = d.length; i--; c.unshift.call(this, d[i]));
}
$ = function (a) {
return /^f/.test(typeof a) ? /in/.test(b.readyState) ? setTimeout(function() { $(a); }, 9) : a() : new i(a);
};
$[d] = i[d] = {
on: function (a, b) {
return this.each(function (c) {
f ? c['add' + e](a, b, false) : c.attachEvent('on' + a, b)
})
},
off: function (a, b) {
return this.each(function (c) {
f ? c['remove' + e](a, b) : c.detachEvent('on' + a, b)
})
},
each: function (a, b) {
for (var c = this, d = 0, e = c.length; d < e; ++d) {
a.call(b || c[d], c[d], d, c)
}
return c
},
splice: c.splice
}
}(document, [], 'prototype', 'EventListener');
$.each = function(arr, callback) {
if(toString.call(arr) === '[object Array]'){
var i = 0, l = arr.length;
for(; i < l; ++i) {
callback.call(arr[i], i, arr[i]);
}
} else {
for (i in arr)
callback.call(arr[i], i, arr[i]);
}
return arr;
};
//extended to include "attr"
$.prototype.attr = function(a, b) {
return b === []._ ? this[0].getAttribute(a) : this.each(function(c) {
c.setAttribute(a, b);
});
};
//extended to include "removeAttr"
$.prototype.removeAttr = function(a) {
return this.each(function(b) {
b.removeAttribute(a);
});
};
//extend to include "parent"
$.prototype.parent = function() {
return (this.length < 2) ? $(this[0].parentNode): [];
};
//custom function to wrap an element in another
$.prototype.wrap = function(a) {
return this.each(function(b) {
var c = document.createElement(a)
b.parentNode.insertBefore(c, b);
c.appendChild(b);
});
};
//quick way of exposing everything like 'addClass', 'removeClass' etc. without having to define each one indivdually
var props = ['add', 'remove', 'toggle', 'has'],
maps = ['add', 'remove', 'toggle', 'contains'];
props.forEach(function(prop, index) {
$.prototype[prop + 'Class'] = function(a) {
return this.each(function(b) {
if(a){
b.classList[maps[index]](a);
}
});
};
});
//extend to include "after"
$.prototype.after = function(a) {
return this.each(function(b) {
b.insertAdjacentHTML('afterend', a);
});
};
//Below is the actual function, all of the above is just a simple replacement for jQuery.
//Should work with just jQuery but you would have to check.
$("img").each(function(){
$(this).wrap("div"); //create a div around an image
var title = $(this).attr("title"); //grab the title
var wrapper = $(this).parent(); //grab the div we just created
wrapper.attr("data-title", title); //set the data-title that we use in the CSS on the wrapper
wrapper.addClass("image"); //add the class that we use for CSS
wrapper.attr("tabindex", "0"); //make the div focusable with tabindex="0"
$(this).after('<span class="visually-hidden">, Title ' + title + '</span>'); //add a span with the title in that is accessible to screen readers - note the use of a comma before the 'Title' part as this makes it more natural (as we are 'hacking' an experience similar to that of a screen reader reading an actual title.)
$(this).removeAttr('title'); //remove the actual title, otherwise some screen readers will announce the title twice.
});
.image{
display:block;
overflow:hidden;
}
/*need relative position in order to absolutely position the overlay*/
.image {
position:relative;
width:200px;
height:200px;
margin: 10px;
}
.image img {
width:100%;
vertical-align:top;
}
/*add a transition*/
.image:after,
.image:before {
position:absolute;
opacity:0;
transition: all 0.5s;
}
/*remove the transition for people who have reduced motion as a preference*/
#media (prefers-reduced-motion: reduce) {
.image:after,
.image:before {
transition: none;
}
}
/*create an overlay*/
.image:after {
content:'';
width:100%;
height:100%;
top:0;
left:0;
background:rgba(0,0,0,0.4);
}
/*create a box at the bottom that contains the 'data-title' text that was added to the div we created*/
.image:before {
content: attr(data-title);
font-size: 1.25rem;
line-height: 1.9rem;
width:100%;
color:#fff;
z-index:1;
bottom:0;
padding:4px 10px;
text-align:left;
background:black;
box-sizing:border-box;
-moz-box-sizing:border-box;
}
/*make the overlay visible on hover and focus*/
.image:hover::after,
.image:hover::before,
.image:focus::after,
.image:focus::before{
opacity:1;
}
/*put a border around on focus*/
.image:focus{
outline: 2px solid #333;
outline-offset: 4px;
}
/*visually hidden class used to make text screen reader accessible but not visible*/
.visually-hidden {
position: absolute !important;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
clip: rect(1px, 1px, 1px, 1px);
white-space: nowrap; /* added line */
}
<img src="https://via.placeholder.com/150" title="First Image" alt="First Image"/>
<img src="https://via.placeholder.com/150" title="Second Image, A Longer Text Test for a more complex title, adjust to your needs" alt="Second Image"/>
According to the HTML 5.2 specification,
The title attribute represents advisory information for the element, such as would be appropriate for a tooltip.
The specification also adds the following warning:
Warning! Relying on the title attribute is currently discouraged as many user agents do not expose the attribute in an accessible manner as required by this specification (e.g., requiring a pointing device such as a mouse to cause a tooltip to appear, which excludes keyboard-only users and touch-only users, such as anyone with a modern phone or tablet).
In other words, one should not rely on the title attribute for exposing information to keyboard users, including screen reader users. This issue has been around for many years. Accessibility standards recommend(ed) the use of the title attribute only on the frame element (which is deprecated in HTML 5) the input element (if you don't use a label element for aesthetic reasons) and the abbr element. See also Steve Faulkner's blogpost Using the HTML title attribute – updated. (Even though the blogpost was last updated in 2013, the advice is essentially still valid.)
If you want the content of the title attribute to be exposed visually on keyboard focus, you'll need to rely on CSS, JavaScript or a combination of both. Note, however, that the img element is not keyboard focusable by default.
I am trying to create a server status icon on the top of my application. When it is off appear as red, and on the other hand when it is on appear as green.
I have done all the dirty job in my DAL, BL, Controller and ViewModel and as a result i have a div element on my page which change colors subjected on the service status. My problem is that i cannot add a label next to the div.
public static class ServerStatusIconHelper
{
public static MvcHtmlString ServerStatusIconHelper(this HtmlHelper htmlHelper, bool isServerActive)
{
// Main container
var div = new TagBuilder("div");
bool isActive = isServerActive;
var labelValue = isActive ? "The server status is On" : "The server status is Off";
if (isActive)
{
div.Attributes.Add("id", "server-warning-on");
div.Attributes.Add("style", "background-color: green; height:25px; margin-bottom: 10px; border-radius: 25px; width: 25px; margin-left: 10px;");
}
else
{
div.Attributes.Add("id", "server-warning-off");
div.Attributes.Add("style", "background-color: red; height:25px; margin-bottom: 10px; border-radius: 25px; width: 25px; margin-left: 10px;");
}
return new MvcHtmlString(div.ToString());
}
}
I would appreciate some help since i dont know to add a div with a paragraph element which will provide the labelValue. In addition if anyone has any idea for something better would be nice.
When using TagBuilder you can set tag content using InnerHtml property or SetInnerText method:
InnerHtml: Gets or sets the inner HTML value for the element.
SetInnerText: Sets the InnerHtml property of the element to an HTML-encoded version of the specified string.
Here is an example:
var div = new TagBuilder("div");
div.AddCssClass("someClass");
div.MergeAttribute("id", "someId");
div.InnerHtml = "Some Text or Html Tag";
var result= div.ToString();
Which generates this output:
<div class="someClass" id="someId">Some Text or Html Tag</div>
You can combine label and div tags this way.
Also, you need to add display: inline-block; to your style to display label next to div.
You can use InnerHtml property of the tag.
var labelValue = isActive ? "The server status is On" : "The server status is Off";
div.InnerHtml = labelValue;
or if you want to concatenate a span element with div, you can do
var span = new TagBuilder("span");
span.InnerHtml = labelValue;
and return as
return new MvcHtmlString(div.ToString() + span.ToString());
I'm using "HTML Renderer for WPF" from NuGet. I'm finding the output to be inadequate, and the discussion boards seem quiet and unmonitored so I thought it better to post here.
I have an HtmlPanel quite trivially in my xaml as
<htmlrenderer:HtmlPanel Grid.Row="2"
Text="{Binding ReportContent}"/>
where
xmlns:htmlrenderer="clr-namespace:TheArtOfDev.HtmlRenderer.WPF;assembly=HtmlRenderer.WPF"
I'm feeding it some simple HTML;
<!DOCTYPE html>
<html><head><title>dummy</title></head>
<body>
<style>
table {
border-spacing: 5px;
}
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 2px;
}
th {
text-align: left;
}
</style>
<h1>Report for <b>Processing dev</b> generated 16/11/2015 16:02</h1>
<hr/>
<h2>Group <i>Everyone</i></h2>
<table><caption>
<h3><b>Stage 1</b>
Run; Mass start</h3></caption><tr><th>pos</th><th>num</th><th>Name</th><th>Time</th></tr>
<tr><td>1</td><td>1</td><td>Person 1</td><td>00:41:00.0</td></tr>
<tr><td>2</td><td>2</td><td>Person 2</td><td>00:47:23.0</td></tr>
<tr><td>3</td><td>3</td><td>Person 3</td><td>00:47:24.0</td></tr>
<tr><td>4</td><td>4</td><td>Person 4</td><td>00:47:24.1</td></tr>
<tr><td>5</td><td>5</td><td>Person 5</td><td>00:52:00.0</td></tr>
<tr><td>6</td><td>6</td><td>Person 6</td><td>00:54:21.0</td></tr>
<tr><td>7</td><td>7</td><td>Person 7</td><td>00:54:32.0</td></tr>
<tr><td>8</td><td>8</td><td>Person 8</td><td>00:55:04.0</td></tr>
<tr><td>9</td><td>9</td><td>Person 9</td><td>00:56:23.0</td></tr>
<tr><td>10</td><td>10</td><td>Person 10</td><td>01:03:00.0</td></tr>
</table>
<table><caption>
<h3>Overall Results</h3>
</caption><tr><th>pos</th><th>num</th><th>Name</th><th>Time</th></tr>
<tr><td>1</td><td>1</td><td>Person 1</td><td>00:41:00.0</td></tr>
<tr><td>2</td><td>2</td><td>Person 2</td><td>00:47:23.0</td></tr>
<tr><td>3</td><td>3</td><td>Person 3</td><td>00:47:24.0</td></tr>
<tr><td>4</td><td>4</td><td>Person 4</td><td>00:47:24.1</td></tr>
<tr><td>5</td><td>5</td><td>Person 5</td><td>00:52:00.0</td></tr>
<tr><td>6</td><td>6</td><td>Person 6</td><td>00:54:21.0</td></tr>
<tr><td>7</td><td>7</td><td>Person 7</td><td>00:54:32.0</td></tr>
<tr><td>8</td><td>8</td><td>Person 8</td><td>00:55:04.0</td></tr>
<tr><td>9</td><td>9</td><td>Person 9</td><td>00:56:23.0</td></tr>
<tr><td>10</td><td>10</td><td>Person 10</td><td>01:03:00.0</td></tr>
</table>
</body></html>
My app renders this as follows. Note the absence of captions on the tables, the garbage upper left (which only appears when I have captions), and the lack of italic text ("Everyone" should be in italics). Loading this into Chrome renders correctly. I've checked it on validator.w3.org and the only error is the lack of a new "scoped" keyword in the style which isn't generally supported yet anyway.
Does anyone else have experience of this library? Given it doesn't seem to be functioning correctly in such a simple case, and seems like it may be dormant, is it worth persisting with? Is there a simple alternative that can just take a block of HTML and render it rather than what seems the over the top solution of CEFSharp, where various page providers have to be created and registered?
Try System.Windows.Controls.WebBrowser:
<Grid>
<WebBrowser x:Name="webBrowser1" Margin="0" Source="file:///C:/Users/Public/test01.html"/>
</Grid>
Or:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
webBrowser1.Source = new Uri("file:///C:/Users/Public/test01.html");
}
I am building a web page live as output for my application. This means that I'm editing the document text directly, instead of pointing the control to a file. I have the following code:
<html>
<head>
<style type = "text/css">
.circle {
position:relative;
moz-border-radius: 10px;
-webkit-border-radius: 10px;
-khtml-border-radius: 10px;
border-radius: 10px;
-moz-background-clip: padding;
-webkit-background-clip: padding-box;
background-clip: padding-box;
border: 1px solid #000;
height: 10px;
width: 10px;
background-color:#33FF00;
}
</style>
<script type="text/javascript">
var step = 0;
var color= '#0000FF';
function timer()
{
var t=setTimeout("switchColor()",125);
}
function switchColor()
{
if (step == 0) {color='#33FF00';}
if (step == 1) {color='#33FF00';}
if (step == 2) {color='#22AA55';}
if (step == 3) {color='#1155AA';}
if (step == 4) {color='#0000FF';}
if (step == 5) {color='#0000FF';}
if (step == 6) {color='#1155AA';}
if (step == 7) {color='#22AA55';}
step = step+1;
if (step > 7) { step = 0;}
var elements = document.getElementsByClassName('circle')
for (var i = 0;i <elements.length;i++)
{
elements[i].style.backgroundColor=color;
}
timer()
}
</script>
</head>
<body onload="timer()" >
<div id="test" class="circle1"></div>
<div class="circle"></div><div class="circle"></div>
<br>
<br>
</body>
</html>
That code is then set as the documentText of a webBrowser control by using a stringBuilder, adding each line with the StringBuilder.AppendLine() function, and then converting the entire stringBuilder to a string.
I get the error that the getElementsByClassName function is not supported, and nothing happens. The html runs perfectly on its own.
The WebBrowser Control can run javascript live, but it has the same limitations as Internet Explorer. Any commands used within the control need to be able to run in Internet Explorer on the associated machine.
You´ll need to use getElementsByTagName('*'), iterate over the list and verify if each item has the desired className.
As an answer for you, I propose that you use jQuery. It can find elements that have a certain class and works great in IE. Specifically look at the class selector.
www.jquery.com
http://api.jquery.com/class-selector/
I have an ASP.NET AJAX autocomplete extender with CompletionListCssClass=autocomplete_completionListElement :
.autocomplete_completionListElement
{
width:500px;
margin : 0px!important;
background-color : inherit;
color : windowtext;
border : buttonshadow;
border-width : 1px;
border-style : solid;
overflow :auto;
height : 200px;
text-align : left;
}
But for some odd reason the width of the auto complete list always takes up the width of the textbox even when I set the width to 500px. Is there a way to fix this?
I believe you can also accomplish this by changing
width:500px;
to
width:500px!important;
Tim Mackey expounds more in this blog post. Basically you have to use !important to override the CSS spit out by the control itself.
I finally figured it out. I used the OnClientPopulated="onListPopulated" property as follows:
function onListPopulated() {
var completionList = $find("AutoCompleteEx").get_completionList();
completionList.style.width = 'auto';
}
You need to set the min-width to 500px