
<!--
 * 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:
<td><a href="http://people.apache.org/~pmuellr/weinre/">http://people.apache.org/~pmuellr/weinre/</a> [temporary]</a>

<tr><td>unofficial binary packages:
<td><a href="http://people.apache.org/~pmuellr/weinre/">http://people.apache.org/~pmuellr/weinre/</a> [temporary]</a>

<tr><td>issues:
<td><a href="https://issues.apache.org/jira/secure/IssueNavigator.jspa?jqlQuery=project=CB+and+component=weinre">https://issues.apache.org/jira/gobble-de-gook/...</a>

<tr><td>create a new issue:
<td>
<a href="https://issues.apache.org/jira/secure/CreateIssueDetails!init.jspa?pid=12312420&components=12316604&issuetype=1">bug</a>
or
<a href="https://issues.apache.org/jira/secure/CreateIssueDetails!init.jspa?pid=12312420&components=12316604&issuetype=2">new feature</a>

<tr><td>cloneable source at Apache:
<td><a href="https://git-wip-us.apache.org/repos/asf/cordova-weinre.git">https://git-wip-us.apache.org/repos/asf/cordova-weinre.git</a>

<tr><td>Apache repo cloned at GitHub:
<td><a href="https://github.com/apache/cordova-weinre">https://github.com/apache/cordova-weinre</a>

<tr><td>mailing lists at Apache:
<td><a href="http://mail-archives.apache.org/mod_mbox/cordova-dev/">http://mail-archives.apache.org/mod_mbox/cordova-dev/</a> (for weinre development)

<tr><td>discussion at Google Group:
<td><a href="http://groups.google.com/group/weinre">http://groups.google.com/group/weinre</a> (for weinre usage)

</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
in the browser, it's all plain old boring JavaScript.

<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>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
<li>Apple Safari
<li>Other recent-ish WebKit-based browsers
</ul>

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

<ul>
<li>Android Browser application
<li>iOS Mobile Safari application
<li>PhoneGap/Cordova
<li>other
</ul>

<h3>Platforms not supported - debug target</h3>

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

