javascript onmouseout works also on mouse over - javascript

I'm trying to show/hide some of text in a button.
the button is
<button id="SOS" onmouseover="show()" onmouseout="hide();">
<p>S.O.S</p>
<div id="sos_left"> <?=$text_to_show_hide?></div>
</button>
and the javascript code is
<script type="text/javascript">
function show()
{
sos_left=document.getElementById('sos_left');
alert("mouseover");
sos_left.style.color = "red";
sos_left.style.fontSize = "28";
}
function hide(){
sos_left=document.getElementById('sos_left');
alert("mouseout");
sos_left.style.color = "blue";
sos_left.style.fontSize = "0";
}
</script>
the thing is that the mouse out alerts even when I'm mouse overing.
NOTE: I can't use jquery because the site is vbulletin based and I use this code on one of the templates.

The problem is that mouseover and mouseout events bubble up, and this means that when your cursor enters and exits from elements that are descendants of your button, the event listener defined on the button is triggered too.
What you can do is to check if the element that generated the event is actually the <button> element. Fix the DOM like this:
<button id="SOS" onmouseover="show(event)" onmouseout="hide(event);">...
Then your JS code:
function show(e) {
if ((e.target || e.srcElement).id !== "SOS") return;
...
function hide(e) {
var tgt = e.target || e.srcElement;
if (tgt.id !== "SOS") return;
// If the cursor enter in one of the descendants, mouseout is fired, but
// we don't want to handle this
if (tgt.contains) {
if (tgt.contains(e.relatedTarget || e.toElement)) return;
} else if (this.compareDocumentPosition)
if (tgt.compareDocumentPosition(e.relatedTarget)
& Node.DOCUMENT_POSITION_CONTAINS) return;
...
In Internet Explorer (and now in Opera too) there are these events mouseenter and mouseleave that behave very similarly, but don't bubble up. For other browsers they're emulated in common frameworks like jQuery.
On a final note, I'd suggest you to use some more modern method to attach your event listeners than the traditional one. Plus, the way you define sos_left implies that it becomes a global variable. Use the keyword var in front of the definition.

you dont hide anything..
use display:none to "remove" element, or visibility:hidden to hide element.
to "re-add" the element, use display: block or visibility:visible, if you used visibility attribute to hide.
try each both to see the difference.
another problem is,
you try to use sos_left as variable, but you didn't declare it as variable.
use var sos_left instead of.

That's because you apply the event to the div not the button. Try this:
sos_button=document.getElementById('SOS');

Related

buttons with no href, onclick etc

Lately, I've been seeing a lot of sites that have clickable objects that don't have any hrefs or onclicks in their html code. I also tried alerting their href, onclick, onmousedown, onmouseup attributes but it only says "undefined". I do notice that there's a lot of complicated javascript in these pages.
one site in particular baffles me:
http://www.sharenator.com/Boy_Teaches_His_Puppy_How_to_Eat/#/doggy_01_Boy_Teaches_His_Puppy_How_to_Eat-0.html
It's actually pretty good. The buttons aren't selectable as well. The ids of the buttons are nextBtn, nextBtn2, prevBtn and prevBtn2.
Anybody has any idea how to implement this?
You can use jQuery's .click(callback) function (http://api.jquery.com/click/) or .delegate(selector, 'click', callback) (prior to jQuery 1.7) and .on('click', selector, callback) (jQuery 1.7+) or .bind('click', callback).
Thanks to Anthony Grist for pointing out that .live() is now deprecated :)
As so:
<button id="clickable">Click Me!!</button>
Then target the button with jQuery:
$("#clickable").click(function(){
// Send user to this link
location.href = "http://www.takemehere.com";
});
You can read more about this on the link I gave, and on jQuery's homepage.
UPDATE
The actual page handles this with:
$('#prevBtn').mousedown (onBackward);
Which would onmousedown call:
function onBackward () {
showImg (currentId - 1);
}
The use of arrow keys:
$(document).keyup (function (event) {
var activeElement = document.activeElement.tagName;
if (activeElement == 'INPUT' || activeElement == 'TEXTAREA') return;
//alert (window.location.pathname);
if (event.keyCode == 39) onForward();
else
if (event.keyCode == 37) onBackward();
});
See http://www.sharenator.com/js/slideshow.js for the source code of the slideshow.
You could try using the jQuery ui library - this can create buttons in the way you specify.
jQuery UI
The event handlers are probably bound using a Javascript framework such as jQuery. They don't use the onclick property of the DOM element. See this jsFiddle for an example of binding a click event handler to a button with jQuery, then click the button to see the value of onclick for that button (displays as null in FF 9).
With javascript, find the element and give it an onClick event handler. e.g.:
var myElement = document.body; // or document.getElementById(...), etc.
myElement.onclick = function(event) {alert(event);}
This will avoid showing anything in the HTML, and is how the website you linked does it (there is no other way to define behavior... except maybe esoteric CSS).
With javascript. Here's an example:
<a id="uniqueId" href="#">Button</a>
<script>
var button = document.getElementById('uniqueId');
button.onclick = function(e) {
alert("clicked!");
}
</script>
the click functions may be initialized in js, for example, $("#nextBtn").click(function);

Disable doubleclick event for an element in Opera

Is there a way to disable (with CSS, JS or jQuery) double-click for a given element?
The problem with Opera is that it displays a menu when I click on an element too fast. Note that I know how to disable this for me. I'd like to be able to disable this for all user that use the script.
The buttons in question are "next"/"previous" buttons and I use input type image for them, but the same happens with "a".
It turended out I need this:
/**
Disable text selection by Chris Barr, of chris-barr.com
*/
$.fn.disableTextSelect = function() {
return this.each(function(){
if($.browser.mozilla){//Firefox
$(this).css('MozUserSelect','none');
}else if($.browser.msie){//IE
$(this).bind('selectstart',function(){return false;});
}else{//Opera, etc.
$(this).mousedown(function(){return false;});
}
});
}
And then I could disable text selection on my button elements like this:
$(function(){ $('input[type=image]').disableTextSelect(); });
And now I can click buttons fast as hell and all works fine :-).
You cannot have a click and dblclick event handler attached on the same element because when you dblclick both the events are going to be triggered. In order to make it work there are few work arounds.
This might help you
Need to cancel click/mouseup events when double-click event detected
Looking at your problem there is a simple solution. In the click event handler once it is clicked set a disabled attribute or some class name(disabled). In the handler before exectuing your code checck for this attribute or class name. If it exists then dont do anything. After sometime remove this attribtue or class name. Try this
$("selector").click(function(){
var $this = $(this);
if(!$this.hasClass("disabled")){
//Do you stuff here
$this.addClass("disabled");
setTimeout(function(){
$this.removeClass("disabled");
}, 200);
}
});
JavaScript would do that for you.
DOMElement.ondblclick = (function () {return false;})();

iOS Web App touch gestures

I've searched all across the web to find a simple way of adding touch gestures to a simple button. Basically I'm trying to find a simple way of getting the back button (which you usually see on the task-bar at the top of an iOS device) to change CSS classes from 'normal' state to 'pressed' state when pressed.
Although I'm very new to Javascript, I would prefer to use standard DOM methods rather than jQuery (or any other library). Would anyone have some complete code and explain how the JavaScript code reads an ontouchstart and ontouchend event and how these functions could be used to change CSS classes?
Any help would be greatly appreciated!
TC
ontouchstart, ontouchmove and ontouchend are managed the same as onclick, onmousemove and so.
You can apply the listeners in a <script> tag or directly in the html element.
Using JavaScript only
var back = document.getElementById("back-button-id");
back.ontouchstart = function( event ) {
// using the target property of the event
// you can reach the hitted html element
event.target.className = 'css-href-selected-class-name';
}
back.ontouchend = function( event ) {
event.target.className = 'css-href-normal-class-name';
}
Using HTML tag and callbacks
1) Declare your Javascript callbacks to swap a css class for any state
function onclickCallback( event ) {
// do something
}
function ontouchstartCallback( event ) {
event.target.className = 'selected';
}
function ontouchendCallback( event ) {
event.target.className = 'normal';
}
2) Put the callbacks into the anchor tag (I suggest to use DIV instead of A)
<div class="normal" onclick="onclickCallback( event );" ontouchstart="ontouchstartCallback( event );" ontouchend="ontouchendCallback( event );">Back</div>
Edit 1: to prevent hilight freezing during scrolling
Try to add the ontouchmove handler
ontouchmove="ontouchmoveCallback( event );"
Then declare the handler function that swap the css class
function ontouchmoveCallback( event ) {
event.target.className = 'normal';
}
Hope this helps!
Ciao.
This should get you started:
HTML:
<input type="button" id="thebutton" value="Do Stuff!" />
Javascript:
var thebutton = document.getElementById("thebutton");
thebutton.ontouchstart = function(e)
{
this.setAttribute('class', 'pressed');
var touches = e.touches; // array of all touch data
var target = touches[0].target; // what DOM element was touched
var pageX = touches[0].pageX; // coords relative to site
var pageY = touches[0].pageY;
var clientX = touches[0].clientX; // coords relative to screen
var clientY = touches[0].clientY;
};
thebutton.ontouchmove = function(e)
{
var touches = e.touches; // same fields as above
var changedTouches = e.changedTouches; // only touches which have changed
};
thebutton.ontouchend = function(e)
{
this.setAttribute('class', '');
// cleanup, if needed
};
For more details, see: http://sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/
It's worth noting that MobileSafari sometimes does wonky things with touch events and form elements (input boxes in particular). You may find it's better to use a styled div than an actual input button.
EDIT: For what you're trying to do, I think you might be better served with simple click events, which generally work fine for things like button presses. Touch events are more for drag and drop, precise finger tracking etc. Try this:
thebutton.onclick = function(e) { this.setAttribute('class', 'your_class'); };
EDIT2: Now I see what you're asking for. Easiest way is this:
thebutton.ontouchstart = function(e) { this.setAttribute('class', 'pressed'); };
thebutton.ontouchend = function(e) { this.setAttribute('class', ''); };
There are a couple of libraries already for jQuery
http://plugins.jquery.com/project/multiswipe
And you also can check this demo from
http://taitems.github.com/Mobile-Web-based-Gesture-Recognition/
And you can fork the example and start working with it.
There are some options but everything its quite new.

