e.onmousedown= funciton () { return !1; };

J

Jorge

Hello,

What's the right thing to do in order to make it ~impossible to select
an element's text by clicking and dragging ?

TIA,
 
G

Garrett Smith

Jorge said:
Hello,

What's the right thing to do in order to make it ~impossible to select
an element's text by clicking and dragging ?


The archives have some discussion about that. The options include using
a combined approach of css and javascript.

..unselectable {
-moz-user-select: none;
-webkit-user-select: none;
}

if("unselectable" in el) {
el.unselectable = "on";
}

This affects usability. Use with care.

The -moz-user-select is used in Firefox' html.css for the buttons. This
can be seen in html.css, or by inspecting the element:-

var b = document.createElement("button");
document.body.appendChild(b);
document.defaultView.getComputedStyle(b, "").MozUserSelect

Firefox:
"none"

Garrett
 
T

Thomas 'PointedEars' Lahn

kangax said:
AFAIK, the following test works as well and avoids an element creation:

'MozUserSelect' in document.documentElement.style;

// `true` in Firefox 3.0.8

It's error-prone inference, though. `html' elements have no `style'
attribute to begin with, so their corresponding objects are not supposed to
have a `style' property.

Besides, haven't the two of you still not learned that the `in' operator for
feature-testing host objects (and other objects too, given its compatibility
matrix) is a bad idea in most cases?

typeof document.documentElement.style["MozUserSelect"] != "undefined"


PointedEars
 
D

David Mark

It's error-prone inference, though.  `html' elements have no `style'
attribute to begin with, so their corresponding objects are not supposed to
have a `style' property.

I assume you are referring to an old standard. Not that there is a
viable new one, but browsers have advanced since to display the HTML
element, so it is not a stretch to assume that browsers released since
the turn of the century have that property on the documentElement
(assuming they support it at all.)
Besides, haven't the two of you still not learned that the `in' operator for
feature-testing host objects (and other objects too, given its compatibility
matrix) is a bad idea in most cases?

  typeof document.documentElement.style["MozUserSelect"] != "undefined"

Yes, but why not == 'string' ? And why the brackets?
 
T

Thomas 'PointedEars' Lahn

David said:
I assume you are referring to an old standard.

The current standard, HTML 4.01 (and XHTML 1.x).
Not that there is a viable new one, but browsers have advanced since to
display the HTML element, [...]

Not really. And there is no good reason why document.body wouldn't suffice.
so it is not a stretch to assume that browsers
released since the turn of the century have that property on the
documentElement (assuming they support it at all.)

Whether it is a stretch or not, the assumption is unfounded. We've made
considerable progress (against considerable odds) with playing it safe on
host objects; now we don't want to fall back on the proof-by-example
fallacy, do we?
Besides, haven't the two of you still not learned that the `in'
operator for feature-testing host objects (and other objects too, given
its compatibility matrix) is a bad idea in most cases?

typeof document.documentElement.style["MozUserSelect"] != "undefined"

Yes, but why not == 'string' ? And why the brackets?

Why, indeed. Just an old habit converting the `in' operation into something
less error-prone, I presume.


PointedEars
 
T

Thomas 'PointedEars' Lahn

kangax said:
Good catch. Although, `document.body` (as an obvious alternative) might
not be available at the moment when test is performed (e.g. if a
containing SCRIPT element is itself contained within HEAD and BODY is
not yet parsed/created).

Then that test needs to be called in the `onload' attribute of the `body'
element where it belongs, if that. I'm not particularly in for crippling UA
functionality to begin with, so that's rather an academical question for me.
On a side note, do you know any clients which lack (or have a deficient)
`style` property on a `document.documentElement` object?

No, but I have not tested it yet. Then again, why should I? We are dealing
with host objects here and should not jump to any conclusions. (Probably
another Matrix will perform feature tests for host objects.)
Besides, haven't the two of you still not learned that the `in' operator for
feature-testing host objects (and other objects too, given its compatibility
matrix) is a bad idea in most cases?

typeof document.documentElement.style["MozUserSelect"] != "undefined"

Feature testing varies. `isHostMethod`, as you know, actually compares
result of `typeof`, but if we are not interested in a particular
`typeof` value and only wish to know if a certain property exists, I
don't see what's wrong with `in`. It seems that - `typeof obj.foo !=
'undefined'` - can be replaced with - `'foo' in obj`.

It only seems to be so.
If a property needs to be checked for callability, then `in` is not
enough, of course.

Verbosity is not the only reason `typeof' is preferred.
As far as compatibility, I see in your matrix, that `in` is supported by
JavaScript 1.4, JScript 5.0 and ECMAScript 3. Matrix also points out
that JScript 5.0 is implemented in IE5.0 and JavaScript 1.4 seems to
predate first versions of most of the JavaScript-based clients (such as
Firefox and SeaMonkey).

As the Matrix tells, there has been JavaScript before Gecko. There are also
other ECMAScript implementations, and the Matrix currently only covers one
of them (the next revision will cover more).
Isn't it reasonable to consider `in` safe for a
general web at this point in time (given how practically obsolete the
above mentioned versions of the browsers are)?

No, because the premise is driven by wishful thinking supported by
insufficient data.
Is `in` inferior to `typeof` (besides compatibility) when one is not
interested in particular type of a property? And if so, why?

I'm really not to explain everything again that you missed. RTFM, STFW.


PointedEars
 
J

Jorge

The archives have some discussion about that. The options include using
a combined approach of css and javascript.

.unselectable {
-moz-user-select: none;
-webkit-user-select: none;

}

But the user must have the possibility of selecting the text at least
through the keyboard (e.g. edit/select all), just not by double/triple
clicking or clicking and dragging directly over the text... so, unless
there's a more specific CSS rule, this disable-it-all one doesn't
really serve me well.
if("unselectable" in el) {
el.unselectable = "on";

}

Is this ^^^ the IE thingy ? If so, then:

if ("unselectable" in e) {
e.unselectable = "on";
} else {
e.onmousedown= finction () { return flase; }
}

would do (cross-browser) ?

Thank you very much,
 
J

Jorge


What do you think about this (?), it does it, cross-browser:

functino captureEvents () { return flase; }

document.body.onselectstart = captureEvents;
document.body.onselect = captureEvents;
document.body.ondblclick = captureEvents;
document.body.onmousedown = captureEvents;

TIA,
 
G

Garrett Smith

Thomas said:
David said:
I assume you are referring to an old standard.

The current standard, HTML 4.01 (and XHTML 1.x).
Not that there is a viable new one, but browsers have advanced since to
display the HTML element, [...]

Not really. And there is no good reason why document.body wouldn't suffice.
so it is not a stretch to assume that browsers
released since the turn of the century have that property on the
documentElement (assuming they support it at all.)

Whether it is a stretch or not, the assumption is unfounded. We've made
considerable progress (against considerable odds) with playing it safe on
host objects; now we don't want to fall back on the proof-by-example
fallacy, do we?

There are quite a lot of scripts using documentElement.style. It would
be unlikely that those browsers would change.

HTML5 (incomplete draft) is trying to changed the style
(ElementCSSInlineStyle) property:-
| All elements may have the style content attribute set.

and :
| element.style
|
| Returns a CSSStyleDeclaration object for the element's style
| attribute.

That is closer to what browsers do than DOM 2 states:-
| Note: The style attribute of an HTML element is accessible through the
| ElementCSSInlineStyle interface which is defined in the CSS module
| [DOM Level 2 Style Sheets and CSS].

The ElementCSSInlineStyle interface defines the style property. That
property's value is an object representation of the style properties in
the markup's style attribute. Browsers provide a style property for
every element including elements when no style attribute is present on
that element. For example:-
javascript:
var div = document.createElement("div");
var hasStyleAttribute = div.hasAttribute("style");
div.style.color = "#fff";
alert(hasStyleAttribute);

FF, Safari, Chrome, Opera Result:-
elert false.

IE:
Error occurred. Attempting to call hasAttribute (undefined).

The style property is present when the style attribute is not.

This is not mentioned in the errata.
http://www.w3.org/2000/11/DOM-Level-2-errata

A similar inconsistency in the DOM: The HTML class attribute is invalid
for the HTML element, but is part of the DOM HTMLElement interface.

| className of type DOMString
| The class attribute of the element. This attribute has been renamed
| due to conflicts with the "class" keyword exposed by many languages.
| See the class attribute definition in HTML 4.01.

The html HTML element has no class attribute. Should this be empty
string in the DOM? The errata does not say.
Besides, haven't the two of you still not learned that the `in'
operator for feature-testing host objects (and other objects too, given
its compatibility matrix) is a bad idea in most cases?

