
<!--
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
-->

<p><span class="weinre">weinre</span> is <b>WE</b>b <b>IN</b>spector <b>RE</b>mote.
Pronounced like the word "winery".  Or maybe like the word "weiner".  Who knows,
really.

<p><span class="weinre">weinre</span> is a debugger for web pages, like
FireBug (for FireFox)
and
Web Inspector (for WebKit-based browsers), except it's designed
to work <b>remotely</b>, and in particular, to <b>allow you debug web pages
on a mobile device such as a phone</b>.

<p>Interesting places to visit:
<table>
<tr><td>- videos at YouTube:               <td><a href="http://www.youtube.com/results?search_query=weinre">http://www.youtube.com/results?search_query=weinre</a>
<tr><td>- this documentation at Apache:    <td>[TBD]</a>
<tr><td>- source at GitHub:                <td><a href="https://git-wip-us.apache.org/repos/asf?p=incubator-cordova-weinre.git;a=summary">https://git-wip-us.apache.org/repos/asf?p=incubator-cordova-weinre.git;a=summary</a>
<tr><td>- discussion at Google Group:      <td><a href="http://groups.google.com/group/weinre">http://groups.google.com/group/weinre</a>
</table>

<p>More information on <span class="weinre">weinre</span>'s big brothers, Web Inspector / Google Chrome
Developer Tools, is available at
<a href="http://code.google.com/chrome/devtools/docs/overview.html">Google's Chrome Dev Tools pages</a>
and
<a href="http://developer.apple.com/library/safari/#documentation/appleapplications/Conceptual/Safari_Developer_Guide/DebuggingYourWebsite/DebuggingYourWebsite.html">Apple's Web Inspector pages</a>.

<p>If you aren't familiar with FireBug or Web Inspector,
<span class="weinre">weinre</span> isn't going to make too much sense to you.
<span class="weinre">weinre</span> reuses the user interface code from the
<a href="http://trac.webkit.org/wiki/WebInspector">Web Inspector project at WebKit</a>,
so if you've used Safari's Web Inspector or Chrome's Developer Tools,
<span class="weinre">weinre</span> will be very familiar.  If you're not
familiar with Web Inspector, the links above to Google's and Apple's documentation
will be useful.

<p>Here's an example session using <span class="weinre">weinre</span>:

<p><img src="images/weinre-demo.jpg">

<p>Two screen captures are shown above.  On the left is the
<span class="weinre">weinre</span> <b>client</b> application, displaying debug
information.
On the right is the <b>target</b> web page, running in Mobile Safari in the iOS Simulator.

<p>In normal usage, you will be running the <b>client</b> application in a browser
on your desktop/laptop, and running a <b>target</b> web page on your mobile device.

<p>In the session above, the debugger is display the Elements panel, with the
embedded console expanded in the bottom third of the window.  In the console
area, we've entered two statements:

<pre>
document.body.style.backgroundColor
document.body.style.backgroundColor = "pink"
</pre>

<p>The result of running the first statement shows the value of the body's background style is not set.
The second statement sets the body's background to pink.  That horrifying pink
background is then rendered in the <b>target</b>'s window.

<p>In addition, an <tt>h1</tt> element is selected in the upper third of the
Elements panel, which causes the side panels on the right to be filled in with
relevant information.  In this case, the matched CSS rules for that <tt>h1</tt>
element are being shown.

<p>If you are familiar with WebKit's Web Inspector,
a partial list of differences between it and <span class="weinre">weinre</span>
are listed below:

<ul class="spaced">

<li><span class="weinre">weinre</span> does not make use of any 'native' code,
it's all JavaScript (and currently Java code for the 'server').

<li>Because <span class="weinre">weinre</span> doesn't use 'native' code,
it's functionality is limited.  For instance, source level debug of JavaScript
is not <span class="strike">possible</span>
<a href="http://lexandera.com/aardwolf/">easy</a>.

<li>Because <span class="weinre">weinre</span> doesn't use 'native' code,
the debug target code will run on browsers
without specialized debug support.  For instance, a browser running on your phone.

<li><span class="weinre">weinre</span> supports 'remote' interaction,
so you can run the debugger user interface on one
machine and can debug a web page running
on another machine.  For instance, debug a web page displayed on your phone from your
laptop.

<li>Because <span class="weinre">weinre</span> supports 'remote' interaction,
multiple debug clients can be debugging the same debug target at the same time.

<li>One thing <b>not</b> different from Web Inspector is that the debug client
user interface only runs on WebKit-based browsers.

</ul>

<!-- ======================================================== -->
<h2>Supported Libraries and Platforms</h2>

<p>Generally version numbers listed here are the earliest
versions of the relevant thing that have been tested.
Later versions of those things are also hopefully supported,
but let us know.

<h3>Platforms not supported</h3>

<ul>
<li>iOS 3.1.3 or earlier
<li>webOS 1.45 or earlier
</ul>

<h3>Libraries not supported</h3>

<ul>
<li>versions of Prototype.js before version 1.7 are not supported,
as they do not support the <tt>JSON.stringify()</tt> API correctly.  You
will get an <tt>alert()</tt> in the web page you are debugging if you
attempt to debug it with <span class="weinre">weinre</span> and you are using an unsupported
version of Prototype.js.
</ul>

<h3>Platforms supported - debug server</h3>
<p>Any platform that supports <a href="http://nodejs.org/">node.js</a>.

<h3>Platforms supported - debug client</h3>
<p>The browser where the debugger user interface runs.

<ul>
<li>Google Chrome 8.x
<li>Apple Safari 5.x
</ul>

<h3>Platforms supported - debug target</h3>
<p>The browser with the page you are debugging.

<ul>
<li>Android 2.2 Browser application
<li>Android 2.2 w/PhoneGap 0.9.2
<li>iOS 4.2.x Mobile Safari application
<li>BlackBerry v6.x simulator
<li>webOS 2.x (unspecified version)
</ul>