Elsewhere click event?

I have an onClick event to change style. How to change style back when a user clicks elsewhere of an item?
Both prototype and scriptaculous libraries included.. many of the below answers doesn't work with them... Also ID of an element is UNDEFINED so it can't be used for reference in javascript.
Thanks, Yan
I have not tested this in all browsers, but if you don't want to introduce any new js framework, this solution only use CSS:
<ul>
<li tabindex="1">First</li>
<li tabindex="2">Second</li>
</ul>
The property tabIndex makes the li element focusable. And the css:
li { color: #F00; }
li:focus { color: #0F0 }
This is of course very basic styling, probably want to put it in classes or whatever.
Great question! You can use "event bubbling", which means that instead of the onclick event on your element, you define an event handler on a higher object (say, document or a table), and there you say something like:
if (event.target === myElement) {
changeStyle();
} else {
changeStyleBack();
}
More here (and elsewhere): http://www.southsearepublic.org/tag/Javascript%20Event%20Bubbling/read
When an item is clicked on it, it gains focus. When something else is clicked on it will lose focus, triggering the onblur event. May not work for all elements, but it would work for, say, <input> elements.
You want the onblur event: "The onblur event occurs when an object loses focus".
You can bind an onClick event on the body and assign the function that restore the style to that event.
There's a live example at http://jsbin.com/oxobi3
I would use jQuery live event and bind click event using :not selector
Maybe try onclick="function1()" onblur="function2()" or onfocus="function1()" onblur="function2()" in the tag.
Here's how you could do it in jQuery:
$(document).click(function(e) {
if ($(e.target).is("#specialItem")) {
$(e.target).addClass("specialClass");
} else {
$(#specialItem").removeClass("specialClass");
}
});
If you're not using jQuery, you can still use the basic model -- apply the onclick event logic at the document level. This will work for items that don't respond to the blur event.
It's been quite a long time since I've used prototype but I hope this helps you (in the non-jQuery sense.)
$(window).observe('click', respondToClick);
function respondToClick(event) {
var element = event.element();
if(!($(this) == element)){
element.addClassName('active');//or do your stuff here
}
}
My approach
var elsewhere = 1;
$(myelement).bind('hoverin',function(){
elsewhere = 0;
});
$(myelement).bind('hoverout',function(){
elsewhere = 1;
});
$('screenarea').click(function(){
if(elsewhere){
change-style-back();
} else{
change-style();
}
});
this will make sure that when you click somewhere on screen and its not on your element, then the style will change back

Using jQuery to test if an input has focus

On the front page of a site I am building, several <div>s use the CSS :hover pseudo-class to add a border when the mouse is over them. One of the <div>s contains a <form> which, using jQuery, will keep the border if an input within it has focus. This works perfectly except that IE6 does not support :hover on any elements other than <a>s. So, for this browser only we are using jQuery to mimic CSS :hover using the $(#element).hover() method. The only problem is, now that jQuery handles both the form focus() and hover(), when an input has focus then the user moves the mouse in and out, the border goes away.
I was thinking we could use some kind of conditional to stop this behavior. For instance, if we tested on mouse out if any of the inputs had focus, we could stop the border from going away. AFAIK, there is no :focus selector in jQuery, so I'm not sure how to make this happen. Any ideas?
jQuery 1.6+
jQuery added a :focus selector so we no longer need to add it ourselves. Just use $("..").is(":focus")
jQuery 1.5 and below
Edit: As times change, we find better methods for testing focus, the new favorite is this gist from Ben Alman:
jQuery.expr[':'].focus = function( elem ) {
return elem === document.activeElement && ( elem.type || elem.href );
};
Quoted from Mathias Bynens here:
Note that the (elem.type || elem.href) test was added to filter out false positives like body. This way, we make sure to filter out all elements except form controls and hyperlinks.
You're defining a new selector. See Plugins/Authoring. Then you can do:
if ($("...").is(":focus")) {
...
}
or:
$("input:focus").doStuff();
Any jQuery
If you just want to figure out which element has focus, you can use
$(document.activeElement)
If you aren't sure if the version will be 1.6 or lower, you can add the :focus selector if it is missing:
(function ( $ ) {
var filters = $.expr[":"];
if ( !filters.focus ) {
filters.focus = function( elem ) {
return elem === document.activeElement && ( elem.type || elem.href );
};
}
})( jQuery );
CSS:
.focus {
border-color:red;
}
JQuery:
$(document).ready(function() {
$('input').blur(function() {
$('input').removeClass("focus");
})
.focus(function() {
$(this).addClass("focus")
});
});
Here’s a more robust answer than the currently accepted one:
jQuery.expr[':'].focus = function(elem) {
return elem === document.activeElement && (elem.type || elem.href);
};
Note that the (elem.type || elem.href) test was added to filter out false positives like body. This way, we make sure to filter out all elements except form controls and hyperlinks.
(Taken from this gist by Ben Alman.)
April 2015 Update
Since this question has been around a while, and some new conventions have come into play, I feel that I should mention the .live method has been depreciated.
In its place, the .on method has now been introduced.
Their documentation is quite useful in explaining how it works;
The .on() method attaches event handlers to the currently selected set
of elements in the jQuery object. As of jQuery 1.7, the .on() method
provides all functionality required for attaching event handlers. For
help in converting from older jQuery event methods, see .bind(),
.delegate(), and .live().
So, in order for you to target the 'input focused' event, you can use this in a script. Something like:
$('input').on("focus", function(){
//do some stuff
});
This is quite robust and even allows you to use the TAB key as well.
I'm not entirely sure what you're after but this sounds like it can be achieved by storing the state of the input elements (or the div?) as a variable:
$('div').each(function(){
var childInputHasFocus = false;
$(this).hover(function(){
if (childInputHasFocus) {
// do something
} else { }
}, function() {
if (childInputHasFocus) {
// do something
} else { }
});
$('input', this)
.focus(function(){
childInputHasFocus = true;
})
.blur(function(){
childInputHasFocus = false;
});
});
An alternative to using classes to mark the state of an element is the internal data store functionality.
P.S.: You are able to store booleans and whatever you desire using the data() function. It's not just about strings :)
$("...").mouseover(function ()
{
// store state on element
}).mouseout(function ()
{
// remove stored state on element
});
And then it's just a matter of accessing the state of elements.
if anyone cares there is a much better way to capture focus now, $(foo).focus(...)
http://api.jquery.com/focus/
Have you thought about using mouseOver and mouseOut to simulate this. Also look into mouseEnter and mouseLeave
Keep track of both states (hovered, focused) as true/false flags, and whenever one changes, run a function that removes border if both are false, otherwise shows border.
So: onfocus sets focused = true, onblur sets focused = false. onmouseover sets hovered = true, onmouseout sets hovered = false. After each of these events run a function that adds/removes border.
As far as I know, you can't ask the browser if any input on the screen has focus, you have to set up some sort of focus tracking.
I usually have a variable called "noFocus" and set it to true. Then I add a focus event to all inputs that makes noFocus false. Then I add a blur event to all inputs that set noFocus back to true.
I have a MooTools class that handles this quite easily, I'm sure you could create a jquery plugin to do the same.
Once that's created, you could do check noFocus before doing any border swapping.
There is no :focus, but there is :selected
http://docs.jquery.com/Selectors/selected
but if you want to change how things look based on what is selected you should probably be working with the blur events.
http://docs.jquery.com/Events/blur
There is a plugin to check if an element is focused: http://plugins.jquery.com/project/focused
$('input').each(function(){
if ($(this) == $.focused()) {
$(this).addClass('focused');
}
})
I had a .live("focus") event set to select() (highlight) the contents of a text input so that the user wouldn't have to select it before typing a new value.
$(formObj).select();
Because of quirks between different browsers, the select would sometimes be superseded by the click that caused it, and it would deselect the contents right after in favor of placing the cursor within the text field (worked mostly ok in FF but failed in IE)
I thought I could solve this by putting a slight delay on the select...
setTimeout(function(){$(formObj).select();},200);
This worked fine and the select would persist, but a funny problem arose.. If you tabbed from one field to the next, the focus would switch to the next field before the select took place. Since select steals focus, the focus would then go back and trigger a new "focus" event. This ended up in a cascade of input selects dancing all over the screen.
A workable solution would be to check that the field still has focus before executing the select(), but as mentioned, there's no simple way to check... I ended up just dispensing with the whole auto highlight, rather than turning what should be a single jQuery select() call into a huge function laden with subroutines...
What I wound up doing is creating an arbitrary class called .elementhasfocus which is added and removed within the jQuery focus() function. When the hover() function runs on mouse out, it checks for .elementhasfocus:
if(!$("#quotebox").is(".boxhasfocus")) $(this).removeClass("box_border");
So if it doesn't have that class (read: no elements within the div have focus) the border is removed. Otherwise, nothing happens.
Simple
<input type="text" />
<script>
$("input").focusin(function() {
alert("I am in Focus");
});
</script>

Categories