A Brief Review of jQuery 1.5

D

David Mark

White on black with blue links. Well, turns out they aren't links.
The blue underlined text can't be clicked as some unfortunately
positioned tooltips fade in over top of them (and sometimes partially
off-screen).

* Lightweight Footprint
* CSS3 Compliant
* Cross-browser

The first point it meaningless without context. Compared to starting
with nothing, it's 70K of extra baggage.

The latter two points are simply false. They are qualified by the
tooltips as "Supports CSS 1 - 3 Selectors and More!" and a list of
selected browsers (so by definition, not cross-browser). Hard to
believe they had the gall to include IE in that list. :)

I'll just focus on one method this time as I'm tired of reading their
bullshit. This is attr's opposite:-

removeAttr: function( name, fn ) {
return this.each(function(){
jQuery.attr( this, name, "" );
if ( this.nodeType === 1 ) {
this.removeAttribute( name );
}
});
},

Same old confused nonsense. Can the documentation shed any light?

".removeAttr( attributeName ) Returns: jQuery"

Seems like they all return jQuery. :)

"Description: Remove an attribute from each element in the set of
matched elements.
version added: 1.0
..removeAttr( attributeName )"

No indication of what an attributeName might be. Oh wait, here it
is:-

"attributeName
An attribute to remove."

I find it hard to believe that it's an attribute. More likely a
string.

"The .removeAttr() method uses the JavaScript removeAttribute()
function, but it has the advantage of being able to be called directly
on a jQuery object and it accounts for different attribute naming
across browsers."

There's no such thing as a "JavaScript removeAttribute() function".
There is a DOM method, but the DOM has nothing to do with Javascript
(or any language). Got to figure the standard DOM method is better
documented than this thing.

And what of these alleged advantages? Calling it "directly on a
jQuery object" would seem like a 70K negative, considering the method
is available on element objects. Oh wait, I forgot the loop! :)

As for accounting for "different attribute naming across browsers", it
is clear that it does nothing of the sort.

The first line inside the loop is:-

jQuery.attr( this, name, "" );

That's just plain wrong. Setting a property or attribute of an
element will not remove an attribute. In fact, it might create one.
This code may throw an exception, add an attribute or change an
attribute's value, but it won't remove anything. It's purely a
mystical incantation (as is most of the attr method).

And yes, they've been told about that. These sorts of obvious
mistakes are ignored for years as voodoo code can only inspire so much
confidence. They do seem more than happy to tack on "cool" new
wrinkles at the drop of a hat though.

Then it silently fails in the case where the generic jQuery wrapper
contains something other than an element node:-

if ( this.nodeType === 1 ) {
this.removeAttribute( name );
}

That's counter-productive. If my app tried to remove an attribute
from a document node, I'd want to know about it immediately (in the
form of an exception). I don't get the feeling that the developers
have sufficient experience debugging Web applications. Otherwise they
wouldn't do things to make it harder on themselves.

And no, it didn't do anything to the name (in stark contrast to
attr). So this will do all sorts of unpredictable things in IE6/7/
Compat Mode. The documentation is simply wrong (and has been for as
long as I can remember) and the community has for years refused to fix
any of it (or even acknowledge there are problems). Considering that
"normalizing" such "offbeat" browsers as IE6/7 is one of the prime
excuses for jQuery's existence, it's hard to figure. The only theory
I have is that they don't fully understand their code, so are less
than confident to change it. They feel secure in one dark room, so
why traipse off to another? :)

As mentioned, there's plenty of reliable documentation for the
standard removeAttribute method. There is also reliable information
about the IE attribute problem, which has been around since at least
1999.

http://www.cinsoft.net/attributes.html

You would think that with as many reminders as the jQuery team has
received on these issues, they'd have it patched up by 2011.

But even if their rendition were perfect, would it really "simplify
DOM traversal" (from their front page) in any way? You could loop
over query results, removing an attribute of each element. Of course,
being tethered to a large, buggy, non-standard CSS selector engine can
hardly be seen as an advantage today. If you must use queries, learn
the Selectors API, stick with the basics and don't rely on it for
anything critical (as old IE users will be left out).

var el = document.getElementById('myid');
if (el) {
el.removeAttribute('onclick');
}

The test of the element reference (which may not be null for any
number of reasons) may seem like overkill in this example. Figure a
real application will have additional code in the - if - clause. As
the "myid" element is needed, it makes no sense to carry on without
it.

But if you insist on making debugging harder and the code more error-
prone, you can do chaining in JS:-

document.getElementById('myid').removeAttribute('onclick');

Too verbose? If you want to slow things down, you can write a one-
line wrapper for gEBI.

This is the sole jQuery example:-

Example:
Clicking the button enables the input next to it.
<!DOCTYPE html>

Have to use the latest cool doctype (no matter how invalid the
markup).

<html>
<head>
<script src="http://code.jquery.com/jquery-1.5.js"></script>

What a shining example for beginning developers. What's missing
there?

</head>

The HEAD isn't done.

<body>
<button>Enable</button>

That may be the worst button in history.

<input type="text" disabled="disabled" value="can't edit this" />
<script>

At least they are consistent. :)

$("button").click(function () {
$(this).next().removeAttr("disabled")
.focus()
.val("editable now");
});
</script>

</body>

And why so complicated? I just wanted to know how to remove an
attribute.

It's not as if this is an isolated example. As mentioned, attr is
similar voodoo. If it can't read/write/remove attributes, it's not
possible for it to simplify DOM anything (they only mention traversal,
but they likely meant manipulation as well). I've heard it argued
that these methods are irrelevant. Of course, one or both is used in
virtually every jQuery example out there. After all, setting
properties (not attributes) makes up the bulk of what most DOM scripts
do. There never was a problem with setting properties in IE (just
attributes), so jQuery created a huge problem where none existed.

And if the above is the extent of the formal documentation, you have
to wonder who keeps up the secret binder with compatibility charts
mapping the various jQuery versions to browser versions and modes.
Rather than trying to track down that elusive information (or God
forbid breaking down and testing the jQuery code), I suggest reading
the W3C's recommendation for the removeAttribute method. Know that
there is a well-known issue with some versions (and modes) of IE. See
my examples as jQuery is clearly no help in this department.

But ultimately, like a lot of things "enhanced" by jQuery (and
others), you may find you never need it. Most applications don't need
to do anything to attributes. If you find yourself setting or
removing an attribute, you are probably making a mistake and should
find the appropriate property (also listed on the W3C site).
Unfortunately, jQuery is one sort of application (a query engine) that
must at least read attributes properly.

http://www.cinsoft.net/slickspeed.html

As a quick glance in IE (particularly Compatibility mode) will tell
you, it predictably fails as a query engine. Considering the
underlying code, it would have taken a miracle to succeed. Doesn't do
much better in browsers outside those listed on jQuery's front page
either. IIRC, Sizzle (the query and lion's share of jQuery) does not
use the "advantageous" attribute methods at all. It uses its own
botched logic, which shouldn't come as any big surprise as, despite
the name and documentation, the attr method mostly returns property
values. And I'd be surprised if they improved on any of that in 1.5.
Perhaps someone else feels like testing that.

There's also the "addEvent" rendition that creates circular
references. And the "Live" thing is a mess of unwieldy hacks,
hopelessly tangled up with queries.

IIRC, passing "onclick" to attr will invoke jQuery's event methods
rather than doing anything to the attribute. So this:-

$('myid').removeAttr('onclick');

....will then do nothing. That's hardly intuitive and more
unfortunately the above will throw an exception in IE < 8 and
Compatibility Mode (due to the call to attr). They really haven't
improved on this removeAttribute thing at all. And they've done a
pretty poor job of documenting their thoughts on the matter.

And then there's the height/width methods (which attr also manages to
invoke) that make no sense, all of that ugly, over-complicated string
manipulation and RegExp abuse, incessant overloading, forgiving
interfaces, no select-one, etc., etc. Little of that has changed in
five years and much of it can't be improved due to the constraints of
the original design.

There's just no magic solution for cross-browser scripting. And if
there was, it wouldn't look anything like jQuery. I know that brings
down those who want to believe otherwise and angers those who would
sell you otherwise. But it was true five years ago and it couldn't be
more apparent today, particularly as the code is still nowhere close
to "mature" (a buzzword frequently associated with jQuery). Even the
worst sort of pessimist couldn't have predicted it would age as poorly
as it has (considering both technical and practical aspects). I think
"rotten" would be more apt at this point (and it was never fresh to
begin with).

You don't send a battery-powered mobile device a useless, complicated
and redundant 70K of junk code. Some of them won't cache it. Some
will choke on it. Virtually none will benefit from jQuery's take on
the Selectors API. Fewer still need jQuery's flailing IE hacks. It's
never been easier to write basic DOM manipulation code that runs
virtually anywhere, except for old versions of IE (and Compatibility
Mode). That's where conditional comments come in (to include
proprietary code and workarounds for old but still much-used
browsers). But jQuery can't be broken up, so now they are looking to
do for mobile what they've done for the desktop.

Are there really any takers for something that? These new devices
present much greater challenges than the old IE versions. So look
ahead five years or so...
 
R

RobG

Hey, a Valentine's Day gift to jQuery! You shouldn't have!!

[...]
"The .removeAttr() method uses the JavaScript removeAttribute()
function, but it has the advantage of being able to be called directly
on a jQuery object and it accounts for different attribute naming
across browsers."

There's no such thing as a "JavaScript removeAttribute() function".
There is a DOM method, but the DOM has nothing to do with Javascript
(or any language). Got to figure the standard DOM method is better
documented than this thing.

I think in general using the term "JavaScript" (or javascript or
whatever) is OK for ECMAScript + browser scripting.

And what of these alleged advantages? Calling it "directly on a
jQuery object" would seem like a 70K negative, considering the method
is available on element objects. Oh wait, I forgot the loop! :)

Yes, that seems to be a very big issue with all such libraries.
Developers who use them would rather dump a slab of mostly unused code
for the sake of writing some basic loops.
As for accounting for "different attribute naming across browsers", it
is clear that it does nothing of the sort.

The first line inside the loop is:-

jQuery.attr( this, name, "" );

That's just plain wrong. Setting a property or attribute of an
element will not remove an attribute. In fact, it might create one.
This code may throw an exception, add an attribute or change an
attribute's value, but it won't remove anything. It's purely a
mystical incantation (as is most of the attr method).

Yes, a pretty amazing piece if logic. Perhaps there was a browser
somewhere that barfed when trying to remove non-existent attributes or
properties (whatever jQuery is actually trying to do) so they figured
they'd add the property/attribute first.


[...]
This is the sole jQuery example:-

Example:
Clicking the button enables the input next to it.
<!DOCTYPE html>

Have to use the latest cool doctype (no matter how invalid the
markup).

HTML5 is accepted by the W3C validator, but it's too early to be using
it for general web pages.

<html>
<head>
<script src="http://code.jquery.com/jquery-1.5.js"></script>

What a shining example for beginning developers. What's missing
there?

Given an HTML5 doctype, I wouldn't stress over a missing type
attibute. I don't think it's ever been an issue.

</head>

The HEAD isn't done.


<body>
<button>Enable</button>

That may be the worst button in history.

It's valid though. ;-)

<input type="text" disabled="disabled" value="can't edit this" />

You missed one. The W3C seems to recommend using:

<!-- empty attributes -->
<input name=address disabled>
<input name=address disabled="">

<URL: http://dev.w3.org/html5/spec/Overview.html#a-quick-introduction-to-html
Though I can't understand why the W3C thinks empty attributes need an
inline value assigned at all, and setting it to empty string makes no
sense - it makes life more difficult.

<script>

At least they are consistent. :)

$("button").click(function () {
$(this).next().removeAttr("disabled")
.focus()
.val("editable now");});
</script>
</body>

And why so complicated? I just wanted to know how to remove an
attribute.

And you have to wonder why they are messing with attributes anyway
when setting the related property is so much more logical. I don't
know why it's preferred to:

It's not as if this is an isolated example. As mentioned, attr is
similar voodoo. If it can't read/write/remove attributes, it's not
possible for it to simplify DOM anything (they only mention traversal,
but they likely meant manipulation as well). I've heard it argued
that these methods are irrelevant. Of course, one or both is used in
virtually every jQuery example out there. After all, setting
properties (not attributes) makes up the bulk of what most DOM scripts
do. There never was a problem with setting properties in IE (just
attributes), so jQuery created a huge problem where none existed.

Yes. You only really have to deal with attributes in a few cases if
you are writing a general purpose library and you want to do things
like distinguish an attribute set to empty string and no attribute at
all. It is quite easy to design around the very few cases where this
is an issue and just use properties.

[...]
You don't send a battery-powered mobile device a useless, complicated
and redundant 70K of junk code.

Plus plugins.
Some of them won't cache it. Some
will choke on it. Virtually none will benefit from jQuery's take on
the Selectors API. Fewer still need jQuery's flailing IE hacks. It's
never been easier to write basic DOM manipulation code that runs
virtually anywhere, except for old versions of IE (and Compatibility
Mode). That's where conditional comments come in (to include
proprietary code and workarounds for old but still much-used
browsers). But jQuery can't be broken up, so now they are looking to
do for mobile what they've done for the desktop.

Are there really any takers for something that? These new devices
present much greater challenges than the old IE versions. So look
ahead five years or so...

Unfortunately it is an easy cop out for developers to write stuff
using some library, then when things fail they can blame the library
or plugin or lack thereof.
 
S

S.T.

Ahhh, David's bimonthly rambling about jQuery's handling of attributes.
Spring must be right around the corner...

I suspect you know this already, but the attr() methods are scheduled
for a rewrite for 1.6 - tentatively late April. Seems they are aware
there are problems but don't view them as critical. Coincidentally the
same opinion I have.
 
T

Thomas 'PointedEars' Lahn

RobG said:
I think in general using the term "JavaScript" (or javascript or
whatever) is OK for ECMAScript + browser scripting.

Well, you have a history of being prone to misleading overgeneralizations.
[...]
<!DOCTYPE html>
[…]
<html>
<head>
<script src="http://code.jquery.com/jquery-1.5.js"></script>

What a shining example for beginning developers. What's missing
there?

Given an HTML5 doctype, I wouldn't stress over a missing type
attibute. I don't think it's ever been an issue.

You are correct.
Yeah, something like <title>jQuery removeAttr example</title> would be
nice.

