Fire onmouseover event when element is disabled - html

I have some controls that I need to disable when users don't have edit privileges, but are sometimes not wide enough to show the entire text of the selected option element. In which case I've added a tool tip with ASP.NET and the following code
ddl.Attributes.Add("onmouseover", "this.title=this.options[this.selectedIndex].title")
This works when the control is enabled, but doesn't work when it is disabled.
The following alert will not fire when a mouse is over the select element:
<select disabled="disabled" onmouseover="alert('hi');">
<option>Disabled</option>
</select>
See this fiddle.
Q: Can I fire the onmouseover event for controls that are disabled?

Disabled elements do not fire events, e.g. users cannot hover or click them to trigger a popover (or tooltip). You can however wrap the disabled element with a DIV and listen to the event fired on that element instead.

Update: Please see nathan william's comment for some serious limitations to this approach. I've updated the fiddle to illustrate the problem areas more clearly.
Expanding on what #Diodeus said, you can use jQuery to automatically create the div container for you and wrap it around any disabled elements.
Use the :disabled selector to find all disabled elements.
Then call the .wrap() method with a function callback
You can use this to refer to the current element in the set.
Then use .attr() method to get the onmouseover value from the parent element and apply the same value to the new div.
$(':disabled').wrap(function() {
return '<div onmouseover="' + $(this).attr('onmouseover') + '" />';
});
Demo in jsFiddle

I know this is an old post, but hopefully this answer will clarify how #Diodeus answer can be implemented!
Disabled elements do not fire events, e.g. users cannot hover or click them to trigger a popover (or tooltip). As a workaround, you can however wrap a <DIV> or <span> around the disabled element and listen to the event fired on that element instead.
NOTE! Using onmouseover and onmouseout in the wrapper <DIV> will not work as expected in Chrome (v69). But will however work in IE. Which is why I recommend users to use onmouseenter and onmouseleave instead, which is working great both in IE and in Chrome.
<select disabled="disabled" onmouseover="alert('hi');">
<option>Disabled</option>
</select>
<div onmouseenter="alert('hi');">
<select disabled="disabled" onmouseover="alert('hi');">
<option>Disabled with wrapper</option>
</select>
</div>
I've put together a JS fiddle with some examples here: http://jsfiddle.net/Dr4co/tg6134ju/

Why can't you add a title on the target element?
title looks like the same as tool tip.
And title works on disabled elements.
when you set the value of your select, also set title:
element.value=value;
element.title = element.options[element.selectedIndex].text;

I know this is an old post, but in chrome you can set css property pointer-events to all and it should allow for events. I haven't checked in other browsers.
button[disabled] {
pointer-events: all;
}
Edit:
Actually I think setting the property to auto is sufficient. As #KyleMit commented, support it's pretty good.
I just used this in project where I needed to disable an button until some validation rules where met, but I also needed to trigger the validation on hover over the button. So adding the pointer-events did the trick. I think it's the easiest way get over the problem stated in the OP.

there are two solutions for this
<Tooltip title="Tooltip" placement="bottom">
<div>
<IconButton disabled>
<Done />
</IconButton>
</div>
</Tooltip>
or this one if you dont want miss the view
<Tooltip title="Tooltip" placement="bottom">
<IconButton component="div" disabled>
<Done />
</IconButton>
</Tooltip>
reference

Related

Toggle ng-click attribute

I have a span with an ng-click="..." attribute. The ng-click slightly modifies the span's CSS within the DOM so that it is more button-like. Within my application I wish to toggle whether or not that span is clickable or not. I can make the ng-click not do anything easy enough but what I would prefer is to just remove/disable the attribute altogether. This is to avoid all "buttonizing" that the ng-click does to the element. It would also be nice if the attribute were re-enabled if the clickable variable becomes true again.
I would like a solution that avoids using $scope.$watches because my application is pretty large and watches are slow.
Thanks!
I think you can have two spans with and without ng-click attribute and based on that clickable variable you control those two spans with ng-if or ng-show
Simple solution suggested by to Achu!
Just use two spans rather than toggle the attribute on a single span.
<span ng-if="clickable" ng-click="...">Click me!</span>
<span ng-if="!clickable">Cant click me!</span>
If I were in such a situation, I would not try to enable or disable ng-click attribute. Rather, I would use some flag variable with the $scope to see if click function should perform its functionality or not like in your controller you have a method like
$scope.spanClick = function(){
if(!$scope.shouldClick){
return;//simply do nothing
}
//Do button click logic
}

Polymer 1.0 - paper-textarea autofocusing even when autofocus set to false

