window object

R

Richard Cornford

Richard Cornford wrote:
... if not resolved as propitious of the object added ... ^^^^^^^^^^
... caught by being resolved as priorities of ..
^^^^^^^^^^
Should be 'properties' and 'properties' respectively.

Respectively if we declare:
window['foo'] = 'bar';
and later call alert(foo) then engine will look first in
the Global scope, fail on it, then look in
the window scope and find it.

With the implication that the global object does not have an
- alert - property or a - foo - property? Neither have been
demonstrated, and the above test shows that both the - window
- object and the global - this - object behave in isolation as
if they have properties corresponding with ECMA 262 defined
global properties, browser global properties, declared local ^^^^^
variables, runtime added properties, etc.
<snip>

Should be "declared global variables".

Richard.
 
V

VK

Richard said:
You lack of awareness of web browsers is becoming legendary.

Adding properties to window was an age old and actively used method to
have
any amount of global variables without pre-declaring each and every one

(before new Object() and stuff).
Nevertheless it never was an issue to think that window['foo'] and var
foo
may refer to the same thing ot may override each other.
JavaScript variable and window property was always two completely
separate things.

As Firefox' Global vs. Window behavior went totally against of all my
experience,
I decided to check that I'm not getting senile in my 37.

I installed Netscape Composer 4.5 from my archives, and after a minute
of nostalgie
and the ritual "NN hit" to microsoft.com :) I run this test:

<html>
<head>
<title>Test</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<script language="JavaScript1.2">
function test() {
var foo = 1;
window['foo'] = 2;
alert(foo); // displays 1
alert(window['foo']); // displays 2
}
</script>
</head>

<body bgcolor="#FFFFFF" onload="test()">
<p>Test</p>
</body>
</html>

I'm glad to see that my memory is still fine - at least here :)
And it was exactly the same with Netscape 2.x, Netscape 3.x, IE 3.x,
Netscape 4.x and IE 4.x

Therefore the many times quoted sentence from ECMA specs is just an
extremely bad wording
caused either by bad English or by bad script knowledge or by both. Mr.
Eich must be left then it was written to get some coffee :)

Therefore the current Firefox scope model is something that never
existed before
Firefox itself and which is not currently implemented anywhere else.
It's the result
of a slavery following of the specification text. In this concern IE is
more "standard"
if we take the "standard" as "something regarded as the most common".

Nevertheless this scope model is already implemented (even if based on
a text errata), so
just another extra difference to deal with. Lucky ECMA did not say that
window properties
are being kept by little green gnomes or something like that. That
would be a real challenge
to implement in the documented way :)
 
R

Richard Cornford

VK said:
Adding properties to window was an age old and actively used
method to have any amount of global variables without
pre-declaring each and every one

And that is relevant because?
(before new Object() and stuff). Nevertheless it never was
an issue to think that window['foo'] and var foo may refer
to the same thing ot may override each other.

If the - var foo; - is declaring a function local variable it is not
expected to refer to the same thing as - window['foo'] -, ever. The
declaring of function local variables and the distinction between local
and global variables is _fundamentally_basic_ to javascript authoring,
and not being able to understand them flags you as an utter incompetent.
All misconceptions that follow from that one basic misconception are
folly built on ignorance.
JavaScript variable and window property was always two
completely separate things.

As Firefox' Global vs. Window behavior went totally against
of all my experience,

Your many years of experience are compliantly worthless. So far you have
not even demonstrated a significant difference in behaviour between IE
and Firefox, let alone anything unexpected in Firefox.
I decided to check that I'm not getting senile in my 37.

It is mental illness that you want to be checking for. You are not
rational.
I installed Netscape Composer 4.5 from my archives, and
after a minute of nostalgie
and the ritual "NN hit" to microsoft.com :) I run this test:

<html>
<head>
<title>Test</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<script language="JavaScript1.2">
function test() {
var foo = 1;
window['foo'] = 2;
alert(foo); // displays 1
alert(window['foo']); // displays 2
}
</script>
</head>

<body bgcolor="#FFFFFF" onload="test()">
<p>Test</p>
</body>
</html>

I'm glad to see that my memory is still fine - at least
here :) And it was exactly the same with Netscape 2.x,
Netscape 3.x, IE 3.x, Netscape 4.x and IE 4.x

