...

View Full Version : Returning ID of Disabled Element on Mouse Down



wisar1111
12-13-2011, 07:27 AM
The following code nicely gets the element ID for the element under the mouse on the mouse down event. It ignores a disabled element though I am assuming there is some way to get this done!

Thanks in advance for any help,
Wisar



// IE is retarded and doesn't pass the event object
if (e == null)
e = window.event;

// IE uses srcElement, others use target
_target = e.target != null ? e.target : e.srcElement;

if (e.target) targ = e.target;
else if (e.srcElement) targ = e.srcElement;
if (targ.nodeType == 3) // defeat Safari bug
targ = targ.parentNode;

_elementId=targ.id?targ.id:targ.id;

alert(_elementId);

Philip M
12-13-2011, 07:52 AM
What kind of element is capable of being disabled but is supposed respond to mousedown? The fact that the element is disabled does not prevent the id from being captured.


<input type = "text" id = "ABC" disabled = true>
<input type = "button" value = "Get ID" onclick = "getID()">

<script type = "text/javascript">

function getID() {
var x = document.getElementById("ABC").id;
alert (x);
}

</script>


Quizmaster: Express 55% as a fraction in its lowest possible form.
Contestant: One eleventh.

wisar1111
12-13-2011, 01:55 PM
The functionality that I am trying to implement is a drag and drop. When the mouse goes down over an element I need to know the ID of that element to be able to drag it. Select boxes have some unusual behaviors when they are active in terms of how they can be selected (e.g. can't click on a value, have to click on the scroll bar or a white-space in the case of a multiple), but, if they were disabled, this problem would presumably go away.

To sum it up, being able to id an element under the mouse, even if it is disabled, would be tres helpful.

Cheers,
Wisar

thesam101
12-13-2011, 02:38 PM
Hi wisar1111

Why not just use JQuery which will do D&D for you?:

http://jqueryui.com/demos/draggable/#default

:thumbsup:

wisar1111
12-13-2011, 04:43 PM
That is a good question...but I am developing a PHP centric application that generates PHP code from the dragged and dropped results. jQuery isn't completely practical at this point though might be in the future. Thanks for the question though. I had looked at jQuery a bit but will do so some more.

Wilsar

Rowsdower!
12-13-2011, 05:48 PM
I cobbled this mess together in a few minutes to test out the problem (pulled from snippets of code from about.com (http://javascript.about.com/library/blfollow2.htm) and geekzilla.com (http://www.geekzilla.co.uk/View5B49D5AB-871E-4ED5-86B8-36686A5AECB3.htm) and mashed together recklessly with messy inline code and global variables :D):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>Drag and Drop Test</title>
<script type="text/javascript">
var ns4 = (navigator.appName.indexOf("Netscape")>=0 && parseFloat(navigator.appVersion) >= 4 && parseFloat(navigator.appVersion) < 5) ? true : false;
function get_left(el) {
if (ns4) {return el.pageX;}
else {
xPos = el.offsetLeft;
tempEl = el.offsetParent;
while (tempEl != null) {
xPos += tempEl.offsetLeft;
tempEl = tempEl.offsetParent;
}
return xPos;
}
}
function get_top(el) {
if (ns4) {return el.pageY;}
else {
yPos = el.offsetTop;
tempEl = el.offsetParent;
while (tempEl != null) {
yPos += tempEl.offsetTop;
tempEl = tempEl.offsetParent;
}
return yPos;
}
}
var target,start_x,start_y,original_x,original_y;
function start_drag(id){
target=id;
original_x = get_left(document.getElementById(target));
original_y = get_top(document.getElementById(target));
var this_style=document.getElementById(target).style;
this_style.position="absolute";
this_style.zIndex="1";
this_style.left = original_x +"px";
this_style.top = original_y +"px";
document.onmousemove = grab_x_y;
}
function end_drag(){
target='';
document.onmousemove = grab_x_y;
}
function grab_x_y(evt){
start_x=parseInt(mouseX(evt));
start_y=parseInt(mouseY(evt));
if(target){
document.onmousemove = follow;
}
}
// Simple follow the mouse script
function mouseX(evt) {if (!evt) evt = window.event; if (evt.pageX) return evt.pageX; else if (evt.clientX)return evt.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft); else return 0;}
function mouseY(evt) {if (!evt) evt = window.event; if (evt.pageY) return evt.pageY; else if (evt.clientY)return evt.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop); else return 0;}
function follow(evt) {
if (document.getElementById(target)) {
var obj = document.getElementById(target).style;
var current_x = parseInt(obj.left);
var current_y = parseInt(obj.top);
obj.left = (original_x + (parseInt(mouseX(evt)) - start_x)) + 'px';
obj.top = (original_y + (parseInt(mouseY(evt)) - start_y)) + 'px';
}
}
document.onmousedown = grab_x_y;
</script>
</head>
<body>
<form action="" method="post" onsubmit="return false;">
<div>
<h1>Drag and Drop Test...</h1>
<div style="width:202px;height:22px;margin-bottom:5px;"><input type="text" size="30" id="text_1" onmousedown="start_drag(this.id);" onmouseup="end_drag();" /></div>
<div style="width:13px;height:15px;margin-bottom:5px;"><input type="radio" id="radio_1" onmousedown="start_drag(this.id);" onmouseup="end_drag();" style="margin:0;padding:0;" /></div>
<div style="width:13px;height:15px;margin-bottom:5px;"><input type="checkbox" id="check_1" onmousedown="start_drag(this.id);" onmouseup="end_drag();" style="margin:0;padding:0;" /></div>
<div style="width:183px;height:49px;margin-bottom:5px;"><textarea id="textarea_1" onmousedown="start_drag(this.id);" onmouseup="end_drag();" style="margin:0;padding:0;border:1px solid #000;" rows="2" cols="20"></textarea></div>
<div style="width:35px;height:20px;margin-bottom:5px;"><select id="selection_1" onmousedown="start_drag(this.id);" onmouseup="end_drag();"><option>1</option><option>2</option></select></div>
<div style="width:35px;height:67px;margin-bottom:5px;"><select id="selection_2" onmousedown="start_drag(this.id);" onmouseup="end_drag();" multiple="multiple"><option>1</option><option>2</option></select></div>
<input type="submit" id="submit" onmousedown="start_drag(this.id);" onmouseup="end_drag();" onclick="return false;" value="submit" />
</div>
</form>
</body>
</html>

With this half-hearted script "drag and drop" functionality seems to work fine on text inputs, radio inputs, checkbox inputs, submit inputs, button inputs, select boxes (mulitple or single), and textarea elements in my local testing for IE8 and FF7.

What browser/input type combinations were you having trouble dragging while not disabled?

Maybe a look at your drag and drop script (rather than your disabled element selection attempt) would help us find the solution to your bigger problem more readily. Then you won't have to worry about trying to drag and drop unnecessarily disabled form elements...

wisar1111
12-13-2011, 06:27 PM
OMG! It is going to take me a bit to digest your post but I wanted to thank you while I was starting my meal. I am not as comfortable in JS as I am in PHP and am new to PHP for that matter!

Your code does behave exactly as I need...I just need to figure out why the stuff that I cobbled together from some of the same sources does not at this point!

Thanks again,
Wisar

Krupski
12-13-2011, 07:13 PM
(1) What kind of element is capable of being disabled but is supposed respond to mousedown?
(2) The fact that the element is disabled does not prevent the id from being captured.


Aren't those opposite concepts?

Philip M
12-13-2011, 08:05 PM
Aren't those opposite concepts?

Explain, please.

Rowsdower!
12-13-2011, 08:36 PM
Cleaned up a bit and packaged:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>Drag and Drop Test</title>
<script type="text/javascript">
/**/
//only needed to appease those browsers which do not have a native implementation of getElementsByClassName...
var getElementsByClassName = function (className, tag, elm){
if (document.getElementsByClassName) {
getElementsByClassName = function (className, tag, elm) {
elm = elm || document;
var elements = elm.getElementsByClassName(className),
nodeName = (tag)? new RegExp("\\b" + tag + "\\b", "i") : null,
returnElements = [],
current;
for(var i=0, il=elements.length; i<il; i+=1){
current = elements;
if(!nodeName || nodeName.test(current.nodeName)) {
returnElements.push(current);
}
}
return returnElements;
};
}
else if (document.evaluate) {
getElementsByClassName = function (className, tag, elm) {
tag = tag || "*";
elm = elm || document;
var classes = className.split(" "),
classesToCheck = "",
xhtmlNamespace = "http://www.w3.org/1999/xhtml",
namespaceResolver = (document.documentElement.namespaceURI === xhtmlNamespace)? xhtmlNamespace : null,
returnElements = [],
elements,
node;
for(var j=0, jl=classes.length; j<jl; j+=1){
classesToCheck += "[contains(concat(' ', @class, ' '), ' " + classes[j] + " ')]";
}
try {
elements = document.evaluate(".//" + tag + classesToCheck, elm, namespaceResolver, 0, null);
}
catch (e) {
elements = document.evaluate(".//" + tag + classesToCheck, elm, null, 0, null);
}
while ((node = elements.iterateNext())) {
returnElements.push(node);
}
return returnElements;
};
}
else {
getElementsByClassName = function (className, tag, elm) {
tag = tag || "*";
elm = elm || document;
var classes = className.split(" "),
classesToCheck = [],
elements = (tag === "*" && elm.all)? elm.all : elm.getElementsByTagName(tag),
current,
returnElements = [],
match;
for(var k=0, kl=classes.length; k<kl; k+=1){
classesToCheck.push(new RegExp("(^|\\s)" + classes[k] + "(\\s|$)"));
}
for(var l=0, ll=elements.length; l<ll; l+=1){
current = elements[l];
match = false;
for(var m=0, ml=classesToCheck.length; m<ml; m+=1){
match = classesToCheck[m].test(current.className);
if (!match) {
break;
}
}
if (match) {
returnElements.push(current);
}
}
return returnElements;
};
}
return getElementsByClassName(className, tag, elm);
};
/**/

/**/
//ripping off the jquery domready check...
(function(){
var DomReady = window.DomReady = {};
// Everything that has to do with properly supporting our document ready event. Brought over from the most awesome jQuery.
var userAgent = navigator.userAgent.toLowerCase();
// Figure out what browser is being used
var browser = {
version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
safari: /webkit/.test(userAgent),
opera: /opera/.test(userAgent),
msie: (/msie/.test(userAgent)) && (!/opera/.test( userAgent )),
mozilla: (/mozilla/.test(userAgent)) && (!/(compatible|webkit)/.test(userAgent))
};
var readyBound = false;
var isReady = false;
var readyList = [];
// Handle when the DOM is ready
function domReady() {
// Make sure that the DOM is not already loaded
if(!isReady) {
// Remember that the DOM is ready
isReady = true;
if(readyList) {
for(var fn = 0; fn < readyList.length; fn++) {
readyList[fn].call(window, []);
}
readyList = [];
}
}
};
// From Simon Willison. A safe way to fire onload w/o screwing up everyone else.
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (oldonload) {
oldonload();
}
func();
}
}
};
// does the heavy work of working through the browsers idiosyncracies (let's call them that) to hook onload.
function bindReady() {
if(readyBound) {
return;
}
readyBound = true;
// Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
if (document.addEventListener && !browser.opera) {
// Use the handy event callback
document.addEventListener("DOMContentLoaded", domReady, false);
}
// If IE is used and is not in a frame
// Continually check to see if the document is ready
if (browser.msie && window == top) (function(){
if (isReady) return;
try {
// If IE is used, use the trick by Diego Perini
// http://javascript.nwbox.com/IEContentLoaded/
document.documentElement.doScroll("left");
} catch(error) {
setTimeout(arguments.callee, 0);
return;
}
// and execute any waiting functions
domReady();
})();
if(browser.opera) {
document.addEventListener( "DOMContentLoaded", function () {
if (isReady) return;
for (var i = 0; i < document.styleSheets.length; i++)
if (document.styleSheets[i].disabled) {
setTimeout( arguments.callee, 0 );
return;
}
// and execute any waiting functions
domReady();
}, false);
}
if(browser.safari) {
var numStyles;
(function(){
if (isReady) return;
if (document.readyState != "loaded" && document.readyState != "complete") {
setTimeout( arguments.callee, 0 );
return;
}
if (numStyles === undefined) {
var links = document.getElementsByTagName("link");
for (var i=0; i < links.length; i++) {
if(links[i].getAttribute('rel') == 'stylesheet') {
numStyles++;
}
}
var styles = document.getElementsByTagName("style");
numStyles += styles.length;
}
if (document.styleSheets.length != numStyles) {
setTimeout( arguments.callee, 0 );
return;
}
// and execute any waiting functions
domReady();
})();
}
// A fallback to window.onload, that will always work
addLoadEvent(domReady);
};
// This is the public function that people can use to hook up ready.
DomReady.ready = function(fn, args) {
// Attach the listeners
bindReady();
// If the DOM is already ready
if (isReady) {
// Execute the function immediately
fn.call(window, []);
} else {
// Add the function to the wait list
readyList.push( function() { return fn.call(window, []); } );
}
};
bindReady();
})();
/**/