I have a paper-textarea inside of a drawer. When I go to the page the paper-textarea autofocuses, which opens the drawer. I've tried to get rid of the focus by trying autofocus="false" and autofocus="off", but neither have worked for me. Any help would be appreciated.
<paper-textarea id="descriptionInput" label="Description" invalid="{{descriptionError}}" error-message="please enter a valid description" value="{{description}}" autofocus="false"></paper-textarea>
Update: Another way to go about this might be to remove the focus programatically, but I've tried this.$.descriptionInput.blur() inside of the attached function, and it's not working either.
This is due to iron-autogrow-textarea's autofocus property default value being set to "off". The autofocus attribute is active if it exists, the only way to disable it is to remove it all together (ie, autofocus="disabled" or autofocus="off" will still autofocus the tag).
I've created a pull request and this will hopefully be fixed in future versions.
For the time being, you can create a disabled input tag before the textarea with an autofocus attribute and visibility set to hidden and this will prevent the textarea from gaining focus.
<input disabled autofocus style="visibilty: hidden">
I ran into an issue with the answer by Kevin Ashcraft, on Safari it was not working.
Here is another option, since the issue it due to the presence of the autofocus attribute, you need to remove that attribute. So I have polymer element and in there I have the following
ready:function(){
var list = Polymer.dom(this.root).querySelectorAll('iron-autogrow-textarea');
list.forEach(function (e) {
e.textarea.removeAttribute("autofocus")
});
}
This scans my dialog, finds all iron-autogrow-textarea and removes the attribute from them... you can change the selector to get only the ones you need.
Update this has been fixed as of latest version Should mention this has been fixed in latest version of https://github.com/PolymerElements/iron-autogrow-textarea/releases/tag/v1.0.8

Make an HTML element non-focusable

Is it possible to make an HTML element non-focusable?
I understand that a list of elements that can receive focus can be defined and that a user can navigate through these elements by pressing a Tab key. I also see that it is up to the browser to control this.
But maybe there is a way to make certain elements non-focusable, say I want a user to skip a certain <a> tag when pressing a Tab.
unfocusable
A negative value means that the element should be focusable, but should not be reachable via sequential keyboard navigation.
See also: developer.mozilla.org
To completely prevent focus, not just when using the tab button, set disabled as an attribute in your HTML element.
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<input class="form-control" type="text"> Click this, you can see it's focusable.
<input class="form-control" type="text" readonly> Click this, you can see it's focusable.
<input class="form-control" type="text" readonly tabindex="-1"> Click this, you can see it's focusable. Not tab'able.
<input class="form-control" type="text" disabled> Click this, you can see it's <strong>not</strong> focusable.
In order to make an prevent an element from taking focus ("non-focusable"), you need to use Javascript to watch for the focus and prevent the default interaction.
In order to prevent an element from being tabbed to, use tabindex=-1 attribute.
Adding tabindex=-1 will make any element focusable, even div elements. This means when a user clicks on it, it would likely get a focus outline, depending on the browser..
You would ideally, want this:
/**
* #this {HTMLElement}
* #param {FocusEvent} event
* #return {void}
*/
function preventFocus(event) {
if (event.relatedTarget) {
// Revert focus back to previous blurring element
event.relatedTarget.focus();
} else {
// No previous focus target, blur instead
this.blur();
// Alternatively: event.currentTarget.blur();
}
}
/* ... */
element.setAttribute('tabindex', '-1');
element.addEventListener('focus', preventFocus);
For safe typechecking, you can perform if (event.relatedTarget instanceof HTMLElement) instead if (event.relatedTarget).
TabIndex is what your looking for: http://www.w3schools.com/jsref/prop_html_tabindex.asp.
When you set a tabIndex value to -1 you will skip it when tabbing through your form.
In case you are looking for a global solution:
Link
document.body.addEventListener('focusin', (e) => {
if (e.target.classList.contains('__nofocus')) {
e.relatedTarget ? e.relatedTarget.focus() : e.target.blur();
}
});
It should work for anchors, buttons and anything else that can receive focus by default. Don't forget to set tabindex="-1" as well as the element would be unpassable by Tab-key navigation.
For the element you do not want to be focused on tab, you have to put the tabindex as a negative value.
I used focusable="false", because tabindex="-1" was not working in IE.
Making a focusable-by-default HTML element a non-focusable one isn't possible without JavaScript.
After diving into focus-related DOM events, I've came up with the following implementation (based on the #ShortFuse's answer, but fixed some issues and edge cases):
// A focus event handler to prevent focusing an element it attached to
onFocus(event: FocusEvent): void {
event.preventDefault();
// Try to remove the focus from this element.
// This is important to always perform, since just focusing the previously focused element won't work in Edge/FF, if that element is unable to actually get the focus back (became invisible, etc.): the focus would stay on the current element in such a case
const currentTarget: any | null = event.currentTarget;
if (currentTarget !== null && isFunction(currentTarget.blur))
currentTarget.blur();
// Try to set focus back to the previous element
const relatedTarget: any | null = event.relatedTarget;
if (relatedTarget !== null && isFunction(relatedTarget.focus))
relatedTarget.focus();
}
// Not the best implementation, but works for the majority of the real-world cases
export function isFunction(value: any): value is Function {
return value instanceof Function;
}
This is implemented in TypeScript, but could be easily adjusted for plain JavaScript.