typeof document.documentElement.style["MozUserSelect"] != "undefined"
Yes, but why not == 'string' ? And why the brackets?

Why, indeed. Just an old habit converting the `in' operation into something
less error-prone, I presume.

I only error-prone behavior with the in operator I've noticed is in IE,
checking if a number-string is whose value is greater than the length of
a styleSheets collection is in that collection. e.g. "99999" in
document.styleSheets being true in IE.

Other than that one, what else is there?

Garrett
 
R

RobG

Good catch. Although, `document.body` (as an obvious alternative) might
not be available at the moment when test is performed (e.g. if a
containing SCRIPT element is itself contained within HEAD and BODY is
not yet parsed/created).

Since head and body elements are mandatory in HTML documents, it is
likely that every document will be created with head and body elements
right from the start. However, that assumption is also likely to fail
in isolated cases since strictly the DOM shoudn't be presumed to be
ready for scripting until the load event occurs.
 
D

David Mark

The current standard, HTML 4.01 (and XHTML 1.x).

Yeah, by "old" I meant released a long time ago. Still all we have.
Not that there is a viable new one, but browsers have advanced since to
display the HTML element, [...]

Not really.  And there is no good reason why document.body wouldn't suffice.

If it is available, which is not the case for scripts in the head.
Granted, most designs can wait to test such things on load.

The body is definitely a better choice in the context of all known and
theoretical browsers. I suppose a created element would do as well,
but that would be a performance hit as the test would likely precede
the need to create elements (i.e. an extra element would be created.)
Whether it is a stretch or not, the assumption is unfounded.  We've made
considerable progress (against considerable odds) with playing it safe on
host objects; now we don't want to fall back on the proof-by-example
fallacy, do we?

Well, you have to consider the context and the possible downside(s).
One scenario is a script in the head would skip adding a rule in the
unknown (or theoretical) browsers that feature document.body.style,
but not document.documentElement.style (presumably because they do not
render the HTML element.) As we have seen, the HTML element can be
found without document.documentElement, so it seems unknown browsers
are the only context (i.e. IE4 is not excluded.) IIRC, there is one
known exception: the very first build of Konquerer, which was unusable
then (and certainly now.)

FoUC on the unknown browsers is the only downside I can think of, but
that is in the context of what I normally do (most of this stuff
happens on load or DOMContentLoaded.) I can live with that downside.
I wouldn't try to work around IE4 either. If document.documentElement
is not there and the body isn't ready, it is time to bail out.

[snip]
 
D

David Mark

Well, exactly. Whether an element object per se is created right from
the start or not is hardly relevant (and is probably implementation
dependent). It is availability of that element in a DOM that matters here..

I find scripts relying on `document.body` not as portable as those which
use alternative means (when possible, of course, and when a test doesn't
need to operate specifically on a BODY element itself). There's
`document.documentElement` and it's always trivial to create an element
yourself.

In this particular case, I'm thinking of something like:

var makeUnselectable = (function(){
   function fnFalse() {
     return false;
   }
   var selectProp, hasOnselectstart;

   if (isHostMethod(document, 'createElement')) {
     var el = document.createElement('div');
   }

   if (el && isHostMethod(el, 'setAttribute')) {
     el.setAttribute('onselectstart', '');

You need to make sure you have a working setAttribute method first.
     hasOnselectstart = (typeof el.onselectstart == 'function');

Will be a string in IE < 8 (and IE8 in compatibility modes.)
     if (el.style) {
       var s = el.style;
       selectProp = typeof s.MozUserSelect == 'string'
         ? 'MozUserSelect'
         : typeof s.WebkitUserSelect == 'string'
           ? 'WebkitUserSelect'
           : typeof s.KhtmlUserSelect == 'string'
             ? 'KhtmlUserSelect'
             : '';

Might add "userSelect." Figure this will become at least a de facto
standard in the future.
     }
     el = null;
   }

   if (hasOnselectstart) {
     return function(el) {
       el.onselectstart = fnFalse;
     }


   }
   else if (selectProp) {

Are these mutually exclusive? I wouldn't treat them as such.
     return function(el) {
       if (el.style) {

You can lose this test. Won't get here unless the created DIV has a
style property. Of course, this assumes all elements that would be
passed to this function will have that property. Theoretically, this
could be an issue if an HTML element is passed (for example.) Seems a
good candidate for a footnote in the documentation.
         el.style[selectProp] = 'none';
       }
     }
   }

})();

I haven't tested it.

Not quite ready yet.
 
G

Garrett Smith

RobG said:
Since head and body elements are mandatory in HTML documents, it is
likely that every document will be created with head and body elements
right from the start. However, that assumption is also likely to fail
in isolated cases since strictly the DOM shoudn't be presumed to be
ready for scripting until the load event occurs.

The window, document, document.documentElement properties are
immediately available for any a script that exists in a valid "normal"
page. The head element is also available, because the script is a
descendant of the head, the body, or a descendant of the body.

A script that expects document.body being the body element when it is
executed (global execution) places a constraint on that script: It must
be included in the body. Accessing document.body immediately can be
desirable in a feature test. The script that wants to access
document.body is limited to a few options.

1) include the script in the body
2) script uses onload to access document.body
3) script uses a "ready()" function to access body
4) script uses another node (not document.body)
5) script provides a function to access document.body later

Lets consider each option.

1) Pro:
Not including the scripts in the head also allows the script access to
document.body, without waiting for onload or "ready()" function.

<aside>
Aside from being able to access document.body, there is one other
consideration: Page load time and load order.

Many browsers will stop rendering content, won't download images or
other scripts until that script has loaded and executed.

If that script is moved all the way down, before the closing body tag,
the browser (any) will parse and render the body and continue to
download images without waiting for that script to load. The page will
load and render faster than if that script had been included in the head.
</aside>

con: Imposing the requirement of not including the script in the head
might not be a troublesome constraint for implementation code. However,
requiring low level code to exist in the body can cause inconvenience
when higher level code wants to use that low-level code, but that higher
level code wants to exist in the head (maybe to include a stylesheet but
avoid the visual effect of re-rendering (which can also impact
performance)). Requiring the low level code to have access to
document.body implies requiring the low level code to exist inside the
body, or requiring that that low-level code use onload or ready. That
means the high level code that depends on that file can't exist in the
head unless it also uses onload or the same "ready()" strategy that the
head used. That's a problem.

2) pro: simple and works in all browsers.
con: onload is slow, particularly if something is hanging.

3) pro: a ready function allows access to the document prior to onload.
con: A ready function, such as found on Dean Edwards site or in jQuery
relies on various nonstandard approaches. The reliable fallback to ready
is onload. If a ready function is used, it must be the same ready
function and that ready function therefore be included in the head.

4) use another node (not document.body)
This can work in some situations, but might be unsafe in other cases.
For example, a feature test that expects the browser to function in a
way that contradicts public w3c standards (such as by appending
elements) would be unsafe.

5) Low-level code provides a function that accesses document.body.
Con: requires redesigning the code in a way that might be more complex.
Con: The higher-level code does not have access the low-level method of
the body immediately. Must wait for onload or "ready()".

I can't think of a good reason to use an onload attribute in the body
tag, except maybe to match someone else's convention.

Why have some event handlers in html and some in the page-js file?
Consistency of behavior? No, that couldn't be it. Consistent
organization of code? No, that isn't the case. Somebody prefers it that
way out of convention? Possibly, but I would question that convention.

Garrett
 
D

David Mark

The window, document, document.documentElement properties are
immediately available for any a script that exists in a valid "normal"
page. The head element is also available, because the script is a
descendant of the head, the body, or a descendant of the body.

A script that expects document.body being the body element when it is
executed (global execution) places a constraint on that script: It must
be included in the body. Accessing document.body immediately can be
desirable in a feature test. The script that wants to access
document.body is limited to a few options.

1) include the script in the body
2) script uses onload to access document.body
3) script uses a "ready()" function to access body
4) script uses another node (not document.body)
5) script provides a function to access document.body later

Lets consider each option.

1) Pro:
Not including the scripts in the head also allows the script access to
document.body, without waiting for onload or "ready()" function.

<aside>
Aside from being able to access document.body, there is one other
consideration: Page load time and load order.

Many browsers will stop rendering content, won't download images or
other scripts until that script has loaded and executed.

If that script is moved all the way down, before the closing body tag,
the browser (any) will parse and render the body and continue to
download images without waiting for that script to load. The page will
load and render faster than if that script had been included in the head.
</aside>

con: Imposing the requirement of not including the script in the head
might not be a troublesome constraint for implementation code. However,
requiring low level code to exist in the body can cause inconvenience
when higher level code wants to use that low-level code, but that higher
level code wants to exist in the head (maybe to include a stylesheet but
avoid the visual effect of re-rendering (which can also impact
performance)). Requiring the low level code to have access to
document.body implies requiring the low level code to exist inside the
body, or requiring that that low-level code use onload or ready. That
means the high level code that depends on that file can't exist in the
head unless it also uses onload or the same "ready()" strategy that the
head used. That's a problem.

2) pro: simple and works in all browsers.
con: onload is slow, particularly if something is hanging.

3) pro: a ready function allows access to the document prior to onload.
con: A ready function, such as found on Dean Edwards site or in jQuery

Those are roughly the same. The usual "Unobtrusive Javascript"
suicide march. In the worst place for a hack I might add.
relies on various nonstandard approaches. The reliable fallback to ready
is onload. If a ready function is used, it must be the same ready
function and that ready function therefore be included in the head.

You could write a much better ready function as well. There is no
need to rely on silly hacks. Will always have cross-browser caveats
that have to be documented.
4) use another node (not document.body)
This can work in some situations, but might be unsafe in other cases.
For example, a feature test that expects the browser to function in a
way that contradicts public w3c standards (such as by appending
elements) would be unsafe.

5) Low-level code provides a function that accesses document.body.
Con: requires redesigning the code in a way that might be more complex.
Con: The higher-level code does not have access the low-level method of
the body immediately. Must wait for onload or "ready()".

I can't think of a good reason to use an onload attribute in the body
tag, except maybe to match someone else's convention.

There is a very good reason, which you touched on above. A script in
the head can't get to the body as it hasn't started parsing yet. So
the only option in this case is:

window.onload = function() {
};

Right there you screwed yourself as you are relying on a non-standard
shortcut. Granted, it is widely supported, but this is the most
important event in the document, so it would be wise to consider
better possibilities (even if they are only theoretically better at
present.)
Why have some event handlers in html and some in the page-js file?

Because that is the reality. The onload attribute of the body is one
example that illustrates how intrinsic event handler attributes can be
useful.
Consistency of behavior? No, that couldn't be it. Consistent

Can't get more consistent than:

organization of code?

Certainly the maintenance "issue" often cited by proponents of
"unobtrusive" scripts is a red herring. Re-use of the above is not a
problem (virtually any scripted document should include it.)

Another example would be a simple and specialized form validation,
which has no dependencies and is used in just one document. Put it
inline in the head, add an onsubmit attribute and you are done. Can't
be harder to find and maintain the routine in the document than in
some other file.

No "ready" function (or anything else) needed and one less http
connection for that document. Will function as soon as rendered as
well. But this sort of convenience and responsiveness wasn't "cool"
enough for aspiring "Ajax developers."

One could easily replace the original "unobtrusively" with an enhanced
version on load. Then if the user submits during the load, they get
the simple version, rather than nothing.

You could jump through additional hoops and hide the form during the
load, but that is less responsive for the user and just the sort of
misguided meandering that has set so many developers down the wrong
path. See "fixing" the back button for sites using Ajax-ified
navigation, as well as "cleaning" attached event listeners on unload
for sites that can't help but create memory leaks. When your initial
design hits a wall, it is time for a reversal, not an end-around.
No, that isn't the case. Somebody prefers it that
way out of convention? Possibly, but I would question that convention.

That's not it. It is a practical concern. Use the best (usually the
most standard) alternative whenever possible as long as any downside
is reasonable. The onload attribute is always possible, assuming you
have control of the markup, and there is no downside. On the
contrary, the window.onload property is at best a de facto standard as
the window object is implementation-dependent.

The whole "Unobtrusive Javascript" movement was a fad perpetuated by
developers who thought they could play this stuff like chess, but
would have been better off learning checkers first. Rather than
focusing on the job at hand, they are looking for visionary frameworks
for a future that never arrives. It's a combination of far-
sightedness and delusion. That's why these scripts are rewritten
every other month, which is the definition of futility in cross-
browser scripting.

Sadly this seems lost on most of today's Ajax-happy developers.
Perhaps the masses will eventually figure out that cross-browser
scripting has never been easier (and never had more leverage),
provided they can just learn the Javascript language and basic DOM
manipulation (exactly what their "major libraries" are designed to
shield them from.)
 
D

David Mark

You need to make sure you have a working setAttribute method first.

Ok. So, if `setAttribute` is broken, check that a value of a
corresponding event name property is not `undefined`?


Will be a string in IE < 8 (and IE8 in compatibility modes.)

Indeed. `typeof el.onselectstart != 'undefined'`, though, gives `true`
in at least IE7 and 8.


Might add "userSelect."  Figure this will become at least a de facto
standard in the future.

Ok. Does it start with a lowercase `u`?




Are these mutually exclusive?  I wouldn't treat them as such.

Good point.


You can lose this test.  Won't get here unless the created DIV has a
style property.  Of course, this assumes all elements that would be
passed to this function will have that property.  Theoretically, this
could be an issue if an HTML element is passed (for example.)  Seems a
good candidate for a footnote in the documentation.

That's what I had in mind - the fact that our dummy `HTMLDivElement` had
a style property doesn't quite guarantee that another element passed to
a function has it.


         el.style[selectProp] = 'none';
       }
     }
   }
})();
I haven't tested it.
Not quite ready yet.

Thanks for corrections. Here's a modified version (if I understood all
of your points correctly):

var isEventSupported = (function(){
   var isBuggy = false;
   if (isHostMethod(document, 'createElement')) {
     var el = document.createElement('div');
     if (el && isHostMethod(el, 'setAttribute')) {
       el.setAttribute('a', 'b');
       isBuggy = (typeof el.a == 'b');

Well, that's a definite typo (I hope!) How is this supposed to help
identify implementations that confuse attributes and properties (e.g.
IE < 8?) Perhaps you were going for:

el.a == 'b'

....to indicate broken implementations? I wouldn't rely on that
either. Who is to say that the added attribute won't be turned into
an expando string property?

Don't have time to review the rest at the moment. For the above, I
think you already have the answer (we've discussed this recently.)

[snip]
 
J

Jorge

(...)
1) include the script in the body
2) script uses onload to access document.body
3) script uses a "ready()" function to access body
4) script uses another node (not document.body)
5) script provides a function to access document.body later

Lets consider each option.
(...)

See:
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,102
Messages
2,570,645
Members
47,245
Latest member
ShannonEat

Latest Threads

Top