// THE DRAG FUNCTION:
var drag = function (){
var get_style = function (element,styleProp){
if (element.currentStyle){
var y = element.currentStyle[styleProp];
}
else if(window.getComputedStyle){
var y = document.defaultView.getComputedStyle(element,null).getPropertyValue(styleProp);
}
return y;
}
var get_left = function (el){
xPos = el.offsetLeft;
tempEl = el.offsetParent;
while (tempEl != null) {
xPos += tempEl.offsetLeft;
tempEl = tempEl.offsetParent;
}
return xPos;
}
var get_top = function (el){
yPos = el.offsetTop;
tempEl = el.offsetParent;
while (tempEl != null) {
yPos += tempEl.offsetTop;
tempEl = tempEl.offsetParent;
}
return yPos;
}
var target,start_x,start_y,original_x,original_y,original_checked,original_onclick;
var start = function (element){
target=element;
if(target.type=="radio" || target.type=="checkbox"){
//store initial radio and check box status to check against later
original_checked=target.checked;
}
else if(target.type=="submit" || target.type=="button" || target.type=="reset"){
//if the target is a submit or button input, we capture any existing onclick and replace it with return false; to stop form submission and function rendering (pending a later check to see if we have moved the element or not).
if(target.onclick){
original_onclick=target.onclick;
}
target.onclick=function(){return false;};
target.setAttribute('onclick','return false;');
}
original_x = get_left(target);
original_y = get_top(target);
var this_style=target.style;
this_style.position="absolute";
this_style.zIndex="1";
this_style.left = original_x +"px";
this_style.top = original_y +"px";
this_style.cursor = "move";
document.onmousemove = grab_x_y;
}
var end = function (){
try{
target.style.removeProperty('cursor');
}
catch(err){
target.style.cursor='';
}
if(((target.type=="radio" && original_checked==false) || target.type=="checkbox") && parseInt(get_left(target))!=original_x && parseInt(get_top(target))!=original_y){
//restore initial radio and check box status if the element has been moved from its spot at the start of the drag...
var fix_me=target;
var data=original_checked;
setTimeout(function(){fix_me.checked=data;},10);
original_checked=null;
}
else if((target.type=="submit" || target.type=="button" || target.type=="reset")){
//if the target is a submit or button input, we replace the original onclick event (if applicable) then determine if a click should be simulated or not based on movement of the element.
if(original_onclick){
var fix_me = target;
var data = original_onclick;
setTimeout(function(){fix_me.onclick=data;},10);
}
else{
var fix_me = target;
setTimeout(function(){fix_me.onclick='';fix_me.removeAttribute('onclick');},11);
}
if(parseInt(get_left(target))==original_x && parseInt(get_top(target))==original_y){
//if we haven't moved, we go ahead and send a click command to the target to activate it...
var click_me = target;
setTimeout(function(){click_me.click();},11);
}
original_onclick=null;
}
target=null;
document.onmousemove = grab_x_y;
}
var grab_x_y = function (evt){
start_x=parseInt(mouseX(evt));
start_y=parseInt(mouseY(evt));
if(target){
document.onmousemove = follow;
}
}
// Simple follow the mouse script
var mouseX = function (evt) {if (!evt) evt = window.event; if (evt.pageX) return evt.pageX; else if (evt.clientX)return evt.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft); else return 0;}
var mouseY = function (evt) {if (!evt) evt = window.event; if (evt.pageY) return evt.pageY; else if (evt.clientY)return evt.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop); else return 0;}
var follow = function (evt) {
if (target) {
var obj = target.style;
obj.left = (original_x + parseInt(mouseX(evt)) - start_x) + 'px';
obj.top = (original_y + parseInt(mouseY(evt)) - start_y) + 'px';
}
}
document.onmousedown = grab_x_y;
return{
get_style:get_style,
start:start,
end:end,
get_top:get_top,
get_left:get_left
};
}();