HTML5 contextmenu attribute question? [duplicate]

can someone explain what the the contextmenu attribute does and if it can be used with all the HTML elements and can someone point me to some online demos/examples?
The contextmenu attribute refers to the <menu> element the user agent should render when a context menu is requested by the user (e.g. using the right mouse button or the Menu/Hyper key on modern keyboards.
You can find an example here.
You can see how it may look like in this demo:
https://bug617528.bugzilla.mozilla.org/attachment.cgi?id=554309
At the time of writing only FireFox 8 supports it.
The context menu appears when the user right-clicks on an interface element. The contextmenu attribute is the ID of a <menu> element to open when the user right clicks on the element with this attribute.
Quoting for you to understand easily:
The contextmenu attribute allows you
to display a menu without taking up
valuable UI space for the menu. It is
a menu which fires on events, such as
mouseup or keyup providing a bubble
menu which provides options and
actions based on those selections.
Source: http://net.tutsplus.com/tutorials/html-css-techniques/html5-globals-and-you/
See official link for more information:
http://www.w3.org/TR/html5/interactive-elements.html
The contextmenu should be used on an input field to specify which menu element is for the field. The menus look sort of like the right click menu or a dropdown box however they are not implemented in any browser yet so you should avoid using them.
This may help clear things up:
http://dev.w3.org/html5/spec-author-view/interactive-elements.html
<form name="npc">
<label>Character name: <input name="char" type="text" contextmenu="namemenu" required></label>
<menu type="context" id="namemenu">
<command label="Pick random name" onclick="document.forms.npc.elements.char.value = getRandomName()">
<command label="Prefill other fields based on name" onclick="prefillFields(document.forms.npc.elements.char.value)">
</menu>
</form>
http://www.w3.org/TR/html5/interactive-elements.html#context-menus

mootools event listener disappears after element.innerHTML is changed

I putting together a page that will display a set of stored values. I am using mootools and AJAX calls to update the values without needing to refresh the page each time the user selects a new item from the drop down menus.
the HTML each line looks something like:
<div class="selections">
<input class="checkbox selector" type="checkbox" CHECKED />
<span class="b_name">
<select class="b_n selector">
<!-- options -->
</select>
</span>
<span class="b_level">
<select class="b_l selector">
<!-- options -->
</select>
</span>
<span class="values">
<!-- the values -->
</span>
</div>
In the head I have set up an event listener like:
$$('.selector').addEvent('change', function(event){changeValues(this);});
My problem is that when the "b_name" select changes I have to update the list of options in the "b_level" select. I accomplish that by getting a list of the possible options from my database through a PHP script on another page and replacing "b_level"'s innerHTML. Once I do that, the event listener attached to "b_l selector" no longer works.
I tried to resolve this issue by explicitly attaching an event listener to "b_l selector" each time "b_name" changes like so:
row.getElement('.b_l').addEvent('change', function(event){changeValues(row.getElement('.b_l'));});
where 'row' is the html element 'div.selections'.
It still isn't working and I have no idea what's going on. Can anyone offer a suggestion as to how I can get this resolved? or perhaps a better way to do what I'm doing.
This is how JavaScript works, it's not a bug.
What you need to use is Element Delegation - you attach an event to the parent element, in the same time specifying the element that the event should be delegated to.
Here's a basic example of Element Delegation in action: http://jsfiddle.net/oskar/ENR3E/
And the documentation: http://mootools.net/docs/more/Element/Element.Delegation
When you set innerHTML on an element, the element's contents are completely cleared and replaced with a new set of elements -- the ones parsed from the innerHTML property. Any events set on the old elements will not apply to the new ones.
jQuery provides a solution to this problem with live() events. I found a solution here that apparently achieves the same with mootools.
Your approach is correct, there's probably just a bug in your addEvent() code. The reason the event handler disappears when you replace the innerHTML is straightforward enough - you are removing the elements that the handlers are on, so the handlers are removed as well. But your approach to re-add the handler should work.
I think it's possible that it's a scoping issue. What happens if you reference the div explicitly, like this:
row.getElement('.b_l').addEvent('change', function(event){
{
changeValues($$('div.selections .b_l'));
});