A `title' element is *mandatory*. All HTML Specifications, including the
upcoming one, are very clear about this.
Pardon?

You missed one. The W3C seems to recommend using:

<!-- empty attributes -->
<input name=address disabled>
<input name=address disabled="">

<URL:
http://dev.w3.org/html5/spec/Overview.html#a-quick-introduction-to-html

Though I can't understand why the W3C thinks empty attributes need an
inline value assigned at all, and setting it to empty string makes no
sense - it makes life more difficult.

The W3C is _not_ recommending anything there. You are referring to the
Editor's Draft, which only Ian Hickson, primarily of WHATWG, is to blame for
(including its ridiculous size, which, among other blunders, makes it hard
to render it the arguably second-fastest graphical browser, Chromium 9.0.x).

Further, both of you have missed that this document is HTML5, not XHTML5,
yet they are using XHTML syntax (the trailing slash). While that was
tolerable with HTML4, although never fully Valid, AIUI it no longer is going
to be acceptable in HTML5 (CMIIW).


PointedEars
 
E

Eric Bednarz

Thomas 'PointedEars' Lahn said:
Further, both of you have missed that this document is HTML5, not XHTML5,
yet they are using XHTML syntax (the trailing slash). While that was
tolerable with HTML4, although never fully Valid,

This statement is a little pregnant. Assuming the solidus in a context
where it can be parsed as NET (null end-tag) delimiter, the character ‘>’
will either be valid or not depending on whether or not the document type
declaration subset allows character data in that context.
AIUI it no longer is going
to be acceptable in HTML5 (CMIIW).

http://www.w3.org/TR/html5/syntax.html#start-tags
 
E

Eric Bednarz

RobG said:
HTML5 is accepted by the W3C validator, but it's too early to be using
it for general web pages.

I’ll bite. The SGML “document type declaration†production is

(mdo ("<!"),
"DOCTYPE",
+ps,
document type name,
?( +ps, external identifier ),
?( +ps, dso ("["), document type declaration subset, dsc ("]") ),
*ps, mdc (">"))

There. The ‘HTML5 Doctype’ available. 1986. Go figure.

Of course you couldn’t validate anything with neither ‘external
identifier’ nor ‘document type declaration subset’. The sensible
document type declaration if you need to validate something would be

<!DOCTYPE html SYSTEM>

assuming that if you *need* to validate anything you have everything you
need (parser, catalog, etc) on your system (menmonic, isn’t it :^),
properly configured.

Of course, the above document type declaration would have the side
effect of triggering bozo-mode in Firefox, and probably some other UAs
(not in IE though :). Since doctype sniffing is the only thing that
browsers do with document type declarations in text/html documents,
anything more than the minimal syntax to trigger [insert alias for
standards compatible mode] in all known implementations is a mystical
incantation itself.

It is still best to insert the few redundant bytes for the external
identifier, though, because then you don’t need to argue about it with
people who don’t understand any of that, like marketeers who read about
Web Standards in some journal, or David.
You missed one. The W3C seems to recommend using:

<!-- empty attributes -->
<input name=address disabled>
<input name=address disabled="">

<URL: http://dev.w3.org/html5/spec/Overview.html#a-quick-introduction-to-html

It’s pretty pointless to quote an unfinished specification anyway, but
the better section on this topic might be:

http://www.w3.org/TR/html5/common-microsyntaxes.html#boolean-attributes
Though I can't understand why the W3C thinks empty attributes need an
inline value assigned at all, and setting it to empty string makes no
sense - it makes life more difficult.

I haven’t read any rationale for it, but there’s a lot of history – and
bad implementations – to consider, I presume. For starters, in HTML 4,
‘disabled’ in

<input disabled>

would be the the attribute *value* (literal), not the attribute
*name*. This is easy to understand if you know that the SGML shorthand
feature that enables this is called ‘attribute name omission’.

The ‘getAttribute’ method, however, incorrectly returns an empty string
in most implementations (*if* you use name omission in your markup, that
is, otherwise there’s no ambiguity and it returns the value). Not IE,
though. How cool is that? :p

So I suppose here’s some compatibility handwaving to align the spec with
the bugs (one of the design goals of HTML5, I think).
 
R

RobG

HTML5 is accepted by the W3C validator, but it's too early to be using
it for general web pages.

I’ll bite. The SGML “document type declaration” production is

  (mdo ("<!"),
   "DOCTYPE",
   +ps,
   document type name,
   ?( +ps, external identifier ),
   ?( +ps, dso ("["), document type declaration subset, dsc ("]") ),
   *ps, mdc (">"))

There. The ‘HTML5 Doctype’ available. 1986. Go figure.

Ok, I'm not up to speed on details of DOCTYPE declarations so I'll
need to do some reading on that. :)


[...]
It’s pretty pointless to quote an unfinished specification anyway,

Apparently that is how it works now, the HTML "specification" is a
living document that will never be finished[1]. WHATWG have decided
that there are no more versions of HTML, just the latest editors draft
that will be updated from time to time to reflect not only what might
be in HTML now, but also what might be there soon.

Maybe from time to time the W3C will issue numbered versions, but
right now HTML5 is just a marketing term. There is no HTML5 standard
and there is no plan to release one (as far as I know).


Upon visiting that URL I am presented with a bright red message
saying:

| This is a work in progress!
| For the latest updates from the HTML WG, possibly
| including important bug fixes, please look at the
| editor's draft instead."

with a link to the document I quoted. So if the W3C is the authority,
they have delegated to the HTML WG. Or is HTML 4.01 still the
standard? I don't know.

I haven’t read any rationale for it, but there’s a lot of history –and
bad implementations – to consider, I presume.

Unfortunately getAttribute deals with such attributes differently
across browsers depending on the value. The DOM property is consistent
though.
For starters, in HTML 4,
‘disabled’ in

   <input disabled>

would be the the attribute *value* (literal), not the attribute
*name*. This is easy to understand if you know that the SGML shorthand
feature that enables this is called ‘attribute name omission’.

Discussions about HTML are OT here, but anyway, thanks for that tip.
If it is of any consequence, the HTML 4.01 spec says:

| disabled [CI]
| When set for a form control, this boolean attribute
| disables the control for user input.

So the confusion between attributes and properties seems pervasive.

The ‘getAttribute’ method, however, incorrectly returns an empty string
in most implementations (*if* you use name omission in your markup, that
is, otherwise there’s no ambiguity and it returns the value). Not IE,
though. How cool is that? :p

Precisely, which is why recommending (perhaps you'd prefer
"suggesting") the use of empty string is inappropriate.

So I suppose here’s some compatibility handwaving to align the spec with
the bugs (one of the design goals of HTML5, I think).

Given the lack of alignment between browsers on such things in an 11
year old standard and the apparent reluctance of developers to sort it
out between themselves, I think the HTML WG strategy of a "living
specification" is not helpful.


1. <URL: http://blog.whatwg.org/html-is-the-new-html5 >

PS. Thomas has pointed out that <URL: ... > is deprecated and should
be <...>, however GG screws up the newer version so I'll keep using
the old one until they fix that. Hopefully newsreaders can deal with
both.
 
E

Eric Bednarz

RobG said:
Upon visiting that URL I am presented with a bright red message
saying:

| This is a work in progress!
| For the latest updates from the HTML WG, possibly
| including important bug fixes, please look at the
| editor's draft instead."

with a link to the document I quoted.

When I was writing my response, the fragment identifier
‘boolean-attributes’ didn’t work for me in the editor’s draft (it might
have just been my browser hanging, the page is idiotically big). I
should have mentioned that to avoid confusion.

My point, however, was really about the *section* ‘Boolean attributes’
as opposed to ‘A quick introduction to HTML’.

| A number of attributes are boolean attributes. The presence of a
| boolean attribute on an element represents the true value, and the
| absence of the attribute represents the false value.
|
| If the attribute is present, its value must either be the empty string
| or a value that is an ASCII case-insensitive match for the attribute's
| canonical name, with no leading or trailing whitespace.
<http://dev.w3.org/html5/spec/Overview.html#boolean-attributes>
 
T

Thomas 'PointedEars' Lahn

Eric said:
This statement is a little pregnant. Assuming the solidus in a context
where it can be parsed as NET (null end-tag) delimiter, the character ‘>’
will either be valid or not depending on whether or not the document type
declaration subset allows character data in that context.

HTML5 is not going to be a document type driven by a DTD. As for HTML4,
that is why I used the word "fully".

(See?) Thanks.


PointedEars
 
E

Eric Bednarz

Thomas 'PointedEars' Lahn said:
HTML5 is not going to be a document type driven by a DTD. As for HTML4,
that is why I used the word "fully".

I don’t see how any given markup construct could not be fully
(in)valid. Not that it matters.
(See?) Thanks.

Neither do I understand whay you mean by ‘See?’, unfortunately. :)

Section 8 describes the HTML5 HTML syntax (as opposed to XHTML syntax in
section 9), and ‘8.1.2.1 Start tags’ #6 says that you *can* have a
solidus before ‘>’ in the start tag of empty (‘void’) elements. I was
under the impression that you thought the opposite to be the case.
 
T

Thomas 'PointedEars' Lahn

Eric said:
I don’t see how any given markup construct could not be fully
(in)valid. Not that it matters.

Context matters.
Neither do I understand whay you mean by ‘See?’, unfortunately. :)

Section 8 describes the HTML5 HTML syntax (as opposed to XHTML syntax in
section 9), and ‘8.1.2.1 Start tags’ #6 says that you *can* have a
solidus before ‘>’ in the start tag of empty (‘void’) elements.

Yes, and that would not be possible if HTML5 was driven by a DTD. So with
your second statement you had proved that your first statement was largely
irrelevant, which caused me to respond with "(Do you) see?".
I was under the impression that you thought the opposite to be the case.

I did.


PointedEars
 
S

S.T.

Of course you wouldn't consider a flaw in basic functionality important

Presumably there's some reasoning justifying the core of DM's latest
hissy fit.

----------
"Why does jQuery do jQuery.attr( this, name, "" ); in removeAttr()?

jQuery does this to fix a bug in some IE versions which don't handle
calls to removeAttribute( name )"
----------

I honestly don't know if the above accurate and sufficiently explains
the use this approach that David finds ever so tragic.

Does it matter either way? Not really.

jQuery tried to make attributes and properties interchangeable for the
convenience of developers. Many (myself included) see this as
over-ambitious/a design mistake as it results in ambiguity under certain
scenarios. From what I've gathered it appears the jQuery developers
agree and are backtracking. We'll see how that turns out but it won't be
a game-changer in any event.

That said, does the current codebase that reflects the suspect decision
indicate the jQuery developers are fools? No. Even David knows that but
he's an attention whore so he'll rant regardless.
 

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
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top