/**/
//calling the jquery ripoff domready function to attach the drag function to draggable elements within the page...
DomReady.ready(function(){
if(document.getElementsByClassName){
var draggables = document.getElementsByClassName('draggable');
}
else{
var draggables = getElementsByClassName('draggable');
}
for(i=0;i<draggables.length;i++){
//add placeholders so things don't shift when we move the draggable items
var placeholder=document.createElement('div');
placeholder.style.width = draggables[i].offsetWidth + "px";
placeholder.style.height = draggables[i].offsetHeight + "px";
if(drag.get_style(draggables[i],'display')=="inline"){
placeholder.style.display = "inline-block";
placeholder.style.height = "auto";
}
//account for margins (which aren't accounted for with offsetWidth and offsetHeight)
if(drag.get_style(draggables[i],'margin')){
placeholder.style.margin=drag.get_style(draggables[i],'margin');
}
if(drag.get_style(draggables[i],'margin-top')){
placeholder.style.marginTop=drag.get_style(draggables[i],'margin-top');
}
if(drag.get_style(draggables[i],'margin-right')){
placeholder.style.marginRight=drag.get_style(draggables[i],'margin-right');
}
if(drag.get_style(draggables[i],'margin-bottom')){
placeholder.style.marginBottom=drag.get_style(draggables[i],'margin-bottom');
}
if(drag.get_style(draggables[i],'margin-left')){
placeholder.style.marginLeft=drag.get_style(draggables[i],'margin-left');
}
//add triggers
draggables[i].onmousedown=function(){drag.start(this);};
draggables[i].onmouseup=function(){drag.end();};
//add absolute positioning
draggables[i].style.position="absolute";
draggables[i].style.top = drag.get_top(draggables[i]) + "px";
draggables[i].style.left = drag.get_left(draggables[i]) + "px";
draggables[i].parentNode.insertBefore(placeholder,draggables[i]);
}
});
/**/
</script>
<style type="text/css">
*{margin:0;padding:0;}
body{padding:10px;}
h1{padding-bottom:20px;}
input,select,textarea{display:block;margin-bottom:5px;}
span.draggable{padding:0px 6px;border:1px solid #c4c4c4;background-color:#efefef;}
#test{width:400px;}
textarea{resize:none;}
</style>
</head>
<body>
<form action="" method="post" onsubmit="return false;">
<div>
<h1><span class="draggable">Drag and Drop</span> Test...</h1>
<input type="text" class="draggable" />
<input type="radio" name="radio_1" class="draggable" />
<input type="checkbox" name="check_1" class="draggable" />
<textarea name="textarea_1" class="draggable" style="border:1px solid #000;" rows="2" cols="20"></textarea>
<select name="selection_1" class="draggable"><option>1</option><option>2</option></select>
<select name="selection_2" class="draggable" multiple="multiple"><option>1</option><option>2</option></select>
<input type="button" class="draggable" value="Alert" onclick="alert('Woohoo! You clicked me!');" />
<input type="reset" class="draggable" value="Reset" />
<input type="submit" class="draggable" onclick="alert('This form would be submitted now if not for the \'return false;\' \nin the form\'s onsubmit attribute...');" value="submit" />
</div>
</form>
</body>
</html>

Add a class of "draggable" to anything that you want to make draggable.

This has weaknesses. The main one (that I can see) is that your draggable items will need to be block display to avoid wrecking your page layout.

Any inline displayed items will be supplanted with <div> element placeholders which are block level and will upset your page layout if they are used to replace inline elements.

Update... [I]I have added code to allow for inline element replacement as well as code to prevent buttons, radio elements, and checkboxes from being activated by dragging them. As far as I know, the only thing this script needs now is something to prevent text selection from occurring during dragging. After that it would be pretty solid...

wisar1111
12-14-2011, 12:02 PM
My approach was capturing mousedown on the document and for some reason this was causing some weird stuff to happen on some elements. Also explained why a disabled element would not register! I have not implemented this change yet but it looks like simply capturing the initial mousedown at the element will fix me while preserving all my other code.

Thanks again, great response!
Wisar1111



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum