<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -13,9 +13,9 @@ function applyAnalytics($, gat, account) {
   }
   $.trackPageview = function(path) {
     if (path) {
-      var url = (path instanceof URL) ? path : new URL(path)
+      var url = new URL(path)
       path = url.pathWithQuery()
-      if (url.domain &amp;&amp; url.domain != 'twitter.com') path = '/' + url.domain + '/' + path
+      if (url.external()) path = '/' + url.host + path
     }
     try { pageTracker._trackPageview(path) } catch(err) {}
   }</diff>
      <filename>toolkit/analytics.js</filename>
    </modified>
    <modified>
      <diff>@@ -159,10 +159,7 @@ function ajax(params) {
       
   params = extend(defaults, params)
   params.headers = extend(defaultHeaders, params.headers || {})
-  
-  if (!/^https?[:]/.test(params.url)) {
-    params.url = window.location.protocol + '//' + window.location.host + params.url
-  }
+  params.url = new URL(params.url).absolutize().toString()
   
   if (typeof params.data == 'object') {
     params.data = objectToQueryString(params.data)
@@ -173,24 +170,41 @@ function ajax(params) {
 }
 
 function loadJSON(url, onload, params) {
-  params = extend({ url: url, onload: onload }, params || {})
-  var handler = params.onload
+  url = new URL(url)
   
-  params.onload = function(response) {
-    if (typeof response.getResponseHeader == 'function') {
-      // native XMLHttpRequest interface
-      var responseType = (response.getResponseHeader('Content-type') || '').split(';')[0]
-    } else {
-      // GM_xmlhttpRequest interface
-      var responseType = (response.responseHeaders.match(/^Content-[Tt]ype:\s*([^\s;]+)/m) || [])[1]
-    }
-    if (responseType == 'application/json' || responseType == 'text/javascript') {
-      var object = eval(&quot;(&quot; + response.responseText + &quot;)&quot;)
-      if (object) handler(object, response)
+  if (params.jsonp) {
+    var head = document.getElementsByTagName('head')[0],
+		    script = document.createElement('script'),
+		    jsonp = ('string' == typeof params.jsonp) ? params.jsonp : '_callback',
+		    callback = 'loadJSON' + (++loadJSON.$uid)
+		
+		window[callback] = function(object) {
+		  onload(object)
+		  window[callback] = null
+		}
+		script.src = url.addQuery(jsonp + '=' + callback)
+		head.appendChild(script)
+  } else {
+    params = extend({ url: url, onload: onload }, params || {})
+    var handler = params.onload
+  
+    params.onload = function(response) {
+      if (typeof response.getResponseHeader == 'function') {
+        // native XMLHttpRequest interface
+        var responseType = (response.getResponseHeader('Content-type') || '').split(';')[0]
+      } else {
+        // GM_xmlhttpRequest interface
+        var responseType = (response.responseHeaders.match(/^Content-[Tt]ype:\s*([^\s;]+)/m) || [])[1]
+      }
+      if (responseType == 'application/json' || responseType == 'text/javascript') {
+        var object = eval(&quot;(&quot; + response.responseText + &quot;)&quot;)
+        if (object) handler(object, response)
+      }
     }
+    return ajax(params)
   }
-  return ajax(params)
 }
+loadJSON.$uid = 0
 
 function strip(string) {
   return string.replace(/^\s+/, '').replace(/\s+$/, '')
@@ -246,11 +260,15 @@ function positionCursor(field, start, end) {
 }
 
 function URL(string) {
-  var match = string.match(/(?:(https?):\/\/([^\/]+))?([^?]*)(?:\?(.*))?/)
+  if (string instanceof URL) return string
+  
+  var match = string.match(/(?:(https?:)\/\/([^\/]+))?([^?]*)(?:\?([^#]*))?(?:#(.*))?/)
   string = match[0]
-  this.domain = match[2]
+  this.protocol = match[1]
+  this.host = match[2]
   this.path = match[3]
   this.query = match[4]
+  this.hash = match[5]
   
   this.toString = function() {
     return string
@@ -259,4 +277,18 @@ function URL(string) {
 
 URL.prototype.pathWithQuery = function() {
   return this.path + (this.query ? '?' + this.query : '')
-}
\ No newline at end of file
+}
+URL.prototype.external = function() {
+  return this.host &amp;&amp; (this.host != window.location.host ||
+    this.protocol != window.location.protocol)
+}
+URL.prototype.absolutize = function() {
+  if (this.host) {
+    return this
+  } else {
+    return new URL(window.location.protocol + '//' + window.location.host + this)
+  }
+}
+URL.prototype.addQuery = function(string) {
+  return new URL(this.toString() + (this.query ? '&amp;' : '?') + string)
+}</diff>
      <filename>toolkit/toolkit.js</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>16612268e5e954f6694cefb6153e5c2bfed512ba</id>
    </parent>
  </parents>
  <author>
    <name>Mislav Marohni&#263;</name>
    <email>mislav.marohnic@gmail.com</email>
  </author>
  <url>http://github.com/mislav/user-scripts/commit/77c33a79f0a92107d49bd9965ddad5ef0c979efa</url>
  <id>77c33a79f0a92107d49bd9965ddad5ef0c979efa</id>
  <committed-date>2009-07-01T09:14:45-07:00</committed-date>
  <authored-date>2009-07-01T09:14:45-07:00</authored-date>
  <message>support JSON-P in loadJSON()

Example:
  loadJSON(url, function(json){ ... }, { jsonp: true })

Other changes:
  - ajax() function now supports URL instances as well as
    strings for the `url` parameter
  - added URL methods: `external`, `absolutize`, `addQuery`
  - `URL#domain` property renamed to `URL#host`</message>
  <tree>cc9b2be486eac9d6f7de5db1f30fb5763472d573</tree>
  <committer>
    <name>Mislav Marohni&#263;</name>
    <email>mislav.marohnic@gmail.com</email>
  </committer>
</commit>