Have you fond a single browser where it is not exactly the same?
Therefore

"Therefor"? What is "therefor" about yet another example of a browser
doing precisely what it would be expected to do?
the many times quoted sentence from ECMA specs
is just an extremely bad wording

Which "many times quoted" sentence? If you never state what it is that
you think is being demonstrated how do you expect people to correct your
misconceptions. Don't forget that your 'demonstration' from the
preceding post was not a demonstration of anything but browsers behaving
exactly as they are supposed to.
caused either by bad English or by bad script knowledge
or by both. Mr. Eich must be left then it was written to
get some coffee :)

Nothing is caused. The problem here is that you don't understand what
you are doing and so you don't understand that what you are observing is
exactly what the code you are writing is supposed to be doing.
Therefore the current Firefox scope model is something that
never existed before Firefox itself and which is not currently
implemented anywhere else.

You have not demonstrated anything divergent or unusual in the handling
of scope in Firefox so there is no evidence for this false assertion.
It's the result of a slavery following of the specification
text. In this concern IE is more "standard" if we take the
"standard" as "something regarded as the most common".

You have not demonstrated any difference in the handling of scope
between Fireforx and IE so this assertion is irrelevant.
Nevertheless this scope model is already implemented (even if
based on a text errata), so just another extra difference to
deal with. Lucky ECMA did not say that window properties are
being kept by little green gnomes or something like that. That
would be a real challenge to implement in the documented way :)

This whole thing is the product of your maintaining fundamental
misconceptions about the way in which javascript works, even in the face
of numerous corrections and explanations. It is irrational for you to be
so wrong, and demonstrated so wrong so often, and for you not to be able
to see yourself as in error. Worry about mental illness not senility.

Richard.
 
V

VK

Richard said:
Your many years of experience are compliantly worthless. So far you have
not even demonstrated a significant difference in behaviour between IE
and Firefox, let alone anything unexpected in Firefox.

It is difficult to argue with a real believer. It is double difficult
to argue with an agressive believer, who's ready to "kill for his
faith" :)

I dared to check you posting history and I see them back to the year
2000, which means that you were reading Books of ECMA six years in the
row by now. That makes damage for sure. :)
My ignorance about Books of ECMA sometimes is a default but sometimes
it is a great benefit as I kept the ability to accept new facts or to
give new explanation to old ones.
IMHO this ability has been seriously weakened from your side as for too
many years your preoccupation was to prove that whatever happens in the
Web was described or predicted in the Books of ECMA. Sorry if I sound
nasty, but seems close to the truth.

Believe you me or not but at the moment of my first post in this thread
(about Global vs. Window scope in IE and Opera) I had no idea about the
following article on MSDN. I found it only tonight while trying to save
the rest of my sanity - as it happens with me after some discussions
with selected people in this newsgroup :)

<blockquote
cite="http://msdn.microsoft.com/workshop/author/perf/perftips.asp">
"Scope Your Object References Wisely"

Within a script, every reference to an object amounts to two calls
from the scripting engine to the DHTML Object Model. For those
unfamiliar with or interested in the intimate details of Automation,
refer to the documentation on IDispatch::GetIDsOfNames and
IDispatch::Invoke
in the Microsoft Platform software development kit (SDK).
....
When Internet Explorer parses a page it accounts for all the objects
on the page for which ID attributes have been explicitly specified.
It adds them to the global namespace of the scripting engine,
allowing you to refer to them directly. That means that the following
is excessive.
<SCRIPT>
var sText = document.all.div1.innerText;
</SCRIPT>
In addition to the extra bytes that are passed across the network
and parsed by the scripting engine, four extra calls are made by
the script engine back to Internet Explorer in order to retrieve
the innerText property of the div.

Notable exceptions to this minimalist approach include the following:
Accessing elements contained within a form.
Accessing properties of an iframe.
Accessing properties of the window object.

When a scripting engine encounters a scoped object model reference in
your code,
the engine needs to resolve the reference by looking up the left-most
piece of that
reference in a look-up table. Two factors influence the scripting
engine's ability
to perform the look-up:

The number of entries in the look-up table.
The scope of the reference.
The number of entries in the table corresponds to the number of global
variables,
named objects, and functions that you have defined on your page.
Thus, you should only declare the ID attribute on those elements
that you explicitly wish to manipulate through script.

As mentioned above, there's a right way and a wrong way to scope
references. When you've assigned an ID attribute to an element, there's
no reason to access the corresponding object through document.all.
Armed with this information, you might think that you should minimize
your object model references in all cases. Let's look at another common
example where this rule doesn't apply:

var sUA = navigator.userAgent;
The code works. It stores the HTTP_USER_AGENT string in the variable
sUA. In order for the scripting engine to resolve this reference,
however, it first attempts to find an object named navigator in the
global look-up table. After looking through the entire table and not
finding such a named item, the engine has to walk through the table
again asking each of the global objects if it supports the navigator
object. When it finally encounters the global window object, the object
that exposes the navigator property, it can then retrieve the userAgent
property. A better way to handle this situation, especially on a page
containing many globally named items, is to fully scope the reference
as follows:

var sUA = window.navigator.userAgent;
If all this talk about look-up tables and global objects has your head
spinning, just remember this simple rule: fully scope your references
to members of the window object. A list of these members is provided in
the DHTML Reference.
</blockquote>

And as a nice parting comment :)

<q
cite="<http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=102277&SiteID=1">
...unlike in Firefox, in IE the window object isn't exactly the
JScript global object.
This was originally so that multiple script languages could safely
coexist in a web page.
</q>

.... sweet dreems ;-)
 
T

Thomas 'PointedEars' Lahn

VK said:
It is difficult to argue with a real believer. It is double difficult
to argue with an agressive believer, who's ready to "kill for his
faith" :)

Your problem is that /you/ are making this a question of faith. It is not.
It is a matter of fact. It is based on hard evidence that you are presented
over and over again. Still you choose to ignore it, and to listen to the
voices in your head instead which originate from your misunderstanding of
informal texts combined with your unjustified snotty attitude. The
described behavior has been specified, and it was implemented as specified.
Even before the specification was actually issued.


PointedEars
 
R

Richard Cornford

VK said:
It is difficult to argue with a real believer. It is double
difficult to argue with an agressive believer, who's ready
to "kill for his faith" :)

If you posted code that showed any browser exhibiting behaviour that
differs from the behaviour that would be expected of a 100% ECMA 262
conforming javascript implementation then there would be no question of
belief, we would be in the realm of facts. But so far in this thread you
have only managed to post code that demonstrates browsers behaving in a
way that look significant in your understanding of the language, but
actually have no baring on the assertions that you are making to explain
them.
I dared to check you posting history and I see them back
to the year 2000,

You cannot even competently perform an archive search.
which means that you were reading Books of ECMA six years
in the row by now.

As your first 'fact' is wrong that conclusion is inevitably also wrong.
But your conclusion would be wrong even if you had got the date right.
It took me a while to see the advantages in gaining a technical
understanding of the language specification so the period over which I
have been reading, and referring to, ECMA 262 is shorter than the period
over which I have been posting to this group.
That makes damage for sure. :)

Yes, I can look at written source code and know precisely how it will
behave before it is executed, while you don't even understand what the
code you write is doing after it is executed; that is real 'damage'
isn't it?
My ignorance about Books of ECMA sometimes is a default but
sometimes it is a great benefit as I kept the ability to
accept new facts or to give new explanation to old ones.

By which you mean that having no technical understanding of javascript
allows you freedom to fabricate explanations and terminology off the top
of your head.
IMHO this ability has been seriously weakened from your side
as for too many years your preoccupation was to prove that
whatever happens in the Web was described or predicted in
the Books of ECMA. Sorry if I sound nasty, but seems close
to the truth.

There is no preoccupation to 'prove' that anything "was described or
predicted in the Books of ECMA". We are not talking about the works of
Nostradamus, ECMA 262 is a technical specification for a programming
language. It prescribes how the core language will behave, from the
interpretation of source code to the evaluation of simplest expression,
in near total precision. It is also the standard that every current web
browser javascript implementation states that it implements, as was the
intention when it was created. It provides sufficient detail to allow
code to be written with a certain expectation of how it will be
interpreted and behave, and it provides a consistent set of well-defined
terminology for use in technical discussions of the subject.

It is also the only source that will answer particular technical
questions, such as which side of an equality expression will be
evaluated first. You won't find that detail in references, user guides
and (most) informal texts, but those are not technical documents and
while language implementers can assert that they implement ECMA 262 they
don't need to put that detail in their non-technical documents as you
can always go to the standard to get the real details.

But in any event, the ability to accept "new facts" is irrelevant while
no new facts are presented, and the ability to identify and reject bogus
facts is more valuable in the growth of knowledge than the ability to
accept new facts.
Believe you me or not but at the moment of my first post
in this thread (about Global vs. Window scope in IE and
Opera) I had no idea about the following article on MSDN.

No, I do believe that you made it up off the top of your head based on
misinterpretations of various sources and code that you did not
understand yourself.
I found it only tonight while
trying to save the rest of my sanity - as it happens with me after
some discussions with selected people in this newsgroup :)

<blockquote
cite="http://msdn.microsoft.com/workshop/author/perf/perftips.asp">
"Scope Your Object References Wisely"

Within a script, every reference to an object amounts to two
calls from the scripting engine to the DHTML Object Model.
For those unfamiliar with or interested in the intimate details
of Automation, refer to the documentation on
IDispatch::GetIDsOfNames and IDispatch::Invoke
in the Microsoft Platform software development kit (SDK).
...
When Internet Explorer parses a page it accounts for all
the objects on the page for which ID attributes have been
explicitly specified. It adds them to the global namespace
of the scripting engine, allowing you to refer to them
directly. That means that the following is excessive.
<SCRIPT>
var sText = document.all.div1.innerText;
</SCRIPT>
In addition to the extra bytes that are passed across
the network and parsed by the scripting engine, four
extra calls are made by the script engine back to
Internet Explorer in order to retrieve the innerText
property of the div.

Notable exceptions to this minimalist approach include
the following:
Accessing elements contained within a form.
Accessing properties of an iframe.
Accessing properties of the window object.

When a scripting engine encounters a scoped object model
reference in your code, the engine needs to resolve the
reference by looking up the left-most piece of that
reference in a look-up table. Two factors influence
the scripting engine's ability to perform the look-up:

The number of entries in the look-up table.
The scope of the reference.
The number of entries in the table corresponds to the
number of global variables,
named objects, and functions that you have defined on
your page. Thus, you should only declare the ID
attribute on those elements that you explicitly wish
to manipulate through script.

As mentioned above, there's a right way and a wrong
way to scope references. When you've assigned an ID
attribute to an element, there's no reason to access
the corresponding object through document.all. Armed
with this information, you might think that you should
minimize your object model references in all cases.
Let's look at another common example where this rule
doesn't apply:

var sUA = navigator.userAgent;
The code works. It stores the HTTP_USER_AGENT string
in the variable sUA. In order for the scripting engine
to resolve this reference, however, it first attempts
to find an object named navigator in the global look-up
table. After looking through the entire table and not
finding such a named item, the engine has to walk through
the table again asking each of the global objects if it
supports the navigator object. When it finally encounters
the global window object, the object that exposes the
navigator property, it can then retrieve the userAgent
property. A better way to handle this situation, especially
on a page containing many globally named items, is to fully
scope the reference as follows:

var sUA = window.navigator.userAgent;
If all this talk about look-up tables and global objects
has your head spinning, just remember this simple rule:
fully scope your references to members of the window object.
A list of these members is provided in the DHTML Reference.
</blockquote>

Well, that does not say that there is an object below the ECMAScript
global object on the scope chain. It is an informal text describing (or
appearing to describe) the internal details of the resolution of the
properties of the global object. And as these details are internal they
have no consequences for the author of javascript code as they do not
change the ability of IE to behave in accordance with ECMA 262.

That is, this document is irrelevant except that it suggests that
features of the internal mechanism would result in particular styles of
property accessor being resolved faster than others. On the other hand,
if true, those might be exploitable details, particularly for those
working on an IE only Intranet. The concrete claim of that article is
that:-

var sUA = navigator.userAgent;

- will take longer to resolve than:-

var sUA = window.navigator.userAgent;

- "especially on a page containing many globally named items".

That is a very specific claim, and relatively easy to verify, or refute.
You may prefer to perceive my actions as driven entirely by a
theoretical approach but I am actually very keen on experimentation and
demonstration. Here is a test script to verify the above claim, it
document.writes 2000 IDed DIV elements as that should qualify as "on a
page containing many globally named items" and so show the advantages of
qualifying the property accessor with - window - to its maximum extent:-

<html>
<head>
<title>navigator tests</title>
<script type="text/javascript">

var frm = null;
var fncts = [
/* Timing of an empty loop to estimate the overheads of the
test itself. */
function(p){
var lim = +frm['loopLimit'].value;
var N, totTime, stTime = new Date().getTime();
for(var c = 0;c < lim;c++){
N = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows __)';
}
totTime = (new Date().getTime() - stTime);
frm["Dur"+p].value = totTime;
frm["Avr"+p].value = (totTime/lim);
frm["Res"+p].value = N;
act(p+1);
},
function(p){
var lim = +frm['loopLimit'].value;
var N, totTime, stTime = new Date().getTime();
for(var c = 0;c < lim;c++){
N = window.navigator.userAgent;
}
totTime = (new Date().getTime() - stTime);
frm["Dur"+p].value = totTime;
frm["Avr"+p].value = (totTime/lim);
frm["Res"+p].value = N;
act(p+1);
},
function(p){
var lim = +frm['loopLimit'].value;
var N, totTime, stTime;
stTime = new Date().getTime();
for(var c = 0;c < lim;c++){
N = navigator.userAgent;
}
totTime = (new Date().getTime() - stTime);
frm["Dur"+p].value = totTime;
frm["Avr"+p].value = (totTime/lim);
frm["Res"+p].value = N;
act(p+1);
}
];

var f;
var running = false;
function setButtons(bl){
frm['loopLimit'].disabled = bl;
var sw = frm['bt'];
if(typeof sw.length == 'undefined'){
sw = [sw];
}
for(var c = 0;c < sw.length;c++){
sw[c].disabled = bl;
}
}
function doTests(){
if(!running){
frm = document.forms['f'].elements;
setButtons(true);
frm["Dur0"].value = '';frm["Avr0"].value = '';
for(var c = 1;c < fncts.length;c++){
frm["Dur"+c].value = '';
frm["Avr"+c].value = '';
frm["CAvr"+c].value = '';
frm["PAvr"+c].value = '';
frm["Res"+c].value = '';
}
running = true;
act(0);
}
}
function act(p){
/* setTimeout is used to minimise the occurrences
of 'a script on this page is running slow' dialogs. */
if(p >= fncts.length){
setTimeout('report()',100);
}else{
setTimeout(('(f = fncts['+p+'])('+p+');'),200);
}
}
function report(){
var c, evaC, lim = +frm['loopLimit'].value;
var emDur = +frm["Dur0"].value
var unaC = (frm["Dur"+(fncts.length-1)].value - emDur) / lim;
frm["CAvr"+(fncts.length-1)].value = unaC;
frm["PAvr"+(fncts.length-1)].value = '100';
for(c = 1;c < (fncts.length-1);c++){
evaC = (frm["Dur"+c].value - emDur) / lim;
frm["CAvr"+c].value = evaC;
frm["PAvr"+c].value = ((evaC/unaC)*100);
}
setButtons(false);
running = false;
}

</script>
</head>
<body>
<div>
<form name="f" action="#">
Loop Length = <input type="text" value="1300000"
name="loopLimit"><br><br>


<input type="button" value="Test" name="bt" onclick="doTests();">
Repeat tests to reduce/expose the influence of background tasks.
<br><br>
Empty Loop Duration (milliseconds) = <input type="text" value="X"
name="Dur0"><br>
Empty Loop Average (milliseconds) = <input type="text" value="X"
name="Avr0" size="22"><br>
(result = <input type="text" value="X" name="Res0" size="22">)<br><br>
<br>



<br>
<code>window.navigator.userAgent</code> Duration (milliseconds) =
<input type="text" value="X" name="Dur1"><br>
<code>window.navigator.userAgent</code> Average (milliseconds) =
<input type="text" value="X" name="Avr1" size="22"><br>
(result = <input type="text" value="X" name="Res1" size="22">)<br><br>


<br>
<code>navigator.userAgent</code> Duration (milliseconds) =
<input type="text" value="X" name="Dur2"><br>
<code>navigator.userAgent</code> Average (milliseconds) =
<input type="text" value="X" name="Avr2" size="22"><br>
(result = <input type="text" value="X"
name="Res2" size="22">)<br><br>


<input type="button" value="Test" name="bt" onclick="doTests();">
Repeat tests to reduce/expose the influence of background tasks.
<br><br>

Results: (duration of test - duration of empty loop) / loop length<br>

<code>window.navigator.userAgent</code> Average (milliseconds) =
<input type="text" value="X" name="CAvr1" size="22"><br>

<code>navigator.userAgent</code> Average (milliseconds) =
<input type="text" value="X" name="CAvr2" size="22"><br>


<br>
<table><tbody><tr><th></th>
<th>Differences (<code>navigator.userAgent</code> = 100%)</th></tr>

<tr><td><code>window.navigator.userAgent</code></td><td>
<input type="text" value="X" name="PAvr1"size="22">%</td></tr>

<tr><td><code>navigator.userAgent</code></td><td>
<input type="text" value="X" name="PAvr2"size="22">%</td></tr>

</tbody></table>

</form>
</div>
<script type="text/javascript">
for(var c = 0;c < 2000;++c){
document.write('<div id=\"test'+c+'\">test'+c+' div<\/div>');
}
</script>

</body>
</html>

And using that test script these are the results I got on the various
stated IE versions and OS/processor combinations:-

IE 5.50.4807.2300IC
Windows NT4 - AMD K6-2 500MHz
| Per-lookup | Difference
--------------------------------------------------------
window.navigator.userAgent | 0.10229 ms | 140.237%
navigator.userAgent | 0.07294 ms | 100%
--------------------------------------------------------


IE 5.50.4134.0100
Windows ME - Celeron 700MHz
| Per-lookup | Difference
--------------------------------------------------------
window.navigator.userAgent | 0.07744 ms | 171.441%
navigator.userAgent | 0.04517 ms | 100%
--------------------------------------------------------


IE 6.0.2800.1106
Windows 98 - P3 500MHz
| Per-lookup | Difference
--------------------------------------------------------
window.navigator.userAgent | 0.09646 ms | 128.973%
navigator.userAgent | 0.07479 ms | 100%
--------------------------------------------------------


IE 6.0.3790.1830
Windows XP Pro 64bit - AMD Athlon 64X2 4400+ (2*2200MHz)
| Per-lookup | Difference
--------------------------------------------------------
window.navigator.userAgent | 0.00867 ms | 137.596%
navigator.userAgent | 0.00630 ms | 100%
--------------------------------------------------------


IE 6.0.2900.2180.xpsp-sp2-rtm.040803.2158
Windows XP Pro 32bit - AMD Athlon 64X2 4400+ (2*2200MHz)
| Per-lookup | Difference
--------------------------------------------------------
window.navigator.userAgent | 0.01064 ms | 129.220%
navigator.userAgent | 0.00823 ms | 100%
--------------------------------------------------------

Oh, look, - navigator.userAgent - resolves quicker than -
window.navigator.userAgent - in every test, by 29 - 79%. That is in
complete *contradiction* to the stated 'fact' in the article cited
above. How can this be, MSDN publishing material that makes statements
that are the opposite of the verifiable truth?

A charitable interpretation may be that this article refers to a
language implementation that has disappeared into the mists of history.
A less charitable interpretation would be that the author did not know
what he was talking about, or did not understand it well enough to draw
accurate conclusions. Either way an article that had little practical
relevance to browser scripting is shown by empirical testing to be false
in its concrete claims and so lacks credibility in general.
And as a nice parting comment :)

<q
cite="<http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=102277&Site
ID=1">
<snip>

Oh, very good, cite a random contribution to a Microsoft hosted public
newsgroup. That is about as authoritative as someone citing one of your
Usenet posts as an authority on javascript. And a post by an individual
who states:- "There is no way to get at the script global object to
enumerate its members", which demonstrates how much he knows:-

... sweet dreems ;-)

Dream on.

Richard.
 

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

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top