You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by an...@apache.org on 2013/10/22 01:24:21 UTC

[1/9] first commit

Updated Branches:
  refs/heads/master [created] f50cc931f


http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/site.js
----------------------------------------------------------------------
diff --git a/attachments/site.js b/attachments/site.js
new file mode 100644
index 0000000..c8ef8ac
--- /dev/null
+++ b/attachments/site.js
@@ -0,0 +1,955 @@
+if (!Object.keys) {
+  Object.keys = function (obj) {
+    var keys = [];
+    for (i in obj) keys.push(i);
+    return keys;
+  }
+}
+if (!Array.prototype.forEach) {
+  Array.prototype.forEach = function (cb) {
+    for (var i=0;i<this.length;i++) {
+      cb(this[i]);
+    }
+  }
+}
+
+
+// escape functionality taken from https://github.com/natevw/flatstache.js/
+var _re1 = /[&\"'<>\\]/g;
+var escape_map = {"&": "&amp;", "\\": "&#92;", "\"": "&quot;", "'": "&#39;", "<": "&lt;", ">": "&gt;"};
+var escapeHTML = function(s) {
+    if (!s) return s;
+    return s.toString().replace(_re1, function(c) { return escape_map[c]; });
+}
+
+var request = function (options, callback) {
+  options.success = function (obj) {
+    callback(null, obj);
+  }
+  options.error = function (err) {
+    if (err) callback(err);
+    else callback(true);
+  }
+  if (options.data && typeof options.data == 'object') {
+    options.data = JSON.stringify(options.data)
+  }
+  if (!options.dataType) options.processData = false;
+  if (!options.dataType) options.contentType = 'application/json';
+  if (!options.dataType) options.dataType = 'json';
+  $.ajax(options)
+}
+
+function prettyDate(time) {
+  if (time.indexOf('.') !== -1) time = time.slice(0, time.indexOf('.'))+'Z'
+  var date = new Date((time || "").replace(/-/g,"/").replace(/[TZ]/g," ")),
+      date = new Date(date.getTime() - (date.getTimezoneOffset() * 1000 * 60))
+      diff = (((new Date()).getTime() - date.getTime()) / 1000),
+      day_diff = Math.floor(diff / 86400)
+      ;
+  
+  if (day_diff === -1) return "now"
+  if ( day_diff >= 31) return day_diff + ' days ago';
+  if ( isNaN(day_diff) || day_diff < 0 || day_diff >= 31 ) return;
+  
+  return day_diff == 0 && (
+      diff < 60 && "just now" ||
+      diff < 120 && "1 minute ago" ||
+      diff < 3600 && Math.floor( diff / 60 ) + " minutes ago" ||
+      diff < 7200 && "1 hour ago" ||
+      diff < 86400 && Math.floor( diff / 3600 ) + " hours ago") ||
+    day_diff == 1 && "Yesterday" ||
+    day_diff < 7 && day_diff + " days ago" ||
+    day_diff < 31 && Math.ceil( day_diff / 7 ) + " weeks ago";
+}
+
+function isGithubUrl(url) {
+  return url.slice(0, 'http://github.com'.length) === 'http://github.com' ||
+         url.slice(0, 'https://github.com'.length) === 'https://github.com' ||
+         url.slice(0, 'git://github.com'.length) === 'git://github.com';
+}
+
+$.expr[":"].exactly = function(obj, index, meta, stack){ 
+  return ($(obj).text() == meta[3])
+}
+
+var param = function( a ) {
+  // Query param builder from jQuery, had to copy out to remove conversion of spaces to +
+  // This is important when converting datastructures to querystrings to send to CouchDB.
+  var s = [];
+  if ( jQuery.isArray(a) || a.jquery ) {
+    jQuery.each( a, function() { add( this.name, this.value ); });    
+  } else { 
+    for ( var prefix in a ) { buildParams( prefix, a[prefix] ); }
+  }
+  return s.join("&");
+  function buildParams( prefix, obj ) {
+    if ( jQuery.isArray(obj) ) {
+      jQuery.each( obj, function( i, v ) {
+        if (  /\[\]$/.test( prefix ) ) { add( prefix, v );
+        } else { buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "") +"]", v )}
+      });        
+    } else if (  obj != null && typeof obj === "object" ) {
+      jQuery.each( obj, function( k, v ) { buildParams( prefix + "[" + k + "]", v ); });        
+    } else { add( prefix, obj ); }
+  }
+  function add( key, value ) {
+    value = jQuery.isFunction(value) ? value() : value;
+    s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
+  }
+}
+
+function clearContent () {
+  $('div#content').html('')
+  $('div#totals').html('')
+}
+
+var app = {};
+app.index = function () {
+  var currentTerms = []
+    , searchResults = {}
+    , docs = {}
+    , currentSearch = ''
+    , lastSearchForPage = ''
+    , limit = 15
+    ;
+  clearContent();
+  $('#tabs a').removeClass('selected');
+  $('#tabs a.tab-find').addClass('selected');
+
+  $('div#content').html(
+  '' +
+    '<div id="search-box">' +
+      '<div id="search-box-input">' +
+        '<input id="search-input"></input>' +
+      '</div>' +
+    '</div>' +
+    '<div id="main-container">' +
+      '<div id="results"></div>' +
+      '<div class="spacer"></div>' +
+      '<div id="top-packages">' +
+        '<div id="latest-packages"><div class="top-title">Latest Updates</div></div>' +
+        '<div id="top-dep-packages"><div class="top-title">Most Depended On</div></div>' +
+      '</div>' +
+      '<div class="spacer"></div>' +
+    '</div>'
+  )
+  
+  request({url:'/api/_all_docs?limit=0'}, function (err, resp) {
+    $('div#totals').html('<a href="/#/_browse/all">' + (resp.total_rows - 1) +' total packages</a>')
+  })
+  
+  request({url:'/_view/updated?descending=true&limit='+limit+'&include_docs=false'}, function (err, resp) {
+    resp.rows.forEach(function (row) {
+      $('<div class="top-package"></div>')
+      .append('<div class="top-package-title"><a href="#/'+row.id+'">'+row.id+'</a></div>')
+      .append('<div class="top-package-updated">'+prettyDate(row.key) +'</div>')
+      .append('<div class="spacer"></div>')
+      .appendTo('div#latest-packages')
+    })
+  })
+  
+  request({url:'/_list/dependencies_limit/dependencies?group=true&descending=true&list_limit='+limit}, function (err, resp) {
+    var results = {};
+    resp.rows.forEach(function (row) {
+        $('<div class="top-package"></div>')
+        .append('<div class="top-package-title"><a href="#/'+escapeHTML(row.key)+'">'+escapeHTML(row.key)+'</a></div>')
+        .append('<div class="top-package-dep">'+escapeHTML(row.value)+'</div>')
+        .append('<div class="spacer"></div>')
+        .appendTo('div#top-dep-packages')
+    })
+  })
+    
+  var updateResults = function () {
+    currentSearch = $('input#search-input').val().toLowerCase();
+    currentTerms = $.trim(currentSearch).split(' ');
+    if (lastSearchForPage === currentSearch) return;
+    if (currentSearch == '') $('div#top-packages').show();
+    else $('div#top-packages').hide();
+    var docsInPage = {}
+      , ranked = {}
+      ;
+    currentTerms.forEach(function (term) {
+      if (searchResults[term] && searchResults[term] !== 'pending') {
+        searchResults[term].forEach(function (id) {
+          if (docs[id] !== 'pending') docsInPage[id] = docs[id]
+        });
+      }
+    })
+    for (i in docsInPage) {
+      var doc = docsInPage[i];
+      doc.rank = 0
+      doc.tagsInSearch = [];
+      if (doc.description) {
+        doc.htmlDescription = doc.description.split('&').join('&amp;')
+                                             .split('"').join('&quot;')
+                                             .split('<').join('&lt;')
+                                             .split('>').join('&gt;')
+      }
+      
+      if (doc._id.toLowerCase() === currentSearch) doc.rank += 1000      
+      
+      if (doc['dist-tags'] && doc['dist-tags'].latest) {
+        var tags = doc.versions[doc['dist-tags'].latest].keywords || doc.versions[doc['dist-tags'].latest].tags || [];
+      } else { 
+        var tags = [];
+      }
+      
+      tags = tags.map(function (tag) {
+          return tag.split('&').join('&amp;')
+                    .split('"').join('&quot;')
+                    .split('<').join('&lt;')
+                    .split('>').join('&gt;')
+      })
+      currentTerms.forEach(function (t) {
+        t = t.toLowerCase();
+        if (doc._id.toLowerCase().indexOf(t.toLowerCase()) !== -1) doc.rank += 750;
+        if (tags.indexOf(t) !== -1) {
+          doc.rank += 300;
+          doc.tagsInSearch.push(t);
+        }
+        if (doc.description && doc.description.toLowerCase().indexOf(t) !== -1) {
+          doc.rank += 100;
+          var i = 0;
+          while (doc.htmlDescription.toLowerCase().indexOf(t, i) !== -1) {
+            var i = doc.htmlDescription.toLowerCase().indexOf(t, i);
+            doc.htmlDescription = 
+                                ( doc.htmlDescription.slice(0, i) 
+                                + '<span class="desc-term">'
+                                + doc.htmlDescription.slice(i, i+t.length)
+                                + '</span>'
+                                + doc.htmlDescription.slice(i + t.length)
+                                )
+                                ;
+            i = i + t.length + '<span class="desc-term"></span>'.length
+          }
+          
+        }
+        doc.tags = tags;
+      })
+      
+      if (!ranked[doc.rank]) ranked[doc.rank] = [];
+      ranked[doc.rank].push(doc);
+    }
+    
+    $('div#results').html('');
+    var keys = Object.keys(ranked);
+    for (var i=0;i<keys.length;i++) keys[i] = parseInt(keys[i])
+    keys.sort(function(a,b){return a - b;});
+    keys.reverse();
+    if (keys.length === 0) {
+      $('div#results').html('<div>No Results</div>')
+    }
+    keys.forEach(function (i) { ranked[i].forEach(function (doc) {
+      var result = $(
+        '<div class="result-container">' +
+          '<div class="result">' + 
+            '<span class="result-name"><a href="#/'+doc._id+'">'+doc._id+'</a></span>' + 
+            '<span class="result-desc">'+(doc.htmlDescription || '') + '</span>' +
+            '<div class="result-tags"></div>' +
+            '<div class="spacer"></div>' +
+          '</div>' +
+        '</div>' +
+        '<div class="spacer"></div>'
+      )
+      
+      if (doc.tags.length > 0) {
+        doc.tags.forEach(function (tag) {
+          result.find('div.result-tags').append('<span class="tag">'+tag+'</span>')
+        })
+      }
+      
+      result.appendTo('div#results')
+      $('span.tag').click(function () {
+        $('input#search-input').val($(this).text()).change();
+      })
+    })})
+    
+    lastSearchForPage = currentSearch;
+  }  
+  
+  var hcTimer = null;
+  var handleChange = function () {
+    if (hcTimer) clearTimeout(hcTimer);
+    hcTimer = setTimeout(handleChange_, 100);
+  }
+  function handleChange_ () {
+    currentSearch = $('input#search-input').val().toLowerCase();
+    currentTerms = $.trim(currentSearch).split(' ')
+    if (currentSearch === '') {
+      $('div#results').html('')
+      $('div#top-packages').show();
+    }
+    lastSearchForPage = ''
+    var terms = currentTerms
+      , c = currentSearch
+      , tlength = terms.length
+      ;
+
+    terms.forEach(function (term) {
+      if (!searchResults[term]) {
+        searchResults[term] = 'pending'
+        var qs = param(
+          { startkey: JSON.stringify(term)
+          , endkey: JSON.stringify(term+'ZZZZZZZZZZZZZZZZZZZ')
+          , limit:25
+          }
+        )
+        ;
+        request({url:'/_list/search/search?'+qs}, function (err, resp) {
+          var docids = [];
+          searchResults[term] = [];
+          resp.rows.forEach(function (row) {
+            searchResults[term].push(row.key);
+            row.value.name = row.value.name.toLowerCase();
+            docs[row.key] = row.value;
+            updateResults();
+          })
+          if (docids.length === 0) {
+            lastSearchForPage = '';
+            updateResults();
+            return 
+          }
+          
+        })
+      } else {tlength -= 1}
+    })
+    if (tlength == 0) {lastSearchForPage = ''; updateResults()}
+  }
+  
+  $('input#search-input').change(handleChange);
+  $('input#search-input').keyup(handleChange)
+  $("input#search-input").focus();
+};
+
+app.showPackage = function () {
+  var id = this.params.id;
+  clearContent();
+  $('div#content').html('<div id="main-container"></div>')
+  request({url:'/api/'+id}, function (err, doc) {
+    var package = $('div#main-container')
+    
+    package.append('<div class="package-title">'+doc._id+'</div>')
+    // package.append('<div class="package-description">'+doc.description+'</div>')
+    
+    if (doc['dist-tags'] && doc['dist-tags'].latest) {
+      if (doc.versions[doc['dist-tags'].latest].homepage) {
+        package.append('<div class="pkg-link"><a href="'+escapeHTML(doc.versions[doc['dist-tags'].latest].homepage)+'">'+escapeHTML(doc.versions[doc['dist-tags'].latest].homepage)+'</a>')
+      }
+    }
+    
+    if (typeof doc.repository === 'string') {
+      repositoryUrl = doc.repository;
+      doc.repository = {
+        type: (isGithubUrl(repositoryUrl) ? 'git' : 'unknown'),
+        url: repositoryUrl
+      }
+    }
+    if (doc.repository && doc.repository.type === 'git' && isGithubUrl(doc.repository.url) ) {
+          package.append('<div class="pkg-link"><a class="github" href="' + escapeHTML(doc.repository.url.replace('.git', '').replace('git://', 'https://')) + '">github</a></div>')
+    }
+     
+    
+    package.append('<div class="spacer"></div>')
+    if (doc.time && doc.time.modified) {
+      package.append('<div class="last-updated">Last updated: '+prettyDate(doc.time.modified)+'</div>')
+    }
+    if (doc.author && doc.author.name) {
+      package.append('<div class="author">by: <a href="/#/_author/'+encodeURIComponent(doc.author.name)+'">'+doc.author.name+'</div>')
+    }
+    
+
+    // 
+    // if (doc.maintainers && doc.maintainers.length > 0) {
+    //   var maintainers = $('<div class="package-maintainers"></div>').appendTo(package);
+    //   doc.maintainers.forEach(function (m) {
+    //     maintainers.append('<div class="package-maintainer">maintainer: '+m.name+'   </div>')
+    //   })
+    // }
+    
+    package.append(
+      '<div id="versions-container">' + 
+        '<div id="version-list"></div>' + 
+        '<div id="version-info"></div>' +
+        '<div class="spacer"></div>' +
+      '</div>'
+    )
+    
+    var showVersion = function (version) {
+      var v = doc.versions[version];
+      
+      if (v.description) {
+        v.htmlDescription = v.description.split('&').join('&amp;')
+                                             .split('"').join('&quot;')
+                                             .split('<').join('&lt;')
+                                             .split('>').join('&gt;')
+      } else {
+        v.htmlDescription = ""
+      }
+      
+      $('div#version-info').html(
+        '<div class="version-info-cell">' +
+          '<div class="version-info-key">Description</div>' +
+          '<div class="version-info-value">'+v.htmlDescription+'</div>' +
+        '</div>' + 
+        '<div class="spacer"></div>' +
+        '<div class="version-info-cell">' +
+          '<div class="version-info-key">Version</div>' +
+          '<div class="version-info-value">'+v.version+'</div>' +
+        '</div>' + 
+        '<div class="spacer"></div>'
+      );
+      
+      if (doc.time && doc.time[version]) {
+        $('div#version-info').append(
+          '<div class="version-info-cell">' +
+            '<div class="version-info-key">Published</div>' +
+            '<div class="version-info-value">' + prettyDate(doc.time[version]) + '</div>' +
+          '</div>' +
+          '<div class="spacer"></div>'
+        )
+      }
+
+      if (v.tags) {
+        var h = '[ ';
+        v.tags.forEach(function (tag) {
+          if (tag !== v.tags[0]) h += ', '
+          h += ('<a href="/#/_tags/'+escapeHTML(tag)+'">'+escapeHTML(tag)+'</a>')
+        })
+        h += ' ]'
+        $('div#version-info').append(
+          '<div class="version-info-cell">' +
+            '<div class="version-info-key">Tags</div>' +
+            '<div class="version-info-value">' + h + '</div>' +
+          '</div>' +
+          '<div class="spacer"></div>' 
+        )
+      }
+      
+      if (v.dependencies) {
+        var h = ''
+        for (i in v.dependencies) {
+          h += '<a class="dep-link" href="#/'+escapeHTML(i)+'">'+escapeHTML(i)+'</a> '
+        }
+        $('div#version-info').append('<div class="version-info-cell">' +
+            '<div class="version-info-key">Dependencies</div>' +
+            '<div class="version-info-value">' + h + '</div>' +
+          '</div>' +
+          '<div class="spacer"></div>'
+        )
+      }
+      
+      if (v.homepage) {
+        $('div#version-info').append(
+          '<div class="version-info-cell">' +
+            '<div class="version-info-key">Homepage</div>' +
+            '<div class="version-info-value">' + escapeHTML(v.homepage) + '</div>' +
+          '</div>' +
+          '<div class="spacer"></div>'
+        )
+      }
+      if (v.repository) {
+        if (typeof v.repository === 'string') {
+          repositoryUrl = v.repository;
+          v.repository = {
+            type: (isGithubUrl(repositoryUrl) ? 'git' : 'unknown'),
+            url: repositoryUrl
+          };
+        }
+        $('div#version-info').append(
+          '<div class="version-info-cell">' +
+            '<div class="version-info-key">Repository</div>' +
+            '<div class="version-info-value">' + 
+              escapeHTML(v.repository.type) + ':    <a href="' + escapeHTML(v.repository.url) + '">'+ escapeHTML(v.repository.url) + '</a>' +
+            '</div>' +
+          '</div>' +
+          '<div class="spacer"></div>'
+        )
+      }
+      if (v.bugs) {
+        var bugs = $(
+          '<div class="version-info-cell">' +
+            '<div class="version-info-key">Bugs</div>' +
+            '<div class="version-info-value"></div>' +
+          '</div>' +
+          '<div class="spacer"></div>'
+        )
+        var bugsHtml = ''
+        if (v.bugs.email) {
+          bugsHtml+= '<div>email:    ' + '<a href="mailto='+v.bugs.email+'">'+v.bugs.email+'</a></div>'
+        }
+        if (v.bugs.url) {
+          bugsHtml += '<div>url:    ' + '<a href="'+v.bugs.url+'">'+v.bugs.url+'</a></div>'
+        }
+        bugs.find('div.version-info-value').html(bugsHtml)
+        $('div#version-info').append(bugs)
+      }
+      if (v.engines) {
+      var eng = [];
+        for (i in v.engines) { eng.push( escapeHTML(i) + ' (' + escapeHTML(v.engines[i]) + ')' ); }
+        $(
+          '<div class="version-info-cell">' +
+            '<div class="version-info-key">Engines</div>' +
+            '<div class="version-info-value">'+eng.join(', ')+'</div>' +
+          '</div>' +
+          '<div class="spacer"></div>'
+        ).appendTo('div#version-info');
+      }
+      if (v.licenses) {
+      h = '';
+        for (i in v.licenses) {
+          h += '<a href="'+escapeHTML(v.licenses[i].url)+'">'+escapeHTML(v.licenses[i].type)+'</a>';
+        }
+        $(
+          '<div class="version-info-cell">' +
+            '<div class="version-info-key">Licenses</div>' +
+            '<div class="version-info-value">'+h+'</div>' +
+          '</div>' +
+          '<div class="spacer"></div>'
+        ).appendTo('div#version-info');
+      }
+
+      
+      //  +
+      // '<div class="version-info-cell">' +
+      //   '<span class="version-info-key">Author</span>' +
+      //   '<span class="version-info-value">'+v.htmlDescription+'<span>' +
+      // '</div>' +
+      // '<div class="version-info-cell">' +
+      //   '<span class="version-info-key">Repository</span>' +
+      //   '<span class="version-info-value">'+v.htmlDescription+'<span>' +
+      // '</div>' +
+      
+    }
+    showVersion(doc['dist-tags'].latest);
+    
+    if (doc['dist-tags']) {
+      for (i in doc['dist-tags']) {
+        $('<div class="package-download">' +
+            '<div id="'+doc['dist-tags'][i]+'" class="version-link">'+
+              '<a href="' + doc.versions[doc['dist-tags'][i]].dist.tarball.replace('jsregistry:5984', 'registry.npmjs.org').replace('packages:5984', 'registry.npmjs.org')+'">'+i+'</a>  ('+doc.versions[doc['dist-tags'][i]].version+')' + 
+            '</div>' +
+          '</div>')
+          .addClass('version-selected')
+          .appendTo('div#version-list')
+          ;
+      }
+      package.append('<br/>')
+    }
+    
+    if (doc.versions) {
+      var versions = Object.keys(doc.versions);
+      versions.reverse();
+      versions.forEach(function (i) {
+        $('div#version-list').append(
+          '<div class="package-download">' +
+            '<div id="'+i+'" class="version-link">'+
+              '<a href="'+doc.versions[i].dist.tarball.replace('jsregistry:5984', 'registry.npmjs.org').replace('packages:5984', 'registry.npmjs.org')+'">'+i+'</a>' + 
+            '</div>' +
+          '</div>'
+        )
+      })
+    }
+    
+    $('div.version-link').mouseover(function () {
+      $('div.version-selected').removeClass('version-selected');
+      $(this).parent().addClass('version-selected');
+      $('div#version-info').css(
+        { top: $(this).position().top - $(this).parent().parent().position().top 
+        , position:'relative'
+        })
+      showVersion(this.id)
+    })
+    
+    var usersStr = '<h4>People who starred '+id+'</h4><div class="users"><p>'
+    if (doc.users)
+      for (var usingUser in doc.users)
+        if (doc.users[usingUser])
+          usersStr += (usersStr.length?' ':'')+'<span class="user">'+usingUser.replace(/</g, '&lt;').replace(/>/g, '&gt;')+'</span>'
+      usersStr += '</p></div>'
+      package.append(usersStr)
+
+    request({url:'/_view/dependencies?reduce=false&key="'+id+'"'}, function (e, resp) {
+      if (resp.rows.length === 0) return;
+      var deps = ''
+      deps += '<h4>Packages that depend on '+id+'</h4><div class="dependencies"><p>'
+      for (var i=0;i<resp.rows.length;i++) {
+        deps += '<span class="dep"><a class="dep" href="/#/' +
+                 resp.rows[i].id+'">'+resp.rows[i].id+'</a></span> '
+      }
+      deps += '</p></div>'
+      package.append(deps)
+    })
+  })
+}
+
+app.browse = function () {
+  var limit = 100
+    ;
+  clearContent();
+  
+  $(
+    '<div id="browse-anchors">' +
+      '<a href="/#/_browse/all">all</a>' +
+      '<a href="/#/_browse/tags">tags</a>' +
+      '<a href="/#/_browse/author">author</a>' +
+      '<a href="/#/_browse/updated">updated</a>' +
+      '<a href="/#/_browse/deps">depended on</a>' +
+    '</div>'
+  )
+  .appendTo('div#content')
+  
+  $('#tabs a').removeClass('selected');
+  $('#tabs a.tab-browse').addClass('selected');
+
+  var c = $('<div id="main-container"></div>')
+    .appendTo('div#content')
+    ;
+  var fetch = function (url, cb) {
+    $('div#more-all').remove();
+    request({url:url(limit)}, function (err, resp) {
+      cb(resp);
+      limit += 100;
+      $('<div id="more-all">Load 100 more</div>')
+        .click(function () {fetch(url, cb);})
+        .appendTo(c)
+        ;
+    })
+  }
+  
+  var routes = {};
+  routes.all = function () {
+    fetch( 
+      function (limit) {
+        return '/api/_all_docs?include_docs=true&limit='+limit+'&skip='+(limit - 100) 
+      }
+      , function (r) {
+        var h = ''
+        r.rows.forEach(function (row) {
+          if (!row.doc.description) row.doc.description = ""
+          row.doc.htmlDescription = row.doc.description
+                                    .split('&').join('&amp;')
+                                    .split('"').join('&quot;')
+                                    .split('<').join('&lt;')
+                                    .split('>').join('&gt;')
+          if (row.id[0] !== '_') {
+            h += (
+              '<div class="all-package">' + 
+                '<div class="all-package-name"><a href="/#/'+row.id+'">' + row.id + '</a></div>' +
+                '<div class="all-package-desc">' + row.doc.htmlDescription + '</div>' +
+              '</div>' +
+              '<div class="spacer"></div>'
+            )
+          }
+        });
+      c.append(h);
+      }
+    );
+    $('a:exactly("all")').css('text-decoration', 'underline');
+  }
+  routes.tags = function () {
+    request({url:'/_view/tags?group=true'}, function (e, resp) {
+      resp.rows.forEach(function (row) {
+        c.append(
+          '<div class="all-package">' + 
+            '<div class="all-package-name"><a href="/#/_tag/'+encodeURIComponent(row.key)+'">' + row.key + '</a></div>' +
+            '<div class="all-package-desc">' + row.value + '</div>' +
+          '</div>' +
+          '<div class="spacer"></div>'
+        )
+      })
+      
+      request({url:'/_view/tags?reduce=false'}, function (e, resp) {
+        resp.rows.forEach(function (row) {
+          $('div.all-package-name:exactly("'+row.key+'")').next().append('<a href="/#/'+row.id+'" class="tag-val">'+row.id+'</a>')
+        })
+        $(self).remove();
+      })
+    })
+    $('a:exactly("tags")').css('text-decoration', 'underline');
+  }
+  routes.author = function () {
+    request({url:'/_view/author?group=true'}, function (e, resp) {
+      resp.rows.forEach(function (row) {
+        c.append(
+          '<div class="all-package">' + 
+            '<div class="all-package-author"><a href="/#/_author/'+encodeURIComponent(row.key)+'">' + row.key + '</a></div>' +
+            '<div class="all-package-auth-list">' + row.value + '</div>' +
+          '</div>' +
+          '<div class="spacer"></div>'
+        )
+      })
+      
+      request({url:'/_view/author?reduce=false'}, function (e, resp) {
+        resp.rows.forEach(function (row) {
+          $('div.all-package-author:exactly("'+row.key+'")').next().append('<a href="/#/'+row.id+'" class="tag-val">'+row.id+' </a>')
+        })
+        $(self).remove();
+      })
+    })
+    $('a:exactly("author")').css('text-decoration', 'underline');
+  }
+  routes.updated = function () {
+    request({url:'/_view/updated'}, function (e, resp) {
+      resp.rows.reverse();
+      resp.rows.forEach(function (row) {
+        c.append(
+          '<div class="all-package">' + 
+            '<div class="all-package-name">'+ prettyDate(row.key) +'</div>' +
+            '<div class="all-package-value"><a href="/#/'+encodeURIComponent(row.id)+'">' + row.id + '</a></div>' +
+          '</div>' +
+          '<div class="spacer"></div>'
+        )
+      })
+    })
+    $('a:exactly("updated")').css('text-decoration', 'underline');
+  }
+  routes.deps = function () {
+    request({url:'/_view/dependencies?group=true'}, function (e, resp) {
+      var deps = {};
+      resp.rows.forEach(function (row) {
+        if (!deps[row.value]) deps[row.value] = []
+        deps[row.value].push(row)
+      })
+      var keys = Object.keys(deps);
+      keys.sort(function(a,b){return a - b;});
+      keys.reverse();
+      keys.forEach(function (k) {
+        deps[k].forEach(function (row) {
+          c.append(
+            '<div class="all-package">' + 
+              '<div class="all-package-deps"><a href="/#/'+encodeURIComponent(row.key)+'">' + escapeHTML(row.key) + '</a></div>' +
+              '<div class="all-package-deps-value">'+escapeHTML(row.value)+'</div>' +
+            '</div>' +
+            '<div class="spacer"></div>'
+          )
+        })
+      })
+    })
+    $('a:exactly("depended on")').css('text-decoration', 'underline');
+  }
+  if (this.params.view) routes[this.params.view]();
+}
+app.tags = function () {
+  var tag = this.params.tag.split('&').join('&amp;')
+                           .split('"').join('&quot;')
+                           .split('<').join('&lt;')
+                           .split('>').join('&gt;')
+  clearContent();
+  $('div#content')
+  .append('<h2 style="text-align:center">tag: '+tag+'</h2>')
+  .append('<div id="main-container"></div>');
+  request({url:'/_view/tags?reduce=false&include_docs=true&key="'+tag+'"'}, function (e, resp) {
+    resp.rows.forEach(function (row) {
+      if (row.doc.description) {
+        row.doc.htmlDescription = row.doc.description.split('&').join('&amp;')
+                                             .split('"').join('&quot;')
+                                             .split('<').join('&lt;')
+                                             .split('>').join('&gt;')
+      } else {
+        row.doc.htmlDescription = ''
+      }
+      $('div#main-container').append(
+        '<div class="all-package">' + 
+          '<div class="tags-pkg-name"><a href="/#/'+encodeURIComponent(row.key)+'">' + row.id + '</a></div>' +
+          '<div class="tags-pkg-desc">'+row.doc.htmlDescription+'</div>' +
+        '</div>' +
+        '<div class="spacer"></div>'
+      );
+      
+    })
+  })
+}
+app.author = function () {
+  var author = this.params.author;
+  clearContent();
+  $('div#content')
+  .append('<h2 style="text-align:center">author: '+escapeHTML(author)+'</h2>')
+  .append('<div id="main-container"></div>');
+  request({url:'/_view/author?reduce=false&include_docs=true&key="'+author+'"'}, function (e, resp) {
+    resp.rows.forEach(function (row) {
+      if (row.doc.description) {
+        row.doc.htmlDescription = row.doc.description.split('&').join('&amp;')
+                                             .split('"').join('&quot;')
+                                             .split('<').join('&lt;')
+                                             .split('>').join('&gt;')
+      } else {
+        row.doc.htmlDescription = ''
+      }
+      $('div#main-container').append(
+        '<div class="all-package">' + 
+          '<div class="tags-pkg-name"><a href="/#/'+encodeURIComponent(row.id)+'">' + row.id + '</a></div>' +
+          '<div class="tags-pkg-desc">'+row.doc.htmlDescription+'</div>' +
+        '</div>' +
+        '<div class="spacer"></div>'
+      );
+      
+    })
+  })
+}
+app.analytics = function () {
+  clearContent();
+  var view = this.params.view || "thisweek";
+  $('div#content').html(
+    '<div id="browse-anchors">' +
+      '<a href="/#/_analytics/thisweek">This Week</a>' +
+      '<a href="/#/_analytics/30days">30 Days</a>' +
+      '<a href="/#/_analytics/alltime">All Time</a>' +
+    '</div>' +
+    '<div id="main-container">' +
+      '<div id="analytics-created"></div>' +
+      '<div id="analytics-latest"></div>' +
+      '<div id="analytics-updated"></div>' +
+    '</div>'  
+  )
+  
+   $('a:exactly("'+{thisweek:'This Week', '30days':'30 Days', alltime:'All Time'}[view]+'")').css('text-decoration', 'underline');
+  
+  $.getScript('/highcharts/highcharts.js', function () {
+    var dt = new Date();
+    if (view == 'thisweek') {
+      dt.setDate(dt.getDate() - 7);
+    }
+    if (view == '30days') {
+      dt.setDate(dt.getDate() - 30);
+    }
+    
+    var series = [];
+    
+    var extract = function (resp, name) {
+      var times = {};
+      resp.rows.reverse();
+      resp.rows.forEach(function (row) {
+        if (view === 'thisweek') {
+          var t = row.key[1].slice(0, 10);
+        }
+        if (view === '30days') {
+          var t = row.key[1].slice(8, 10);
+        }
+        if (view === 'alltime') {
+          var t = row.key[1].slice(0, 7);
+        }
+        
+        if (!times[t]) times[t] = 0;
+        times[t] += 1;
+      })
+      var x = {name:name, data:[]};
+      for (i in times) {
+        x.data.push(times[i]);
+      }
+      series.push(x);
+      if (series.length === 3) graph(times);
+    }
+    
+    graphNames = 
+      { thisweek: 'This Week'
+      , '30days': '30 Days' 
+      , alltime: 'All Time'
+      }
+    
+    var graph = function (times) {
+      chart = new Highcharts.Chart(
+        {
+          chart: {
+             renderTo: 'analytics-created',
+             defaultSeriesType: 'line'
+          },
+          title: {
+             text: graphNames[view]
+          },
+          xAxis: {
+             categories: Object.keys(times)
+          },
+          tooltip: {
+             enabled: false,
+             formatter: function() {
+                return '<b>'+ this.series.name +'</b><br/>'+
+                   this.x +': '+ this.y +'°C';
+             }
+          },
+          plotOptions: {
+             line: {
+                dataLabels: {
+                   enabled: true
+                },
+                enableMouseTracking: false
+             }
+          },
+          series: series
+       });
+    }
+    
+    if (view === 'thisweek' || view === '30days') {
+      var endkey = dt.toISOString().slice(0, 10);
+    }
+    if (view === 'alltime') {
+      var endkey = null;
+    }
+    
+    request({url:'/_view/analytics?'+param(
+      {reduce:'false'
+      , descending:'true'
+      , endkey:JSON.stringify(['created', endkey])
+      , startkey:JSON.stringify(['created', new Date()])
+      })}, 
+      function (e, resp) {
+        extract(resp, 'created')
+    })
+    request({url:'/_view/analytics?'+param(
+      {reduce:'false'
+      , descending:'true'
+      , endkey:JSON.stringify(['update', endkey])
+      , startkey:JSON.stringify(['update', new Date()])
+      })}, 
+      function (e, resp) {
+        
+        extract(resp, 'updated')
+    })
+    request({url:'/_view/analytics?'+param(
+      {reduce:'false'
+      , descending:'true'
+      , endkey:JSON.stringify(['latest', endkey])
+      , startkey:JSON.stringify(['latest', new Date()])
+      })}, 
+      function (e, resp) {
+        extract(resp, 'latest')
+    })
+  })
+}
+
+$(function () { 
+  app.s = $.sammy(function () {
+    // Index of all databases
+    this.get('', app.index);
+    this.get("#/", app.index);
+    this.get("#/_analytics", app.analytics);
+    this.get("#/_analytics/:view", app.analytics);
+    this.get("#/_browse", app.browse);
+    this.get("#/_browse/:view", app.browse);
+    this.get("#/_tag/:tag", app.tags);
+    this.get("#/_author/:author", app.author);
+    this.get("#/_install", function () {
+      clearContent();
+      request({url:'/install.html', dataType:'html'}, function (e, resp) {
+        $('div#content').html('<div id="main-container">'+resp+'</div>');
+      })
+    });
+    this.get("#/_publish", function () {
+      clearContent();
+      request({url:'/publish.html', dataType:'html'}, function (e, resp) {
+        $('div#content').html('<div id="main-container">'+resp+'</div>');
+      })
+    });
+    this.get("#/_more", function () {
+      clearContent();
+      $('#tabs a').removeClass('selected');
+      $('#tabs a.tab-more').addClass('selected');
+      request({url:'/more.html', dataType:'html'}, function (e, resp) {
+        $('div#content').html('<div id="main-container">'+resp+'</div>');
+      })
+    });
+    this.get("#/:id", app.showPackage);
+    
+    
+  })
+  app.s.run();
+});


[9/9] git commit: first commit

Posted by an...@apache.org.
first commit


Project: http://git-wip-us.apache.org/repos/asf/cordova-registry-web/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-registry-web/commit/f50cc931
Tree: http://git-wip-us.apache.org/repos/asf/cordova-registry-web/tree/f50cc931
Diff: http://git-wip-us.apache.org/repos/asf/cordova-registry-web/diff/f50cc931

Branch: refs/heads/master
Commit: f50cc931fb8a8051abf4b504a5e7ff8cbf4b560c
Parents: 
Author: Anis Kadri <an...@apache.org>
Authored: Mon Oct 21 16:23:49 2013 -0700
Committer: Anis Kadri <an...@apache.org>
Committed: Mon Oct 21 16:23:49 2013 -0700

----------------------------------------------------------------------
 app.js                                          |   169 +
 attachments/font/fonts/icomoon.dev.svg          |    18 +
 attachments/font/fonts/icomoon.eot              |   Bin 0 -> 1644 bytes
 attachments/font/fonts/icomoon.svg              |    18 +
 attachments/font/fonts/icomoon.ttf              |   Bin 0 -> 1480 bytes
 attachments/font/fonts/icomoon.woff             |   Bin 0 -> 1216 bytes
 attachments/font/lte-ie7.js                     |    28 +
 attachments/font/style.css                      |    42 +
 .../highcharts/adapters/mootools-adapter.js     |    11 +
 .../highcharts/adapters/mootools-adapter.src.js |   214 +
 .../highcharts/adapters/prototype-adapter.js    |    14 +
 .../adapters/prototype-adapter.src.js           |   254 +
 attachments/highcharts/highcharts.js            |   160 +
 attachments/highcharts/highcharts.src.js        | 10580 +++++++++++++++++
 attachments/highcharts/modules/exporting.js     |    21 +
 attachments/highcharts/modules/exporting.src.js |   671 ++
 attachments/highcharts/themes/dark-blue.js      |   170 +
 attachments/highcharts/themes/dark-green.js     |   170 +
 attachments/highcharts/themes/gray.js           |   164 +
 attachments/highcharts/themes/grid.js           |    97 +
 attachments/images/favicon.ico                  |   Bin 0 -> 1150 bytes
 attachments/images/grid.png                     |   Bin 0 -> 1169 bytes
 attachments/index.html                          |    50 +
 attachments/install.html                        |    20 +
 attachments/jquery-1.4.4.min.js                 |   167 +
 attachments/layout.css                          |   387 +
 attachments/layout.less                         |   461 +
 attachments/more.html                           |     3 +
 attachments/publish.html                        |     0
 attachments/sammy/plugins/sammy.cache.js        |   115 +
 .../sammy/plugins/sammy.data_location_proxy.js  |    78 +
 attachments/sammy/plugins/sammy.ejs.js          |   700 ++
 attachments/sammy/plugins/sammy.form.js         |   274 +
 attachments/sammy/plugins/sammy.haml.js         |   553 +
 attachments/sammy/plugins/sammy.json.js         |   362 +
 attachments/sammy/plugins/sammy.meld.js         |   140 +
 attachments/sammy/plugins/sammy.mustache.js     |   444 +
 .../sammy/plugins/sammy.nested_params.js        |   118 +
 .../sammy/plugins/sammy.path_location_proxy.js  |    29 +
 attachments/sammy/plugins/sammy.pure.js         |   756 ++
 attachments/sammy/plugins/sammy.storage.js      |   577 +
 attachments/sammy/plugins/sammy.template.js     |   117 +
 attachments/sammy/plugins/sammy.title.js        |    59 +
 attachments/sammy/sammy.js                      |  1704 +++
 attachments/site.js                             |   955 ++
 45 files changed, 20870 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/app.js
----------------------------------------------------------------------
diff --git a/app.js b/app.js
new file mode 100644
index 0000000..4ebf2b6
--- /dev/null
+++ b/app.js
@@ -0,0 +1,169 @@
+var couchapp = require('couchapp')
+  , path = require('path')
+
+
+ddoc =
+  { _id:'_design/ui'
+  , rewrites :
+    [ {from:"/", to:'index.html'}
+    , {from:"/favicon.ico", to:'../../npm/favicon.ico'}
+    , {from:"/api", to:'../../'}
+    , {from:"/api/*", to:'../../*'}
+    , {from:"/*", to:'*'}
+    ]
+  , lists : {}
+  }
+
+
+function packageSearch (doc) {
+  var descriptionBlacklist =
+    [ "for"
+    , "and"
+    , "in"
+    , "are"
+    , "is"
+    , "it"
+    , "do"
+    , "of"
+    , "on"
+    , "the"
+    , "to"
+    , "as"
+    ]
+
+  if (doc.name) { // There aren't any better attributes for check if isPackage()
+    if (doc.name) {
+      var names = [doc.name];
+      if (doc.name.indexOf('-') !== -1) doc.name.split('-').forEach(function (n) {names.push(n)});
+      if (doc.name.indexOf('_') !== -1) doc.name.split('_').forEach(function (n) {names.push(n)});
+      names.forEach(function (n) {
+        if (n.length > 1) emit(n.toLowerCase(), doc);
+      });
+    }
+    if (doc['dist-tags'] && doc['dist-tags'].latest && (
+        doc.versions[doc['dist-tags'].latest].keywords || doc.versions[doc['dist-tags'].latest].tags
+        )) {
+      var tags = (doc.versions[doc['dist-tags'].latest].keywords || doc.versions[doc['dist-tags'].latest].tags)
+      tags.forEach(function (tag) {
+        tag.split(' ').forEach(function (t) {
+          if (t.length > 0) emit(t.toLowerCase(), doc);
+        });
+      })
+    }
+    if (doc.description) {
+      doc.description.split(' ').forEach(function (d) {
+        d = d.toLowerCase();
+        while (d.indexOf('.') !== -1) d = d.replace('.', '');
+        while (d.indexOf('\n') !== -1) d = d.replace('\n', '');
+        while (d.indexOf('\r') !== -1) d = d.replace('\n', '');
+        while (d.indexOf('`') !== -1) d = d.replace('`', '');
+        while (d.indexOf('_') !== -1) d = d.replace('_', '');
+        while (d.indexOf('"') !== -1) d = d.replace('"', '');
+        while (d.indexOf('\'') !== -1) d = d.replace('\'', '');
+        while (d.indexOf('(') !== -1) d = d.replace('(', '');
+        while (d.indexOf(')') !== -1) d = d.replace(')', '');
+        while (d.indexOf('[') !== -1) d = d.replace('[', '');
+        while (d.indexOf(']') !== -1) d = d.replace(']', '');
+        while (d.indexOf('{') !== -1) d = d.replace('{', '');
+        while (d.indexOf('}') !== -1) d = d.replace('}', '');
+        while (d.indexOf('*') !== -1) d = d.replace('*', '');
+        while (d.indexOf('%') !== -1) d = d.replace('%', '');
+        while (d.indexOf('+') !== -1) d = d.replace('+', '');
+        if (descriptionBlacklist.indexOf(d) !== -1) d = '';
+        if (d.length > 1) emit(d, doc);
+      })
+    }
+  }
+}
+
+function dependencies (doc) {
+  if (doc['dist-tags'] && doc['dist-tags'].latest) {
+    var dist = doc.versions[doc['dist-tags'].latest];
+    for (i in dist.dependencies) {
+      emit(i, dist.dependencies[i])
+    }
+  }
+}
+
+ddoc.views =
+  { search: { map: packageSearch }
+  , dependencies: {map: dependencies, reduce:"_count"}
+  , updated: {map: function (doc) {
+      var l = doc["dist-tags"].latest
+        , t = doc.time && doc.time[l]
+      if (t) emit(t, 1)
+    }}
+  , tags:
+    { map: function (doc) {
+             if (doc['dist-tags'] && doc['dist-tags'].latest) {
+              doc.versions[doc['dist-tags'].latest].tags.forEach(function (t) {emit(t, 1)})
+             }
+           }
+    , reduce: "_sum"
+    }
+  , author:
+    { map: function (doc) {
+             if (doc.author && doc.author.name) {
+               emit(doc.author.name, 1);
+             }
+           }
+    , reduce: "_sum"
+    }
+  , analytics:
+    { map: function (doc) {
+             if (doc.time) {
+               if (doc.time.modified) {
+                 emit(['latest', doc.time.modified], 1);
+               }
+               if (doc.time.created) {
+                 emit(['created', doc.time.created], 1);
+               }
+               for (i in doc.time) {
+                 emit(['update', doc.time[i]], 1);
+               }
+             }
+           }
+    , reduce: "_sum"
+    }
+  }
+  ;
+  
+ddoc.lists.dependencies_limit = function(head, req) {
+    var deps = [];
+    while(row = getRow()) {
+        deps.push(row);
+    }
+    var sorted = deps.sort(function(a,b) { return req.query.descending !== "true" ? a.value - b.value : b.value - a.value; });    
+    // using list_Limit rather than limit because limit appears to limit the initial view set
+    // assuming there's a supported convention but using this for now
+    var limit = req.query.list_limit && parseInt(req.query.list_limit);
+    send(JSON.stringify({ total_rows: deps.length, rows: limit ? sorted.splice(0, limit) : sorted}));
+};
+
+ddoc.lists.search = function(head, req) {
+    Object.keys = Object.keys
+      || function (o) { var a = []
+                        for (var i in o) a.push(i)
+                        return a }
+    var set = {};
+    var rows = [];
+    while(row = getRow()) {
+        set[row.id] = { key: row.id, count: set[row.id] ? set[row.id].count + 1 : 1, value: row.value };
+    }
+    var keys = Object.keys(set);
+    for(var i=0; i<keys.length; i++) {
+        rows.push(set[keys[i]]);
+    }
+    send(JSON.stringify({ rows: rows} ));
+};
+
+
+// ddoc.validate_doc_update = function (newDoc, oldDoc, userCtx) {
+//   if (newDoc._deleted === true && userCtx.roles.indexOf('_admin') === -1) {
+//     throw "Only admin can delete documents on this database.";
+//   }
+// }
+
+couchapp.loadAttachments(ddoc, path.join(__dirname, 'attachments'));
+
+module.exports = ddoc;

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/font/fonts/icomoon.dev.svg
----------------------------------------------------------------------
diff --git a/attachments/font/fonts/icomoon.dev.svg b/attachments/font/fonts/icomoon.dev.svg
new file mode 100644
index 0000000..957e34e
--- /dev/null
+++ b/attachments/font/fonts/icomoon.dev.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>
+This is a custom SVG font generated by IcoMoon.
+<iconset grid="20"></iconset>
+</metadata>
+<defs>
+<font id="icomoon" horiz-adv-x="640" >
+<font-face units-per-em="640" ascent="608" descent="-32" />
+<missing-glyph horiz-adv-x="640" />
+<glyph class="hidden" unicode="&#xf000;" d="M0,608L 640 -32L0 -32 z" horiz-adv-x="0" />
+<glyph unicode="&#xe005;" d="M 411.556,320.889c-7.854,0-14.222-23.687-14.222-52.907c0-29.221, 6.368-52.907, 14.222-52.907
+		s 14.222,23.685, 14.222,52.907C 425.778,297.202, 419.41,320.889, 411.556,320.889z M 489.778,594.667l-341.333,0 l-142.222-227.556l 56.889-369.778l 101.333,0 l-7.111,85.333l 49.778,0 l 7.111-85.333l 209.778,0 l 7.111,85.333l 49.778,0 l-7.111-85.333
+		l 101.333,0 l 56.889,369.778L 489.778,594.667z M 489.778,139.556l-341.333,0 l-28.444,227.556l 56.889,113.778l 91.429,0 l-6.096-42.667l 113.778,0 l-6.096,42.667L 461.333,480.889 l 56.889-113.778L 489.778,139.556z M 232,316.48
+		c-7.854,0-14.222-23.689-14.222-52.907s 6.368-52.907, 14.222-52.907c 7.854,0, 14.222,23.687, 14.222,52.907S 239.854,316.48, 232,316.48z" data-tags="cordova" />
+<glyph unicode="&#x20;" horiz-adv-x="320" />
+</font></defs></svg>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/font/fonts/icomoon.eot
----------------------------------------------------------------------
diff --git a/attachments/font/fonts/icomoon.eot b/attachments/font/fonts/icomoon.eot
new file mode 100644
index 0000000..f74ae8c
Binary files /dev/null and b/attachments/font/fonts/icomoon.eot differ

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/font/fonts/icomoon.svg
----------------------------------------------------------------------
diff --git a/attachments/font/fonts/icomoon.svg b/attachments/font/fonts/icomoon.svg
new file mode 100644
index 0000000..6641b7f
--- /dev/null
+++ b/attachments/font/fonts/icomoon.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>
+This is a custom SVG font generated by IcoMoon.
+<iconset grid="20"></iconset>
+</metadata>
+<defs>
+<font id="icomoon" horiz-adv-x="640" >
+<font-face units-per-em="640" ascent="608" descent="-32" />
+<missing-glyph horiz-adv-x="640" />
+<glyph class="hidden" unicode="&#xf000;" d="M0,608L 640 -32L0 -32 z" horiz-adv-x="0" />
+<glyph unicode="&#xe005;" d="M 411.556,320.889c-7.854,0-14.222-23.687-14.222-52.907c0-29.221, 6.368-52.907, 14.222-52.907
+		s 14.222,23.685, 14.222,52.907C 425.778,297.202, 419.41,320.889, 411.556,320.889z M 489.778,594.667l-341.333,0 l-142.222-227.556l 56.889-369.778l 101.333,0 l-7.111,85.333l 49.778,0 l 7.111-85.333l 209.778,0 l 7.111,85.333l 49.778,0 l-7.111-85.333
+		l 101.333,0 l 56.889,369.778L 489.778,594.667z M 489.778,139.556l-341.333,0 l-28.444,227.556l 56.889,113.778l 91.429,0 l-6.096-42.667l 113.778,0 l-6.096,42.667L 461.333,480.889 l 56.889-113.778L 489.778,139.556z M 232,316.48
+		c-7.854,0-14.222-23.689-14.222-52.907s 6.368-52.907, 14.222-52.907c 7.854,0, 14.222,23.687, 14.222,52.907S 239.854,316.48, 232,316.48z"  />
+<glyph unicode="&#x20;" horiz-adv-x="320" />
+</font></defs></svg>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/font/fonts/icomoon.ttf
----------------------------------------------------------------------
diff --git a/attachments/font/fonts/icomoon.ttf b/attachments/font/fonts/icomoon.ttf
new file mode 100644
index 0000000..85480a4
Binary files /dev/null and b/attachments/font/fonts/icomoon.ttf differ

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/font/fonts/icomoon.woff
----------------------------------------------------------------------
diff --git a/attachments/font/fonts/icomoon.woff b/attachments/font/fonts/icomoon.woff
new file mode 100644
index 0000000..8d75453
Binary files /dev/null and b/attachments/font/fonts/icomoon.woff differ

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/font/lte-ie7.js
----------------------------------------------------------------------
diff --git a/attachments/font/lte-ie7.js b/attachments/font/lte-ie7.js
new file mode 100644
index 0000000..88b53ac
--- /dev/null
+++ b/attachments/font/lte-ie7.js
@@ -0,0 +1,28 @@
+/* Load this script using conditional IE comments if you need to support IE 7 and IE 6. */
+
+window.onload = function() {
+	function addIcon(el, entity) {
+		var html = el.innerHTML;
+		el.innerHTML = '<span style="font-family: \'icomoon\'">' + entity + '</span>' + html;
+	}
+	var icons = {
+			'icon-cordova' : '&#xe005;'
+		},
+		els = document.getElementsByTagName('*'),
+		i, attr, html, c, el;
+	for (i = 0; ; i += 1) {
+		el = els[i];
+		if(!el) {
+			break;
+		}
+		attr = el.getAttribute('data-icon');
+		if (attr) {
+			addIcon(el, attr);
+		}
+		c = el.className;
+		c = c.match(/icon-[^\s'"]+/);
+		if (c && icons[c[0]]) {
+			addIcon(el, icons[c[0]]);
+		}
+	}
+};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/font/style.css
----------------------------------------------------------------------
diff --git a/attachments/font/style.css b/attachments/font/style.css
new file mode 100644
index 0000000..b40c49c
--- /dev/null
+++ b/attachments/font/style.css
@@ -0,0 +1,42 @@
+@font-face {
+	font-family: 'icomoon';
+	src:url('fonts/icomoon.eot');
+	src:url('fonts/icomoon.eot?#iefix') format('embedded-opentype'),
+		url('fonts/icomoon.woff') format('woff'),
+		url('fonts/icomoon.ttf') format('truetype'),
+		url('fonts/icomoon.svg#icomoon') format('svg');
+	font-weight: normal;
+	font-style: normal;
+}
+
+/* Use the following CSS code if you want to use data attributes for inserting your icons */
+[data-icon]:before {
+	font-family: 'icomoon';
+	content: attr(data-icon);
+	speak: none;
+	font-weight: normal;
+	font-variant: normal;
+	text-transform: none;
+	line-height: 1;
+	-webkit-font-smoothing: antialiased;
+}
+
+/* Use the following CSS code if you want to have a class per icon */
+/*
+Instead of a list of all class selectors,
+you can use the generic selector below, but it's slower:
+[class*="icon-"] {
+*/
+.icon-cordova {
+	font-family: 'icomoon';
+	speak: none;
+	font-style: normal;
+	font-weight: normal;
+	font-variant: normal;
+	text-transform: none;
+	line-height: 1;
+	-webkit-font-smoothing: antialiased;
+}
+.icon-cordova:before {
+	content: "\e005";
+}

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/highcharts/adapters/mootools-adapter.js
----------------------------------------------------------------------
diff --git a/attachments/highcharts/adapters/mootools-adapter.js b/attachments/highcharts/adapters/mootools-adapter.js
new file mode 100755
index 0000000..82ecb13
--- /dev/null
+++ b/attachments/highcharts/adapters/mootools-adapter.js
@@ -0,0 +1,11 @@
+/*
+ Highcharts JS v2.1.2 (2011-01-12)
+ MooTools adapter
+
+ (c) 2010 Torstein H?nsi
+
+ License: www.highcharts.com/license
+*/
+var HighchartsAdapter={init:function(){var a=Fx.prototype,b=a.start,c=Fx.Morph.prototype,d=c.compute;a.start=function(f){var e=this.element;if(f.d)this.paths=Highcharts.pathAnim.init(e,e.d,this.toD);b.apply(this,arguments)};c.compute=function(f,e,h){var g=this.paths;if(g)this.element.attr("d",Highcharts.pathAnim.step(g[0],g[1],h,this.toD));else return d.apply(this,arguments)}},animate:function(a,b,c){var d=a.attr,f=c&&c.complete;if(d&&!a.setStyle){a.getStyle=a.attr;a.setStyle=function(){var e=arguments;
+a.attr.call(a,e[0],e[1][0])};a.$family=a.uid=true}HighchartsAdapter.stop(a);c=new Fx.Morph(d?a:$(a),$extend({transition:Fx.Transitions.Quad.easeInOut},c));if(b.d)c.toD=b.d;f&&c.addEvent("complete",f);c.start(b);a.fx=c},each:$each,map:function(a,b){return a.map(b)},grep:function(a,b){return a.filter(b)},merge:$merge,hyphenate:function(a){return a.hyphenate()},addEvent:function(a,b,c){if(typeof b=="string"){if(b=="unload")b="beforeunload";if(!a.addEvent)if(a.nodeName)a=$(a);else $extend(a,new Events);
+a.addEvent(b,c)}},removeEvent:function(a,b,c){if(b){if(b=="unload")b="beforeunload";a.removeEvent(b,c)}},fireEvent:function(a,b,c,d){b=new Event({type:b,target:a});b=$extend(b,c);b.preventDefault=function(){d=null};a.fireEvent&&a.fireEvent(b.type,b);d&&d(b)},stop:function(a){a.fx&&a.fx.cancel()}};

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/highcharts/adapters/mootools-adapter.src.js
----------------------------------------------------------------------
diff --git a/attachments/highcharts/adapters/mootools-adapter.src.js b/attachments/highcharts/adapters/mootools-adapter.src.js
new file mode 100755
index 0000000..32082ae
--- /dev/null
+++ b/attachments/highcharts/adapters/mootools-adapter.src.js
@@ -0,0 +1,214 @@
+/** 
+ * @license Highcharts JS v2.1.2 (2011-01-12)
+ * MooTools adapter
+ * 
+ * (c) 2010 Torstein Hønsi
+ * 
+ * License: www.highcharts.com/license
+ */
+
+// JSLint options:
+/*global Highcharts, Fx, $, $extend, $each, $merge, Events, Event */
+
+var HighchartsAdapter = {
+	/**
+	 * Initialize the adapter. This is run once as Highcharts is first run.
+	 */
+	init: function() {
+		var fxProto = Fx.prototype,
+			fxStart = fxProto.start,
+			morphProto = Fx.Morph.prototype,
+			morphCompute = morphProto.compute;
+			
+		// override Fx.start to allow animation of SVG element wrappers
+		fxProto.start = function(from, to) {
+			var fx = this,
+				elem = fx.element;
+			
+			// special for animating paths
+			if (from.d) {
+				//this.fromD = this.element.d.split(' ');
+				fx.paths = Highcharts.pathAnim.init(
+					elem, 
+					elem.d, 
+					fx.toD
+				);
+			}
+			fxStart.apply(fx, arguments);
+		};
+		
+		// override Fx.step to allow animation of SVG element wrappers
+		morphProto.compute = function(from, to, delta) {
+			var fx = this,
+				paths = fx.paths;
+			
+			if (paths) {
+				fx.element.attr(
+					'd', 
+					Highcharts.pathAnim.step(paths[0], paths[1], delta, fx.toD)
+				);
+			} else {
+				return morphCompute.apply(fx, arguments);
+			}
+		};
+		
+	},	
+	
+	/**
+	 * Animate a HTML element or SVG element wrapper
+	 * @param {Object} el
+	 * @param {Object} params
+	 * @param {Object} options jQuery-like animation options: duration, easing, callback
+	 */
+	animate: function (el, params, options) {
+		var isSVGElement = el.attr,
+			effect,
+			complete = options && options.complete;
+		
+		if (isSVGElement && !el.setStyle) {
+			// add setStyle and getStyle methods for internal use in Moo
+			el.getStyle = el.attr;
+			el.setStyle = function() { // property value is given as array in Moo - break it down
+				var args = arguments;
+				el.attr.call(el, args[0], args[1][0]);
+			}
+			// dirty hack to trick Moo into handling el as an element wrapper
+			el.$family = el.uid = true;
+		}
+		
+		// stop running animations
+		HighchartsAdapter.stop(el);
+		
+		// define and run the effect
+		effect = new Fx.Morph(
+			isSVGElement ? el : $(el), 
+			$extend({
+				transition: Fx.Transitions.Quad.easeInOut
+			}, options)
+		);
+		
+		// special treatment for paths
+		if (params.d) {
+			effect.toD = params.d;
+		}
+		
+		// jQuery-like events
+		if (complete) {
+			effect.addEvent('complete', complete);
+		}
+		
+		// run
+		effect.start(params);
+		
+		// record for use in stop method
+		el.fx = effect;
+	},
+	
+	/**
+	 * MooTool's each function
+	 * 
+	 */
+	each: $each,
+	
+	/**
+	 * Map an array
+	 * @param {Array} arr
+	 * @param {Function} fn
+	 */
+	map: function (arr, fn){
+		return arr.map(fn);
+	},
+	
+	/**
+	 * Grep or filter an array
+	 * @param {Array} arr
+	 * @param {Function} fn
+	 */
+	grep: function(arr, fn) {
+		return arr.filter(fn);
+	},
+	
+	/**
+	 * Deep merge two objects and return a third
+	 */
+	merge: $merge,
+	
+	/**
+	 * Hyphenate a string, like minWidth becomes min-width
+	 * @param {Object} str
+	 */
+	hyphenate: function (str){
+		return str.hyphenate();
+	},
+	
+	/**
+	 * Add an event listener
+	 * @param {Object} el HTML element or custom object
+	 * @param {String} type Event type
+	 * @param {Function} fn Event handler
+	 */
+	addEvent: function (el, type, fn) {
+		if (typeof type == 'string') { // chart broke due to el being string, type function
+		
+			if (type == 'unload') { // Moo self destructs before custom unload events
+				type = 'beforeunload';
+			}
+
+			// if the addEvent method is not defined, el is a custom Highcharts object
+			// like series or point
+			if (!el.addEvent) {
+				if (el.nodeName) {
+					el = $(el); // a dynamically generated node
+				} else {
+					$extend(el, new Events()); // a custom object
+				}
+			}
+			
+			el.addEvent(type, fn);
+		}
+	},
+	
+	removeEvent: function(el, type, fn) {
+		if (type) {
+			if (type == 'unload') { // Moo self destructs before custom unload events
+				type = 'beforeunload';
+			}
+
+
+			el.removeEvent(type, fn);
+		}
+	},
+	
+	fireEvent: function(el, event, eventArguments, defaultFunction) {
+		// create an event object that keeps all functions		
+		event = new Event({ 
+			type: event,
+			target: el
+		});
+		event = $extend(event, eventArguments);
+		// override the preventDefault function to be able to use
+		// this for custom events
+		event.preventDefault = function() {
+			defaultFunction = null;
+		};
+		// if fireEvent is not available on the object, there hasn't been added
+		// any events to it above
+		if (el.fireEvent) {
+			el.fireEvent(event.type, event);
+		}
+		
+		// fire the default if it is passed and it is not prevented above
+		if (defaultFunction) {
+			defaultFunction(event);
+		}		
+	},
+	
+	/**
+	 * Stop running animations on the object
+	 */
+	stop: function (el) {
+		if (el.fx) {
+			el.fx.cancel();
+		}
+	}
+};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/highcharts/adapters/prototype-adapter.js
----------------------------------------------------------------------
diff --git a/attachments/highcharts/adapters/prototype-adapter.js b/attachments/highcharts/adapters/prototype-adapter.js
new file mode 100755
index 0000000..6040fe3
--- /dev/null
+++ b/attachments/highcharts/adapters/prototype-adapter.js
@@ -0,0 +1,14 @@
+/*
+ Highcharts JS v2.1.2 (2011-01-12)
+ Prototype adapter
+
+ @author Michael Nelson, Torstein H?nsi.
+
+ Feel free to use and modify this script.
+ Highcharts license: www.highcharts.com/license.
+*/
+var HighchartsAdapter=function(){var l=typeof Effect!="undefined";return{init:function(){if(l)Effect.HighchartsTransition=Class.create(Effect.Base,{initialize:function(a,b,c,d){var e;this.element=a;e=a.attr(b);if(b=="d"){this.paths=Highcharts.pathAnim.init(a,a.d,c);this.toD=c;e=0;c=1}this.start(Object.extend(d||{},{from:e,to:c,attribute:b}))},setup:function(){HighchartsAdapter._extend(this.element);this.element._highchart_animation=this},update:function(a){var b=this.paths;if(b)a=Highcharts.pathAnim.step(b[0],
+b[1],a,this.toD);this.element.attr(this.options.attribute,a)},finish:function(){this.element._highchart_animation=null}})},addEvent:function(a,b,c){if(a.addEventListener||a.attachEvent)Event.observe($(a),b,c);else{HighchartsAdapter._extend(a);a._highcharts_observe(b,c)}},animate:function(a,b,c){var d;c=c||{};c.delay=0;c.duration=(c.duration||500)/1E3;if(l)for(d in b)new Effect.HighchartsTransition($(a),d,b[d],c);else for(d in b)a.attr(d,b[d]);if(!a.attr)throw"Todo: implement animate DOM objects";
+},stop:function(a){a._highcharts_extended&&a._highchart_animation&&a._highchart_animation.cancel()},each:function(a,b){$A(a).each(b)},fireEvent:function(a,b,c,d){if(b.preventDefault)d=null;if(a.fire)a.fire(b,c);else a._highcharts_extended&&a._highcharts_fire(b,c);d&&d(c)},removeEvent:function(a,b,c){if($(a).stopObserving)a.stopObserving(a,b,c);else{HighchartsAdapter._extend(a);a._highcharts_stop_observing(b,c)}},grep:function(a,b){return a.findAll(b)},hyphenate:function(a){return a.replace(/([A-Z])/g,
+function(b,c){return"-"+c.toLowerCase()})},map:function(a,b){return a.map(b)},merge:function(){function a(e,i){var f,g,h,j,k;for(g in i){f=i[g];h=typeof f==="undefined";j=f===null;k=i===e[g];if(!(h||j||k)){h=typeof f==="object";j=f&&h&&f.constructor==Array;k=!!f.nodeType;e[g]=h&&!j&&!k?a(typeof e[g]=="object"?e[g]:{},f):i[g]}}return e}for(var b=arguments,c={},d=0;d<b.length;d++)c=a(c,b[d]);return c},_extend:function(a){a._highcharts_extended||Object.extend(a,{_highchart_events:{},_highchart_animation:null,
+_highcharts_extended:true,_highcharts_observe:function(b,c){this._highchart_events[b]=[this._highchart_events[b],c].compact().flatten()},_highcharts_stop_observing:function(b,c){this._highchart_events[b]=[this._highchart_events[b]].compact().flatten().without(c)},_highcharts_fire:function(b,c){(this._highchart_events[b]||[]).each(function(d){c&&c.stopped||d.bind(this)(c)}.bind(this))}})}}}();

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/highcharts/adapters/prototype-adapter.src.js
----------------------------------------------------------------------
diff --git a/attachments/highcharts/adapters/prototype-adapter.src.js b/attachments/highcharts/adapters/prototype-adapter.src.js
new file mode 100755
index 0000000..3804169
--- /dev/null
+++ b/attachments/highcharts/adapters/prototype-adapter.src.js
@@ -0,0 +1,254 @@
+/** 
+ * @license Highcharts JS v2.1.2 (2011-01-12)
+ * Prototype adapter
+ * 
+ * @author Michael Nelson, Torstein Hønsi.
+ * 
+ * Feel free to use and modify this script.
+ * Highcharts license: www.highcharts.com/license.
+ */
+
+/* 
+ * Known issues: 
+ *    - Some grid lines land in wrong position - http://jsfiddle.net/highcharts/jaRhY/28
+ */
+
+// JSLint options:
+/*jslint forin: true */
+/*global Effect, Class, Highcharts, Event, $, $A */
+
+// Adapter interface between prototype and the Highcarts charting library
+var HighchartsAdapter = (function() {
+
+var hasEffect = typeof Effect != 'undefined';
+
+return { 
+	
+	init: function() {
+		
+		if (hasEffect) {
+			/**
+			 * Animation for Highcharts SVG element wrappers only
+			 * @param {Object} element
+			 * @param {Object} attribute
+			 * @param {Object} to
+			 * @param {Object} options
+			 */
+			Effect.HighchartsTransition = Class.create(Effect.Base, {
+				initialize: function(element, attr, to, options){
+					var from,
+						opts;
+					
+					this.element = element;
+					
+					from = element.attr(attr);
+					
+					// special treatment for paths
+					if (attr == 'd') {
+						this.paths = Highcharts.pathAnim.init(
+							element, 
+							element.d,
+							to
+						);
+						this.toD = to;
+						
+						
+						// fake values in order to read relative position as a float in update
+						from = 0; 
+						to = 1;				
+					}
+					
+					opts = Object.extend((options || {}), {
+						from: from,
+						to: to,
+						attribute: attr
+					});
+					this.start(opts);
+				},
+				setup: function(){
+					HighchartsAdapter._extend(this.element);
+					this.element._highchart_animation = this;
+				},
+				update: function(position) {
+					var paths = this.paths;
+					
+					if (paths) {
+						position = Highcharts.pathAnim.step(paths[0], paths[1], position, this.toD);
+					}
+					
+					this.element.attr(this.options.attribute, position);
+				},
+				finish: function(){
+					this.element._highchart_animation = null;
+				}
+			});
+		}
+	},
+	
+	// el needs an event to be attached. el is not necessarily a dom element
+	addEvent: function(el, event, fn) {
+		if (el.addEventListener || el.attachEvent) {
+			Event.observe($(el), event, fn);
+		
+		} else {
+			HighchartsAdapter._extend(el);
+			el._highcharts_observe(event, fn);
+		}
+	},
+	
+	// motion makes things pretty. use it if effects is loaded, if not... still get to the end result.
+	animate: function(el, params, options) { 
+		var key,
+			fx;
+		
+		// default options
+		options = options || {};
+		options.delay = 0;
+		options.duration = (options.duration || 500) / 1000;
+		
+		// animate wrappers and DOM elements
+		if (hasEffect) { 
+			for (key in params) {
+				fx = new Effect.HighchartsTransition($(el), key, params[key], options);
+			}
+		} else { 
+			for (key in params) {
+				el.attr(key, params[key]);
+			}
+		}
+		
+		if (!el.attr) {
+			throw 'Todo: implement animate DOM objects';
+		}
+	},
+	
+	// this only occurs in higcharts 2.0+
+	stop: function(el){
+		if (el._highcharts_extended && el._highchart_animation) {
+			el._highchart_animation.cancel();
+		}
+	},
+	
+	// um.. each
+	each: function(arr, fn){
+		$A(arr).each(fn);
+	},
+	
+	// fire an event based on an event name (event) and an object (el).
+	// again, el may not be a dom element
+	fireEvent: function(el, event, eventArguments, defaultFunction){
+		if (event.preventDefault) {
+			defaultFunction = null;
+		}
+		
+		if (el.fire) {
+			el.fire(event, eventArguments);
+		} else if (el._highcharts_extended) {
+			el._highcharts_fire(event, eventArguments);
+		}
+		
+		if (defaultFunction) { 
+			defaultFunction(eventArguments);
+		}
+	},
+	
+	removeEvent: function(el, event, handler){
+		if ($(el).stopObserving) {
+			el.stopObserving(el, event, handler);
+			
+		} else {
+			HighchartsAdapter._extend(el);
+			el._highcharts_stop_observing(event, handler);
+		}
+	},
+	
+	// um, grep
+	grep: function(arr, fn){
+		return arr.findAll(fn);
+	},
+	
+	// change leftPadding to left-padding
+	hyphenate: function(str){
+		return str.replace(/([A-Z])/g, function(a, b){
+			return '-' + b.toLowerCase();
+		});
+	},
+	
+	// um, map
+	map: function(arr, fn){
+		return arr.map(fn);
+	},
+	
+	// deep merge. merge({a : 'a', b : {b1 : 'b1', b2 : 'b2'}}, {b : {b2 : 'b2_prime'}, c : 'c'}) => {a : 'a', b : {b1 : 'b1', b2 : 'b2_prime'}, c : 'c'}
+	merge: function(){
+		function doCopy(copy, original) {
+			var value,
+				key,
+				undef,
+				nil,
+				same,
+				obj,
+				arr,
+				node;
+				
+			for (key in original) {
+				value = original[key];
+				undef = typeof(value) === 'undefined';
+				nil = value === null;
+				same = original === copy[key];
+				
+				if (undef || nil || same) { 
+					continue;
+				}
+				
+				obj = typeof(value) === 'object';
+				arr = value && obj && value.constructor == Array;
+				node = !!value.nodeType;
+				
+				if (obj && !arr && !node) {
+					copy[key] = doCopy(typeof copy[key] == 'object' ? copy[key] : {}, value);
+				}
+				else {
+					copy[key] = original[key];
+				}
+			}
+			return copy;
+		}
+		
+		var args = arguments, retVal = {};
+		
+		for (var i = 0; i < args.length; i++) {
+			retVal = doCopy(retVal, args[i]);			
+		}
+		
+		return retVal;
+	},
+	
+	// extend an object to handle highchart events (highchart objects, not svg elements). 
+	// this is a very simple way of handling events but whatever, it works (i think)
+	_extend: function(object){
+		if (!object._highcharts_extended) {
+			Object.extend(object, {
+				_highchart_events: {},
+				_highchart_animation: null,
+				_highcharts_extended: true,
+				_highcharts_observe: function(name, fn){
+					this._highchart_events[name] = [this._highchart_events[name], fn].compact().flatten();
+				},
+				_highcharts_stop_observing: function(name, fn){
+					this._highchart_events[name] = [this._highchart_events[name]].compact().flatten().without(fn);
+				},
+				_highcharts_fire: function(name, args){
+					(this._highchart_events[name] || []).each(function(fn){
+						if (args && args.stopped) {
+							return; // "throw $break" wasn't working. i think because of the scope of 'this'.
+						}
+						fn.bind(this)(args);
+					}
+.bind(this));
+				}
+			});
+		}
+	}
+};
+})();


[8/9] first commit

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/highcharts/highcharts.js
----------------------------------------------------------------------
diff --git a/attachments/highcharts/highcharts.js b/attachments/highcharts/highcharts.js
new file mode 100755
index 0000000..4e7ebb6
--- /dev/null
+++ b/attachments/highcharts/highcharts.js
@@ -0,0 +1,160 @@
+/*
+ Highcharts JS v2.1.2 (2011-01-12)
+
+ (c) 2009-2010 Torstein H?nsi
+
+ License: www.highcharts.com/license
+*/
+(function(){function ma(a,b){a||(a={});for(var c in b)a[c]=b[c];return a}function oa(a,b){return parseInt(a,b||10)}function Ib(a){return typeof a=="string"}function Jb(a){return typeof a=="object"}function bc(a){return typeof a=="number"}function mc(a,b){for(var c=a.length;c--;)if(a[c]==b){a.splice(c,1);break}}function L(a){return a!==Qa&&a!==null}function xa(a,b,c){var d,e;if(Ib(b))if(L(c))a.setAttribute(b,c);else{if(a&&a.getAttribute)e=a.getAttribute(b)}else if(L(b)&&Jb(b))for(d in b)a.setAttribute(d,
+b[d]);return e}function nc(a){if(!a||a.constructor!=Array)a=[a];return a}function y(){var a=arguments,b,c,d=a.length;for(b=0;b<d;b++){c=a[b];if(typeof c!=="undefined"&&c!==null)return c}}function Vd(a){var b="",c;for(c in a)b+=Ad(c)+":"+a[c]+";";return b}function La(a,b){if(Ac)if(b&&b.opacity!==Qa)b.filter="alpha(opacity="+b.opacity*100+")";ma(a.style,b)}function eb(a,b,c,d,e){a=za.createElement(a);b&&ma(a,b);e&&La(a,{padding:0,border:mb,margin:0});c&&La(a,c);d&&d.appendChild(a);return a}function Kb(a,
+b){Bc=y(a,b.animation)}function Bd(){var a=Ra.global.useUTC;Cc=a?Date.UTC:function(b,c,d,e,f,g){return(new Date(b,c,y(d,1),y(e,0),y(f,0),y(g,0))).getTime()};$c=a?"getUTCMinutes":"getMinutes";ad=a?"getUTCHours":"getHours";bd=a?"getUTCDay":"getDay";oc=a?"getUTCDate":"getDate";Dc=a?"getUTCMonth":"getMonth";Ec=a?"getUTCFullYear":"getFullYear";Cd=a?"setUTCMinutes":"setMinutes";Dd=a?"setUTCHours":"setHours";cd=a?"setUTCDate":"setDate";Ed=a?"setUTCMonth":"setMonth";Fd=a?"setUTCFullYear":"setFullYear"}function Fc(a){Gc||
+(Gc=eb(Lb));a&&Gc.appendChild(a);Gc.innerHTML=""}function wb(a,b){var c=function(){};c.prototype=new a;ma(c.prototype,b);return c}function Gd(a,b,c,d){var e=Ra.lang;a=a;var f=isNaN(b=ab(b))?2:b;b=c===undefined?e.decimalPoint:c;d=d===undefined?e.thousandsSep:d;e=a<0?"-":"";c=oa(a=ab(+a||0).toFixed(f))+"";var g=(g=c.length)>3?g%3:0;return e+(g?c.substr(0,g)+d:"")+c.substr(g).replace(/(\d{3})(?=\d)/g,"$1"+d)+(f?b+ab(a-c).toFixed(f).slice(2):"")}function Hc(){}function Hd(a,b){function c(m,h){function x(l,
+p){this.pos=l;this.minor=p;this.isNew=true;p||this.addLabel()}function w(l){if(l){this.options=l;this.id=l.id}return this}function P(){var l=[],p=[],r;Sa=v=null;Y=[];t(Aa,function(o){r=false;t(["xAxis","yAxis"],function(ja){if(o.isCartesian&&(ja=="xAxis"&&ka||ja=="yAxis"&&!ka)&&(o.options[ja]==h.index||o.options[ja]===Qa&&h.index===0)){o[ja]=s;Y.push(o);r=true}});if(!o.visible&&u.ignoreHiddenSeries)r=false;if(r){var U,X,H,C,fa;if(!ka){U=o.options.stacking;Ic=U=="percent";if(U){C=o.type+y(o.options.stack,
+"");fa="-"+C;o.stackKey=C;X=l[C]||[];l[C]=X;H=p[fa]||[];p[fa]=H}if(Ic){Sa=0;v=99}}if(o.isCartesian){t(o.data,function(ja){var D=ja.x,la=ja.y,S=la<0,Z=S?H:X;S=S?fa:C;if(Sa===null)Sa=v=ja[I];if(ka)if(D>v)v=D;else{if(D<Sa)Sa=D}else if(L(la)){if(U)Z[D]=L(Z[D])?Z[D]+la:la;la=Z?Z[D]:la;ja=y(ja.low,la);if(!Ic)if(la>v)v=la;else if(ja<Sa)Sa=ja;if(U){ca[S]||(ca[S]={});ca[S][D]={total:la,cum:la}}}});if(/(area|column|bar)/.test(o.type)&&!ka)if(Sa>=0){Sa=0;Id=true}else if(v<0){v=0;Jd=true}}}})}function ga(l,p){var r;
+Db=p?1:Ta.pow(10,Mb(Ta.log(l)/Ta.LN10));r=l/Db;if(!p){p=[1,2,2.5,5,10];if(h.allowDecimals===false)if(Db==1)p=[1,2,5,10];else if(Db<=0.1)p=[1/Db]}for(var o=0;o<p.length;o++){l=p[o];if(r<=(p[o]+(p[o+1]||p[o]))/2)break}l*=Db;return l}function M(l){var p;p=l;if(L(Db)){p=(Db<1?V(1/Db):1)*10;p=V(l*p)/p}return p}function da(){var l,p,r,o,U=h.tickInterval,X=h.tickPixelInterval;l=h.maxZoom||(ka?nb(m.smallestInterval*5,v-Sa):null);B=O?Ca:ra;if(Nb){r=m[ka?"xAxis":"yAxis"][h.linkedTo];o=r.getExtremes();J=y(o.min,
+o.dataMin);Q=y(o.max,o.dataMax)}else{J=y(na,h.min,Sa);Q=y(Ma,h.max,v)}if(Q-J<l){o=(l-Q+J)/2;J=Ga(J-o,y(h.min,J-o),Sa);Q=nb(J+l,y(h.max,J+l),v)}if(!bb&&!Ic&&!Nb&&L(J)&&L(Q)){l=Q-J||1;if(!L(h.min)&&!L(na)&&Wb&&(Sa<0||!Id))J-=l*Wb;if(!L(h.max)&&!L(Ma)&&Kd&&(v>0||!Jd))Q+=l*Kd}Ua=J==Q?1:Nb&&!U&&X==r.options.tickPixelInterval?r.tickInterval:y(U,bb?1:(Q-J)*X/B);if(!N&&!L(h.tickInterval))Ua=ga(Ua);s.tickInterval=Ua;Jc=h.minorTickInterval==="auto"&&Ua?Ua/5:h.minorTickInterval;if(N){pa=[];U=Ra.global.useUTC;
+var H=1E3/ob,C=6E4/ob,fa=36E5/ob;X=864E5/ob;l=6048E5/ob;o=2592E6/ob;var ja=31556952E3/ob,D=[["second",H,[1,2,5,10,15,30]],["minute",C,[1,2,5,10,15,30]],["hour",fa,[1,2,3,4,6,8,12]],["day",X,[1,2]],["week",l,[1,2]],["month",o,[1,2,3,4,6]],["year",ja,null]],la=D[6],S=la[1],Z=la[2];for(r=0;r<D.length;r++){la=D[r];S=la[1];Z=la[2];if(D[r+1])if(Ua<=(S*Z[Z.length-1]+D[r+1][1])/2)break}if(S==ja&&Ua<5*S)Z=[1,2,5];D=ga(Ua/S,Z);Z=new Date(J*ob);Z.setMilliseconds(0);if(S>=H)Z.setSeconds(S>=C?0:D*Mb(Z.getSeconds()/
+D));if(S>=C)Z[Cd](S>=fa?0:D*Mb(Z[$c]()/D));if(S>=fa)Z[Dd](S>=X?0:D*Mb(Z[ad]()/D));if(S>=X)Z[cd](S>=o?1:D*Mb(Z[oc]()/D));if(S>=o){Z[Ed](S>=ja?0:D*Mb(Z[Dc]()/D));p=Z[Ec]()}if(S>=ja){p-=p%D;Z[Fd](p)}S==l&&Z[cd](Z[oc]()-Z[bd]()+h.startOfWeek);r=1;p=Z[Ec]();H=Z.getTime()/ob;C=Z[Dc]();for(fa=Z[oc]();H<Q&&r<Ca;){pa.push(H);if(S==ja)H=Cc(p+r*D,0)/ob;else if(S==o)H=Cc(p,C+r*D)/ob;else if(!U&&(S==X||S==l))H=Cc(p,C,fa+r*D*(S==X?1:7));else H+=S*D;r++}pa.push(H);Kc=h.dateTimeLabelFormats[la[0]]}else{r=Mb(J/Ua)*
+Ua;p=dd(Q/Ua)*Ua;pa=[];for(r=M(r);r<=p;){pa.push(r);r=M(r+Ua)}}if(!Nb){if(bb||ka&&m.hasColumn){p=(bb?1:Ua)*0.5;if(bb||!L(y(h.min,na)))J-=p;if(bb||!L(y(h.max,Ma)))Q+=p}p=pa[0];r=pa[pa.length-1];if(h.startOnTick)J=p;else J>p&&pa.shift();if(h.endOnTick)Q=r;else Q<r&&pa.pop();Eb||(Eb={x:0,y:0});if(!N&&pa.length>Eb[I])Eb[I]=pa.length}}function Da(){var l,p;fb=J;cc=Q;P();da();ha=F;F=B/(Q-J||1);if(!ka)for(l in ca)for(p in ca[l])ca[l][p].cum=ca[l][p].total;if(!s.isDirty)s.isDirty=J!=fb||Q!=cc}function sa(l){l=
+(new w(l)).render();Ob.push(l);return l}function Ya(){var l=h.title,p=h.alternateGridColor,r=h.lineWidth,o,U,X=m.hasRendered,H=X&&L(fb)&&!isNaN(fb);o=Y.length&&L(J)&&L(Q);B=O?Ca:ra;F=B/(Q-J||1);va=O?W:pb;if(o||Nb){if(Jc&&!bb)for(o=J+(pa[0]-J)%Jc;o<=Q;o+=Jc){Xb[o]||(Xb[o]=new x(o,true));H&&Xb[o].isNew&&Xb[o].render(null,true);Xb[o].isActive=true;Xb[o].render()}t(pa,function(C,fa){if(!Nb||C>=J&&C<=Q){H&&qb[C].isNew&&qb[C].render(fa,true);qb[C].isActive=true;qb[C].render(fa)}});p&&t(pa,function(C,fa){if(fa%
+2===0&&C<Q){dc[C]||(dc[C]=new w);dc[C].options={from:C,to:pa[fa+1]!==Qa?pa[fa+1]:Q,color:p};dc[C].render();dc[C].isActive=true}});X||t((h.plotLines||[]).concat(h.plotBands||[]),function(C){Ob.push((new w(C)).render())})}t([qb,Xb,dc],function(C){for(var fa in C)if(C[fa].isActive)C[fa].isActive=false;else{C[fa].destroy();delete C[fa]}});if(r){o=W+(Na?Ca:0)+R;U=Oa-pb-(Na?ra:0)+R;o=$.crispLine([Wa,O?W:o,O?U:aa,Ba,O?Va-zb:o,O?U:Oa-pb],r);if(Ea)Ea.animate({d:o});else Ea=$.path(o).attr({stroke:h.lineColor,
+"stroke-width":r,zIndex:7}).add()}if(s.axisTitle){o=O?W:aa;r=oa(l.style.fontSize||12);o={low:o+(O?0:B),middle:o+B/2,high:o+(O?B:0)}[l.align];r=(O?aa+ra:W)+(O?1:-1)*(Na?-1:1)*ed+(G==2?r:0);s.axisTitle[X?"animate":"attr"]({x:O?o:r+(Na?Ca:0)+R+(l.x||0),y:O?r-(Na?ra:0)+R:o+(l.y||0)})}s.isDirty=false}function Ha(l){for(var p=0;p<Ob.length;p++)Ob[p].id==l&&Ob[p].destroy()}var ka=h.isX,Na=h.opposite,O=Fa?!ka:ka,G=O?Na?0:2:Na?1:3,ca={};h=wa(ka?Lc:fd,[Wd,Xd,Ld,Yd][G],h);var s=this,N=h.type=="datetime",R=h.offset||
+0,I=ka?"x":"y",B,F,ha,va=O?W:pb,ta,Ia,rb,Fb,Ea,Sa,v,Y,na,Ma,Q=null,J=null,fb,cc,Wb=h.minPadding,Kd=h.maxPadding,Nb=L(h.linkedTo),Id,Jd,Ic,Md=h.events,gd,Ob=[],Ua,Jc,Db,pa,qb={},Xb={},dc={},ec,fc,ed,Kc,bb=h.categories,Zd=h.labels.formatter||function(){var l=this.value;return Kc?Mc(Kc,l):Ua%1E6===0?l/1E6+"M":Ua%1E3===0?l/1E3+"k":!bb&&l>=1E3?Gd(l,0):l},Nc=O&&h.labels.staggerLines,Yb=h.reversed,Zb=bb&&h.tickmarkPlacement=="between"?0.5:0;x.prototype={addLabel:function(){var l=this.pos,p=h.labels,r=!(l==
+J&&!y(h.showFirstLabel,1)||l==Q&&!y(h.showLastLabel,0)),o,U=this.label;l=Zd.call({isFirst:l==pa[0],isLast:l==pa[pa.length-1],dateTimeLabelFormat:Kc,value:bb&&bb[l]?bb[l]:l});o=o&&{width:o-2*(p.padding||10)+Za};if(U===Qa)this.label=L(l)&&r&&p.enabled?$.text(l,0,0).attr({align:p.align,rotation:p.rotation}).css(ma(o,p.style)).add(rb):null;else U&&U.attr({text:l}).css(o)},getLabelSize:function(){var l=this.label;return l?(this.labelBBox=l.getBBox())[O?"height":"width"]:0},render:function(l,p){var r=!this.minor,
+o=this.label,U=this.pos,X=h.labels,H=this.gridLine,C=r?h.gridLineWidth:h.minorGridLineWidth,fa=r?h.gridLineColor:h.minorGridLineColor,ja=r?h.gridLineDashStyle:h.minorGridLineDashStyle,D=this.mark,la=r?h.tickLength:h.minorTickLength,S=r?h.tickWidth:h.minorTickWidth||0,Z=r?h.tickColor:h.minorTickColor,pc=r?h.tickPosition:h.minorTickPosition;r=X.step;var gb=p&&Oc||Oa,Pb;Pb=O?ta(U+Zb,null,null,p)+va:W+R+(Na?(p&&hd||Va)-zb-W:0);gb=O?gb-pb+R-(Na?ra:0):gb-ta(U+Zb,null,null,p)-va;if(C){U=Ia(U+Zb,C,p);if(H===
+Qa){H={stroke:fa,"stroke-width":C};if(ja)H.dashstyle=ja;this.gridLine=H=C?$.path(U).attr(H).add(Fb):null}H&&U&&H.animate({d:U})}if(S){if(pc=="inside")la=-la;if(Na)la=-la;C=$.crispLine([Wa,Pb,gb,Ba,Pb+(O?0:-la),gb+(O?la:0)],S);if(D)D.animate({d:C});else this.mark=$.path(C).attr({stroke:Z,"stroke-width":S}).add(rb)}if(o){Pb=Pb+X.x-(Zb&&O?Zb*F*(Yb?-1:1):0);gb=gb+X.y-(Zb&&!O?Zb*F*(Yb?1:-1):0);L(X.y)||(gb+=parseInt(o.styles.lineHeight)*0.9-o.getBBox().height/2);if(Nc)gb+=l%Nc*16;if(r)o[l%r?"hide":"show"]();
+o[this.isNew?"attr":"animate"]({x:Pb,y:gb})}this.isNew=false},destroy:function(){for(var l in this)this[l]&&this[l].destroy&&this[l].destroy()}};w.prototype={render:function(){var l=this,p=l.options,r=p.label,o=l.label,U=p.width,X=p.to,H,C=p.from,fa=p.dashStyle,ja=l.svgElem,D=[],la,S,Z=p.color;S=p.zIndex;var pc=p.events;if(U){D=Ia(p.value,U);p={stroke:Z,"stroke-width":U};if(fa)p.dashstyle=fa}else if(L(C)&&L(X)){C=Ga(C,J);X=nb(X,Q);H=Ia(X);if((D=Ia(C))&&H)D.push(H[4],H[5],H[1],H[2]);else D=null;p=
+{fill:Z}}else return;if(L(S))p.zIndex=S;if(ja)if(D)ja.animate({d:D},null,ja.onGetPath);else{ja.hide();ja.onGetPath=function(){ja.show()}}else if(D&&D.length){l.svgElem=ja=$.path(D).attr(p).add();if(pc){fa=function(gb){ja.on(gb,function(Pb){pc[gb].apply(l,[Pb])})};for(la in pc)fa(la)}}if(r&&L(r.text)&&D&&D.length&&Ca>0&&ra>0){r=wa({align:O&&H&&"center",x:O?!H&&4:10,verticalAlign:!O&&H&&"middle",y:O?H?16:10:H?6:-4,rotation:O&&!H&&90},r);if(!o)l.label=o=$.text(r.text,0,0).attr({align:r.textAlign||r.align,
+rotation:r.rotation,zIndex:S}).css(r.style).add();H=[D[1],D[4],D[6]||D[1]];D=[D[2],D[5],D[7]||D[2]];la=nb.apply(Ta,H);S=nb.apply(Ta,D);o.align(r,false,{x:la,y:S,width:Ga.apply(Ta,H)-la,height:Ga.apply(Ta,D)-S});o.show()}else o&&o.hide();return l},destroy:function(){for(var l in this){this[l]&&this[l].destroy&&this[l].destroy();delete this[l]}mc(Ob,this)}};ta=function(l,p,r,o){var U=1,X=0,H=o?ha:F;o=o?fb:J;H||(H=F);if(r){U*=-1;X=B}if(Yb){U*=-1;X-=U*B}if(p){if(Yb)l=B-l;l=l/H+o}else l=U*(l-o)*H+X;return l};
+Ia=function(l,p,r){var o,U,X;l=ta(l,null,null,r);var H=r&&Oc||Oa,C=r&&hd||Va,fa;r=U=V(l+va);o=X=V(H-l-va);if(isNaN(l))fa=true;else if(O){o=aa;X=H-pb;if(r<W||r>W+Ca)fa=true}else{r=W;U=C-zb;if(o<aa||o>aa+ra)fa=true}return fa?null:$.crispLine([Wa,r,o,Ba,U,X],p||0)};if(Fa&&ka&&Yb===Qa)Yb=true;ma(s,{addPlotBand:sa,addPlotLine:sa,adjustTickAmount:function(){if(Eb&&!N&&!bb&&!Nb){var l=ec,p=pa.length;ec=Eb[I];if(p<ec){for(;pa.length<ec;)pa.push(M(pa[pa.length-1]+Ua));F*=(p-1)/(ec-1);Q=pa[pa.length-1]}if(L(l)&&
+ec!=l)s.isDirty=true}},categories:bb,getExtremes:function(){return{min:J,max:Q,dataMin:Sa,dataMax:v}},getPlotLinePath:Ia,getThreshold:function(l){if(J>l)l=J;else if(Q<l)l=Q;return ta(l,0,1)},isXAxis:ka,options:h,plotLinesAndBands:Ob,getOffset:function(){var l=Y.length&&L(J)&&L(Q),p=0,r=0,o=h.title,U=h.labels,X=[-1,1,1,-1][G];if(!rb){rb=$.g("axis").attr({zIndex:7}).add();Fb=$.g("grid").attr({zIndex:1}).add()}fc=0;if(l||Nb){t(pa,function(C){if(qb[C])qb[C].addLabel();else qb[C]=new x(C);if(G===0||G==
+2||{1:"left",3:"right"}[G]==U.align)fc=Ga(qb[C].getLabelSize(),fc)});if(Nc)fc+=(Nc-1)*16}else for(var H in qb){qb[H].destroy();delete qb[H]}if(o&&o.text){if(!s.axisTitle)s.axisTitle=$.text(o.text,0,0).attr({zIndex:7,rotation:o.rotation||0,align:o.textAlign||{low:"left",middle:"center",high:"right"}[o.align]}).css(o.style).add();p=s.axisTitle.getBBox()[O?"height":"width"];r=y(o.margin,O?5:10)}R=X*(h.offset||Qb[G]);ed=fc+(G!=2&&fc&&X*h.labels[O?"y":"x"])+r;Qb[G]=Ga(Qb[G],ed+p+X*R)},render:Ya,setCategories:function(l,
+p){s.categories=bb=l;t(Y,function(r){r.translate();r.setTooltipPoints(true)});s.isDirty=true;y(p,true)&&m.redraw()},setExtremes:function(l,p,r,o){Kb(o,m);r=y(r,true);Ja(s,"setExtremes",{min:l,max:p},function(){na=l;Ma=p;r&&m.redraw()})},setScale:Da,setTickPositions:da,translate:ta,redraw:function(){gc.resetTracker&&gc.resetTracker();Ya();t(Ob,function(l){l.render()});t(Y,function(l){l.isDirty=true})},removePlotBand:Ha,removePlotLine:Ha,reversed:Yb,stacks:ca});for(gd in Md)Pa(s,gd,Md[gd]);Da()}function d(){var m=
+{};return{add:function(h,x,w,P){if(!m[h]){x=$.text(x,0,0).css(a.toolbar.itemStyle).align({align:"right",x:-zb-20,y:aa+30}).on("click",P).attr({align:"right",zIndex:20}).add();m[h]=x}},remove:function(h){Fc(m[h].element);m[h]=null}}}function e(m){function h(){var I=this.points||nc(this),B=I[0].series.xAxis,F=this.x;B=B&&B.options.type=="datetime";var ha=Ib(F)||B,va;va=ha?['<span style="font-size: 10px">',B?Mc("%A, %b %e, %Y",F):F,"</span><br/>"]:[];t(I,function(ta){va.push(ta.point.tooltipFormatter(ha))});
+return va.join("")}function x(I,B){G=ka?I:(2*G+I)/3;ca=ka?B:(ca+B)/2;s.translate(G,ca);id=ab(I-G)>1||ab(B-ca)>1?function(){x(I,B)}:null}function w(){if(!ka){var I=q.hoverPoints;s.hide();t(da,function(B){B&&B.hide()});I&&t(I,function(B){B.setState()});q.hoverPoints=null;ka=true}}var P,ga=m.borderWidth,M=m.crosshairs,da=[],Da=m.style,sa=m.shared,Ya=oa(Da.padding),Ha=ga+Ya,ka=true,Na,O,G=0,ca=0;Da.padding=0;var s=$.g("tooltip").attr({zIndex:8}).add(),N=$.rect(Ha,Ha,0,0,m.borderRadius,ga).attr({fill:m.backgroundColor,
+"stroke-width":ga}).add(s).shadow(m.shadow),R=$.text("",Ya+Ha,oa(Da.fontSize)+Ya+Ha).attr({zIndex:1}).css(Da).add(s);s.hide();return{shared:sa,refresh:function(I){var B,F,ha,va=0,ta={},Ia=[];ha=I.tooltipPos;B=m.formatter||h;ta=q.hoverPoints;var rb=function(Ea){return{series:Ea.series,point:Ea,x:Ea.category,y:Ea.y,percentage:Ea.percentage,total:Ea.total||Ea.stackTotal}};if(sa){ta&&t(ta,function(Ea){Ea.setState()});q.hoverPoints=I;t(I,function(Ea){Ea.setState(xb);va+=Ea.plotY;Ia.push(rb(Ea))});F=I[0].plotX;
+va=V(va)/I.length;ta={x:I[0].category};ta.points=Ia;I=I[0]}else ta=rb(I);ta=B.call(ta);P=I.series;F=sa?F:I.plotX;va=sa?va:I.plotY;B=V(ha?ha[0]:Fa?Ca-va:F);F=V(ha?ha[1]:Fa?ra-F:va);ha=sa||!I.series.isCartesian||hc(B,F);if(ta===false||!ha)w();else{if(ka){s.show();ka=false}R.attr({text:ta});ha=R.getBBox();Na=ha.width;O=ha.height;N.attr({width:Na+2*Ya,height:O+2*Ya,stroke:m.borderColor||I.color||P.color||"#606060"});B=B-Na+W-25;F=F-O+aa+10;if(B<7){B=7;F-=30}if(F<5)F=5;else if(F+O>Oa)F=Oa-O-5;x(V(B-Ha),
+V(F-Ha))}if(M){M=nc(M);F=M.length;for(var Fb;F--;)if(M[F]&&(Fb=I.series[F?"yAxis":"xAxis"])){B=Fb.getPlotLinePath(I[F?"y":"x"],1);if(da[F])da[F].attr({d:B,visibility:Ab});else{ha={"stroke-width":M[F].width||1,stroke:M[F].color||"#C0C0C0",zIndex:2};if(M[F].dashStyle)ha.dashstyle=M[F].dashStyle;da[F]=$.path(B).attr(ha).add()}}}},hide:w}}function f(m,h){function x(G){var ca;G=G||hb.event;if(!G.target)G.target=G.srcElement;ca=G.touches?G.touches.item(0):G;if(G.type!="mousemove"||hb.opera){for(var s=ua,
+N={left:s.offsetLeft,top:s.offsetTop};s=s.offsetParent;){N.left+=s.offsetLeft;N.top+=s.offsetTop;if(s!=za.body&&s!=za.documentElement){N.left-=s.scrollLeft;N.top-=s.scrollTop}}qc=N}if(Ac){G.chartX=G.x;G.chartY=G.y}else if(ca.layerX===Qa){G.chartX=ca.pageX-qc.left;G.chartY=ca.pageY-qc.top}else{G.chartX=G.layerX;G.chartY=G.layerY}return G}function w(G){var ca={xAxis:[],yAxis:[]};t(Xa,function(s){var N=s.translate,R=s.isXAxis;ca[R?"xAxis":"yAxis"].push({axis:s,value:N((Fa?!R:R)?G.chartX-W:ra-G.chartY+
+aa,true)})});return ca}function P(){var G=m.hoverSeries,ca=m.hoverPoint;ca&&ca.onMouseOut();G&&G.onMouseOut();rc&&rc.hide();jd=null}function ga(){if(sa){var G={xAxis:[],yAxis:[]},ca=sa.getBBox(),s=ca.x-W,N=ca.y-aa;if(Da){t(Xa,function(R){var I=R.translate,B=R.isXAxis,F=Fa?!B:B,ha=I(F?s:ra-N-ca.height,true);I=I(F?s+ca.width:ra-N,true);G[B?"xAxis":"yAxis"].push({axis:R,min:nb(ha,I),max:Ga(ha,I)})});Ja(m,"selection",G,kd)}sa=sa.destroy()}m.mouseIsDown=ld=Da=false;Bb(za,Gb?"touchend":"mouseup",ga)}var M,
+da,Da,sa,Ya=u.zoomType,Ha=/x/.test(Ya),ka=/y/.test(Ya),Na=Ha&&!Fa||ka&&Fa,O=ka&&!Fa||Ha&&Fa;Pc=function(){if(Qc){Qc.translate(W,aa);Fa&&Qc.attr({width:m.plotWidth,height:m.plotHeight}).invert()}else m.trackerGroup=Qc=$.g("tracker").attr({zIndex:9}).add()};Pc();if(h.enabled)m.tooltip=rc=e(h);(function(){var G=true;ua.onmousedown=function(s){s=x(s);m.mouseIsDown=ld=true;M=s.chartX;da=s.chartY;Pa(za,Gb?"touchend":"mouseup",ga)};var ca=function(s){if(!(s&&s.touches&&s.touches.length>1)){s=x(s);if(!Gb)s.returnValue=
+false;var N=s.chartX,R=s.chartY,I=!hc(N-W,R-aa);if(Gb&&s.type=="touchstart")if(xa(s.target,"isTracker"))m.runTrackerClick||s.preventDefault();else!$d&&!I&&s.preventDefault();if(I){G||P();if(N<W)N=W;else if(N>W+Ca)N=W+Ca;if(R<aa)R=aa;else if(R>aa+ra)R=aa+ra}if(ld&&s.type!="touchstart"){if(Da=Math.sqrt(Math.pow(M-N,2)+Math.pow(da-R,2))>10){if(ic&&(Ha||ka)&&hc(M-W,da-aa))sa||(sa=$.rect(W,aa,Na?1:Ca,O?1:ra,0).attr({fill:"rgba(69,114,167,0.25)",zIndex:7}).add());if(sa&&Na){N=N-M;sa.attr({width:ab(N),x:(N>
+0?0:N)+M})}if(sa&&O){R=R-da;sa.attr({height:ab(R),y:(R>0?0:R)+da})}}}else if(!I){var B;R=m.hoverPoint;N=m.hoverSeries;var F,ha,va=Va,ta=Fa?s.chartY:s.chartX-W;if(rc&&h.shared){B=[];F=Aa.length;for(ha=0;ha<F;ha++)if(Aa[ha].visible&&Aa[ha].tooltipPoints.length){s=Aa[ha].tooltipPoints[ta];s._dist=ab(ta-s.plotX);va=nb(va,s._dist);B.push(s)}for(F=B.length;F--;)B[F]._dist>va&&B.splice(F,1);if(B.length&&B[0].plotX!=jd){rc.refresh(B);jd=B[0].plotX}}if(N&&N.tracker)(s=N.tooltipPoints[ta])&&s!=R&&s.onMouseOver()}return(G=
+I)||!ic}};ua.onmousemove=ca;Pa(ua,"mouseleave",P);ua.ontouchstart=function(s){if(Ha||ka)ua.onmousedown(s);ca(s)};ua.ontouchmove=ca;ua.ontouchend=function(){Da&&P()};ua.onclick=function(s){var N=m.hoverPoint;s=x(s);s.cancelBubble=true;if(!Da)if(N&&xa(s.target,"isTracker")){var R=N.plotX,I=N.plotY;ma(N,{pageX:qc.left+W+(Fa?Ca-I:R),pageY:qc.top+aa+(Fa?ra-R:I)});Ja(N.series,"click",ma(s,{point:N}));N.firePointEvent("click",s)}else{ma(s,w(s));hc(s.chartX-W,s.chartY-aa)&&Ja(m,"click",s)}Da=false}})();Nd=
+setInterval(function(){id&&id()},32);ma(this,{zoomX:Ha,zoomY:ka,resetTracker:P})}function g(m){var h=m.type||u.type||u.defaultSeriesType,x=sb[h],w=q.hasRendered;if(w)if(Fa&&h=="column")x=sb.bar;else if(!Fa&&h=="bar")x=sb.column;h=new x;h.init(q,m);if(!w&&h.inverted)Fa=true;if(h.isCartesian)ic=h.isCartesian;Aa.push(h);return h}function i(){u.alignTicks!==false&&t(Xa,function(m){m.adjustTickAmount()});Eb=null}function j(m){var h=q.isDirtyLegend,x,w=q.isDirtyBox,P=Aa.length,ga=P,M=q.clipRect;for(Kb(m,
+q);ga--;){m=Aa[ga];if(m.isDirty&&m.options.stacking){x=true;break}}if(x)for(ga=P;ga--;){m=Aa[ga];if(m.options.stacking)m.isDirty=true}t(Aa,function(da){if(da.isDirty){da.cleanData();da.getSegments();if(da.options.legendType=="point")h=true}});if(h&&md.renderLegend){md.renderLegend();q.isDirtyLegend=false}if(ic){if(!Rc){Eb=null;t(Xa,function(da){da.setScale()})}i();sc();t(Xa,function(da){if(da.isDirty||w){da.redraw();w=true}})}if(w){nd();Pc();if(M){Sc(M);M.animate({width:q.plotSizeX,height:q.plotSizeY})}}t(Aa,
+function(da){if(da.isDirty&&da.visible&&(!da.isCartesian||da.xAxis))da.redraw()});gc&&gc.resetTracker&&gc.resetTracker();Ja(q,"redraw")}function k(){var m=a.xAxis||{},h=a.yAxis||{},x;m=nc(m);t(m,function(w,P){w.index=P;w.isX=true});h=nc(h);t(h,function(w,P){w.index=P});Xa=m.concat(h);q.xAxis=[];q.yAxis=[];Xa=jc(Xa,function(w){x=new c(q,w);q[x.isXAxis?"xAxis":"yAxis"].push(x);return x});i()}function n(m,h){kc=wa(a.title,m);tc=wa(a.subtitle,h);t([["title",m,kc],["subtitle",h,tc]],function(x){var w=
+x[0],P=q[w],ga=x[1];x=x[2];if(P&&ga){P.destroy();P=null}if(x&&x.text&&!P)q[w]=$.text(x.text,0,0).attr({align:x.align,"class":"highcharts-"+w,zIndex:1}).css(x.style).add().align(x,false,uc)})}function z(){ib=u.renderTo;Od=$b+od++;if(Ib(ib))ib=za.getElementById(ib);ib.innerHTML="";if(!ib.offsetWidth){Rb=ib.cloneNode(0);La(Rb,{position:lc,top:"-9999px",display:""});za.body.appendChild(Rb)}Tc=(Rb||ib).offsetWidth;vc=(Rb||ib).offsetHeight;q.chartWidth=Va=u.width||Tc||600;q.chartHeight=Oa=u.height||(vc>
+19?vc:400);q.container=ua=eb(Lb,{className:"highcharts-container"+(u.className?" "+u.className:""),id:Od},ma({position:Pd,overflow:tb,width:Va+Za,height:Oa+Za,textAlign:"left"},u.style),Rb||ib);q.renderer=$=u.renderer=="SVG"?new Uc(ua,Va,Oa):new Qd(ua,Va,Oa);var m,h;if(/Firefox/.test(wc)&&ua.getBoundingClientRect){m=function(){La(ua,{left:0,top:0});h=ua.getBoundingClientRect();La(ua,{left:-h.left%1+Za,top:-h.top%1+Za})};m();Pa(hb,"resize",m);Pa(q,"destroy",function(){Bb(hb,"resize",m)})}}function E(){function m(){var x=
+u.width||ib.offsetWidth,w=u.height||ib.offsetHeight;if(x&&w){if(x!=Tc||w!=vc){clearTimeout(h);h=setTimeout(function(){pd(x,w,false)},100)}Tc=x;vc=w}}var h;Pa(window,"resize",m);Pa(q,"destroy",function(){Bb(window,"resize",m)})}function ia(){var m=a.labels,h=a.credits,x;n();md=q.legend=new ae(q);sc();t(Xa,function(w){w.setTickPositions(true)});i();sc();nd();ic&&t(Xa,function(w){w.render()});if(!q.seriesGroup)q.seriesGroup=$.g("series-group").attr({zIndex:3}).add();t(Aa,function(w){w.translate();w.setTooltipPoints();
+w.render()});m.items&&t(m.items,function(){var w=ma(m.style,this.style),P=oa(w.left)+W,ga=oa(w.top)+aa+12;delete w.left;delete w.top;$.text(this.html,P,ga).attr({zIndex:2}).css(w).add()});if(!q.toolbar)q.toolbar=d(q);if(h.enabled&&!q.credits){x=h.href;$.text(h.text,0,0).on("click",function(){if(x)location.href=x}).attr({align:h.position.align,zIndex:8}).css(h.style).add().align(h.position)}Pc();q.hasRendered=true;if(Rb){ib.appendChild(ua);Fc(Rb)}}function T(){var m=Aa.length,h=ua&&ua.parentNode;Ja(q,
+"destroy");Bb(hb,"unload",T);Bb(q);for(t(Xa,function(x){Bb(x)});m--;)Aa[m].destroy();ua.innerHTML="";Bb(ua);h&&h.removeChild(ua);ua=null;$.alignedObjects=null;clearInterval(Nd);for(m in q)delete q[m]}function K(){if(!xc&&!hb.parent&&za.readyState!="complete")za.attachEvent("onreadystatechange",function(){za.detachEvent("onreadystatechange",K);K()});else{z();qd();rd();t(a.series||[],function(m){g(m)});q.inverted=Fa=y(Fa,a.chart.inverted);k();q.render=ia;q.tracker=gc=new f(q,a.tooltip);ia();Ja(q,"load");
+b&&b.apply(q,[q]);t(q.callbacks,function(m){m.apply(q,[q])})}}Lc=wa(Lc,Ra.xAxis);fd=wa(fd,Ra.yAxis);Ra.xAxis=Ra.yAxis=null;a=wa(Ra,a);var u=a.chart,A=u.margin;A=Jb(A)?A:[A,A,A,A];var ba=y(u.marginTop,A[0]),ya=y(u.marginRight,A[1]),ea=y(u.marginBottom,A[2]),qa=y(u.marginLeft,A[3]),$a=u.spacingTop,jb=u.spacingRight,sd=u.spacingBottom,Vc=u.spacingLeft,uc,kc,tc,aa,zb,pb,W,Qb,ib,Rb,ua,Od,Tc,vc,Va,Oa,hd,Oc,td,ud,vd,wd,q=this,$d=(A=u.events)&&!!A.click,xd,hc,rc,ld,ac,Rd,yd,ra,Ca,gc,Qc,Pc,md,Sb,Tb,qc,ic=
+u.showAxes,Rc=0,Xa=[],Eb,Aa=[],Fa,$,id,Nd,jd,nd,sc,qd,rd,pd,kd,Sd,ae=function(m){function h(v,Y){var na=v.legendItem,Ma=v.legendLine,Q=v.legendSymbol,J=O.color,fb=Y?M.itemStyle.color:J;J=Y?v.color:J;na&&na.css({fill:fb});Ma&&Ma.attr({stroke:J});Q&&Q.attr({stroke:J,fill:J})}function x(v,Y,na){var Ma=v.legendItem,Q=v.legendLine,J=v.legendSymbol;v=v.checkbox;Ma&&Ma.attr({x:Y,y:na});Q&&Q.translate(Y,na-4);J&&J.attr({x:Y+J.xOff,y:na+J.yOff});if(v){v.x=Y;v.y=na}}function w(){t(Ya,function(v){var Y=v.checkbox;
+Y&&La(Y,{left:Ia.attr("translateX")+v.legendItemWidth+Y.x-40+Za,top:Ia.attr("translateY")+Y.y-11+Za})})}function P(v){var Y,na,Ma,Q,J,fb=v.legendItem;Q=v.series||v;if(!fb){J=/^(bar|pie|area|column)$/.test(Q.type);v.legendItem=fb=$.text(M.labelFormatter.call(v),0,0).css(v.visible?ka:O).on("mouseover",function(){v.setState(xb);fb.css(Na)}).on("mouseout",function(){fb.css(v.visible?ka:O);v.setState()}).on("click",function(){var Wb=function(){v.setVisible()};v.firePointEvent?v.firePointEvent("legendItemClick",
+null,Wb):Ja(v,"legendItemClick",null,Wb)}).attr({zIndex:2}).add(Ia);if(!J&&v.options&&v.options.lineWidth){var cc=v.options;Q={"stroke-width":cc.lineWidth,zIndex:2};if(cc.dashStyle)Q.dashstyle=cc.dashStyle;v.legendLine=$.path([Wa,-Da-sa,0,Ba,-sa,0]).attr(Q).add(Ia)}if(J)Y=$.rect(na=-Da-sa,Ma=-11,Da,12,2).attr({"stroke-width":0,zIndex:3}).add(Ia);else if(v.options&&v.options.marker&&v.options.marker.enabled)Y=$.symbol(v.symbol,na=-Da/2-sa,Ma=-4,v.options.marker.radius).attr(v.pointAttr[cb]).attr({zIndex:3}).add(Ia);
+if(Y){Y.xOff=na;Y.yOff=Ma}v.legendSymbol=Y;h(v,v.visible);if(v.options&&v.options.showCheckbox){v.checkbox=eb("input",{type:"checkbox",checked:v.selected,defaultChecked:v.selected},M.itemCheckboxStyle,ua);Pa(v.checkbox,"click",function(Wb){Ja(v,"checkboxClick",{checked:Wb.target.checked},function(){v.select()})})}}Y=fb.getBBox();na=v.legendItemWidth=M.itemWidth||Da+sa+Y.width+ca;F=Y.height;if(da&&R-N+na>(Fb||Va-2*G-N)){R=N;I+=F}B=I;x(v,R,I);if(da)R+=na;else I+=F;rb=Fb||Ga(da?R-N:na,rb);Ya.push(v)}
+function ga(){R=N;I=s;B=rb=0;Ya=[];Ia||(Ia=$.g("legend").attr({zIndex:7}).add());Sa&&Ea.reverse();t(Ea,function(Ma){if(Ma.options.showInLegend)t(Ma.options.legendType=="point"?Ma.data:[Ma],P)});Sa&&Ea.reverse();Sb=Fb||rb;Tb=B-s+F;if(va||ta){Sb+=2*G;Tb+=2*G;if(ha)Sb>0&&Tb>0&&ha.animate({width:Sb,height:Tb});else ha=$.rect(0,0,Sb,Tb,M.borderRadius,va||0).attr({stroke:M.borderColor,"stroke-width":va||0,fill:ta||mb}).add(Ia).shadow(M.shadow);ha[Ya.length?"show":"hide"]()}for(var v=["left","right","top",
+"bottom"],Y,na=4;na--;){Y=v[na];if(Ha[Y]&&Ha[Y]!="auto"){M[na<2?"align":"verticalAlign"]=Y;M[na<2?"x":"y"]=oa(Ha[Y])*(na%2?-1:1)}}Ia.align(ma(M,{width:Sb,height:Tb}),true,uc);Rc||w()}var M=m.options.legend;if(M.enabled){var da=M.layout=="horizontal",Da=M.symbolWidth,sa=M.symbolPadding,Ya,Ha=M.style,ka=M.itemStyle,Na=M.itemHoverStyle,O=M.itemHiddenStyle,G=oa(Ha.padding),ca=20,s=18,N=4+G+Da+sa,R,I,B,F=0,ha,va=M.borderWidth,ta=M.backgroundColor,Ia,rb,Fb=M.width,Ea=m.series,Sa=M.reversed;ga();Pa(m,"endResize",
+w);return{colorizeItem:h,destroyItem:function(v){var Y=v.checkbox;t(["legendItem","legendLine","legendSymbol"],function(na){v[na]&&v[na].destroy()});Y&&Fc(v.checkbox)},renderLegend:ga}}};hc=function(m,h){return m>=0&&m<=Ca&&h>=0&&h<=ra};Sd=function(){Ja(q,"selection",{resetSelection:true},kd);q.toolbar.remove("zoom")};kd=function(m){var h=Ra.lang,x=q.pointCount<100;q.toolbar.add("zoom",h.resetZoom,h.resetZoomTitle,Sd);!m||m.resetSelection?t(Xa,function(w){w.setExtremes(null,null,false,x)}):t(m.xAxis.concat(m.yAxis),
+function(w){var P=w.axis;if(q.tracker[P.isXAxis?"zoomX":"zoomY"])P.setExtremes(w.min,w.max,false,x)});j()};sc=function(){var m=a.legend,h=y(m.margin,10),x=m.x,w=m.y,P=m.align,ga=m.verticalAlign,M;qd();if((q.title||q.subtitle)&&!L(ba))if(M=Ga(q.title&&!kc.floating&&!kc.verticalAlign&&kc.y||0,q.subtitle&&!tc.floating&&!tc.verticalAlign&&tc.y||0))aa=Ga(aa,M+y(kc.margin,15)+$a);if(m.enabled&&!m.floating)if(P=="right")L(ya)||(zb=Ga(zb,Sb-x+h+jb));else if(P=="left")L(qa)||(W=Ga(W,Sb+x+h+Vc));else if(ga==
+"top")L(ba)||(aa=Ga(aa,Tb+w+h+$a));else if(ga=="bottom")L(ea)||(pb=Ga(pb,Tb-w+h+sd));ic&&t(Xa,function(da){da.getOffset()});L(qa)||(W+=Qb[3]);L(ba)||(aa+=Qb[0]);L(ea)||(pb+=Qb[2]);L(ya)||(zb+=Qb[1]);rd()};pd=function(m,h,x){var w=q.title,P=q.subtitle;Rc+=1;Kb(x,q);Oc=Oa;hd=Va;Va=V(m);Oa=V(h);La(ua,{width:Va+Za,height:Oa+Za});$.setSize(Va,Oa,x);Ca=Va-W-zb;ra=Oa-aa-pb;Eb=null;t(Xa,function(ga){ga.isDirty=true;ga.setScale()});t(Aa,function(ga){ga.isDirty=true});q.isDirtyLegend=true;q.isDirtyBox=true;
+sc();w&&w.align(null,null,uc);P&&P.align(null,null,uc);j(x);Oc=null;Ja(q,"resize");setTimeout(function(){Ja(q,"endResize",null,function(){Rc-=1})},Bc&&Bc.duration||500)};rd=function(){q.plotLeft=W=V(W);q.plotTop=aa=V(aa);q.plotWidth=Ca=V(Va-W-zb);q.plotHeight=ra=V(Oa-aa-pb);q.plotSizeX=Fa?ra:Ca;q.plotSizeY=Fa?Ca:ra;uc={x:Vc,y:$a,width:Va-Vc-jb,height:Oa-$a-sd}};qd=function(){aa=y(ba,$a);zb=y(ya,jb);pb=y(ea,sd);W=y(qa,Vc);Qb=[0,0,0,0]};nd=function(){var m=u.borderWidth||0,h=u.backgroundColor,x=u.plotBackgroundColor,
+w=u.plotBackgroundImage,P,ga={x:W,y:aa,width:Ca,height:ra};P=m+(u.shadow?8:0);if(m||h)if(td)td.animate({width:Va-P,height:Oa-P});else td=$.rect(P/2,P/2,Va-P,Oa-P,u.borderRadius,m).attr({stroke:u.borderColor,"stroke-width":m,fill:h||mb}).add().shadow(u.shadow);if(x)if(ud)ud.animate(ga);else ud=$.rect(W,aa,Ca,ra,0).attr({fill:x}).add().shadow(u.plotShadow);if(w)if(vd)vd.animate(ga);else vd=$.image(w,W,aa,Ca,ra).add();if(u.plotBorderWidth)if(wd)wd.animate(ga);else wd=$.rect(W,aa,Ca,ra,0,u.plotBorderWidth).attr({stroke:u.plotBorderColor,
+"stroke-width":u.plotBorderWidth,zIndex:4}).add();q.isDirtyBox=false};Wc=Hb=0;Pa(hb,"unload",T);u.reflow!==false&&Pa(q,"load",E);if(A)for(xd in A)Pa(q,xd,A[xd]);q.options=a;q.series=Aa;q.addSeries=function(m,h,x){var w;if(m){Kb(x,q);h=y(h,true);Ja(q,"addSeries",{options:m},function(){w=g(m);w.isDirty=true;q.isDirtyLegend=true;h&&q.redraw()})}return w};q.animation=y(u.animation,true);q.destroy=T;q.get=function(m){var h,x,w;for(h=0;h<Xa.length;h++)if(Xa[h].options.id==m)return Xa[h];for(h=0;h<Aa.length;h++)if(Aa[h].options.id==
+m)return Aa[h];for(h=0;h<Aa.length;h++){w=Aa[h].data;for(x=0;x<w.length;x++)if(w[x].id==m)return w[x]}return null};q.getSelectedPoints=function(){var m=[];t(Aa,function(h){m=m.concat(zd(h.data,function(x){return x.selected}))});return m};q.getSelectedSeries=function(){return zd(Aa,function(m){return m.selected})};q.hideLoading=function(){Xc(ac,{opacity:0},{duration:a.loading.hideDuration,complete:function(){La(ac,{display:mb})}});yd=false};q.isInsidePlot=hc;q.redraw=j;q.setSize=pd;q.setTitle=n;q.showLoading=
+function(m){var h=a.loading;if(!ac){ac=eb(Lb,{className:"highcharts-loading"},ma(h.style,{left:W+Za,top:aa+Za,width:Ca+Za,height:ra+Za,zIndex:10,display:mb}),ua);Rd=eb("span",null,h.labelStyle,ac)}Rd.innerHTML=m||a.lang.loading;if(!yd){La(ac,{opacity:0,display:""});Xc(ac,{opacity:h.style.opacity},{duration:h.showDuration});yd=true}};q.pointCount=0;K()}var za=document,hb=window,Ta=Math,V=Ta.round,Mb=Ta.floor,dd=Ta.ceil,Ga=Ta.max,nb=Ta.min,ab=Ta.abs,ub=Ta.cos,yb=Ta.sin,Ub=Ta.PI,Td=Ub*2/360,wc=navigator.userAgent,
+Ac=/msie/i.test(wc)&&!hb.opera,yc=za.documentMode==8,be=/AppleWebKit/.test(wc),xc=hb.SVGAngle||za.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1"),Gb="ontouchstart"in za.documentElement,Hb,Wc,ce={},od=0,ob=1,Gc,Ra,Mc,Bc,Yc,Qa,Lb="div",lc="absolute",Pd="relative",tb="hidden",$b="highcharts-",Ab="visible",Za="px",mb="none",Wa="M",Ba="L",Ud="rgba(192,192,192,"+(xc?1.0E-6:0.0020)+")",cb="",xb="hover",Cc,$c,ad,bd,oc,Dc,Ec,Cd,Dd,cd,Ed,Fd,db=hb.HighchartsAdapter,Cb=db||
+{},t=Cb.each,zd=Cb.grep,jc=Cb.map,wa=Cb.merge,Ad=Cb.hyphenate,Pa=Cb.addEvent,Bb=Cb.removeEvent,Ja=Cb.fireEvent,Xc=Cb.animate,Sc=Cb.stop,sb={};db&&db.init&&db.init();if(!db&&hb.jQuery){var kb=jQuery;t=function(a,b){for(var c=0,d=a.length;c<d;c++)if(b.call(a[c],a[c],c,a)===false)return c};zd=kb.grep;jc=function(a,b){for(var c=[],d=0,e=a.length;d<e;d++)c[d]=b.call(a[d],a[d],d,a);return c};wa=function(){var a=arguments;return kb.extend(true,null,a[0],a[1],a[2],a[3])};Ad=function(a){return a.replace(/([A-Z])/g,
+function(b,c){return"-"+c.toLowerCase()})};Pa=function(a,b,c){kb(a).bind(b,c)};Bb=function(a,b,c){var d=za.removeEventListener?"removeEventListener":"detachEvent";if(za[d]&&!a[d])a[d]=function(){};kb(a).unbind(b,c)};Ja=function(a,b,c,d){var e=kb.Event(b),f="detached"+b;ma(e,c);if(a[b]){a[f]=a[b];a[b]=null}kb(a).trigger(e);if(a[f]){a[b]=a[f];a[f]=null}d&&!e.isDefaultPrevented()&&d(e)};Xc=function(a,b,c){var d=kb(a);if(b.d){a.toD=b.d;b.d=1}d.stop();d.animate(b,c)};Sc=function(a){kb(a).stop()};kb.extend(kb.easing,
+{easeOutQuad:function(a,b,c,d,e){return-d*(b/=e)*(b-2)+c}});var de=jQuery.fx.step._default,ee=jQuery.fx.prototype.cur;kb.fx.step._default=function(a){var b=a.elem;b.attr?b.attr(a.prop,a.now):de.apply(this,arguments)};kb.fx.step.d=function(a){var b=a.elem;if(!a.started){var c=Yc.init(b,b.d,b.toD);a.start=c[0];a.end=c[1];a.started=true}b.attr("d",Yc.step(a.start,a.end,a.pos,b.toD))};kb.fx.prototype.cur=function(){var a=this.elem;return a.attr?a.attr(this.prop):ee.apply(this,arguments)}}Yc={init:function(a,
+b,c){b=b||"";var d=a.shift,e=b.indexOf("C")>-1,f=e?7:3,g;b=b.split(" ");c=[].concat(c);var i,j,k=function(n){for(g=n.length;g--;)n[g]==Wa&&n.splice(g+1,0,n[g+1],n[g+2],n[g+1],n[g+2])};if(e){k(b);k(c)}if(a.isArea){i=b.splice(b.length-6,6);j=c.splice(c.length-6,6)}if(d){c=[].concat(c).splice(0,f).concat(c);a.shift=false}if(b.length)for(a=c.length;b.length<a;){d=[].concat(b).splice(b.length-f,f);if(e){d[f-6]=d[f-2];d[f-5]=d[f-1]}b=b.concat(d)}if(i){b=b.concat(i);c=c.concat(j)}return[b,c]},step:function(a,
+b,c,d){var e=[],f=a.length;if(c==1)e=d;else if(f==b.length&&c<1)for(;f--;){d=parseFloat(a[f]);e[f]=isNaN(d)?a[f]:c*parseFloat(b[f]-d)+d}else e=b;return e}};db={enabled:true,align:"center",x:0,y:15,style:{color:"#666",fontSize:"11px",lineHeight:"14px"}};Ra={colors:["#4572A7","#AA4643","#89A54E","#80699B","#3D96AE","#DB843D","#92A8CD","#A47D7C","#B5CA92"],symbols:["circle","diamond","square","triangle","triangle-down"],lang:{loading:"Loading...",months:["January","February","March","April","May","June",
+"July","August","September","October","November","December"],weekdays:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],decimalPoint:".",resetZoom:"Reset zoom",resetZoomTitle:"Reset zoom level 1:1",thousandsSep:","},global:{useUTC:true},chart:{borderColor:"#4572A7",borderRadius:5,defaultSeriesType:"line",ignoreHiddenSeries:true,spacingTop:10,spacingRight:10,spacingBottom:15,spacingLeft:10,style:{fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif',
+fontSize:"12px"},backgroundColor:"#FFFFFF",plotBorderColor:"#C0C0C0"},title:{text:"Chart title",align:"center",y:15,style:{color:"#3E576F",fontSize:"16px"}},subtitle:{text:"",align:"center",y:30,style:{color:"#6D869F"}},plotOptions:{line:{allowPointSelect:false,showCheckbox:false,animation:{duration:1E3},events:{},lineWidth:2,shadow:true,marker:{enabled:true,lineWidth:0,radius:4,lineColor:"#FFFFFF",states:{hover:{},select:{fillColor:"#FFFFFF",lineColor:"#000000",lineWidth:2}}},point:{events:{}},dataLabels:wa(db,
+{enabled:false,y:-6,formatter:function(){return this.y}}),showInLegend:true,states:{hover:{marker:{}},select:{marker:{}}},stickyTracking:true}},labels:{style:{position:lc,color:"#3E576F"}},legend:{enabled:true,align:"center",layout:"horizontal",labelFormatter:function(){return this.name},borderWidth:1,borderColor:"#909090",borderRadius:5,shadow:false,style:{padding:"5px"},itemStyle:{cursor:"pointer",color:"#3E576F"},itemHoverStyle:{cursor:"pointer",color:"#000000"},itemHiddenStyle:{color:"#C0C0C0"},
+itemCheckboxStyle:{position:lc,width:"13px",height:"13px"},symbolWidth:16,symbolPadding:5,verticalAlign:"bottom",x:0,y:0},loading:{hideDuration:100,labelStyle:{fontWeight:"bold",position:Pd,top:"1em"},showDuration:100,style:{position:lc,backgroundColor:"white",opacity:0.5,textAlign:"center"}},tooltip:{enabled:true,backgroundColor:"rgba(255, 255, 255, .85)",borderWidth:2,borderRadius:5,shadow:true,snap:Gb?25:10,style:{color:"#333333",fontSize:"12px",padding:"5px",whiteSpace:"nowrap"}},toolbar:{itemStyle:{color:"#4572A7",
+cursor:"pointer"}},credits:{enabled:true,text:"Highcharts.com",href:"http://www.highcharts.com",position:{align:"right",x:-10,verticalAlign:"bottom",y:-5},style:{cursor:"pointer",color:"#909090",fontSize:"10px"}}};var Lc={dateTimeLabelFormats:{second:"%H:%M:%S",minute:"%H:%M",hour:"%H:%M",day:"%e. %b",week:"%e. %b",month:"%b '%y",year:"%Y"},endOnTick:false,gridLineColor:"#C0C0C0",labels:db,lineColor:"#C0D0E0",lineWidth:1,max:null,min:null,minPadding:0.01,maxPadding:0.01,minorGridLineColor:"#E0E0E0",
+minorGridLineWidth:1,minorTickColor:"#A0A0A0",minorTickLength:2,minorTickPosition:"outside",startOfWeek:1,startOnTick:false,tickColor:"#C0D0E0",tickLength:5,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",tickWidth:1,title:{align:"middle",style:{color:"#6D869F",fontWeight:"bold"}},type:"linear"},fd=wa(Lc,{endOnTick:true,gridLineWidth:1,tickPixelInterval:72,showLastLabel:true,labels:{align:"right",x:-8,y:3},lineWidth:0,maxPadding:0.05,minPadding:0.05,startOnTick:true,tickWidth:0,
+title:{rotation:270,text:"Y-values"}}),Yd={labels:{align:"right",x:-8,y:null},title:{rotation:270}},Xd={labels:{align:"left",x:8,y:null},title:{rotation:90}},Ld={labels:{align:"center",x:0,y:14},title:{rotation:0}},Wd=wa(Ld,{labels:{y:-5}}),vb=Ra.plotOptions;db=vb.line;vb.spline=wa(db);vb.scatter=wa(db,{lineWidth:0,states:{hover:{lineWidth:0}}});vb.area=wa(db,{});vb.areaspline=wa(vb.area);vb.column=wa(db,{borderColor:"#FFFFFF",borderWidth:1,borderRadius:0,groupPadding:0.2,marker:null,pointPadding:0.1,
+minPointLength:0,states:{hover:{brightness:0.1,shadow:false},select:{color:"#C0C0C0",borderColor:"#000000",shadow:false}}});vb.bar=wa(vb.column,{dataLabels:{align:"left",x:5,y:0}});vb.pie=wa(db,{borderColor:"#FFFFFF",borderWidth:1,center:["50%","50%"],colorByPoint:true,dataLabels:{distance:30,enabled:true,formatter:function(){return this.point.name},y:5},legendType:"point",marker:null,size:"75%",showInLegend:false,slicedOffset:10,states:{hover:{brightness:0.1,shadow:false}}});Bd();var Vb=function(a){var b=
+[],c;(function(d){if(c=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/.exec(d))b=[oa(c[1]),oa(c[2]),oa(c[3]),parseFloat(c[4],10)];else if(c=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(d))b=[oa(c[1],16),oa(c[2],16),oa(c[3],16),1]})(a);return{get:function(d){return b&&!isNaN(b[0])?d=="rgb"?"rgb("+b[0]+","+b[1]+","+b[2]+")":d=="a"?b[3]:"rgba("+b.join(",")+")":a},brighten:function(d){if(bc(d)&&d!==0){var e;for(e=0;e<3;e++){b[e]+=oa(d*255);if(b[e]<
+0)b[e]=0;if(b[e]>255)b[e]=255}}return this},setOpacity:function(d){b[3]=d;return this}}};Mc=function(a,b,c){function d(E){return E.toString().replace(/^([0-9])$/,"0$1")}if(!L(b)||isNaN(b))return"Invalid date";a=y(a,"%Y-%m-%d %H:%M:%S");b=new Date(b*ob);var e=b[ad](),f=b[bd](),g=b[oc](),i=b[Dc](),j=b[Ec](),k=Ra.lang,n=k.weekdays;k=k.months;b={a:n[f].substr(0,3),A:n[f],d:d(g),e:g,b:k[i].substr(0,3),B:k[i],m:d(i+1),y:j.toString().substr(2,2),Y:j,H:d(e),I:d(e%12||12),l:e%12||12,M:d(b[$c]()),p:e<12?"AM":
+"PM",P:e<12?"am":"pm",S:d(b.getSeconds())};for(var z in b)a=a.replace("%"+z,b[z]);return c?a.substr(0,1).toUpperCase()+a.substr(1):a};Hc.prototype={init:function(a,b){this.element=za.createElementNS("http://www.w3.org/2000/svg",b);this.renderer=a},animate:function(a,b,c){if(b=y(b,Bc,true)){b=wa(b);if(c)b.complete=c;Xc(this,a,b)}else{this.attr(a);c&&c()}},attr:function(a,b){var c,d,e,f,g=this.element,i=g.nodeName,j=this.renderer,k,n=this.shadows,z,E=this;if(Ib(a)&&L(b)){c=a;a={};a[c]=b}if(Ib(a)){c=
+a;if(i=="circle")c={x:"cx",y:"cy"}[c]||c;else if(c=="strokeWidth")c="stroke-width";E=xa(g,c)||this[c]||0;if(c!="d"&&c!="visibility")E=parseFloat(E)}else for(c in a){k=false;d=a[c];if(c=="d"){if(d&&d.join)d=d.join(" ");if(/(NaN| {2}|^$)/.test(d))d="M 0 0";this.d=d}else if(c=="x"&&i=="text"){for(e=0;e<g.childNodes.length;e++){f=g.childNodes[e];xa(f,"x")==xa(g,"x")&&xa(f,"x",d)}if(this.rotation)xa(g,"transform","rotate("+this.rotation+" "+d+" "+oa(a.y||xa(g,"y"))+")")}else if(c=="fill")d=j.color(d,g,
+c);else if(i=="circle"&&(c=="x"||c=="y"))c={x:"cx",y:"cy"}[c]||c;else if(c=="translateX"||c=="translateY"||c=="rotation"||c=="verticalAlign"){this[c]=d;this.updateTransform();k=true}else if(c=="stroke")d=j.color(d,g,c);else if(c=="dashstyle"){c="stroke-dasharray";if(d){d=d.toLowerCase().replace("shortdashdotdot","3,1,1,1,1,1,").replace("shortdashdot","3,1,1,1").replace("shortdot","1,1,").replace("shortdash","3,1,").replace("longdash","8,3,").replace(/dot/g,"1,3,").replace("dash","4,3,").replace(/,$/,
+"").split(",");for(e=d.length;e--;)d[e]=oa(d[e])*a["stroke-width"];d=d.join(",")}}else if(c=="isTracker")this[c]=d;else if(c=="width")d=oa(d);else if(c=="align"){c="text-anchor";d={left:"start",center:"middle",right:"end"}[d]}if(c=="strokeWidth")c="stroke-width";if(be&&c=="stroke-width"&&d===0)d=1.0E-6;if(this.symbolName&&/^(x|y|r|start|end|innerR)/.test(c)){if(!z){this.symbolAttr(a);z=true}k=true}if(n&&/^(width|height|visibility|x|y|d)$/.test(c))for(e=n.length;e--;)xa(n[e],c,d);if(c=="text"){this.textStr=
+d;j.buildText(this)}else k||xa(g,c,d)}return E},symbolAttr:function(a){this.x=y(a.x,this.x);this.y=y(a.y,this.y);this.r=y(a.r,this.r);this.start=y(a.start,this.start);this.end=y(a.end,this.end);this.width=y(a.width,this.width);this.height=y(a.height,this.height);this.innerR=y(a.innerR,this.innerR);this.attr({d:this.renderer.symbols[this.symbolName](this.x,this.y,this.r,{start:this.start,end:this.end,width:this.width,height:this.height,innerR:this.innerR})})},clip:function(a){return this.attr("clip-path",
+"url("+this.renderer.url+"#"+a.id+")")},css:function(a){var b=this.element;if(a&&a.color)a.fill=a.color;a=ma(this.styles,a);Ac&&!xc?La(this.element,a):this.attr({style:Vd(a)});this.styles=a;a.width&&b.nodeName=="text"&&this.added&&this.renderer.buildText(this);return this},on:function(a,b){var c=b;if(Gb&&a=="click"){a="touchstart";c=function(d){d.preventDefault();b()}}this.element["on"+a]=c;return this},translate:function(a,b){return this.attr({translateX:a,translateY:b})},invert:function(){this.inverted=
+true;this.updateTransform();return this},updateTransform:function(){var a=this.translateX||0,b=this.translateY||0,c=this.inverted,d=this.rotation,e=[];if(c){a+=this.attr("width");b+=this.attr("height")}if(a||b)e.push("translate("+a+","+b+")");if(c)e.push("rotate(90) scale(-1,1)");else d&&e.push("rotate("+d+" "+this.x+" "+this.y+")");e.length&&xa(this.element,"transform",e.join(" "))},toFront:function(){var a=this.element;a.parentNode.appendChild(a);return this},align:function(a,b,c){if(a){this.alignOptions=
+a;this.alignByTranslate=b;c||this.renderer.alignedObjects.push(this)}else{a=this.alignOptions;b=this.alignByTranslate}c=y(c,this.renderer);var d=a.align,e=a.verticalAlign,f=(c.x||0)+(a.x||0),g=(c.y||0)+(a.y||0),i={};if(/^(right|center)$/.test(d))f+=(c.width-(a.width||0))/{right:1,center:2}[d];i[b?"translateX":"x"]=f;if(/^(bottom|middle)$/.test(e))g+=(c.height-(a.height||0))/({bottom:1,middle:2}[e]||1);i[b?"translateY":"y"]=g;this[this.placed?"animate":"attr"](i);this.placed=true;return this},getBBox:function(){var a,
+b,c,d=this.rotation,e=d*Td;try{a=ma({},this.element.getBBox())}catch(f){a={width:0,height:0}}b=a.width;c=a.height;if(d){a.width=ab(c*yb(e))+ab(b*ub(e));a.height=ab(c*ub(e))+ab(b*yb(e))}return a},show:function(){return this.attr({visibility:Ab})},hide:function(){return this.attr({visibility:tb})},add:function(a){var b=this.renderer,c=a||b,d=c.element||b.box,e=d.childNodes,f=this.element,g=xa(f,"zIndex"),i=this.textStr,j;this.parentInverted=a&&a.inverted;if(g){c.handleZ=true;g=oa(g)}if(c.handleZ)for(j=
+0;j<e.length;j++){a=e[j];c=xa(a,"zIndex");if(a!=f&&(oa(c)>g||!L(g)&&L(c))){d.insertBefore(f,a);return this}}if(i!==undefined){b.buildText(this);this.added=true}d.appendChild(f);return this},destroy:function(){var a=this.element||{},b=this.shadows,c=a.parentNode,d;a.onclick=a.onmouseout=a.onmouseover=a.onmousemove=null;Sc(this);c&&c.removeChild(a);b&&t(b,function(e){(c=e.parentNode)&&c.removeChild(e)});mc(this.renderer.alignedObjects,this);for(d in this)delete this[d];return null},empty:function(){for(var a=
+this.element,b=a.childNodes,c=b.length;c--;)a.removeChild(b[c])},shadow:function(a){var b=[],c,d=this.element,e=this.parentInverted?"(-1,-1)":"(1,1)";if(a){for(a=1;a<=3;a++){c=d.cloneNode(0);xa(c,{isShadow:"true",stroke:"rgb(0, 0, 0)","stroke-opacity":0.05*a,"stroke-width":7-2*a,transform:"translate"+e,fill:mb});d.parentNode.insertBefore(c,d);b.push(c)}this.shadows=b}return this}};var Uc=function(){this.init.apply(this,arguments)};Uc.prototype={init:function(a,b,c){var d=location,e;this.Element=Hc;
+e=this.createElement("svg").attr({xmlns:"http://www.w3.org/2000/svg",version:"1.1"});a.appendChild(e.element);this.box=e.element;this.boxWrapper=e;this.alignedObjects=[];this.url=Ac?"":d.href.replace(/#.*?$/,"");this.defs=this.createElement("defs").add();this.setSize(b,c,false)},createElement:function(a){var b=new this.Element;b.init(this,a);return b},buildText:function(a){var b=a.element,c=y(a.textStr,"").toString().replace(/<(b|strong)>/g,'<span style="font-weight:bold">').replace(/<(i|em)>/g,'<span style="font-style:italic">').replace(/<a/g,
+"<span").replace(/<\/(b|strong|i|em|a)>/g,"</span>").split(/<br[^>]?>/g),d=b.childNodes,e=/style="([^"]+)"/,f=/href="([^"]+)"/,g=xa(b,"x"),i=(a=a.styles)&&oa(a.width),j=a&&a.lineHeight,k;for(a=d.length;a--;)b.removeChild(d[a]);i&&this.box.appendChild(b);t(c,function(n,z){var E,ia=0,T;n=n.replace(/<span/g,"|||<span").replace(/<\/span>/g,"</span>|||");E=n.split("|||");t(E,function(K){if(K!==""||E.length==1){var u={},A=za.createElementNS("http://www.w3.org/2000/svg","tspan");e.test(K)&&xa(A,"style",
+K.match(e)[1].replace(/(;| |^)color([ :])/,"$1fill$2"));if(f.test(K)){xa(A,"onclick",'location.href="'+K.match(f)[1]+'"');La(A,{cursor:"pointer"})}K=K.replace(/<(.|\n)*?>/g,"")||" ";A.appendChild(za.createTextNode(K));if(ia)u.dx=3;else u.x=g;if(!ia){if(z){T=oa(window.getComputedStyle(k,null).getPropertyValue("line-height"));if(isNaN(T))T=j||k.offsetHeight||18;xa(A,"dy",T)}k=A}xa(A,u);b.appendChild(A);ia++;if(i){K=K.replace(/-/g,"- ").split(" ");for(var ba,ya=[];K.length||ya.length;){ba=b.getBBox().width;
+u=ba>i;if(!u||K.length==1){K=ya;ya=[];A=za.createElementNS("http://www.w3.org/2000/svg","tspan");xa(A,{x:g,dy:j||16});b.appendChild(A);if(ba>i)i=ba}else{A.removeChild(A.firstChild);ya.unshift(K.pop())}A.appendChild(za.createTextNode(K.join(" ").replace(/- /g,"-")))}}}})})},crispLine:function(a,b){if(a[1]==a[4])a[1]=a[4]=V(a[1])+b%2/2;if(a[2]==a[5])a[2]=a[5]=V(a[2])+b%2/2;return a},path:function(a){return this.createElement("path").attr({d:a,fill:mb})},circle:function(a,b,c){a=Jb(a)?a:{x:a,y:b,r:c};
+return this.createElement("circle").attr(a)},arc:function(a,b,c,d,e,f){if(Jb(a)){b=a.y;c=a.r;d=a.innerR;e=a.start;f=a.end;a=a.x}return this.symbol("arc",a||0,b||0,c||0,{innerR:d||0,start:e||0,end:f||0})},rect:function(a,b,c,d,e,f){if(arguments.length>1){var g=(f||0)%2/2;a=V(a||0)+g;b=V(b||0)+g;c=V((c||0)-2*g);d=V((d||0)-2*g)}g=Jb(a)?a:{x:a,y:b,width:Ga(c,0),height:Ga(d,0)};return this.createElement("rect").attr(ma(g,{rx:e||g.r,ry:e||g.r,fill:mb}))},setSize:function(a,b,c){var d=this.alignedObjects,
+e=d.length;this.width=a;this.height=b;for(this.boxWrapper[y(c,true)?"animate":"attr"]({width:a,height:b});e--;)d[e].align()},g:function(a){return this.createElement("g").attr(L(a)&&{"class":$b+a})},image:function(a,b,c,d,e){var f={preserveAspectRatio:mb};arguments.length>1&&ma(f,{x:b,y:c,width:d,height:e});f=this.createElement("image").attr(f);f.element.setAttributeNS("http://www.w3.org/1999/xlink","href",a);return f},symbol:function(a,b,c,d,e){var f,g=this.symbols[a];g=g&&g(b,c,d,e);var i=/^url\((.*?)\)$/;
+if(g){f=this.path(g);ma(f,{symbolName:a,x:b,y:c,r:d});e&&ma(f,e)}else if(i.test(a)){a=a.match(i)[1];f=this.image(a).attr({x:b,y:c});eb("img",{onload:function(){var j=ce[this.src]||[this.width,this.height];f.attr({width:j[0],height:j[1]}).translate(-V(j[0]/2),-V(j[1]/2))},src:a})}else f=this.circle(b,c,d);return f},symbols:{square:function(a,b,c){c=0.707*c;return[Wa,a-c,b-c,Ba,a+c,b-c,a+c,b+c,a-c,b+c,"Z"]},triangle:function(a,b,c){return[Wa,a,b-1.33*c,Ba,a+c,b+0.67*c,a-c,b+0.67*c,"Z"]},"triangle-down":function(a,
+b,c){return[Wa,a,b+1.33*c,Ba,a-c,b-0.67*c,a+c,b-0.67*c,"Z"]},diamond:function(a,b,c){return[Wa,a,b-c,Ba,a+c,b,a,b+c,a-c,b,"Z"]},arc:function(a,b,c,d){var e=d.start,f=d.end-1.0E-6,g=d.innerR,i=ub(e),j=yb(e),k=ub(f);f=yb(f);d=d.end-e<Ub?0:1;return[Wa,a+c*i,b+c*j,"A",c,c,0,d,1,a+c*k,b+c*f,Ba,a+g*k,b+g*f,"A",g,g,0,d,0,a+g*i,b+g*j,"Z"]}},clipRect:function(a,b,c,d){var e=$b+od++,f=this.createElement("clipPath").attr({id:e}).add(this.defs);a=this.rect(a,b,c,d,0).add(f);a.id=e;return a},color:function(a,
+b,c){var d,e=/^rgba/;if(a&&a.linearGradient){var f=this;b=a.linearGradient;c=$b+od++;var g,i,j;g=f.createElement("linearGradient").attr({id:c,gradientUnits:"userSpaceOnUse",x1:b[0],y1:b[1],x2:b[2],y2:b[3]}).add(f.defs);t(a.stops,function(k){if(e.test(k[1])){d=Vb(k[1]);i=d.get("rgb");j=d.get("a")}else{i=k[1];j=1}f.createElement("stop").attr({offset:k[0],"stop-color":i,"stop-opacity":j}).add(g)});return"url("+this.url+"#"+c+")"}else if(e.test(a)){d=Vb(a);xa(b,c+"-opacity",d.get("a"));return d.get("rgb")}else return a},
+text:function(a,b,c){var d=Ra.chart.style;b=V(y(b,0));c=V(y(c,0));a=this.createElement("text").attr({x:b,y:c,text:a}).css({"font-family":d.fontFamily,"font-size":d.fontSize});a.x=b;a.y=c;return a}};var Ka;if(!xc){var fe=wb(Hc,{init:function(a,b){var c=["<",b,' filled="f" stroked="f"'],d=["position: ",lc,";"];if(b=="shape"||b==Lb)d.push("left:0;top:0;width:10px;height:10px;");if(yc)d.push("visibility: ",b==Lb?tb:Ab);c.push(' style="',d.join(""),'"/>');if(b){c=b==Lb||b=="span"||b=="img"?c.join(""):
+a.prepVML(c);this.element=eb(c)}this.renderer=a},add:function(a){var b=this.renderer,c=this.element,d=b.box;d=a?a.element||a:d;a&&a.inverted&&b.invertChild(c,d);yc&&d.gVis==tb&&La(c,{visibility:tb});d.appendChild(c);this.added=true;this.alignOnAdd&&this.updateTransform();return this},attr:function(a,b){var c,d,e,f=this.element||{},g=f.style,i=f.nodeName,j=this.renderer,k=this.symbolName,n,z,E=this.shadows,ia=this;if(Ib(a)&&L(b)){c=a;a={};a[c]=b}if(Ib(a)){c=a;ia=c=="strokeWidth"||c=="stroke-width"?
+this.strokeweight:this[c]}else for(c in a){d=a[c];n=false;if(k&&/^(x|y|r|start|end|width|height|innerR)/.test(c)){if(!z){this.symbolAttr(a);z=true}n=true}else if(c=="d"){d=d||[];this.d=d.join(" ");e=d.length;for(n=[];e--;)n[e]=bc(d[e])?V(d[e]*10)-5:d[e]=="Z"?"x":d[e];d=n.join(" ")||"x";f.path=d;if(E)for(e=E.length;e--;)E[e].path=d;n=true}else if(c=="zIndex"||c=="visibility"){if(yc&&c=="visibility"&&i=="DIV"){f.gVis=d;n=f.childNodes;for(e=n.length;e--;)La(n[e],{visibility:d});if(d==Ab)d=null}if(d)g[c]=
+d;n=true}else if(/^(width|height)$/.test(c)){if(this.updateClipping){this[c]=d;this.updateClipping()}else g[c]=d;n=true}else if(/^(x|y)$/.test(c)){this[c]=d;if(f.tagName=="SPAN")this.updateTransform();else g[{x:"left",y:"top"}[c]]=d}else if(c=="class")f.className=d;else if(c=="stroke"){d=j.color(d,f,c);c="strokecolor"}else if(c=="stroke-width"||c=="strokeWidth"){f.stroked=d?true:false;c="strokeweight";this[c]=d;if(bc(d))d+=Za}else if(c=="dashstyle"){(f.getElementsByTagName("stroke")[0]||eb(j.prepVML(["<stroke/>"]),
+null,null,f))[c]=d||"solid";this.dashstyle=d;n=true}else if(c=="fill")if(i=="SPAN")g.color=d;else{f.filled=d!=mb?true:false;d=j.color(d,f,c);c="fillcolor"}else if(c=="translateX"||c=="translateY"||c=="rotation"||c=="align"){if(c=="align")c="textAlign";this[c]=d;this.updateTransform();n=true}else if(c=="text"){f.innerHTML=d;n=true}if(E&&c=="visibility")for(e=E.length;e--;)E[e].style[c]=d;if(!n)if(yc)f[c]=d;else xa(f,c,d)}return ia},clip:function(a){var b=this,c=a.members;c.push(b);b.destroyClip=function(){mc(c,
+b)};return b.css(a.getCSS(b.inverted))},css:function(a){var b=this.element;(b=a&&a.width&&b.tagName=="SPAN")&&ma(a,{display:"block",whiteSpace:"normal"});this.styles=ma(this.styles,a);La(this.element,a);b&&this.updateTransform();return this},destroy:function(){this.destroyClip&&this.destroyClip();Hc.prototype.destroy.apply(this)},empty:function(){for(var a=this.element.childNodes,b=a.length,c;b--;){c=a[b];c.parentNode.removeChild(c)}},getBBox:function(){var a=this.element;if(a.nodeName=="text")a.style.position=
+lc;return{x:a.offsetLeft,y:a.offsetTop,width:a.offsetWidth,height:a.offsetHeight}},on:function(a,b){this.element["on"+a]=function(){var c=hb.event;c.target=c.srcElement;b(c)};return this},updateTransform:function(){if(this.added){var a=this,b=a.element,c=a.translateX||0,d=a.translateY||0,e=a.x||0,f=a.y||0,g=a.textAlign||"left",i={left:0,center:0.5,right:1}[g],j=g&&g!="left";if(c||d)a.css({marginLeft:c,marginTop:d});a.inverted&&t(b.childNodes,function(A){a.renderer.invertChild(A,b)});if(b.tagName==
+"SPAN"){var k,n;c=a.rotation;var z;k=0;d=1;var E=0,ia,T=a.xCorr||0,K=a.yCorr||0,u=[c,g,b.innerHTML,b.style.width].join(",");if(u!=a.cTT){if(L(c)){k=c*Td;d=ub(k);E=yb(k);La(b,{filter:c?["progid:DXImageTransform.Microsoft.Matrix(M11=",d,", M12=",-E,", M21=",E,", M22=",d,", sizingMethod='auto expand')"].join(""):mb})}k=b.offsetWidth;n=b.offsetHeight;z=V(oa(b.style.fontSize||12)*1.2);T=d<0&&-k;K=E<0&&-n;ia=d*E<0;T+=E*z*(ia?1-i:i);K-=d*z*(c?ia?i:1-i:1);if(j){T-=k*i*(d<0?-1:1);if(c)K-=n*i*(E<0?-1:1);La(b,
+{textAlign:g})}a.xCorr=T;a.yCorr=K}La(b,{left:e+T,top:f+K});a.cTT=u}}else this.alignOnAdd=true},shadow:function(a){var b=[],c=this.element,d=this.renderer,e,f=c.style,g,i=c.path;if(""+c.path==="")i="x";if(a){for(a=1;a<=3;a++){g=['<shape isShadow="true" strokeweight="',7-2*a,'" filled="false" path="',i,'" coordsize="100,100" style="',c.style.cssText,'" />'];e=eb(d.prepVML(g),null,{left:oa(f.left)+1,top:oa(f.top)+1});g=['<stroke color="black" opacity="',0.05*a,'"/>'];eb(d.prepVML(g),null,null,e);c.parentNode.insertBefore(e,
+c);b.push(e)}this.shadows=b}return this}});Ka=function(){this.init.apply(this,arguments)};Ka.prototype=wa(Uc.prototype,{isIE8:wc.indexOf("MSIE 8.0")>-1,init:function(a,b,c){var d;this.Element=fe;this.alignedObjects=[];d=this.createElement(Lb);a.appendChild(d.element);this.box=d.element;this.boxWrapper=d;this.setSize(b,c,false);if(!za.namespaces.hcv){za.namespaces.add("hcv","urn:schemas-microsoft-com:vml");za.createStyleSheet().cssText="hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } "}},
+clipRect:function(a,b,c,d){var e=this.createElement();return ma(e,{members:[],left:a,top:b,width:c,height:d,getCSS:function(f){var g=this.top,i=this.left,j=i+this.width,k=g+this.height;g={clip:"rect("+V(f?i:g)+"px,"+V(f?k:j)+"px,"+V(f?j:k)+"px,"+V(f?g:i)+"px)"};!f&&yc&&ma(g,{width:j+Za,height:k+Za});return g},updateClipping:function(){t(e.members,function(f){f.css(e.getCSS(f.inverted))})}})},color:function(a,b,c){var d,e=/^rgba/;if(a&&a.linearGradient){var f,g,i=a.linearGradient,j,k,n,z;t(a.stops,
+function(E,ia){if(e.test(E[1])){d=Vb(E[1]);f=d.get("rgb");g=d.get("a")}else{f=E[1];g=1}if(ia){n=f;z=g}else{j=f;k=g}});a=90-Ta.atan((i[3]-i[1])/(i[2]-i[0]))*180/Ub;c=["<",c,' colors="0% ',j,",100% ",n,'" angle="',a,'" opacity="',z,'" o:opacity2="',k,'" type="gradient" focus="100%" />'];eb(this.prepVML(c),null,null,b)}else if(e.test(a)&&b.tagName!="IMG"){d=Vb(a);c=["<",c,' opacity="',d.get("a"),'"/>'];eb(this.prepVML(c),null,null,b);return d.get("rgb")}else return a},prepVML:function(a){var b=this.isIE8;
+a=a.join("");if(b){a=a.replace("/>",' xmlns="urn:schemas-microsoft-com:vml" />');a=a.indexOf('style="')==-1?a.replace("/>",' style="display:inline-block;behavior:url(#default#VML);" />'):a.replace('style="','style="display:inline-block;behavior:url(#default#VML);')}else a=a.replace("<","<hcv:");return a},text:function(a,b,c){var d=Ra.chart.style;return this.createElement("span").attr({text:a,x:V(b),y:V(c)}).css({whiteSpace:"nowrap",fontFamily:d.fontFamily,fontSize:d.fontSize})},path:function(a){return this.createElement("shape").attr({coordsize:"100 100",
+d:a})},circle:function(a,b,c){return this.path(this.symbols.circle(a,b,c))},g:function(a){var b;if(a)b={className:$b+a,"class":$b+a};return this.createElement(Lb).attr(b)},image:function(a,b,c,d,e){var f=this.createElement("img").attr({src:a});arguments.length>1&&f.css({left:b,top:c,width:d,height:e});return f},rect:function(a,b,c,d,e,f){if(arguments.length>1){var g=(f||0)%2/2;a=V(a||0)+g;b=V(b||0)+g;c=V((c||0)-2*g);d=V((d||0)-2*g)}if(Jb(a)){b=a.y;c=a.width;d=a.height;e=a.r;a=a.x}return this.symbol("rect",
+a||0,b||0,e||0,{width:c||0,height:d||0})},invertChild:function(a,b){var c=b.style;La(a,{flip:"x",left:oa(c.width)-10,top:oa(c.height)-10,rotation:-90})},symbols:{arc:function(a,b,c,d){var e=d.start,f=d.end,g=ub(e),i=yb(e),j=ub(f),k=yb(f);d=d.innerR;if(f-e===0)return["x"];else if(f-e==2*Ub)j=-0.07/c;return["wa",a-c,b-c,a+c,b+c,a+c*g,b+c*i,a+c*j,b+c*k,"at",a-d,b-d,a+d,b+d,a+d*j,b+d*k,a+d*g,b+d*i,"x","e"]},circle:function(a,b,c){return["wa",a-c,b-c,a+c,b+c,a+c,b,a+c,b,"e"]},rect:function(a,b,c,d){var e=
+d.width;d=d.height;var f=a+e,g=b+d;c=nb(c,e,d);return[Wa,a+c,b,Ba,f-c,b,"wa",f-2*c,b,f,b+2*c,f-c,b,f,b+c,Ba,f,g-c,"wa",f-2*c,g-2*c,f,g,f,g-c,f-c,g,Ba,a+c,g,"wa",a,g-2*c,a+2*c,g,a+c,g,a,g-c,Ba,a,b+c,"wa",a,b,a+2*c,b+2*c,a,b+c,a+c,b,"x","e"]}}})}var Qd=xc?Uc:Ka;Hd.prototype.callbacks=[];var zc=function(){};zc.prototype={init:function(a,b){var c;this.series=a;this.applyOptions(b);this.pointAttr={};if(a.options.colorByPoint){c=a.chart.options.colors;if(!this.options)this.options={};this.color=this.options.color=
+this.color||c[Hb++];if(Hb>=c.length)Hb=0}a.chart.pointCount++;return this},applyOptions:function(a){var b=this.series;this.config=a;if(bc(a)||a===null)this.y=a;else if(Jb(a)&&!bc(a.length)){ma(this,a);this.options=a}else if(Ib(a[0])){this.name=a[0];this.y=a[1]}else if(bc(a[0])){this.x=a[0];this.y=a[1]}if(this.x===Qa)this.x=b.autoIncrement()},destroy:function(){var a=this,b=a.series,c;b.chart.pointCount--;a==b.chart.hoverPoint&&a.onMouseOut();b.chart.hoverPoints=null;Bb(a);t(["graphic","tracker","group",
+"dataLabel","connector"],function(d){a[d]&&a[d].destroy()});a.legendItem&&a.series.chart.legend.destroyItem(a);for(c in a)a[c]=null},select:function(a,b){var c=this,d=c.series.chart;c.selected=a=y(a,!c.selected);c.firePointEvent(a?"select":"unselect");c.setState(a&&"select");b||t(d.getSelectedPoints(),function(e){if(e.selected&&e!=c){e.selected=false;e.setState(cb);e.firePointEvent("unselect")}})},onMouseOver:function(){var a=this.series.chart,b=a.tooltip,c=a.hoverPoint;c&&c!=this&&c.onMouseOut();
+this.firePointEvent("mouseOver");b&&!b.shared&&b.refresh(this);this.setState(xb);a.hoverPoint=this},onMouseOut:function(){this.firePointEvent("mouseOut");this.setState();this.series.chart.hoverPoint=null},tooltipFormatter:function(a){var b=this.series;return['<span style="color:'+b.color+'">',this.name||b.name,"</span>: ",!a?"<b>x = "+(this.name||this.x)+",</b> ":"","<b>",!a?"y = ":"",this.y,"</b><br/>"].join("")},update:function(a,b,c){var d=this,e=d.series,f=e.chart;Kb(c,f);b=y(b,true);d.firePointEvent("update",
+{options:a},function(){d.applyOptions(a);e.isDirty=true;b&&f.redraw()})},remove:function(a,b){var c=this,d=c.series,e=d.chart,f=d.data;Kb(b,e);a=y(a,true);c.firePointEvent("remove",null,function(){mc(f,c);c.destroy();d.isDirty=true;a&&e.redraw()})},firePointEvent:function(a,b,c){var d=this,e=this.series.options;if(e.point.events[a]||d.options&&d.options.events&&d.options.events[a])this.importEvents();if(a=="click"&&e.allowPointSelect)c=function(f){d.select(null,f.ctrlKey||f.metaKey||f.shiftKey)};
+Ja(this,a,b,c)},importEvents:function(){if(!this.hasImportedEvents){var a=wa(this.series.options.point,this.options).events,b;this.events=a;for(b in a)Pa(this,b,a[b]);this.hasImportedEvents=true}},setState:function(a){var b=this.series,c=b.options.states,d=vb[b.type].marker&&b.options.marker,e=d&&!d.enabled,f=(d=d&&d.states[a])&&d.enabled===false,g=b.stateMarkerGraphic,i=b.chart,j=this.pointAttr;a||(a=cb);if(!(a==this.state||this.selected&&a!="select"||c[a]&&c[a].enabled===false||a&&(f||e&&!d.enabled))){if(this.graphic)this.graphic.attr(j[a]);
+else{if(a){if(!g)b.stateMarkerGraphic=g=i.renderer.circle(0,0,j[a].r).attr(j[a]).add(b.group);g.translate(this.plotX,this.plotY)}if(g)g[a?"show":"hide"]()}this.state=a}}};var lb=function(){};lb.prototype={isCartesian:true,type:"line",pointClass:zc,pointAttrToOptions:{stroke:"lineColor","stroke-width":"lineWidth",fill:"fillColor",r:"radius"},init:function(a,b){var c,d;d=a.series.length;this.chart=a;b=this.setOptions(b);ma(this,{index:d,options:b,name:b.name||"Series "+(d+1),state:cb,pointAttr:{},visible:b.visible!==
+false,selected:b.selected===true});d=b.events;for(c in d)Pa(this,c,d[c]);if(d&&d.click||b.point&&b.point.events&&b.point.events.click||b.allowPointSelect)a.runTrackerClick=true;this.getColor();this.getSymbol();this.setData(b.data,false)},autoIncrement:function(){var a=this.options,b=this.xIncrement;b=y(b,a.pointStart,0);this.pointInterval=y(this.pointInterval,a.pointInterval,1);this.xIncrement=b+this.pointInterval;return b},cleanData:function(){var a=this.chart,b=this.data,c,d,e=a.smallestInterval,
+f,g;b.sort(function(i,j){return i.x-j.x});for(g=b.length-1;g>=0;g--)b[g-1]&&b[g-1].x==b[g].x&&b.splice(g-1,1);for(g=b.length-1;g>=0;g--)if(b[g-1]){f=b[g].x-b[g-1].x;if(d===Qa||f<d){d=f;c=g}}if(e===Qa||d<e)a.smallestInterval=d;this.closestPoints=c},getSegments:function(){var a=-1,b=[],c=this.data;t(c,function(d,e){if(d.y===null){e>a+1&&b.push(c.slice(a+1,e));a=e}else e==c.length-1&&b.push(c.slice(a+1,e+1))});this.segments=b},setOptions:function(a){var b=this.chart.options.plotOptions;return wa(b[this.type],
+b.series,a)},getColor:function(){var a=this.chart.options.colors;this.color=this.options.color||a[Hb++]||"#0000ff";if(Hb>=a.length)Hb=0},getSymbol:function(){var a=this.chart.options.symbols;this.symbol=this.options.marker.symbol||a[Wc++];if(Wc>=a.length)Wc=0},addPoint:function(a,b,c,d){var e=this.data,f=this.graph,g=this.area,i=this.chart;a=(new this.pointClass).init(this,a);Kb(d,i);if(f&&c)f.shift=c;if(g){g.shift=c;g.isArea=true}b=y(b,true);e.push(a);c&&e[0].remove(false);this.isDirty=true;b&&i.redraw()},
+setData:function(a,b){var c=this,d=c.data,e=c.initialColor,f=c.chart,g=d&&d.length||0;c.xIncrement=null;if(L(e))Hb=e;for(a=jc(nc(a||[]),function(i){return(new c.pointClass).init(c,i)});g--;)d[g].destroy();c.data=a;c.cleanData();c.getSegments();c.isDirty=true;f.isDirtyBox=true;y(b,true)&&f.redraw(false)},remove:function(a,b){var c=this,d=c.chart;a=y(a,true);if(!c.isRemoving){c.isRemoving=true;Ja(c,"remove",null,function(){c.destroy();d.isDirtyLegend=d.isDirtyBox=true;a&&d.redraw(b)})}c.isRemoving=
+false},translate:function(){for(var a=this.chart,b=this.options.stacking,c=this.xAxis.categories,d=this.yAxis,e=this.data,f=e.length;f--;){var g=e[f],i=g.x,j=g.y,k=g.low,n=d.stacks[(j<0?"-":"")+this.stackKey];g.plotX=this.xAxis.translate(i);if(b&&this.visible&&n[i]){k=n[i];i=k.total;k.cum=k=k.cum-j;j=k+j;if(b=="percent"){k=i?k*100/i:0;j=i?j*100/i:0}g.percentage=i?g.y*100/i:0;g.stackTotal=i}if(L(k))g.yBottom=d.translate(k,0,1);if(j!==null)g.plotY=d.translate(j,0,1);g.clientX=a.inverted?a.plotHeight-
+g.plotX:g.plotX;g.category=c&&c[g.x]!==Qa?c[g.x]:g.x}},setTooltipPoints:function(a){var b=this.chart,c=b.inverted,d=[],e=V((c?b.plotTop:b.plotLeft)+b.plotSizeX),f,g,i=[];if(a)this.tooltipPoints=null;t(this.segments,function(j){d=d.concat(j)});if(this.xAxis&&this.xAxis.reversed)d=d.reverse();t(d,function(j,k){f=d[k-1]?d[k-1].high+1:0;for(g=j.high=d[k+1]?Mb((j.plotX+(d[k+1]?d[k+1].plotX:e))/2):e;f<=g;)i[c?e-f++:f++]=j});this.tooltipPoints=i},onMouseOver:function(){var a=this.chart,b=a.hoverSeries;if(!(!Gb&&
+a.mouseIsDown)){b&&b!=this&&b.onMouseOut();this.options.events.mouseOver&&Ja(this,"mouseOver");this.tracker&&this.tracker.toFront();this.setState(xb);a.hoverSeries=this}},onMouseOut:function(){var a=this.options,b=this.chart,c=b.tooltip,d=b.hoverPoint;d&&d.onMouseOut();this&&a.events.mouseOut&&Ja(this,"mouseOut");c&&!a.stickyTracking&&c.hide();this.setState();b.hoverSeries=null},animate:function(a){var b=this.chart,c=this.clipRect,d=this.options.animation;if(d&&!Jb(d))d={};if(a){if(!c.isAnimating){c.attr("width",
+0);c.isAnimating=true}}else{c.animate({width:b.plotSizeX},d);this.animate=null}},drawPoints:function(){var a,b=this.data,c=this.chart,d,e,f,g,i,j;if(this.options.marker.enabled)for(f=b.length;f--;){g=b[f];d=g.plotX;e=g.plotY;j=g.graphic;if(e!==Qa&&!isNaN(e)){a=g.pointAttr[g.selected?"select":cb];i=a.r;if(j)j.animate({x:d,y:e,r:i});else g.graphic=c.renderer.symbol(y(g.marker&&g.marker.symbol,this.symbol),d,e,i).attr(a).add(this.group)}}},convertAttribs:function(a,b,c,d){var e=this.pointAttrToOptions,
+f,g,i={};a=a||{};b=b||{};c=c||{};d=d||{};for(f in e){g=e[f];i[f]=y(a[g],b[f],c[f],d[f])}return i},getAttribs:function(){var a=this,b=vb[a.type].marker?a.options.marker:a.options,c=b.states,d=c[xb],e,f=a.color,g={stroke:f,fill:f},i=a.data,j=[],k,n=a.pointAttrToOptions;if(a.options.marker){d.radius=d.radius||b.radius+2;d.lineWidth=d.lineWidth||b.lineWidth+1}else d.color=d.color||Vb(d.color||f).brighten(d.brightness).get();j[cb]=a.convertAttribs(b,g);t([xb,"select"],function(E){j[E]=a.convertAttribs(c[E],
+j[cb])});a.pointAttr=j;for(f=i.length;f--;){g=i[f];if((b=g.options&&g.options.marker||g.options)&&b.enabled===false)b.radius=0;e=false;if(g.options)for(var z in n)if(L(b[n[z]]))e=true;if(e){k=[];c=b.states||{};e=c[xb]=c[xb]||{};if(!a.options.marker)e.color=Vb(e.color||g.options.color).brighten(e.brightness||d.brightness).get();k[cb]=a.convertAttribs(b,j[cb]);k[xb]=a.convertAttribs(c[xb],j[xb],k[cb]);k.select=a.convertAttribs(c.select,j.select,k[cb])}else k=j;g.pointAttr=k}},destroy:function(){var a=
+this,b=a.chart,c=/\/5[0-9\.]+ Safari\//.test(wc),d,e;Bb(a);a.legendItem&&a.chart.legend.destroyItem(a);t(a.data,function(f){f.destroy()});t(["area","graph","dataLabelsGroup","group","tracker"],function(f){if(a[f]){d=c&&f=="group"?"hide":"destroy";a[f][d]()}});if(b.hoverSeries==a)b.hoverSeries=null;mc(b.series,a);for(e in a)delete a[e]},drawDataLabels:function(){if(this.options.dataLabels.enabled){var a=this,b,c,d=a.data,e=a.options.dataLabels,f,g=a.dataLabelsGroup,i=a.chart,j=i.inverted,k=a.type,
+n;if(!g)g=a.dataLabelsGroup=i.renderer.g($b+"data-labels").attr({visibility:a.visible?Ab:tb,zIndex:5}).translate(i.plotLeft,i.plotTop).add();n=e.color;if(n=="auto")n=null;e.style.color=y(n,a.color);t(d,function(z){var E=z.barX;E=E&&E+z.barW/2||z.plotX||-999;var ia=y(z.plotY,-999),T=z.dataLabel,K=e.align;f=e.formatter.call({x:z.x,y:z.y,series:a,point:z,percentage:z.percentage,total:z.total||z.stackTotal});b=(j?i.plotWidth-ia:E)+e.x;c=(j?i.plotHeight-E:ia)+e.y;if(k=="column")b+={left:-1,right:1}[K]*
+z.barW/2||0;if(T)T.animate({x:b,y:c});else if(f)T=z.dataLabel=i.renderer.text(f,b,c).attr({align:K,rotation:e.rotation,zIndex:1}).css(e.style).add(g);j&&!e.y&&T.attr({y:c+parseInt(T.styles.lineHeight)*0.9-T.getBBox().height/2})})}},drawGraph:function(){var a=this,b=a.options,c=a.graph,d=[],e,f=a.area,g=a.group,i=b.lineColor||a.color,j=b.lineWidth,k=b.dashStyle,n,z=a.chart.renderer,E=a.yAxis.getThreshold(b.threshold||0),ia=/^area/.test(a.type),T=[],K=[];t(a.segments,function(u){n=[];t(u,function(ea,
+qa){if(a.getPointSpline)n.push.apply(n,a.getPointSpline(u,ea,qa));else{n.push(qa?Ba:Wa);qa&&b.step&&n.push(ea.plotX,u[qa-1].plotY);n.push(ea.plotX,ea.plotY)}});if(u.length>1)d=d.concat(n);else T.push(u[0]);if(ia){var A=[],ba,ya=n.length;for(ba=0;ba<ya;ba++)A.push(n[ba]);ya==3&&A.push(Ba,n[1],n[2]);if(b.stacking&&a.type!="areaspline")for(ba=u.length-1;ba>=0;ba--)A.push(u[ba].plotX,u[ba].yBottom);else A.push(Ba,u[u.length-1].plotX,E,Ba,u[0].plotX,E);K=K.concat(A)}});a.graphPath=d;a.singlePoints=T;if(ia){e=
+y(b.fillColor,Vb(a.color).setOpacity(b.fillOpacity||0.75).get());if(f)f.animate({d:K});else a.area=a.chart.renderer.path(K).attr({fill:e}).add(g)}if(c)c.animate({d:d});else if(j){c={stroke:i,"stroke-width":j};if(k)c.dashstyle=k;a.graph=z.path(d).attr(c).add(g).shadow(b.shadow)}},render:function(){var a=this,b=a.chart,c,d,e=a.options,f=e.animation,g=f&&a.animate;f=g?f&&f.duration||500:0;var i=a.clipRect;d=b.renderer;if(!i){i=a.clipRect=!b.hasRendered&&b.clipRect?b.clipRect:d.clipRect(0,0,b.plotSizeX,
+b.plotSizeY);if(!b.clipRect)b.clipRect=i}if(!a.group){c=a.group=d.g("series");if(b.inverted){d=function(){c.attr({width:b.plotWidth,height:b.plotHeight}).invert()};d();Pa(b,"resize",d)}c.clip(a.clipRect).attr({visibility:a.visible?Ab:tb,zIndex:e.zIndex}).translate(b.plotLeft,b.plotTop).add(b.seriesGroup)}a.drawDataLabels();g&&a.animate(true);a.getAttribs();a.drawGraph&&a.drawGraph();a.drawPoints();a.options.enableMouseTracking!==false&&a.drawTracker();g&&a.animate();setTimeout(function(){i.isAnimating=
+false;if((c=a.group)&&i!=b.clipRect&&i.renderer){c.clip(a.clipRect=b.clipRect);i.destroy()}},f);a.isDirty=false},redraw:function(){var a=this.chart,b=this.group;if(b){a.inverted&&b.attr({width:a.plotWidth,height:a.plotHeight});b.animate({translateX:a.plotLeft,translateY:a.plotTop})}this.translate();this.setTooltipPoints(true);this.render()},setState:function(a){var b=this.options,c=this.graph,d=b.states;b=b.lineWidth;a=a||cb;if(this.state!=a){this.state=a;if(!(d[a]&&d[a].enabled===false)){if(a)b=
+d[a].lineWidth||b+1;if(c&&!c.dashstyle)c.attr({"stroke-width":b},a?0:500)}}},setVisible:function(a,b){var c=this.chart,d=this.legendItem,e=this.group,f=this.tracker,g=this.dataLabelsGroup,i,j=this.data,k=c.options.chart.ignoreHiddenSeries;i=this.visible;i=(this.visible=a=a===Qa?!i:a)?"show":"hide";e&&e[i]();if(f)f[i]();else for(e=j.length;e--;){f=j[e];f.tracker&&f.tracker[i]()}g&&g[i]();d&&c.legend.colorizeItem(this,a);this.isDirty=true;this.options.stacking&&t(c.series,function(n){if(n.options.stacking&&
+n.visible)n.isDirty=true});if(k)c.isDirtyBox=true;b!==false&&c.redraw();Ja(this,i)},show:function(){this.setVisible(true)},hide:function(){this.setVisible(false)},select:function(a){this.selected=a=a===Qa?!this.selected:a;if(this.checkbox)this.checkbox.checked=a;Ja(this,a?"select":"unselect")},drawTracker:function(){var a=this,b=a.options,c=[].concat(a.graphPath),d=c.length,e=a.chart,f=e.options.tooltip.snap,g=a.tracker,i=b.cursor;i=i&&{cursor:i};var j=a.singlePoints,k;if(d)for(k=d+1;k--;){c[k]==
+Wa&&c.splice(k+1,0,c[k+1]-f,c[k+2],Ba);if(k&&c[k]==Wa||k==d)c.splice(k,0,Ba,c[k-2]+f,c[k-1])}for(k=0;k<j.length;k++){d=j[k];c.push(Wa,d.plotX-f,d.plotY,Ba,d.plotX+f,d.plotY)}if(g)g.attr({d:c});else a.tracker=e.renderer.path(c).attr({isTracker:true,stroke:Ud,fill:mb,"stroke-width":b.lineWidth+2*f,visibility:a.visible?Ab:tb,zIndex:1}).on(Gb?"touchstart":"mouseover",function(){e.hoverSeries!=a&&a.onMouseOver()}).on("mouseout",function(){b.stickyTracking||a.onMouseOut()}).css(i).add(e.trackerGroup)}};
+Ka=wb(lb);sb.line=Ka;Ka=wb(lb,{type:"area"});sb.area=Ka;Ka=wb(lb,{type:"spline",getPointSpline:function(a,b,c){var d=b.plotX,e=b.plotY,f=a[c-1],g=a[c+1],i,j,k,n;if(c&&c<a.length-1){a=f.plotY;k=g.plotX;g=g.plotY;var z;i=(1.5*d+f.plotX)/2.5;j=(1.5*e+a)/2.5;k=(1.5*d+k)/2.5;n=(1.5*e+g)/2.5;z=(n-j)*(k-d)/(k-i)+e-n;j+=z;n+=z;if(j>a&&j>e){j=Ga(a,e);n=2*e-j}else if(j<a&&j<e){j=nb(a,e);n=2*e-j}if(n>g&&n>e){n=Ga(g,e);j=2*e-n}else if(n<g&&n<e){n=nb(g,e);j=2*e-n}b.rightContX=k;b.rightContY=n}if(c){b=["C",f.rightContX||
+f.plotX,f.rightContY||f.plotY,i||d,j||e,d,e];f.rightContX=f.rightContY=null}else b=[Wa,d,e];return b}});sb.spline=Ka;Ka=wb(Ka,{type:"areaspline"});sb.areaspline=Ka;var Zc=wb(lb,{type:"column",pointAttrToOptions:{stroke:"borderColor","stroke-width":"borderWidth",fill:"color",r:"borderRadius"},init:function(){lb.prototype.init.apply(this,arguments);var a=this,b=a.chart;b.hasColumn=true;b.hasRendered&&t(b.series,function(c){if(c.type==a.type)c.isDirty=true})},translate:function(){var a=this,b=a.chart,
+c=0,d=a.xAxis.reversed,e=a.xAxis.categories,f={},g,i;lb.prototype.translate.apply(a);t(b.series,function(A){if(A.type==a.type){if(A.options.stacking){g=A.stackKey;if(f[g]===Qa)f[g]=c++;i=f[g]}else i=c++;A.columnIndex=i}});var j=a.options,k=a.data,n=a.closestPoints;b=ab(k[1]?k[n].plotX-k[n-1].plotX:b.plotSizeX/(e?e.length:1));e=b*j.groupPadding;n=(b-2*e)/c;var z=j.pointWidth,E=L(z)?(n-z)/2:n*j.pointPadding,ia=y(z,n-2*E),T=E+(e+((d?c-a.columnIndex:a.columnIndex)||0)*n-b/2)*(d?-1:1),K=a.yAxis.getThreshold(j.threshold||
+0),u=y(j.minPointLength,5);t(k,function(A){var ba=A.plotY,ya=A.yBottom||K,ea=A.plotX+T,qa=dd(nb(ba,ya)),$a=dd(Ga(ba,ya)-qa),jb;if(ab($a)<u){if(u){$a=u;qa=ab(qa-K)>u?ya-u:K-(ba<=K?u:0)}jb=qa-3}ma(A,{barX:ea,barY:qa,barW:ia,barH:$a});A.shapeType="rect";A.shapeArgs={x:ea,y:qa,width:ia,height:$a,r:j.borderRadius};A.trackerArgs=L(jb)&&wa(A.shapeArgs,{height:Ga(6,$a+3),y:jb})})},getSymbol:function(){},drawGraph:function(){},drawPoints:function(){var a=this,b=a.options,c=a.chart.renderer,d,e;t(a.data,function(f){var g=
+f.plotY;if(g!==Qa&&!isNaN(g)){d=f.graphic;e=f.shapeArgs;if(d){Sc(d);d.animate(e)}else f.graphic=c[f.shapeType](e).attr(f.pointAttr[f.selected?"select":cb]).add(a.group).shadow(b.shadow)}})},drawTracker:function(){var a=this,b=a.chart,c=b.renderer,d,e,f=+new Date,g=a.options.cursor,i=g&&{cursor:g},j;t(a.data,function(k){e=k.tracker;d=k.trackerArgs||k.shapeArgs;if(k.y!==null)if(e)e.attr(d);else k.tracker=c[k.shapeType](d).attr({isTracker:f,fill:Ud,visibility:a.visible?Ab:tb,zIndex:1}).on(Gb?"touchstart":
+"mouseover",function(n){j=n.relatedTarget||n.fromElement;b.hoverSeries!=a&&xa(j,"isTracker")!=f&&a.onMouseOver();k.onMouseOver()}).on("mouseout",function(n){if(!a.options.stickyTracking){j=n.relatedTarget||n.toElement;xa(j,"isTracker")!=f&&a.onMouseOut()}}).css(i).add(b.trackerGroup)})},animate:function(a){var b=this,c=b.data;if(!a){t(c,function(d){var e=d.graphic;if(e){e.attr({height:0,y:b.yAxis.translate(0,0,1)});e.animate({height:d.barH,y:d.barY},b.options.animation)}});b.animate=null}},remove:function(){var a=
+this,b=a.chart;b.hasRendered&&t(b.series,function(c){if(c.type==a.type)c.isDirty=true});lb.prototype.remove.apply(a,arguments)}});sb.column=Zc;Ka=wb(Zc,{type:"bar",init:function(a){a.inverted=this.inverted=true;Zc.prototype.init.apply(this,arguments)}});sb.bar=Ka;Ka=wb(lb,{type:"scatter",translate:function(){var a=this;lb.prototype.translate.apply(a);t(a.data,function(b){b.shapeType="circle";b.shapeArgs={x:b.plotX,y:b.plotY,r:a.chart.options.tooltip.snap}})},drawTracker:function(){var a=this,b=a.options.cursor,
+c=b&&{cursor:b},d;t(a.data,function(e){(d=e.graphic)&&d.attr({isTracker:true}).on("mouseover",function(){a.onMouseOver();e.onMouseOver()}).on("mouseout",function(){a.options.stickyTracking||a.onMouseOut()}).css(c)})},cleanData:function(){}});sb.scatter=Ka;Ka=wb(zc,{init:function(){zc.prototype.init.apply(this,arguments);var a=this,b;ma(a,{visible:a.visible!==false,name:y(a.name,"Slice")});b=function(){a.slice()};Pa(a,"select",b);Pa(a,"unselect",b);return a},setVisible:function(a){var b=this.series.chart,
+c=this.tracker,d=this.dataLabel,e=this.connector,f;f=(this.visible=a=a===Qa?!this.visible:a)?"show":"hide";this.group[f]();c&&c[f]();d&&d[f]();e&&e[f]();this.legendItem&&b.legend.colorizeItem(this,a)},slice:function(a,b,c){var d=this.series.chart,e=this.slicedTranslation;Kb(c,d);y(b,true);a=this.sliced=L(a)?a:!this.sliced;this.group.animate({translateX:a?e[0]:d.plotLeft,translateY:a?e[1]:d.plotTop})}});Ka=wb(lb,{type:"pie",isCartesian:false,pointClass:Ka,pointAttrToOptions:{stroke:"borderColor","stroke-width":"borderWidth",
+fill:"color"},getColor:function(){this.initialColor=Hb},animate:function(){var a=this;t(a.data,function(b){var c=b.graphic;b=b.shapeArgs;var d=-Ub/2;if(c){c.attr({r:0,start:d,end:d});c.animate({r:b.r,start:b.start,end:b.end},a.options.animation)}});a.animate=null},translate:function(){var a=0,b=-0.25,c=this.options,d=c.slicedOffset,e=d+c.borderWidth,f=c.center,g=this.chart,i=g.plotWidth,j=g.plotHeight,k,n,z,E=this.data,ia=2*Ub,T,K=nb(i,j),u,A,ba,ya=c.dataLabels.distance;f.push(c.size,c.innerSize||
+0);f=jc(f,function(ea,qa){return(u=/%$/.test(ea))?[i,j,K,K][qa]*oa(ea)/100:ea});this.getX=function(ea,qa){z=Ta.asin((ea-f[1])/(f[2]/2+ya));return f[0]+(qa?-1:1)*ub(z)*(f[2]/2+ya)};this.center=f;t(E,function(ea){a+=ea.y});t(E,function(ea){T=a?ea.y/a:0;k=V(b*ia*1E3)/1E3;b+=T;n=V(b*ia*1E3)/1E3;ea.shapeType="arc";ea.shapeArgs={x:f[0],y:f[1],r:f[2]/2,innerR:f[3]/2,start:k,end:n};z=(n+k)/2;ea.slicedTranslation=jc([ub(z)*d+g.plotLeft,yb(z)*d+g.plotTop],V);A=ub(z)*f[2]/2;ba=yb(z)*f[2]/2;ea.tooltipPos=[f[0]+
+A*0.7,f[1]+ba*0.7];ea.labelPos=[f[0]+A+ub(z)*ya,f[1]+ba+yb(z)*ya,f[0]+A+ub(z)*e,f[1]+ba+yb(z)*e,f[0]+A,f[1]+ba,ya<0?"center":z<ia/4?"left":"right",z];ea.percentage=T*100;ea.total=a});this.setTooltipPoints()},render:function(){this.getAttribs();this.drawPoints();this.options.enableMouseTracking!==false&&this.drawTracker();this.drawDataLabels();this.options.animation&&this.animate&&this.animate();this.isDirty=false},drawPoints:function(){var a=this.chart,b=a.renderer,c,d,e,f;t(this.data,function(g){d=
+g.graphic;f=g.shapeArgs;e=g.group;if(!e)e=g.group=b.g("point").attr({zIndex:5}).add();c=g.sliced?g.slicedTranslation:[a.plotLeft,a.plotTop];e.translate(c[0],c[1]);if(d)d.animate(f);else g.graphic=b.arc(f).attr(ma(g.pointAttr[cb],{"stroke-linejoin":"round"})).add(g.group);g.visible===false&&g.setVisible(false)})},drawDataLabels:function(){var a=this.data,b,c=this.chart,d=this.options.dataLabels,e=y(d.connectorPadding,10),f=y(d.connectorWidth,1),g,i,j=d.distance>0,k,n,z=this.center[1],E=[[],[],[],[]],
+ia,T,K,u,A,ba,ya,ea=4,qa;lb.prototype.drawDataLabels.apply(this);t(a,function($a){var jb=$a.labelPos[7];E[jb<0?0:jb<Ub/2?1:jb<Ub?2:3].push($a)});E[1].reverse();E[3].reverse();for(ya=function($a,jb){return $a.y>jb.y};ea--;){a=0;b=[].concat(E[ea]);b.sort(ya);for(qa=b.length;qa--;)b[qa].rank=qa;for(u=0;u<2;u++){n=(ba=ea%3)?9999:-9999;A=ba?-1:1;for(qa=0;qa<E[ea].length;qa++){b=E[ea][qa];if(g=b.dataLabel){i=b.labelPos;K=Ab;ia=i[0];T=i[1];k||(k=g&&g.getBBox().height);if(j)if(u&&b.rank<a)K=tb;else if(!ba&&
+T<n+k||ba&&T>n-k){T=n+A*k;ia=this.getX(T,ea>1);if(!ba&&T+k>z||ba&&T-k<z)if(u)K=tb;else a++}if(b.visible===false)K=tb;if(K==Ab)n=T;if(u){g.attr({visibility:K,align:i[6]})[g.moved?"animate":"attr"]({x:ia+d.x+({left:e,right:-e}[i[6]]||0),y:T+d.y});g.moved=true;if(j&&f){g=b.connector;i=[Wa,ia+(i[6]=="left"?5:-5),T,Ba,ia,T,Ba,i[2],i[3],Ba,i[4],i[5]];if(g){g.animate({d:i});g.attr("visibility",K)}else b.connector=g=this.chart.renderer.path(i).attr({"stroke-width":f,stroke:d.connectorColor||"#606060",visibility:K,
+zIndex:3}).translate(c.plotLeft,c.plotTop).add()}}}}}}},drawTracker:Zc.prototype.drawTracker,getSymbol:function(){}});sb.pie=Ka;hb.Highcharts={Chart:Hd,dateFormat:Mc,pathAnim:Yc,getOptions:function(){return Ra},numberFormat:Gd,Point:zc,Color:Vb,Renderer:Qd,seriesTypes:sb,setOptions:function(a){Ra=wa(Ra,a);Bd();return Ra},Series:lb,addEvent:Pa,createElement:eb,discardElement:Fc,css:La,each:t,extend:ma,map:jc,merge:wa,pick:y,extendClass:wb,version:"2.1.2"}})();


[7/9] first commit

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/highcharts/highcharts.src.js
----------------------------------------------------------------------
diff --git a/attachments/highcharts/highcharts.src.js b/attachments/highcharts/highcharts.src.js
new file mode 100755
index 0000000..0a661b0
--- /dev/null
+++ b/attachments/highcharts/highcharts.src.js
@@ -0,0 +1,10580 @@
+// ==ClosureCompiler==
+// @compilation_level SIMPLE_OPTIMIZATIONS
+
+/**
+ * @license Highcharts JS v2.1.2 (2011-01-12)
+ * 
+ * (c) 2009-2010 Torstein Hønsi
+ * 
+ * License: www.highcharts.com/license
+ */
+
+// JSLint options:
+/*jslint forin: true */
+/*global document, window, navigator, setInterval, clearInterval, clearTimeout, setTimeout, location, jQuery, $ */
+	
+(function() {
+// encapsulated variables
+var doc = document,
+	win = window,
+	math = Math,
+	mathRound = math.round,
+	mathFloor = math.floor,
+	mathCeil = math.ceil,
+	mathMax = math.max,
+	mathMin = math.min,
+	mathAbs = math.abs,
+	mathCos = math.cos,
+	mathSin = math.sin,
+	mathPI = math.PI,
+	deg2rad = mathPI * 2 / 360,
+	
+	
+	// some variables
+	userAgent = navigator.userAgent,
+	isIE = /msie/i.test(userAgent) && !win.opera,
+	docMode8 = doc.documentMode == 8,
+	isWebKit = /AppleWebKit/.test(userAgent),
+	hasSVG = win.SVGAngle || doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"),
+	SVG_NS = 'http://www.w3.org/2000/svg',
+	hasTouch = 'ontouchstart' in doc.documentElement,
+	colorCounter,
+	symbolCounter,
+	symbolSizes = {},
+	idCounter = 0,
+	timeFactor = 1, // 1 = JavaScript time, 1000 = Unix time
+	garbageBin,
+	defaultOptions,
+	dateFormat, // function
+	globalAnimation,
+	pathAnim,
+	
+	
+	// some constants for frequently used strings
+	UNDEFINED,
+	DIV = 'div',
+	ABSOLUTE = 'absolute',
+	RELATIVE = 'relative',
+	HIDDEN = 'hidden',
+	PREFIX = 'highcharts-',
+	VISIBLE = 'visible',
+	PX = 'px',
+	NONE = 'none',
+	M = 'M',
+	L = 'L',
+	/*
+	 * Empirical lowest possible opacities for TRACKER_FILL
+	 * IE6: 0.002
+	 * IE7: 0.002
+	 * IE8: 0.002
+	 * IE9: 0.00000000001 (unlimited)
+	 * FF: 0.00000000001 (unlimited)
+	 * Chrome: 0.000001
+	 * Safari: 0.000001
+	 * Opera: 0.00000000001 (unlimited)
+	 */
+	TRACKER_FILL = 'rgba(192,192,192,'+ (hasSVG ? 0.000001 : 0.002) +')', // invisible but clickable
+	NORMAL_STATE = '',
+	HOVER_STATE = 'hover',
+	SELECT_STATE = 'select',
+	
+	// time methods, changed based on whether or not UTC is used
+	makeTime,
+	getMinutes,
+	getHours,
+	getDay,
+	getDate,
+	getMonth,
+	getFullYear,
+	setMinutes,
+	setHours,
+	setDate,
+	setMonth,
+	setFullYear,
+	
+	// check for a custom HighchartsAdapter defined prior to this file
+	globalAdapter = win.HighchartsAdapter,
+	adapter = globalAdapter || {}, 
+	
+	// Utility functions. If the HighchartsAdapter is not defined, adapter is an empty object
+	// and all the utility functions will be null. In that case they are populated by the 
+	// default adapters below.
+	each = adapter.each,
+	grep = adapter.grep,
+	map = adapter.map,
+	merge = adapter.merge,
+	hyphenate = adapter.hyphenate,
+	addEvent = adapter.addEvent,
+	removeEvent = adapter.removeEvent,
+	fireEvent = adapter.fireEvent,
+	animate = adapter.animate,
+	stop = adapter.stop,
+	
+	// lookup over the types and the associated classes
+	seriesTypes = {},
+	hoverChart;
+	
+/**
+ * Extend an object with the members of another
+ * @param {Object} a The object to be extended
+ * @param {Object} b The object to add to the first one
+ */
+function extend(a, b) {
+	if (!a) {
+		a = {};
+	}
+	for (var n in b) {
+		a[n] = b[n];
+	}
+	return a;
+}
+
+/**
+ * Shortcut for parseInt
+ * @param {Object} s
+ */
+function pInt(s, mag) {
+	return parseInt(s, mag || 10);
+}
+
+/**
+ * Check for string
+ * @param {Object} s
+ */
+function isString(s) {
+	return typeof s == 'string';
+}
+
+/**
+ * Check for object
+ * @param {Object} obj
+ */
+function isObject(obj) {
+	return typeof obj == 'object';
+}
+
+/**
+ * Check for number
+ * @param {Object} n
+ */
+function isNumber(n) {
+	return typeof n == 'number';
+}
+
+/**
+ * Remove last occurence of an item from an array
+ * @param {Array} arr
+ * @param {Mixed} item
+ */
+function erase(arr, item) {
+	var i = arr.length;
+	while (i--) {
+		if (arr[i] == item) {
+			arr.splice(i, 1);
+			break;
+		}
+	}
+	//return arr;
+}
+
+/**
+ * Returns true if the object is not null or undefined. Like MooTools' $.defined.
+ * @param {Object} obj
+ */
+function defined (obj) {
+	return obj !== UNDEFINED && obj !== null;
+}
+
+/**
+ * Set or get an attribute or an object of attributes. Can't use jQuery attr because
+ * it attempts to set expando properties on the SVG element, which is not allowed.
+ * 
+ * @param {Object} elem The DOM element to receive the attribute(s)
+ * @param {String|Object} prop The property or an abject of key-value pairs
+ * @param {String} value The value if a single property is set
+ */
+function attr(elem, prop, value) {
+	var key,
+		setAttribute = 'setAttribute',
+		ret;
+	
+	// if the prop is a string
+	if (isString(prop)) {
+		// set the value
+		if (defined(value)) {
+
+			elem[setAttribute](prop, value);
+		
+		// get the value
+		} else if (elem && elem.getAttribute) { // elem not defined when printing pie demo...
+			ret = elem.getAttribute(prop);
+		}
+	
+	// else if prop is defined, it is a hash of key/value pairs
+	} else if (defined(prop) && isObject(prop)) {
+		for (key in prop) {
+			elem[setAttribute](key, prop[key]);
+		}
+	}
+	return ret;
+}
+/**
+ * Check if an element is an array, and if not, make it into an array. Like
+ * MooTools' $.splat.
+ */
+function splat(obj) {
+	if (!obj || obj.constructor != Array) {
+		obj = [obj];
+	}
+	return obj; 
+}
+
+
+
+/**
+ * Return the first value that is defined. Like MooTools' $.pick.
+ */
+function pick() {
+	var args = arguments,
+		i,
+		arg,
+		length = args.length;
+	for (i = 0; i < length; i++) {
+		arg = args[i];
+		if (typeof arg !== 'undefined' && arg !== null) {
+			return arg;
+		}
+	}
+}
+/**
+ * Make a style string from a JS object
+ * @param {Object} style
+ */
+function serializeCSS(style) {
+	var s = '', 
+		key;
+	// serialize the declaration
+	for (key in style) {
+		s += hyphenate(key) +':'+ style[key] + ';';
+	}
+	return s;
+	
+}
+/**
+ * Set CSS on a give element
+ * @param {Object} el
+ * @param {Object} styles
+ */
+function css (el, styles) {
+	if (isIE) {
+		if (styles && styles.opacity !== UNDEFINED) {
+			styles.filter = 'alpha(opacity='+ (styles.opacity * 100) +')';
+		}
+	}
+	extend(el.style, styles);
+}
+
+/**
+ * Utility function to create element with attributes and styles
+ * @param {Object} tag
+ * @param {Object} attribs
+ * @param {Object} styles
+ * @param {Object} parent
+ * @param {Object} nopad
+ */
+function createElement (tag, attribs, styles, parent, nopad) {
+	var el = doc.createElement(tag);
+	if (attribs) {
+		extend(el, attribs);
+	}
+	if (nopad) {
+		css(el, {padding: 0, border: NONE, margin: 0});
+	}
+	if (styles) {
+		css(el, styles);
+	}
+	if (parent) {
+		parent.appendChild(el);
+	}	
+	return el;
+}
+
+/**
+ * Set the global animation to either a given value, or fall back to the 
+ * given chart's animation option
+ * @param {Object} animation
+ * @param {Object} chart
+ */
+function setAnimation(animation, chart) {
+	globalAnimation = pick(animation, chart.animation);
+}
+
+/* 
+ * Define the adapter for frameworks. If an external adapter is not defined, 
+ * Highcharts reverts to the built-in jQuery adapter.
+ */
+if (globalAdapter && globalAdapter.init) {
+	globalAdapter.init();
+} 
+if (!globalAdapter && win.jQuery) {
+	var jQ = jQuery;
+	
+	/**
+	 * Utility for iterating over an array. Parameters are reversed compared to jQuery.
+	 * @param {Array} arr
+	 * @param {Function} fn
+	 */
+	each = function(arr, fn) {
+		for (var i = 0, len = arr.length; i < len; i++) {
+			if (fn.call(arr[i], arr[i], i, arr) === false) {
+				return i;
+			}
+		}
+	};
+	
+	/**
+	 * Filter an array
+	 */
+	grep = jQ.grep;
+	
+	/**
+	 * Map an array
+	 * @param {Array} arr
+	 * @param {Function} fn
+	 */
+	map = function(arr, fn){
+		//return jQuery.map(arr, fn);
+		var results = [];
+		for (var i = 0, len = arr.length; i < len; i++) {
+			results[i] = fn.call(arr[i], arr[i], i, arr);
+		}
+		return results;
+		
+	};
+	
+	/**
+	 * Deep merge two objects and return a third object
+	 */
+	merge = function(){
+		var args = arguments;
+		return jQ.extend(true, null, args[0], args[1], args[2], args[3]);
+	};
+	
+	/**
+	 * Convert a camelCase string to a hyphenated string
+	 * @param {String} str
+	 */
+	hyphenate = function (str) {
+		return str.replace(/([A-Z])/g, function(a, b){ return '-'+ b.toLowerCase(); });
+	};
+	
+	/**
+	 * Add an event listener
+	 * @param {Object} el A HTML element or custom object
+	 * @param {String} event The event type
+	 * @param {Function} fn The event handler
+	 */
+	addEvent = function (el, event, fn){
+		jQ(el).bind(event, fn);
+	};
+	
+	/**
+	 * Remove event added with addEvent
+	 * @param {Object} el The object
+	 * @param {String} eventType The event type. Leave blank to remove all events.
+	 * @param {Function} handler The function to remove
+	 */
+	removeEvent = function(el, eventType, handler) {
+		// workaround for jQuery issue with unbinding custom events:
+		// http://forum.jquery.com/topic/javascript-error-when-unbinding-a-custom-event-using-jquery-1-4-2
+		var func = doc.removeEventListener ? 'removeEventListener' : 'detachEvent';
+		if (doc[func] && !el[func]) {
+			el[func] = function() {};
+		}
+		
+		jQ(el).unbind(eventType, handler);
+	};
+	
+	/**
+	 * Fire an event on a custom object
+	 * @param {Object} el
+	 * @param {String} type
+	 * @param {Object} eventArguments
+	 * @param {Function} defaultFunction
+	 */
+	fireEvent = function(el, type, eventArguments, defaultFunction) {
+		var event = jQ.Event(type),
+			detachedType = 'detached'+ type;
+		extend(event, eventArguments);
+		
+		// Prevent jQuery from triggering the object method that is named the
+		// same as the event. For example, if the event is 'select', jQuery
+		// attempts calling el.select and it goes into a loop.
+		if (el[type]) {
+			el[detachedType] = el[type];
+			el[type] = null;	
+		}
+		
+		// trigger it
+		jQ(el).trigger(event);
+		
+		// attach the method
+		if (el[detachedType]) {
+			el[type] = el[detachedType];
+			el[detachedType] = null;
+		}
+		
+		if (defaultFunction && !event.isDefaultPrevented()) {
+			defaultFunction(event);
+		}	
+	};
+
+	/**
+	 * Animate a HTML element or SVG element wrapper
+	 * @param {Object} el
+	 * @param {Object} params
+	 * @param {Object} options jQuery-like animation options: duration, easing, callback
+	 */
+	animate = function (el, params, options) {
+		var $el = jQ(el);
+		if (params.d) {
+			el.toD = params.d; // keep the array form for paths, used in jQ.fx.step.d
+			params.d = 1; // because in jQuery, animating to an array has a different meaning
+		}
+		
+		$el.stop();
+		$el.animate(params, options);
+		
+	};
+	/**
+	 * Stop running animation
+	 */
+	stop = function (el) {
+		jQ(el).stop();
+	};
+	
+	
+	// extend jQuery
+	jQ.extend( jQ.easing, {
+		easeOutQuad: function (x, t, b, c, d) {
+			return -c *(t/=d)*(t-2) + b;
+		}
+	});
+					
+	// extend the animate function to allow SVG animations
+	var oldStepDefault = jQuery.fx.step._default, 
+		oldCur = jQuery.fx.prototype.cur;
+	
+	// do the step
+	jQ.fx.step._default = function(fx){
+		var elem = fx.elem;
+		if (elem.attr) { // is SVG element wrapper
+			elem.attr(fx.prop, fx.now);
+		} else {
+			oldStepDefault.apply(this, arguments);
+		}
+	};
+	// animate paths
+	jQ.fx.step.d = function(fx) {
+		var elem = fx.elem;
+			
+		
+		// Normally start and end should be set in state == 0, but sometimes,
+		// for reasons unknown, this doesn't happen. Perhaps state == 0 is skipped
+		// in these cases
+		if (!fx.started) {
+			var ends = pathAnim.init(elem, elem.d, elem.toD);
+			fx.start = ends[0];
+			fx.end = ends[1];
+			fx.started = true;
+		}
+		
+		
+		// interpolate each value of the path
+		elem.attr('d', pathAnim.step(fx.start, fx.end, fx.pos, elem.toD));
+	
+	};
+	// get the current value
+	jQ.fx.prototype.cur = function() {
+		var elem = this.elem,
+			r;
+		if (elem.attr) { // is SVG element wrapper
+			r = elem.attr(this.prop);
+		} else {
+			r = oldCur.apply(this, arguments);
+		}
+		return r;
+	};
+}
+
+
+/**
+ * Add a global listener for mousemove events
+ */
+/*addEvent(doc, 'mousemove', function(e) {
+	if (globalMouseMove) {
+		globalMouseMove(e);
+	}
+});*/
+
+/**
+ * Path interpolation algorithm used across adapters
+ */
+pathAnim = {
+	/**
+	 * Prepare start and end values so that the path can be animated one to one
+	 */
+	init: function(elem, fromD, toD) {
+		fromD = fromD || '';
+		var shift = elem.shift,
+			bezier = fromD.indexOf('C') > -1,
+			numParams = bezier ? 7 : 3,
+			endLength,
+			slice,
+			i,
+			start = fromD.split(' '),
+			end = [].concat(toD), // copy
+			startBaseLine,
+			endBaseLine,
+			sixify = function(arr) { // in splines make move points have six parameters like bezier curves
+				i = arr.length;
+				while (i--) {
+					if (arr[i] == M) {
+						arr.splice(i + 1, 0, arr[i+1], arr[i+2], arr[i+1], arr[i+2]);
+					}
+				}
+			};
+		
+		if (bezier) {
+			sixify(start);
+			sixify(end);
+		}
+		
+		// pull out the base lines before padding
+		if (elem.isArea) { 
+			startBaseLine = start.splice(start.length - 6, 6);
+			endBaseLine = end.splice(end.length - 6, 6);
+		}
+		
+		// if shifting points, prepend a dummy point to the end path
+		if (shift) {
+
+			end = [].concat(end).splice(0, numParams).concat(end);
+			elem.shift = false; // reset for following animations
+		}
+		
+		// copy and append last point until the length matches the end length
+		if (start.length) {
+			endLength = end.length;
+			while (start.length < endLength) {		
+				
+				//bezier && sixify(start); 
+				slice = [].concat(start).splice(start.length - numParams, numParams);
+				if (bezier) { // disable first control point
+					slice[numParams - 6] = slice[numParams - 2];
+					slice[numParams - 5] = slice[numParams - 1];
+				}
+				start = start.concat(slice);
+			}
+		}
+		
+		if (startBaseLine) { // append the base lines for areas
+			start = start.concat(startBaseLine);
+			end = end.concat(endBaseLine);
+		}
+		return [start, end];
+	},
+	
+	/**
+	 * Interpolate each value of the path and return the array
+	 */
+	step: function(start, end, pos, complete) {
+		var ret = [],
+			i = start.length,
+			startVal;
+			
+		if (pos == 1) { // land on the final path without adjustment points appended in the ends
+			ret = complete;
+			
+		} else if (i == end.length && pos < 1) {
+			while (i--) {
+				startVal = parseFloat(start[i]);
+				ret[i] = 
+					isNaN(startVal) ? // a letter instruction like M or L
+						start[i] :
+						pos * (parseFloat(end[i] - startVal)) + startVal;
+				
+			}
+		} else { // if animation is finished or length not matching, land on right value
+			ret = end;
+		}
+		return ret;
+	}
+};
+
+/**
+ * Set the time methods globally based on the useUTC option. Time method can be either 
+ * local time or UTC (default).
+ */
+function setTimeMethods() {
+	var useUTC = defaultOptions.global.useUTC;
+	
+	makeTime = useUTC ? Date.UTC : function(year, month, date, hours, minutes, seconds) {
+		return new Date(
+			year, 
+			month, 
+			pick(date, 1), 
+			pick(hours, 0), 
+			pick(minutes, 0), 
+			pick(seconds, 0)
+		).getTime();
+	};
+	getMinutes = useUTC ? 'getUTCMinutes' : 'getMinutes';
+	getHours = useUTC ? 'getUTCHours' : 'getHours';
+	getDay = useUTC ? 'getUTCDay' : 'getDay';
+	getDate = useUTC ? 'getUTCDate' : 'getDate';
+	getMonth = useUTC ? 'getUTCMonth' : 'getMonth';
+	getFullYear = useUTC ? 'getUTCFullYear' : 'getFullYear';
+	setMinutes = useUTC ? 'setUTCMinutes' : 'setMinutes';
+	setHours = useUTC ? 'setUTCHours' : 'setHours';
+	setDate = useUTC ? 'setUTCDate' : 'setDate';
+	setMonth = useUTC ? 'setUTCMonth' : 'setMonth';
+	setFullYear = useUTC ? 'setUTCFullYear' : 'setFullYear';
+		
+}
+
+/**
+ * Merge the default options with custom options and return the new options structure
+ * @param {Object} options The new custom options
+ */
+function setOptions(options) {
+	defaultOptions = merge(defaultOptions, options);
+	
+	// apply UTC
+	setTimeMethods();
+	
+	return defaultOptions;
+}
+
+/**
+ * Get the updated default options. Merely exposing defaultOptions for outside modules
+ * isn't enough because the setOptions method creates a new object.
+ */
+function getOptions() {
+	return defaultOptions;
+}
+
+/**
+ * Discard an element by moving it to the bin and delete
+ * @param {Object} The HTML node to discard
+ */
+function discardElement(element) {
+	// create a garbage bin element, not part of the DOM
+	if (!garbageBin) {
+		garbageBin = createElement(DIV);
+	}
+	
+	// move the node and empty bin
+	if (element) {
+		garbageBin.appendChild(element);
+	}
+	garbageBin.innerHTML = '';
+}
+
+/* ****************************************************************************
+ * Handle the options                                                         *
+ *****************************************************************************/
+var 
+
+defaultLabelOptions = {
+	enabled: true,
+	// rotation: 0,
+	align: 'center',
+	x: 0,
+	y: 15,
+	/*formatter: function() {
+		return this.value;
+	},*/
+	style: {
+		color: '#666',
+		fontSize: '11px',
+		lineHeight: '14px'
+	}
+};
+
+defaultOptions = {
+	colors: ['#4572A7', '#AA4643', '#89A54E', '#80699B', '#3D96AE', 
+		'#DB843D', '#92A8CD', '#A47D7C', '#B5CA92'],
+	symbols: ['circle', 'diamond', 'square', 'triangle', 'triangle-down'],
+	lang: {
+		loading: 'Loading...',
+		months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 
+				'August', 'September', 'October', 'November', 'December'],
+		weekdays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
+		decimalPoint: '.',
+		resetZoom: 'Reset zoom',
+		resetZoomTitle: 'Reset zoom level 1:1',
+		thousandsSep: ','
+	},
+	global: {
+		useUTC: true
+	},
+	chart: {
+		//animation: true,
+		//alignTicks: false,
+		//reflow: true,
+		//className: null,
+		//events: { load, selection },
+		//margin: [null],
+		//marginTop: null,
+		//marginRight: null,
+		//marginBottom: null,
+		//marginLeft: null,
+		borderColor: '#4572A7',
+		//borderWidth: 0,
+		borderRadius: 5,		
+		defaultSeriesType: 'line',
+		ignoreHiddenSeries: true,
+		//inverted: false,
+		//shadow: false,
+		spacingTop: 10,
+		spacingRight: 10,
+		spacingBottom: 15,
+		spacingLeft: 10,
+		style: {
+			fontFamily: '"Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif', // default font
+			fontSize: '12px'
+		},
+		backgroundColor: '#FFFFFF',
+		//plotBackgroundColor: null,
+		plotBorderColor: '#C0C0C0'
+		//plotBorderWidth: 0,
+		//plotShadow: false,
+		//zoomType: ''
+	},
+	title: {
+		text: 'Chart title',
+		align: 'center',
+		// floating: false,
+		// margin: 15,
+		// x: 0,
+		// verticalAlign: 'top',
+		y: 15, // docs
+		style: {
+			color: '#3E576F',
+			fontSize: '16px'
+		}
+
+	},
+	subtitle: {
+		text: '',
+		align: 'center',
+		// floating: false
+		// x: 0,
+		// verticalAlign: 'top',
+		y: 30, // docs
+		style: {
+			color: '#6D869F'
+		}
+	},
+	
+	plotOptions: {
+		line: { // base series options
+			allowPointSelect: false,
+			showCheckbox: false,
+			animation: {
+				duration: 1000
+			},
+			//cursor: 'default',
+			//dashStyle: null,
+			//enableMouseTracking: true,
+			events: {},
+			lineWidth: 2,
+			shadow: true,
+			// stacking: null,
+			marker: { 
+				enabled: true,
+				//symbol: null, 
+				lineWidth: 0,
+				radius: 4,
+				lineColor: '#FFFFFF',
+				//fillColor: null, 
+				states: { // states for a single point
+					hover: {
+						//radius: base + 2
+					},
+					select: {
+						fillColor: '#FFFFFF',
+						lineColor: '#000000',
+						lineWidth: 2
+					}					
+				}
+			},
+			point: {
+				events: {}
+			},
+			dataLabels: merge(defaultLabelOptions, {
+				enabled: false,
+				y: -6,
+				formatter: function() {
+					return this.y;
+				}
+			}),
+			
+			//pointStart: 0,
+			//pointInterval: 1,
+			showInLegend: true,
+			states: { // states for the entire series
+				hover: {
+					//enabled: false,
+					//lineWidth: base + 1,
+					marker: {
+						// lineWidth: base + 1,
+						// radius: base + 1
+					}
+				},
+				select: {
+					marker: {}
+				}
+			},
+			stickyTracking: true
+			//zIndex: null
+		}
+	},
+	labels: {
+		//items: [],
+		style: {
+			//font: defaultFont,
+			position: ABSOLUTE,
+			color: '#3E576F'
+		}
+	},
+	legend: {
+		enabled: true,
+		align: 'center',
+		//floating: false,
+		layout: 'horizontal',
+		labelFormatter: function() {
+			return this.name;
+		},
+		// lineHeight: 16, // docs: deprecated
+		borderWidth: 1,
+		borderColor: '#909090',
+		borderRadius: 5,
+		// margin: 10,
+		// reversed: false,
+		shadow: false,
+		// backgroundColor: null,
+		style: {
+			padding: '5px'
+		},
+		itemStyle: {
+			cursor: 'pointer',
+			color: '#3E576F'
+		},
+		itemHoverStyle: {
+			cursor: 'pointer',
+			color: '#000000'
+		},
+		itemHiddenStyle: {
+			color: '#C0C0C0'
+		},
+		itemCheckboxStyle: {
+			position: ABSOLUTE,
+			width: '13px', // for IE precision
+			height: '13px'
+		},
+		// itemWidth: undefined,
+		symbolWidth: 16,
+		symbolPadding: 5,
+		verticalAlign: 'bottom',
+		// width: undefined,
+		x: 0, // docs
+		y: 0 // docs
+	},
+	
+	loading: {
+		hideDuration: 100,
+		labelStyle: {
+			fontWeight: 'bold',
+			position: RELATIVE,
+			top: '1em'
+		},
+		showDuration: 100,
+		style: {
+			position: ABSOLUTE,
+			backgroundColor: 'white',
+			opacity: 0.5,
+			textAlign: 'center'
+		}
+	},
+	
+	tooltip: {
+		enabled: true,
+		//crosshairs: null,
+		backgroundColor: 'rgba(255, 255, 255, .85)',
+		borderWidth: 2,
+		borderRadius: 5,
+		//formatter: defaultFormatter,
+		shadow: true,
+		//shared: false,
+		snap: hasTouch ? 25 : 10,
+		style: {
+			color: '#333333',
+			fontSize: '12px',
+			padding: '5px',
+			whiteSpace: 'nowrap'
+		}
+	},
+	
+	toolbar: {
+		itemStyle: {
+			color: '#4572A7',
+			cursor: 'pointer'
+		}
+	},
+	
+	credits: {
+		enabled: true,
+		text: 'Highcharts.com',
+		href: 'http://www.highcharts.com',
+		position: {
+			align: 'right',
+			x: -10,
+			verticalAlign: 'bottom',
+			y: -5
+		},
+		style: {
+			cursor: 'pointer',
+			color: '#909090',
+			fontSize: '10px'
+		}
+	}
+};
+
+// Axis defaults
+var defaultXAxisOptions =  {
+	// allowDecimals: null,
+	// alternateGridColor: null,
+	// categories: [],
+	dateTimeLabelFormats: {
+		second: '%H:%M:%S',
+		minute: '%H:%M',
+		hour: '%H:%M',
+		day: '%e. %b',
+		week: '%e. %b',
+		month: '%b \'%y',
+		year: '%Y'
+	},
+	endOnTick: false,
+	gridLineColor: '#C0C0C0',
+	// gridLineDashStyle: 'solid', // docs
+	// gridLineWidth: 0,
+	// reversed: false,
+	
+	labels: defaultLabelOptions,
+		// { step: null },
+	lineColor: '#C0D0E0',
+	lineWidth: 1,
+	//linkedTo: null,
+	max: null,
+	min: null,
+	minPadding: 0.01,
+	maxPadding: 0.01,
+	//maxZoom: null,
+	minorGridLineColor: '#E0E0E0',
+	// minorGridLineDashStyle: null,
+	minorGridLineWidth: 1,
+	minorTickColor: '#A0A0A0',
+	//minorTickInterval: null,
+	minorTickLength: 2,
+	minorTickPosition: 'outside', // inside or outside
+	//minorTickWidth: 0,
+	//opposite: false,
+	//offset: 0,
+	//plotBands: [{
+	//	events: {},
+	//	zIndex: 1,
+	//	labels: { align, x, verticalAlign, y, style, rotation, textAlign }
+	//}],
+	//plotLines: [{
+	//	events: {}
+	//  dashStyle: {}
+	//	zIndex:
+	//	labels: { align, x, verticalAlign, y, style, rotation, textAlign }
+	//}],
+	//reversed: false,
+	// showFirstLabel: true,
+	// showLastLabel: false,
+	startOfWeek: 1, 
+	startOnTick: false,
+	tickColor: '#C0D0E0',
+	//tickInterval: null,
+	tickLength: 5,
+	tickmarkPlacement: 'between', // on or between
+	tickPixelInterval: 100,
+	tickPosition: 'outside',
+	tickWidth: 1,
+	title: {
+		//text: null,
+		align: 'middle', // low, middle or high
+		//margin: 0 for horizontal, 10 for vertical axes,
+		//rotation: 0,
+		//side: 'outside',
+		style: {
+			color: '#6D869F',
+			//font: defaultFont.replace('normal', 'bold')
+			fontWeight: 'bold'
+		}
+		//x: 0,
+		//y: 0
+	},
+	type: 'linear' // linear or datetime
+},
+
+defaultYAxisOptions = merge(defaultXAxisOptions, {
+	endOnTick: true,
+	gridLineWidth: 1,
+	tickPixelInterval: 72,
+	showLastLabel: true,
+	labels: {
+		align: 'right',
+		x: -8,
+		y: 3
+	},
+	lineWidth: 0,
+	maxPadding: 0.05,
+	minPadding: 0.05,
+	startOnTick: true,
+	tickWidth: 0,
+	title: {
+		rotation: 270,
+		text: 'Y-values'
+	}
+}),
+
+defaultLeftAxisOptions = {
+	labels: {
+		align: 'right',
+		x: -8,
+		y: null // docs
+	},
+	title: {
+		rotation: 270
+	}
+},
+defaultRightAxisOptions = {
+	labels: {
+		align: 'left',
+		x: 8,
+		y: null // docs
+	},
+	title: {
+		rotation: 90
+	}
+},
+defaultBottomAxisOptions = { // horizontal axis
+	labels: {
+		align: 'center',
+		x: 0,
+		y: 14
+		// staggerLines: null
+	},
+	title: {
+		rotation: 0
+	}
+},
+defaultTopAxisOptions = merge(defaultBottomAxisOptions, {
+	labels: {
+		y: -5
+		// staggerLines: null
+	}
+});
+
+
+ 
+
+// Series defaults
+var defaultPlotOptions = defaultOptions.plotOptions, 
+	defaultSeriesOptions = defaultPlotOptions.line; 
+//defaultPlotOptions.line = merge(defaultSeriesOptions);
+defaultPlotOptions.spline = merge(defaultSeriesOptions);
+defaultPlotOptions.scatter = merge(defaultSeriesOptions, {
+	lineWidth: 0,
+	states: {
+		hover: {
+			lineWidth: 0
+		}
+	}
+});
+defaultPlotOptions.area = merge(defaultSeriesOptions, {
+	// threshold: 0,
+	// lineColor: null, // overrides color, but lets fillColor be unaltered
+	// fillOpacity: 0.75,
+	// fillColor: null
+
+});
+defaultPlotOptions.areaspline = merge(defaultPlotOptions.area);
+defaultPlotOptions.column = merge(defaultSeriesOptions, {
+	borderColor: '#FFFFFF',
+	borderWidth: 1,
+	borderRadius: 0,
+	//colorByPoint: undefined,
+	groupPadding: 0.2,
+	marker: null, // point options are specified in the base options
+	pointPadding: 0.1,
+	//pointWidth: null,
+	minPointLength: 0, 
+	states: {
+		hover: {
+			brightness: 0.1,
+			shadow: false
+		},
+		select: {
+			color: '#C0C0C0',
+			borderColor: '#000000',
+			shadow: false
+		}
+	}
+});
+defaultPlotOptions.bar = merge(defaultPlotOptions.column, {
+	dataLabels: {
+		align: 'left',
+		x: 5,
+		y: 0
+	}
+});
+defaultPlotOptions.pie = merge(defaultSeriesOptions, {
+	//dragType: '', // n/a
+	borderColor: '#FFFFFF',
+	borderWidth: 1,
+	center: ['50%', '50%'],
+	colorByPoint: true, // always true for pies
+	dataLabels: {
+		// align: null,
+		// connectorWidth: 1,
+		// connectorColor: '#606060',
+		// connectorPadding: 5,
+		distance: 30,
+		enabled: true,
+		formatter: function() {
+			return this.point.name;
+		},
+		y: 5
+	},
+	//innerSize: 0,
+	legendType: 'point',
+	marker: null, // point options are specified in the base options
+	size: '75%',
+	showInLegend: false,
+	slicedOffset: 10,
+	states: {
+		hover: {
+			brightness: 0.1,
+			shadow: false
+		}
+	}
+	
+});
+
+// set the default time methods
+setTimeMethods();
+
+
+/**
+ * Extend a prototyped class by new members
+ * @param {Object} parent
+ * @param {Object} members
+ */
+function extendClass(parent, members) {
+	var object = function(){};
+	object.prototype = new parent();
+	extend(object.prototype, members);
+	return object;
+}
+
+
+/**
+ * Handle color operations. The object methods are chainable.
+ * @param {String} input The input color in either rbga or hex format
+ */
+var Color = function(input) {
+	// declare variables
+	var rgba = [], result;
+	
+	/**
+	 * Parse the input color to rgba array
+	 * @param {String} input
+	 */
+	function init(input) {
+		
+		// rgba
+		if((result = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/.exec(input))) {
+			rgba = [pInt(result[1]), pInt(result[2]), pInt(result[3]), parseFloat(result[4], 10)];
+		}
+
+		// hex
+		else if((result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(input))) {
+			rgba = [pInt(result[1],16), pInt(result[2],16), pInt(result[3],16), 1];
+		}
+	
+	}
+	/**
+	 * Return the color a specified format
+	 * @param {String} format
+	 */
+	function get(format) {
+		var ret;
+		
+		// it's NaN if gradient colors on a column chart
+		if (rgba && !isNaN(rgba[0])) {
+			if (format == 'rgb') {
+				ret = 'rgb('+ rgba[0] +','+ rgba[1] +','+ rgba[2] +')';
+			} else if (format == 'a') {
+				ret = rgba[3];
+			} else {
+				ret = 'rgba('+ rgba.join(',') +')';
+			}
+		} else {
+			ret = input;
+		}
+		return ret;
+	}
+	
+	/**
+	 * Brighten the color
+	 * @param {Number} alpha
+	 */
+	function brighten(alpha) {
+		if (isNumber(alpha) && alpha !== 0) {
+			var i;
+			for (i = 0; i < 3; i++) {
+				rgba[i] += pInt(alpha * 255);
+				
+				if (rgba[i] < 0) {
+					rgba[i] = 0;
+				}
+				if (rgba[i] > 255) {
+					rgba[i] = 255;
+				}
+			}
+		}
+		return this;
+	}
+	/**
+	 * Set the color's opacity to a given alpha value
+	 * @param {Number} alpha
+	 */
+	function setOpacity(alpha) {
+		rgba[3] = alpha;
+		return this;
+	}	
+	
+	// initialize: parse the input
+	init(input);
+	
+	// public methods
+	return {
+		get: get,
+		brighten: brighten,
+		setOpacity: setOpacity
+	};
+};
+
+
+
+/**
+ * Format a number and return a string based on input settings
+ * @param {Number} number The input number to format
+ * @param {Number} decimals The amount of decimals
+ * @param {String} decPoint The decimal point, defaults to the one given in the lang options
+ * @param {String} thousandsSep The thousands separator, defaults to the one given in the lang options
+ */
+function numberFormat (number, decimals, decPoint, thousandsSep) {
+	var lang = defaultOptions.lang,
+		// http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_number_format/
+		n = number, c = isNaN(decimals = mathAbs(decimals)) ? 2 : decimals,
+		d = decPoint === undefined ? lang.decimalPoint : decPoint,
+		t = thousandsSep === undefined ? lang.thousandsSep : thousandsSep, s = n < 0 ? "-" : "",
+		i = pInt(n = mathAbs(+n || 0).toFixed(c)) + "", j = (j = i.length) > 3 ? j % 3 : 0;
+    
+	return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) +
+		(c ? d + mathAbs(n - i).toFixed(c).slice(2) : "");
+}
+
+/**
+ * Based on http://www.php.net/manual/en/function.strftime.php 
+ * @param {String} format
+ * @param {Number} timestamp
+ * @param {Boolean} capitalize
+ */
+dateFormat = function (format, timestamp, capitalize) {
+	function pad (number) {
+		return number.toString().replace(/^([0-9])$/, '0$1');
+	}
+	
+	if (!defined(timestamp) || isNaN(timestamp)) {
+		return 'Invalid date';
+	}
+	format = pick(format, '%Y-%m-%d %H:%M:%S');
+	
+	var date = new Date(timestamp * timeFactor),
+	
+		// get the basic time values
+		hours = date[getHours](),
+		day = date[getDay](),
+		dayOfMonth = date[getDate](),
+		month = date[getMonth](),
+		fullYear = date[getFullYear](),
+		lang = defaultOptions.lang,
+		langWeekdays = lang.weekdays,
+		langMonths = lang.months,
+		
+		// list all format keys
+		replacements = {
+
+			// Day
+			'a': langWeekdays[day].substr(0, 3), // Short weekday, like 'Mon'
+			'A': langWeekdays[day], // Long weekday, like 'Monday'
+			'd': pad(dayOfMonth), // Two digit day of the month, 01 to 31 
+			'e': dayOfMonth, // Day of the month, 1 through 31 
+			
+			// Week (none implemented)
+			
+			// Month
+			'b': langMonths[month].substr(0, 3), // Short month, like 'Jan'
+			'B': langMonths[month], // Long month, like 'January'
+			'm': pad(month + 1), // Two digit month number, 01 through 12
+			
+			// Year
+			'y': fullYear.toString().substr(2, 2), // Two digits year, like 09 for 2009
+			'Y': fullYear, // Four digits year, like 2009
+			
+			// Time
+			'H': pad(hours), // Two digits hours in 24h format, 00 through 23
+			'I': pad((hours % 12) || 12), // Two digits hours in 12h format, 00 through 11
+			'l': (hours % 12) || 12, // Hours in 12h format, 1 through 12
+			'M': pad(date[getMinutes]()), // Two digits minutes, 00 through 59
+			'p': hours < 12 ? 'AM' : 'PM', // Upper case AM or PM
+			'P': hours < 12 ? 'am' : 'pm', // Lower case AM or PM
+			'S': pad(date.getSeconds()) // Two digits seconds, 00 through  59
+			
+		};
+
+
+	// do the replaces
+	for (var key in replacements) {
+		format = format.replace('%'+ key, replacements[key]);
+	}
+		
+	// Optionally capitalize the string and return
+	return capitalize ? format.substr(0, 1).toUpperCase() + format.substr(1) : format;
+};
+
+
+
+/**
+ * Loop up the node tree and add offsetWidth and offsetHeight to get the
+ * total page offset for a given element. Used by Opera and iOS on hover and
+ * all browsers on point click.
+ * 
+ * @param {Object} el
+ * 
+ */
+function getPosition (el) {
+	var p = { left: el.offsetLeft, top: el.offsetTop };
+	while ((el = el.offsetParent))	{
+		p.left += el.offsetLeft;
+		p.top += el.offsetTop;
+		if (el != doc.body && el != doc.documentElement) {
+			p.left -= el.scrollLeft;
+			p.top -= el.scrollTop;
+		}
+	}
+	return p;
+}
+
+
+/**
+ * A wrapper object for SVG elements 
+ */
+function SVGElement () {}
+
+SVGElement.prototype = {
+	/**
+	 * Initialize the SVG renderer
+	 * @param {Object} renderer
+	 * @param {String} nodeName
+	 */
+	init: function(renderer, nodeName) {
+		this.element = doc.createElementNS(SVG_NS, nodeName);
+		this.renderer = renderer;
+	},
+	/**
+	 * Animate a given attribute
+	 * @param {Object} params
+	 * @param {Number} options The same options as in jQuery animation
+	 * @param {Function} complete Function to perform at the end of animation
+	 */
+	animate: function(params, options, complete) {
+		var animOptions = pick(options, globalAnimation, true);
+		if (animOptions) {
+			animOptions = merge(animOptions);
+			if (complete) { // allows using a callback with the global animation without overwriting it
+				animOptions.complete = complete;
+			}
+			animate(this, params, animOptions);
+		} else {
+			this.attr(params);
+			if (complete) {
+				complete();
+			}
+		}
+	},
+	/**
+	 * Set or get a given attribute
+	 * @param {Object|String} hash
+	 * @param {Mixed|Undefined} val
+	 */
+	attr: function(hash, val) {
+		var key, 
+			value, 
+			i, 
+			child,
+			element = this.element,
+			nodeName = element.nodeName,
+			renderer = this.renderer,
+			skipAttr,
+			shadows = this.shadows,
+			hasSetSymbolSize,
+			ret = this;
+			
+		// single key-value pair
+		if (isString(hash) && defined(val)) {
+			key = hash;
+			hash = {};
+			hash[key] = val;
+		}
+		
+		// used as a getter: first argument is a string, second is undefined
+		if (isString(hash)) {
+			key = hash;
+			if (nodeName == 'circle') {
+				key = { x: 'cx', y: 'cy' }[key] || key;
+			} else if (key == 'strokeWidth') {
+				key = 'stroke-width';
+			}
+			ret = attr(element, key) || this[key] || 0;
+			
+			if (key != 'd' && key != 'visibility') { // 'd' is string in animation step
+				ret = parseFloat(ret);
+			}
+			
+		// setter
+		} else {
+		
+			for (key in hash) {
+				skipAttr = false; // reset
+				value = hash[key];
+				
+				// paths
+				if (key == 'd') {
+					if (value && value.join) { // join path
+						value = value.join(' ');
+					}					
+					if (/(NaN| {2}|^$)/.test(value)) {
+						value = 'M 0 0';
+					}
+					this.d = value; // shortcut for animations
+					
+				// update child tspans x values
+				} else if (key == 'x' && nodeName == 'text') { 
+					for (i = 0; i < element.childNodes.length; i++ ) {
+						child = element.childNodes[i];
+						// if the x values are equal, the tspan represents a linebreak
+						if (attr(child, 'x') == attr(element, 'x')) {
+							//child.setAttribute('x', value);
+							attr(child, 'x', value);
+						}
+					}
+					
+					if (this.rotation) {
+						attr(element, 'transform', 'rotate('+ this.rotation +' '+ value +' '+
+							pInt(hash.y || attr(element, 'y')) +')');
+					}
+					
+				// apply gradients
+				} else if (key == 'fill') {
+					value = renderer.color(value, element, key);
+				
+				// circle x and y
+				} else if (nodeName == 'circle' && (key == 'x' || key == 'y')) {
+					key = { x: 'cx', y: 'cy' }[key] || key;
+					
+				// translation and text rotation
+				} else if (key == 'translateX' || key == 'translateY' || key == 'rotation' || key == 'verticalAlign') {
+					this[key] = value;
+					this.updateTransform();
+					skipAttr = true;
+	
+				// apply opacity as subnode (required by legacy WebKit and Batik)
+				} else if (key == 'stroke') {
+					value = renderer.color(value, element, key);
+					
+				// emulate VML's dashstyle implementation
+				} else if (key == 'dashstyle') {
+					key = 'stroke-dasharray';
+					if (value) {
+						value = value.toLowerCase()
+							.replace('shortdashdotdot', '3,1,1,1,1,1,')
+							.replace('shortdashdot', '3,1,1,1')
+							.replace('shortdot', '1,1,')
+							.replace('shortdash', '3,1,')
+							.replace('longdash', '8,3,')
+							.replace(/dot/g, '1,3,')
+							.replace('dash', '4,3,')
+							.replace(/,$/, '')
+							.split(','); // ending comma
+						
+						i = value.length;
+						while (i--) {
+							value[i] = pInt(value[i]) * hash['stroke-width'];
+						}
+						value = value.join(',');
+					}	
+					
+				// special
+				} else if (key == 'isTracker') {
+					this[key] = value;
+				
+				// IE9/MooTools combo: MooTools returns objects instead of numbers and IE9 Beta 2
+				// is unable to cast them. Test again with final IE9.
+				} else if (key == 'width') {
+					value = pInt(value);
+				
+				// Text alignment
+				} else if (key == 'align') {
+					key = 'text-anchor';
+					value = { left: 'start', center: 'middle', right: 'end' }[value];
+				}
+				
+				
+				
+				// jQuery animate changes case
+				if (key == 'strokeWidth') {
+					key = 'stroke-width';
+				}
+				
+				// Chrome/Win < 6 bug (http://code.google.com/p/chromium/issues/detail?id=15461)				
+				if (isWebKit && key == 'stroke-width' && value === 0) {
+					value = 0.000001;
+				}
+				
+				// symbols
+				if (this.symbolName && /^(x|y|r|start|end|innerR)/.test(key)) {
+					
+					
+					if (!hasSetSymbolSize) {
+						this.symbolAttr(hash);
+						hasSetSymbolSize = true;
+					}
+					skipAttr = true;
+				}
+				
+				// let the shadow follow the main element
+				if (shadows && /^(width|height|visibility|x|y|d)$/.test(key)) {
+					i = shadows.length;
+					while (i--) {
+						attr(shadows[i], key, value);
+					}					
+				}
+				
+				/* trows errors in Chrome
+				if ((key == 'width' || key == 'height') && nodeName == 'rect' && value < 0) {
+					console.log(element);
+				}
+				*/
+				
+					
+				
+				if (key == 'text') {
+					// only one node allowed
+					this.textStr = value;
+					renderer.buildText(this);
+				} else if (!skipAttr) {
+					//element.setAttribute(key, value);
+					attr(element, key, value);
+				}
+				
+			}
+			
+		}
+		return ret;
+	},
+	
+	/**
+	 * If one of the symbol size affecting parameters are changed,
+	 * check all the others only once for each call to an element's
+	 * .attr() method
+	 * @param {Object} hash
+	 */
+	symbolAttr: function(hash) {
+		var wrapper = this;
+		
+		wrapper.x = pick(hash.x, wrapper.x);
+		wrapper.y = pick(hash.y, wrapper.y); // mootools animation bug needs parseFloat
+		wrapper.r = pick(hash.r, wrapper.r);
+		wrapper.start = pick(hash.start, wrapper.start);
+		wrapper.end = pick(hash.end, wrapper.end);
+		wrapper.width = pick(hash.width, wrapper.width);
+		wrapper.height = pick(hash.height, wrapper.height);
+		wrapper.innerR = pick(hash.innerR, wrapper.innerR);
+		
+		wrapper.attr({ 
+			d: wrapper.renderer.symbols[wrapper.symbolName](wrapper.x, wrapper.y, wrapper.r, {
+				start: wrapper.start, 
+				end: wrapper.end,
+				width: wrapper.width, 
+				height: wrapper.height,
+				innerR: wrapper.innerR
+			})
+		});
+	},
+	
+	/**
+	 * Apply a clipping path to this object
+	 * @param {String} id
+	 */
+	clip: function(clipRect) {
+		return this.attr('clip-path', 'url('+ this.renderer.url +'#'+ clipRect.id +')');
+	},
+	
+	/**
+	 * Set styles for the element
+	 * @param {Object} styles
+	 */
+	css: function(styles) {
+		var elemWrapper = this,
+			elem = elemWrapper.element;
+		
+		// convert legacy
+		if (styles && styles.color) {
+			styles.fill = styles.color;
+		}
+		
+		// save the styles in an object
+		styles = extend(
+			elemWrapper.styles,
+			styles
+		);
+		
+		// serialize and set style attribute
+		if (isIE && !hasSVG) { // legacy IE doesn't support setting style attribute 
+			css(elemWrapper.element, styles);	
+		} else {
+			elemWrapper.attr({
+				style: serializeCSS(styles)
+			});
+		}
+		
+		
+		// store object
+		elemWrapper.styles = styles;
+		
+		// re-build text
+		if (styles.width && elem.nodeName == 'text' && elemWrapper.added) {
+			elemWrapper.renderer.buildText(elemWrapper);
+		}
+		
+		return elemWrapper;
+	},
+	
+	/**
+	 * Add an event listener
+	 * @param {String} eventType
+	 * @param {Function} handler
+	 */
+	on: function(eventType, handler) {
+		var fn = handler;
+		// touch
+		if (hasTouch && eventType == 'click') {
+			eventType = 'touchstart';
+			fn = function(e) {
+				e.preventDefault();
+				handler();
+			}
+		}
+		// simplest possible event model for internal use
+		this.element['on'+ eventType] = fn;
+		return this;
+	},
+	
+	
+	/**
+	 * Move an object and its children by x and y values
+	 * @param {Number} x
+	 * @param {Number} y
+	 */
+	translate: function(x, y) {
+		return this.attr({
+			translateX: x,
+			translateY: y
+		});
+	},
+	
+	/**
+	 * Invert a group, rotate and flip
+	 */
+	invert: function() {
+		var wrapper = this;
+		wrapper.inverted = true;
+		wrapper.updateTransform();
+		return wrapper;
+	},
+	
+	/**
+	 * Private method to update the transform attribute based on internal 
+	 * properties
+	 */
+	updateTransform: function() {
+		var wrapper = this,
+			translateX = wrapper.translateX || 0,
+			translateY = wrapper.translateY || 0,
+			inverted = wrapper.inverted,
+			rotation = wrapper.rotation,
+			transform = [];
+			
+		// flipping affects translate as adjustment for flipping around the group's axis
+		if (inverted) {
+			translateX += wrapper.attr('width');
+			translateY += wrapper.attr('height');
+		}
+			
+		// apply translate
+		if (translateX || translateY) {
+			transform.push('translate('+ translateX +','+ translateY +')');
+		}
+		
+		// apply rotation
+		if (inverted) {
+			transform.push('rotate(90) scale(-1,1)');
+		} else if (rotation) { // text rotation
+			transform.push('rotate('+ rotation +' '+ wrapper.x +' '+ wrapper.y +')');
+		}
+		
+		if (transform.length) {
+			attr(wrapper.element, 'transform', transform.join(' '));
+		}
+	},
+	/**
+	 * Bring the element to the front
+	 */
+	toFront: function() {
+		var element = this.element;
+		element.parentNode.appendChild(element);
+		return this;
+	},
+	
+	
+	/**
+	 * Break down alignment options like align, verticalAlign, x and y 
+	 * to x and y relative to the chart.
+	 * 
+	 * @param {Object} alignOptions
+	 * @param {Boolean} alignByTranslate
+	 * @param {Object} box The box to align to, needs a width and height
+	 * 
+	 */
+	align: function(alignOptions, alignByTranslate, box) {
+		
+		if (!alignOptions) { // called on resize
+			alignOptions = this.alignOptions;
+			alignByTranslate = this.alignByTranslate;
+		} else { // first call on instanciate
+			this.alignOptions = alignOptions;
+			this.alignByTranslate = alignByTranslate;
+			if (!box) { // boxes other than renderer handle this internally
+				this.renderer.alignedObjects.push(this);
+			}
+		}
+		
+		box = pick(box, this.renderer);
+		
+		var align = alignOptions.align,
+			vAlign = alignOptions.verticalAlign,
+			x = (box.x || 0) + (alignOptions.x || 0), // default: left align
+			y = (box.y || 0) + (alignOptions.y || 0), // default: top align
+			attribs = {};
+			
+			
+		// align
+		if (/^(right|center)$/.test(align)) {
+			x += (box.width - (alignOptions.width || 0) ) /
+					{ right: 1, center: 2 }[align];
+		}
+		attribs[alignByTranslate ? 'translateX' : 'x'] = x;
+		
+		
+		// vertical align
+		if (/^(bottom|middle)$/.test(vAlign)) {
+			y += (box.height - (alignOptions.height || 0)) /
+					({ bottom: 1, middle: 2 }[vAlign] || 1);
+			
+		}
+		attribs[alignByTranslate ? 'translateY' : 'y'] = y;
+		
+		// animate only if already placed
+		this[this.placed ? 'animate' : 'attr'](attribs);
+		this.placed = true;
+		
+		return this;
+	},
+	
+	/**
+	 * Get the bounding box (width, height, x and y) for the element
+	 */
+	getBBox: function() {		
+		var	bBox,
+			width,
+			height,
+			rotation = this.rotation,
+			rad = rotation * deg2rad;
+			
+		try { // fails in Firefox if the container has display: none
+			// use extend because IE9 is not allowed to change width and height in case 
+			// of rotation (below)
+			bBox = extend({}, this.element.getBBox());
+		} catch(e) {
+			bBox = { width: 0, height: 0 };
+		}
+		width = bBox.width;
+		height = bBox.height;
+			
+		// adjust for rotated text
+		if (rotation) {
+			bBox.width = mathAbs(height * mathSin(rad)) + mathAbs(width * mathCos(rad));
+			bBox.height = mathAbs(height * mathCos(rad)) + mathAbs(width * mathSin(rad));
+		}
+		
+		return bBox;
+	},
+	
+	/* *
+	 * Manually compute width and height of rotated text from non-rotated. Shared by SVG and VML
+	 * @param {Object} bBox
+	 * @param {number} rotation
+	 * /
+	rotateBBox: function(bBox, rotation) {
+		var rad = rotation * math.PI * 2 / 360, // radians
+			width = bBox.width,
+			height = bBox.height;
+			
+		
+	},*/
+	
+	/**
+	 * Show the element
+	 */
+	show: function() {
+		return this.attr({ visibility: VISIBLE });
+	},
+	
+	/**
+	 * Hide the element
+	 */
+	hide: function() {
+		return this.attr({ visibility: HIDDEN });
+	},
+	
+	/**
+	 * Add the element
+	 * @param {Object|Undefined} parent Can be an element, an element wrapper or undefined
+	 *    to append the element to the renderer.box.
+	 */ 
+	add: function(parent) {
+	
+		var renderer = this.renderer,
+			parentWrapper = parent || renderer,
+			parentNode = parentWrapper.element || renderer.box,
+			childNodes = parentNode.childNodes,
+			element = this.element,
+			zIndex = attr(element, 'zIndex'),
+			textStr = this.textStr,
+			otherElement,
+			otherZIndex,
+			i;
+			
+		// mark as inverted
+		this.parentInverted = parent && parent.inverted;
+		
+		// mark the container as having z indexed children
+		if (zIndex) {
+			parentWrapper.handleZ = true;
+			zIndex = pInt(zIndex);
+		}
+
+		// insert according to this and other elements' zIndex
+		if (parentWrapper.handleZ) { // this element or any of its siblings has a z index
+			for (i = 0; i < childNodes.length; i++) {
+				otherElement = childNodes[i];
+				otherZIndex = attr(otherElement, 'zIndex');
+				if (otherElement != element && (
+						// insert before the first element with a higher zIndex
+						pInt(otherZIndex) > zIndex || 
+						// if no zIndex given, insert before the first element with a zIndex
+						(!defined(zIndex) && defined(otherZIndex))  
+						
+						)) {
+					parentNode.insertBefore(element, otherElement);
+					return this;
+				}
+			}
+		}
+		
+		// operations before adding
+		if (textStr !== undefined) {
+			renderer.buildText(this);
+			this.added = true;
+		}
+		
+		// default: append at the end
+		parentNode.appendChild(element);
+		return this;
+	},
+
+	/**
+	 * Destroy the element and element wrapper
+	 */
+	destroy: function() {
+		var wrapper = this,
+			element = wrapper.element || {},
+			shadows = wrapper.shadows,
+			parentNode = element.parentNode,
+			key;
+		
+		// remove events
+		element.onclick = element.onmouseout = element.onmouseover = element.onmousemove = null;
+		stop(wrapper); // stop running animations
+		
+		// remove element
+		if (parentNode) {
+			parentNode.removeChild(element);
+		}
+		
+		// destroy shadows
+		if (shadows) {
+			each(shadows, function(shadow) {
+				parentNode = shadow.parentNode;
+				if (parentNode) { // the entire chart HTML can be overwritten
+					parentNode.removeChild(shadow);
+				}				
+			});
+		}
+		
+		// remove from alignObjects
+		erase(wrapper.renderer.alignedObjects, wrapper);
+				
+		for (key in wrapper) {
+			delete wrapper[key];
+		}
+		
+		return null;
+	},
+	
+	/**
+	 * Empty a group element
+	 */
+	empty: function() {
+		var element = this.element,
+			childNodes = element.childNodes,
+			i = childNodes.length;
+			
+		while (i--) {
+			element.removeChild(childNodes[i]);
+		}
+	},
+	
+	/**
+	 * Add a shadow to the element. Must be done after the element is added to the DOM
+	 * @param {Boolean} apply
+	 */
+	shadow: function(apply) {
+		var shadows = [],
+			i,
+			shadow,
+			element = this.element,
+			
+			// compensate for inverted plot area
+			transform = this.parentInverted ? '(-1,-1)' : '(1,1)';
+			
+		
+		if (apply) {
+			for (i = 1; i <= 3; i++) {
+				shadow = element.cloneNode(0);
+				attr(shadow, {
+					'isShadow': 'true',
+					'stroke': 'rgb(0, 0, 0)',
+					'stroke-opacity': 0.05 * i,
+					'stroke-width': 7 - 2 * i,
+					'transform': 'translate'+ transform,
+					'fill': NONE
+				});
+				
+				
+				element.parentNode.insertBefore(shadow, element);
+				
+				shadows.push(shadow);
+			}
+			
+			this.shadows = shadows;
+		}
+		return this;
+	
+	}
+};
+
+
+
+/**
+ * The default SVG renderer
+ */
+var SVGRenderer = function() {
+	this.init.apply(this, arguments);
+};
+SVGRenderer.prototype = {
+	/**
+	 * Initialize the SVGRenderer
+	 * @param {Object} container
+	 * @param {Number} width
+	 * @param {Number} height
+	 */
+	init: function(container, width, height) {
+		var renderer = this,
+			loc = location,
+			boxWrapper;
+					
+		renderer.Element = SVGElement;
+		boxWrapper = renderer.createElement('svg')
+			.attr({
+				xmlns: SVG_NS,
+				version: '1.1'
+			});
+		container.appendChild(boxWrapper.element);
+		
+		// object properties
+		renderer.box = boxWrapper.element;
+		renderer.boxWrapper = boxWrapper;
+		renderer.alignedObjects = [];
+		renderer.url = isIE ? '' : loc.href.replace(/#.*?$/, ''); // page url used for internal references
+		renderer.defs = this.createElement('defs').add();
+		
+		renderer.setSize(width, height, false);
+		
+	},
+	
+	
+	/**
+	 * Create a wrapper for an SVG element
+	 * @param {Object} nodeName
+	 */
+	createElement: function(nodeName) {
+		var wrapper = new this.Element();
+		wrapper.init(this, nodeName);
+		return wrapper;
+	},
+	
+	
+	/** 
+	 * Parse a simple HTML string into SVG tspans
+	 * 
+	 * @param {Object} textNode The parent text SVG node
+	 */
+	buildText: function(wrapper) {
+		var textNode = wrapper.element,
+			lines = pick(wrapper.textStr, '').toString()
+				.replace(/<(b|strong)>/g, '<span style="font-weight:bold">')
+				.replace(/<(i|em)>/g, '<span style="font-style:italic">')
+				.replace(/<a/g, '<span')
+				.replace(/<\/(b|strong|i|em|a)>/g, '</span>')
+				.split(/<br[^>]?>/g),
+			childNodes = textNode.childNodes,
+			styleRegex = /style="([^"]+)"/,
+			hrefRegex = /href="([^"]+)"/,
+			parentX = attr(textNode, 'x'),
+			textStyles = wrapper.styles,
+			width = textStyles && pInt(textStyles.width),
+			textLineHeight = textStyles && textStyles.lineHeight,
+			lastLine,
+			i = childNodes.length;
+			
+		// remove old text
+		while (i--) {
+			textNode.removeChild(childNodes[i]);
+		}
+		
+		if (width) {
+			this.box.appendChild(textNode); // attach it to the DOM to read offset width
+		}
+		
+		each(lines, function(line, lineNo) {
+			var spans, spanNo = 0, lineHeight;
+			
+			line = line.replace(/<span/g, '|||<span').replace(/<\/span>/g, '</span>|||');
+			spans = line.split('|||');
+			
+			each(spans, function (span) {
+				if (span !== '' || spans.length == 1) {
+					var attributes = {},
+						tspan = doc.createElementNS(SVG_NS, 'tspan');
+					if (styleRegex.test(span)) {
+						attr(
+							tspan, 
+							'style', 
+							span.match(styleRegex)[1].replace(/(;| |^)color([ :])/, '$1fill$2')
+						);
+					}
+					if (hrefRegex.test(span)) {
+						attr(tspan, 'onclick', 'location.href=\"'+ span.match(hrefRegex)[1] +'\"');
+						css(tspan, { cursor: 'pointer' });
+					}
+					
+					span = span.replace(/<(.|\n)*?>/g, '') || ' ';
+					tspan.appendChild(doc.createTextNode(span)); // WebKit needs a string
+					
+					//console.log('"'+tspan.textContent+'"');
+					if (!spanNo) { // first span in a line, align it to the left
+						attributes.x = parentX;
+					} else {
+						// Firefox ignores spaces at the front or end of the tspan
+						attributes.dx = 3; // space
+					}
+					
+					// first span on subsequent line, add the line height
+					if (!spanNo) {						
+						if (lineNo) {
+							// Webkit and opera sometimes return 'normal' as the line height. In that
+							// case, webkit uses offsetHeight, while Opera falls back to 18
+							lineHeight = pInt(window.getComputedStyle(lastLine, null).getPropertyValue('line-height'));
+							if (isNaN(lineHeight)) {
+								lineHeight = textLineHeight || lastLine.offsetHeight || 18;
+							}
+							attr(tspan, 'dy', lineHeight);
+						}
+						lastLine = tspan; // record for use in next line						
+					}
+					
+					// add attributes
+					attr(tspan, attributes);
+					
+					// append it
+					textNode.appendChild(tspan);
+					
+					spanNo++;
+					
+					// check width and apply soft breaks
+					if (width) {
+						var words = span.replace(/-/g, '- ').split(' '),
+							tooLong,
+							actualWidth,
+							rest = [];
+						
+						while (words.length || rest.length) {
+							actualWidth = textNode.getBBox().width;
+							tooLong = actualWidth > width;
+							if (!tooLong || words.length == 1) { // new line needed
+								words = rest;
+								rest = [];
+								tspan = doc.createElementNS(SVG_NS, 'tspan');
+								attr(tspan, {
+									x: parentX,
+									dy: textLineHeight || 16
+								});
+								textNode.appendChild(tspan);
+								
+								if (actualWidth > width) { // a single word is pressing it out
+									width = actualWidth;
+								}
+							} else { // append to existing line tspan
+								tspan.removeChild(tspan.firstChild);
+								rest.unshift(words.pop());
+							}
+							
+							tspan.appendChild(doc.createTextNode(words.join(' ').replace(/- /g, '-')));
+						}
+						
+					}
+				}
+			});
+		});
+		
+		
+	},
+	
+	/**
+	 * Make a straight line crisper by not spilling out to neighbour pixels
+	 * @param {Array} points
+	 * @param {Number} width 
+	 */
+	crispLine: function(points, width) {
+		// points format: [M, 0, 0, L, 100, 0]
+		// normalize to a crisp line
+		if (points[1] == points[4]) {
+			points[1] = points[4] = mathRound(points[1]) + (width % 2 / 2);
+		}
+		if (points[2] == points[5]) {
+			points[2] = points[5] = mathRound(points[2]) + (width % 2 / 2);
+		}
+		return points;
+	},
+	
+	
+	/**
+	 * Draw a path
+	 * @param {Array} path An SVG path in array form
+	 */
+	path: function (path) {
+		return this.createElement('path').attr({ 
+			d: path, 
+			fill: NONE
+		});
+	},
+	
+	/**
+	 * Draw and return an SVG circle
+	 * @param {Number} x The x position
+	 * @param {Number} y The y position
+	 * @param {Number} r The radius
+	 */
+	circle: function (x, y, r) {
+		var attr = isObject(x) ?
+			x :
+			{
+				x: x,
+				y: y,
+				r: r
+			};
+		
+		return this.createElement('circle').attr(attr);
+	},
+	
+	/**
+	 * Draw and return an arc
+	 * @param {Number} x X position
+	 * @param {Number} y Y position
+	 * @param {Number} r Radius
+	 * @param {Number} innerR Inner radius like used in donut charts
+	 * @param {Number} start Starting angle
+	 * @param {Number} end Ending angle
+	 */
+	arc: function (x, y, r, innerR, start, end) {
+		// arcs are defined as symbols for the ability to set 
+		// attributes in attr and animate
+		
+		if (isObject(x)) {
+			y = x.y;
+			r = x.r;
+			innerR = x.innerR;
+			start = x.start;
+			end = x.end;
+			x = x.x;
+		}
+		
+		return this.symbol('arc', x || 0, y || 0, r || 0, {
+			innerR: innerR || 0,
+			start: start || 0,
+			end: end || 0
+		});
+	},
+	
+	/**
+	 * Draw and return a rectangle
+	 * @param {Number} x Left position
+	 * @param {Number} y Top position
+	 * @param {Number} width
+	 * @param {Number} height
+	 * @param {Number} r Border corner radius
+	 * @param {Number} strokeWidth A stroke width can be supplied to allow crisp drawing
+	 */
+	rect: function (x, y, width, height, r, strokeWidth) {
+		
+		if (arguments.length > 1) {
+			var normalizer = (strokeWidth || 0) % 2 / 2;
+
+			// normalize for crisp edges
+			x = mathRound(x || 0) + normalizer;
+			y = mathRound(y || 0) + normalizer;
+			width = mathRound((width || 0) - 2 * normalizer);
+			height = mathRound((height || 0) - 2 * normalizer);
+		}
+		
+		var attr = isObject(x) ? 
+			x : // the attributes can be passed as the first argument
+			{
+				x: x,
+				y: y,
+				width: mathMax(width, 0),
+				height: mathMax(height, 0)
+			};			
+		
+		return this.createElement('rect').attr(extend(attr, {
+			rx: r || attr.r,
+			ry: r || attr.r,
+			fill: NONE
+		}));
+	},
+	
+	/**
+	 * Resize the box and re-align all aligned elements
+	 * @param {Object} width
+	 * @param {Object} height
+	 * @param {Boolean} animate
+	 * 
+	 */
+	setSize: function(width, height, animate) {
+		var renderer = this,
+			alignedObjects = renderer.alignedObjects,
+			i = alignedObjects.length;
+		
+		renderer.width = width;
+		renderer.height = height;
+		
+		renderer.boxWrapper[pick(animate, true) ? 'animate' : 'attr']({
+			width: width,
+			height: height
+		});		
+		
+		while (i--) {
+			alignedObjects[i].align();
+		}
+	},
+	
+	/**
+	 * Create a group
+	 * @param {String} name The group will be given a class name of 'highcharts-{name}'.
+	 *     This can be used for styling and scripting.
+	 */
+	g: function(name) {
+		return this.createElement('g').attr(
+			defined(name) && { 'class': PREFIX + name }
+		);
+	},
+	
+	/**
+	 * Display an image
+	 * @param {String} src
+	 * @param {Number} x
+	 * @param {Number} y
+	 * @param {Number} width
+	 * @param {Number} height
+	 */
+	image: function(src, x, y, width, height) {
+		var attribs = {
+				preserveAspectRatio: NONE	
+			},
+			elemWrapper;
+			
+		// optional properties
+		if (arguments.length > 1) {
+			extend(attribs, {
+				x: x,
+				y: y,
+				width: width,
+				height: height
+			});
+		}
+		
+		elemWrapper = this.createElement('image').attr(attribs);		
+		
+		// set the href in the xlink namespace
+		elemWrapper.element.setAttributeNS('http://www.w3.org/1999/xlink', 
+			'href', src);
+			
+		return elemWrapper;					
+	},
+	
+	/**
+	 * Draw a symbol out of pre-defined shape paths from the namespace 'symbol' object.
+	 * 
+	 * @param {Object} symbol
+	 * @param {Object} x
+	 * @param {Object} y
+	 * @param {Object} radius
+	 * @param {Object} options
+	 */
+	symbol: function(symbol, x, y, radius, options) {
+		
+		var obj,
+			
+			// get the symbol definition function
+			symbolFn = this.symbols[symbol],
+			
+			// check if there's a path defined for this symbol
+			path = symbolFn && symbolFn(
+				x, 
+				y, 
+				radius, 
+				options
+			),
+			
+			imageRegex = /^url\((.*?)\)$/,
+			imageSrc;
+			
+		if (path) {
+		
+			obj = this.path(path);
+			// expando properties for use in animate and attr
+			extend(obj, {
+				symbolName: symbol,
+				x: x,
+				y: y,
+				r: radius
+			});
+			if (options) {
+				extend(obj, options);
+			}
+			
+			
+		// image symbols
+		} else if (imageRegex.test(symbol)) {
+			
+			imageSrc = symbol.match(imageRegex)[1];
+			
+			// create the image synchronously, add attribs async
+			obj = this.image(imageSrc)
+				.attr({
+					x: x,
+					y: y
+				});
+			
+			// create a dummy JavaScript image to get the width and height  
+			createElement('img', {
+				onload: function() {
+					var img = this,
+						size = symbolSizes[img.src] || [img.width, img.height];
+					obj.attr({						
+						width: size[0],
+						height: size[1]
+					}).translate(
+						-mathRound(size[0] / 2),
+						-mathRound(size[1] / 2)
+					);
+				},
+				src: imageSrc
+			});
+				
+		// default circles
+		} else {
+			obj = this.circle(x, y, radius);
+		}
+		
+		return obj;
+	},
+	
+	/**
+	 * An extendable collection of functions for defining symbol paths.
+	 */
+	symbols: {
+		'square': function (x, y, radius) {
+			var len = 0.707 * radius;
+			return [
+				M, x-len, y-len,
+				L, x+len, y-len,
+				x+len, y+len,
+				x-len, y+len,
+				'Z'
+			];
+		},
+			
+		'triangle': function (x, y, radius) {
+			return [
+				M, x, y-1.33 * radius,
+				L, x+radius, y + 0.67 * radius,
+				x-radius, y + 0.67 * radius,
+				'Z'
+			];
+		},
+			
+		'triangle-down': function (x, y, radius) {
+			return [
+				M, x, y + 1.33 * radius,
+				L, x-radius, y-0.67 * radius,
+				x+radius, y-0.67 * radius,
+				'Z'
+			];
+		},
+		'diamond': function (x, y, radius) {
+			return [
+				M, x, y-radius,
+				L, x+radius, y,
+				x, y+radius,
+				x-radius, y,
+				'Z'
+			];
+		},
+		'arc': function (x, y, radius, options) {
+			var start = options.start,
+				end = options.end - 0.000001, // to prevent cos and sin of start and end from becoming equal on 360 arcs
+				innerRadius = options.innerR,
+				cosStart = mathCos(start),
+				sinStart = mathSin(start),
+				cosEnd = mathCos(end),
+				sinEnd = mathSin(end),
+				longArc = options.end - start < mathPI ? 0 : 1;
+				
+			return [
+				M,
+				x + radius * cosStart,
+				y + radius * sinStart,
+				'A', // arcTo
+				radius, // x radius
+				radius, // y radius
+				0, // slanting
+				longArc, // long or short arc
+				1, // clockwise
+				x + radius * cosEnd,
+				y + radius * sinEnd,
+				L,				
+				x + innerRadius * cosEnd, 
+				y + innerRadius * sinEnd,
+				'A', // arcTo
+				innerRadius, // x radius
+				innerRadius, // y radius
+				0, // slanting
+				longArc, // long or short arc
+				0, // clockwise
+				x + innerRadius * cosStart,
+				y + innerRadius * sinStart,
+				
+				'Z' // close
+			];
+		}
+	},
+	
+	/**
+	 * Define a clipping rectangle
+	 * @param {String} id
+	 * @param {Number} x
+	 * @param {Number} y
+	 * @param {Number} width
+	 * @param {Number} height
+	 */
+	clipRect: function (x, y, width, height) {
+		var wrapper,
+			id = PREFIX + idCounter++,
+			
+			clipPath = this.createElement('clipPath').attr({
+				id: id
+			}).add(this.defs);
+		
+		wrapper = this.rect(x, y, width, height, 0).add(clipPath);
+		wrapper.id = id;
+		
+		return wrapper;
+	},
+	
+	
+	/**
+	 * Take a color and return it if it's a string, make it a gradient if it's a
+	 * gradient configuration object
+	 * 
+	 * @param {Object} color The color or config object
+	 */
+	color: function(color, elem, prop) {
+		var colorObject,
+			regexRgba = /^rgba/;
+		if (color && color.linearGradient) {
+			var renderer = this,
+				strLinearGradient = 'linearGradient',
+				linearGradient = color[strLinearGradient],
+				id = PREFIX + idCounter++,
+				gradientObject,
+				stopColor,
+				stopOpacity;
+			gradientObject = renderer.createElement(strLinearGradient).attr({
+				id: id,
+				gradientUnits: 'userSpaceOnUse',
+				x1: linearGradient[0],
+				y1: linearGradient[1],
+				x2: linearGradient[2],
+				y2: linearGradient[3]
+			}).add(renderer.defs);
+			
+			each(color.stops, function(stop) {
+				if (regexRgba.test(stop[1])) {
+					colorObject = Color(stop[1]);
+					stopColor = colorObject.get('rgb');
+					stopOpacity = colorObject.get('a');
+				} else {
+					stopColor = stop[1];
+					stopOpacity = 1;
+				}
+				renderer.createElement('stop').attr({
+					offset: stop[0],
+					'stop-color': stopColor,
+					'stop-opacity': stopOpacity
+				}).add(gradientObject);
+			});
+			
+			return 'url('+ this.url +'#'+ id +')';
+			
+		// Webkit and Batik can't show rgba.
+		} else if (regexRgba.test(color)) {
+			colorObject = Color(color);
+			attr(elem, prop +'-opacity', colorObject.get('a'));
+			
+			return colorObject.get('rgb');
+			
+			
+		} else {
+			return color;
+		}
+		
+	},
+	
+		
+	/**
+	 * Add text to the SVG object
+	 * @param {String} str
+	 * @param {Number} x Left position
+	 * @param {Number} y Top position
+	 */
+	text: function(str, x, y) {
+		
+		// declare variables
+		var defaultChartStyle = defaultOptions.chart.style,
+			wrapper;
+	
+		x = mathRound(pick(x, 0));
+		y = mathRound(pick(y, 0));
+		
+		wrapper = this.createElement('text')
+			.attr({
+				x: x,
+				y: y,
+				text: str	
+			})
+			.css({
+				'font-family': defaultChartStyle.fontFamily,
+				'font-size': defaultChartStyle.fontSize
+			});
+			
+		wrapper.x = x;
+		wrapper.y = y;
+		return wrapper;
+	}
+}; // end SVGRenderer
+
+
+
+
+/* **************************************************************************** 
+ *                                                                            * 
+ * START OF INTERNET EXPLORER <= 8 SPECIFIC CODE                              *
+ *                                                                            *
+ * For applications and websites that don't need IE support, like platform    *
+ * targeted mobile apps and web apps, this code can be removed.               *
+ *                                                                            *
+ *****************************************************************************/
+var VMLRenderer;
+if (!hasSVG) {
+
+/**
+ * The VML element wrapper.
+ */
+var VMLElement = extendClass( SVGElement, {
+	
+	/**
+	 * Initialize a new VML element wrapper. It builds the markup as a string
+	 * to minimize DOM traffic.
+	 * @param {Object} renderer
+	 * @param {Object} nodeName
+	 */
+	init: function(renderer, nodeName) {
+		var markup =  ['<', nodeName, ' filled="f" stroked="f"'],
+			style = ['position: ', ABSOLUTE, ';'];
+		
+		// divs and shapes need size
+		if (nodeName == 'shape' || nodeName == DIV) {
+			style.push('left:0;top:0;width:10px;height:10px;');
+		}
+		if (docMode8) {
+			style.push('visibility: ', nodeName == DIV ? HIDDEN : VISIBLE);
+		}
+		
+		markup.push(' style="', style.join(''), '"/>');
+		
+		// create element with default attributes and style
+		if (nodeName) {
+			markup = nodeName == DIV || nodeName == 'span' || nodeName == 'img' ? 
+				markup.join('')
+				: renderer.prepVML(markup);
+			this.element = createElement(markup);
+		}
+		
+		this.renderer = renderer;
+	},
+	
+	/**
+	 * Add the node to the given parent
+	 * @param {Object} parent
+	 */
+	add: function(parent) {
+		var wrapper = this,
+			renderer = wrapper.renderer,
+			element = wrapper.element,
+			box = renderer.box,
+			inverted = parent && parent.inverted,
+		
+			// get the parent node
+			parentNode = parent ? 
+				parent.element || parent : 
+				box;
+			
+			
+		// if the parent group is inverted, apply inversion on all children
+		if (inverted) { // only on groups
+			renderer.invertChild(element, parentNode);			
+		}
+		
+		// issue #140 workaround - related to #61 and #74
+		if (docMode8 && parentNode.gVis == HIDDEN) {
+			css(element, { visibility: HIDDEN });
+		}
+		
+		// append it
+		parentNode.appendChild(element);
+		
+		// align text after adding to be able to read offset
+		wrapper.added = true;
+		if (wrapper.alignOnAdd) {
+			wrapper.updateTransform();
+		}		
+		
+		return wrapper;
+	},
+	
+	/**
+	 * Get or set attributes
+	 */
+	attr: function(hash, val) {
+		var key, 
+			value, 
+			i, 
+			element = this.element || {},
+			elemStyle = element.style,
+			nodeName = element.nodeName,
+			renderer = this.renderer,
+			symbolName = this.symbolName,
+			childNodes,
+			hasSetSymbolSize,
+			shadows = this.shadows,
+			skipAttr,
+			ret = this;
+			
+		// single key-value pair
+		if (isString(hash) && defined(val)) {
+			key = hash;
+			hash = {};
+			hash[key] = val;
+		}
+		
+		// used as a getter, val is undefined
+		if (isString(hash)) {
+			key = hash;
+			if (key == 'strokeWidth' || key == 'stroke-width') {
+				ret = this.strokeweight;
+			} else {
+				ret = this[key];
+			}
+			
+		// setter
+		} else {		
+			for (key in hash) {
+				value = hash[key];
+				skipAttr = false;
+				
+				// prepare paths
+				// symbols
+				if (symbolName && /^(x|y|r|start|end|width|height|innerR)/.test(key)) {
+					// if one of the symbol size affecting parameters are changed,
+					// check all the others only once for each call to an element's
+					// .attr() method
+					if (!hasSetSymbolSize) {
+							
+						this.symbolAttr(hash);						
+					
+						hasSetSymbolSize = true;
+					} 
+					
+					skipAttr = true;
+					
+				} else if (key == 'd') {
+					value = value || [];
+					this.d = value.join(' '); // used in getter for animation
+					
+					// convert paths 
+					i = value.length;
+					var convertedPath = [];
+					while (i--) {					
+						
+						// Multiply by 10 to allow subpixel precision.
+						// Substracting half a pixel seems to make the coordinates
+						// align with SVG, but this hasn't been tested thoroughly
+						if (isNumber(value[i])) {
+							convertedPath[i] = mathRound(value[i] * 10) - 5;
+						}
+						// close the path
+						else if (value[i] == 'Z') {
+							convertedPath[i] = 'x';
+						} 
+						else {
+							convertedPath[i] = value[i];
+						}
+						
+					}
+					value = convertedPath.join(' ') || 'x';							
+					element.path = value;
+			
+					// update shadows
+					if (shadows) {
+						i = shadows.length;
+						while (i--) {
+							shadows[i].path = value;
+						}
+					}
+					skipAttr = true;
+	
+				// directly mapped to css
+				} else if (key == 'zIndex' || key == 'visibility') {
+					
+					// issue 61 workaround
+					if (docMode8 && key == 'visibility' && nodeName == 'DIV') {
+						element.gVis = value;
+						childNodes = element.childNodes;
+						i = childNodes.length;
+						while (i--) {
+							css(childNodes[i], { visibility: value });
+						}
+						if (value == VISIBLE) { // issue 74
+							value = null;
+						}
+					}
+					
+					if (value) {
+						elemStyle[key] = value;
+					}
+					
+					
+					
+					skipAttr = true;
+				
+				// width and height
+				} else if (/^(width|height)$/.test(key)) {
+					
+										
+					// clipping rectangle special
+					if (this.updateClipping) {
+						this[key] = value;
+						this.updateClipping();
+						
+					} else {
+						// normal
+						elemStyle[key] = value;
+					}
+					
+					skipAttr = true;
+					
+				// x and y 
+				} else if (/^(x|y)$/.test(key)) {
+
+					this[key] = value; // used in getter
+					
+					if (element.tagName == 'SPAN') {
+						this.updateTransform();
+					
+					} else {
+						elemStyle[{ x: 'left', y: 'top' }[key]] = value;
+					}
+					
+				// class name
+				} else if (key == 'class') {
+					// IE8 Standards mode has problems retrieving the className
+					element.className = value;
+			
+				// stroke
+				} else if (key == 'stroke') {
+					
+					value = renderer.color(value, element, key);				
+						
+					key = 'strokecolor';
+					
+				// stroke width
+				} else if (key == 'stroke-width' || key == 'strokeWidth') {
+					element.stroked = value ? true : false;
+					key = 'strokeweight';
+					this[key] = value; // used in getter, issue #113
+					if (isNumber(value)) {
+						value += PX;
+					}
+					
+				// dashStyle					 
+				} else if (key == 'dashstyle') {
+					var strokeElem = element.getElementsByTagName('stroke')[0] ||
+						createElement(renderer.prepVML(['<stroke/>']), null, null, element);
+					strokeElem[key] = value || 'solid';
+					this.dashstyle = value; /* because changing stroke-width will change the dash length
+						and cause an epileptic effect */ 
+					skipAttr = true;
+					
+				// fill
+				} else if (key == 'fill') {
+					
+					if (nodeName == 'SPAN') { // text color
+						elemStyle.color = value;
+					} else {
+						element.filled = value != NONE ? true : false;
+						
+						value = renderer.color(value, element, key);
+						
+						key = 'fillcolor';
+					}
+				
+				// translation for animation
+				} else if (key == 'translateX' || key == 'translateY' || key == 'rotation' || key == 'align') {
+					if (key == 'align') {
+						key = 'textAlign';
+					}
+					this[key] = value;
+					this.updateTransform();
+					
+					skipAttr = true;
+				}
+				
+				// text for rotated and non-rotated elements
+				else if (key == 'text') {
+					element.innerHTML = value;
+					skipAttr = true;
+				} 
+				
+					
+				// let the shadow follow the main element
+				if (shadows && key == 'visibility') {
+					i = shadows.length;
+					while (i--) {
+						shadows[i].style[key] = value;
+					}
+				}
+				
+				
+				
+				if (!skipAttr) {
+					if (docMode8) { // IE8 setAttribute bug
+						element[key] = value;
+					} else {
+						attr(element, key, value);
+					}
+				}
+			}			
+		}
+		return ret;
+	},
+	
+	/**
+	 * Set the element's clipping to a predefined rectangle
+	 * 
+	 * @param {String} id The id of the clip rectangle
+	 */
+	clip: function(clipRect) {
+		var wrapper = this,
+			clipMembers = clipRect.members;
+			
+		clipMembers.push(wrapper);
+		wrapper.destroyClip = function() {
+			erase(clipMembers, wrapper);
+		};
+		return wrapper.css(clipRect.getCSS(wrapper.inverted));
+	},
+	
+	/**
+	 * Set styles for the element
+	 * @param {Object} styles
+	 */
+	css: function(styles) {
+		var wrapper = this,
+			element = wrapper.element,
+			textWidth = styles && styles.width && element.tagName == 'SPAN';
+		
+		if (textWidth) {
+			extend(styles, {
+				display: 'block',
+				whiteSpace: 'normal'
+			});	
+		}
+		wrapper.styles = extend(wrapper.styles, styles);
+		css(wrapper.element, styles);
+		
+		if (textWidth) {
+			wrapper.updateTransform();	
+		}
+		
+		return wrapper;
+	},
+	
+	/**
+	 * Extend element.destroy by removing it from the clip members array
+	 */
+	destroy: function() {
+		var wrapper = this;
+		
+		if (wrapper.destroyClip) {
+			wrapper.destroyClip();
+		}
+		
+		SVGElement.prototype.destroy.apply(wrapper);
+	},
+	
+	/**
+	 * Remove all child nodes of a group, except the v:group element
+	 */
+	empty: function() {
+		var element = this.element,
+			childNodes = element.childNodes,
+			i = childNodes.length,
+			node;
+			
+		while (i--) {
+			node = childNodes[i];
+			node.parentNode.removeChild(node);
+		}
+	},
+	
+	/**
+	 * VML override for calculating the bounding box based on offsets
+	 * 
+	 * @return {Object} A hash containing values for x, y, width and height
+	 */
+	
+	getBBox: function() {
+		var element = this.element;
+		
+		// faking getBBox in exported SVG in legacy IE
+		if (element.nodeName == 'text') {
+			element.style.position = ABSOLUTE;
+		}
+		
+		return {
+			x: element.offsetLeft,
+			y: element.offsetTop,
+			width: element.offsetWidth,
+			height: element.offsetHeight
+		};
+					
+	},
+	
+	/**
+	 * Add an event listener. VML override for normalizing event parameters.
+	 * @param {String} eventType
+	 * @param {Function} handler
+	 */
+	on: function(eventType, handler) {
+		// simplest possible event model for internal use
+		this.element['on'+ eventType] = function() {
+			var evt = win.event;
+			evt.target = evt.srcElement;
+			handler(evt);
+		};
+		return this;
+	},
+	
+	
+	/**
+	 * VML override private method to update elements based on internal 
+	 * properties based on SVG transform
+	 */
+	updateTransform: function(hash) { 
+		// aligning non added elements is expensive
+		if (!this.added) {
+			this.alignOnAdd = true;
+			return;
+		}
+		
+		var wrapper = this,
+			elem = wrapper.element,
+			translateX = wrapper.translateX || 0,
+			translateY = wrapper.translateY || 0,
+			x = wrapper.x || 0,
+			y = wrapper.y || 0,
+			align = wrapper.textAlign || 'left',
+			alignCorrection = { left: 0, center: 0.5, right: 1 }[align],
+			nonLeft = align && align != 'left';
+		
+		// apply translate
+		if (translateX || translateY) {
+			wrapper.css({
+				marginLeft: translateX,
+				marginTop: translateY
+			});
+		}
+		
+		// apply inversion
+		if (wrapper.inverted) { // wrapper is a group
+			each(elem.childNodes, function(child) {
+				wrapper.renderer.invertChild(child, elem);
+			});
+		}
+		
+		if (elem.tagName == 'SPAN') {
+			
+			var width, height,
+				rotation = wrapper.rotation,
+				lineHeight,
+				radians = 0,
+				costheta = 1,
+				sintheta = 0,
+				quad,
+				xCorr = wrapper.xCorr || 0,
+				yCorr = wrapper.yCorr || 0,
+				currentTextTransform = [rotation, align, elem.innerHTML, elem.style.width].join(',');
+				
+			if (currentTextTransform != wrapper.cTT) { // do the calculations and DOM access only if properties changed
+				
+				if (defined(rotation)) {
+					radians = rotation * deg2rad; // deg to rad
+					costheta = mathCos(radians);
+					sintheta = mathSin(radians);				
+					 
+					// Adjust for alignment and rotation.
+					// Test case: http://highcharts.com/tests/?file=text-rotation
+					css(elem, {
+						filter: rotation ? ['progid:DXImageTransform.Microsoft.Matrix(M11=', costheta, 
+							', M12=', -sintheta, ', M21=', sintheta, ', M22=', costheta, 
+							', sizingMethod=\'auto expand\')'].join('') : NONE
+					});
+				}
+				
+				width = elem.offsetWidth;
+				height = elem.offsetHeight;
+				
+				// correct x and y
+				lineHeight = mathRound(pInt(elem.style.fontSize || 12) * 1.2);
+				xCorr = costheta < 0 && -width;
+				yCorr = sintheta < 0 && -height;
+				
+				// correct for lineHeight and corners spilling out after rotation
+				quad = costheta * sintheta < 0;
+				xCorr += sintheta * lineHeight * (quad ? 1 - alignCorrection : alignCorrection);
+				yCorr -= costheta * lineHeight * (rotation ? (quad ? alignCorrection : 1 - alignCorrection) : 1);
+				
+				// correct for the length/height of the text
+				if (nonLeft) {
+					xCorr -= width * alignCorrection * (costheta < 0 ? -1 : 1);
+					if (rotation) {
+						yCorr -= height * alignCorrection * (sintheta < 0 ? -1 : 1);
+					}
+					css(elem, {
+						textAlign: align
+					});
+				}
+				
+				// record correction
+				wrapper.xCorr = xCorr;
+				wrapper.yCorr = yCorr; 
+			}
+			
+			// apply position with correction
+			css(elem, {
+				left: x + xCorr,
+				top: y + yCorr
+			});
+			
+			// record current text transform
+			wrapper.cTT = currentTextTransform;
+		}
+	},
+	
+	/**
+	 * Apply a drop shadow by copying elements and giving them different strokes 
+	 * @param {Boolean} apply
+	 */
+	shadow: function(apply) {
+		var shadows = [],
+			i,
+			element = this.element,
+			renderer = this.renderer,
+			shadow,
+			elemStyle = element.style,
+			markup,
+			path = element.path;
+			
+		// the path is some mysterious string-like object that can be cast to a string
+		if (''+ element.path === '') {
+			path = 'x';
+		}
+			
+		if (apply) {
+			for (i = 1; i <= 3; i++) {
+				markup = ['<shape isShadow="true" strokeweight="', ( 7 - 2 * i ) ,
+					'" filled="false" path="', path,
+					'" coordsize="100,100" style="', element.style.cssText, '" />'];
+				shadow = createElement(renderer.prepVML(markup),
+					null, {
+						left: pInt(elemStyle.left) + 1,
+						top: pInt(elemStyle.top) + 1
+					}
+				);
+				
+				// apply the opacity
+				markup = ['<stroke color="black" opacity="', (0.05 * i), '"/>'];
+				createElement(renderer.prepVML(markup), null, null, shadow);				
+				
+				
+				// insert it
+				element.parentNode.insertBefore(shadow, element);
+				
+				// record it
+				shadows.push(shadow);				
+				
+			}
+			
+			this.shadows = shadows;
+		}
+		return this;
+	
+	}
+});
+	
+/**
+ * The VML renderer
+ */
+VMLRenderer = function() {
+	this.init.apply(this, arguments);
+};
+VMLRenderer.prototype = merge( SVGRenderer.prototype, { // inherit SVGRenderer
+	
+	isIE8: userAgent.indexOf('MSIE 8.0') > -1,
+	
+
+	/**
+	 * Initialize the VMLRenderer
+	 * @param {Object} container
+	 * @param {Number} width
+	 * @param {Number} height
+	 */
+	init: function(container, width, height) {
+		var renderer = this,
+			boxWrapper;
+
+		renderer.Element = VMLElement;
+		renderer.alignedObjects = [];
+		
+		boxWrapper = renderer.createElement(DIV);
+		container.appendChild(boxWrapper.element);
+		
+		
+		// generate the containing box
+		renderer.box = boxWrapper.element;
+		renderer.boxWrapper = boxWrapper;
+		
+		
+		renderer.setSize(width, height, false);
+		
+		// The only way to make IE6 and IE7 print is to use a global namespace. However,
+		// with IE8 the only way to make the dynamic shapes visible in screen and print mode
+		// seems to be to add the xmlns attribute and the behaviour style inline. 
+		if (!doc.namespaces.hcv) {			
+			
+			doc.namespaces.add('hcv', 'urn:schemas-microsoft-com:vml');
+			
+			// setup default css
+			doc.createStyleSheet().cssText = 
+				'hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke'+
+				'{ behavior:url(#default#VML); display: inline-block; } ';
+			
+		}	
+	},
+	
+	/**
+	 * Define a clipping rectangle. In VML it is accomplished by storing the values
+	 * for setting the CSS style to all associated members.
+	 * 
+	 * @param {Number} x
+	 * @param {Number} y
+	 * @param {Number} width
+	 * @param {Number} height
+	 */
+	clipRect: function (x, y, width, height) {
+				
+		// create a dummy element
+		var clipRect = this.createElement();
+		
+		// mimic a rectangle with its style object for automatic updating in attr
+		return extend(clipRect, {
+			members: [],
+			left: x,
+			top: y,
+			width: width,
+			height: height,
+			getCSS: function(inverted) {
+				var rect = this,//clipRect.element.style,
+					top = rect.top,
+					left = rect.left,
+					right = left + rect.width,
+					bottom = top + rect.height,
+					ret = {
+						clip: 'rect('+ 
+							mathRound(inverted ? left : top) + 'px,'+ 
+							mathRound(inverted ? bottom : right) + 'px,'+ 
+							mathRound(inverted ? right : bottom) + 'px,'+ 
+							mathRound(inverted ? top : left) +'px)'
+					};
+					
+				// issue 74 workaround
+				if (!inverted && docMode8) {
+					extend(ret, {
+						width: right +PX,
+						height: bottom +PX
+					});
+				}
+				return ret;
+			},
+			
+			// used in attr and animation to update the clipping of all members
+			updateClipping: function() {
+				each(clipRect.members, function(member) {
+					member.css(clipRect.getCSS(member.inverted));
+				});
+			}
+		});
+		
+	},
+	
+	
+	/**
+	 * Take a color and return it if it's a string, make it a gradient if it's a
+	 * gradient configuration object, and apply opacity.
+	 * 
+	 * @param {Object} color The color or config object
+	 */
+	color: function(color, elem, prop) {
+		var colorObject,
+			regexRgba = /^rgba/,
+			markup;
+			
+		if (color && color.linearGradient) {
+			
+			var stopColor, 
+				stopOpacity,
+				linearGradient = color.linearGradient,
+				angle,
+				color1,
+				opacity1,
+				color2,
+				opacity2;	
+				
+			each(color.stops, function(stop, i) {
+				if (regexRgba.test(stop[1])) {
+					colorObject = Color(stop[1]);
+					stopColor = colorObject.get('rgb');
+					stopOpacity = colorObject.get('a');
+				} else {
+					stopColor = stop[1];
+					stopOpacity = 1;
+				}
+				
+				if (!i) { // first
+					color1 = stopColor;
+					opacity1 = stopOpacity;
+				} else {
+					color2 = stopColor;
+					opacity2 = stopOpacity;
+				}
+			});
+			
+			
+			
+			// calculate the angle based on the linear vector
+			angle = 90  - math.atan(
+				(linearGradient[3] - linearGradient[1]) / // y vector
+				(linearGradient[2] - linearGradient[0]) // x vector
+				) * 180 / mathPI;
+			
+			// when colors attribute is used, the meanings of opacity and o:opacity2
+			// are reversed.
+			markup = ['<', prop, ' colors="0% ', color1, ',100% ', color2, '" angle="', angle,
+				'" opacity="', opacity2, '" o:opacity2="', opacity1,
+				'" type="gradient" focus="100%" />'];
+			createElement(this.prepVML(markup), null, null, elem);
+			
+			
+		
+		// if the color is an rgba color, split it and add a fill node
+		// to hold the opacity component
+		} else if (regexRgba.test(color) && elem.tagName != 'IMG') {
+			
+			colorObject = Color(color);
+			
+			markup = ['<', prop, ' opacity="', colorObject.get('a'), '"/>'];
+			createElement(this.prepVML(markup), null, null, elem);
+			
+			return colorObject.get('rgb');
+			
+			
+		} else {
+			return color;
+		}
+		
+	},
+	
+	/**
+	 * Take a VML string and prepare it for either IE8 or IE6/IE7. 
+	 * @param {Array} markup A string array of the VML markup to prepare
+	 */
+	prepVML: function(markup) {
+		var vmlStyle = 'display:inline-block;behavior:url(#default#VML);',
+			isIE8 = this.isIE8;
+	
+		markup = markup.join('');
+		
+		if (isIE8) { // add xmlns and style inline
+			markup = markup.replace('/>', ' xmlns="urn:schemas-microsoft-com:vml" />');
+			if (markup.indexOf('style="') == -1) {
+				markup = markup.replace('/>', ' style="'+ vmlStyle +'" />');
+			} else {
+				markup = markup.replace('style="', 'style="'+ vmlStyle);
+			}
+
+		} else { // add namespace
+			markup = markup.replace('<', '<hcv:');
+		}
+
+		return markup;
+	},
+	
+	/**
+	 * Create rotated and aligned text
+	 * @param {String} str
+	 * @param {Number} x
+	 * @param {Number} y
+	 */
+	text: function(str, x, y) {
+		
+		var defaultChartStyle = defaultOptions.chart.style; 
+			
+		return this.createElement('span')
+			.attr({
+				text: str,
+				x: mathRound(x),
+				y: mathRound(y)
+			})
+			.css({
+				whiteSpace: 'nowrap',
+				fontFamily: defaultChartStyle.fontFamily,
+				fontSize: defaultChartStyle.fontSize
+			});
+	},
+	
+	/**
+	 * Create and return a path element
+	 * @param {Array} path
+	 */
+	path: function (path) {
+		// create the shape
+		return this.createElement('shape').attr({
+			// subpixel precision down to 0.1 (width and height = 10px)
+			coordsize: '100 100',
+			d: path
+		});
+	},
+	
+	/**
+	 * Create and return a circle element. In VML circles are implemented as
+	 * shapes, which is faster than v:oval
+	 * @param {Number} x
+	 * @param {Number} y
+	 * @param {Number} r
+	 */
+	circle: function(x, y, r) {
+		return this.path(this.symbols.circle(x, y, r));
+	},
+	
+	/**
+	 * Create a group using an outer div and an inner v:group to allow rotating 
+	 * and flipping. A simple v:group would have problems with positioning
+	 * child HTML elements and CSS clip.
+	 * 
+	 * @param {String} name The name of the group
+	 */
+	g: function(name) {
+		var wrapper,
+			attribs;
+		
+		// set the class name	
+		if (name) {
+			attribs = { 'className': PREFIX + name, 'class': PREFIX + name };
+		}
+		
+		// the div to hold HTML and clipping	
+		wrapper = this.createElement(DIV).attr(attribs);
+		
+		return wrapper;
+	},
+	
+	/**
+	 * VML override to create a regular HTML image
+	 * @param {String} src
+	 * @param {Number} x
+	 * @param {Number} y
+	 * @param {Number} width
+	 * @param {Number} height
+	 */
+	image: function(src, x, y, width, height) {
+		var obj = this.createElement('img')
+			.attr({ src: src });
+			
+		if (arguments.length > 1) {
+			obj.css({
+				left: x,
+				top: y,
+				width: width,
+				height: height
+			});
+		}
+		return obj;
+	},
+	
+	/**
+	 * VML uses a shape for rect to overcome bugs and rotation problems
+	 */
+	rect: function(x, y, width, height, r, strokeWidth) {
+		// todo: share this code with SVG
+		if (arguments.length > 1) {
+			var normalizer = (strokeWidth || 0) % 2 / 2;
+
+			// normalize for crisp edges
+			x = mathRound(x || 0) + normalizer;
+			y = mathRound(y || 0) + normalizer;
+			width = mathRound((width || 0) - 2 * normalizer);
+			height = mathRound((height || 0) - 2 * normalizer);
+		}
+		
+		if (isObject(x)) { // the attributes can be passed as the first argument 
+			y = x.y;
+			width = x.width;
+			height = x.height;
+			r = x.r;
+			x = x.x;
+		} 
+		
+		return this.symbol('rect', x || 0, y || 0, r || 0, {
+			width: width || 0,
+			height: height || 0
+		});		
+	},
+	
+	/**
+	 * In the VML renderer, each child of an inverted div (group) is inverted
+	 * @param {Object} element
+	 * @param {Object} parentNode
+	 */
+	invertChild: function(element, parentNode) {
+		var parentStyle = parentNode.style;
+			
+		css(element, { 
+			flip: 'x',
+			left: pInt(parentStyle.width) - 10,
+			top: pInt(parentStyle.height) - 10,
+			rotation: -90
+		});
+	},
+	
+	/**
+	 * Symbol definitions that override the parent SVG renderer's symbols
+	 * 
+	 */
+	symbols: {
+		// VML specific arc function
+		arc: function (x, y, radius, options) {
+			var start = options.start,
+				end = options.end,
+				cosStart = mathCos(start),
+				sinStart = mathSin(start),
+				cosEnd = mathCos(end),
+				sinEnd = mathSin(end),
+				innerRadius = options.innerR;
+				
+			if (end - start === 0) { // no angle, don't show it. 
+				return ['x'];
+				
+			} else if (end - start == 2 * mathPI) { // full circle
+				// empirical correction found by trying out the limits for different radii
+				cosEnd = -0.07 / radius;
+			}
+								
+			return [
+				'wa', // clockwise arc to
+				x - radius, // left
+				y - radius, // top
+				x + radius, // right
+				y + radius, // bottom
+				x + radius * cosStart, // start x
+				y + radius * sinStart, // start y
+				x + radius * cosEnd, // end x
+				y + radius * sinEnd, // end y
+				
+				
+				'at', // anti clockwise arc to
+				x - innerRadius, // left
+				

<TRUNCATED>

[2/9] first commit

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/sammy/sammy.js
----------------------------------------------------------------------
diff --git a/attachments/sammy/sammy.js b/attachments/sammy/sammy.js
new file mode 100644
index 0000000..d4b251f
--- /dev/null
+++ b/attachments/sammy/sammy.js
@@ -0,0 +1,1704 @@
+// name: sammy
+// version: 0.6.0pre
+
+(function($) {
+
+  var Sammy,
+      PATH_REPLACER = "([^\/]+)",
+      PATH_NAME_MATCHER = /:([\w\d]+)/g,
+      QUERY_STRING_MATCHER = /\?([^#]*)$/,
+      // mainly for making `arguments` an Array
+      _makeArray = function(nonarray) { return Array.prototype.slice.call(nonarray); },
+      // borrowed from jQuery
+      _isFunction = function( obj ) { return Object.prototype.toString.call(obj) === "[object Function]"; },
+      _isArray = function( obj ) { return Object.prototype.toString.call(obj) === "[object Array]"; },
+      _decode = decodeURIComponent,
+      _escapeHTML = function(s) {
+        return s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+      },
+      _routeWrapper = function(verb) {
+        return function(path, callback) { return this.route.apply(this, [verb, path, callback]); };
+      },
+      _template_cache = {},
+      loggers = [];
+
+
+  // `Sammy` (also aliased as $.sammy) is not only the namespace for a
+  // number of prototypes, its also a top level method that allows for easy
+  // creation/management of `Sammy.Application` instances. There are a
+  // number of different forms for `Sammy()` but each returns an instance
+  // of `Sammy.Application`. When a new instance is created using
+  // `Sammy` it is added to an Object called `Sammy.apps`. This
+  // provides for an easy way to get at existing Sammy applications. Only one
+  // instance is allowed per `element_selector` so when calling
+  // `Sammy('selector')` multiple times, the first time will create
+  // the application and the following times will extend the application
+  // already added to that selector.
+  //
+  // ### Example
+  //
+  //      // returns the app at #main or a new app
+  //      Sammy('#main')
+  //
+  //      // equivilent to "new Sammy.Application", except appends to apps
+  //      Sammy();
+  //      Sammy(function() { ... });
+  //
+  //      // extends the app at '#main' with function.
+  //      Sammy('#main', function() { ... });
+  //
+  Sammy = function() {
+    var args = _makeArray(arguments),
+        app, selector;
+    Sammy.apps = Sammy.apps || {};
+    if (args.length === 0 || args[0] && _isFunction(args[0])) { // Sammy()
+      return Sammy.apply(Sammy, ['body'].concat(args));
+    } else if (typeof (selector = args.shift()) == 'string') { // Sammy('#main')
+      app = Sammy.apps[selector] || new Sammy.Application();
+      app.element_selector = selector;
+      if (args.length > 0) {
+        $.each(args, function(i, plugin) {
+          app.use(plugin);
+        });
+      }
+      // if the selector changes make sure the refrence in Sammy.apps changes
+      if (app.element_selector != selector) {
+        delete Sammy.apps[selector];
+      }
+      Sammy.apps[app.element_selector] = app;
+      return app;
+    }
+  };
+
+  Sammy.VERSION = '0.6.0';
+
+  // Add to the global logger pool. Takes a function that accepts an
+  // unknown number of arguments and should print them or send them somewhere
+  // The first argument is always a timestamp.
+  Sammy.addLogger = function(logger) {
+    loggers.push(logger);
+  };
+
+  // Sends a log message to each logger listed in the global
+  // loggers pool. Can take any number of arguments.
+  // Also prefixes the arguments with a timestamp.
+  Sammy.log = function()  {
+    var args = _makeArray(arguments);
+    args.unshift("[" + Date() + "]");
+    $.each(loggers, function(i, logger) {
+      logger.apply(Sammy, args);
+    });
+  };
+
+  if (typeof window.console != 'undefined') {
+    if (_isFunction(console.log.apply)) {
+      Sammy.addLogger(function() {
+        window.console.log.apply(console, arguments);
+      });
+    } else {
+      Sammy.addLogger(function() {
+        window.console.log(arguments);
+      });
+    }
+  } else if (typeof console != 'undefined') {
+    Sammy.addLogger(function() {
+      console.log.apply(console, arguments);
+    });
+  }
+
+  $.extend(Sammy, {
+    makeArray: _makeArray,
+    isFunction: _isFunction,
+    isArray: _isArray
+  })
+
+  // Sammy.Object is the base for all other Sammy classes. It provides some useful
+  // functionality, including cloning, iterating, etc.
+  Sammy.Object = function(obj) { // constructor
+    return $.extend(this, obj || {});
+  };
+
+  $.extend(Sammy.Object.prototype, {
+
+    // Escape HTML in string, use in templates to prevent script injection.
+    // Also aliased as `h()`
+    escapeHTML: _escapeHTML,
+    h: _escapeHTML,
+
+    // Returns a copy of the object with Functions removed.
+    toHash: function() {
+      var json = {};
+      $.each(this, function(k,v) {
+        if (!_isFunction(v)) {
+          json[k] = v;
+        }
+      });
+      return json;
+    },
+
+    // Renders a simple HTML version of this Objects attributes.
+    // Does not render functions.
+    // For example. Given this Sammy.Object:
+    //
+    //    var s = new Sammy.Object({first_name: 'Sammy', last_name: 'Davis Jr.'});
+    //    s.toHTML() //=> '<strong>first_name</strong> Sammy<br /><strong>last_name</strong> Davis Jr.<br />'
+    //
+    toHTML: function() {
+      var display = "";
+      $.each(this, function(k, v) {
+        if (!_isFunction(v)) {
+          display += "<strong>" + k + "</strong> " + v + "<br />";
+        }
+      });
+      return display;
+    },
+
+    // Returns an array of keys for this object. If `attributes_only`
+    // is true will not return keys that map to a `function()`
+    keys: function(attributes_only) {
+      var keys = [];
+      for (var property in this) {
+        if (!_isFunction(this[property]) || !attributes_only) {
+          keys.push(property);
+        }
+      }
+      return keys;
+    },
+
+    // Checks if the object has a value at `key` and that the value is not empty
+    has: function(key) {
+      return this[key] && $.trim(this[key].toString()) != '';
+    },
+
+    // convenience method to join as many arguments as you want
+    // by the first argument - useful for making paths
+    join: function() {
+      var args = _makeArray(arguments);
+      var delimiter = args.shift();
+      return args.join(delimiter);
+    },
+
+    // Shortcut to Sammy.log
+    log: function() {
+      Sammy.log.apply(Sammy, arguments);
+    },
+
+    // Returns a string representation of this object.
+    // if `include_functions` is true, it will also toString() the
+    // methods of this object. By default only prints the attributes.
+    toString: function(include_functions) {
+      var s = [];
+      $.each(this, function(k, v) {
+        if (!_isFunction(v) || include_functions) {
+          s.push('"' + k + '": ' + v.toString());
+        }
+      });
+      return "Sammy.Object: {" + s.join(',') + "}";
+    }
+  });
+
+  // The HashLocationProxy is the default location proxy for all Sammy applications.
+  // A location proxy is a prototype that conforms to a simple interface. The purpose
+  // of a location proxy is to notify the Sammy.Application its bound to when the location
+  // or 'external state' changes. The HashLocationProxy considers the state to be
+  // changed when the 'hash' (window.location.hash / '#') changes. It does this in two
+  // different ways depending on what browser you are using. The newest browsers
+  // (IE, Safari > 4, FF >= 3.6) support a 'onhashchange' DOM event, thats fired whenever
+  // the location.hash changes. In this situation the HashLocationProxy just binds
+  // to this event and delegates it to the application. In the case of older browsers
+  // a poller is set up to track changes to the hash. Unlike Sammy 0.3 or earlier,
+  // the HashLocationProxy allows the poller to be a global object, eliminating the
+  // need for multiple pollers even when thier are multiple apps on the page.
+  Sammy.HashLocationProxy = function(app, run_interval_every) {
+    this.app = app;
+    // set is native to false and start the poller immediately
+    this.is_native = false;
+    this._startPolling(run_interval_every);
+  };
+
+  Sammy.HashLocationProxy.prototype = {
+
+    // bind the proxy events to the current app.
+    bind: function() {
+      var proxy = this, app = this.app;
+      $(window).bind('hashchange.' + this.app.eventNamespace(), function(e, non_native) {
+        // if we receive a native hash change event, set the proxy accordingly
+        // and stop polling
+        if (proxy.is_native === false && !non_native) {
+          Sammy.log('native hash change exists, using');
+          proxy.is_native = true;
+          clearInterval(Sammy.HashLocationProxy._interval);
+        }
+        app.trigger('location-changed');
+      });
+      if (!Sammy.HashLocationProxy._bindings) {
+        Sammy.HashLocationProxy._bindings = 0;
+      }
+      Sammy.HashLocationProxy._bindings++;
+    },
+
+    // unbind the proxy events from the current app
+    unbind: function() {
+      $(window).unbind('hashchange.' + this.app.eventNamespace());
+      Sammy.HashLocationProxy._bindings--;
+      if (Sammy.HashLocationProxy._bindings <= 0) {
+        clearInterval(Sammy.HashLocationProxy._interval);
+      }
+    },
+
+    // get the current location from the hash.
+    getLocation: function() {
+     // Bypass the `window.location.hash` attribute.  If a question mark
+      // appears in the hash IE6 will strip it and all of the following
+      // characters from `window.location.hash`.
+      var matches = window.location.toString().match(/^[^#]*(#.+)$/);
+      return matches ? matches[1] : '';
+    },
+
+    // set the current location to `new_location`
+    setLocation: function(new_location) {
+      return (window.location = new_location);
+    },
+
+    _startPolling: function(every) {
+      // set up interval
+      var proxy = this;
+      if (!Sammy.HashLocationProxy._interval) {
+        if (!every) { every = 10; }
+        var hashCheck = function() {
+          current_location = proxy.getLocation();
+          if (!Sammy.HashLocationProxy._last_location ||
+            current_location != Sammy.HashLocationProxy._last_location) {
+            setTimeout(function() {
+              $(window).trigger('hashchange', [true]);
+            }, 13);
+          }
+          Sammy.HashLocationProxy._last_location = current_location;
+        };
+        hashCheck();
+        Sammy.HashLocationProxy._interval = setInterval(hashCheck, every);
+      }
+    }
+  };
+
+
+  // Sammy.Application is the Base prototype for defining 'applications'.
+  // An 'application' is a collection of 'routes' and bound events that is
+  // attached to an element when `run()` is called.
+  // The only argument an 'app_function' is evaluated within the context of the application.
+  Sammy.Application = function(app_function) {
+    var app = this;
+    this.routes            = {};
+    this.listeners         = new Sammy.Object({});
+    this.arounds           = [];
+    this.befores           = [];
+    // generate a unique namespace
+    this.namespace         = (new Date()).getTime() + '-' + parseInt(Math.random() * 1000, 10);
+    this.context_prototype = function() { Sammy.EventContext.apply(this, arguments); };
+    this.context_prototype.prototype = new Sammy.EventContext();
+
+    if (_isFunction(app_function)) {
+      app_function.apply(this, [this]);
+    }
+    // set the location proxy if not defined to the default (HashLocationProxy)
+    if (!this._location_proxy) {
+      this.setLocationProxy(new Sammy.HashLocationProxy(this, this.run_interval_every));
+    }
+    if (this.debug) {
+      this.bindToAllEvents(function(e, data) {
+        app.log(app.toString(), e.cleaned_type, data || {});
+      });
+    }
+  };
+
+  Sammy.Application.prototype = $.extend({}, Sammy.Object.prototype, {
+
+    // the four route verbs
+    ROUTE_VERBS: ['get','post','put','delete'],
+
+    // An array of the default events triggered by the
+    // application during its lifecycle
+    APP_EVENTS: ['run','unload','lookup-route','run-route','route-found','event-context-before','event-context-after','changed','error','check-form-submission','redirect'],
+
+    _last_route: null,
+    _location_proxy: null,
+    _running: false,
+
+    // Defines what element the application is bound to. Provide a selector
+    // (parseable by `jQuery()`) and this will be used by `$element()`
+    element_selector: 'body',
+
+    // When set to true, logs all of the default events using `log()`
+    debug: false,
+
+    // When set to true, and the error() handler is not overriden, will actually
+    // raise JS errors in routes (500) and when routes can't be found (404)
+    raise_errors: false,
+
+    // The time in milliseconds that the URL is queried for changes
+    run_interval_every: 50,
+
+    // The default template engine to use when using `partial()` in an
+    // `EventContext`. `template_engine` can either be a string that
+    // corresponds to the name of a method/helper on EventContext or it can be a function
+    // that takes two arguments, the content of the unrendered partial and an optional
+    // JS object that contains interpolation data. Template engine is only called/refered
+    // to if the extension of the partial is null or unknown. See `partial()`
+    // for more information
+    template_engine: null,
+
+    // //=> Sammy.Application: body
+    toString: function() {
+      return 'Sammy.Application:' + this.element_selector;
+    },
+
+    // returns a jQuery object of the Applications bound element.
+    $element: function() {
+      return $(this.element_selector);
+    },
+
+    // `use()` is the entry point for including Sammy plugins.
+    // The first argument to use should be a function() that is evaluated
+    // in the context of the current application, just like the `app_function`
+    // argument to the `Sammy.Application` constructor.
+    //
+    // Any additional arguments are passed to the app function sequentially.
+    //
+    // For much more detail about plugins, check out:
+    // http://code.quirkey.com/sammy/doc/plugins.html
+    //
+    // ### Example
+    //
+    //      var MyPlugin = function(app, prepend) {
+    //
+    //        this.helpers({
+    //          myhelper: function(text) {
+    //            alert(prepend + " " + text);
+    //          }
+    //        });
+    //
+    //      };
+    //
+    //      var app = $.sammy(function() {
+    //
+    //        this.use(MyPlugin, 'This is my plugin');
+    //
+    //        this.get('#/', function() {
+    //          this.myhelper('and dont you forget it!');
+    //          //=> Alerts: This is my plugin and dont you forget it!
+    //        });
+    //
+    //      });
+    //
+    // If plugin is passed as a string it assumes your are trying to load
+    // Sammy."Plugin". This is the prefered way of loading core Sammy plugins
+    // as it allows for better error-messaging.
+    //
+    // ### Example
+    //
+    //      $.sammy(function() {
+    //        this.use('Mustache'); //=> Sammy.Mustache
+    //        this.use('Storage'); //=> Sammy.Storage
+    //      });
+    //
+    use: function() {
+      // flatten the arguments
+      var args = _makeArray(arguments),
+          plugin = args.shift(),
+          plugin_name = plugin || '';
+      try {
+        args.unshift(this);
+        if (typeof plugin == 'string') {
+          plugin_name = 'Sammy.' + plugin;
+          plugin = Sammy[plugin];
+        }
+        plugin.apply(this, args);
+      } catch(e) {
+        if (typeof plugin === 'undefined') {
+          this.error("Plugin Error: called use() but plugin (" + plugin_name.toString() + ") is not defined", e);
+        } else if (!_isFunction(plugin)) {
+          this.error("Plugin Error: called use() but '" + plugin_name.toString() + "' is not a function", e);
+        } else {
+          this.error("Plugin Error", e);
+        }
+      }
+      return this;
+    },
+
+    // Sets the location proxy for the current app. By default this is set to
+    // a new `Sammy.HashLocationProxy` on initialization. However, you can set
+    // the location_proxy inside you're app function to give your app a custom
+    // location mechanism. See `Sammy.HashLocationProxy` and `Sammy.DataLocationProxy`
+    // for examples.
+    //
+    // `setLocationProxy()` takes an initialized location proxy.
+    //
+    // ### Example
+    //
+    //        // to bind to data instead of the default hash;
+    //        var app = $.sammy(function() {
+    //          this.setLocationProxy(new Sammy.DataLocationProxy(this));
+    //        });
+    //
+    setLocationProxy: function(new_proxy) {
+      var original_proxy = this._location_proxy;
+      this._location_proxy = new_proxy;
+      if (this.isRunning()) {
+        if (original_proxy) {
+          // if there is already a location proxy, unbind it.
+          original_proxy.unbind();
+        }
+        this._location_proxy.bind();
+      }
+    },
+
+    // `route()` is the main method for defining routes within an application.
+    // For great detail on routes, check out: http://code.quirkey.com/sammy/doc/routes.html
+    //
+    // This method also has aliases for each of the different verbs (eg. `get()`, `post()`, etc.)
+    //
+    // ### Arguments
+    //
+    // * `verb` A String in the set of ROUTE_VERBS or 'any'. 'any' will add routes for each
+    //    of the ROUTE_VERBS. If only two arguments are passed,
+    //    the first argument is the path, the second is the callback and the verb
+    //    is assumed to be 'any'.
+    // * `path` A Regexp or a String representing the path to match to invoke this verb.
+    // * `callback` A Function that is called/evaluated whent the route is run see: `runRoute()`.
+    //    It is also possible to pass a string as the callback, which is looked up as the name
+    //    of a method on the application.
+    //
+    route: function(verb, path, callback) {
+      var app = this, param_names = [], add_route;
+
+      // if the method signature is just (path, callback)
+      // assume the verb is 'any'
+      if (!callback && _isFunction(path)) {
+        path = verb;
+        callback = path;
+        verb = 'any';
+      }
+
+      verb = verb.toLowerCase(); // ensure verb is lower case
+
+      // if path is a string turn it into a regex
+      if (path.constructor == String) {
+
+        // Needs to be explicitly set because IE will maintain the index unless NULL is returned,
+        // which means that with two consecutive routes that contain params, the second set of params will not be found and end up in splat instead of params
+        // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp/lastIndex
+        PATH_NAME_MATCHER.lastIndex = 0;
+
+        // find the names
+        while ((path_match = PATH_NAME_MATCHER.exec(path)) !== null) {
+          param_names.push(path_match[1]);
+        }
+        // replace with the path replacement
+        path = new RegExp("^" + path.replace(PATH_NAME_MATCHER, PATH_REPLACER) + "$");
+      }
+      // lookup callback
+      if (typeof callback == 'string') {
+        callback = app[callback];
+      }
+
+      add_route = function(with_verb) {
+        var r = {verb: with_verb, path: path, callback: callback, param_names: param_names};
+        // add route to routes array
+        app.routes[with_verb] = app.routes[with_verb] || [];
+        // place routes in order of definition
+        app.routes[with_verb].push(r);
+      };
+
+      if (verb === 'any') {
+        $.each(this.ROUTE_VERBS, function(i, v) { add_route(v); });
+      } else {
+        add_route(verb);
+      }
+
+      // return the app
+      return this;
+    },
+
+    // Alias for route('get', ...)
+    get: _routeWrapper('get'),
+
+    // Alias for route('post', ...)
+    post: _routeWrapper('post'),
+
+    // Alias for route('put', ...)
+    put: _routeWrapper('put'),
+
+    // Alias for route('delete', ...)
+    del: _routeWrapper('delete'),
+
+    // Alias for route('any', ...)
+    any: _routeWrapper('any'),
+
+    // `mapRoutes` takes an array of arrays, each array being passed to route()
+    // as arguments, this allows for mass definition of routes. Another benefit is
+    // this makes it possible/easier to load routes via remote JSON.
+    //
+    // ### Example
+    //
+    //    var app = $.sammy(function() {
+    //
+    //      this.mapRoutes([
+    //          ['get', '#/', function() { this.log('index'); }],
+    //          // strings in callbacks are looked up as methods on the app
+    //          ['post', '#/create', 'addUser'],
+    //          // No verb assumes 'any' as the verb
+    //          [/dowhatever/, function() { this.log(this.verb, this.path)}];
+    //        ]);
+    //    })
+    //
+    mapRoutes: function(route_array) {
+      var app = this;
+      $.each(route_array, function(i, route_args) {
+        app.route.apply(app, route_args);
+      });
+      return this;
+    },
+
+    // A unique event namespace defined per application.
+    // All events bound with `bind()` are automatically bound within this space.
+    eventNamespace: function() {
+      return ['sammy-app', this.namespace].join('-');
+    },
+
+    // Works just like `jQuery.fn.bind()` with a couple noteable differences.
+    //
+    // * It binds all events to the application element
+    // * All events are bound within the `eventNamespace()`
+    // * Events are not actually bound until the application is started with `run()`
+    // * callbacks are evaluated within the context of a Sammy.EventContext
+    //
+    // See http://code.quirkey.com/sammy/docs/events.html for more info.
+    //
+    bind: function(name, data, callback) {
+      var app = this;
+      // build the callback
+      // if the arity is 2, callback is the second argument
+      if (typeof callback == 'undefined') { callback = data; }
+      var listener_callback =  function() {
+        // pull off the context from the arguments to the callback
+        var e, context, data;
+        e       = arguments[0];
+        data    = arguments[1];
+        if (data && data.context) {
+          context = data.context;
+          delete data.context;
+        } else {
+          context = new app.context_prototype(app, 'bind', e.type, data, e.target);
+        }
+        e.cleaned_type = e.type.replace(app.eventNamespace(), '');
+        callback.apply(context, [e, data]);
+      };
+
+      // it could be that the app element doesnt exist yet
+      // so attach to the listeners array and then run()
+      // will actually bind the event.
+      if (!this.listeners[name]) { this.listeners[name] = []; }
+      this.listeners[name].push(listener_callback);
+      if (this.isRunning()) {
+        // if the app is running
+        // *actually* bind the event to the app element
+        this._listen(name, listener_callback);
+      }
+      return this;
+    },
+
+    // Triggers custom events defined with `bind()`
+    //
+    // ### Arguments
+    //
+    // * `name` The name of the event. Automatically prefixed with the `eventNamespace()`
+    // * `data` An optional Object that can be passed to the bound callback.
+    // * `context` An optional context/Object in which to execute the bound callback.
+    //   If no context is supplied a the context is a new `Sammy.EventContext`
+    //
+    trigger: function(name, data) {
+      this.$element().trigger([name, this.eventNamespace()].join('.'), [data]);
+      return this;
+    },
+
+    // Reruns the current route
+    refresh: function() {
+      this.last_location = null;
+      this.trigger('location-changed');
+      return this;
+    },
+
+    // Takes a single callback that is pushed on to a stack.
+    // Before any route is run, the callbacks are evaluated in order within
+    // the current `Sammy.EventContext`
+    //
+    // If any of the callbacks explicitly return false, execution of any
+    // further callbacks and the route itself is halted.
+    //
+    // You can also provide a set of options that will define when to run this
+    // before based on the route it proceeds.
+    //
+    // ### Example
+    //
+    //      var app = $.sammy(function() {
+    //
+    //        // will run at #/route but not at #/
+    //        this.before('#/route', function() {
+    //          //...
+    //        });
+    //
+    //        // will run at #/ but not at #/route
+    //        this.before({except: {path: '#/route'}}, function() {
+    //          this.log('not before #/route');
+    //        });
+    //
+    //        this.get('#/', function() {});
+    //
+    //        this.get('#/route', function() {});
+    //
+    //      });
+    //
+    // See `contextMatchesOptions()` for a full list of supported options
+    //
+    before: function(options, callback) {
+      if (_isFunction(options)) {
+        callback = options;
+        options = {};
+      }
+      this.befores.push([options, callback]);
+      return this;
+    },
+
+    // A shortcut for binding a callback to be run after a route is executed.
+    // After callbacks have no guarunteed order.
+    after: function(callback) {
+      return this.bind('event-context-after', callback);
+    },
+
+
+    // Adds an around filter to the application. around filters are functions
+    // that take a single argument `callback` which is the entire route
+    // execution path wrapped up in a closure. This means you can decide whether
+    // or not to proceed with execution by not invoking `callback` or,
+    // more usefuly wrapping callback inside the result of an asynchronous execution.
+    //
+    // ### Example
+    //
+    // The most common use case for around() is calling a _possibly_ async function
+    // and executing the route within the functions callback:
+    //
+    //      var app = $.sammy(function() {
+    //
+    //        var current_user = false;
+    //
+    //        function checkLoggedIn(callback) {
+    //          // /session returns a JSON representation of the logged in user
+    //          // or an empty object
+    //          if (!current_user) {
+    //            $.getJSON('/session', function(json) {
+    //              if (json.login) {
+    //                // show the user as logged in
+    //                current_user = json;
+    //                // execute the route path
+    //                callback();
+    //              } else {
+    //                // show the user as not logged in
+    //                current_user = false;
+    //                // the context of aroundFilters is an EventContext
+    //                this.redirect('#/login');
+    //              }
+    //            });
+    //          } else {
+    //            // execute the route path
+    //            callback();
+    //          }
+    //        };
+    //
+    //        this.around(checkLoggedIn);
+    //
+    //      });
+    //
+    around: function(callback) {
+      this.arounds.push(callback);
+      return this;
+    },
+
+    // Returns `true` if the current application is running.
+    isRunning: function() {
+      return this._running;
+    },
+
+    // Helpers extends the EventContext prototype specific to this app.
+    // This allows you to define app specific helper functions that can be used
+    // whenever you're inside of an event context (templates, routes, bind).
+    //
+    // ### Example
+    //
+    //    var app = $.sammy(function() {
+    //
+    //      helpers({
+    //        upcase: function(text) {
+    //         return text.toString().toUpperCase();
+    //        }
+    //      });
+    //
+    //      get('#/', function() { with(this) {
+    //        // inside of this context I can use the helpers
+    //        $('#main').html(upcase($('#main').text());
+    //      }});
+    //
+    //    });
+    //
+    //
+    // ### Arguments
+    //
+    // * `extensions` An object collection of functions to extend the context.
+    //
+    helpers: function(extensions) {
+      $.extend(this.context_prototype.prototype, extensions);
+      return this;
+    },
+
+    // Helper extends the event context just like `helpers()` but does it
+    // a single method at a time. This is especially useful for dynamically named
+    // helpers
+    //
+    // ### Example
+    //
+    //     // Trivial example that adds 3 helper methods to the context dynamically
+    //     var app = $.sammy(function(app) {
+    //
+    //       $.each([1,2,3], function(i, num) {
+    //         app.helper('helper' + num, function() {
+    //           this.log("I'm helper number " + num);
+    //         });
+    //       });
+    //
+    //       this.get('#/', function() {
+    //         this.helper2(); //=> I'm helper number 2
+    //       });
+    //     });
+    //
+    // ### Arguments
+    //
+    // * `name` The name of the method
+    // * `method` The function to be added to the prototype at `name`
+    //
+    helper: function(name, method) {
+      this.context_prototype.prototype[name] = method;
+      return this;
+    },
+
+    // Actually starts the application's lifecycle. `run()` should be invoked
+    // within a document.ready block to ensure the DOM exists before binding events, etc.
+    //
+    // ### Example
+    //
+    //    var app = $.sammy(function() { ... }); // your application
+    //    $(function() { // document.ready
+    //        app.run();
+    //     });
+    //
+    // ### Arguments
+    //
+    // * `start_url` Optionally, a String can be passed which the App will redirect to
+    //   after the events/routes have been bound.
+    run: function(start_url) {
+      if (this.isRunning()) { return false; }
+      var app = this;
+
+      // actually bind all the listeners
+      $.each(this.listeners.toHash(), function(name, callbacks) {
+        $.each(callbacks, function(i, listener_callback) {
+          app._listen(name, listener_callback);
+        });
+      });
+
+      this.trigger('run', {start_url: start_url});
+      this._running = true;
+      // set last location
+      this.last_location = null;
+      if (this.getLocation() == '' && typeof start_url != 'undefined') {
+        this.setLocation(start_url);
+      }
+      // check url
+      this._checkLocation();
+      this._location_proxy.bind();
+      this.bind('location-changed', function() {
+        app._checkLocation();
+      });
+
+      // bind to submit to capture post/put/delete routes
+      this.bind('submit', function(e) {
+        var returned = app._checkFormSubmission($(e.target).closest('form'));
+        return (returned === false) ? e.preventDefault() : false;
+      });
+
+      // bind unload to body unload
+      $(window).bind('beforeunload', function() {
+        app.unload();
+      });
+
+      // trigger html changed
+      return this.trigger('changed');
+    },
+
+    // The opposite of `run()`, un-binds all event listeners and intervals
+    // `run()` Automaticaly binds a `onunload` event to run this when
+    // the document is closed.
+    unload: function() {
+      if (!this.isRunning()) { return false; }
+      var app = this;
+      this.trigger('unload');
+      // clear interval
+      this._location_proxy.unbind();
+      // unbind form submits
+      this.$element().unbind('submit').removeClass(app.eventNamespace());
+      // unbind all events
+      $.each(this.listeners.toHash() , function(name, listeners) {
+        $.each(listeners, function(i, listener_callback) {
+          app._unlisten(name, listener_callback);
+        });
+      });
+      this._running = false;
+      return this;
+    },
+
+    // Will bind a single callback function to every event that is already
+    // being listened to in the app. This includes all the `APP_EVENTS`
+    // as well as any custom events defined with `bind()`.
+    //
+    // Used internally for debug logging.
+    bindToAllEvents: function(callback) {
+      var app = this;
+      // bind to the APP_EVENTS first
+      $.each(this.APP_EVENTS, function(i, e) {
+        app.bind(e, callback);
+      });
+      // next, bind to listener names (only if they dont exist in APP_EVENTS)
+      $.each(this.listeners.keys(true), function(i, name) {
+        if (app.APP_EVENTS.indexOf(name) == -1) {
+          app.bind(name, callback);
+        }
+      });
+      return this;
+    },
+
+    // Returns a copy of the given path with any query string after the hash
+    // removed.
+    routablePath: function(path) {
+      return path.replace(QUERY_STRING_MATCHER, '');
+    },
+
+    // Given a verb and a String path, will return either a route object or false
+    // if a matching route can be found within the current defined set.
+    lookupRoute: function(verb, path) {
+      var app = this, routed = false;
+      this.trigger('lookup-route', {verb: verb, path: path});
+      if (typeof this.routes[verb] != 'undefined') {
+        $.each(this.routes[verb], function(i, route) {
+          if (app.routablePath(path).match(route.path)) {
+            routed = route;
+            route._path = path;
+            return false;
+          }
+        });
+        // Also check against the base path
+        $.each(this.routes[verb], function(i, route) {
+          if (app.routablePath(window.location.pathname).match(route.path)) {
+            routed = route;
+            route._path = window.location.pathname;
+            return false;
+          }
+        });
+      }
+      return routed;
+    },
+
+    // First, invokes `lookupRoute()` and if a route is found, parses the
+    // possible URL params and then invokes the route's callback within a new
+    // `Sammy.EventContext`. If the route can not be found, it calls
+    // `notFound()`. If `raise_errors` is set to `true` and
+    // the `error()` has not been overriden, it will throw an actual JS
+    // error.
+    //
+    // You probably will never have to call this directly.
+    //
+    // ### Arguments
+    //
+    // * `verb` A String for the verb.
+    // * `path` A String path to lookup.
+    // * `params` An Object of Params pulled from the URI or passed directly.
+    //
+    // ### Returns
+    //
+    // Either returns the value returned by the route callback or raises a 404 Not Found error.
+    //
+    runRoute: function(verb, path, params, target) {
+      var app = this,
+          route = this.lookupRoute(verb, path),
+          context,
+          wrapped_route,
+          arounds,
+          around,
+          befores,
+          before,
+          callback_args,
+          final_returned;
+
+      this.log('runRoute', [verb, path].join(' '));
+      this.trigger('run-route', {verb: verb, path: path, params: params});
+      if (typeof params == 'undefined') { params = {}; }
+      $.extend(params, this._parseQueryString(path));
+      
+      if (route) {
+        this.trigger('route-found', {route: route});
+        // pull out the params from the path
+        if ((path_params = route.path.exec(this.routablePath(route._path))) !== null) {
+          // first match is the full path
+          path_params.shift();
+          // for each of the matches
+          $.each(path_params, function(i, param) {
+            // if theres a matching param name
+            if (route.param_names[i]) {
+              // set the name to the match
+              params[route.param_names[i]] = _decode(param);
+            } else {
+              // initialize 'splat'
+              if (!params.splat) { params.splat = []; }
+              params.splat.push(_decode(param));
+            }
+          });
+        }
+
+        // set event context
+        context  = new this.context_prototype(this, verb, path, params, target);
+        // ensure arrays
+        arounds = this.arounds.slice(0);
+        befores = this.befores.slice(0);
+        // set the callback args to the context + contents of the splat
+        callback_args = [context].concat(params.splat);
+        // wrap the route up with the before filters
+        wrapped_route = function() {
+          var returned;
+          while (befores.length > 0) {
+            before = befores.shift();
+            // check the options
+            if (app.contextMatchesOptions(context, before[0])) {
+              returned = before[1].apply(context, [context]);
+              if (returned === false) { return false; }
+            }
+          }
+          app.last_route = route;
+          context.trigger('event-context-before', {context: context});
+          returned = route.callback.apply(context, callback_args);
+          context.trigger('event-context-after', {context: context});
+          return returned;
+        };
+        $.each(arounds.reverse(), function(i, around) {
+          var last_wrapped_route = wrapped_route;
+          wrapped_route = function() { return around.apply(context, [last_wrapped_route]); };
+        });
+        try {
+          final_returned = wrapped_route();
+        } catch(e) {
+          this.error(['500 Error', verb, path].join(' '), e);
+        }
+        return final_returned;
+      } else {
+        return this.notFound(verb, path);
+      }
+    },
+
+    // Matches an object of options against an `EventContext` like object that
+    // contains `path` and `verb` attributes. Internally Sammy uses this
+    // for matching `before()` filters against specific options. You can set the
+    // object to _only_ match certain paths or verbs, or match all paths or verbs _except_
+    // those that match the options.
+    //
+    // ### Example
+    //
+    //     var app = $.sammy(),
+    //         context = {verb: 'get', path: '#/mypath'};
+    //
+    //     // match against a path string
+    //     app.contextMatchesOptions(context, '#/mypath'); //=> true
+    //     app.contextMatchesOptions(context, '#/otherpath'); //=> false
+    //     // equivilent to
+    //     app.contextMatchesOptions(context, {only: {path:'#/mypath'}}); //=> true
+    //     app.contextMatchesOptions(context, {only: {path:'#/otherpath'}}); //=> false
+    //     // match against a path regexp
+    //     app.contextMatchesOptions(context, /path/); //=> true
+    //     app.contextMatchesOptions(context, /^path/); //=> false
+    //     // match only a verb
+    //     app.contextMatchesOptions(context, {only: {verb:'get'}}); //=> true
+    //     app.contextMatchesOptions(context, {only: {verb:'post'}}); //=> false
+    //     // match all except a verb
+    //     app.contextMatchesOptions(context, {except: {verb:'post'}}); //=> true
+    //     app.contextMatchesOptions(context, {except: {verb:'get'}}); //=> false
+    //     // match all except a path
+    //     app.contextMatchesOptions(context, {except: {path:'#/otherpath'}}); //=> true
+    //     app.contextMatchesOptions(context, {except: {path:'#/mypath'}}); //=> false
+    //
+    contextMatchesOptions: function(context, match_options, positive) {
+      // empty options always match
+      var options = match_options;
+      if (typeof options === 'undefined' || options == {}) {
+        return true;
+      }
+      if (typeof positive === 'undefined') {
+        positive = true;
+      }
+      // normalize options
+      if (typeof options === 'string' || _isFunction(options.test)) {
+        options = {path: options};
+      }
+      if (options.only) {
+        return this.contextMatchesOptions(context, options.only, true);
+      } else if (options.except) {
+        return this.contextMatchesOptions(context, options.except, false);
+      }
+      var path_matched = true, verb_matched = true;
+      if (options.path) {
+        // wierd regexp test
+        if (_isFunction(options.path.test)) {
+          path_matched = options.path.test(context.path);
+        } else {
+          path_matched = (options.path.toString() === context.path);
+        }
+      }
+      if (options.verb) {
+        verb_matched = options.verb === context.verb;
+      }
+      return positive ? (verb_matched && path_matched) : !(verb_matched && path_matched);
+    },
+
+
+    // Delegates to the `location_proxy` to get the current location.
+    // See `Sammy.HashLocationProxy` for more info on location proxies.
+    getLocation: function() {
+      return this._location_proxy.getLocation();
+    },
+
+    // Delegates to the `location_proxy` to set the current location.
+    // See `Sammy.HashLocationProxy` for more info on location proxies.
+    //
+    // ### Arguments
+    //
+    // * `new_location` A new location string (e.g. '#/')
+    //
+    setLocation: function(new_location) {
+      return this._location_proxy.setLocation(new_location);
+    },
+
+    // Swaps the content of `$element()` with `content`
+    // You can override this method to provide an alternate swap behavior
+    // for `EventContext.partial()`.
+    //
+    // ### Example
+    //
+    //    var app = $.sammy(function() {
+    //
+    //      // implements a 'fade out'/'fade in'
+    //      this.swap = function(content) {
+    //        this.$element().hide('slow').html(content).show('slow');
+    //      }
+    //
+    //      get('#/', function() {
+    //        this.partial('index.html.erb') // will fade out and in
+    //      });
+    //
+    //    });
+    //
+    swap: function(content) {
+      return this.$element().html(content);
+    },
+
+    // a simple global cache for templates. Uses the same semantics as
+    // `Sammy.Cache` and `Sammy.Storage` so can easily be replaced with
+    // a persistant storage that lasts beyond the current request.
+    templateCache: function(key, value) {
+      if (typeof value != 'undefined') {
+        return _template_cache[key] = value;
+      } else {
+        return _template_cache[key];
+      }
+    },
+
+    // This thows a '404 Not Found' error by invoking `error()`.
+    // Override this method or `error()` to provide custom
+    // 404 behavior (i.e redirecting to / or showing a warning)
+    notFound: function(verb, path) {
+      var ret = this.error(['404 Not Found', verb, path].join(' '));
+      return (verb === 'get') ? ret : true;
+    },
+
+    // The base error handler takes a string `message` and an `Error`
+    // object. If `raise_errors` is set to `true` on the app level,
+    // this will re-throw the error to the browser. Otherwise it will send the error
+    // to `log()`. Override this method to provide custom error handling
+    // e.g logging to a server side component or displaying some feedback to the
+    // user.
+    error: function(message, original_error) {
+      if (!original_error) { original_error = new Error(); }
+      original_error.message = [message, original_error.message].join(' ');
+      this.trigger('error', {message: original_error.message, error: original_error});
+      if (this.raise_errors) {
+        throw(original_error);
+      } else {
+        this.log(original_error.message, original_error);
+      }
+    },
+
+    _checkLocation: function() {
+      var location, returned;
+      // get current location
+      location = this.getLocation();
+      // compare to see if hash has changed
+      if (location != this.last_location) {
+        // reset last location
+        this.last_location = location;
+        // lookup route for current hash
+        returned = this.runRoute('get', location);
+      }
+      return returned;
+    },
+
+    _getFormVerb: function(form) {
+      var $form = $(form), verb;
+      $_method = $form.find('input[name="_method"]');
+      if ($_method.length > 0) { verb = $_method.val(); }
+      if (!verb) { verb = $form[0].getAttribute('method'); }
+      return $.trim(verb.toString().toLowerCase());
+    },
+
+    _checkFormSubmission: function(form) {
+      var $form, path, verb, params, returned;
+      this.trigger('check-form-submission', {form: form});
+      $form = $(form);
+      path  = $form.attr('action');
+      verb  = this._getFormVerb($form);
+      if (!verb || verb == '') { verb = 'get'; }
+      this.log('_checkFormSubmission', $form, path, verb);
+      if (verb === 'get') {
+        this.setLocation(path + '?' + $form.serialize());
+        returned = false;
+      } else {
+        params = $.extend({}, this._parseFormParams($form));
+        returned = this.runRoute(verb, path, params, form.get(0));
+      };
+      return (typeof returned == 'undefined') ? false : returned;
+    },
+
+    _parseFormParams: function($form) {
+      var params = {},
+          form_fields = $form.serializeArray(),
+          i;
+      for (i = 0; i < form_fields.length; i++) {
+        params = this._parseParamPair(params, form_fields[i].name, form_fields[i].value);
+      }
+      return params;
+    },
+
+    _parseQueryString: function(path) {
+      var params = {}, parts, pairs, pair, i;
+
+      parts = path.match(QUERY_STRING_MATCHER);
+      if (parts) {
+        pairs = parts[1].split('&');
+        for (i = 0; i < pairs.length; i++) {
+          pair = pairs[i].split('=');
+          params = this._parseParamPair(params, _decode(pair[0]), _decode(pair[1]));
+        }
+      }
+      return params;
+    },
+
+    _parseParamPair: function(params, key, value) {
+      if (params[key]) {
+        if (_isArray(params[key])) {
+          params[key].push(value);
+        } else {
+          params[key] = [params[key], value];
+        }
+      } else {
+        params[key] = value;
+      }
+      return params;
+    },
+
+    _listen: function(name, callback) {
+      return this.$element().bind([name, this.eventNamespace()].join('.'), callback);
+    },
+
+    _unlisten: function(name, callback) {
+      return this.$element().unbind([name, this.eventNamespace()].join('.'), callback);
+    }
+
+  });
+
+  // `Sammy.RenderContext` is an object that makes sequential template loading,
+  // rendering and interpolation seamless even when dealing with asyncronous
+  // operations.
+  //
+  // `RenderContext` objects are not usually created directly, rather they are
+  // instatiated from an `Sammy.EventContext` by using `render()`, `load()` or
+  // `partial()` which all return `RenderContext` objects.
+  //
+  // `RenderContext` methods always returns a modified `RenderContext`
+  // for chaining (like jQuery itself).
+  //
+  // The core magic is in the `then()` method which puts the callback passed as
+  // an argument into a queue to be executed once the previous callback is complete.
+  // All the methods of `RenderContext` are wrapped in `then()` which allows you
+  // to queue up methods by chaining, but maintaing a guarunteed execution order
+  // even with remote calls to fetch templates.
+  //
+  Sammy.RenderContext = function(event_context) {
+    this.event_context    = event_context;
+    this.callbacks        = [];
+    this.previous_content = null;
+    this.content          = null;
+    this.next_engine      = false;
+    this.waiting          = false;
+  };
+
+  $.extend(Sammy.RenderContext.prototype, {
+
+    // The "core" of the `RenderContext` object, adds the `callback` to the
+    // queue. If the context is `waiting` (meaning an async operation is happening)
+    // then the callback will be executed in order, once the other operations are
+    // complete. If there is no currently executing operation, the `callback`
+    // is executed immediately.
+    //
+    // The value returned from the callback is stored in `content` for the
+    // subsiquent operation. If you return `false`, the queue will pause, and
+    // the next callback in the queue will not be executed until `next()` is
+    // called. This allows for the guarunteed order of execution while working
+    // with async operations.
+    //
+    // ### Example
+    //
+    //      this.get('#/', function() {
+    //        // initialize the RenderContext
+    //        // Even though `load()` executes async, the next `then()`
+    //        // wont execute until the load finishes
+    //        this.load('myfile.txt')
+    //            .then(function(content) {
+    //              // the first argument to then is the content of the
+    //              // prev operation
+    //              $('#main').html(content);
+    //            });
+    //      });
+    //
+    then: function(callback) {
+      if (_isFunction(callback)) {
+        var context = this;
+        if (this.waiting) {
+          this.callbacks.push(callback);
+        } else {
+          this.wait();
+          setTimeout(function() {
+            var returned = callback.apply(context, [context.content, context.previous_content]);
+            if (returned !== false) {
+              context.next(returned);
+            }
+          }, 13);
+        }
+      }
+      return this;
+    },
+
+    // Pause the `RenderContext` queue. Combined with `next()` allows for async
+    // operations.
+    //
+    // ### Example
+    //
+    //        this.get('#/', function() {
+    //          this.load('mytext.json')
+    //              .then(function(content) {
+    //                var context = this,
+    //                    data    = JSON.parse(content);
+    //                // pause execution
+    //                context.wait();
+    //                // post to a url
+    //                $.post(data.url, {}, function(response) {
+    //                  context.next(JSON.parse(response));
+    //                });
+    //              })
+    //              .then(function(data) {
+    //                // data is json from the previous post
+    //                $('#message').text(data.status);
+    //              });
+    //        });
+    wait: function() {
+      this.waiting = true;
+    },
+
+    // Resume the queue, setting `content` to be used in the next operation.
+    // See `wait()` for an example.
+    next: function(content) {
+      this.waiting = false;
+      if (typeof content !== 'undefined') {
+        this.previous_content = this.content;
+        this.content = content;
+      }
+      if (this.callbacks.length > 0) {
+        this.then(this.callbacks.shift());
+      }
+    },
+
+    // Load a template into the context.
+    // The `location` can either be a string specifiying the remote path to the
+    // file, a jQuery object, or a DOM element.
+    //
+    // No interpolation happens by default, the content is stored in
+    // `content`.
+    //
+    // In the case of a path, unless the option `{cache: false}` is passed the
+    // data is stored in the app's `templateCache()`.
+    //
+    // If a jQuery or DOM object is passed the `innerHTML` of the node is pulled in.
+    // This is useful for nesting templates as part of the initial page load wrapped
+    // in invisible elements or `<script>` tags. With template paths, the template
+    // engine is looked up by the extension. For DOM/jQuery embedded templates,
+    // this isnt possible, so there are a couple of options:
+    //
+    //  * pass an `{engine:}` option.
+    //  * define the engine in the `data-engine` attribute of the passed node.
+    //  * just store the raw template data and use `interpolate()` manually
+    //
+    // If a `callback` is passed it is executed after the template load.
+    load: function(location, options, callback) {
+      var context = this;
+      return this.then(function() {
+        var should_cache, cached;
+        if (_isFunction(options)) {
+          callback = options;
+          options = {};
+        } else {
+          options = $.extend({}, options);
+        }
+        if (callback) { this.then(callback); }
+        if (typeof location === 'string') {
+          // its a path
+          should_cache = !(options.cache === false);
+          delete options.cache;
+          if (options.engine) {
+            context.next_engine = options.engine;
+            delete options.engine;
+          }
+          if (should_cache && (cached = this.event_context.app.templateCache(location))) {
+            return cached;
+          }
+          this.wait();
+          $.ajax($.extend({
+            url: location,
+            data: {},
+            type: 'get',
+            success: function(data) {
+              if (should_cache) {
+                context.event_context.app.templateCache(location, data);
+              }
+              context.next(data);
+            }
+          }, options));
+          return false;
+        } else {
+          // its a dom/jQuery
+          if (location.nodeType) {
+            return location.innerHTML;
+          }
+          if (location.selector) {
+            // its a jQuery
+            context.next_engine = location.attr('data-engine');
+            if (options.clone === false) {
+              return location.remove()[0].innerHTML.toString();
+            } else {
+              return location[0].innerHTML.toString();
+            }
+          }
+        }
+      });
+    },
+
+    // `load()` a template and then `interpolate()` it with data.
+    //
+    // ### Example
+    //
+    //      this.get('#/', function() {
+    //        this.render('mytemplate.template', {name: 'test'});
+    //      });
+    //
+    render: function(location, data, callback) {
+      if (_isFunction(location) && !data) {
+        return this.then(location);
+      } else {
+        return this.load(location).interpolate(data, location).then(callback);
+      }
+    },
+
+    // itterates over an array, applying the callback for each item item. the
+    // callback takes the same style of arguments as `jQuery.each()` (index, item).
+    // The return value of each callback is collected as a single string and stored
+    // as `content` to be used in the next iteration of the `RenderContext`.
+    collect: function(array, callback) {
+      var context = this;
+      return this.then(function() {
+        var contents = "";
+        $.each(array, function(i, item) {
+          var returned = callback.apply(context, [i, item]);
+          contents += returned;
+          return returned;
+        });
+        return contents;
+      });
+    },
+
+    // loads a template, and then interpolates it for each item in the `data`
+    // array.
+    renderEach: function(location, name, data, callback) {
+      if (_isArray(name)) {
+        callback = data;
+        data = name;
+        name = null;
+      }
+      if (!data && _isArray(this.content)) {
+        data = this.content;
+      }
+      return this.load(location).collect(data, function(i, value) {
+        var idata = {};
+        name ? (idata[name] = value) : (idata = value);
+        return this.event_context.interpolate(this.content, idata, location);
+      });
+    },
+
+    // uses the previous loaded `content` and the `data` object to interpolate
+    // a template. `engine` defines the templating/interpolation method/engine
+    // that should be used. If `engine` is not passed, the `next_engine` is
+    // used. If `retain` is `true`, the final interpolated data is appended to
+    // the `previous_content` instead of just replacing it.
+    interpolate: function(data, engine, retain) {
+      var context = this;
+      return this.then(function(content, prev) {
+        if (this.next_engine) {
+          engine = this.next_engine;
+          this.next_engine = false;
+        }
+        var rendered = context.event_context.interpolate(content, data, engine);
+        return retain ? prev + rendered : rendered;
+      });
+    },
+
+    // executes `EventContext#swap()` with the `content`
+    swap: function() {
+      return this.then(function(content) {
+        this.event_context.swap(content);
+      }).trigger('changed', {});
+    },
+
+    // Same usage as `jQuery.fn.appendTo()` but uses `then()` to ensure order
+    appendTo: function(selector) {
+      return this.then(function(content) {
+        $(selector).append(content);
+      }).trigger('changed', {});
+    },
+
+    // Same usage as `jQuery.fn.prependTo()` but uses `then()` to ensure order
+    prependTo: function(selector) {
+      return this.then(function(content) {
+        $(selector).prepend(content);
+      }).trigger('changed', {});
+    },
+
+    // Replaces the `$(selector)` using `html()` with the previously loaded
+    // `content`
+    replace: function(selector) {
+      return this.then(function(content) {
+        $(selector).html(content);
+      }).trigger('changed', {});
+    },
+
+    // trigger the event in the order of the event context. Same semantics
+    // as `Sammy.EventContext#trigger()`. If data is ommitted, `content`
+    // is sent as `{content: content}`
+    trigger: function(name, data) {
+      return this.then(function(content) {
+        if (typeof data == 'undefined') { data = {content: content}; }
+        this.event_context.trigger(name, data);
+      });
+    }
+
+  });
+
+  // `Sammy.EventContext` objects are created every time a route is run or a
+  // bound event is triggered. The callbacks for these events are evaluated within a `Sammy.EventContext`
+  // This within these callbacks the special methods of `EventContext` are available.
+  //
+  // ### Example
+  //
+  //  $.sammy(function() {
+  //    // The context here is this Sammy.Application
+  //    this.get('#/:name', function() {
+  //      // The context here is a new Sammy.EventContext
+  //      if (this.params['name'] == 'sammy') {
+  //        this.partial('name.html.erb', {name: 'Sammy'});
+  //      } else {
+  //        this.redirect('#/somewhere-else')
+  //      }
+  //    });
+  //  });
+  //
+  // Initialize a new EventContext
+  //
+  // ### Arguments
+  //
+  // * `app` The `Sammy.Application` this event is called within.
+  // * `verb` The verb invoked to run this context/route.
+  // * `path` The string path invoked to run this context/route.
+  // * `params` An Object of optional params to pass to the context. Is converted
+  //   to a `Sammy.Object`.
+  // * `target` a DOM element that the event that holds this context originates
+  //   from. For post, put and del routes, this is the form element that triggered
+  //   the route.
+  //
+  Sammy.EventContext = function(app, verb, path, params, target) {
+    this.app    = app;
+    this.verb   = verb;
+    this.path   = path;
+    this.params = new Sammy.Object(params);
+    this.target = target;
+  };
+
+  Sammy.EventContext.prototype = $.extend({}, Sammy.Object.prototype, {
+
+    // A shortcut to the app's `$element()`
+    $element: function() {
+      return this.app.$element();
+    },
+
+    // Look up a templating engine within the current app and context.
+    // `engine` can be one of the following:
+    //
+    // * a function: should conform to `function(content, data) { return interploated; }`
+    // * a template path: 'template.ejs', looks up the extension to match to
+    //   the `ejs()` helper
+    // * a string referering to the helper: "mustache" => `mustache()`
+    //
+    // If no engine is found, use the app's default `template_engine`
+    //
+    engineFor: function(engine) {
+      var context = this, engine_match;
+      // if path is actually an engine function just return it
+      if (_isFunction(engine)) { return engine; }
+      // lookup engine name by path extension
+      engine = engine.toString();
+      if ((engine_match = engine.match(/\.([^\.]+)$/))) {
+        engine = engine_match[1];
+      }
+      // set the engine to the default template engine if no match is found
+      if (engine && _isFunction(context[engine])) {
+        return context[engine];
+      }
+      if (context.app.template_engine) {
+        return this.engineFor(context.app.template_engine);
+      }
+      return function(content, data) { return content; };
+    },
+
+    // using the template `engine` found with `engineFor()`, interpolate the
+    // `data` into `content`
+    interpolate: function(content, data, engine) {
+      return this.engineFor(engine).apply(this, [content, data]);
+    },
+
+    // Create and return a `Sammy.RenderContext` calling `render()` on it.
+    // Loads the template and interpolate the data, however does not actual
+    // place it in the DOM.
+    //
+    // ### Example
+    //
+    //      // mytemplate.mustache <div class="name">{{name}}</div>
+    //      render('mytemplate.mustache', {name: 'quirkey'});
+    //      // sets the `content` to <div class="name">quirkey</div>
+    //      render('mytemplate.mustache', {name: 'quirkey'})
+    //        .appendTo('ul');
+    //      // appends the rendered content to $('ul')
+    //
+    render: function(location, data, callback) {
+      return new Sammy.RenderContext(this).render(location, data, callback);
+    },
+
+    // create a new `Sammy.RenderContext` calling `load()` with `location` and
+    // `options`. Called without interpolation or placement, this allows for
+    // preloading/caching the templates.
+    load: function(location, options, callback) {
+      return new Sammy.RenderContext(this).load(location, options, callback);
+    },
+
+    // `render()` the the `location` with `data` and then `swap()` the
+    // app's `$element` with the rendered content.
+    partial: function(location, data) {
+      return this.render(location, data).swap();
+    },
+
+    // Changes the location of the current window. If `to` begins with
+    // '#' it only changes the document's hash. If passed more than 1 argument
+    // redirect will join them together with forward slashes.
+    //
+    // ### Example
+    //
+    //      redirect('#/other/route');
+    //      // equivilent to
+    //      redirect('#', 'other', 'route');
+    //
+    redirect: function() {
+      var to, args = _makeArray(arguments),
+          current_location = this.app.getLocation();
+      if (args.length > 1) {
+        args.unshift('/');
+        to = this.join.apply(this, args);
+      } else {
+        to = args[0];
+      }
+      this.trigger('redirect', {to: to});
+      this.app.last_location = this.path;
+      this.app.setLocation(to);
+      if (current_location == to) {
+        this.app.trigger('location-changed');
+      }
+    },
+
+    // Triggers events on `app` within the current context.
+    trigger: function(name, data) {
+      if (typeof data == 'undefined') { data = {}; }
+      if (!data.context) { data.context = this; }
+      return this.app.trigger(name, data);
+    },
+
+    // A shortcut to app's `eventNamespace()`
+    eventNamespace: function() {
+      return this.app.eventNamespace();
+    },
+
+    // A shortcut to app's `swap()`
+    swap: function(contents) {
+      return this.app.swap(contents);
+    },
+
+    // Raises a possible `notFound()` error for the current path.
+    notFound: function() {
+      return this.app.notFound(this.verb, this.path);
+    },
+
+    // //=> Sammy.EventContext: get #/ {}
+    toString: function() {
+      return "Sammy.EventContext: " + [this.verb, this.path, this.params].join(' ');
+    }
+
+  });
+
+  // An alias to Sammy
+  $.sammy = window.Sammy = Sammy;
+
+})(jQuery);


[5/9] first commit

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/jquery-1.4.4.min.js
----------------------------------------------------------------------
diff --git a/attachments/jquery-1.4.4.min.js b/attachments/jquery-1.4.4.min.js
new file mode 100644
index 0000000..8f3ca2e
--- /dev/null
+++ b/attachments/jquery-1.4.4.min.js
@@ -0,0 +1,167 @@
+/*!
+ * jQuery JavaScript Library v1.4.4
+ * http://jquery.com/
+ *
+ * Copyright 2010, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2010, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Thu Nov 11 19:04:53 2010 -0500
+ */
+(function(E,B){function ka(a,b,d){if(d===B&&a.nodeType===1){d=a.getAttribute("data-"+b);if(typeof d==="string"){try{d=d==="true"?true:d==="false"?false:d==="null"?null:!c.isNaN(d)?parseFloat(d):Ja.test(d)?c.parseJSON(d):d}catch(e){}c.data(a,b,d)}else d=B}return d}function U(){return false}function ca(){return true}function la(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function Ka(a){var b,d,e,f,h,l,k,o,x,r,A,C=[];f=[];h=c.data(this,this.nodeType?"events":"__events__");if(typeof h==="function")h=
+h.events;if(!(a.liveFired===this||!h||!h.live||a.button&&a.type==="click")){if(a.namespace)A=RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)");a.liveFired=this;var J=h.live.slice(0);for(k=0;k<J.length;k++){h=J[k];h.origType.replace(X,"")===a.type?f.push(h.selector):J.splice(k--,1)}f=c(a.target).closest(f,a.currentTarget);o=0;for(x=f.length;o<x;o++){r=f[o];for(k=0;k<J.length;k++){h=J[k];if(r.selector===h.selector&&(!A||A.test(h.namespace))){l=r.elem;e=null;if(h.preType==="mouseenter"||
+h.preType==="mouseleave"){a.type=h.preType;e=c(a.relatedTarget).closest(h.selector)[0]}if(!e||e!==l)C.push({elem:l,handleObj:h,level:r.level})}}}o=0;for(x=C.length;o<x;o++){f=C[o];if(d&&f.level>d)break;a.currentTarget=f.elem;a.data=f.handleObj.data;a.handleObj=f.handleObj;A=f.handleObj.origHandler.apply(f.elem,arguments);if(A===false||a.isPropagationStopped()){d=f.level;if(A===false)b=false;if(a.isImmediatePropagationStopped())break}}return b}}function Y(a,b){return(a&&a!=="*"?a+".":"")+b.replace(La,
+"`").replace(Ma,"&")}function ma(a,b,d){if(c.isFunction(b))return c.grep(a,function(f,h){return!!b.call(f,h,f)===d});else if(b.nodeType)return c.grep(a,function(f){return f===b===d});else if(typeof b==="string"){var e=c.grep(a,function(f){return f.nodeType===1});if(Na.test(b))return c.filter(b,e,!d);else b=c.filter(b,e)}return c.grep(a,function(f){return c.inArray(f,b)>=0===d})}function na(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var e=c.data(a[d++]),f=c.data(this,
+e);if(e=e&&e.events){delete f.handle;f.events={};for(var h in e)for(var l in e[h])c.event.add(this,h,e[h][l],e[h][l].data)}}})}function Oa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function oa(a,b,d){var e=b==="width"?a.offsetWidth:a.offsetHeight;if(d==="border")return e;c.each(b==="width"?Pa:Qa,function(){d||(e-=parseFloat(c.css(a,"padding"+this))||0);if(d==="margin")e+=parseFloat(c.css(a,
+"margin"+this))||0;else e-=parseFloat(c.css(a,"border"+this+"Width"))||0});return e}function da(a,b,d,e){if(c.isArray(b)&&b.length)c.each(b,function(f,h){d||Ra.test(a)?e(a,h):da(a+"["+(typeof h==="object"||c.isArray(h)?f:"")+"]",h,d,e)});else if(!d&&b!=null&&typeof b==="object")c.isEmptyObject(b)?e(a,""):c.each(b,function(f,h){da(a+"["+f+"]",h,d,e)});else e(a,b)}function S(a,b){var d={};c.each(pa.concat.apply([],pa.slice(0,b)),function(){d[this]=a});return d}function qa(a){if(!ea[a]){var b=c("<"+
+a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d==="")d="block";ea[a]=d}return ea[a]}function fa(a){return c.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var t=E.document,c=function(){function a(){if(!b.isReady){try{t.documentElement.doScroll("left")}catch(j){setTimeout(a,1);return}b.ready()}}var b=function(j,s){return new b.fn.init(j,s)},d=E.jQuery,e=E.$,f,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,l=/\S/,k=/^\s+/,o=/\s+$/,x=/\W/,r=/\d/,A=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,
+C=/^[\],:{}\s]*$/,J=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,w=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,I=/(?:^|:|,)(?:\s*\[)+/g,L=/(webkit)[ \/]([\w.]+)/,g=/(opera)(?:.*version)?[ \/]([\w.]+)/,i=/(msie) ([\w.]+)/,n=/(mozilla)(?:.*? rv:([\w.]+))?/,m=navigator.userAgent,p=false,q=[],u,y=Object.prototype.toString,F=Object.prototype.hasOwnProperty,M=Array.prototype.push,N=Array.prototype.slice,O=String.prototype.trim,D=Array.prototype.indexOf,R={};b.fn=b.prototype={init:function(j,
+s){var v,z,H;if(!j)return this;if(j.nodeType){this.context=this[0]=j;this.length=1;return this}if(j==="body"&&!s&&t.body){this.context=t;this[0]=t.body;this.selector="body";this.length=1;return this}if(typeof j==="string")if((v=h.exec(j))&&(v[1]||!s))if(v[1]){H=s?s.ownerDocument||s:t;if(z=A.exec(j))if(b.isPlainObject(s)){j=[t.createElement(z[1])];b.fn.attr.call(j,s,true)}else j=[H.createElement(z[1])];else{z=b.buildFragment([v[1]],[H]);j=(z.cacheable?z.fragment.cloneNode(true):z.fragment).childNodes}return b.merge(this,
+j)}else{if((z=t.getElementById(v[2]))&&z.parentNode){if(z.id!==v[2])return f.find(j);this.length=1;this[0]=z}this.context=t;this.selector=j;return this}else if(!s&&!x.test(j)){this.selector=j;this.context=t;j=t.getElementsByTagName(j);return b.merge(this,j)}else return!s||s.jquery?(s||f).find(j):b(s).find(j);else if(b.isFunction(j))return f.ready(j);if(j.selector!==B){this.selector=j.selector;this.context=j.context}return b.makeArray(j,this)},selector:"",jquery:"1.4.4",length:0,size:function(){return this.length},
+toArray:function(){return N.call(this,0)},get:function(j){return j==null?this.toArray():j<0?this.slice(j)[0]:this[j]},pushStack:function(j,s,v){var z=b();b.isArray(j)?M.apply(z,j):b.merge(z,j);z.prevObject=this;z.context=this.context;if(s==="find")z.selector=this.selector+(this.selector?" ":"")+v;else if(s)z.selector=this.selector+"."+s+"("+v+")";return z},each:function(j,s){return b.each(this,j,s)},ready:function(j){b.bindReady();if(b.isReady)j.call(t,b);else q&&q.push(j);return this},eq:function(j){return j===
+-1?this.slice(j):this.slice(j,+j+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(N.apply(this,arguments),"slice",N.call(arguments).join(","))},map:function(j){return this.pushStack(b.map(this,function(s,v){return j.call(s,v,s)}))},end:function(){return this.prevObject||b(null)},push:M,sort:[].sort,splice:[].splice};b.fn.init.prototype=b.fn;b.extend=b.fn.extend=function(){var j,s,v,z,H,G=arguments[0]||{},K=1,Q=arguments.length,ga=false;
+if(typeof G==="boolean"){ga=G;G=arguments[1]||{};K=2}if(typeof G!=="object"&&!b.isFunction(G))G={};if(Q===K){G=this;--K}for(;K<Q;K++)if((j=arguments[K])!=null)for(s in j){v=G[s];z=j[s];if(G!==z)if(ga&&z&&(b.isPlainObject(z)||(H=b.isArray(z)))){if(H){H=false;v=v&&b.isArray(v)?v:[]}else v=v&&b.isPlainObject(v)?v:{};G[s]=b.extend(ga,v,z)}else if(z!==B)G[s]=z}return G};b.extend({noConflict:function(j){E.$=e;if(j)E.jQuery=d;return b},isReady:false,readyWait:1,ready:function(j){j===true&&b.readyWait--;
+if(!b.readyWait||j!==true&&!b.isReady){if(!t.body)return setTimeout(b.ready,1);b.isReady=true;if(!(j!==true&&--b.readyWait>0))if(q){var s=0,v=q;for(q=null;j=v[s++];)j.call(t,b);b.fn.trigger&&b(t).trigger("ready").unbind("ready")}}},bindReady:function(){if(!p){p=true;if(t.readyState==="complete")return setTimeout(b.ready,1);if(t.addEventListener){t.addEventListener("DOMContentLoaded",u,false);E.addEventListener("load",b.ready,false)}else if(t.attachEvent){t.attachEvent("onreadystatechange",u);E.attachEvent("onload",
+b.ready);var j=false;try{j=E.frameElement==null}catch(s){}t.documentElement.doScroll&&j&&a()}}},isFunction:function(j){return b.type(j)==="function"},isArray:Array.isArray||function(j){return b.type(j)==="array"},isWindow:function(j){return j&&typeof j==="object"&&"setInterval"in j},isNaN:function(j){return j==null||!r.test(j)||isNaN(j)},type:function(j){return j==null?String(j):R[y.call(j)]||"object"},isPlainObject:function(j){if(!j||b.type(j)!=="object"||j.nodeType||b.isWindow(j))return false;if(j.constructor&&
+!F.call(j,"constructor")&&!F.call(j.constructor.prototype,"isPrototypeOf"))return false;for(var s in j);return s===B||F.call(j,s)},isEmptyObject:function(j){for(var s in j)return false;return true},error:function(j){throw j;},parseJSON:function(j){if(typeof j!=="string"||!j)return null;j=b.trim(j);if(C.test(j.replace(J,"@").replace(w,"]").replace(I,"")))return E.JSON&&E.JSON.parse?E.JSON.parse(j):(new Function("return "+j))();else b.error("Invalid JSON: "+j)},noop:function(){},globalEval:function(j){if(j&&
+l.test(j)){var s=t.getElementsByTagName("head")[0]||t.documentElement,v=t.createElement("script");v.type="text/javascript";if(b.support.scriptEval)v.appendChild(t.createTextNode(j));else v.text=j;s.insertBefore(v,s.firstChild);s.removeChild(v)}},nodeName:function(j,s){return j.nodeName&&j.nodeName.toUpperCase()===s.toUpperCase()},each:function(j,s,v){var z,H=0,G=j.length,K=G===B||b.isFunction(j);if(v)if(K)for(z in j){if(s.apply(j[z],v)===false)break}else for(;H<G;){if(s.apply(j[H++],v)===false)break}else if(K)for(z in j){if(s.call(j[z],
+z,j[z])===false)break}else for(v=j[0];H<G&&s.call(v,H,v)!==false;v=j[++H]);return j},trim:O?function(j){return j==null?"":O.call(j)}:function(j){return j==null?"":j.toString().replace(k,"").replace(o,"")},makeArray:function(j,s){var v=s||[];if(j!=null){var z=b.type(j);j.length==null||z==="string"||z==="function"||z==="regexp"||b.isWindow(j)?M.call(v,j):b.merge(v,j)}return v},inArray:function(j,s){if(s.indexOf)return s.indexOf(j);for(var v=0,z=s.length;v<z;v++)if(s[v]===j)return v;return-1},merge:function(j,
+s){var v=j.length,z=0;if(typeof s.length==="number")for(var H=s.length;z<H;z++)j[v++]=s[z];else for(;s[z]!==B;)j[v++]=s[z++];j.length=v;return j},grep:function(j,s,v){var z=[],H;v=!!v;for(var G=0,K=j.length;G<K;G++){H=!!s(j[G],G);v!==H&&z.push(j[G])}return z},map:function(j,s,v){for(var z=[],H,G=0,K=j.length;G<K;G++){H=s(j[G],G,v);if(H!=null)z[z.length]=H}return z.concat.apply([],z)},guid:1,proxy:function(j,s,v){if(arguments.length===2)if(typeof s==="string"){v=j;j=v[s];s=B}else if(s&&!b.isFunction(s)){v=
+s;s=B}if(!s&&j)s=function(){return j.apply(v||this,arguments)};if(j)s.guid=j.guid=j.guid||s.guid||b.guid++;return s},access:function(j,s,v,z,H,G){var K=j.length;if(typeof s==="object"){for(var Q in s)b.access(j,Q,s[Q],z,H,v);return j}if(v!==B){z=!G&&z&&b.isFunction(v);for(Q=0;Q<K;Q++)H(j[Q],s,z?v.call(j[Q],Q,H(j[Q],s)):v,G);return j}return K?H(j[0],s):B},now:function(){return(new Date).getTime()},uaMatch:function(j){j=j.toLowerCase();j=L.exec(j)||g.exec(j)||i.exec(j)||j.indexOf("compatible")<0&&n.exec(j)||
+[];return{browser:j[1]||"",version:j[2]||"0"}},browser:{}});b.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(j,s){R["[object "+s+"]"]=s.toLowerCase()});m=b.uaMatch(m);if(m.browser){b.browser[m.browser]=true;b.browser.version=m.version}if(b.browser.webkit)b.browser.safari=true;if(D)b.inArray=function(j,s){return D.call(s,j)};if(!/\s/.test("\u00a0")){k=/^[\s\xA0]+/;o=/[\s\xA0]+$/}f=b(t);if(t.addEventListener)u=function(){t.removeEventListener("DOMContentLoaded",u,
+false);b.ready()};else if(t.attachEvent)u=function(){if(t.readyState==="complete"){t.detachEvent("onreadystatechange",u);b.ready()}};return E.jQuery=E.$=b}();(function(){c.support={};var a=t.documentElement,b=t.createElement("script"),d=t.createElement("div"),e="script"+c.now();d.style.display="none";d.innerHTML="   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";var f=d.getElementsByTagName("*"),h=d.getElementsByTagName("a")[0],l=t.createElement("select"),
+k=l.appendChild(t.createElement("option"));if(!(!f||!f.length||!h)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(h.getAttribute("style")),hrefNormalized:h.getAttribute("href")==="/a",opacity:/^0.55$/.test(h.style.opacity),cssFloat:!!h.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:k.selected,deleteExpando:true,optDisabled:false,checkClone:false,
+scriptEval:false,noCloneEvent:true,boxModel:null,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableHiddenOffsets:true};l.disabled=true;c.support.optDisabled=!k.disabled;b.type="text/javascript";try{b.appendChild(t.createTextNode("window."+e+"=1;"))}catch(o){}a.insertBefore(b,a.firstChild);if(E[e]){c.support.scriptEval=true;delete E[e]}try{delete b.test}catch(x){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function r(){c.support.noCloneEvent=
+false;d.detachEvent("onclick",r)});d.cloneNode(true).fireEvent("onclick")}d=t.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=t.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var r=t.createElement("div");r.style.width=r.style.paddingLeft="1px";t.body.appendChild(r);c.boxModel=c.support.boxModel=r.offsetWidth===2;if("zoom"in r.style){r.style.display="inline";r.style.zoom=
+1;c.support.inlineBlockNeedsLayout=r.offsetWidth===2;r.style.display="";r.innerHTML="<div style='width:4px;'></div>";c.support.shrinkWrapBlocks=r.offsetWidth!==2}r.innerHTML="<table><tr><td style='padding:0;display:none'></td><td>t</td></tr></table>";var A=r.getElementsByTagName("td");c.support.reliableHiddenOffsets=A[0].offsetHeight===0;A[0].style.display="";A[1].style.display="none";c.support.reliableHiddenOffsets=c.support.reliableHiddenOffsets&&A[0].offsetHeight===0;r.innerHTML="";t.body.removeChild(r).style.display=
+"none"});a=function(r){var A=t.createElement("div");r="on"+r;var C=r in A;if(!C){A.setAttribute(r,"return;");C=typeof A[r]==="function"}return C};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=f=h=null}})();var ra={},Ja=/^(?:\{.*\}|\[.*\])$/;c.extend({cache:{},uuid:0,expando:"jQuery"+c.now(),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},data:function(a,b,d){if(c.acceptData(a)){a=a==E?ra:a;var e=a.nodeType,f=e?a[c.expando]:null,h=
+c.cache;if(!(e&&!f&&typeof b==="string"&&d===B)){if(e)f||(a[c.expando]=f=++c.uuid);else h=a;if(typeof b==="object")if(e)h[f]=c.extend(h[f],b);else c.extend(h,b);else if(e&&!h[f])h[f]={};a=e?h[f]:h;if(d!==B)a[b]=d;return typeof b==="string"?a[b]:a}}},removeData:function(a,b){if(c.acceptData(a)){a=a==E?ra:a;var d=a.nodeType,e=d?a[c.expando]:a,f=c.cache,h=d?f[e]:e;if(b){if(h){delete h[b];d&&c.isEmptyObject(h)&&c.removeData(a)}}else if(d&&c.support.deleteExpando)delete a[c.expando];else if(a.removeAttribute)a.removeAttribute(c.expando);
+else if(d)delete f[e];else for(var l in a)delete a[l]}},acceptData:function(a){if(a.nodeName){var b=c.noData[a.nodeName.toLowerCase()];if(b)return!(b===true||a.getAttribute("classid")!==b)}return true}});c.fn.extend({data:function(a,b){var d=null;if(typeof a==="undefined"){if(this.length){var e=this[0].attributes,f;d=c.data(this[0]);for(var h=0,l=e.length;h<l;h++){f=e[h].name;if(f.indexOf("data-")===0){f=f.substr(5);ka(this[0],f,d[f])}}}return d}else if(typeof a==="object")return this.each(function(){c.data(this,
+a)});var k=a.split(".");k[1]=k[1]?"."+k[1]:"";if(b===B){d=this.triggerHandler("getData"+k[1]+"!",[k[0]]);if(d===B&&this.length){d=c.data(this[0],a);d=ka(this[0],a,d)}return d===B&&k[1]?this.data(k[0]):d}else return this.each(function(){var o=c(this),x=[k[0],b];o.triggerHandler("setData"+k[1]+"!",x);c.data(this,a,b);o.triggerHandler("changeData"+k[1]+"!",x)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var e=
+c.data(a,b);if(!d)return e||[];if(!e||c.isArray(d))e=c.data(a,b,c.makeArray(d));else e.push(d);return e}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),e=d.shift();if(e==="inprogress")e=d.shift();if(e){b==="fx"&&d.unshift("inprogress");e.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===B)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,
+a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var sa=/[\n\t]/g,ha=/\s+/,Sa=/\r/g,Ta=/^(?:href|src|style)$/,Ua=/^(?:button|input)$/i,Va=/^(?:button|input|object|select|textarea)$/i,Wa=/^a(?:rea)?$/i,ta=/^(?:radio|checkbox)$/i;c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",
+colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};c.fn.extend({attr:function(a,b){return c.access(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(x){var r=c(this);r.addClass(a.call(this,x,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ha),d=0,e=this.length;d<e;d++){var f=this[d];if(f.nodeType===
+1)if(f.className){for(var h=" "+f.className+" ",l=f.className,k=0,o=b.length;k<o;k++)if(h.indexOf(" "+b[k]+" ")<0)l+=" "+b[k];f.className=c.trim(l)}else f.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(o){var x=c(this);x.removeClass(a.call(this,o,x.attr("class")))});if(a&&typeof a==="string"||a===B)for(var b=(a||"").split(ha),d=0,e=this.length;d<e;d++){var f=this[d];if(f.nodeType===1&&f.className)if(a){for(var h=(" "+f.className+" ").replace(sa," "),
+l=0,k=b.length;l<k;l++)h=h.replace(" "+b[l]+" "," ");f.className=c.trim(h)}else f.className=""}return this},toggleClass:function(a,b){var d=typeof a,e=typeof b==="boolean";if(c.isFunction(a))return this.each(function(f){var h=c(this);h.toggleClass(a.call(this,f,h.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var f,h=0,l=c(this),k=b,o=a.split(ha);f=o[h++];){k=e?k:!l.hasClass(f);l[k?"addClass":"removeClass"](f)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,
+"__className__",this.className);this.className=this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(sa," ").indexOf(a)>-1)return true;return false},val:function(a){if(!arguments.length){var b=this[0];if(b){if(c.nodeName(b,"option")){var d=b.attributes.value;return!d||d.specified?b.value:b.text}if(c.nodeName(b,"select")){var e=b.selectedIndex;d=[];var f=b.options;b=b.type==="select-one";
+if(e<0)return null;var h=b?e:0;for(e=b?e+1:f.length;h<e;h++){var l=f[h];if(l.selected&&(c.support.optDisabled?!l.disabled:l.getAttribute("disabled")===null)&&(!l.parentNode.disabled||!c.nodeName(l.parentNode,"optgroup"))){a=c(l).val();if(b)return a;d.push(a)}}return d}if(ta.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Sa,"")}return B}var k=c.isFunction(a);return this.each(function(o){var x=c(this),r=a;if(this.nodeType===1){if(k)r=
+a.call(this,o,x.val());if(r==null)r="";else if(typeof r==="number")r+="";else if(c.isArray(r))r=c.map(r,function(C){return C==null?"":C+""});if(c.isArray(r)&&ta.test(this.type))this.checked=c.inArray(x.val(),r)>=0;else if(c.nodeName(this,"select")){var A=c.makeArray(r);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),A)>=0});if(!A.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},
+attr:function(a,b,d,e){if(!a||a.nodeType===3||a.nodeType===8)return B;if(e&&b in c.attrFn)return c(a)[b](d);e=a.nodeType!==1||!c.isXMLDoc(a);var f=d!==B;b=e&&c.props[b]||b;var h=Ta.test(b);if((b in a||a[b]!==B)&&e&&!h){if(f){b==="type"&&Ua.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");if(d===null)a.nodeType===1&&a.removeAttribute(b);else a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&
+b.specified?b.value:Va.test(a.nodeName)||Wa.test(a.nodeName)&&a.href?0:B;return a[b]}if(!c.support.style&&e&&b==="style"){if(f)a.style.cssText=""+d;return a.style.cssText}f&&a.setAttribute(b,""+d);if(!a.attributes[b]&&a.hasAttribute&&!a.hasAttribute(b))return B;a=!c.support.hrefNormalized&&e&&h?a.getAttribute(b,2):a.getAttribute(b);return a===null?B:a}});var X=/\.(.*)$/,ia=/^(?:textarea|input|select)$/i,La=/\./g,Ma=/ /g,Xa=/[^\w\s.|`]/g,Ya=function(a){return a.replace(Xa,"\\$&")},ua={focusin:0,focusout:0};
+c.event={add:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(c.isWindow(a)&&a!==E&&!a.frameElement)a=E;if(d===false)d=U;else if(!d)return;var f,h;if(d.handler){f=d;d=f.handler}if(!d.guid)d.guid=c.guid++;if(h=c.data(a)){var l=a.nodeType?"events":"__events__",k=h[l],o=h.handle;if(typeof k==="function"){o=k.handle;k=k.events}else if(!k){a.nodeType||(h[l]=h=function(){});h.events=k={}}if(!o)h.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,
+arguments):B};o.elem=a;b=b.split(" ");for(var x=0,r;l=b[x++];){h=f?c.extend({},f):{handler:d,data:e};if(l.indexOf(".")>-1){r=l.split(".");l=r.shift();h.namespace=r.slice(0).sort().join(".")}else{r=[];h.namespace=""}h.type=l;if(!h.guid)h.guid=d.guid;var A=k[l],C=c.event.special[l]||{};if(!A){A=k[l]=[];if(!C.setup||C.setup.call(a,e,r,o)===false)if(a.addEventListener)a.addEventListener(l,o,false);else a.attachEvent&&a.attachEvent("on"+l,o)}if(C.add){C.add.call(a,h);if(!h.handler.guid)h.handler.guid=
+d.guid}A.push(h);c.event.global[l]=true}a=null}}},global:{},remove:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(d===false)d=U;var f,h,l=0,k,o,x,r,A,C,J=a.nodeType?"events":"__events__",w=c.data(a),I=w&&w[J];if(w&&I){if(typeof I==="function"){w=I;I=I.events}if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(f in I)c.event.remove(a,f+b)}else{for(b=b.split(" ");f=b[l++];){r=f;k=f.indexOf(".")<0;o=[];if(!k){o=f.split(".");f=o.shift();x=RegExp("(^|\\.)"+
+c.map(o.slice(0).sort(),Ya).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(A=I[f])if(d){r=c.event.special[f]||{};for(h=e||0;h<A.length;h++){C=A[h];if(d.guid===C.guid){if(k||x.test(C.namespace)){e==null&&A.splice(h--,1);r.remove&&r.remove.call(a,C)}if(e!=null)break}}if(A.length===0||e!=null&&A.length===1){if(!r.teardown||r.teardown.call(a,o)===false)c.removeEvent(a,f,w.handle);delete I[f]}}else for(h=0;h<A.length;h++){C=A[h];if(k||x.test(C.namespace)){c.event.remove(a,r,C.handler,h);A.splice(h--,1)}}}if(c.isEmptyObject(I)){if(b=
+w.handle)b.elem=null;delete w.events;delete w.handle;if(typeof w==="function")c.removeData(a,J);else c.isEmptyObject(w)&&c.removeData(a)}}}}},trigger:function(a,b,d,e){var f=a.type||a;if(!e){a=typeof a==="object"?a[c.expando]?a:c.extend(c.Event(f),a):c.Event(f);if(f.indexOf("!")>=0){a.type=f=f.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[f]&&c.each(c.cache,function(){this.events&&this.events[f]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===
+8)return B;a.result=B;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(e=d.nodeType?c.data(d,"handle"):(c.data(d,"__events__")||{}).handle)&&e.apply(d,b);e=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+f]&&d["on"+f].apply(d,b)===false){a.result=false;a.preventDefault()}}catch(h){}if(!a.isPropagationStopped()&&e)c.event.trigger(a,b,e,true);else if(!a.isDefaultPrevented()){var l;e=a.target;var k=f.replace(X,""),o=c.nodeName(e,"a")&&k===
+"click",x=c.event.special[k]||{};if((!x._default||x._default.call(d,a)===false)&&!o&&!(e&&e.nodeName&&c.noData[e.nodeName.toLowerCase()])){try{if(e[k]){if(l=e["on"+k])e["on"+k]=null;c.event.triggered=true;e[k]()}}catch(r){}if(l)e["on"+k]=l;c.event.triggered=false}}},handle:function(a){var b,d,e,f;d=[];var h=c.makeArray(arguments);a=h[0]=c.event.fix(a||E.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;if(!b){e=a.type.split(".");a.type=e.shift();d=e.slice(0).sort();e=RegExp("(^|\\.)"+
+d.join("\\.(?:.*\\.)?")+"(\\.|$)")}a.namespace=a.namespace||d.join(".");f=c.data(this,this.nodeType?"events":"__events__");if(typeof f==="function")f=f.events;d=(f||{})[a.type];if(f&&d){d=d.slice(0);f=0;for(var l=d.length;f<l;f++){var k=d[f];if(b||e.test(k.namespace)){a.handler=k.handler;a.data=k.data;a.handleObj=k;k=k.handler.apply(this,h);if(k!==B){a.result=k;if(k===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+fix:function(a){if(a[c.expando])return a;var b=a;a=c.Event(b);for(var d=this.props.length,e;d;){e=this.props[--d];a[e]=b[e]}if(!a.target)a.target=a.srcElement||t;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=t.documentElement;d=t.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
+d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(a.which==null&&(a.charCode!=null||a.keyCode!=null))a.which=a.charCode!=null?a.charCode:a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==B)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,Y(a.origType,a.selector),c.extend({},a,{handler:Ka,guid:a.handler.guid}))},remove:function(a){c.event.remove(this,
+Y(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,d){if(c.isWindow(this))this.onbeforeunload=d},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};c.removeEvent=t.removeEventListener?function(a,b,d){a.removeEventListener&&a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent&&a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=a;this.type=a.type}else this.type=a;this.timeStamp=
+c.now();this[c.expando]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=ca;var a=this.originalEvent;if(a)if(a.preventDefault)a.preventDefault();else a.returnValue=false},stopPropagation:function(){this.isPropagationStopped=ca;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=ca;this.stopPropagation()},isDefaultPrevented:U,isPropagationStopped:U,isImmediatePropagationStopped:U};
+var va=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},wa=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?wa:va,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?wa:va)}}});if(!c.support.submitBubbles)c.event.special.submit={setup:function(){if(this.nodeName.toLowerCase()!==
+"form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length){a.liveFired=B;return la("submit",this,arguments)}});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13){a.liveFired=B;return la("submit",this,arguments)}})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};if(!c.support.changeBubbles){var V,
+xa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(e){return e.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},Z=function(a,b){var d=a.target,e,f;if(!(!ia.test(d.nodeName)||d.readOnly)){e=c.data(d,"_change_data");f=xa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",f);if(!(e===B||f===e))if(e!=null||f){a.type="change";a.liveFired=
+B;return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:Z,beforedeactivate:Z,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return Z.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return Z.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,"_change_data",xa(a))}},setup:function(){if(this.type===
+"file")return false;for(var a in V)c.event.add(this,a+".specialChange",V[a]);return ia.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return ia.test(this.nodeName)}};V=c.event.special.change.filters;V.focus=V.beforeactivate}t.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(e){e=c.event.fix(e);e.type=b;return c.event.trigger(e,null,e.target)}c.event.special[b]={setup:function(){ua[b]++===0&&t.addEventListener(a,d,true)},teardown:function(){--ua[b]===
+0&&t.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,e,f){if(typeof d==="object"){for(var h in d)this[b](h,e,d[h],f);return this}if(c.isFunction(e)||e===false){f=e;e=B}var l=b==="one"?c.proxy(f,function(o){c(this).unbind(o,l);return f.apply(this,arguments)}):f;if(d==="unload"&&b!=="one")this.one(d,e,f);else{h=0;for(var k=this.length;h<k;h++)c.event.add(this[h],d,l,e)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&!a.preventDefault)for(var d in a)this.unbind(d,
+a[d]);else{d=0;for(var e=this.length;d<e;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,e){return this.live(b,d,e,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){var d=c.Event(a);d.preventDefault();d.stopPropagation();c.event.trigger(d,b,this[0]);return d.result}},toggle:function(a){for(var b=arguments,d=
+1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(e){var f=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,f+1);e.preventDefault();return b[f].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var ya={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,e,f,h){var l,k=0,o,x,r=h||this.selector;h=h?this:c(this.context);if(typeof d===
+"object"&&!d.preventDefault){for(l in d)h[b](l,e,d[l],r);return this}if(c.isFunction(e)){f=e;e=B}for(d=(d||"").split(" ");(l=d[k++])!=null;){o=X.exec(l);x="";if(o){x=o[0];l=l.replace(X,"")}if(l==="hover")d.push("mouseenter"+x,"mouseleave"+x);else{o=l;if(l==="focus"||l==="blur"){d.push(ya[l]+x);l+=x}else l=(ya[l]||l)+x;if(b==="live"){x=0;for(var A=h.length;x<A;x++)c.event.add(h[x],"live."+Y(l,r),{data:e,selector:r,handler:f,origType:l,origHandler:f,preType:o})}else h.unbind("live."+Y(l,r),f)}}return this}});
+c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){c.fn[b]=function(d,e){if(e==null){e=d;d=null}return arguments.length>0?this.bind(b,d,e):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});E.attachEvent&&!E.addEventListener&&c(E).bind("unload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});
+(function(){function a(g,i,n,m,p,q){p=0;for(var u=m.length;p<u;p++){var y=m[p];if(y){var F=false;for(y=y[g];y;){if(y.sizcache===n){F=m[y.sizset];break}if(y.nodeType===1&&!q){y.sizcache=n;y.sizset=p}if(y.nodeName.toLowerCase()===i){F=y;break}y=y[g]}m[p]=F}}}function b(g,i,n,m,p,q){p=0;for(var u=m.length;p<u;p++){var y=m[p];if(y){var F=false;for(y=y[g];y;){if(y.sizcache===n){F=m[y.sizset];break}if(y.nodeType===1){if(!q){y.sizcache=n;y.sizset=p}if(typeof i!=="string"){if(y===i){F=true;break}}else if(k.filter(i,
+[y]).length>0){F=y;break}}y=y[g]}m[p]=F}}}var d=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,h=false,l=true;[0,0].sort(function(){l=false;return 0});var k=function(g,i,n,m){n=n||[];var p=i=i||t;if(i.nodeType!==1&&i.nodeType!==9)return[];if(!g||typeof g!=="string")return n;var q,u,y,F,M,N=true,O=k.isXML(i),D=[],R=g;do{d.exec("");if(q=d.exec(R)){R=q[3];D.push(q[1]);if(q[2]){F=q[3];
+break}}}while(q);if(D.length>1&&x.exec(g))if(D.length===2&&o.relative[D[0]])u=L(D[0]+D[1],i);else for(u=o.relative[D[0]]?[i]:k(D.shift(),i);D.length;){g=D.shift();if(o.relative[g])g+=D.shift();u=L(g,u)}else{if(!m&&D.length>1&&i.nodeType===9&&!O&&o.match.ID.test(D[0])&&!o.match.ID.test(D[D.length-1])){q=k.find(D.shift(),i,O);i=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]}if(i){q=m?{expr:D.pop(),set:C(m)}:k.find(D.pop(),D.length===1&&(D[0]==="~"||D[0]==="+")&&i.parentNode?i.parentNode:i,O);u=q.expr?k.filter(q.expr,
+q.set):q.set;if(D.length>0)y=C(u);else N=false;for(;D.length;){q=M=D.pop();if(o.relative[M])q=D.pop();else M="";if(q==null)q=i;o.relative[M](y,q,O)}}else y=[]}y||(y=u);y||k.error(M||g);if(f.call(y)==="[object Array]")if(N)if(i&&i.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&k.contains(i,y[g])))n.push(u[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&n.push(u[g]);else n.push.apply(n,y);else C(y,n);if(F){k(F,p,n,m);k.uniqueSort(n)}return n};k.uniqueSort=function(g){if(w){h=
+l;g.sort(w);if(h)for(var i=1;i<g.length;i++)g[i]===g[i-1]&&g.splice(i--,1)}return g};k.matches=function(g,i){return k(g,null,null,i)};k.matchesSelector=function(g,i){return k(i,null,null,[g]).length>0};k.find=function(g,i,n){var m;if(!g)return[];for(var p=0,q=o.order.length;p<q;p++){var u,y=o.order[p];if(u=o.leftMatch[y].exec(g)){var F=u[1];u.splice(1,1);if(F.substr(F.length-1)!=="\\"){u[1]=(u[1]||"").replace(/\\/g,"");m=o.find[y](u,i,n);if(m!=null){g=g.replace(o.match[y],"");break}}}}m||(m=i.getElementsByTagName("*"));
+return{set:m,expr:g}};k.filter=function(g,i,n,m){for(var p,q,u=g,y=[],F=i,M=i&&i[0]&&k.isXML(i[0]);g&&i.length;){for(var N in o.filter)if((p=o.leftMatch[N].exec(g))!=null&&p[2]){var O,D,R=o.filter[N];D=p[1];q=false;p.splice(1,1);if(D.substr(D.length-1)!=="\\"){if(F===y)y=[];if(o.preFilter[N])if(p=o.preFilter[N](p,F,n,y,m,M)){if(p===true)continue}else q=O=true;if(p)for(var j=0;(D=F[j])!=null;j++)if(D){O=R(D,p,j,F);var s=m^!!O;if(n&&O!=null)if(s)q=true;else F[j]=false;else if(s){y.push(D);q=true}}if(O!==
+B){n||(F=y);g=g.replace(o.match[N],"");if(!q)return[];break}}}if(g===u)if(q==null)k.error(g);else break;u=g}return F};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var o=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/,
+POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},relative:{"+":function(g,i){var n=typeof i==="string",m=n&&!/\W/.test(i);n=n&&!m;if(m)i=i.toLowerCase();m=0;for(var p=g.length,q;m<p;m++)if(q=g[m]){for(;(q=q.previousSibling)&&q.nodeType!==1;);g[m]=n||q&&q.nodeName.toLowerCase()===
+i?q||false:q===i}n&&k.filter(i,g,true)},">":function(g,i){var n,m=typeof i==="string",p=0,q=g.length;if(m&&!/\W/.test(i))for(i=i.toLowerCase();p<q;p++){if(n=g[p]){n=n.parentNode;g[p]=n.nodeName.toLowerCase()===i?n:false}}else{for(;p<q;p++)if(n=g[p])g[p]=m?n.parentNode:n.parentNode===i;m&&k.filter(i,g,true)}},"":function(g,i,n){var m,p=e++,q=b;if(typeof i==="string"&&!/\W/.test(i)){m=i=i.toLowerCase();q=a}q("parentNode",i,p,g,m,n)},"~":function(g,i,n){var m,p=e++,q=b;if(typeof i==="string"&&!/\W/.test(i)){m=
+i=i.toLowerCase();q=a}q("previousSibling",i,p,g,m,n)}},find:{ID:function(g,i,n){if(typeof i.getElementById!=="undefined"&&!n)return(g=i.getElementById(g[1]))&&g.parentNode?[g]:[]},NAME:function(g,i){if(typeof i.getElementsByName!=="undefined"){for(var n=[],m=i.getElementsByName(g[1]),p=0,q=m.length;p<q;p++)m[p].getAttribute("name")===g[1]&&n.push(m[p]);return n.length===0?null:n}},TAG:function(g,i){return i.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,i,n,m,p,q){g=" "+g[1].replace(/\\/g,
+"")+" ";if(q)return g;q=0;for(var u;(u=i[q])!=null;q++)if(u)if(p^(u.className&&(" "+u.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))n||m.push(u);else if(n)i[q]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var i=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=i[1]+(i[2]||1)-0;g[3]=i[3]-0}g[0]=e++;return g},ATTR:function(g,i,n,
+m,p,q){i=g[1].replace(/\\/g,"");if(!q&&o.attrMap[i])g[1]=o.attrMap[i];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,i,n,m,p){if(g[1]==="not")if((d.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,i);else{g=k.filter(g[3],i,n,true^p);n||m.push.apply(m,g);return false}else if(o.match.POS.test(g[0])||o.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===
+true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,i,n){return!!k(n[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===
+g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,i){return i===0},last:function(g,i,n,m){return i===m.length-1},even:function(g,i){return i%2===0},odd:function(g,i){return i%2===1},lt:function(g,i,n){return i<n[3]-0},gt:function(g,i,n){return i>n[3]-0},nth:function(g,i,n){return n[3]-
+0===i},eq:function(g,i,n){return n[3]-0===i}},filter:{PSEUDO:function(g,i,n,m){var p=i[1],q=o.filters[p];if(q)return q(g,n,i,m);else if(p==="contains")return(g.textContent||g.innerText||k.getText([g])||"").indexOf(i[3])>=0;else if(p==="not"){i=i[3];n=0;for(m=i.length;n<m;n++)if(i[n]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+p)},CHILD:function(g,i){var n=i[1],m=g;switch(n){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(n===
+"first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":n=i[2];var p=i[3];if(n===1&&p===0)return true;var q=i[0],u=g.parentNode;if(u&&(u.sizcache!==q||!g.nodeIndex)){var y=0;for(m=u.firstChild;m;m=m.nextSibling)if(m.nodeType===1)m.nodeIndex=++y;u.sizcache=q}m=g.nodeIndex-p;return n===0?m===0:m%n===0&&m/n>=0}},ID:function(g,i){return g.nodeType===1&&g.getAttribute("id")===i},TAG:function(g,i){return i==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===
+i},CLASS:function(g,i){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(i)>-1},ATTR:function(g,i){var n=i[1];n=o.attrHandle[n]?o.attrHandle[n](g):g[n]!=null?g[n]:g.getAttribute(n);var m=n+"",p=i[2],q=i[4];return n==null?p==="!=":p==="="?m===q:p==="*="?m.indexOf(q)>=0:p==="~="?(" "+m+" ").indexOf(q)>=0:!q?m&&n!==false:p==="!="?m!==q:p==="^="?m.indexOf(q)===0:p==="$="?m.substr(m.length-q.length)===q:p==="|="?m===q||m.substr(0,q.length+1)===q+"-":false},POS:function(g,i,n,m){var p=o.setFilters[i[2]];
+if(p)return p(g,n,i,m)}}},x=o.match.POS,r=function(g,i){return"\\"+(i-0+1)},A;for(A in o.match){o.match[A]=RegExp(o.match[A].source+/(?![^\[]*\])(?![^\(]*\))/.source);o.leftMatch[A]=RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[A].source.replace(/\\(\d+)/g,r))}var C=function(g,i){g=Array.prototype.slice.call(g,0);if(i){i.push.apply(i,g);return i}return g};try{Array.prototype.slice.call(t.documentElement.childNodes,0)}catch(J){C=function(g,i){var n=0,m=i||[];if(f.call(g)==="[object Array]")Array.prototype.push.apply(m,
+g);else if(typeof g.length==="number")for(var p=g.length;n<p;n++)m.push(g[n]);else for(;g[n];n++)m.push(g[n]);return m}}var w,I;if(t.documentElement.compareDocumentPosition)w=function(g,i){if(g===i){h=true;return 0}if(!g.compareDocumentPosition||!i.compareDocumentPosition)return g.compareDocumentPosition?-1:1;return g.compareDocumentPosition(i)&4?-1:1};else{w=function(g,i){var n,m,p=[],q=[];n=g.parentNode;m=i.parentNode;var u=n;if(g===i){h=true;return 0}else if(n===m)return I(g,i);else if(n){if(!m)return 1}else return-1;
+for(;u;){p.unshift(u);u=u.parentNode}for(u=m;u;){q.unshift(u);u=u.parentNode}n=p.length;m=q.length;for(u=0;u<n&&u<m;u++)if(p[u]!==q[u])return I(p[u],q[u]);return u===n?I(g,q[u],-1):I(p[u],i,1)};I=function(g,i,n){if(g===i)return n;for(g=g.nextSibling;g;){if(g===i)return-1;g=g.nextSibling}return 1}}k.getText=function(g){for(var i="",n,m=0;g[m];m++){n=g[m];if(n.nodeType===3||n.nodeType===4)i+=n.nodeValue;else if(n.nodeType!==8)i+=k.getText(n.childNodes)}return i};(function(){var g=t.createElement("div"),
+i="script"+(new Date).getTime(),n=t.documentElement;g.innerHTML="<a name='"+i+"'/>";n.insertBefore(g,n.firstChild);if(t.getElementById(i)){o.find.ID=function(m,p,q){if(typeof p.getElementById!=="undefined"&&!q)return(p=p.getElementById(m[1]))?p.id===m[1]||typeof p.getAttributeNode!=="undefined"&&p.getAttributeNode("id").nodeValue===m[1]?[p]:B:[]};o.filter.ID=function(m,p){var q=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&q&&q.nodeValue===p}}n.removeChild(g);
+n=g=null})();(function(){var g=t.createElement("div");g.appendChild(t.createComment(""));if(g.getElementsByTagName("*").length>0)o.find.TAG=function(i,n){var m=n.getElementsByTagName(i[1]);if(i[1]==="*"){for(var p=[],q=0;m[q];q++)m[q].nodeType===1&&p.push(m[q]);m=p}return m};g.innerHTML="<a href='#'></a>";if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")o.attrHandle.href=function(i){return i.getAttribute("href",2)};g=null})();t.querySelectorAll&&
+function(){var g=k,i=t.createElement("div");i.innerHTML="<p class='TEST'></p>";if(!(i.querySelectorAll&&i.querySelectorAll(".TEST").length===0)){k=function(m,p,q,u){p=p||t;m=m.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!u&&!k.isXML(p))if(p.nodeType===9)try{return C(p.querySelectorAll(m),q)}catch(y){}else if(p.nodeType===1&&p.nodeName.toLowerCase()!=="object"){var F=p.getAttribute("id"),M=F||"__sizzle__";F||p.setAttribute("id",M);try{return C(p.querySelectorAll("#"+M+" "+m),q)}catch(N){}finally{F||
+p.removeAttribute("id")}}return g(m,p,q,u)};for(var n in g)k[n]=g[n];i=null}}();(function(){var g=t.documentElement,i=g.matchesSelector||g.mozMatchesSelector||g.webkitMatchesSelector||g.msMatchesSelector,n=false;try{i.call(t.documentElement,"[test!='']:sizzle")}catch(m){n=true}if(i)k.matchesSelector=function(p,q){q=q.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(p))try{if(n||!o.match.PSEUDO.test(q)&&!/!=/.test(q))return i.call(p,q)}catch(u){}return k(q,null,null,[p]).length>0}})();(function(){var g=
+t.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){o.order.splice(1,0,"CLASS");o.find.CLASS=function(i,n,m){if(typeof n.getElementsByClassName!=="undefined"&&!m)return n.getElementsByClassName(i[1])};g=null}}})();k.contains=t.documentElement.contains?function(g,i){return g!==i&&(g.contains?g.contains(i):true)}:t.documentElement.compareDocumentPosition?
+function(g,i){return!!(g.compareDocumentPosition(i)&16)}:function(){return false};k.isXML=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false};var L=function(g,i){for(var n,m=[],p="",q=i.nodeType?[i]:i;n=o.match.PSEUDO.exec(g);){p+=n[0];g=g.replace(o.match.PSEUDO,"")}g=o.relative[g]?g+"*":g;n=0;for(var u=q.length;n<u;n++)k(g,q[n],m);return k.filter(p,m)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=k.getText;c.isXMLDoc=k.isXML;
+c.contains=k.contains})();var Za=/Until$/,$a=/^(?:parents|prevUntil|prevAll)/,ab=/,/,Na=/^.[^:#\[\.,]*$/,bb=Array.prototype.slice,cb=c.expr.match.POS;c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,e=0,f=this.length;e<f;e++){d=b.length;c.find(a,this[e],b);if(e>0)for(var h=d;h<b.length;h++)for(var l=0;l<d;l++)if(b[l]===b[h]){b.splice(h--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,e=b.length;d<e;d++)if(c.contains(this,b[d]))return true})},
+not:function(a){return this.pushStack(ma(this,a,false),"not",a)},filter:function(a){return this.pushStack(ma(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){var d=[],e,f,h=this[0];if(c.isArray(a)){var l,k={},o=1;if(h&&a.length){e=0;for(f=a.length;e<f;e++){l=a[e];k[l]||(k[l]=c.expr.match.POS.test(l)?c(l,b||this.context):l)}for(;h&&h.ownerDocument&&h!==b;){for(l in k){e=k[l];if(e.jquery?e.index(h)>-1:c(h).is(e))d.push({selector:l,elem:h,level:o})}h=
+h.parentNode;o++}}return d}l=cb.test(a)?c(a,b||this.context):null;e=0;for(f=this.length;e<f;e++)for(h=this[e];h;)if(l?l.index(h)>-1:c.find.matchesSelector(h,a)){d.push(h);break}else{h=h.parentNode;if(!h||!h.ownerDocument||h===b)break}d=d.length>1?c.unique(d):d;return this.pushStack(d,"closest",a)},index:function(a){if(!a||typeof a==="string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var d=typeof a==="string"?c(a,b||this.context):
+c.makeArray(a),e=c.merge(this.get(),d);return this.pushStack(!d[0]||!d[0].parentNode||d[0].parentNode.nodeType===11||!e[0]||!e[0].parentNode||e[0].parentNode.nodeType===11?e:c.unique(e))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,
+2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,
+b){c.fn[a]=function(d,e){var f=c.map(this,b,d);Za.test(a)||(e=d);if(e&&typeof e==="string")f=c.filter(e,f);f=this.length>1?c.unique(f):f;if((this.length>1||ab.test(e))&&$a.test(a))f=f.reverse();return this.pushStack(f,a,bb.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return b.length===1?c.find.matchesSelector(b[0],a)?[b[0]]:[]:c.find.matches(a,b)},dir:function(a,b,d){var e=[];for(a=a[b];a&&a.nodeType!==9&&(d===B||a.nodeType!==1||!c(a).is(d));){a.nodeType===1&&
+e.push(a);a=a[b]}return e},nth:function(a,b,d){b=b||1;for(var e=0;a;a=a[d])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var za=/ jQuery\d+="(?:\d+|null)"/g,$=/^\s+/,Aa=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Ba=/<([\w:]+)/,db=/<tbody/i,eb=/<|&#?\w+;/,Ca=/<(?:script|object|embed|option|style)/i,Da=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/\=([^="'>\s]+\/)>/g,P={option:[1,
+"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};P.optgroup=P.option;P.tbody=P.tfoot=P.colgroup=P.caption=P.thead;P.th=P.td;if(!c.support.htmlSerialize)P._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
+c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==B)return this.empty().append((this[0]&&this[0].ownerDocument||t).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
+wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
+prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
+this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,e;(e=this[d])!=null;d++)if(!a||c.filter(a,[e]).length){if(!b&&e.nodeType===1){c.cleanData(e.getElementsByTagName("*"));c.cleanData([e])}e.parentNode&&e.parentNode.removeChild(e)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
+return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,e=this.ownerDocument;if(!d){d=e.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(za,"").replace(fb,'="$1">').replace($,"")],e)[0]}else return this.cloneNode(true)});if(a===true){na(this,b);na(this.find("*"),b.find("*"))}return b},html:function(a){if(a===B)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(za,""):null;
+else if(typeof a==="string"&&!Ca.test(a)&&(c.support.leadingWhitespace||!$.test(a))&&!P[(Ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Aa,"<$1></$2>");try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(e){this.empty().append(a)}}else c.isFunction(a)?this.each(function(f){var h=c(this);h.html(a.call(this,f,h.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=
+c(this),e=d.html();d.replaceWith(a.call(this,b,e))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){var e,f,h,l=a[0],k=[];if(!c.support.checkClone&&arguments.length===3&&typeof l==="string"&&Da.test(l))return this.each(function(){c(this).domManip(a,
+b,d,true)});if(c.isFunction(l))return this.each(function(x){var r=c(this);a[0]=l.call(this,x,b?r.html():B);r.domManip(a,b,d)});if(this[0]){e=l&&l.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:c.buildFragment(a,this,k);h=e.fragment;if(f=h.childNodes.length===1?h=h.firstChild:h.firstChild){b=b&&c.nodeName(f,"tr");f=0;for(var o=this.length;f<o;f++)d.call(b?c.nodeName(this[f],"table")?this[f].getElementsByTagName("tbody")[0]||this[f].appendChild(this[f].ownerDocument.createElement("tbody")):
+this[f]:this[f],f>0||e.cacheable||this.length>1?h.cloneNode(true):h)}k.length&&c.each(k,Oa)}return this}});c.buildFragment=function(a,b,d){var e,f,h;b=b&&b[0]?b[0].ownerDocument||b[0]:t;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===t&&!Ca.test(a[0])&&(c.support.checkClone||!Da.test(a[0]))){f=true;if(h=c.fragments[a[0]])if(h!==1)e=h}if(!e){e=b.createDocumentFragment();c.clean(a,b,e,d)}if(f)c.fragments[a[0]]=h?e:1;return{fragment:e,cacheable:f}};c.fragments={};c.each({appendTo:"append",
+prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var e=[];d=c(d);var f=this.length===1&&this[0].parentNode;if(f&&f.nodeType===11&&f.childNodes.length===1&&d.length===1){d[b](this[0]);return this}else{f=0;for(var h=d.length;f<h;f++){var l=(f>0?this.clone(true):this).get();c(d[f])[b](l);e=e.concat(l)}return this.pushStack(e,a,d.selector)}}});c.extend({clean:function(a,b,d,e){b=b||t;if(typeof b.createElement==="undefined")b=b.ownerDocument||
+b[0]&&b[0].ownerDocument||t;for(var f=[],h=0,l;(l=a[h])!=null;h++){if(typeof l==="number")l+="";if(l){if(typeof l==="string"&&!eb.test(l))l=b.createTextNode(l);else if(typeof l==="string"){l=l.replace(Aa,"<$1></$2>");var k=(Ba.exec(l)||["",""])[1].toLowerCase(),o=P[k]||P._default,x=o[0],r=b.createElement("div");for(r.innerHTML=o[1]+l+o[2];x--;)r=r.lastChild;if(!c.support.tbody){x=db.test(l);k=k==="table"&&!x?r.firstChild&&r.firstChild.childNodes:o[1]==="<table>"&&!x?r.childNodes:[];for(o=k.length-
+1;o>=0;--o)c.nodeName(k[o],"tbody")&&!k[o].childNodes.length&&k[o].parentNode.removeChild(k[o])}!c.support.leadingWhitespace&&$.test(l)&&r.insertBefore(b.createTextNode($.exec(l)[0]),r.firstChild);l=r.childNodes}if(l.nodeType)f.push(l);else f=c.merge(f,l)}}if(d)for(h=0;f[h];h++)if(e&&c.nodeName(f[h],"script")&&(!f[h].type||f[h].type.toLowerCase()==="text/javascript"))e.push(f[h].parentNode?f[h].parentNode.removeChild(f[h]):f[h]);else{f[h].nodeType===1&&f.splice.apply(f,[h+1,0].concat(c.makeArray(f[h].getElementsByTagName("script"))));
+d.appendChild(f[h])}return f},cleanData:function(a){for(var b,d,e=c.cache,f=c.event.special,h=c.support.deleteExpando,l=0,k;(k=a[l])!=null;l++)if(!(k.nodeName&&c.noData[k.nodeName.toLowerCase()]))if(d=k[c.expando]){if((b=e[d])&&b.events)for(var o in b.events)f[o]?c.event.remove(k,o):c.removeEvent(k,o,b.handle);if(h)delete k[c.expando];else k.removeAttribute&&k.removeAttribute(c.expando);delete e[d]}}});var Ea=/alpha\([^)]*\)/i,gb=/opacity=([^)]*)/,hb=/-([a-z])/ig,ib=/([A-Z])/g,Fa=/^-?\d+(?:px)?$/i,
+jb=/^-?\d/,kb={position:"absolute",visibility:"hidden",display:"block"},Pa=["Left","Right"],Qa=["Top","Bottom"],W,Ga,aa,lb=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){if(arguments.length===2&&b===B)return this;return c.access(this,a,b,true,function(d,e,f){return f!==B?c.style(d,e,f):c.css(d,e)})};c.extend({cssHooks:{opacity:{get:function(a,b){if(b){var d=W(a,"opacity","opacity");return d===""?"1":d}else return a.style.opacity}}},cssNumber:{zIndex:true,fontWeight:true,opacity:true,
+zoom:true,lineHeight:true},cssProps:{"float":c.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,d,e){if(!(!a||a.nodeType===3||a.nodeType===8||!a.style)){var f,h=c.camelCase(b),l=a.style,k=c.cssHooks[h];b=c.cssProps[h]||h;if(d!==B){if(!(typeof d==="number"&&isNaN(d)||d==null)){if(typeof d==="number"&&!c.cssNumber[h])d+="px";if(!k||!("set"in k)||(d=k.set(a,d))!==B)try{l[b]=d}catch(o){}}}else{if(k&&"get"in k&&(f=k.get(a,false,e))!==B)return f;return l[b]}}},css:function(a,b,d){var e,f=c.camelCase(b),
+h=c.cssHooks[f];b=c.cssProps[f]||f;if(h&&"get"in h&&(e=h.get(a,true,d))!==B)return e;else if(W)return W(a,b,f)},swap:function(a,b,d){var e={},f;for(f in b){e[f]=a.style[f];a.style[f]=b[f]}d.call(a);for(f in b)a.style[f]=e[f]},camelCase:function(a){return a.replace(hb,lb)}});c.curCSS=c.css;c.each(["height","width"],function(a,b){c.cssHooks[b]={get:function(d,e,f){var h;if(e){if(d.offsetWidth!==0)h=oa(d,b,f);else c.swap(d,kb,function(){h=oa(d,b,f)});if(h<=0){h=W(d,b,b);if(h==="0px"&&aa)h=aa(d,b,b);
+if(h!=null)return h===""||h==="auto"?"0px":h}if(h<0||h==null){h=d.style[b];return h===""||h==="auto"?"0px":h}return typeof h==="string"?h:h+"px"}},set:function(d,e){if(Fa.test(e)){e=parseFloat(e);if(e>=0)return e+"px"}else return e}}});if(!c.support.opacity)c.cssHooks.opacity={get:function(a,b){return gb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var d=a.style;d.zoom=1;var e=c.isNaN(b)?"":"alpha(opacity="+b*100+")",f=
+d.filter||"";d.filter=Ea.test(f)?f.replace(Ea,e):d.filter+" "+e}};if(t.defaultView&&t.defaultView.getComputedStyle)Ga=function(a,b,d){var e;d=d.replace(ib,"-$1").toLowerCase();if(!(b=a.ownerDocument.defaultView))return B;if(b=b.getComputedStyle(a,null)){e=b.getPropertyValue(d);if(e===""&&!c.contains(a.ownerDocument.documentElement,a))e=c.style(a,d)}return e};if(t.documentElement.currentStyle)aa=function(a,b){var d,e,f=a.currentStyle&&a.currentStyle[b],h=a.style;if(!Fa.test(f)&&jb.test(f)){d=h.left;
+e=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;h.left=b==="fontSize"?"1em":f||0;f=h.pixelLeft+"px";h.left=d;a.runtimeStyle.left=e}return f===""?"auto":f};W=Ga||aa;if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetHeight;return a.offsetWidth===0&&b===0||!c.support.reliableHiddenOffsets&&(a.style.display||c.css(a,"display"))==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var mb=c.now(),nb=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
+ob=/^(?:select|textarea)/i,pb=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,qb=/^(?:GET|HEAD)$/,Ra=/\[\]$/,T=/\=\?(&|$)/,ja=/\?/,rb=/([?&])_=[^&]*/,sb=/^(\w+:)?\/\/([^\/?#]+)/,tb=/%20/g,ub=/#.*$/,Ha=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!=="string"&&Ha)return Ha.apply(this,arguments);else if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var f=a.slice(e,a.length);a=a.slice(0,e)}e="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b===
+"object"){b=c.param(b,c.ajaxSettings.traditional);e="POST"}var h=this;c.ajax({url:a,type:e,dataType:"html",data:b,complete:function(l,k){if(k==="success"||k==="notmodified")h.html(f?c("<div>").append(l.responseText.replace(nb,"")).find(f):l.responseText);d&&h.each(d,[l.responseText,k,l])}});return this},serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&
+!this.disabled&&(this.checked||ob.test(this.nodeName)||pb.test(this.type))}).map(function(a,b){var d=c(this).val();return d==null?null:c.isArray(d)?c.map(d,function(e){return{name:b.name,value:e}}):{name:b.name,value:d}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:e})},
+getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:e})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return new E.XMLHttpRequest},accepts:{xml:"application/xml, text/xml",html:"text/html",
+script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},ajax:function(a){var b=c.extend(true,{},c.ajaxSettings,a),d,e,f,h=b.type.toUpperCase(),l=qb.test(h);b.url=b.url.replace(ub,"");b.context=a&&a.context!=null?a.context:b;if(b.data&&b.processData&&typeof b.data!=="string")b.data=c.param(b.data,b.traditional);if(b.dataType==="jsonp"){if(h==="GET")T.test(b.url)||(b.url+=(ja.test(b.url)?"&":"?")+(b.jsonp||"callback")+"=?");else if(!b.data||
+!T.test(b.data))b.data=(b.data?b.data+"&":"")+(b.jsonp||"callback")+"=?";b.dataType="json"}if(b.dataType==="json"&&(b.data&&T.test(b.data)||T.test(b.url))){d=b.jsonpCallback||"jsonp"+mb++;if(b.data)b.data=(b.data+"").replace(T,"="+d+"$1");b.url=b.url.replace(T,"="+d+"$1");b.dataType="script";var k=E[d];E[d]=function(m){if(c.isFunction(k))k(m);else{E[d]=B;try{delete E[d]}catch(p){}}f=m;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);r&&r.removeChild(A)}}if(b.dataType==="script"&&b.cache===null)b.cache=
+false;if(b.cache===false&&l){var o=c.now(),x=b.url.replace(rb,"$1_="+o);b.url=x+(x===b.url?(ja.test(b.url)?"&":"?")+"_="+o:"")}if(b.data&&l)b.url+=(ja.test(b.url)?"&":"?")+b.data;b.global&&c.active++===0&&c.event.trigger("ajaxStart");o=(o=sb.exec(b.url))&&(o[1]&&o[1].toLowerCase()!==location.protocol||o[2].toLowerCase()!==location.host);if(b.dataType==="script"&&h==="GET"&&o){var r=t.getElementsByTagName("head")[0]||t.documentElement,A=t.createElement("script");if(b.scriptCharset)A.charset=b.scriptCharset;
+A.src=b.url;if(!d){var C=false;A.onload=A.onreadystatechange=function(){if(!C&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){C=true;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);A.onload=A.onreadystatechange=null;r&&A.parentNode&&r.removeChild(A)}}}r.insertBefore(A,r.firstChild);return B}var J=false,w=b.xhr();if(w){b.username?w.open(h,b.url,b.async,b.username,b.password):w.open(h,b.url,b.async);try{if(b.data!=null&&!l||a&&a.contentType)w.setRequestHeader("Content-Type",
+b.contentType);if(b.ifModified){c.lastModified[b.url]&&w.setRequestHeader("If-Modified-Since",c.lastModified[b.url]);c.etag[b.url]&&w.setRequestHeader("If-None-Match",c.etag[b.url])}o||w.setRequestHeader("X-Requested-With","XMLHttpRequest");w.setRequestHeader("Accept",b.dataType&&b.accepts[b.dataType]?b.accepts[b.dataType]+", */*; q=0.01":b.accepts._default)}catch(I){}if(b.beforeSend&&b.beforeSend.call(b.context,w,b)===false){b.global&&c.active--===1&&c.event.trigger("ajaxStop");w.abort();return false}b.global&&
+c.triggerGlobal(b,"ajaxSend",[w,b]);var L=w.onreadystatechange=function(m){if(!w||w.readyState===0||m==="abort"){J||c.handleComplete(b,w,e,f);J=true;if(w)w.onreadystatechange=c.noop}else if(!J&&w&&(w.readyState===4||m==="timeout")){J=true;w.onreadystatechange=c.noop;e=m==="timeout"?"timeout":!c.httpSuccess(w)?"error":b.ifModified&&c.httpNotModified(w,b.url)?"notmodified":"success";var p;if(e==="success")try{f=c.httpData(w,b.dataType,b)}catch(q){e="parsererror";p=q}if(e==="success"||e==="notmodified")d||
+c.handleSuccess(b,w,e,f);else c.handleError(b,w,e,p);d||c.handleComplete(b,w,e,f);m==="timeout"&&w.abort();if(b.async)w=null}};try{var g=w.abort;w.abort=function(){w&&Function.prototype.call.call(g,w);L("abort")}}catch(i){}b.async&&b.timeout>0&&setTimeout(function(){w&&!J&&L("timeout")},b.timeout);try{w.send(l||b.data==null?null:b.data)}catch(n){c.handleError(b,w,null,n);c.handleComplete(b,w,e,f)}b.async||L();return w}},param:function(a,b){var d=[],e=function(h,l){l=c.isFunction(l)?l():l;d[d.length]=
+encodeURIComponent(h)+"="+encodeURIComponent(l)};if(b===B)b=c.ajaxSettings.traditional;if(c.isArray(a)||a.jquery)c.each(a,function(){e(this.name,this.value)});else for(var f in a)da(f,a[f],b,e);return d.join("&").replace(tb,"+")}});c.extend({active:0,lastModified:{},etag:{},handleError:function(a,b,d,e){a.error&&a.error.call(a.context,b,d,e);a.global&&c.triggerGlobal(a,"ajaxError",[b,a,e])},handleSuccess:function(a,b,d,e){a.success&&a.success.call(a.context,e,d,b);a.global&&c.triggerGlobal(a,"ajaxSuccess",
+[b,a])},handleComplete:function(a,b,d){a.complete&&a.complete.call(a.context,b,d);a.global&&c.triggerGlobal(a,"ajaxComplete",[b,a]);a.global&&c.active--===1&&c.event.trigger("ajaxStop")},triggerGlobal:function(a,b,d){(a.context&&a.context.url==null?c(a.context):c.event).trigger(b,d)},httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===1223}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),
+e=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(e)c.etag[b]=e;return a.status===304},httpData:function(a,b,d){var e=a.getResponseHeader("content-type")||"",f=b==="xml"||!b&&e.indexOf("xml")>=0;a=f?a.responseXML:a.responseText;f&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b==="json"||!b&&e.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&e.indexOf("javascript")>=0)c.globalEval(a);return a}});
+if(E.ActiveXObject)c.ajaxSettings.xhr=function(){if(E.location.protocol!=="file:")try{return new E.XMLHttpRequest}catch(a){}try{return new E.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}};c.support.ajax=!!c.ajaxSettings.xhr();var ea={},vb=/^(?:toggle|show|hide)$/,wb=/^([+\-]=)?([\d+.\-]+)(.*)$/,ba,pa=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b,d){if(a||a===0)return this.animate(S("show",
+3),a,b,d);else{d=0;for(var e=this.length;d<e;d++){a=this[d];b=a.style.display;if(!c.data(a,"olddisplay")&&b==="none")b=a.style.display="";b===""&&c.css(a,"display")==="none"&&c.data(a,"olddisplay",qa(a.nodeName))}for(d=0;d<e;d++){a=this[d];b=a.style.display;if(b===""||b==="none")a.style.display=c.data(a,"olddisplay")||""}return this}},hide:function(a,b,d){if(a||a===0)return this.animate(S("hide",3),a,b,d);else{a=0;for(b=this.length;a<b;a++){d=c.css(this[a],"display");d!=="none"&&c.data(this[a],"olddisplay",
+d)}for(a=0;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b,d){var e=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||e?this.each(function(){var f=e?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(S("toggle",3),a,b,d);return this},fadeTo:function(a,b,d,e){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d,e)},animate:function(a,b,d,e){var f=c.speed(b,
+d,e);if(c.isEmptyObject(a))return this.each(f.complete);return this[f.queue===false?"each":"queue"](function(){var h=c.extend({},f),l,k=this.nodeType===1,o=k&&c(this).is(":hidden"),x=this;for(l in a){var r=c.camelCase(l);if(l!==r){a[r]=a[l];delete a[l];l=r}if(a[l]==="hide"&&o||a[l]==="show"&&!o)return h.complete.call(this);if(k&&(l==="height"||l==="width")){h.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY];if(c.css(this,"display")==="inline"&&c.css(this,"float")==="none")if(c.support.inlineBlockNeedsLayout)if(qa(this.nodeName)===
+"inline")this.style.display="inline-block";else{this.style.display="inline";this.style.zoom=1}else this.style.display="inline-block"}if(c.isArray(a[l])){(h.specialEasing=h.specialEasing||{})[l]=a[l][1];a[l]=a[l][0]}}if(h.overflow!=null)this.style.overflow="hidden";h.curAnim=c.extend({},a);c.each(a,function(A,C){var J=new c.fx(x,h,A);if(vb.test(C))J[C==="toggle"?o?"show":"hide":C](a);else{var w=wb.exec(C),I=J.cur()||0;if(w){var L=parseFloat(w[2]),g=w[3]||"px";if(g!=="px"){c.style(x,A,(L||1)+g);I=(L||
+1)/J.cur()*I;c.style(x,A,I+g)}if(w[1])L=(w[1]==="-="?-1:1)*L+I;J.custom(I,L,g)}else J.custom(I,C,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);this.each(function(){for(var e=d.length-1;e>=0;e--)if(d[e].elem===this){b&&d[e](true);d.splice(e,1)}});b||this.dequeue();return this}});c.each({slideDown:S("show",1),slideUp:S("hide",1),slideToggle:S("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){c.fn[a]=function(d,e,f){return this.animate(b,
+d,e,f)}});c.extend({speed:function(a,b,d){var e=a&&typeof a==="object"?c.extend({},a):{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};e.duration=c.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in c.fx.speeds?c.fx.speeds[e.duration]:c.fx.speeds._default;e.old=e.complete;e.complete=function(){e.queue!==false&&c(this).dequeue();c.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,d,e){return d+e*a},swing:function(a,b,d,e){return(-Math.cos(a*
+Math.PI)/2+0.5)*e+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||c.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a=parseFloat(c.css(this.elem,this.prop));return a&&a>-1E4?a:0},custom:function(a,b,d){function e(l){return f.step(l)}
+var f=this,h=c.fx;this.startTime=c.now();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;this.pos=this.state=0;e.elem=this.elem;if(e()&&c.timers.push(e)&&!ba)ba=setInterval(h.tick,h.interval)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;
+this.custom(this.cur(),0)},step:function(a){var b=c.now(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var e in this.options.curAnim)if(this.options.curAnim[e]!==true)d=false;if(d){if(this.options.overflow!=null&&!c.support.shrinkWrapBlocks){var f=this.elem,h=this.options;c.each(["","X","Y"],function(k,o){f.style["overflow"+o]=h.overflow[k]})}this.options.hide&&c(this.elem).hide();if(this.options.hide||
+this.options.show)for(var l in this.options.curAnim)c.style(this.elem,l,this.options.orig[l]);this.options.complete.call(this.elem)}return false}else{a=b-this.startTime;this.state=a/this.options.duration;b=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||b](this.state,a,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=
+c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||c.fx.stop()},interval:13,stop:function(){clearInterval(ba);ba=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===
+b.elem}).length};var xb=/^t(?:able|d|h)$/i,Ia=/^(?:body|html)$/i;c.fn.offset="getBoundingClientRect"in t.documentElement?function(a){var b=this[0],d;if(a)return this.each(function(l){c.offset.setOffset(this,a,l)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);try{d=b.getBoundingClientRect()}catch(e){}var f=b.ownerDocument,h=f.documentElement;if(!d||!c.contains(h,b))return d||{top:0,left:0};b=f.body;f=fa(f);return{top:d.top+(f.pageYOffset||c.support.boxModel&&
+h.scrollTop||b.scrollTop)-(h.clientTop||b.clientTop||0),left:d.left+(f.pageXOffset||c.support.boxModel&&h.scrollLeft||b.scrollLeft)-(h.clientLeft||b.clientLeft||0)}}:function(a){var b=this[0];if(a)return this.each(function(x){c.offset.setOffset(this,a,x)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d,e=b.offsetParent,f=b.ownerDocument,h=f.documentElement,l=f.body;d=(f=f.defaultView)?f.getComputedStyle(b,null):b.currentStyle;
+for(var k=b.offsetTop,o=b.offsetLeft;(b=b.parentNode)&&b!==l&&b!==h;){if(c.offset.supportsFixedPosition&&d.position==="fixed")break;d=f?f.getComputedStyle(b,null):b.currentStyle;k-=b.scrollTop;o-=b.scrollLeft;if(b===e){k+=b.offsetTop;o+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&xb.test(b.nodeName))){k+=parseFloat(d.borderTopWidth)||0;o+=parseFloat(d.borderLeftWidth)||0}e=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"){k+=
+parseFloat(d.borderTopWidth)||0;o+=parseFloat(d.borderLeftWidth)||0}d=d}if(d.position==="relative"||d.position==="static"){k+=l.offsetTop;o+=l.offsetLeft}if(c.offset.supportsFixedPosition&&d.position==="fixed"){k+=Math.max(h.scrollTop,l.scrollTop);o+=Math.max(h.scrollLeft,l.scrollLeft)}return{top:k,left:o}};c.offset={initialize:function(){var a=t.body,b=t.createElement("div"),d,e,f,h=parseFloat(c.css(a,"marginTop"))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",
+height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";a.insertBefore(b,a.firstChild);d=b.firstChild;e=d.firstChild;f=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=e.offsetTop!==5;this.doesAddBorderForTableAndCells=
+f.offsetTop===5;e.style.position="fixed";e.style.top="20px";this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15;e.style.position=e.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==h;a.removeChild(b);c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.css(a,
+"marginTop"))||0;d+=parseFloat(c.css(a,"marginLeft"))||0}return{top:b,left:d}},setOffset:function(a,b,d){var e=c.css(a,"position");if(e==="static")a.style.position="relative";var f=c(a),h=f.offset(),l=c.css(a,"top"),k=c.css(a,"left"),o=e==="absolute"&&c.inArray("auto",[l,k])>-1;e={};var x={};if(o)x=f.position();l=o?x.top:parseInt(l,10)||0;k=o?x.left:parseInt(k,10)||0;if(c.isFunction(b))b=b.call(a,d,h);if(b.top!=null)e.top=b.top-h.top+l;if(b.left!=null)e.left=b.left-h.left+k;"using"in b?b.using.call(a,
+e):f.css(e)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),e=Ia.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.css(a,"marginTop"))||0;d.left-=parseFloat(c.css(a,"marginLeft"))||0;e.top+=parseFloat(c.css(b[0],"borderTopWidth"))||0;e.left+=parseFloat(c.css(b[0],"borderLeftWidth"))||0;return{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||t.body;a&&!Ia.test(a.nodeName)&&
+c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(e){var f=this[0],h;if(!f)return null;if(e!==B)return this.each(function(){if(h=fa(this))h.scrollTo(!a?e:c(h).scrollLeft(),a?e:c(h).scrollTop());else this[d]=e});else return(h=fa(f))?"pageXOffset"in h?h[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&h.document.documentElement[d]||h.document.body[d]:f[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();
+c.fn["inner"+b]=function(){return this[0]?parseFloat(c.css(this[0],d,"padding")):null};c.fn["outer"+b]=function(e){return this[0]?parseFloat(c.css(this[0],d,e?"margin":"border")):null};c.fn[d]=function(e){var f=this[0];if(!f)return e==null?null:this;if(c.isFunction(e))return this.each(function(l){var k=c(this);k[d](e.call(this,l,k[d]()))});if(c.isWindow(f))return f.document.compatMode==="CSS1Compat"&&f.document.documentElement["client"+b]||f.document.body["client"+b];else if(f.nodeType===9)return Math.max(f.documentElement["client"+
+b],f.body["scroll"+b],f.documentElement["scroll"+b],f.body["offset"+b],f.documentElement["offset"+b]);else if(e===B){f=c.css(f,d);var h=parseFloat(f);return c.isNaN(h)?f:h}else return this.css(d,typeof e==="string"?e:e+"px")}})})(window);

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/layout.css
----------------------------------------------------------------------
diff --git a/attachments/layout.css b/attachments/layout.css
new file mode 100644
index 0000000..8b7b5e2
--- /dev/null
+++ b/attachments/layout.css
@@ -0,0 +1,387 @@
+@import "font/style.css";
+/* ----- mixins ------ */
+/* ----- font ----- */
+html {
+  font-size: 17px;
+  font-family: 'HelveticaNeue-Light', Helvetica, Arial, sans-serif;
+  color: #3b4854;
+}
+h1 {
+  font-size: 1.8em;
+  font-weight: normal;
+}
+h2 {
+  font-size: 1.2em;
+  font-weight: normal;
+}
+/* ----- basic layout ----- */
+body {
+  background: #fff;
+  margin: 0;
+}
+.wrap,
+#tabs {
+  max-width: 1000px;
+  margin: 0 auto;
+  padding: 40px 0;
+}
+.grid {
+  background: url(images/grid.png);
+}
+/* ----- common elements -----*/
+a {
+  color: #4cc2e4;
+  text-decoration: none;
+}
+a.dep-link {
+  padding-right: 7px;
+}
+.spacer,
+.clear {
+  clear: both;
+}
+.button {
+  display: inline-block;
+  background-color: #4cc2e4;
+  margin-left: 8px;
+  padding: 10px 16px;
+  color: #fff;
+  font-size: 1.5em;
+  text-align: center;
+  text-decoration: none;
+  -webkit-transition: background 0.25s linear;
+  -moz-transition: background 0.25s linear;
+  transition: background 0.25s linear;
+  border-bottom: 4px solid #21b2dc;
+}
+.button:hover {
+  background-color: #4cd6fc;
+  color: #fff;
+}
+/* ----- header ---- */
+#header {
+  text-align: left;
+  border-bottom: 3px solid rgba(0, 0, 0, 0.1);
+  position: relative;
+  z-index: 3;
+  margin-bottom: -3px;
+}
+#header .wrap {
+  padding: 20px 0;
+}
+#header a {
+  -webkit-transition: color 0.25s linear;
+  -moz-transition: color 0.25s linear;
+  transition: color 0.25s linear;
+  color: #3b4854;
+  display: inline-block;
+  padding: 6px 0;
+  position: relative;
+}
+#header a:hover {
+  color: #4cc2e4;
+}
+#header a.logo {
+  padding-left: 40px;
+  font-size: 1.2em;
+}
+#header a.logo:before {
+  font-size: 1.5em;
+  position: absolute;
+  left: 0;
+  top: 3px;
+}
+#header #howto {
+  float: right;
+}
+#header #howto a {
+  padding-top: 10px;
+  margin-left: 24px;
+}
+#header #howto a span {
+  position: absolute;
+  top: 0px;
+  left: 0;
+  font-size: 10px;
+  font-weight: 600;
+}
+/* ----- content ---- */
+#content-wrapper {
+  padding-top: 0;
+}
+#content,
+#tabs a,
+#tabs span {
+  background: #fff;
+  padding: 2% 2%;
+  -moz-border-radius: 5px;
+  -webkit-border-radius: 5px;
+  border-radius: 5px;
+  position: relative;
+}
+#content {
+  padding: 4% 2%;
+}
+#tabs {
+  margin-bottom: -7px;
+  padding-bottom: 0;
+}
+#tabs a,
+#tabs span {
+  display: inline-block;
+  padding: 16px 20px 18px;
+  margin: 0 10px 0 0;
+}
+#tabs a {
+  -webkit-transition: background-color 0.25s linear;
+  -moz-transition: background-color 0.25s linear;
+  transition: background-color 0.25s linear;
+  background-color: #4cc2e4;
+  color: #fff;
+}
+#tabs a:hover {
+  background-color: #78d1eb;
+}
+#tabs a.selected {
+  background-color: #fff;
+  color: #3b4854;
+}
+#tabs a.selected:hover {
+  background-color: #fff;
+}
+#search-box {
+  width: auto;
+  margin-bottom: 20px;
+}
+#search-box-input span {
+  line-height: 60px;
+  width: 5%;
+  font-size: 1.5em;
+  font-weight: bold;
+  text-align: center;
+  float: left;
+}
+#search-box-input .button {
+  padding-left: 2%;
+  padding-right: 2%;
+  width: 25%;
+  float: left;
+}
+#search-input {
+  width: auto;
+  min-width: 90%;
+  font-size: 1.5em;
+  padding: 10px 2%;
+  border: none;
+  font-weight: normal;
+  margin: 0 8px 0 0;
+  border: 1px solid #ddd;
+  border-top: 4px #ddd solid;
+}
+#search-input:focus {
+  outline-color: #4cc2e4;
+}
+#browse-anchors a {
+  margin-right: 20px;
+  padding: 3px 5px 3px 5px;
+  background-color: #fff;
+  display: inline-block;
+  background-color: #4cc2e4;
+  margin-right: 8px;
+  padding: 4px 12px;
+  color: #fff;
+  text-align: center;
+  text-decoration: none;
+  -webkit-transition: background 0.25s linear;
+  -moz-transition: background 0.25s linear;
+  transition: background 0.25s linear;
+  border-bottom: 2px solid #21b2dc;
+}
+#browse-anchors a:hover {
+  background-color: #4cd6fc;
+  color: #fff;
+}
+/* ----- footer ---- */
+#footer {
+  height: 40px;
+}
+/* ----- everything else ----- */
+div#results {
+  font-size: 20px;
+  width: 100%;
+  padding-top: 4px;
+}
+div.result {
+  width: 100%;
+}
+div.result-container {
+  padding-bottom: 6px;
+}
+span.result-name {
+  padding-right: 10px;
+}
+span.result-desc {
+  color: #6B6B6B;
+}
+div.result-tags {
+  text-align: right;
+  font-size: 16px;
+  padding-right: 4px;
+  float: right;
+}
+span.tag {
+  padding-left: 6px;
+  cursor: pointer;
+  color: #878787;
+}
+span.desc-term {
+  color: #141414;
+}
+div.package {
+  text-align: center;
+}
+div.package-title {
+  font-size: 45px;
+  float: left;
+}
+div.pkg-link {
+  float: left;
+  padding-top: 20px;
+  margin-left: 30px;
+}
+div#latest-packages {
+  width: 45%;
+  float: left;
+  margin-right: 5%;
+}
+div#top-dep-packages {
+  width: 45%;
+  margin-left: 5%;
+  float: left;
+}
+div.top-title {
+  text-align: center;
+}
+div.top-package {
+  width: 100%;
+}
+div.top-package-title {
+  padding-right: 7px;
+  float: left;
+}
+div.top-package-updated {
+  float: right;
+  text-align: right;
+  padding-right: 15px;
+}
+div.top-package-dep {
+  float: right;
+  text-align: right;
+  padding-right: 15px;
+}
+div.dependencies {
+  width: 80%;
+  text-align: left;
+  padding-left: 10%;
+  padding-right: 10%;
+}
+div.users {
+  width: 80%;
+  text-align: left;
+  padding-left: 10%;
+  padding-right: 10%;
+}
+a.dep {
+  margin-right: 10px;
+}
+a.user {
+  margin-right: 10px;
+}
+div#totals {
+  float: right;
+  position: absolute;
+  top: 10px;
+  right: 10px;
+}
+div.all-package {
+  width: 100%;
+}
+div.all-package-name {
+  width: 40%;
+  padding-right: 2%;
+  float: left;
+}
+div.all-package-desc {
+  width: 50%;
+  float: left;
+}
+div#more-all {
+  cursor: pointer;
+  color: blue;
+}
+div#versions-container {
+  margin-top: 10px;
+  width: 100%;
+}
+div#version-list {
+  float: left;
+  width: 20%;
+}
+div#version-info {
+  float: left;
+  width: 78%;
+  background-color: #B9D3EE;
+  padding: 1% 1% 1% 1%;
+}
+div.version-info-cell {
+  width: 100%;
+}
+div.version-info-key {
+  float: left;
+}
+div.version-info-value {
+  float: right;
+  text-align: right;
+}
+div.version-selected {
+  background-color: #B9D3EE;
+}
+div.version-link {
+  width: 100%;
+  padding: 3px 0px 0px 10px;
+}
+span.expand-tags {
+  padding-left: 10px;
+  font-size: 12px;
+  cursor: pointer;
+  color: #FF1D4E;
+}
+a.tag-val {
+  padding-right: 10px;
+  padding-left: 5px;
+}
+div.all-package-author {
+  width: 30%;
+  float: left;
+}
+div.all-package-auth-list {
+  width: 70%;
+  float: left;
+}
+div.all-package-deps {
+  width: 50%;
+  float: left;
+}
+div.all-package-deps-value {
+  width: 50%;
+  float: left;
+}
+div.tags-pkg-name {
+  float: left;
+  width: 30%;
+  font-size: 30px;
+}
+div.tags-pkg-desc {
+  float: left;
+  width: 70%;
+}


[4/9] first commit

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/layout.less
----------------------------------------------------------------------
diff --git a/attachments/layout.less b/attachments/layout.less
new file mode 100644
index 0000000..1ccef0a
--- /dev/null
+++ b/attachments/layout.less
@@ -0,0 +1,461 @@
+/* ----- mixins ------ */
+
+.border-radius( @radius: 8px ) {
+    -moz-border-radius: @radius;
+    -webkit-border-radius: @radius;
+    border-radius: @radius;
+}
+
+.transition ( @type: all, @sec: 0.25s ) {
+    -webkit-transition: @type @sec linear;
+    -moz-transition: @type @sec linear;
+    transition: @type @sec linear;
+}
+
+@highlight-color: #4cc2e4;
+@font-color: #3b4854;
+
+@import "font/style.css";
+
+/* ----- font ----- */
+
+html {
+    font-size: 17px;
+    font-family: 'HelveticaNeue-Light', Helvetica, Arial, sans-serif;
+    color: @font-color;
+} 
+
+h1 {
+    font-size: 1.8em;
+    font-weight: normal;
+}
+
+h2 {
+    font-size: 1.2em;
+    font-weight: normal;
+}
+
+
+/* ----- basic layout ----- */
+
+body {
+    background: #fff;
+    margin: 0;
+}
+
+.wrap, #tabs {
+    max-width: 1000px;
+    margin: 0 auto;
+    padding: 40px 0;
+}
+
+.grid {
+    background: url(images/grid.png);
+}
+
+
+/* ----- common elements -----*/
+
+a {
+    color: @highlight-color;
+    text-decoration:none;
+}
+
+a.dep-link {
+    padding-right:7px;
+}
+
+.spacer, .clear { 
+    clear:both; 
+}
+
+.button {
+    display: inline-block;
+    background-color: @highlight-color;
+    margin-left: 8px;
+    padding: 10px 16px;
+    color: #fff;
+    font-size: 1.5em;
+    text-align: center;
+    text-decoration: none;
+    .transition( background );
+    border-bottom: 4px solid darken(@highlight-color,10%);
+
+    &:hover {
+        background-color: #4cd6fc;
+        color: #fff;
+    }
+}
+
+
+/* ----- header ---- */
+
+#header {
+    text-align: left;
+    border-bottom: 3px solid rgba(0,0,0,0.1);
+    position: relative;
+    z-index: 3;
+    margin-bottom: -3px;
+
+    .wrap {
+        padding: 20px 0;
+    }
+
+    a {
+        .transition( color );
+        color: @font-color;
+        display: inline-block;
+        padding: 6px 0;
+        position: relative;
+
+        &:hover {
+            color: @highlight-color;
+        }
+    }
+
+    a.logo {
+        padding-left: 40px;
+        font-size: 1.2em;
+
+        &:before {
+            font-size: 1.5em;
+            position: absolute;
+            left: 0;
+            top: 3px;
+        }
+    }
+
+    #howto {
+        float: right;
+
+        a {
+            padding-top: 10px;
+            margin-left: 24px;
+
+            span {
+                position: absolute;
+                top: -0px;
+                left: 0;
+                font-size: 10px;
+                font-weight: 600;
+            }
+        }
+    }
+}
+
+
+/* ----- content ---- */
+
+#content-wrapper {
+    padding-top: 0;
+}
+
+
+#content,
+#tabs a, #tabs span {
+    background: #fff;
+    padding: 2% 2%;
+    .border-radius( 5px );
+    position: relative;
+}
+
+#content {
+    padding: 4% 2%;
+}
+
+#tabs {
+    margin-bottom: -7px;
+    padding-bottom: 0;
+
+    a, span {
+        display: inline-block;
+        padding: 16px 20px 18px;
+        margin: 0 10px 0 0;
+    }
+
+    a {
+        .transition( background-color );
+        background-color: @highlight-color;
+        color: #fff;
+
+        &:hover {
+            background-color: lighten( @highlight-color, 10% );
+        }
+
+        &.selected {
+            background-color: #fff;
+            color: @font-color;
+            &:hover {
+                background-color: #fff;
+            }
+        }
+    }
+}
+
+#search-box {
+    width: auto;
+    margin-bottom: 20px;
+}
+
+#search-box-input {
+    span {
+        line-height: 60px;
+        width: 5%;
+        font-size: 1.5em;
+        font-weight: bold;
+        text-align: center;
+        float: left;
+    }
+
+    .button {
+        padding-left: 2%;
+        padding-right: 2%;
+        width: 25%;
+        float: left;
+    }
+}
+
+#search-input {
+    width: auto;
+    min-width: 90%;
+    font-size: 1.5em;
+    padding: 10px 2%;
+    border: none;
+    font-weight: normal;
+    margin: 0 8px 0 0;
+    border: 1px solid #ddd;
+    border-top: 4px #ddd solid;
+    // float: left;
+
+    &:focus {
+        outline-color: @highlight-color;
+    }
+}
+
+#browse-anchors {
+
+    a {
+        margin-right:20px;
+        padding: 3px 5px 3px 5px;
+        background-color: #fff;
+
+        display: inline-block;
+        background-color: @highlight-color;
+        margin-right: 8px;
+        padding: 4px 12px;
+        color: #fff;
+        text-align: center;
+        text-decoration: none;
+        .transition( background );
+        border-bottom: 2px solid darken(@highlight-color,10%);
+
+        &:hover {
+        background-color: #4cd6fc;
+        color: #fff;
+    }
+    }
+}
+
+
+// #main-container, #search-box, 
+
+
+
+
+/* ----- footer ---- */
+
+#footer {
+    height:40px;
+}
+
+
+/* ----- everything else ----- */
+
+div#results {
+  font-size:20px;
+  width:100%;
+  padding-top:4px;
+}
+div.result {
+  width:100%;
+}
+div.result-container {
+  padding-bottom:6px;
+}
+span.result-name {
+  padding-right:10px;
+}
+span.result-desc {
+  color:#6B6B6B;
+}
+div.result-tags {
+  text-align:right;
+  font-size:16px;
+  padding-right:4px;
+  float:right;
+}
+span.tag {
+  padding-left:6px;
+  cursor:pointer;
+  color:#878787;
+}
+span.desc-term {
+  color:#141414;
+}
+div.package {
+  text-align:center;
+}
+
+div.package-title {
+  font-size:45px;
+  float:left;
+}
+div.pkg-link {
+  float:left;
+  padding-top:20px;
+  margin-left:30px;
+}
+
+div#latest-packages {
+  width:45%;
+  float:left;
+  margin-right: 5%;
+}
+
+div#top-dep-packages {
+  width:45%;
+  margin-left:5%;
+  float:left;
+}
+
+div.top-title {
+  text-align:center;
+}
+
+div.top-package {
+  width:100%;
+}
+div.top-package-title {
+  padding-right:7px;
+  float:left;
+}
+div.top-package-updated {
+  float:right;
+  text-align:right;
+  padding-right:15px;
+}
+div.top-package-dep {
+  float:right;
+  text-align:right;
+  padding-right:15px;
+}
+
+div.dependencies {
+  width:80%;
+  text-align:left;
+  padding-left:10%;
+  padding-right:10%;
+}
+div.users {
+  width:80%;
+  text-align:left;
+  padding-left:10%;
+  padding-right:10%;
+}
+a.dep {
+  margin-right:10px;
+}
+a.user {
+  margin-right:10px;
+}
+div#totals {
+  float:right;
+  position:absolute;
+  top:10px;
+  right:10px;
+}
+div.all-package {
+  width:100%;
+}
+div.all-package-name {
+  width:40%;
+  padding-right:2%;
+  float:left;
+}
+div.all-package-desc {
+  width:50%;
+  float:left;
+}
+div#more-all {
+  cursor:pointer;
+  color:blue;
+}
+
+div#versions-container {
+  margin-top:10px;
+  width:100%;
+}
+div#version-list {
+  float:left;
+  width:20%;
+}
+div#version-info {
+  float:left;
+  width:78%;
+  background-color:#B9D3EE;
+  padding: 1% 1% 1% 1%;
+}
+div.version-info-cell {
+  width:100%;
+}
+div.version-info-key {
+  float:left;
+}
+div.version-info-value {
+  float:right;
+  text-align:right;
+}
+div.version-selected {
+  background-color:#B9D3EE;
+}
+div.version-link {
+  width:100%;
+  padding: 3px 0px 0px 10px;
+}
+
+span.expand-tags {
+  padding-left:10px;
+  font-size:12px;
+  cursor:pointer;
+  color:#FF1D4E;
+}
+a.tag-val {
+  padding-right:10px;
+  padding-left:5px;
+}
+div.all-package-author {
+  width:30%;
+  float:left;
+}
+
+div.all-package-auth-list {
+  width:70%;
+  float:left;
+}
+div.all-package-deps {
+  width:50%;
+  float:left;
+}
+div.all-package-deps-value {
+  width:50%;
+  float:left;
+}
+div.tags-pkg-name {
+  float:left;
+  width:30%;
+  font-size:30px;
+}
+div.tags-pkg-desc {
+  float:left;
+  width:70%;
+}

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/more.html
----------------------------------------------------------------------
diff --git a/attachments/more.html b/attachments/more.html
new file mode 100644
index 0000000..c6fa383
--- /dev/null
+++ b/attachments/more.html
@@ -0,0 +1,3 @@
+<h2>Goodies</h2>
+
+<h3><a href="/#/_analytics">Analytics</a></div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/publish.html
----------------------------------------------------------------------
diff --git a/attachments/publish.html b/attachments/publish.html
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/sammy/plugins/sammy.cache.js
----------------------------------------------------------------------
diff --git a/attachments/sammy/plugins/sammy.cache.js b/attachments/sammy/plugins/sammy.cache.js
new file mode 100644
index 0000000..b2622c8
--- /dev/null
+++ b/attachments/sammy/plugins/sammy.cache.js
@@ -0,0 +1,115 @@
+// deprecated
+(function($) {
+
+  Sammy = Sammy || {};
+
+  // A simple cache strategy that stores key/values in memory.
+  Sammy.MemoryCacheProxy = function(initial) {
+    this._cache = initial || {};
+  };
+
+  $.extend(Sammy.MemoryCacheProxy.prototype, {
+    exists: function(name) {
+      return (typeof this._cache[name] != "undefined");
+    },
+    set: function(name, value) {
+      return this._cache[name] = value;
+    },
+    get: function(name) {
+      return this._cache[name];
+    },
+    clear: function(name) {
+      delete this._cache[name];
+    }
+  });
+
+  // A simple cache strategy that stores key/values <tt>$element.data()</tt> with a <tt>cache.</tt> prefix
+  Sammy.DataCacheProxy = function(initial, $element) {
+    initial = initial || {};
+    this.$element = $element;
+    $.each(initial, function(key, value) {
+      $element.data('cache.' + key, value);
+    });
+  };
+
+  $.extend(Sammy.DataCacheProxy.prototype, {
+    exists: function(name) {
+      return (typeof this.$element.data('cache.' + name) != "undefined");
+    },
+    set: function(name, value) {
+      return this.$element.data('cache.' + name, value);
+    },
+    get: function(name) {
+      return this.$element.data('cache.' + name);
+    },
+    clear: function(name) {
+      this.$element.removeData('cache.' + name);
+    }
+  });
+
+  // Sammy.Cache provides helpers for caching data within the lifecycle of a
+  // Sammy app. The plugin provides two main methods on <tt>Sammy.Application<tt>,
+  // <tt>cache</tt> and <tt>clearCache</tt>. Each app has its own cache store so that
+  // you dont have to worry about collisions. There are currently two different 'cache proxies'
+  // that share the same API but store the data in different ways.
+  //
+  // ### Arguments
+  //
+  // * `proxy` decides which caching proxy to use, either 'memory'(default) or 'data'
+  //
+  Sammy.Cache = function(app, proxy) {
+
+    app.log('**WARNING:** This version of Sammy.Cache has been deprecated in favor of using the version in Sammy.Storage and will be removed in 1.0')
+
+    if (proxy == 'data') {
+      this.cache_proxy = new Sammy.DataCacheProxy({}, this.$element());
+    } else {
+      this.cache_proxy = new Sammy.MemoryCacheProxy({});
+    }
+
+    app.cache_partials = true;
+
+    $.extend(app, {
+      // cache is the main method for interacting with the cache store. The same
+      // method is used for both setting and getting the value. The API is similar
+      // to jQuery.fn.attr()
+      //
+      // ### Examples
+      //
+      //      // setting a value
+      //      cache('key', 'value');
+      //
+      //      // getting a value
+      //      cache('key'); //=> 'value'
+      //
+      //      // setting a value with a callback
+      //      cache('key', function() {
+      //        // this is the app
+      //        return app.element_selector;
+      //      });
+      //
+      cache: function(name, value) {
+        if (typeof value == 'undefined') {
+          return this.cache_proxy.get(name);
+        } else if ($.isFunction(value) && !this.cache_proxy.exists(name)) {
+          return this.cache_proxy.set(name, value.apply(this));
+        } else {
+          return this.cache_proxy.set(name, value)
+        }
+      },
+
+      // clears the cached value for <tt>name</tt>
+      clearCache: function(name) {
+        return this.cache_proxy.clear(name);
+      }
+    });
+
+    app.helpers({
+      // a helper shortcut for use in <tt>Sammy.EventContext</tt>
+      cache: function(name, value) {
+        return this.app.cache(name, value);
+      }
+    });
+  };
+
+})(jQuery);

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/sammy/plugins/sammy.data_location_proxy.js
----------------------------------------------------------------------
diff --git a/attachments/sammy/plugins/sammy.data_location_proxy.js b/attachments/sammy/plugins/sammy.data_location_proxy.js
new file mode 100644
index 0000000..6b0ada3
--- /dev/null
+++ b/attachments/sammy/plugins/sammy.data_location_proxy.js
@@ -0,0 +1,78 @@
+(function($) {
+
+  Sammy = Sammy || {};
+
+  // The DataLocationProxy is an optional location proxy prototype. As opposed to
+  // the `HashLocationProxy` it gets its location from a jQuery.data attribute
+  // tied to the application's element. You can set the name of the attribute by
+  // passing a string as the second argument to the constructor. The default attribute
+  // name is 'sammy-location'. To read more about location proxies, check out the
+  // documentation for `Sammy.HashLocationProxy`
+  //
+  // An optional `href_attribute` can be passed, which specifies a DOM element
+  // attribute that holds "links" to different locations in the app. When the
+  // proxy is bound, clicks to element that have this attribute activate a
+  // `setLocation()` using the contents of the `href_attribute`.
+  //
+  // ### Example
+  //
+  //      var app = $.sammy(function() {
+  //        // set up the location proxy
+  //        this.setLocationProxy(new Sammy.DataLocationProxy(this, 'location', 'rel'));
+  //
+  //        this.get('about', function() {
+  //          this.partial('about.html');
+  //        });
+  //
+  //      });
+  //
+  // In this scenario, if an element existed within the template:
+  //
+  //      <a href="/about" rel="about">About Us</a>
+  //
+  // Clicking on that link would not go to /about, but would set the apps location
+  // to 'about' and trigger the route.
+  Sammy.DataLocationProxy = function(app, data_name, href_attribute) {
+    this.app            = app;
+    this.data_name      = data_name || 'sammy-location';
+    this.href_attribute = href_attribute;
+  };
+
+  Sammy.DataLocationProxy.prototype = {
+    bind: function() {
+      var proxy = this;
+      this.app.$element().bind('setData', function(e, key, value) {
+        if (key == proxy.data_name) {
+          // jQuery unfortunately fires the event before it sets the value
+          // work around it, by setting the value ourselves
+          proxy.app.$element().each(function() {
+            $.data(this, proxy.data_name, value);
+          });
+          proxy.app.trigger('location-changed');
+        }
+      });
+      if (this.href_attribute) {
+        this.app.$element().delegate('[' + this.href_attribute + ']', 'click', function(e) {
+          e.preventDefault();
+          proxy.setLocation($(this).attr(proxy.href_attribute));
+        });
+      }
+    },
+
+    unbind: function() {
+      if (this.href_attribute) {
+        this.app.$element().undelegate('[' + this.href_attribute + ']', 'click');
+      }
+      this.app.$element().unbind('setData');
+    },
+
+    getLocation: function() {
+      return this.app.$element().data(this.data_name);
+    },
+
+    setLocation: function(new_location) {
+      return this.app.$element().data(this.data_name, new_location);
+    }
+  };
+
+})(jQuery);

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/sammy/plugins/sammy.ejs.js
----------------------------------------------------------------------
diff --git a/attachments/sammy/plugins/sammy.ejs.js b/attachments/sammy/plugins/sammy.ejs.js
new file mode 100644
index 0000000..4fb7493
--- /dev/null
+++ b/attachments/sammy/plugins/sammy.ejs.js
@@ -0,0 +1,700 @@
+(function($) {
+
+  // Embeddedjs is property of http://embeddedjs.com/
+  // Sammy ejs plugin written Codeofficer @ http://www.codeofficer.com/
+
+  var rsplit = function(string, regex) {
+    var result = regex.exec(string),
+        retArr = new Array(),
+        first_idx, last_idx, first_bit;
+    while (result != null) {
+      first_idx = result.index;
+      last_idx = regex.lastIndex;
+      if ((first_idx) != 0) {
+        first_bit = string.substring(0, first_idx);
+        retArr.push(string.substring(0, first_idx));
+        string = string.slice(first_idx);
+      };
+      retArr.push(result[0]);
+      string = string.slice(result[0].length);
+      result = regex.exec(string);
+    };
+    if (! string == '') {
+      retArr.push(string);
+    };
+    return retArr;
+  };
+
+  var chop = function(string) {
+    return string.substr(0, string.length - 1);
+  };
+
+  var extend = function(d, s) {
+    for (var n in s) {
+      if(s.hasOwnProperty(n))   d[n] = s[n];
+    };
+  };
+
+  /* @Constructor*/
+  EJS = function(options) {
+    options = (typeof(options) == "string") ? {view: options} : options;
+    this.set_options(options);
+    if (options.precompiled) {
+      this.template = {};
+      this.template.process = options.precompiled;
+      EJS.update(this.name, this);
+      return;
+    };
+    if (options.element) {
+      if (typeof(options.element) == 'string') {
+        var name = options.element;
+        options.element = document.getElementById(options.element);
+        if (options.element == null) throw name + 'does not exist!';
+      };
+      if (options.element.value) {
+        this.text = options.element.value;
+      } else {
+        this.text = options.element.innerHTML;
+      };
+      this.name = options.element.id;
+      this.type = '[';
+    } else if (options.url) {
+      options.url = EJS.endExt(options.url, this.extMatch);
+      this.name = this.name ? this.name : options.url;
+      var url = options.url;
+      //options.view = options.absolute_url || options.view || options.;
+      var template = EJS.get(this.name /*url*/, this.cache);
+      if (template) return template;
+      if (template == EJS.INVALID_PATH) return null;
+      try {
+        this.text = EJS.request( url + (this.cache ? '' : '?' + Math.random() ));
+      } catch(e) {};
+      if (this.text == null) {
+        throw( {type: 'EJS', message: 'There is no template at '+url}  );
+      };
+      //this.name = url;
+    };
+    var template = new EJS.Compiler(this.text, this.type);
+    template.compile(options, this.name);
+    EJS.update(this.name, this);
+    this.template = template;
+  };
+
+  /* @Prototype*/
+  EJS.prototype = {
+  /**
+   * Renders an object with extra view helpers attached to the view.
+   * @param {Object} object data to be rendered
+   * @param {Object} extra_helpers an object with additonal view helpers
+   * @return {String} returns the result of the string
+   */
+    render : function(object, extra_helpers) {
+      object = object || {};
+      this._extra_helpers = extra_helpers;
+      var v = new EJS.Helpers(object, extra_helpers || {});
+      return this.template.process.call(object, object,v);
+    },
+
+    update : function(element, options) {
+      if (typeof(element) == 'string') {
+        element = document.getElementById(element);
+      };
+      if (options == null) {
+        _template = this;
+        return function(object) {
+          EJS.prototype.update.call(_template, element, object);
+        };
+      };
+      if (typeof(options) == 'string') {
+        params = {};
+        params.url = options;
+        _template = this;
+        params.onComplete = function(request) {
+          var object = eval(request.responseText);
+          EJS.prototype.update.call(_template, element, object);
+        };
+        EJS.ajax_request(params);
+      } else {
+        element.innerHTML = this.render(options);
+      };
+    },
+
+    out : function() {
+      return this.template.out;
+    },
+
+    /**
+     * Sets options on this view to be rendered with.
+     * @param {Object} options
+     */
+    set_options : function(options){
+      this.type = options.type || EJS.type;
+      this.cache = (options.cache != null) ? options.cache : EJS.cache;
+      this.text = options.text || null;
+      this.name =   options.name || null;
+      this.ext = options.ext || EJS.ext;
+      this.extMatch = new RegExp(this.ext.replace(/\./, '\.'));
+    }
+  };
+
+  EJS.endExt = function(path, match) {
+    if (!path) return null;
+    match.lastIndex = 0;
+    return path + (match.test(path) ? '' : this.ext);
+  };
+
+  /* @Static*/
+  EJS.Scanner = function(source, left, right) {
+    extend(this, {
+      left_delimiter:  left +'%',
+      right_delimiter: '%'+right,
+      double_left: left+'%%',
+      double_right: '%%'+right,
+      left_equal: left+'%=',
+      left_comment: left+'%#'
+    });
+    this.SplitRegexp = (left == '[') ? /(\[%%)|(%%\])|(\[%=)|(\[%#)|(\[%)|(%\]\n)|(%\])|(\n)/ : new RegExp('('+this.double_left+')|(%%'+this.double_right+')|('+this.left_equal+')|('+this.left_comment+')|('+this.left_delimiter+')|('+this.right_delimiter+'\n)|('+this.right_delimiter+')|(\n)');
+    this.source = source;
+    this.stag = null;
+    this.lines = 0;
+  };
+
+  EJS.Scanner.to_text = function(input) {
+    if (input == null || input === undefined) return '';
+    if(input instanceof Date) return input.toDateString();
+    if(input.toString) return input.toString();
+    return '';
+  };
+
+  EJS.Scanner.prototype = {
+    scan: function(block) {
+      scanline = this.scanline;
+      regex = this.SplitRegexp;
+      if (! this.source == '') {
+        var source_split = rsplit(this.source, /\n/);
+        for (var i=0; i<source_split.length; i++) {
+          var item = source_split[i];
+          this.scanline(item, regex, block);
+        };
+      };
+    },
+
+    scanline: function(line, regex, block) {
+      this.lines++;
+      var line_split = rsplit(line, regex);
+      for (var i=0; i<line_split.length; i++) {
+        var token = line_split[i];
+        if (token != null) {
+          try {
+            block(token, this);
+          } catch(e) {
+            throw {type: 'EJS.Scanner', line: this.lines};
+          };
+        };
+      };
+    }
+  };
+
+  EJS.Buffer = function(pre_cmd, post_cmd) {
+    this.line = new Array();
+    this.script = "";
+    this.pre_cmd = pre_cmd;
+    this.post_cmd = post_cmd;
+    for (var i=0; i<this.pre_cmd.length; i++) {
+      this.push(pre_cmd[i]);
+    };
+  };
+
+  EJS.Buffer.prototype = {
+    push: function(cmd) {
+      this.line.push(cmd);
+    },
+
+    cr: function() {
+      this.script = this.script + this.line.join('; ');
+      this.line = new Array();
+      this.script = this.script + "\n";
+    },
+
+    close: function() {
+      if (this.line.length > 0) {
+        for (var i=0; i<this.post_cmd.length; i++){
+          this.push(pre_cmd[i]);
+        };
+        this.script = this.script + this.line.join('; ');
+        line = null;
+      };
+    }
+  };
+
+  EJS.Compiler = function(source, left) {
+    this.pre_cmd = ['var ___ViewO = [];'];
+    this.post_cmd = new Array();
+    this.source = ' ';
+    if (source != null) {
+      if (typeof(source) == 'string') {
+        source = source.replace(/\r\n/g, "\n");
+        source = source.replace(/\r/g,   "\n");
+        this.source = source;
+      } else if (source.innerHTML) {
+        this.source = source.innerHTML;
+      };
+      if (typeof this.source != 'string') {
+        this.source = "";
+      };
+    };
+    left = left || '<';
+    var right = '>';
+    switch(left) {
+      case '[':
+        right = ']';
+        break;
+      case '<':
+        break;
+      default:
+        throw left+' is not a supported deliminator';
+        break;
+    };
+    this.scanner = new EJS.Scanner(this.source, left, right);
+    this.out = '';
+  };
+
+  EJS.Compiler.prototype = {
+    compile: function(options, name) {
+      options = options || {};
+      this.out = '';
+      var put_cmd = "___ViewO.push(";
+      var insert_cmd = put_cmd;
+      var buff = new EJS.Buffer(this.pre_cmd, this.post_cmd);
+      var content = '';
+      var clean = function(content) {
+        content = content.replace(/\\/g, '\\\\');
+        content = content.replace(/\n/g, '\\n');
+        content = content.replace(/"/g,   '\\"');
+        return content;
+      };
+      this.scanner.scan(function(token, scanner) {
+        if (scanner.stag == null)  {
+          switch(token) {
+            case '\n':
+              content = content + "\n";
+              buff.push(put_cmd + '"' + clean(content) + '");');
+              buff.cr();
+              content = '';
+              break;
+            case scanner.left_delimiter:
+            case scanner.left_equal:
+            case scanner.left_comment:
+              scanner.stag = token;
+              if (content.length > 0) {
+                buff.push(put_cmd + '"' + clean(content) + '")');
+              };
+              content = '';
+              break;
+            case scanner.double_left:
+              content = content + scanner.left_delimiter;
+              break;
+            default:
+              content = content + token;
+              break;
+          };
+        } else {
+          switch(token) {
+            case scanner.right_delimiter:
+              switch(scanner.stag) {
+                case scanner.left_delimiter:
+                  if (content[content.length - 1] == '\n') {
+                    content = chop(content);
+                    buff.push(content);
+                    buff.cr();
+                  } else {
+                    buff.push(content);
+                  };
+                  break;
+                case scanner.left_equal:
+                  buff.push(insert_cmd + "(EJS.Scanner.to_text(" + content + ")))");
+                  break;
+              };
+              scanner.stag = null;
+              content = '';
+              break;
+            case scanner.double_right:
+              content = content + scanner.right_delimiter;
+              break;
+            default:
+              content = content + token;
+              break;
+          };
+        };
+      });
+      if (content.length > 0) {
+        // Chould be content.dump in Ruby
+        buff.push(put_cmd + '"' + clean(content) + '")');
+      };
+      buff.close();
+      this.out = buff.script + ";";
+      var to_be_evaled = '/*' + name + '*/this.process = function(_CONTEXT,_VIEW) { try { with(_VIEW) { with (_CONTEXT) {' + this.out + " return ___ViewO.join('');}}}catch(e){e.lineNumber=null;throw e;}};";
+      try {
+        eval(to_be_evaled);
+      } catch(e) {
+        if (typeof JSLINT != 'undefined') {
+          JSLINT(this.out);
+          for (var i = 0; i < JSLINT.errors.length; i++) {
+            var error = JSLINT.errors[i];
+            if (error.reason != "Unnecessary semicolon.") {
+              error.line++;
+              var e = new Error();
+              e.lineNumber = error.line;
+              e.message = error.reason;
+              if (options.view) e.fileName = options.view;
+              throw e;
+            };
+          };
+        } else {
+          throw e;
+        };
+      };
+    }
+  };
+
+  //type, cache, folder
+  /**
+   * Sets default options for all views
+   * @param {Object} options Set view with the following options
+   * <table class="options">
+          <tbody><tr><th>Option</th><th>Default</th><th>Description</th></tr>
+          <tr>
+            <td>type</td>
+            <td>'<'</td>
+            <td>type of magic tags.   Options are '&lt;' or '['
+            </td>
+          </tr>
+          <tr>
+            <td>cache</td>
+            <td>true in production mode, false in other modes</td>
+            <td>true to cache template.
+            </td>
+          </tr>
+    </tbody></table>
+   *
+   */
+  EJS.config = function(options){
+    EJS.cache = (options.cache != null) ? options.cache : EJS.cache;
+    EJS.type = (options.type != null) ? options.type : EJS.type;
+    EJS.ext = (options.ext != null) ? options.ext : EJS.ext;
+    var templates_directory = EJS.templates_directory || {}; //nice and private container
+    EJS.templates_directory = templates_directory;
+    EJS.get = function(path, cache) {
+      if(cache == false) return null;
+      if(templates_directory[path]) return templates_directory[path];
+      return null;
+    };
+    EJS.update = function(path, template) {
+      if (path == null) return;
+      templates_directory[path] = template ;
+    };
+    EJS.INVALID_PATH =  -1;
+  };
+  EJS.config( {cache: true, type: '<', ext: '.ejs' } );
+
+  /**
+   * @constructor
+   * By adding functions to EJS.Helpers.prototype, those functions will be available in the
+   * views.
+   * @init Creates a view helper.   This function is called internally.  You should never call it.
+   * @param {Object} data The data passed to the view.  Helpers have access to it through this._data
+   */
+  EJS.Helpers = function(data, extras){
+    this._data = data;
+    this._extras = extras;
+    extend(this, extras);
+  };
+
+  /* @prototype*/
+  EJS.Helpers.prototype = {
+    /**
+     * Renders a new view.  If data is passed in, uses that to render the view.
+     * @param {Object} options standard options passed to a new view.
+     * @param {optional:Object} data
+     * @return {String}
+     */
+    view: function(options, data, helpers) {
+      if (!helpers) helpers = this._extras;
+      if (!data) data = this._data;
+      return new EJS(options).render(data, helpers);
+    },
+    /**
+     * For a given value, tries to create a human representation.
+     * @param {Object} input the value being converted.
+     * @param {Object} null_text what text should be present if input == null or undefined, defaults to ''
+     * @return {String}
+     */
+    to_text: function(input, null_text) {
+      if (input == null || input === undefined) return null_text || '';
+      if (input instanceof(Date)) return input.toDateString();
+      if (input.toString) return input.toString().replace(/\n/g, '<br />').replace(/''/g, "'");
+      return '';
+    }
+  };
+
+  EJS.newRequest = function() {
+    var factories = [function() { return new ActiveXObject("Msxml2.XMLHTTP"); },function() { return new XMLHttpRequest(); },function() { return new ActiveXObject("Microsoft.XMLHTTP"); }];
+    for(var i = 0; i < factories.length; i++) {
+      try {
+        var request = factories[i]();
+        if (request != null)  return request;
+      } catch(e) { continue; }
+    };
+  };
+
+  EJS.request = function(path) {
+    var request = new EJS.newRequest();
+    request.open("GET", path, false);
+    try {
+      request.send(null);
+    } catch(e){
+      return null;
+    };
+    if ( request.status == 404 || request.status == 2 ||(request.status == 0 && request.responseText == '') ) return null;
+    return request.responseText;
+  };
+
+  EJS.ajax_request = function(params) {
+    params.method = ( params.method ? params.method : 'GET');
+    var request = new EJS.newRequest();
+    request.onreadystatechange = function() {
+      if (request.readyState == 4) {
+        if (request.status == 200) {
+          params.onComplete(request);
+        } else {
+          params.onComplete(request);
+        };
+      };
+    };
+    request.open(params.method, params.url);
+    request.send(null);
+  };
+
+  EJS.Helpers.prototype.date_tag = function(name, value , html_options) {
+    if(!(value instanceof(Date))) value = new Date();
+    var month_names = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
+    var years = [], months = [], days =[];
+    var year = value.getFullYear();
+    var month = value.getMonth();
+    var day = value.getDate();
+    for (var y = year - 15; y < year+15 ; y++) {
+      years.push({value: y, text: y});
+    };
+    for (var m = 0; m < 12; m++) {
+      months.push({value: (m), text: month_names[m]});
+    };
+    for (var d = 0; d < 31; d++) {
+      days.push({value: (d+1), text: (d+1)});
+    };
+    var year_select = this.select_tag(name+'[year]', year, years, {id: name+'[year]'} );
+    var month_select = this.select_tag(name+'[month]', month, months, {id: name+'[month]'});
+    var day_select = this.select_tag(name+'[day]', day, days, {id: name+'[day]'});
+    return year_select+month_select+day_select;
+  };
+
+  EJS.Helpers.prototype.form_tag = function(action, html_options) {
+    html_options = html_options || {};
+    html_options.action = action;
+    if(html_options.multipart == true) {
+      html_options.method = 'post';
+      html_options.enctype = 'multipart/form-data';
+    };
+    return this.start_tag_for('form', html_options);
+  };
+
+  EJS.Helpers.prototype.form_tag_end = function() {
+    return this.tag_end('form');
+  };
+
+  EJS.Helpers.prototype.hidden_field_tag   = function(name, value, html_options) {
+    return this.input_field_tag(name, value, 'hidden', html_options);
+  };
+
+  EJS.Helpers.prototype.input_field_tag = function(name, value , inputType, html_options) {
+    html_options = html_options || {};
+    html_options.id   = html_options.id || name;
+    html_options.value = value || '';
+    html_options.type = inputType || 'text';
+    html_options.name = name;
+    return this.single_tag_for('input', html_options);
+  };
+
+  EJS.Helpers.prototype.is_current_page = function(url) {
+    return (window.location.href == url || window.location.pathname == url ? true : false);
+  };
+
+  EJS.Helpers.prototype.link_to = function(name, url, html_options) {
+    if(!name) var name = 'null';
+    if(!html_options) var html_options = {};
+    if(html_options.confirm){
+      html_options.onclick = " var ret_confirm = confirm(\""+html_options.confirm+"\"); if(!ret_confirm){ return false;} ";
+      html_options.confirm = null;
+    };
+    html_options.href = url;
+    return this.start_tag_for('a', html_options)+name+ this.tag_end('a');
+  };
+
+  EJS.Helpers.prototype.submit_link_to = function(name, url, html_options) {
+    if(!name) var name = 'null';
+    if(!html_options) var html_options = {};
+    html_options.onclick = html_options.onclick || '';
+    if(html_options.confirm){
+      html_options.onclick = " var ret_confirm = confirm(\""+html_options.confirm+"\"); if(!ret_confirm){ return false;} ";
+      html_options.confirm = null;
+    };
+    html_options.value = name;
+    html_options.type = 'submit';
+    html_options.onclick = html_options.onclick + (url ? this.url_for(url) : '')+'return false;';
+    return this.start_tag_for('input', html_options);
+  };
+
+  EJS.Helpers.prototype.link_to_if = function(condition, name, url, html_options, post, block) {
+    return this.link_to_unless((condition == false), name, url, html_options, post, block);
+  };
+
+  EJS.Helpers.prototype.link_to_unless = function(condition, name, url, html_options, block) {
+    html_options = html_options || {};
+    if(condition) {
+      if(block && typeof(block) == 'function') {
+        return block(name, url, html_options, block);
+      } else {
+        return name;
+      };
+    } else {
+      return this.link_to(name, url, html_options);
+    };
+  };
+
+  EJS.Helpers.prototype.link_to_unless_current = function(name, url, html_options, block) {
+    html_options = html_options || {};
+    return this.link_to_unless(this.is_current_page(url), name, url, html_options, block);
+  };
+
+
+  EJS.Helpers.prototype.password_field_tag = function(name, value, html_options) {
+    return this.input_field_tag(name, value, 'password', html_options);
+  };
+
+  EJS.Helpers.prototype.select_tag = function(name, value, choices, html_options) {
+    html_options = html_options || {};
+    html_options.id   = html_options.id  || name;
+    html_options.value = value;
+    html_options.name = name;
+    var txt = '';
+    txt += this.start_tag_for('select', html_options);
+    for(var i = 0; i < choices.length; i++) {
+      var choice = choices[i];
+      var optionOptions = {value: choice.value};
+      if(choice.value == value) optionOptions.selected ='selected';
+      txt += this.start_tag_for('option', optionOptions )+choice.text+this.tag_end('option');
+    };
+    txt += this.tag_end('select');
+    return txt;
+  };
+
+  EJS.Helpers.prototype.single_tag_for = function(tag, html_options) {
+    return this.tag(tag, html_options, '/>');
+  };
+
+  EJS.Helpers.prototype.start_tag_for = function(tag, html_options)   {
+    return this.tag(tag, html_options);
+  };
+
+  EJS.Helpers.prototype.submit_tag = function(name, html_options) {
+    html_options = html_options || {};
+    html_options.type = html_options.type   || 'submit';
+    html_options.value = name || 'Submit';
+    return this.single_tag_for('input', html_options);
+  };
+
+  EJS.Helpers.prototype.tag = function(tag, html_options, end) {
+    if(!end) var end = '>';
+    var txt = ' ';
+    for(var attr in html_options) {
+      if(html_options[attr] != null) {
+        var value = html_options[attr].toString();
+      } else {
+        var value='';
+      };
+      // special case because "class" is a reserved word in IE
+      if(attr == "Class") attr = "class";
+      if( value.indexOf("'") != -1 ) {
+        txt += attr+'=\"'+value+'\" ';
+      } else {
+        txt += attr+"='"+value+"' ";
+      };
+    };
+    return '<' + tag + txt + end;
+  };
+
+  EJS.Helpers.prototype.tag_end = function(tag) {
+    return '</'+tag+'>';
+  };
+
+  EJS.Helpers.prototype.text_area_tag = function(name, value, html_options) {
+    html_options = html_options || {};
+    html_options.id   = html_options.id  || name;
+    html_options.name   = html_options.name  || name;
+    value = value || '';
+    if(html_options.size) {
+      html_options.cols = html_options.size.split('x')[0];
+      html_options.rows = html_options.size.split('x')[1];
+      delete html_options.size;
+    };
+    html_options.cols = html_options.cols  || 50;
+    html_options.rows = html_options.rows  || 4;
+    return  this.start_tag_for('textarea', html_options)+value+this.tag_end('textarea');
+  };
+
+  EJS.Helpers.prototype.text_tag = EJS.Helpers.prototype.text_area_tag;
+
+  EJS.Helpers.prototype.text_field_tag = function(name, value, html_options) {
+    return this.input_field_tag(name, value, 'text', html_options);
+  };
+
+  EJS.Helpers.prototype.url_for = function(url) {
+    return 'window.location="' + url + '";';
+  };
+
+  EJS.Helpers.prototype.img_tag = function(image_location, alt, options){
+    options = options || {};
+    options.src = image_location;
+    options.alt = alt;
+    return this.single_tag_for('img', options);
+  };
+
+  // -------------------------------------------------------------
+
+  Sammy = Sammy || {};
+
+  Sammy.EJS = function(app, method_alias) {
+
+    // *Helper:* Uses simple templating to parse ERB like templates.
+    //
+    // ### Arguments
+    //
+    // * `template` A String template. '<% %>' tags are evaluated as Javascript and replaced with the elements in data.
+    // * `data` An Object containing the replacement values for the template.
+    //data is extended with the <tt>EventContext</tt> allowing you to call its methods within the template.
+    // * `name` An optional String name to cache the template.
+    //
+    var template = function(template, data, name) {
+      // use name for caching
+      if (typeof name == 'undefined') name = template;
+      return new EJS({text: template, name: name}).render(data);
+    };
+
+    // set the default method name/extension
+    if (!method_alias) method_alias = 'ejs';
+
+    // create the helper at the method alias
+    app.helper(method_alias, template);
+
+   };
+
+})(jQuery);

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/sammy/plugins/sammy.form.js
----------------------------------------------------------------------
diff --git a/attachments/sammy/plugins/sammy.form.js b/attachments/sammy/plugins/sammy.form.js
new file mode 100644
index 0000000..78edb87
--- /dev/null
+++ b/attachments/sammy/plugins/sammy.form.js
@@ -0,0 +1,274 @@
+(function($) {
+
+  Sammy = Sammy || {};
+
+  function getStringContent(object, content) {
+    if (typeof content === 'undefined') {
+      return '';
+    } else if ($.isFunction(content)) {
+      content = content.apply(object);
+    }
+    return content.toString();
+  };
+
+  function simple_element(tag, attributes, content) {
+    var html = "<";
+    html += tag;
+    if (typeof attributes != 'undefined') {
+      $.each(attributes, function(key, value) {
+        if (value != null) {
+          html += " " + key + "='";
+          html += getStringContent(attributes, value).replace(/\'/g, "\'");
+          html += "'";
+        }
+      });
+    }
+    if (content === false) {
+      html += ">";
+    } else if (typeof content != 'undefined') {
+      html += ">";
+      html += getStringContent(this, content);
+      html += "</" + tag + ">";
+    } else {
+      html += " />";
+    }
+    return html;
+  };
+
+  // Sammy.FormBuilder is based very closely on the Rails FormBuilder classes.
+  // Its goal is to make it easy to create HTML forms for creating and editing
+  // JavaScript objects. It eases the process by auto-populating existing values
+  // into form inputs and creating input names suitable for parsing by
+  // Sammy.NestedParams and other backend frameworks.
+  //
+  // You initialize a Sammy.FormBuilder by passing the 'name' of the object and
+  // the object itself. Once initialized you create form elements with the object's
+  // prototype methods. Each of these methods returns a string of HTML suitable for
+  // appending through a template or directly with jQuery.
+  //
+  // ### Example
+  //
+  //      var item = {
+  //        name: 'My Item',
+  //        price: '$25.50',
+  //        meta: {
+  //          id: '123'
+  //        }
+  //      };
+  //      var form = new Sammy.FormBuilder('item', item);
+  //      form.text('name');
+  //      //=> <input type='text' name='item[form]' value='My Item' />
+  //
+  // Nested attributes can be accessed/referred to by a 'keypath' which is
+  // basically a string representation of the dot notation.
+  //
+  //      form.hidden('meta.id');
+  //      //=> <input type='hidden' name='item[meta][id]' value='123' />
+  //
+  Sammy.FormBuilder = function(name, object) {
+    this.name   = name;
+    this.object = object;
+  };
+
+  $.extend(Sammy.FormBuilder.prototype, {
+
+    // creates the open form tag with the object attributes
+    open: function(attributes) {
+      return simple_element('form', $.extend({'method': 'post', 'action': '#/' + this.name + 's'}, attributes), false);
+    },
+
+    // closes the form
+    close: function() {
+      return '</form>';
+    },
+
+    // creates a label for `keypath` with the text `content
+    // with an optional `attributes` object
+    label: function(keypath, content, attributes) {
+      var attrs = {'for': this._attributesForKeyPath(keypath).name};
+      return simple_element('label', $.extend(attrs, attributes), content);
+    },
+
+    // creates a hidden input for `keypath` with an optional `attributes` object
+    hidden: function(keypath, attributes) {
+      attributes = $.extend({type: 'hidden'}, this._attributesForKeyPath(keypath), attributes);
+      return simple_element('input', attributes);
+    },
+
+    // creates a text input for `keypath` with an optional `attributes` object
+    text: function(keypath, attributes) {
+      attributes = $.extend({type: 'text'}, this._attributesForKeyPath(keypath), attributes);
+      return simple_element('input', attributes);
+    },
+
+    // creates a textarea for `keypath` with an optional `attributes` object
+    textarea: function(keypath, attributes) {
+      var current;
+      attributes = $.extend(this._attributesForKeyPath(keypath), attributes);
+      current = attributes.value;
+      delete attributes['value'];
+      return simple_element('textarea', attributes, current);
+    },
+
+    // creates a password input for `keypath` with an optional `attributes` object
+    password: function(keypath, attributes) {
+      return this.text(keypath, $.extend({type: 'password'}, attributes));
+    },
+
+    // creates a select element for `keypath` with the option elements
+    // specified by an array in `options`. If `options` is an array of arrays,
+    // the first element in each subarray becomes the text of the option and the
+    // second becomes the value.
+    //
+    // ### Example
+    //
+    //     var options = [
+    //       ['Small', 's'],
+    //       ['Medium', 'm'],
+    //       ['Large', 'l']
+    //     ];
+    //     form.select('size', options);
+    //     //=> <select name='item[size]'><option value='s'>Small</option> ...
+    //
+    //
+    select: function(keypath, options, attributes) {
+      var option_html = "", selected;
+      attributes = $.extend(this._attributesForKeyPath(keypath), attributes);
+      selected = attributes.value;
+      delete attributes['value'];
+      $.each(options, function(i, option) {
+        var value, text, option_attrs;
+        if ($.isArray(option)) {
+          value = option[1], text = option[0];
+        } else {
+          value = option, text = option;
+        }
+        option_attrs = {value: getStringContent(this.object, value)};
+        // select the correct option
+        if (value === selected) { option_attrs.selected = 'selected'; }
+        option_html += simple_element('option', option_attrs, text);
+      });
+      return simple_element('select', attributes, option_html);
+    },
+
+    // creates a radio input for keypath with the value `value`. Multiple
+    // radios can be created with different value, if `value` equals the
+    // current value of the key of the form builder's object the attribute
+    // checked='checked' will be added.
+    radio: function(keypath, value, attributes) {
+      var selected;
+      attributes = $.extend(this._attributesForKeyPath(keypath), attributes);
+      selected = attributes.value;
+      attributes.value = getStringContent(this.object, value);
+      if (selected == attributes.value) {
+        attributes.checked = 'checked';
+      }
+      return simple_element('input', $.extend({type:'radio'}, attributes));
+    },
+
+    // creates a checkbox input for keypath with the value `value`. Multiple
+    // checkboxes can be created with different value, if `value` equals the
+    // current value of the key of the form builder's object the attribute
+    // checked='checked' will be added.
+    //
+    // By default `checkbox()` also generates a hidden element whose value is
+    // the inverse of the value given. This is known hack to get around a common
+    // gotcha where browsers and jQuery itself does not include 'unchecked'
+    // elements in the list of submittable inputs. This ensures that a value
+    // should always be passed to Sammy and hence the server. You can disable
+    // the creation of the hidden element by setting the `hidden_element` attribute
+    // to `false`
+    checkbox: function(keypath, value, attributes) {
+      var content = "";
+      if (!attributes) { attributes = {}; }
+      if (attributes.hidden_element !== false) {
+        content += this.hidden(keypath, {'value': !value});
+      }
+      delete attributes['hidden_element'];
+      content += this.radio(keypath, value, $.extend({type: 'checkbox'}, attributes));
+      return content;
+    },
+
+    // creates a submit input for `keypath` with an optional `attributes` object
+    submit: function(attributes) {
+      return simple_element('input', $.extend({'type': 'submit'}, attributes));
+    },
+
+    _attributesForKeyPath: function(keypath) {
+      var builder    = this,
+          keys       = $.isArray(keypath) ? keypath : keypath.split(/\./),
+          name       = builder.name,
+          value      = builder.object,
+          class_name = builder.name;
+
+      $.each(keys, function(i, key) {
+        if ((typeof value === 'undefined') || value == '') {
+          value = ''
+        } else if (typeof key == 'number' || key.match(/^\d+$/)) {
+          value = value[parseInt(key, 10)];
+        } else {
+          value = value[key];
+        }
+        name += "[" + key + "]";
+        class_name += "-" + key;
+      });
+      return {'name': name,
+              'value': getStringContent(builder.object, value),
+              'class': class_name};
+    }
+  });
+
+  // Sammy.Form is a Sammy plugin that adds form building helpers to a
+  // Sammy.Application
+  Sammy.Form = function(app) {
+
+    app.helpers({
+      // simple_element is a simple helper for creating HTML tags.
+      //
+      // ### Arguments
+      //
+      // * `tag` the HTML tag to generate e.g. input, p, etc/
+      // * `attributes` an object representing the attributes of the element as
+      //   key value pairs. e.g. {class: 'element-class'}
+      // * `content` an optional string representing the content for the
+      //   the element. If ommited, the element becomes self closing
+      //
+      simple_element: simple_element,
+
+      // formFor creates a Sammy.Form builder object with the passed `name`
+      // and `object` and passes it as an argument to the `content_callback`.
+      // This is a shortcut for creating FormBuilder objects for use within
+      // templates.
+      //
+      // ### Example
+      //
+      //      // in item_form.template
+      //
+      //      <% formFor('item', item, function(f) { %>
+      //        <%= f.open({action: '#/items'}) %>
+      //        <p>
+      //          <%= f.label('name') %>
+      //          <%= f.text('name') %>
+      //        </p>
+      //        <p>
+      //          <%= f.submit() %>
+      //        </p>
+      //        <%= f.close() %>
+      //      <% }); %>
+      //
+      formFor: function(name, object, content_callback) {
+        var builder;
+        // define a form with just a name
+        if ($.isFunction(object)) {
+          content_callback = object;
+          object = this[name];
+        }
+        builder = new Sammy.FormBuilder(name, object),
+        content_callback.apply(this, [builder]);
+        return builder;
+      }
+    });
+
+  };
+
+})(jQuery);

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/sammy/plugins/sammy.haml.js
----------------------------------------------------------------------
diff --git a/attachments/sammy/plugins/sammy.haml.js b/attachments/sammy/plugins/sammy.haml.js
new file mode 100644
index 0000000..9ea579d
--- /dev/null
+++ b/attachments/sammy/plugins/sammy.haml.js
@@ -0,0 +1,553 @@
+(function($) {
+
+  /*
+    port of http://github.com/creationix/haml-js
+    version v0.2.2 - 2010-04-05
+    by Tim Caswell <ti...@creationix.com>
+  */
+
+  var matchers, self_close_tags, embedder;
+
+  function html_escape(text) {
+    return (text + "").
+      replace(/&/g, "&amp;").
+      replace(/</g, "&lt;").
+      replace(/>/g, "&gt;").
+      replace(/\"/g, "&quot;");
+  }
+
+  function render_attribs(attribs) {
+    var key, value, result = [];
+    for (key in attribs) {
+      if (key !== 'content' && attribs.hasOwnProperty(key)) {
+        switch (attribs[key]) {
+        case 'undefined':
+        case 'false':
+        case 'null':
+        case '""':
+          break;
+        default:
+          try {
+            value = JSON.parse("[" + attribs[key] +"]")[0];
+            if (value === true) {
+              value = key;
+            } else if (typeof value === 'string' && embedder.test(value)) {
+              value = '" +\n' + parse_interpol(html_escape(value)) + ' +\n"';
+            } else {
+              value = html_escape(value);
+            }
+            result.push(" " + key + '=\\"' + value + '\\"');
+          } catch (e) {
+            result.push(" " + key + '=\\"" + html_escape(' + attribs[key] + ') + "\\"');
+          }
+        }
+      }
+    }
+    return result.join("");
+  }
+
+  // Parse the attribute block using a state machine
+  function parse_attribs(line) {
+    var attributes = {},
+        l = line.length,
+        i, c,
+        count = 1,
+        quote = false,
+        skip = false,
+        open, close, joiner, seperator,
+        pair = {
+          start: 1,
+          middle: null,
+          end: null
+        };
+
+    if (!(l > 0 && (line.charAt(0) === '{' || line.charAt(0) === '('))) {
+      return {
+        content: line[0] === ' ' ? line.substr(1, l) : line
+      };
+    }
+    open = line.charAt(0);
+    close = (open === '{') ? '}' : ')';
+    joiner = (open === '{') ? ':' : '=';
+    seperator = (open === '{') ? ',' : ' ';
+
+    function process_pair() {
+      if (typeof pair.start === 'number' &&
+          typeof pair.middle === 'number' &&
+          typeof pair.end === 'number') {
+        var key = line.substr(pair.start, pair.middle - pair.start).trim(),
+            value = line.substr(pair.middle + 1, pair.end - pair.middle - 1).trim();
+        attributes[key] = value;
+      }
+      pair = {
+        start: null,
+        middle: null,
+        end: null
+      };
+    }
+
+    for (i = 1; count > 0; i += 1) {
+
+      // If we reach the end of the line, then there is a problem
+      if (i > l) {
+        throw "Malformed attribute block";
+      }
+
+      c = line.charAt(i);
+      if (skip) {
+        skip = false;
+      } else {
+        if (quote) {
+          if (c === '\\') {
+            skip = true;
+          }
+          if (c === quote) {
+            quote = false;
+          }
+        } else {
+          if (c === '"' || c === "'") {
+            quote = c;
+          }
+
+          if (count === 1) {
+            if (c === joiner) {
+              pair.middle = i;
+            }
+            if (c === seperator || c === close) {
+              pair.end = i;
+              process_pair();
+              if (c === seperator) {
+                pair.start = i + 1;
+              }
+            }
+          }
+
+          if (c === open) {
+            count += 1;
+          }
+          if (c === close) {
+            count -= 1;
+          }
+        }
+      }
+    }
+    attributes.content = line.substr(i, line.length);
+    return attributes;
+  }
+
+  // Split interpolated strings into an array of literals and code fragments.
+  function parse_interpol(value) {
+    var items = [],
+        pos = 0,
+        next = 0,
+        match;
+    while (true) {
+      // Match up to embedded string
+      next = value.substr(pos).search(embedder);
+      if (next < 0) {
+        if (pos < value.length) {
+          items.push(JSON.stringify(value.substr(pos)));
+        }
+        break;
+      }
+      items.push(JSON.stringify(value.substr(pos, next)));
+      pos += next;
+
+      // Match embedded string
+      match = value.substr(pos).match(embedder);
+      next = match[0].length;
+      if (next < 0) { break; }
+      items.push(match[1] || match[2]);
+      pos += next;
+    }
+    return items.filter(function (part) { return part && part.length > 0}).join(" +\n");
+  }
+
+  // Used to find embedded code in interpolated strings.
+  embedder = /\#\{([^}]*)\}/;
+
+  self_close_tags = ["meta", "img", "link", "br", "hr", "input", "area", "base"];
+
+  // All matchers' regexps should capture leading whitespace in first capture
+  // and trailing content in last capture
+  matchers = [
+    // html tags
+    {
+      regexp: /^(\s*)((?:[.#%][a-z_\-][a-z0-9_\-]*)+)(.*)$/i,
+      process: function () {
+        var tag, classes, ids, attribs, content;
+        tag = this.matches[2];
+        classes = tag.match(/\.([a-z_\-][a-z0-9_\-]*)/gi);
+        ids = tag.match(/\#([a-z_\-][a-z0-9_\-]*)/gi);
+        tag = tag.match(/\%([a-z_\-][a-z0-9_\-]*)/gi);
+
+        // Default to <div> tag
+        tag = tag ? tag[0].substr(1, tag[0].length) : 'div';
+
+        attribs = this.matches[3];
+        if (attribs) {
+          attribs = parse_attribs(attribs);
+          if (attribs.content) {
+            this.contents.unshift(attribs.content.trim());
+            delete(attribs.content);
+          }
+        } else {
+          attribs = {};
+        }
+
+        if (classes) {
+          classes = classes.map(function (klass) {
+            return klass.substr(1, klass.length);
+          }).join(' ');
+          if (attribs['class']) {
+            try {
+              attribs['class'] = JSON.stringify(classes + " " + JSON.parse(attribs['class']));
+            } catch (e) {
+              attribs['class'] = JSON.stringify(classes + " ") + " + " + attribs['class'];
+            }
+          } else {
+            attribs['class'] = JSON.stringify(classes);
+          }
+        }
+        if (ids) {
+          ids = ids.map(function (id) {
+            return id.substr(1, id.length);
+          }).join(' ');
+          if (attribs.id) {
+            attribs.id = JSON.stringify(ids + " ") + attribs.id;
+          } else {
+            attribs.id = JSON.stringify(ids);
+          }
+        }
+
+        attribs = render_attribs(attribs);
+
+        content = this.render_contents();
+        if (content === '""') {
+          content = '';
+        }
+
+        if (self_close_tags.indexOf(tag) == -1) {
+          return '"<' + tag + attribs + '>"' +
+            (content.length > 0 ? ' + \n' + content : "") +
+            ' + \n"</' + tag + '>"';
+        } else {
+          return '"<' + tag + attribs + ' />"';
+        }
+      }
+    },
+
+    // each loops
+    {
+      regexp: /^(\s*)(?::for|:each)\s+(?:([a-z_][a-z_\-]*),\s*)?([a-z_][a-z_\-]*)\s+in\s+(.*)(\s*)$/i,
+      process: function () {
+        var ivar = this.matches[2] || '__key__', // index
+            vvar = this.matches[3],              // value
+            avar = this.matches[4],              // array
+            rvar = '__result__';                 // results
+
+        if (this.matches[5]) {
+          this.contents.unshift(this.matches[5]);
+        }
+        return '(function () { ' +
+          'var ' + rvar + ' = [], ' + ivar + ', ' + vvar + '; ' +
+          'for (' + ivar + ' in ' + avar + ') { ' +
+          'if (' + avar + '.hasOwnProperty(' + ivar + ')) { ' +
+          vvar + ' = ' + avar + '[' + ivar + ']; ' +
+          rvar + '.push(\n' + (this.render_contents() || "''") + '\n); ' +
+          '} } return ' + rvar + '.join(""); }).call(this)';
+      }
+    },
+
+    // if statements
+    {
+      regexp: /^(\s*):if\s+(.*)\s*$/i,
+      process: function () {
+        var condition = this.matches[2];
+        return '(function () { ' +
+          'if (' + condition + ') { ' +
+          'return (\n' + (this.render_contents() || '') + '\n);' +
+          '} else { return ""; } }).call(this)';
+      }
+    },
+
+    // declarations
+    {
+      regexp: /^()!!!(?:\s*(.*))\s*$/,
+      process: function () {
+        var line = '';
+        switch ((this.matches[2] || '').toLowerCase()) {
+        case '':
+          // XHTML 1.0 Transitional
+          line = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
+          break;
+        case 'strict':
+        case '1.0':
+          // XHTML 1.0 Strict
+          line = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
+          break;
+        case 'frameset':
+          // XHTML 1.0 Frameset
+          line = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">';
+          break;
+        case '5':
+          // XHTML 5
+          line = '<!DOCTYPE html>';
+          break;
+        case '1.1':
+          // XHTML 1.1
+          line = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">';
+          break;
+        case 'basic':
+          // XHTML Basic 1.1
+          line = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">';
+          break;
+        case 'mobile':
+          // XHTML Mobile 1.2
+          line = '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">';
+          break;
+        case 'xml':
+          // XML
+          line = "<?xml version='1.0' encoding='utf-8' ?>";
+          break;
+        case 'xml iso-8859-1':
+          // XML iso-8859-1
+          line = "<?xml version='1.0' encoding='iso-8859-1' ?>";
+          break;
+        }
+        return JSON.stringify(line + "\n");
+      }
+    },
+
+    // Embedded markdown. Needs to be added to exports externally.
+    {
+      regexp: /^(\s*):markdown\s*$/i,
+      process: function () {
+        return parse_interpol(exports.Markdown.encode(this.contents.join("\n")));
+      }
+    },
+
+    // script blocks
+    {
+      regexp: /^(\s*):(?:java)?script\s*$/,
+      process: function () {
+        return parse_interpol('\n<script type="text/javascript">\n' +
+          '//<![CDATA[\n' +
+          this.contents.join("\n") +
+          "\n//]]>\n</script>\n");
+      }
+    },
+
+    // css blocks
+    {
+      regexp: /^(\s*):css\s*$/,
+      process: function () {
+        return JSON.stringify('\n<style type="text/css">\n' +
+          this.contents.join("\n") +
+          "\n</style>\n");
+      }
+    },
+
+  ];
+
+  function compile(lines) {
+    var block = false,
+        output = [];
+
+    // If lines is a string, turn it into an array
+    if (typeof lines === 'string') {
+      lines = lines.trim().split("\n");
+    }
+
+    lines.forEach(function(line) {
+      var match, found = false;
+
+      // Collect all text as raw until outdent
+      if (block) {
+        match = block.check_indent(line);
+        if (match) {
+          block.contents.push(match[1] || "");
+          return;
+        } else {
+          output.push(block.process());
+          block = false;
+        }
+      }
+
+      matchers.forEach(function (matcher) {
+        if (!found) {
+          match = matcher.regexp(line);
+          if (match) {
+            block = {
+              contents: [],
+              matches: match,
+              check_indent: new RegExp("^(?:\\s*|" + match[1] + "  (.*))$"),
+              process: matcher.process,
+              render_contents: function () {
+                return compile(this. contents);
+              }
+            };
+            found = true;
+          }
+        }
+      });
+
+      // Match plain text
+      if (!found) {
+        output.push(function () {
+          // Escaped plain text
+          if (line[0] === '\\') {
+            return parse_interpol(line.substr(1, line.length));
+          }
+
+          // Plain variable data
+          if (line[0] === '=') {
+            line = line.substr(1, line.length).trim();
+            try {
+              return parse_interpol(JSON.parse(line));
+            } catch (e) {
+              return line;
+            }
+          }
+
+          // HTML escape variable data
+          if (line.substr(0, 2) === "&=") {
+            line = line.substr(2, line.length).trim();
+            try {
+              return JSON.stringify(html_escape(JSON.parse(line)));
+            } catch (e2) {
+              return 'html_escape(' + line + ')';
+            }
+          }
+
+          // Plain text
+          return parse_interpol(line);
+        }());
+      }
+
+    });
+    if (block) {
+      output.push(block.process());
+    }
+    return output.filter(function (part) { return part && part.length > 0}).join(" +\n");
+  };
+
+  function optimize(js) {
+    var new_js = [], buffer = [], part, end;
+
+    function flush() {
+      if (buffer.length > 0) {
+        new_js.push(JSON.stringify(buffer.join("")) + end);
+        buffer = [];
+      }
+    }
+    js.split("\n").forEach(function (line) {
+      part = line.match(/^(\".*\")(\s*\+\s*)?$/);
+      if (!part) {
+        flush();
+        new_js.push(line);
+        return;
+      }
+      end = part[2] || "";
+      part = part[1];
+      try {
+        buffer.push(JSON.parse(part));
+      } catch (e) {
+        flush();
+        new_js.push(line);
+      }
+    });
+    flush();
+    return new_js.join("\n");
+  };
+
+  function Haml(haml) {
+    var js = optimize(compile(haml));
+    return new Function("locals",
+      html_escape + "\n" +
+      "with(locals || {}) {\n" +
+      "  try {\n" +
+      "    return (" + js + ");\n" +
+      "  } catch (e) {\n" +
+      "    return \"\\n<pre class='error'>\" + html_escape(e.stack) + \"</pre>\\n\";\n" +
+      "  }\n" +
+      "}");
+  }
+
+
+  Sammy = Sammy || {};
+
+  // <tt>Sammy.Haml</tt> provides a quick way of using haml style templates in your app.
+  // The plugin itself includes the haml-js library created by Tim Caswell at
+  // at http://github.com/creationix/haml-js
+  //
+  // Haml is an alternative HTML syntax that is really great for describing
+  // the structure of HTML documents.
+  //
+  // By default using Sammy.Haml in your app adds the <tt>haml()</tt> method to the EventContext
+  // prototype. However, just like <tt>Sammy.Template</tt> you can change the default name of the method
+  // by passing a second argument (e.g. you could use the hml() as the method alias so that all the template
+  // files could be in the form file.hml instead of file.haml)
+  //
+  // ### Example
+  //
+  // The template (mytemplate.haml):
+  //
+  //       %h1&= title
+  //
+  //       Hey, #{name}! Welcome to Haml!
+  //
+  // The app:
+  //
+  //       var $.app = $.sammy(function() {
+  //         // include the plugin
+  //         this.use(Sammy.Haml);
+  //
+  //         this.get('#/hello/:name', function() {
+  //           // set local vars
+  //           this.title = 'Hello!'
+  //           this.name = this.params.name;
+  //           // render the template and pass it through haml
+  //           this.partial('mytemplate.haml');
+  //         });
+  //
+  //       });
+  //
+  // If I go to #/hello/AQ in the browser, Sammy will render this to the <tt>body</tt>:
+  //
+  //       <h1>Hello!</h1>
+  //
+  //       Hey, AQ! Welcome to HAML!
+  //
+  // Note: You dont have to include the haml.js file on top of the plugin as the plugin
+  // includes the full source.
+  //
+  Sammy.Haml = function(app, method_alias) {
+    app.use(Sammy.JSON);
+
+    var haml_cache = {};
+    // *Helper* Uses haml-js to parse a template and interpolate and work with the passed data
+    //
+    // ### Arguments
+    //
+    // * `template` A String template.
+    // * `data` An Object containing the replacement values for the template.
+    //   data is extended with the <tt>EventContext</tt> allowing you to call its methods within the template.
+    //
+    var haml = function(template, data, name) {
+      // use name for caching
+      if (typeof name == 'undefined') name = template;
+      var fn = haml_cache[name];
+      if (!fn) {
+        fn = haml_cache[name] = Haml(template);
+      }
+      return fn($.extend({}, this, data));
+    };
+
+    // set the default method name/extension
+    if (!method_alias) method_alias = 'haml';
+    app.helper(method_alias, haml);
+
+  };
+
+})(jQuery);

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/sammy/plugins/sammy.json.js
----------------------------------------------------------------------
diff --git a/attachments/sammy/plugins/sammy.json.js b/attachments/sammy/plugins/sammy.json.js
new file mode 100644
index 0000000..83b9dd0
--- /dev/null
+++ b/attachments/sammy/plugins/sammy.json.js
@@ -0,0 +1,362 @@
+(function($) {
+
+  // json2.js - only included if native json does not exist
+  // http://www.json.org/js.html
+  if (!window.JSON) {
+    window.JSON = {};
+  }
+  (function () {
+
+      function f(n) {
+          // Format integers to have at least two digits.
+          return n < 10 ? '0' + n : n;
+      }
+
+      if (typeof Date.prototype.toJSON !== 'function') {
+
+          Date.prototype.toJSON = function (key) {
+
+              return this.getUTCFullYear()   + '-' +
+                   f(this.getUTCMonth() + 1) + '-' +
+                   f(this.getUTCDate())      + 'T' +
+                   f(this.getUTCHours())     + ':' +
+                   f(this.getUTCMinutes())   + ':' +
+                   f(this.getUTCSeconds())   + 'Z';
+          };
+
+          String.prototype.toJSON =
+          Number.prototype.toJSON =
+          Boolean.prototype.toJSON = function (key) {
+              return this.valueOf();
+          };
+      }
+
+      var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+          escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+          gap,
+          indent,
+          meta = {    // table of character substitutions
+              '\b': '\\b',
+              '\t': '\\t',
+              '\n': '\\n',
+              '\f': '\\f',
+              '\r': '\\r',
+              '"' : '\\"',
+              '\\': '\\\\'
+          },
+          rep;
+
+
+      function quote(string) {
+
+  // If the string contains no control characters, no quote characters, and no
+  // backslash characters, then we can safely slap some quotes around it.
+  // Otherwise we must also replace the offending characters with safe escape
+  // sequences.
+
+          escapable.lastIndex = 0;
+          return escapable.test(string) ?
+              '"' + string.replace(escapable, function (a) {
+                  var c = meta[a];
+                  return typeof c === 'string' ? c :
+                      '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+              }) + '"' :
+              '"' + string + '"';
+      }
+
+
+      function str(key, holder) {
+
+  // Produce a string from holder[key].
+
+          var i,          // The loop counter.
+              k,          // The member key.
+              v,          // The member value.
+              length,
+              mind = gap,
+              partial,
+              value = holder[key];
+
+  // If the value has a toJSON method, call it to obtain a replacement value.
+
+          if (value && typeof value === 'object' &&
+                  typeof value.toJSON === 'function') {
+              value = value.toJSON(key);
+          }
+
+  // If we were called with a replacer function, then call the replacer to
+  // obtain a replacement value.
+
+          if (typeof rep === 'function') {
+              value = rep.call(holder, key, value);
+          }
+
+  // What happens next depends on the value's type.
+
+          switch (typeof value) {
+          case 'string':
+              return quote(value);
+
+          case 'number':
+
+  // JSON numbers must be finite. Encode non-finite numbers as null.
+
+              return isFinite(value) ? String(value) : 'null';
+
+          case 'boolean':
+          case 'null':
+
+  // If the value is a boolean or null, convert it to a string. Note:
+  // typeof null does not produce 'null'. The case is included here in
+  // the remote chance that this gets fixed someday.
+
+              return String(value);
+
+  // If the type is 'object', we might be dealing with an object or an array or
+  // null.
+
+          case 'object':
+
+  // Due to a specification blunder in ECMAScript, typeof null is 'object',
+  // so watch out for that case.
+
+              if (!value) {
+                  return 'null';
+              }
+
+  // Make an array to hold the partial results of stringifying this object value.
+
+              gap += indent;
+              partial = [];
+
+  // Is the value an array?
+
+              if (Object.prototype.toString.apply(value) === '[object Array]') {
+
+  // The value is an array. Stringify every element. Use null as a placeholder
+  // for non-JSON values.
+
+                  length = value.length;
+                  for (i = 0; i < length; i += 1) {
+                      partial[i] = str(i, value) || 'null';
+                  }
+
+  // Join all of the elements together, separated with commas, and wrap them in
+  // brackets.
+
+                  v = partial.length === 0 ? '[]' :
+                      gap ? '[\n' + gap +
+                              partial.join(',\n' + gap) + '\n' +
+                                  mind + ']' :
+                            '[' + partial.join(',') + ']';
+                  gap = mind;
+                  return v;
+              }
+
+  // If the replacer is an array, use it to select the members to be stringified.
+
+              if (rep && typeof rep === 'object') {
+                  length = rep.length;
+                  for (i = 0; i < length; i += 1) {
+                      k = rep[i];
+                      if (typeof k === 'string') {
+                          v = str(k, value);
+                          if (v) {
+                              partial.push(quote(k) + (gap ? ': ' : ':') + v);
+                          }
+                      }
+                  }
+              } else {
+
+  // Otherwise, iterate through all of the keys in the object.
+
+                  for (k in value) {
+                      if (Object.hasOwnProperty.call(value, k)) {
+                          v = str(k, value);
+                          if (v) {
+                              partial.push(quote(k) + (gap ? ': ' : ':') + v);
+                          }
+                      }
+                  }
+              }
+
+  // Join all of the member texts together, separated with commas,
+  // and wrap them in braces.
+
+              v = partial.length === 0 ? '{}' :
+                  gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
+                          mind + '}' : '{' + partial.join(',') + '}';
+              gap = mind;
+              return v;
+          }
+      }
+
+  // If the JSON object does not yet have a stringify method, give it one.
+
+      if (typeof JSON.stringify !== 'function') {
+          JSON.stringify = function (value, replacer, space) {
+
+  // The stringify method takes a value and an optional replacer, and an optional
+  // space parameter, and returns a JSON text. The replacer can be a function
+  // that can replace values, or an array of strings that will select the keys.
+  // A default replacer method can be provided. Use of the space parameter can
+  // produce text that is more easily readable.
+
+              var i;
+              gap = '';
+              indent = '';
+
+  // If the space parameter is a number, make an indent string containing that
+  // many spaces.
+
+              if (typeof space === 'number') {
+                  for (i = 0; i < space; i += 1) {
+                      indent += ' ';
+                  }
+
+  // If the space parameter is a string, it will be used as the indent string.
+
+              } else if (typeof space === 'string') {
+                  indent = space;
+              }
+
+  // If there is a replacer, it must be a function or an array.
+  // Otherwise, throw an error.
+
+              rep = replacer;
+              if (replacer && typeof replacer !== 'function' &&
+                      (typeof replacer !== 'object' ||
+                       typeof replacer.length !== 'number')) {
+                  throw new Error('JSON.stringify');
+              }
+
+  // Make a fake root object containing our value under the key of ''.
+  // Return the result of stringifying the value.
+
+              return str('', {'': value});
+          };
+      }
+
+
+  // If the JSON object does not yet have a parse method, give it one.
+
+      if (typeof JSON.parse !== 'function') {
+          JSON.parse = function (text, reviver) {
+
+  // The parse method takes a text and an optional reviver function, and returns
+  // a JavaScript value if the text is a valid JSON text.
+
+              var j;
+
+              function walk(holder, key) {
+
+  // The walk method is used to recursively walk the resulting structure so
+  // that modifications can be made.
+
+                  var k, v, value = holder[key];
+                  if (value && typeof value === 'object') {
+                      for (k in value) {
+                          if (Object.hasOwnProperty.call(value, k)) {
+                              v = walk(value, k);
+                              if (v !== undefined) {
+                                  value[k] = v;
+                              } else {
+                                  delete value[k];
+                              }
+                          }
+                      }
+                  }
+                  return reviver.call(holder, key, value);
+              }
+
+
+  // Parsing happens in four stages. In the first stage, we replace certain
+  // Unicode characters with escape sequences. JavaScript handles many characters
+  // incorrectly, either silently deleting them, or treating them as line endings.
+
+              cx.lastIndex = 0;
+              if (cx.test(text)) {
+                  text = text.replace(cx, function (a) {
+                      return '\\u' +
+                          ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+                  });
+              }
+
+  // In the second stage, we run the text against regular expressions that look
+  // for non-JSON patterns. We are especially concerned with '()' and 'new'
+  // because they can cause invocation, and '=' because it can cause mutation.
+  // But just to be safe, we want to reject all unexpected forms.
+
+  // We split the second stage into 4 regexp operations in order to work around
+  // crippling inefficiencies in IE's and Safari's regexp engines. First we
+  // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
+  // replace all simple value tokens with ']' characters. Third, we delete all
+  // open brackets that follow a colon or comma or that begin the text. Finally,
+  // we look to see that the remaining characters are only whitespace or ']' or
+  // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
+
+              if (/^[\],:{}\s]*$/.
+  test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
+  replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
+  replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+  // In the third stage we use the eval function to compile the text into a
+  // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
+  // in JavaScript: it can begin a block or an object literal. We wrap the text
+  // in parens to eliminate the ambiguity.
+
+                  j = eval('(' + text + ')');
+
+  // In the optional fourth stage, we recursively walk the new structure, passing
+  // each name/value pair to a reviver function for possible transformation.
+
+                  return typeof reviver === 'function' ?
+                      walk({'': j}, '') : j;
+              }
+
+  // If the text is not JSON parseable, then a SyntaxError is thrown.
+
+              throw new SyntaxError('JSON.parse');
+          };
+      }
+  }());
+
+  Sammy = Sammy || {};
+
+  // Sammy.JSON is a simple wrapper around Douglas Crockford's ever-useful json2.js
+  // (http://www.json.org/js.html]) Sammy.JSON includes the top level JSON object if
+  // it doesn't already exist (a.k.a. does not override the native implementation that
+  // some browsers include). It also adds a <tt>json()</tt> helper to a Sammy app when
+  // included.
+  Sammy.JSON = function(app) {
+
+    app.helpers({
+      // json is a polymorphic function that translates objects aback and forth
+      // from JSON to JS. If given a string, it will parse into JS, if given a JS
+      // object it will stringify into JSON.
+      //
+      // ### Example
+      //
+      //      var app = $.sammy(function() {
+      //        this.use(Sammy.JSON);
+      //
+      //        this.get('#/', function() {
+      //          this.json({user_id: 123}); //=> "{\"user_id\":\"123\"}"
+      //          this.json("{\"user_id\":\"123\"}"); //=> [object Object]
+      //          this.json("{\"user_id\":\"123\"}").user_id; //=> "123"
+      //        });
+      //      })
+      //
+      //
+      json: function(object) {
+        if (typeof object == 'string') {
+          return JSON.parse(object);
+        } else {
+          return JSON.stringify(object);
+        }
+      }
+    });
+
+  }
+
+})(jQuery);

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/sammy/plugins/sammy.meld.js
----------------------------------------------------------------------
diff --git a/attachments/sammy/plugins/sammy.meld.js b/attachments/sammy/plugins/sammy.meld.js
new file mode 100644
index 0000000..9753969
--- /dev/null
+++ b/attachments/sammy/plugins/sammy.meld.js
@@ -0,0 +1,140 @@
+(function($) {
+
+  Sammy = Sammy || {};
+
+  // `Sammy.Meld` is a simple templating engine that uses the power of jQuery's
+  // DOM manipulation to easily meld JSON data and HTML templates very quickly.
+  //
+  // The template can either be a string (i.e. loaded from a remote template)
+  // or a DOM Element/jQuery object. This allows you to have templates be DOM
+  // elements as the initial document load.
+  //
+  // ### Example
+  //
+  // The simplest case is a nested `<div>` whose class name is tied to a
+  // property of a JS object.
+  //
+  // Template:
+  //
+  //        <div class="post">
+  //          <div class="title"></div>
+  //          <div class="entry"></div>
+  //          <div class="author">
+  //            <span class="name"></span>
+  //          </div>
+  //        </div>
+  //
+  // Data:
+  //
+  //        {
+  //          "post": {
+  //            "title": "My Post",
+  //            "entry": "My Entry",
+  //            "author": {
+  //              "name": "@aq"
+  //            }
+  //          }
+  //        }
+  //
+  // Result:
+  //
+  //        <div class="post">
+  //          <div class="title">My Post</div>
+  //          <div class="entry">My Entry</div>
+  //          <div class="author">
+  //            <span class="name">@aq</span>
+  //          </div>
+  //        </div>
+  //
+  // Templates can be much more complex, and more deeply nested.
+  // More examples can be found in `test/fixtures/meld/`
+  //
+  // If you don't think the lookup by classes is semantic for you, you can easily
+  // switch the method of lookup by defining a selector function in the options
+  //
+  // For example:
+  //
+  //      meld($('.post'), post_data, {
+  //        selector: function(k) {
+  //          return '[data-key=' + k + ']';
+  //        }
+  //      });
+  //
+  // Would look for template nodes like `<div data-key='entry'>`
+  //
+  Sammy.Meld = function(app, method_alias) {
+    var default_options = {
+      selector: function(k) { return '.' + k; },
+      remove_false: true
+    };
+
+    var meld = function(template, data, options) {
+      var $template = $(template);
+
+      options = $.extend(default_options, options || {});
+
+      if (typeof data === 'string') {
+        $template.html(data);
+      } else {
+        $.each(data, function(key, value) {
+          var selector = options.selector(key),
+              $sub = $template.filter(selector),
+              $container,
+              $item,
+              is_list = false,
+              subindex = $template.index($sub);
+
+          if ($sub.length === 0) { $sub = $template.find(selector); }
+          if ($sub.length > 0) {
+            if ($.isArray(value)) {
+              $container = $('<div/>');
+              if ($sub.is('ol, ul')) {
+                is_list = true;
+                $item   = $sub.children('li:first');
+                if ($item.length == 0) { $item = $('<li/>'); }
+              } else if ($sub.children().length == 1) {
+                is_list = true;
+                $item = $sub.children(':first').clone();
+              } else {
+                $item = $sub.clone();
+              }
+              for (var i = 0; i < value.length; i++) {
+                $container.append(meld($item.clone(), value[i], options));
+              }
+              if (is_list) {
+                $sub.html($container.html());
+              } else if ($sub[0] == $template[0]) {
+                $template = $($container.html());
+              } else if (subindex >= 0) {
+                var args = [subindex, 1];
+                args = args.concat($container.children().get());
+                $template.splice.apply($template, args);
+              }
+            } else if (options.remove_false && value === false) {
+              $template.splice(subindex, 1);
+            } else if (typeof value === 'object') {
+              if ($sub.is(':empty')) {
+                $sub.attr(value, true);
+              } else {
+                $sub.html(meld($sub.html(), value, options));
+              }
+            } else {
+              $sub.html(value.toString());
+            }
+          } else {
+            $template.attr({key: value}, true);
+          }
+        });
+      }
+      var dom = $template;
+      return dom;
+    };
+
+    // set the default method name/extension
+    if (!method_alias) method_alias = 'meld';
+    // create the helper at the method alias
+    app.helper(method_alias, meld);
+
+  };
+
+})(jQuery);


[3/9] first commit

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/sammy/plugins/sammy.mustache.js
----------------------------------------------------------------------
diff --git a/attachments/sammy/plugins/sammy.mustache.js b/attachments/sammy/plugins/sammy.mustache.js
new file mode 100644
index 0000000..169f0c7
--- /dev/null
+++ b/attachments/sammy/plugins/sammy.mustache.js
@@ -0,0 +1,444 @@
+(function($) {
+
+if (!window.Mustache) {
+
+  /*
+    mustache.js — Logic-less templates in JavaScript
+
+    See http://mustache.github.com/ for more info.
+  */
+
+  var Mustache = function() {
+    var Renderer = function() {};
+
+    Renderer.prototype = {
+      otag: "{{",
+      ctag: "}}",
+      pragmas: {},
+      buffer: [],
+      pragmas_implemented: {
+        "IMPLICIT-ITERATOR": true
+      },
+      context: {},
+
+      render: function(template, context, partials, in_recursion) {
+        // reset buffer & set context
+        if(!in_recursion) {
+          this.context = context;
+          this.buffer = []; // TODO: make this non-lazy
+        }
+
+        // fail fast
+        if(!this.includes("", template)) {
+          if(in_recursion) {
+            return template;
+          } else {
+            this.send(template);
+            return;
+          }
+        }
+
+        template = this.render_pragmas(template);
+        var html = this.render_section(template, context, partials);
+        if(in_recursion) {
+          return this.render_tags(html, context, partials, in_recursion);
+        }
+
+        this.render_tags(html, context, partials, in_recursion);
+      },
+
+      /*
+        Sends parsed lines
+      */
+      send: function(line) {
+        if(line != "") {
+          this.buffer.push(line);
+        }
+      },
+
+      /*
+        Looks for %PRAGMAS
+      */
+      render_pragmas: function(template) {
+        // no pragmas
+        if(!this.includes("%", template)) {
+          return template;
+        }
+
+        var that = this;
+        var regex = new RegExp(this.otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" +
+              this.ctag);
+        return template.replace(regex, function(match, pragma, options) {
+          if(!that.pragmas_implemented[pragma]) {
+            throw({message:
+              "This implementation of mustache doesn't understand the '" +
+              pragma + "' pragma"});
+          }
+          that.pragmas[pragma] = {};
+          if(options) {
+            var opts = options.split("=");
+            that.pragmas[pragma][opts[0]] = opts[1];
+          }
+          return "";
+          // ignore unknown pragmas silently
+        });
+      },
+
+      /*
+        Tries to find a partial in the curent scope and render it
+      */
+      render_partial: function(name, context, partials) {
+        name = this.trim(name);
+        if(!partials || partials[name] === undefined) {
+          throw({message: "unknown_partial '" + name + "'"});
+        }
+        if(typeof(context[name]) != "object") {
+          return this.render(partials[name], context, partials, true);
+        }
+        return this.render(partials[name], context[name], partials, true);
+      },
+
+      /*
+        Renders inverted (^) and normal (#) sections
+      */
+      render_section: function(template, context, partials) {
+        if(!this.includes("#", template) && !this.includes("^", template)) {
+          return template;
+        }
+
+        var that = this;
+        // CSW - Added "+?" so it finds the tighest bound, not the widest
+        var regex = new RegExp(this.otag + "(\\^|\\#)\\s*(.+)\\s*" + this.ctag +
+                "\n*([\\s\\S]+?)" + this.otag + "\\/\\s*\\2\\s*" + this.ctag +
+                "\\s*", "mg");
+
+        // for each {{#foo}}{{/foo}} section do...
+        return template.replace(regex, function(match, type, name, content) {
+          var value = that.find(name, context);
+          if(type == "^") { // inverted section
+            if(!value || that.is_array(value) && value.length === 0) {
+              // false or empty list, render it
+              return that.render(content, context, partials, true);
+            } else {
+              return "";
+            }
+          } else if(type == "#") { // normal section
+            if(that.is_array(value)) { // Enumerable, Let's loop!
+              return that.map(value, function(row) {
+                return that.render(content, that.create_context(row),
+                  partials, true);
+              }).join("");
+            } else if(that.is_object(value)) { // Object, Use it as subcontext!
+              return that.render(content, that.create_context(value),
+                partials, true);
+            } else if(typeof value === "function") {
+              // higher order section
+              return value.call(context, content, function(text) {
+                return that.render(text, context, partials, true);
+              });
+            } else if(value) { // boolean section
+              return that.render(content, context, partials, true);
+            } else {
+              return "";
+            }
+          }
+        });
+      },
+
+      /*
+        Replace {{foo}} and friends with values from our view
+      */
+      render_tags: function(template, context, partials, in_recursion) {
+        // tit for tat
+        var that = this;
+
+        var new_regex = function() {
+          return new RegExp(that.otag + "(=|!|>|\\{|%)?([^\\/#\\^]+?)\\1?" +
+            that.ctag + "+", "g");
+        };
+
+        var regex = new_regex();
+        var tag_replace_callback = function(match, operator, name) {
+          switch(operator) {
+          case "!": // ignore comments
+            return "";
+          case "=": // set new delimiters, rebuild the replace regexp
+            that.set_delimiters(name);
+            regex = new_regex();
+            return "";
+          case ">": // render partial
+            return that.render_partial(name, context, partials);
+          case "{": // the triple mustache is unescaped
+            return that.find(name, context);
+          default: // escape the value
+            return that.escape(that.find(name, context));
+          }
+        };
+        var lines = template.split("\n");
+        for(var i = 0; i < lines.length; i++) {
+          lines[i] = lines[i].replace(regex, tag_replace_callback, this);
+          if(!in_recursion) {
+            this.send(lines[i]);
+          }
+        }
+
+        if(in_recursion) {
+          return lines.join("\n");
+        }
+      },
+
+      set_delimiters: function(delimiters) {
+        var dels = delimiters.split(" ");
+        this.otag = this.escape_regex(dels[0]);
+        this.ctag = this.escape_regex(dels[1]);
+      },
+
+      escape_regex: function(text) {
+        // thank you Simon Willison
+        if(!arguments.callee.sRE) {
+          var specials = [
+            '/', '.', '*', '+', '?', '|',
+            '(', ')', '[', ']', '{', '}', '\\'
+          ];
+          arguments.callee.sRE = new RegExp(
+            '(\\' + specials.join('|\\') + ')', 'g'
+          );
+        }
+        return text.replace(arguments.callee.sRE, '\\$1');
+      },
+
+      /*
+        find `name` in current `context`. That is find me a value
+        from the view object
+      */
+      find: function(name, context) {
+        name = this.trim(name);
+
+        // Checks whether a value is thruthy or false or 0
+        function is_kinda_truthy(bool) {
+          return bool === false || bool === 0 || bool;
+        }
+
+        var value;
+        if(is_kinda_truthy(context[name])) {
+          value = context[name];
+        } else if(is_kinda_truthy(this.context[name])) {
+          value = this.context[name];
+        }
+
+        if(typeof value === "function") {
+          return value.apply(context);
+        }
+        if(value !== undefined) {
+          return value;
+        }
+        // silently ignore unkown variables
+        return "";
+      },
+
+      // Utility methods
+
+      /* includes tag */
+      includes: function(needle, haystack) {
+        return haystack.indexOf(this.otag + needle) != -1;
+      },
+
+      /*
+        Does away with nasty characters
+      */
+      escape: function(s) {
+        s = String(s === null ? "" : s);
+        return s.replace(/&(?!\w+;)|["<>\\]/g, function(s) {
+          switch(s) {
+          case "&": return "&amp;";
+          case "\\": return "\\\\";
+          case '"': return '\"';
+          case "<": return "&lt;";
+          case ">": return "&gt;";
+          default: return s;
+          }
+        });
+      },
+
+      // by @langalex, support for arrays of strings
+      create_context: function(_context) {
+        if(this.is_object(_context)) {
+          return _context;
+        } else {
+          var iterator = ".";
+          if(this.pragmas["IMPLICIT-ITERATOR"]) {
+            iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator;
+          }
+          var ctx = {};
+          ctx[iterator] = _context;
+          return ctx;
+        }
+      },
+
+      is_object: function(a) {
+        return a && typeof a == "object";
+      },
+
+      is_array: function(a) {
+        return Object.prototype.toString.call(a) === '[object Array]';
+      },
+
+      /*
+        Gets rid of leading and trailing whitespace
+      */
+      trim: function(s) {
+        return s.replace(/^\s*|\s*$/g, "");
+      },
+
+      /*
+        Why, why, why? Because IE. Cry, cry cry.
+      */
+      map: function(array, fn) {
+        if (typeof array.map == "function") {
+          return array.map(fn);
+        } else {
+          var r = [];
+          var l = array.length;
+          for(var i = 0; i < l; i++) {
+            r.push(fn(array[i]));
+          }
+          return r;
+        }
+      }
+    };
+
+    return({
+      name: "mustache.js",
+      version: "0.3.1-dev",
+
+      /*
+        Turns a template and view into HTML
+      */
+      to_html: function(template, view, partials, send_fun) {
+        var renderer = new Renderer();
+        if(send_fun) {
+          renderer.send = send_fun;
+        }
+        renderer.render(template, view, partials);
+        if(!send_fun) {
+          return renderer.buffer.join("\n");
+        }
+      }
+    });
+  }();
+
+} // Ensure Mustache
+
+  Sammy = Sammy || {};
+
+  // <tt>Sammy.Mustache</tt> provides a quick way of using mustache style templates in your app.
+  // The plugin itself includes the awesome mustache.js lib created and maintained by Jan Lehnardt
+  // at http://github.com/janl/mustache.js
+  //
+  // Mustache is a clever templating system that relys on double brackets {{}} for interpolation.
+  // For full details on syntax check out the original Ruby implementation created by Chris Wanstrath at
+  // http://github.com/defunkt/mustache
+  //
+  // By default using Sammy.Mustache in your app adds the <tt>mustache()</tt> method to the EventContext
+  // prototype. However, just like <tt>Sammy.Template</tt> you can change the default name of the method
+  // by passing a second argument (e.g. you could use the ms() as the method alias so that all the template
+  // files could be in the form file.ms instead of file.mustache)
+  //
+  // ### Example #1
+  //
+  // The template (mytemplate.ms):
+  //
+  //       <h1>\{\{title\}\}<h1>
+  //
+  //       Hey, {{name}}! Welcome to Mustache!
+  //
+  // The app:
+  //
+  //       var $.app = $.sammy(function() {
+  //         // include the plugin and alias mustache() to ms()
+  //         this.use(Sammy.Mustache, 'ms');
+  //
+  //         this.get('#/hello/:name', function() {
+  //           // set local vars
+  //           this.title = 'Hello!'
+  //           this.name = this.params.name;
+  //           // render the template and pass it through mustache
+  //           this.partial('mytemplate.ms');
+  //         });
+  //
+  //       });
+  //
+  // If I go to #/hello/AQ in the browser, Sammy will render this to the <tt>body</tt>:
+  //
+  //       <h1>Hello!</h1>
+  //
+  //       Hey, AQ! Welcome to Mustache!
+  //
+  //
+  // ### Example #2 - Mustache partials
+  //
+  // The template (mytemplate.ms)
+  //
+  //       Hey, {{name}}! {{>hello_friend}}
+  //
+  //
+  // The partial (mypartial.ms)
+  //
+  //       Say hello to your friend {{friend}}!
+  //
+  // The app:
+  //
+  //       var $.app = $.sammy(function() {
+  //         // include the plugin and alias mustache() to ms()
+  //         this.use(Sammy.Mustache, 'ms');
+  //
+  //         this.get('#/hello/:name/to/:friend', function() {
+  //           var context = this;
+  //
+  //           // fetch mustache-partial first
+  //           $.get('mypartial.ms', function(response){
+  //             context.partials = response;
+  //
+  //             // set local vars
+  //             context.name = this.params.name;
+  //             context.hello_friend = {name: this.params.friend};
+  //
+  //             // render the template and pass it through mustache
+  //             context.partial('mytemplate.ms');
+  //           });
+  //         });
+  //
+  //       });
+  //
+  // If I go to #/hello/AQ/to/dP in the browser, Sammy will render this to the <tt>body</tt>:
+  //
+  //       Hey, AQ! Say hello to your friend dP!
+  //
+  // Note: You dont have to include the mustache.js file on top of the plugin as the plugin
+  // includes the full source.
+  //
+  Sammy.Mustache = function(app, method_alias) {
+
+    // *Helper* Uses Mustache.js to parse a template and interpolate and work with the passed data
+    //
+    // ### Arguments
+    //
+    // * `template` A String template. {{}} Tags are evaluated and interpolated by Mustache.js
+    // * `data` An Object containing the replacement values for the template.
+    //   data is extended with the <tt>EventContext</tt> allowing you to call its methods within the template.
+    // * `partials` An Object containing one or more partials (String templates
+    //   that are called from the main template).
+    //
+    var mustache = function(template, data, partials) {
+      data     = $.extend({}, this, data);
+      partials = $.extend({}, data.partials, partials);
+      return Mustache.to_html(template, data, partials);
+    };
+
+    // set the default method name/extension
+    if (!method_alias) method_alias = 'mustache';
+    app.helper(method_alias, mustache);
+
+  };
+
+})(jQuery);

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/sammy/plugins/sammy.nested_params.js
----------------------------------------------------------------------
diff --git a/attachments/sammy/plugins/sammy.nested_params.js b/attachments/sammy/plugins/sammy.nested_params.js
new file mode 100644
index 0000000..645f8c9
--- /dev/null
+++ b/attachments/sammy/plugins/sammy.nested_params.js
@@ -0,0 +1,118 @@
+(function($) {
+
+  Sammy = Sammy || {};
+
+  function parseValue(value) {
+    value = unescape(value);
+    if (value === "true") {
+      return true;
+    } else if (value === "false") {
+      return false;
+    } else {
+      return value;
+    }
+  };
+
+  function parseNestedParam(params, field_name, field_value) {
+    var match, name, rest;
+
+    if (field_name.match(/^[^\[]+$/)) {
+      // basic value
+      params[field_name] = parseValue(field_value);
+    } else if (match = field_name.match(/^([^\[]+)\[\](.*)$/)) {
+      // array
+      name = match[1];
+      rest = match[2];
+
+      if(params[name] && !$.isArray(params[name])) { throw('400 Bad Request'); }
+
+      if (rest) {
+        // array is not at the end of the parameter string
+        match = rest.match(/^\[([^\]]+)\](.*)$/);
+        if(!match) { throw('400 Bad Request'); }
+
+        if (params[name]) {
+          if(params[name][params[name].length - 1][match[1]]) {
+            params[name].push(parseNestedParam({}, match[1] + match[2], field_value));
+          } else {
+            $.extend(true, params[name][params[name].length - 1], parseNestedParam({}, match[1] + match[2], field_value));
+          }
+        } else {
+          params[name] = [parseNestedParam({}, match[1] + match[2], field_value)];
+        }
+      } else {
+        // array is at the end of the parameter string
+        if (params[name]) {
+          params[name].push(parseValue(field_value));
+        } else {
+          params[name] = [parseValue(field_value)];
+        }
+      }
+    } else if (match = field_name.match(/^([^\[]+)\[([^\[]+)\](.*)$/)) {
+      // hash
+      name = match[1];
+      rest = match[2] + match[3];
+
+      if (params[name] && $.isArray(params[name])) { throw('400 Bad Request'); }
+
+      if (params[name]) {
+        $.extend(true, params[name], parseNestedParam(params[name], rest, field_value));
+      } else {
+        params[name] = parseNestedParam({}, rest, field_value);
+      }
+    }
+    return params;
+  };
+
+  // <tt>Sammy.NestedParams</tt> overrides the default form parsing behavior to provide
+  // extended functionality for parsing Rack/Rails style form name/value pairs into JS
+  // Objects. In fact it passes the same suite of tests as Rack's nested query parsing.
+  // The code and tests were ported to JavaScript/Sammy by http://github.com/endor
+  //
+  // This allows you to translate a form with properly named inputs into a JSON object.
+  //
+  // ### Example
+  //
+  // Given an HTML form like so:
+  //
+  //     <form action="#/parse_me" method="post">
+  //       <input type="text" name="obj[first]" />
+  //       <input type="text" name="obj[second]" />
+  //       <input type="text" name="obj[hash][first]" />
+  //       <input type="text" name="obj[hash][second]" />
+  //     </form>
+  //
+  // And a Sammy app like:
+  //
+  //     var app = $.sammy(function(app) {
+  //       this.use(Sammy.NestedParams);
+  //
+  //       this.post('#/parse_me', function(context) {
+  //         $.log(this.params);
+  //       });
+  //     });
+  //
+  // If you filled out the form with some values and submitted it, you would see something
+  // like this in your log:
+  //
+  //     {
+  //       'obj': {
+  //         'first': 'value',
+  //         'second': 'value',
+  //         'hash': {
+  //           'first': 'value',
+  //           'second': 'value'
+  //         }
+  //       }
+  //     }
+  //
+  // It supports creating arrays with [] and other niceities. Check out the tests for
+  // full specs.
+  //
+  Sammy.NestedParams = function(app) {
+
+    app._parseParamPair = parseNestedParam;
+
+  };
+
+})(jQuery);

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/sammy/plugins/sammy.path_location_proxy.js
----------------------------------------------------------------------
diff --git a/attachments/sammy/plugins/sammy.path_location_proxy.js b/attachments/sammy/plugins/sammy.path_location_proxy.js
new file mode 100644
index 0000000..13f9014
--- /dev/null
+++ b/attachments/sammy/plugins/sammy.path_location_proxy.js
@@ -0,0 +1,29 @@
+(function($) {
+
+  Sammy = Sammy || {};
+
+  // `Sammy.PathLocationProxy` is a simple Location Proxy that just
+  // gets and sets window.location. This allows you to use
+  // Sammy to route on the full URL path instead of just the hash. It
+  // will take a full refresh to get the app to change state.
+  //
+  // To read more about location proxies, check out the
+  // documentation for `Sammy.HashLocationProxy`
+  Sammy.PathLocationProxy = function(app) {
+    this.app = app;
+  };
+
+  Sammy.PathLocationProxy.prototype = {
+    bind: function() {},
+    unbind: function() {},
+
+    getLocation: function() {
+      return [window.location.pathname, window.location.search].join('');
+    },
+
+    setLocation: function(new_location) {
+      return window.location = new_location;
+    }
+  };
+
+})(jQuery);

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/sammy/plugins/sammy.pure.js
----------------------------------------------------------------------
diff --git a/attachments/sammy/plugins/sammy.pure.js b/attachments/sammy/plugins/sammy.pure.js
new file mode 100644
index 0000000..16fe3df
--- /dev/null
+++ b/attachments/sammy/plugins/sammy.pure.js
@@ -0,0 +1,756 @@
+(function($) {
+
+/*!
+  PURE Unobtrusive Rendering Engine for HTML
+
+  Licensed under the MIT licenses.
+  More information at: http://www.opensource.org
+
+  Copyright (c) 2010 Michael Cvilic - BeeBole.com
+
+  Thanks to Rog Peppe for the functional JS jump
+  revision: 2.47
+*/
+
+var $p, pure = $p = function(){
+  var sel = arguments[0],
+    ctxt = false;
+
+  if(typeof sel === 'string'){
+    ctxt = arguments[1] || false;
+  }
+  return $p.core(sel, ctxt);
+};
+
+$p.core = function(sel, ctxt, plugins){
+  //get an instance of the plugins
+  var plugins = getPlugins(),
+    templates = [];
+
+  //search for the template node(s)
+  switch(typeof sel){
+    case 'string':
+      templates = plugins.find(ctxt || document, sel);
+      if(templates.length === 0) {
+        error('The template "' + sel + '" was not found');
+      }
+    break;
+    case 'undefined':
+      error('The template root is undefined, check your selector');
+    break;
+    default:
+      templates = [sel];
+  }
+
+  for(var i = 0, ii = templates.length; i < ii; i++){
+    plugins[i] = templates[i];
+  }
+  plugins.length = ii;
+
+  // set the signature string that will be replaced at render time
+  var Sig = '_s' + Math.floor( Math.random() * 1000000 ) + '_',
+    // another signature to prepend to attributes and avoid checks: style, height, on[events]...
+    attPfx = '_a' + Math.floor( Math.random() * 1000000 ) + '_',
+    // rx to parse selectors, e.g. "+tr.foo[class]"
+    selRx = /^(\+)?([^\@\+]+)?\@?([^\+]+)?(\+)?$/,
+    // set automatically attributes for some tags
+    autoAttr = {
+      IMG:'src',
+      INPUT:'value'
+    },
+    // check if the argument is an array - thanks salty-horse (Ori Avtalion)
+    isArray = Array.isArray ?
+      function(o) {
+        return Array.isArray(o);
+      } :
+      function(o) {
+        return Object.prototype.toString.call(o) === "[object Array]";
+      };
+
+  return plugins;
+
+
+  /* * * * * * * * * * * * * * * * * * * * * * * * * *
+    core functions
+   * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+
+  // error utility
+  function error(e){
+    if(typeof console !== 'undefined'){
+      console.log(e);
+    }else{ alert(e); }
+    throw('pure error: ' + e);
+  }
+
+  //return a new instance of plugins
+  function getPlugins(){
+    var plugins = $p.plugins,
+      f = function(){};
+    f.prototype = plugins;
+
+    // do not overwrite functions if external definition
+    f.prototype.compile    = plugins.compile || compile;
+    f.prototype.render     = plugins.render || render;
+    f.prototype.autoRender = plugins.autoRender || autoRender;
+    f.prototype.find       = plugins.find || find;
+
+    // give the compiler and the error handling to the plugin context
+    f.prototype._compiler  = compiler;
+    f.prototype._error     = error;
+
+    return new f();
+  }
+
+  // returns the outer HTML of a node
+  function outerHTML(node){
+    // if IE take the internal method otherwise build one
+    return node.outerHTML || (
+      function(n){
+            var div = document.createElement('div'), h;
+            div.appendChild( n.cloneNode(true) );
+        h = div.innerHTML;
+        div = null;
+        return h;
+      })(node);
+  }
+
+  // returns the string generator function
+  function wrapquote(qfn, f){
+    return function(ctxt){
+      return qfn('' + f.call(ctxt.context, ctxt));
+    };
+  }
+
+  // default find using querySelector when available on the browser
+  function find(n, sel){
+    if(typeof n === 'string'){
+      sel = n;
+      n = false;
+    }
+    if(typeof document.querySelectorAll !== 'undefined'){
+      return (n||document).querySelectorAll( sel );
+    }else{
+      error('You can test PURE standalone with: iPhone, FF3.5+, Safari4+ and IE8+\n\nTo run PURE on your browser, you need a JS library/framework with a CSS selector engine');
+    }
+  }
+
+  // create a function that concatenates constant string
+  // sections (given in parts) and the results of called
+  // functions to fill in the gaps between parts (fns).
+  // fns[n] fills in the gap between parts[n-1] and parts[n];
+  // fns[0] is unused.
+  // this is the inner template evaluation loop.
+  function concatenator(parts, fns){
+    return function(ctxt){
+      var strs = [ parts[ 0 ] ],
+        n = parts.length,
+        fnVal, pVal, attLine, pos;
+
+      for(var i = 1; i < n; i++){
+        fnVal = fns[i]( ctxt );
+        pVal = parts[i];
+
+        // if the value is empty and attribute, remove it
+        if(fnVal === ''){
+          attLine = strs[ strs.length - 1 ];
+          if( ( pos = attLine.search( /[\w]+=\"?$/ ) ) > -1){
+            strs[ strs.length - 1 ] = attLine.substring( 0, pos );
+            pVal = pVal.substr( 1 );
+          }
+        }
+
+        strs[ strs.length ] = fnVal;
+        strs[ strs.length ] = pVal;
+      }
+      return strs.join('');
+    };
+  }
+
+  // parse and check the loop directive
+  function parseloopspec(p){
+    var m = p.match( /^(\w+)\s*<-\s*(\S+)?$/ );
+    if(m === null){
+      error('bad loop spec: "' + p + '"');
+    }
+    if(m[1] === 'item'){
+      error('"item<-..." is a reserved word for the current running iteration.\n\nPlease choose another name for your loop.');
+    }
+    if( !m[2] || (m[2] && (/context/i).test(m[2]))){ //undefined or space(IE)
+      m[2] = function(ctxt){return ctxt.context;};
+    }
+    return {name: m[1], sel: m[2]};
+  }
+
+  // parse a data selector and return a function that
+  // can traverse the data accordingly, given a context.
+  function dataselectfn(sel){
+    if(typeof(sel) === 'function'){
+      return sel;
+    }
+    //check for a valid js variable name with hyphen(for properties only), $, _ and :
+    var m = sel.match(/^[a-zA-Z\$_\@][\w\$:-]*(\.[\w\$:-]*[^\.])*$/);
+    if(m === null){
+      var found = false, s = sel, parts = [], pfns = [], i = 0, retStr;
+      // check if literal
+      if(/\'|\"/.test( s.charAt(0) )){
+        if(/\'|\"/.test( s.charAt(s.length-1) )){
+          retStr = s.substring(1, s.length-1);
+          return function(){ return retStr; };
+        }
+      }else{
+        // check if literal + #{var}
+        while((m = s.match(/#\{([^{}]+)\}/)) !== null){
+          found = true;
+          parts[i++] = s.slice(0, m.index);
+          pfns[i] = dataselectfn(m[1]);
+          s = s.slice(m.index + m[0].length, s.length);
+        }
+      }
+      if(!found){
+        error('bad data selector syntax: ' + sel);
+      }
+      parts[i] = s;
+      return concatenator(parts, pfns);
+    }
+    m = sel.split('.');
+    return function(ctxt){
+      var data = ctxt.context;
+      if(!data){
+        return '';
+      }
+      var  v = ctxt[m[0]],
+        i = 0;
+      if(v && v.item){
+        data = v.item;
+        i += 1;
+      }
+      var n = m.length;
+      for(; i < n; i++){
+        if(!data){break;}
+        data = data[m[i]];
+      }
+      return (!data && data !== 0) ? '':data;
+    };
+  }
+
+  // wrap in an object the target node/attr and their properties
+  function gettarget(dom, sel, isloop){
+    var osel, prepend, selector, attr, append, target = [];
+    if( typeof sel === 'string' ){
+      osel = sel;
+      var m = sel.match(selRx);
+      if( !m ){
+        error( 'bad selector syntax: ' + sel );
+      }
+
+      prepend = m[1];
+      selector = m[2];
+      attr = m[3];
+      append = m[4];
+
+      if(selector === '.' || ( !selector && attr ) ){
+        target[0] = dom;
+      }else{
+        target = plugins.find(dom, selector);
+      }
+      if(!target || target.length === 0){
+        return error('The node "' + sel + '" was not found in the template');
+      }
+    }else{
+      // autoRender node
+      prepend = sel.prepend;
+      attr = sel.attr;
+      append = sel.append;
+      target = [dom];
+    }
+
+    if( prepend || append ){
+      if( prepend && append ){
+        error('append/prepend cannot take place at the same time');
+      }else if( isloop ){
+        error('no append/prepend/replace modifiers allowed for loop target');
+      }else if( append && isloop ){
+        error('cannot append with loop (sel: ' + osel + ')');
+      }
+    }
+    var setstr, getstr, quotefn, isStyle, isClass, attName, setfn;
+    if(attr){
+      isStyle = (/^style$/i).test(attr);
+      isClass = (/^class$/i).test(attr);
+      attName = isClass ? 'className' : attr;
+      setstr = function(node, s) {
+        node.setAttribute(attPfx + attr, s);
+        if (attName in node && !isStyle) {
+          node[attName] = '';
+        }
+        if (node.nodeType === 1) {
+          node.removeAttribute(attr);
+          isClass && node.removeAttribute(attName);
+        }
+      };
+      if (isStyle || isClass) {//IE no quotes special care
+        if(isStyle){
+          getstr = function(n){ return n.style.cssText; };
+        }else{
+          getstr = function(n){ return n.className;  };
+        }
+        quotefn = function(s){ return s.replace(/\"/g, '&quot;'); };
+      }else {
+        getstr = function(n){ return n.getAttribute(attr); };
+        quotefn = function(s){ return s.replace(/\"/g, '&quot;').replace(/\s/g, '&nbsp;'); };
+      }
+      if(prepend){
+        setfn = function(node, s){ setstr( node, s + getstr( node )); };
+      }else if(append){
+        setfn = function(node, s){ setstr( node, getstr( node ) + s); };
+      }else{
+        setfn = function(node, s){ setstr( node, s ); };
+      }
+    }else{
+      if (isloop) {
+        setfn = function(node, s) {
+          var pn = node.parentNode;
+          if (pn) {
+            //replace node with s
+            pn.insertBefore(document.createTextNode(s), node.nextSibling);
+            pn.removeChild(node);
+          }
+        };
+      } else {
+        if (prepend) {
+          setfn = function(node, s) { node.insertBefore(document.createTextNode(s), node.firstChild);  };
+        } else if (append) {
+          setfn = function(node, s) { node.appendChild(document.createTextNode(s));};
+        } else {
+          setfn = function(node, s) {
+            while (node.firstChild) { node.removeChild(node.firstChild); }
+            node.appendChild(document.createTextNode(s));
+          };
+        }
+      }
+      quotefn = function(s) { return s; };
+    }
+    return { attr: attr, nodes: target, set: setfn, sel: osel, quotefn: quotefn };
+  }
+
+  function setsig(target, n){
+    var sig = Sig + n + ':';
+    for(var i = 0; i < target.nodes.length; i++){
+      // could check for overlapping targets here.
+      target.set( target.nodes[i], sig );
+    }
+  }
+
+  // read de loop data, and pass it to the inner rendering function
+  function loopfn(name, dselect, inner, sorter, filter){
+    return function(ctxt){
+      var a = dselect(ctxt),
+        old = ctxt[name],
+        temp = { items : a },
+        filtered = 0,
+        length,
+        strs = [],
+        buildArg = function(idx, temp, ftr, len){
+          ctxt.pos = temp.pos = idx;
+          ctxt.item = temp.item = a[ idx ];
+          ctxt.items = a;
+          //if array, set a length property - filtered items
+          typeof len !== 'undefined' &&  (ctxt.length = len);
+          //if filter directive
+          if(typeof ftr === 'function' && ftr(ctxt) === false){
+            filtered++;
+            return;
+          }
+          strs.push( inner.call(temp, ctxt ) );
+        };
+      ctxt[name] = temp;
+      if( isArray(a) ){
+        length = a.length || 0;
+        // if sort directive
+        if(typeof sorter === 'function'){
+          a.sort(sorter);
+        }
+        //loop on array
+        for(var i = 0, ii = length; i < ii; i++){
+          buildArg(i, temp, filter, length - filtered);
+        }
+      }else{
+        if(a && typeof sorter !== 'undefined'){
+          error('sort is only available on arrays, not objects');
+        }
+        //loop on collections
+        for(var prop in a){
+          a.hasOwnProperty( prop ) && buildArg(prop, temp, filter);
+        }
+      }
+
+      typeof old !== 'undefined' ? ctxt[name] = old : delete ctxt[name];
+      return strs.join('');
+    };
+  }
+  // generate the template for a loop node
+  function loopgen(dom, sel, loop, fns){
+    var already = false, ls, sorter, filter, prop;
+    for(prop in loop){
+      if(loop.hasOwnProperty(prop)){
+        if(prop === 'sort'){
+          sorter = loop.sort;
+          continue;
+        }else if(prop === 'filter'){
+          filter = loop.filter;
+          continue;
+        }
+        if(already){
+          error('cannot have more than one loop on a target');
+        }
+        ls = prop;
+        already = true;
+      }
+    }
+    if(!ls){
+      error('Error in the selector: ' + sel + '\nA directive action must be a string, a function or a loop(<-)');
+    }
+    var dsel = loop[ls];
+    // if it's a simple data selector then we default to contents, not replacement.
+    if(typeof(dsel) === 'string' || typeof(dsel) === 'function'){
+      loop = {};
+      loop[ls] = {root: dsel};
+      return loopgen(dom, sel, loop, fns);
+    }
+    var spec = parseloopspec(ls),
+      itersel = dataselectfn(spec.sel),
+      target = gettarget(dom, sel, true),
+      nodes = target.nodes;
+
+    for(i = 0; i < nodes.length; i++){
+      var node = nodes[i],
+        inner = compiler(node, dsel);
+      fns[fns.length] = wrapquote(target.quotefn, loopfn(spec.name, itersel, inner, sorter, filter));
+      target.nodes = [node];    // N.B. side effect on target.
+      setsig(target, fns.length - 1);
+    }
+  }
+
+  function getAutoNodes(n, data){
+    var ns = n.getElementsByTagName('*'),
+      an = [],
+      openLoops = {a:[],l:{}},
+      cspec,
+      isNodeValue,
+      i, ii, j, jj, ni, cs, cj;
+    //for each node found in the template
+    for(i = -1, ii = ns.length; i < ii; i++){
+      ni = i > -1 ?ns[i]:n;
+      if(ni.nodeType === 1 && ni.className !== ''){
+        //when a className is found
+        cs = ni.className.split(' ');
+        // for each className
+        for(j = 0, jj=cs.length;j<jj;j++){
+          cj = cs[j];
+          // check if it is related to a context property
+          cspec = checkClass(cj, ni.tagName);
+          // if so, store the node, plus the type of data
+          if(cspec !== false){
+            isNodeValue = (/nodevalue/i).test(cspec.attr);
+            if(cspec.sel.indexOf('@') > -1 || isNodeValue){
+              ni.className = ni.className.replace('@'+cspec.attr, '');
+              if(isNodeValue){
+                cspec.attr = false;
+              }
+            }
+            an.push({n:ni, cspec:cspec});
+          }
+        }
+      }
+    }
+    return an;
+
+    function checkClass(c, tagName){
+      // read the class
+      var ca = c.match(selRx),
+        attr = ca[3] || autoAttr[tagName],
+        cspec = {prepend:!!ca[1], prop:ca[2], attr:attr, append:!!ca[4], sel:c},
+        i, ii, loopi, loopil, val;
+      // check in existing open loops
+      for(i = openLoops.a.length-1; i >= 0; i--){
+        loopi = openLoops.a[i];
+        loopil = loopi.l[0];
+        val = loopil && loopil[cspec.prop];
+        if(typeof val !== 'undefined'){
+          cspec.prop = loopi.p + '.' + cspec.prop;
+          if(openLoops.l[cspec.prop] === true){
+            val = val[0];
+          }
+          break;
+        }
+      }
+      // not found check first level of data
+      if(typeof val === 'undefined'){
+        val = isArray(data) ? data[0][cspec.prop] : data[cspec.prop];
+        // nothing found return
+        if(typeof val === 'undefined'){
+          return false;
+        }
+      }
+      // set the spec for autoNode
+      if(isArray(val)){
+        openLoops.a.push( {l:val, p:cspec.prop} );
+        openLoops.l[cspec.prop] = true;
+        cspec.t = 'loop';
+      }else{
+        cspec.t = 'str';
+      }
+      return cspec;
+    }
+  }
+
+  // returns a function that, given a context argument,
+  // will render the template defined by dom and directive.
+  function compiler(dom, directive, data, ans){
+    var fns = [];
+    // autoRendering nodes parsing -> auto-nodes
+    ans = ans || data && getAutoNodes(dom, data);
+    if(data){
+      var j, jj, cspec, n, target, nodes, itersel, node, inner;
+      // for each auto-nodes
+      while(ans.length > 0){
+        cspec = ans[0].cspec;
+        n = ans[0].n;
+        ans.splice(0, 1);
+        if(cspec.t === 'str'){
+          // if the target is a value
+          target = gettarget(n, cspec, false);
+          setsig(target, fns.length);
+          fns[fns.length] = wrapquote(target.quotefn, dataselectfn(cspec.prop));
+        }else{
+          // if the target is a loop
+          itersel = dataselectfn(cspec.sel);
+          target = gettarget(n, cspec, true);
+          nodes = target.nodes;
+          for(j = 0, jj = nodes.length; j < jj; j++){
+            node = nodes[j];
+            inner = compiler(node, false, data, ans);
+            fns[fns.length] = wrapquote(target.quotefn, loopfn(cspec.sel, itersel, inner));
+            target.nodes = [node];
+            setsig(target, fns.length - 1);
+          }
+        }
+      }
+    }
+    // read directives
+    var target, dsel;
+    for(var sel in directive){
+      if(directive.hasOwnProperty(sel)){
+        dsel = directive[sel];
+        if(typeof(dsel) === 'function' || typeof(dsel) === 'string'){
+          // set the value for the node/attr
+          target = gettarget(dom, sel, false);
+          setsig(target, fns.length);
+          fns[fns.length] = wrapquote(target.quotefn, dataselectfn(dsel));
+        }else{
+          // loop on node
+          loopgen(dom, sel, dsel, fns);
+        }
+      }
+    }
+        // convert node to a string
+        var h = outerHTML(dom), pfns = [];
+    // IE adds an unremovable "selected, value" attribute
+    // hard replace while waiting for a better solution
+        h = h.replace(/<([^>]+)\s(value\=""|selected)\s?([^>]*)>/ig, "<$1 $3>");
+
+        // remove attribute prefix
+        h = h.split(attPfx).join('');
+
+    // slice the html string at "Sig"
+    var parts = h.split( Sig ), p;
+    // for each slice add the return string of
+    for(var i = 1; i < parts.length; i++){
+      p = parts[i];
+      // part is of the form "fn-number:..." as placed there by setsig.
+      pfns[i] = fns[ parseInt(p, 10) ];
+      parts[i] = p.substring( p.indexOf(':') + 1 );
+    }
+    return concatenator(parts, pfns);
+  }
+  // compile the template with directive
+  // if a context is passed, the autoRendering is triggered automatically
+  // return a function waiting the data as argument
+  function compile(directive, ctxt, template){
+    var rfn = compiler( ( template || this[0] ).cloneNode(true), directive, ctxt);
+    return function(context){
+      return rfn({context:context});
+    };
+  }
+  //compile with the directive as argument
+  // run the template function on the context argument
+  // return an HTML string
+  // should replace the template and return this
+  function render(ctxt, directive){
+    var fn = typeof directive === 'function' ? directive : plugins.compile( directive, false, this[0] );
+    for(var i = 0, ii = this.length; i < ii; i++){
+      this[i] = replaceWith( this[i], fn( ctxt, false ));
+    }
+    context = null;
+    return this;
+  }
+
+  // compile the template with autoRender
+  // run the template function on the context argument
+  // return an HTML string
+  function autoRender(ctxt, directive){
+    var fn = plugins.compile( directive, ctxt, this[0] );
+    for(var i = 0, ii = this.length; i < ii; i++){
+      this[i] = replaceWith( this[i], fn( ctxt, false));
+    }
+    context = null;
+    return this;
+  }
+
+  function replaceWith(elm, html) {
+    var ne,
+      ep = elm.parentNode,
+      depth = 0;
+    switch (elm.tagName) {
+      case 'TBODY': case 'THEAD': case 'TFOOT':
+        html = '<TABLE>' + html + '</TABLE>';
+        depth = 1;
+      break;
+      case 'TR':
+        html = '<TABLE><TBODY>' + html + '</TBODY></TABLE>';
+        depth = 2;
+      break;
+      case 'TD': case 'TH':
+        html = '<TABLE><TBODY><TR>' + html + '</TR></TBODY></TABLE>';
+        depth = 3;
+      break;
+    }
+    tmp = document.createElement('SPAN');
+    tmp.style.display = 'none';
+    document.body.appendChild(tmp);
+    tmp.innerHTML = html;
+    ne = tmp.firstChild;
+    while (depth--) {
+      ne = ne.firstChild;
+    }
+    ep.insertBefore(ne, elm);
+    ep.removeChild(elm);
+    document.body.removeChild(tmp);
+    elm = ne;
+
+    ne = ep = null;
+    return elm;
+  }
+};
+
+$p.plugins = {};
+
+$p.libs = {
+  dojo:function(){
+    if(typeof document.querySelector === 'undefined'){
+      $p.plugins.find = function(n, sel){
+        return dojo.query(sel, n);
+      };
+    }
+  },
+  domassistant:function(){
+    if(typeof document.querySelector === 'undefined'){
+      $p.plugins.find = function(n, sel){
+        return $(n).cssSelect(sel);
+      };
+    }
+    DOMAssistant.attach({
+      publicMethods : [ 'compile', 'render', 'autoRender'],
+      compile:function(directive, ctxt){ return $p(this).compile(directive, ctxt); },
+      render:function(ctxt, directive){ return $( $p(this).render(ctxt, directive) )[0]; },
+      autoRender:function(ctxt, directive){ return $( $p(this).autoRender(ctxt, directive) )[0]; }
+    });
+  },
+  jquery:function(){
+    if(typeof document.querySelector === 'undefined'){
+      $p.plugins.find = function(n, sel){
+        return jQuery(n).find(sel);
+      };
+    }
+    jQuery.fn.extend({
+      compile:function(directive, ctxt){ return $p(this[0]).compile(directive, ctxt); },
+      render:function(ctxt, directive){ return jQuery( $p( this[0] ).render( ctxt, directive ) ); },
+      autoRender:function(ctxt, directive){ return jQuery( $p( this[0] ).autoRender( ctxt, directive ) ); }
+    });
+  },
+  mootools:function(){
+    if(typeof document.querySelector === 'undefined'){
+      $p.plugins.find = function(n, sel){
+        return $(n).getElements(sel);
+      };
+    }
+    Element.implement({
+      compile:function(directive, ctxt){ return $p(this).compile(directive, ctxt); },
+      render:function(ctxt, directive){ return $p(this).render(ctxt, directive); },
+      autoRender:function(ctxt, directive){ return $p(this).autoRender(ctxt, directive); }
+    });
+  },
+  prototype:function(){
+    if(typeof document.querySelector === 'undefined'){
+      $p.plugins.find = function(n, sel){
+        n = n === document ? n.body : n;
+        return typeof n === 'string' ? $$(n) : $(n).select(sel);
+      };
+    }
+    Element.addMethods({
+      compile:function(element, directive, ctxt){ return $p(element).compile(directive, ctxt); },
+      render:function(element, ctxt, directive){ return $p(element).render(ctxt, directive); },
+      autoRender:function(element, ctxt, directive){ return $p(element).autoRender(ctxt, directive); }
+    });
+  },
+  sizzle:function(){
+    if(typeof document.querySelector === 'undefined'){
+      $p.plugins.find = function(n, sel){
+        return Sizzle(sel, n);
+      };
+    }
+  },
+  sly:function(){
+    if(typeof document.querySelector === 'undefined'){
+      $p.plugins.find = function(n, sel){
+        return Sly(sel, n);
+      };
+    }
+  }
+};
+
+// get lib specifics if available
+(function(){
+  var libkey =
+    typeof dojo         !== 'undefined' && 'dojo' ||
+    typeof DOMAssistant !== 'undefined' && 'domassistant' ||
+    typeof jQuery       !== 'undefined' && 'jquery' ||
+    typeof MooTools     !== 'undefined' && 'mootools' ||
+    typeof Prototype    !== 'undefined' && 'prototype' ||
+    typeof Sizzle       !== 'undefined' && 'sizzle' ||
+    typeof Sly          !== 'undefined' && 'sly';
+
+  libkey && $p.libs[libkey]();
+})();
+
+
+  Sammy = Sammy || {};
+
+  // `Sammy.Pure` is a simple wrapper around the pure.js templating engine for
+  // use in Sammy apps.
+  //
+  // See http://beebole.com/pure/ for detailed documentation.
+  Sammy.Pure = function(app, method_alias) {
+
+    var pure = function(template, data, directives) {
+      return $(template).autoRender(data, directives);
+    };
+
+    // set the default method name/extension
+    if (!method_alias) method_alias = 'pure';
+    app.helper(method_alias, pure);
+
+  };
+
+})(jQuery);

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/sammy/plugins/sammy.storage.js
----------------------------------------------------------------------
diff --git a/attachments/sammy/plugins/sammy.storage.js b/attachments/sammy/plugins/sammy.storage.js
new file mode 100644
index 0000000..d97ab93
--- /dev/null
+++ b/attachments/sammy/plugins/sammy.storage.js
@@ -0,0 +1,577 @@
+(function($) {
+
+  Sammy = Sammy || {};
+
+  // Sammy.Store is an abstract adapter class that wraps the multitude of in
+  // browser data storage into a single common set of methods for storing and
+  // retreiving data. The JSON library is used (through the inclusion of the
+  // Sammy.JSON) plugin, to automatically convert objects back and forth from
+  // stored strings.
+  //
+  // Sammy.Store can be used directly, but within a Sammy.Application it is much
+  // easier to use the `Sammy.Storage` plugin and its helper methods.
+  //
+  // Sammy.Store also supports the KVO pattern, by firing DOM/jQuery Events when
+  // a key is set.
+  //
+  // ### Example
+  //
+  //      // create a new store named 'mystore', tied to the #main element, using HTML5 localStorage
+  //      // Note: localStorage only works on browsers that support it
+  //      var store = new Sammy.Store({name: 'mystore', element: '#element', type: 'local'});
+  //      store.set('foo', 'bar');
+  //      store.get('foo'); //=> 'bar'
+  //      store.set('json', {obj: 'this is an obj'});
+  //      store.get('json'); //=> {obj: 'this is an obj'}
+  //      store.keys(); //=> ['foo','json']
+  //      store.clear('foo');
+  //      store.keys(); //=> ['json']
+  //      store.clearAll();
+  //      store.keys(); //=> []
+  //
+  // ### Arguments
+  //
+  // The constructor takes a single argument which is a Object containing these possible options.
+  //
+  // * `name` The name/namespace of this store. Stores are unique by name/type. (default 'store')
+  // * `element` A selector for the element that the store is bound to. (default 'body')
+  // * `type` The type of storage/proxy to use (default 'memory')
+  //
+  // Extra options are passed to the storage constructor.
+  // Sammy.Store supports the following methods of storage:
+  //
+  // * `memory` Basic object storage
+  // * `data` jQuery.data DOM Storage
+  // * `cookie` Access to document.cookie. Limited to 2K
+  // * `local` HTML5 DOM localStorage, browswer support is currently limited.
+  // * `session` HTML5 DOM sessionStorage, browswer support is currently limited.
+  //
+  Sammy.Store = function(options) {
+    var store = this;
+    this.options  = options || {};
+    this.name     = this.options.name || 'store';
+    this.element  = this.options.element || 'body';
+    this.$element = $(this.element);
+    if ($.isArray(this.options.type)) {
+      $.each(this.options.type, function(i, type) {
+        if (Sammy.Store.isAvailable(type)) {
+          store.type = type;
+          return false;
+        }
+      });
+    } else {
+      this.type = this.options.type || 'memory';
+    }
+    this.meta_key = this.options.meta_key || '__keys__';
+    this.storage  = new Sammy.Store[Sammy.Store.stores[this.type]](this.name, this.element, this.options);
+  };
+
+  Sammy.Store.stores = {
+    'memory': 'Memory',
+    'data': 'Data',
+    'local': 'LocalStorage',
+    'session': 'SessionStorage',
+    'cookie': 'Cookie'
+  };
+
+  $.extend(Sammy.Store.prototype, {
+    // Checks for the availability of the current storage type in the current browser/config.
+    isAvailable: function() {
+      if ($.isFunction(this.storage.isAvailable)) {
+        return this.storage.isAvailable();
+      } else {
+        true;
+      }
+    },
+    // Checks for the existance of `key` in the current store. Returns a boolean.
+    exists: function(key) {
+      return this.storage.exists(key);
+    },
+    // Sets the value of `key` with `value`. If `value` is an
+    // object, it is turned to and stored as a string with `JSON.stringify`.
+    // It also tries to conform to the KVO pattern triggering jQuery events on the
+    // element that the store is bound to.
+    //
+    // ### Example
+    //
+    //      var store = new Sammy.Store({name: 'kvo'});
+    //      $('body').bind('set-kvo-foo', function(e, data) {
+    //        Sammy.log(data.key + ' changed to ' + data.value);
+    //      });
+    //      store.set('foo', 'bar'); // logged: foo changed to bar
+    //
+    set: function(key, value) {
+      var string_value = (typeof value == 'string') ? value : JSON.stringify(value);
+      key = key.toString();
+      this.storage.set(key, string_value);
+      if (key != this.meta_key) {
+        this._addKey(key);
+        this.$element.trigger('set-' + this.name, {key: key, value: value});
+        this.$element.trigger('set-' + this.name + '-' + key, {key: key, value: value});
+      };
+      // always return the original value
+      return value;
+    },
+    // Returns the set value at `key`, parsing with `JSON.parse` and
+    // turning into an object if possible
+    get: function(key) {
+      var value = this.storage.get(key);
+      if (typeof value == 'undefined' || value == null || value == '') {
+        return value;
+      }
+      try {
+        return JSON.parse(value);
+      } catch(e) {
+        return value;
+      }
+    },
+    // Removes the value at `key` from the current store
+    clear: function(key) {
+      this._removeKey(key);
+      return this.storage.clear(key);
+    },
+    // Clears all the values for the current store.
+    clearAll: function() {
+      var self = this;
+      this.each(function(key, value) {
+        self.clear(key);
+      });
+    },
+    // Returns the all the keys set for the current store as an array.
+    // Internally Sammy.Store keeps this array in a 'meta_key' for easy access.
+    keys: function() {
+      return this.get(this.meta_key) || [];
+    },
+    // Iterates over each key value pair passing them to the `callback` function
+    //
+    // ### Example
+    //
+    //      store.each(function(key, value) {
+    //        Sammy.log('key', key, 'value', value);
+    //      });
+    //
+    each: function(callback) {
+      var i = 0,
+          keys = this.keys(),
+          returned;
+
+      for (i; i < keys.length; i++) {
+        returned = callback(keys[i], this.get(keys[i]));
+        if (returned === false) { return false; }
+      };
+    },
+    // Filters the store by a filter function that takes a key value.
+    // Returns an array of arrays where the first element of each array
+    // is the key and the second is the value of that key.
+    //
+    // ### Example
+    //
+    //      var store = new Sammy.Store;
+    //      store.set('one', 'two');
+    //      store.set('two', 'three');
+    //      store.set('1', 'two');
+    //      var returned = store.filter(function(key, value) {
+    //        // only return
+    //        return value === 'two';
+    //      });
+    //      // returned => [['one', 'two'], ['1', 'two']];
+    //
+    filter: function(callback) {
+      var found = [];
+      this.each(function(key, value) {
+        if (callback(key, value)) {
+          found.push([key, value]);
+        }
+        return true;
+      });
+      return found;
+    },
+    // Works exactly like filter except only returns the first matching key
+    // value pair instead of all of them
+    first: function(callback) {
+      var found = false;
+      this.each(function(key, value) {
+        if (callback(key, value)) {
+          found = [key, value];
+          return false;
+        }
+      });
+      return found;
+    },
+    // Returns the value at `key` if set, otherwise, runs the callback
+    // and sets the value to the value returned in the callback.
+    //
+    // ### Example
+    //
+    //    var store = new Sammy.Store;
+    //    store.exists('foo'); //=> false
+    //    store.fetch('foo', function() {
+    //      return 'bar!';
+    //    }); //=> 'bar!'
+    //    store.get('foo') //=> 'bar!'
+    //    store.fetch('foo', function() {
+    //      return 'baz!';
+    //    }); //=> 'bar!
+    //
+    fetch: function(key, callback) {
+      if (!this.exists(key)) {
+        return this.set(key, callback.apply(this));
+      } else {
+        return this.get(key);
+      }
+    },
+    // loads the response of a request to `path` into `key`.
+    //
+    // ### Example
+    //
+    // In /mytemplate.tpl:
+    //
+    //    My Template
+    //
+    // In app.js:
+    //
+    //    var store = new Sammy.Store;
+    //    store.load('mytemplate', '/mytemplate.tpl', function() {
+    //      s.get('mytemplate') //=> My Template
+    //    });
+    //
+    load: function(key, path, callback) {
+      var s = this;
+      $.get(path, function(response) {
+        s.set(key, response);
+        if (callback) { callback.apply(this, [response]); }
+      });
+    },
+
+    _addKey: function(key) {
+      var keys = this.keys();
+      if ($.inArray(key, keys) == -1) { keys.push(key); }
+      this.set(this.meta_key, keys);
+    },
+    _removeKey: function(key) {
+      var keys = this.keys();
+      var index = $.inArray(key, keys);
+      if (index != -1) { keys.splice(index, 1); }
+      this.set(this.meta_key, keys);
+    }
+  });
+
+  // Tests if the type of storage is available/works in the current browser/config.
+  // Especially useful for testing the availability of the awesome, but not widely
+  // supported HTML5 DOM storage
+  Sammy.Store.isAvailable = function(type) {
+    try {
+      return Sammy.Store[Sammy.Store.stores[type]].prototype.isAvailable();
+    } catch(e) {
+      return false;
+    }
+  };
+
+  // Memory ('memory') is the basic/default store. It stores data in a global
+  // JS object. Data is lost on refresh.
+  Sammy.Store.Memory = function(name, element) {
+    this.name  = name;
+    this.element = element;
+    this.namespace = [this.element, this.name].join('.');
+    Sammy.Store.Memory.store = Sammy.Store.Memory.store || {};
+    Sammy.Store.Memory.store[this.namespace] = Sammy.Store.Memory.store[this.namespace] || {};
+    this.store = Sammy.Store.Memory.store[this.namespace];
+  };
+  $.extend(Sammy.Store.Memory.prototype, {
+    isAvailable: function() { return true; },
+    exists: function(key) {
+      return (typeof this.store[key] != "undefined");
+    },
+    set: function(key, value) {
+      return this.store[key] = value;
+    },
+    get: function(key) {
+      return this.store[key];
+    },
+    clear: function(key) {
+      delete this.store[key];
+    }
+  });
+
+  // Data ('data') stores objects using the jQuery.data() methods. This has the advantadge
+  // of scoping the data to the specific element. Like the 'memory' store its data
+  // will only last for the length of the current request (data is lost on refresh/etc).
+  Sammy.Store.Data = function(name, element) {
+    this.name = name;
+    this.element = element;
+    this.$element = $(element);
+  };
+  $.extend(Sammy.Store.Data.prototype, {
+    isAvailable: function() { return true; },
+    exists: function(key) {
+      return (typeof this.$element.data(this._key(key)) != "undefined");
+    },
+    set: function(key, value) {
+      return this.$element.data(this._key(key), value);
+    },
+    get: function(key) {
+      return this.$element.data(this._key(key));
+    },
+    clear: function(key) {
+      this.$element.removeData(this._key(key));
+    },
+    _key: function(key) {
+      return ['store', this.name, key].join('.');
+    }
+  });
+
+  // LocalStorage ('local') makes use of HTML5 DOM Storage, and the window.localStorage
+  // object. The great advantage of this method is that data will persist beyond
+  // the current request. It can be considered a pretty awesome replacement for
+  // cookies accessed via JS. The great disadvantage, though, is its only available
+  // on the latest and greatest browsers.
+  //
+  // For more info on DOM Storage:
+  // [https://developer.mozilla.org/en/DOM/Storage]
+  // [http://www.w3.org/TR/2009/WD-webstorage-20091222/]
+  //
+  Sammy.Store.LocalStorage = function(name, element) {
+    this.name = name;
+    this.element = element;
+  };
+  $.extend(Sammy.Store.LocalStorage.prototype, {
+    isAvailable: function() {
+      return ('localStorage' in window) && (window.location.protocol != 'file:');
+    },
+    exists: function(key) {
+      return (this.get(key) != null);
+    },
+    set: function(key, value) {
+      return window.localStorage.setItem(this._key(key), value);
+    },
+    get: function(key) {
+      return window.localStorage.getItem(this._key(key));
+    },
+    clear: function(key) {
+      window.localStorage.removeItem(this._key(key));;
+    },
+    _key: function(key) {
+      return ['store', this.element, this.name, key].join('.');
+    }
+  });
+
+  // .SessionStorage ('session') is similar to LocalStorage (part of the same API)
+  // and shares similar browser support/availability. The difference is that
+  // SessionStorage is only persistant through the current 'session' which is defined
+  // as the length that the current window is open. This means that data will survive
+  // refreshes but not close/open or multiple windows/tabs. For more info, check out
+  // the `LocalStorage` documentation and links.
+  Sammy.Store.SessionStorage = function(name, element) {
+    this.name = name;
+    this.element = element;
+  };
+  $.extend(Sammy.Store.SessionStorage.prototype, {
+    isAvailable: function() {
+      return ('sessionStorage' in window) &&
+      (window.location.protocol != 'file:') &&
+      ($.isFunction(window.sessionStorage.setItem));
+    },
+    exists: function(key) {
+      return (this.get(key) != null);
+    },
+    set: function(key, value) {
+      return window.sessionStorage.setItem(this._key(key), value);
+    },
+    get: function(key) {
+      var value = window.sessionStorage.getItem(this._key(key));
+      if (value && typeof value.value != "undefined") { value = value.value }
+      return value;
+    },
+    clear: function(key) {
+      window.sessionStorage.removeItem(this._key(key));;
+    },
+    _key: function(key) {
+      return ['store', this.element, this.name, key].join('.');
+    }
+  });
+
+  // .Cookie ('cookie') storage uses browser cookies to store data. JavaScript
+  // has access to a single document.cookie variable, which is limited to 2Kb in
+  // size. Cookies are also considered 'unsecure' as the data can be read easily
+  // by other sites/JS. Cookies do have the advantage, though, of being widely
+  // supported and persistent through refresh and close/open. Where available,
+  // HTML5 DOM Storage like LocalStorage and SessionStorage should be used.
+  //
+  // .Cookie can also take additional options:
+  //
+  // * `expires_in` Number of seconds to keep the cookie alive (default 2 weeks).
+  // * `path` The path to activate the current cookie for (default '/').
+  //
+  // For more information about document.cookie, check out the pre-eminint article
+  // by ppk: [http://www.quirksmode.org/js/cookies.html]
+  //
+  Sammy.Store.Cookie = function(name, element, options) {
+    this.name = name;
+    this.element = element;
+    this.options = options || {};
+    this.path = this.options.path || '/';
+    // set the expires in seconds or default 14 days
+    this.expires_in = this.options.expires_in || (14 * 24 * 60 * 60);
+  };
+  $.extend(Sammy.Store.Cookie.prototype, {
+    isAvailable: function() {
+      return ('cookie' in document) && (window.location.protocol != 'file:');
+    },
+    exists: function(key) {
+      return (this.get(key) != null);
+    },
+    set: function(key, value) {
+      return this._setCookie(key, value);
+    },
+    get: function(key) {
+      return this._getCookie(key);
+    },
+    clear: function(key) {
+      this._setCookie(key, "", -1);
+    },
+    _key: function(key) {
+      return ['store', this.element, this.name, key].join('.');
+    },
+    _getCookie: function(key) {
+      var escaped = this._key(key).replace(/(\.|\*|\(|\)|\[|\])/g, '\\$1');
+      var match = document.cookie.match("(^|;\\s)" + escaped + "=([^;]*)(;|$)")
+      return (match ? match[2] : null);
+    },
+    _setCookie: function(key, value, expires) {
+      if (!expires) { expires = (this.expires_in * 1000) }
+      var date = new Date();
+      date.setTime(date.getTime() + expires);
+      var set_cookie = [
+        this._key(key), "=", value,
+        "; expires=", date.toGMTString(),
+        "; path=", this.path
+      ].join('');
+      document.cookie = set_cookie;
+    }
+  });
+
+  // Sammy.Storage is a plugin that provides shortcuts for creating and using
+  // Sammy.Store objects. Once included it provides the `store()` app level
+  // and helper methods. Depends on Sammy.JSON (or json2.js).
+  Sammy.Storage = function(app) {
+    this.use(Sammy.JSON);
+
+    this.stores = this.stores || {};
+
+    // `store()` creates and looks up existing `Sammy.Store` objects
+    // for the current application. The first time used for a given `'name'`
+    // initializes a `Sammy.Store` and also creates a helper under the store's
+    // name.
+    //
+    // ### Example
+    //
+    //      var app = $.sammy(function() {
+    //        this.use(Sammy.Storage);
+    //
+    //        // initializes the store on app creation.
+    //        this.store('mystore', {type: 'cookie'});
+    //
+    //        this.get('#/', function() {
+    //          // returns the Sammy.Store object
+    //          this.store('mystore');
+    //          // sets 'foo' to 'bar' using the shortcut/helper
+    //          // equivilent to this.store('mystore').set('foo', 'bar');
+    //          this.mystore('foo', 'bar');
+    //          // returns 'bar'
+    //          // equivilent to this.store('mystore').get('foo');
+    //          this.mystore('foo');
+    //          // returns 'baz!'
+    //          // equivilent to:
+    //          // this.store('mystore').fetch('foo!', function() {
+    //          //   return 'baz!';
+    //          // })
+    //          this.mystore('foo!', function() {
+    //            return 'baz!';
+    //          });
+    //
+    //          this.clearMystore();
+    //          // equivilent to:
+    //          // this.store('mystore').clearAll()
+    //        });
+    //
+    //      });
+    //
+    // ### Arguments
+    //
+    // * `name` The name of the store and helper. the name must be unique per application.
+    // * `options` A JS object of options that can be passed to the Store constuctor on initialization.
+    //
+    this.store = function(name, options) {
+      // if the store has not been initialized
+      if (typeof this.stores[name] == 'undefined') {
+        // create initialize the store
+        var clear_method_name = "clear" + name.substr(0,1).toUpperCase() + name.substr(1);
+        this.stores[name] = new Sammy.Store($.extend({
+          name: name,
+          element: this.element_selector
+        }, options || {}));
+        // app.name()
+        this[name] = function(key, value) {
+          if (typeof value == 'undefined') {
+            return this.stores[name].get(key);
+          } else if ($.isFunction(value)) {
+            return this.stores[name].fetch(key, value);
+          } else {
+            return this.stores[name].set(key, value)
+          }
+        };
+        // app.clearName();
+        this[clear_method_name] = function() {
+          return this.stores[name].clearAll();
+        }
+        // context.name()
+        this.helper(name, function() {
+          return this.app[name].apply(this.app, arguments);
+        });
+        // context.clearName();
+        this.helper(clear_method_name, function() {
+          return this.app[clear_method_name]();
+        });
+      }
+      return this.stores[name];
+    };
+
+    this.helpers({
+      store: function() {
+        return this.app.store.apply(this.app, arguments);
+      }
+    });
+  };
+
+  // Sammy.Session is an additional plugin for creating a common 'session' store
+  // for the given app. It is a very simple wrapper around `Sammy.Storage`
+  // that provides a simple fallback mechanism for trying to provide the best
+  // possible storage type for the session. This means, `LocalStorage`
+  // if available, otherwise `Cookie`, otherwise `Memory`.
+  // It provides the `session()` helper through `Sammy.Storage#store()`.
+  //
+  // See the `Sammy.Storage` plugin for full documentation.
+  //
+  Sammy.Session = function(app, options) {
+    this.use(Sammy.Storage);
+    // check for local storage, then cookie storage, then just use memory
+    this.store('session', $.extend({type: ['local', 'cookie', 'memory']}, options));
+  };
+
+  // Sammy.Cache provides helpers for caching data within the lifecycle of a
+  // Sammy app. The plugin provides two main methods on `Sammy.Application`,
+  // `cache` and `clearCache`. Each app has its own cache store so that
+  // you dont have to worry about collisions. As of 0.5 the original Sammy.Cache module
+  // has been deprecated in favor of this one based on Sammy.Storage. The exposed
+  // API is almost identical, but Sammy.Storage provides additional backends including
+  // HTML5 Storage. `Sammy.Cache` will try to use these backends when available
+  // (in this order) `LocalStorage`, `SessionStorage`, and `Memory`
+  Sammy.Cache = function(app, options) {
+    this.use(Sammy.Storage);
+    // set cache_partials to true
+    this.cache_partials = true;
+    // check for local storage, then session storage, then just use memory
+    this.store('cache', $.extend({type: ['local', 'session', 'memory']}, options));
+  };
+
+})(jQuery);

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/sammy/plugins/sammy.template.js
----------------------------------------------------------------------
diff --git a/attachments/sammy/plugins/sammy.template.js b/attachments/sammy/plugins/sammy.template.js
new file mode 100644
index 0000000..f24c23e
--- /dev/null
+++ b/attachments/sammy/plugins/sammy.template.js
@@ -0,0 +1,117 @@
+(function($) {
+
+  // Simple JavaScript Templating
+  // John Resig - http://ejohn.org/ - MIT Licensed
+  // adapted from: http://ejohn.org/blog/javascript-micro-templating/
+  // originally $.srender by Greg Borenstein http://ideasfordozens.com in Feb 2009
+  // modified for Sammy by Aaron Quint for caching templates by name
+  var srender_cache = {};
+  var srender = function(name, template, data) {
+    // target is an optional element; if provided, the result will be inserted into it
+    // otherwise the result will simply be returned to the caller
+    if (srender_cache[name]) {
+      fn = srender_cache[name];
+    } else {
+      if (typeof template == 'undefined') {
+        // was a cache check, return false
+        return false;
+      }
+      // Generate a reusable function that will serve as a template
+      // generator (and which will be cached).
+      fn = srender_cache[name] = new Function("obj",
+      "var p=[],print=function(){p.push.apply(p,arguments);};" +
+
+      // Introduce the data as local variables using with(){}
+      "with(obj){p.push(\"" +
+
+      // Convert the template into pure JavaScript
+      template
+        .replace(/[\r\t\n]/g, " ")
+        .replace(/\"/g, '\\"')
+        .split("<%").join("\t")
+        .replace(/((^|%>)[^\t]*)/g, "$1\r")
+        .replace(/\t=(.*?)%>/g, "\",$1,\"")
+        .split("\t").join("\");")
+        .split("%>").join("p.push(\"")
+        .split("\r").join("")
+        + "\");}return p.join('');");
+    }
+
+    if (typeof data != 'undefined') {
+      return fn(data);
+    } else {
+      return fn;
+    }
+  };
+
+  Sammy = Sammy || {};
+
+  // <tt>Sammy.Template</tt> is a simple plugin that provides a way to create
+  // and render client side templates. The rendering code is based on John Resig's
+  // quick templates and Greg Borenstien's srender plugin.
+  // This is also a great template/boilerplate for Sammy plugins.
+  //
+  // Templates use <% %> tags to denote embedded javascript.
+  //
+  // ### Examples
+  //
+  // Here is an example template (user.template):
+  //
+  //      <div class="user">
+  //        <div class="user-name"><%= user.name %></div>
+  //        <% if (user.photo_url) { %>
+  //          <div class="photo"><img src="<%= user.photo_url %>" /></div>
+  //        <% } %>
+  //      </div>
+  //
+  // Given that is a publicly accesible file, you would render it like:
+  //
+  //       $.sammy(function() {
+  //         // include the plugin
+  //         this.use(Sammy.Template);
+  //
+  //         this.get('#/', function() {
+  //           // the template is rendered in the current context.
+  //           this.user = {name: 'Aaron Quint'};
+  //           // partial calls template() because of the file extension
+  //           this.partial('user.template');
+  //         })
+  //       });
+  //
+  // You can also pass a second argument to use() that will alias the template
+  // method and therefore allow you to use a different extension for template files
+  // in <tt>partial()</tt>
+  //
+  //      // alias to 'tpl'
+  //      this.use(Sammy.Template, 'tpl');
+  //
+  //      // now .tpl files will be run through srender
+  //      this.get('#/', function() {
+  //        this.partial('myfile.tpl');
+  //      });
+  //
+  Sammy.Template = function(app, method_alias) {
+
+    // *Helper:* Uses simple templating to parse ERB like templates.
+    //
+    // ### Arguments
+    //
+    // * `template` A String template. '<% %>' tags are evaluated as Javascript and replaced with the elements in data.
+    // * `data` An Object containing the replacement values for the template.
+    //   data is extended with the <tt>EventContext</tt> allowing you to call its methods within the template.
+    // * `name` An optional String name to cache the template.
+    //
+    var template = function(template, data, name) {
+      // use name for caching
+      if (typeof name == 'undefined') name = template;
+      return srender(name, template, $.extend({}, this, data));
+    };
+
+    // set the default method name/extension
+    if (!method_alias) method_alias = 'template';
+    // create the helper at the method alias
+    app.helper(method_alias, template);
+
+  };
+
+})(jQuery);

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/sammy/plugins/sammy.title.js
----------------------------------------------------------------------
diff --git a/attachments/sammy/plugins/sammy.title.js b/attachments/sammy/plugins/sammy.title.js
new file mode 100644
index 0000000..9874a1e
--- /dev/null
+++ b/attachments/sammy/plugins/sammy.title.js
@@ -0,0 +1,59 @@
+(function($) {
+
+  Sammy = Sammy || {};
+
+  // Sammy.Title is a very simple plugin to easily set the document's title.
+  // It supplies a helper for setting the title (`title()`) within routes,
+  // and an app level method for setting the global title (`setTitle()`)
+  Sammy.Title = function() {
+
+    // setTitle allows setting a global title or a function that modifies the
+    // title for each route/page.
+    //
+    // ### Example
+    //
+    //    // setting a title prefix
+    //    $.sammy(function() {
+    //
+    //      this.setTitle('My App -');
+    //
+    //      this.get('#/', function() {
+    //        this.title('Home'); // document's title == "My App - Home"
+    //      });
+    //    });
+    //
+    //    // setting a title with a function
+    //    $.sammy(function() {
+    //
+    //      this.setTitle(function(title) {
+    //        return [title, " /// My App"].join('');
+    //      });
+    //
+    //      this.get('#/', function() {
+    //        this.title('Home'); // document's title == "Home /// My App";
+    //      });
+    //    });
+    //
+    this.setTitle = function(title) {
+      if (!$.isFunction(title)) {
+        this.title_function = function(additional_title) {
+          return [title, additional_title].join(' ');
+        }
+      } else {
+        this.title_function = title;
+      }
+    };
+
+    // *Helper* title() sets the document title, passing it through the function
+    // defined by setTitle() if set.
+    this.helper('title', function() {
+      var new_title = $.makeArray(arguments).join(' ');
+      if (this.app.title_function) {
+        new_title = this.app.title_function(new_title);
+      }
+      document.title = new_title;
+    });
+
+  };
+
+})(jQuery);


[6/9] first commit

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/highcharts/modules/exporting.js
----------------------------------------------------------------------
diff --git a/attachments/highcharts/modules/exporting.js b/attachments/highcharts/modules/exporting.js
new file mode 100755
index 0000000..b30fe65
--- /dev/null
+++ b/attachments/highcharts/modules/exporting.js
@@ -0,0 +1,21 @@
+/*
+ Highcharts JS v2.1.2 (2011-01-12)
+ Exporting module
+
+ (c) 2010 Torstein H?nsi
+
+ License: www.highcharts.com/license
+*/
+(function(){var j=Highcharts,y=j.Chart,C=j.addEvent,r=j.createElement,z=j.discardElement,u=j.css,w=j.merge,s=j.each,p=j.extend,D=Math.max,q=document,E=window,A="ontouchstart"in q.documentElement,B=j.setOptions({lang:{downloadPNG:"Download PNG image",downloadJPEG:"Download JPEG image",downloadPDF:"Download PDF document",downloadSVG:"Download SVG vector image",exportButtonTitle:"Export to raster or vector image",printButtonTitle:"Print the chart"}});B.navigation={menuStyle:{border:"1px solid #A0A0A0",
+background:"#FFFFFF"},menuItemStyle:{padding:"0 5px",background:"none",color:"#303030",fontSize:A?"14px":"11px"},menuItemHoverStyle:{background:"#4572A5",color:"#FFFFFF"},buttonOptions:{align:"right",backgroundColor:{linearGradient:[0,0,0,20],stops:[[0.4,"#F7F7F7"],[0.6,"#E3E3E3"]]},borderColor:"#B0B0B0",borderRadius:3,borderWidth:1,height:20,hoverBorderColor:"#909090",hoverSymbolFill:"#81A7CF",hoverSymbolStroke:"#4572A5",symbolFill:"#E0E0E0",symbolStroke:"#A0A0A0",symbolX:11.5,symbolY:10.5,verticalAlign:"top",
+width:24,y:10}};B.exporting={type:"image/png",url:"http://export.highcharts.com/",width:800,buttons:{exportButton:{symbol:"exportIcon",x:-10,symbolFill:"#A8BF77",hoverSymbolFill:"#768F3E",_titleKey:"exportButtonTitle",menuItems:[{textKey:"downloadPNG",onclick:function(){this.exportChart()}},{textKey:"downloadJPEG",onclick:function(){this.exportChart({type:"image/jpeg"})}},{textKey:"downloadPDF",onclick:function(){this.exportChart({type:"application/pdf"})}},{textKey:"downloadSVG",onclick:function(){this.exportChart({type:"image/svg+xml"})}}]},
+printButton:{symbol:"printIcon",x:-36,symbolFill:"#B5C9DF",hoverSymbolFill:"#779ABF",_titleKey:"printButtonTitle",onclick:function(){this.print()}}}};p(y.prototype,{getSVG:function(b){var c=this,a,e,d,k,f,h,i=w(c.options,b);if(!q.createElementNS)q.createElementNS=function(l,g){var n=q.createElement(g);n.getBBox=function(){return c.renderer.Element.prototype.getBBox.apply({element:n})};return n};a=r("div",null,{position:"absolute",top:"-9999em",width:c.chartWidth+"px",height:c.chartHeight+"px"},q.body);
+p(i.chart,{renderTo:a,renderer:"SVG"});i.exporting.enabled=false;i.chart.plotBackgroundImage=null;i.series=[];s(c.series,function(l){d=l.options;d.animation=false;d.showCheckbox=false;if(d&&d.marker&&/^url\(/.test(d.marker.symbol))d.marker.symbol="circle";d.data=[];s(l.data,function(g){k=g.config;f=p(typeof k=="object"&&k.constructor!=Array&&g.config,{x:g.x,y:g.y,name:g.name});d.data.push(f);(h=g.config&&g.config.marker)&&/^url\(/.test(h.symbol)&&delete h.symbol});i.series.push(d)});b=new Highcharts.Chart(i);
+e=b.container.innerHTML;i=null;b.destroy();z(a);e=e.replace(/zIndex="[^"]+"/g,"").replace(/isShadow="[^"]+"/g,"").replace(/symbolName="[^"]+"/g,"").replace(/jQuery[0-9]+="[^"]+"/g,"").replace(/isTracker="[^"]+"/g,"").replace(/url\([^#]+#/g,"url(#").replace(/id=([^" >]+)/g,'id="$1"').replace(/class=([^" ]+)/g,'class="$1"').replace(/ transform /g," ").replace(/:(path|rect)/g,"$1").replace(/style="([^"]+)"/g,function(l){return l.toLowerCase()});e=e.replace(/(url\(#highcharts-[0-9]+)&quot;/g,"$1").replace(/&quot;/g,
+"'");if(e.match(/ xmlns="/g).length==2)e=e.replace(/xmlns="[^"]+"/,"");return e},exportChart:function(b,c){var a,e=this.getSVG(c);b=w(this.options.exporting,b);a=r("form",{method:"post",action:b.url},{display:"none"},q.body);s(["filename","type","width","svg"],function(d){r("input",{type:"hidden",name:d,value:{filename:b.filename||"chart",type:b.type,width:b.width,svg:e}[d]},null,a)});a.submit();z(a)},print:function(){var b=this,c=b.container,a=[],e=c.parentNode,d=q.body,k=d.childNodes;if(!b.isPrinting){b.isPrinting=
+true;s(k,function(f,h){if(f.nodeType==1){a[h]=f.style.display;f.style.display="none"}});d.appendChild(c);E.print();setTimeout(function(){e.appendChild(c);s(k,function(f,h){if(f.nodeType==1)f.style.display=a[h]});b.isPrinting=false},1E3)}},contextMenu:function(b,c,a,e,d,k){var f=this,h=f.options.navigation,i=h.menuItemStyle,l=f.chartWidth,g=f.chartHeight,n="cache-"+b,m=f[n],o=D(d,k),t,x;if(!m){f[n]=m=r("div",{className:"highcharts-"+b},{position:"absolute",zIndex:1E3,padding:o+"px"},f.container);t=
+r("div",null,p({MozBoxShadow:"3px 3px 10px #888",WebkitBoxShadow:"3px 3px 10px #888",boxShadow:"3px 3px 10px #888"},h.menuStyle),m);x=function(){u(m,{display:"none"})};C(m,"mouseleave",x);s(c,function(v){if(v)r("div",{onmouseover:function(){u(this,h.menuItemHoverStyle)},onmouseout:function(){u(this,i)},innerHTML:v.text||j.getOptions().lang[v.textKey]},p({cursor:"pointer"},i),t)[A?"ontouchstart":"onclick"]=function(){x();v.onclick.apply(f,arguments)}});f.exportMenuWidth=m.offsetWidth;f.exportMenuHeight=
+m.offsetHeight}b={display:"block"};if(a+f.exportMenuWidth>l)b.right=l-a-d-o+"px";else b.left=a-o+"px";if(e+k+f.exportMenuHeight>g)b.bottom=g-e-o+"px";else b.top=e+k-o+"px";u(m,b)},addButton:function(b){function c(){g.attr(o);l.attr(m)}var a=this,e=a.renderer,d=w(a.options.navigation.buttonOptions,b),k=d.onclick,f=d.menuItems,h=d.width,i=d.height,l,g,n;b=d.borderWidth;var m={stroke:d.borderColor},o={stroke:d.symbolStroke,fill:d.symbolFill};if(d.enabled!==false){l=e.rect(0,0,h,i,d.borderRadius,b).align(d,
+true).attr(p({fill:d.backgroundColor,"stroke-width":b,zIndex:19},m)).add();n=e.rect(0,0,h,i,0).align(d).attr({fill:"rgba(255, 255, 255, 0.001)",title:j.getOptions().lang[d._titleKey],zIndex:21}).css({cursor:"pointer"}).on("mouseover",function(){g.attr({stroke:d.hoverSymbolStroke,fill:d.hoverSymbolFill});l.attr({stroke:d.hoverBorderColor})}).on("mouseout",c).on("click",c).add();if(f)k=function(){c();var t=n.getBBox();a.contextMenu("export-menu",f,t.x,t.y,h,i)};n.on("click",function(){k.apply(a,arguments)});
+g=e.symbol(d.symbol,d.symbolX,d.symbolY,(d.symbolSize||12)/2).align(d,true).attr(p(o,{"stroke-width":d.symbolStrokeWidth||1,zIndex:20})).add()}}});j.Renderer.prototype.symbols.exportIcon=function(b,c,a){return["M",b-a,c+a,"L",b+a,c+a,b+a,c+a*0.5,b-a,c+a*0.5,"Z","M",b,c+a*0.5,"L",b-a*0.5,c-a/3,b-a/6,c-a/3,b-a/6,c-a,b+a/6,c-a,b+a/6,c-a/3,b+a*0.5,c-a/3,"Z"]};j.Renderer.prototype.symbols.printIcon=function(b,c,a){return["M",b-a,c+a*0.5,"L",b+a,c+a*0.5,b+a,c-a/3,b-a,c-a/3,"Z","M",b-a*0.5,c-a/3,"L",b-a*
+0.5,c-a,b+a*0.5,c-a,b+a*0.5,c-a/3,"Z","M",b-a*0.5,c+a*0.5,"L",b-a*0.75,c+a,b+a*0.75,c+a,b+a*0.5,c+a*0.5,"Z"]};y.prototype.callbacks.push(function(b){var c,a=b.options.exporting,e=a.buttons;if(a.enabled!==false)for(c in e)b.addButton(e[c])})})();

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/highcharts/modules/exporting.src.js
----------------------------------------------------------------------
diff --git a/attachments/highcharts/modules/exporting.src.js b/attachments/highcharts/modules/exporting.src.js
new file mode 100755
index 0000000..b0829c8
--- /dev/null
+++ b/attachments/highcharts/modules/exporting.src.js
@@ -0,0 +1,671 @@
+/** 
+ * @license Highcharts JS v2.1.2 (2011-01-12)
+ * Exporting module
+ * 
+ * (c) 2010 Torstein Hønsi
+ * 
+ * License: www.highcharts.com/license
+ */
+
+// JSLint options:
+/*global Highcharts, document, window, Math, setTimeout */
+
+(function() { // encapsulate
+
+// create shortcuts
+var HC = Highcharts,
+	Chart = HC.Chart,
+	addEvent = HC.addEvent,
+	createElement = HC.createElement,
+	discardElement = HC.discardElement,
+	css = HC.css,
+	merge = HC.merge,
+	each = HC.each,
+	extend = HC.extend,
+	math = Math,
+	mathMax = math.max,
+	doc = document,
+	win = window,
+	hasTouch = 'ontouchstart' in doc.documentElement,	
+	M = 'M',
+	L = 'L',
+	DIV = 'div',
+	HIDDEN = 'hidden',
+	NONE = 'none',
+	PREFIX = 'highcharts-',
+	ABSOLUTE = 'absolute',
+	PX = 'px',
+
+
+
+	// Add language and get the defaultOptions
+	defaultOptions = HC.setOptions({
+		lang: {
+			downloadPNG: 'Download PNG image',
+			downloadJPEG: 'Download JPEG image',
+			downloadPDF: 'Download PDF document',
+			downloadSVG: 'Download SVG vector image',
+			exportButtonTitle: 'Export to raster or vector image',
+			printButtonTitle: 'Print the chart'
+		}
+	});
+
+// Buttons and menus are collected in a separate config option set called 'navigation'.
+// This can be extended later to add control buttons like zoom and pan right click menus.
+defaultOptions.navigation = {
+	menuStyle: {
+		border: '1px solid #A0A0A0',
+		background: '#FFFFFF'
+	},
+	menuItemStyle: {
+		padding: '0 5px',
+		background: NONE,
+		color: '#303030',
+		fontSize: hasTouch ? '14px' : '11px'
+	},
+	menuItemHoverStyle: {
+		background: '#4572A5',
+		color: '#FFFFFF'
+	},
+	
+	buttonOptions: {
+		align: 'right',
+		backgroundColor: {
+			linearGradient: [0, 0, 0, 20],
+			stops: [
+				[0.4, '#F7F7F7'],
+				[0.6, '#E3E3E3']
+			]
+		},
+		borderColor: '#B0B0B0',
+		borderRadius: 3,
+		borderWidth: 1,
+		//enabled: true,
+		height: 20,
+		hoverBorderColor: '#909090',
+		hoverSymbolFill: '#81A7CF',
+		hoverSymbolStroke: '#4572A5',
+		symbolFill: '#E0E0E0',
+		//symbolSize: 12,
+		symbolStroke: '#A0A0A0',
+		//symbolStrokeWidth: 1,
+		symbolX: 11.5,
+		symbolY: 10.5,
+		verticalAlign: 'top',
+		width: 24,
+		y: 10		
+	}
+};
+
+
+
+// Add the export related options
+defaultOptions.exporting = {
+	//enabled: true,
+	//filename: 'chart',
+	type: 'image/png',
+	url: 'http://export.highcharts.com/',
+	width: 800,
+	buttons: {
+		exportButton: {
+			//enabled: true,
+			symbol: 'exportIcon',
+			x: -10,
+			symbolFill: '#A8BF77',
+			hoverSymbolFill: '#768F3E',
+			_titleKey: 'exportButtonTitle',
+			menuItems: [{
+				textKey: 'downloadPNG',
+				onclick: function() {
+					this.exportChart();
+				}
+			}, {
+				textKey: 'downloadJPEG',
+				onclick: function() {
+					this.exportChart({
+						type: 'image/jpeg'
+					});
+				}
+			}, {
+				textKey: 'downloadPDF',
+				onclick: function() {
+					this.exportChart({
+						type: 'application/pdf'
+					});
+				}
+			}, {
+				textKey: 'downloadSVG',
+				onclick: function() {
+					this.exportChart({
+						type: 'image/svg+xml'
+					});
+				}
+			}/*, {
+				text: 'View SVG',
+				onclick: function() {
+					var svg = this.getSVG()
+						.replace(/</g, '\n&lt;')
+						.replace(/>/g, '&gt;');
+						
+					doc.body.innerHTML = '<pre>'+ svg +'</pre>';
+				}
+			}*/]
+			
+		},
+		printButton: {
+			//enabled: true,
+			symbol: 'printIcon',
+			x: -36,
+			symbolFill: '#B5C9DF',
+			hoverSymbolFill: '#779ABF',
+			_titleKey: 'printButtonTitle',
+			onclick: function() {
+				this.print();
+			}
+		}
+	}
+};
+
+
+
+extend(Chart.prototype, {
+	/**
+	 * Return an SVG representation of the chart
+	 * 
+	 * @param additionalOptions {Object} Additional chart options for the generated SVG representation
+	 */	
+	 getSVG: function(additionalOptions) {
+		var chart = this,
+			chartCopy,
+			sandbox,
+			svg,
+			seriesOptions,
+			config,
+			pointOptions,
+			pointMarker,
+			options = merge(chart.options, additionalOptions); // copy the options and add extra options
+		
+		// IE compatibility hack for generating SVG content that it doesn't really understand
+		if (!doc.createElementNS) {
+			doc.createElementNS = function(ns, tagName) {
+				var elem = doc.createElement(tagName);
+				elem.getBBox = function() {
+					return chart.renderer.Element.prototype.getBBox.apply({ element: elem });
+				};
+				return elem;
+			};
+		}
+		
+		// create a sandbox where a new chart will be generated
+		sandbox = createElement(DIV, null, {
+			position: ABSOLUTE,
+			top: '-9999em',
+			width: chart.chartWidth + PX,
+			height: chart.chartHeight + PX
+		}, doc.body);
+		
+		// override some options
+		extend(options.chart, {
+			renderTo: sandbox,
+			renderer: 'SVG'
+		});
+		options.exporting.enabled = false; // hide buttons in print
+		options.chart.plotBackgroundImage = null; // the converter doesn't handle images
+		// prepare for replicating the chart
+		options.series = [];
+		each(chart.series, function(serie) {
+			seriesOptions = serie.options;			
+			
+			seriesOptions.animation = false; // turn off animation
+			seriesOptions.showCheckbox = false;
+			
+			// remove image markers
+			if (seriesOptions && seriesOptions.marker && /^url\(/.test(seriesOptions.marker.symbol)) { 
+				seriesOptions.marker.symbol = 'circle';
+			}
+			
+			seriesOptions.data = [];
+			
+			each(serie.data, function(point) {
+				/*pointOptions = point.config === null || typeof point.config == 'number' ?
+					{ y: point.y } :
+					point.config;
+				pointOptions.x = point.x;*/
+				
+				// extend the options by those values that can be expressed in a number or array config
+				config = point.config;
+				pointOptions = extend(
+					typeof config == 'object' && config.constructor != Array && point.config, {
+						x: point.x,
+						y: point.y,
+						name: point.name
+					}
+				);
+				seriesOptions.data.push(pointOptions); // copy fresh updated data
+								
+				// remove image markers
+				pointMarker = point.config && point.config.marker;
+				if (pointMarker && /^url\(/.test(pointMarker.symbol)) { 
+					delete pointMarker.symbol;
+				}
+			});	
+			
+			options.series.push(seriesOptions);
+		});
+		
+		// generate the chart copy
+		chartCopy = new Highcharts.Chart(options);
+		
+		// get the SVG from the container's innerHTML
+		svg = chartCopy.container.innerHTML;
+		
+		// free up memory
+		options = null;
+		chartCopy.destroy();
+		discardElement(sandbox);
+		
+		// sanitize
+		svg = svg
+			.replace(/zIndex="[^"]+"/g, '') 
+			.replace(/isShadow="[^"]+"/g, '')
+			.replace(/symbolName="[^"]+"/g, '')
+			.replace(/jQuery[0-9]+="[^"]+"/g, '')
+			.replace(/isTracker="[^"]+"/g, '')
+			.replace(/url\([^#]+#/g, 'url(#')
+			/* This fails in IE < 8
+			.replace(/([0-9]+)\.([0-9]+)/g, function(s1, s2, s3) { // round off to save weight
+				return s2 +'.'+ s3[0];
+			})*/ 
+			
+			// IE specific
+			.replace(/id=([^" >]+)/g, 'id="$1"') 
+			.replace(/class=([^" ]+)/g, 'class="$1"')
+			.replace(/ transform /g, ' ')
+			.replace(/:(path|rect)/g, '$1')
+			.replace(/style="([^"]+)"/g, function(s) {
+				return s.toLowerCase();
+			});
+			
+		// IE9 beta bugs with innerHTML. Test again with final IE9.
+		svg = svg.replace(/(url\(#highcharts-[0-9]+)&quot;/g, '$1')
+			.replace(/&quot;/g, "'");
+		if (svg.match(/ xmlns="/g).length == 2) {
+			svg = svg.replace(/xmlns="[^"]+"/, '');
+		}
+			
+		return svg;
+	},
+	
+	/**
+	 * Submit the SVG representation of the chart to the server
+	 * @param {Object} options Exporting options. Possible members are url, type and width.
+	 * @param {Object} chartOptions Additional chart options for the SVG representation of the chart
+	 */
+	exportChart: function(options, chartOptions) {
+		var form,
+			chart = this,
+			svg = chart.getSVG(chartOptions);
+			
+		// merge the options
+		options = merge(chart.options.exporting, options);
+		
+		// create the form
+		form = createElement('form', {
+			method: 'post',
+			action: options.url
+		}, {
+			display: NONE
+		}, doc.body);
+		
+		// add the values
+		each(['filename', 'type', 'width', 'svg'], function(name) {
+			createElement('input', {
+				type: HIDDEN,
+				name: name,
+				value: { 
+					filename: options.filename || 'chart', 
+					type: options.type, 
+					width: options.width, 
+					svg: svg 
+				}[name]
+			}, null, form);
+		});
+		
+		// submit
+		form.submit();
+		
+		// clean up
+		discardElement(form);
+	},
+	
+	/**
+	 * Print the chart
+	 */
+	print: function() {
+		
+		var chart = this,
+			container = chart.container,
+			origDisplay = [],
+			origParent = container.parentNode,
+			body = doc.body,
+			childNodes = body.childNodes;
+			
+		if (chart.isPrinting) { // block the button while in printing mode
+			return;
+		}
+		
+		chart.isPrinting = true;
+		
+		// hide all body content	
+		each(childNodes, function(node, i) {
+			if (node.nodeType == 1) {
+				origDisplay[i] = node.style.display;
+				node.style.display = NONE;
+			}
+		});
+			
+		// pull out the chart
+		body.appendChild(container);
+		 
+		// print
+		win.print();		
+		
+		// allow the browser to prepare before reverting
+		setTimeout(function() {
+
+			// put the chart back in
+			origParent.appendChild(container);
+			
+			// restore all body content
+			each(childNodes, function(node, i) {
+				if (node.nodeType == 1) {
+					node.style.display = origDisplay[i];
+				}
+			});
+			
+			chart.isPrinting = false;
+			
+		}, 1000);
+
+	},
+	
+	/**
+	 * Display a popup menu for choosing the export type 
+	 * 
+	 * @param {String} name An identifier for the menu
+	 * @param {Array} items A collection with text and onclicks for the items
+	 * @param {Number} x The x position of the opener button
+	 * @param {Number} y The y position of the opener button
+	 * @param {Number} width The width of the opener button
+	 * @param {Number} height The height of the opener button
+	 */
+	contextMenu: function(name, items, x, y, width, height) {
+		var chart = this,
+			navOptions = chart.options.navigation,
+			menuItemStyle = navOptions.menuItemStyle,
+			chartWidth = chart.chartWidth,
+			chartHeight = chart.chartHeight,
+			cacheName = 'cache-'+ name,
+			menu = chart[cacheName],
+			menuPadding = mathMax(width, height), // for mouse leave detection
+			boxShadow = '3px 3px 10px #888',
+			innerMenu,
+			hide,
+			menuStyle; 
+		
+		// create the menu only the first time
+		if (!menu) {
+			
+			// create a HTML element above the SVG		
+			chart[cacheName] = menu = createElement(DIV, {
+				className: PREFIX + name
+			}, {
+				position: ABSOLUTE,
+				zIndex: 1000,
+				padding: menuPadding + PX
+			}, chart.container);
+			
+			innerMenu = createElement(DIV, null, 
+				extend({
+					MozBoxShadow: boxShadow,
+					WebkitBoxShadow: boxShadow,
+					boxShadow: boxShadow
+				}, navOptions.menuStyle) , menu);
+			
+			// hide on mouse out
+			hide = function() {
+				css(menu, { display: NONE });
+			};
+			
+			addEvent(menu, 'mouseleave', hide);
+			
+			
+			// create the items
+			each(items, function(item) {
+				if (item) {
+					var div = createElement(DIV, {
+						onmouseover: function() {
+							css(this, navOptions.menuItemHoverStyle);
+						},
+						onmouseout: function() {
+							css(this, menuItemStyle);
+						},
+						innerHTML: item.text || HC.getOptions().lang[item.textKey]
+					}, extend({
+						cursor: 'pointer'
+					}, menuItemStyle), innerMenu);
+					
+					div[hasTouch ? 'ontouchstart' : 'onclick'] = function() {
+						hide();
+						item.onclick.apply(chart, arguments);
+					};
+						
+				}
+			});
+			
+			chart.exportMenuWidth = menu.offsetWidth;
+			chart.exportMenuHeight = menu.offsetHeight;
+		}
+		
+		menuStyle = { display: 'block' };
+		
+		// if outside right, right align it
+		if (x + chart.exportMenuWidth > chartWidth) {
+			menuStyle.right = (chartWidth - x - width - menuPadding) + PX;
+		} else {
+			menuStyle.left = (x - menuPadding) + PX;
+		}
+		// if outside bottom, bottom align it
+		if (y + height + chart.exportMenuHeight > chartHeight) {
+			menuStyle.bottom = (chartHeight - y - menuPadding)  + PX;
+		} else {
+			menuStyle.top = (y + height - menuPadding) + PX;
+		}
+		
+		css(menu, menuStyle);
+	},
+	
+	/**
+	 * Add the export button to the chart
+	 */
+	addButton: function(options) {
+		var chart = this,
+			renderer = chart.renderer,
+			btnOptions = merge(chart.options.navigation.buttonOptions, options),
+			onclick = btnOptions.onclick,
+			menuItems = btnOptions.menuItems,
+			/*position = chart.getAlignment(btnOptions),
+			buttonLeft = position.x,
+			buttonTop = position.y,*/
+			buttonWidth = btnOptions.width,
+			buttonHeight = btnOptions.height,
+			box,
+			symbol,
+			button,	
+			borderWidth = btnOptions.borderWidth,
+			boxAttr = {
+				stroke: btnOptions.borderColor
+				
+			},
+			symbolAttr = {
+				stroke: btnOptions.symbolStroke,
+				fill: btnOptions.symbolFill
+			};
+			
+		if (btnOptions.enabled === false) {
+			return;
+		}
+			
+		// element to capture the click
+		function revert() {
+			symbol.attr(symbolAttr);
+			box.attr(boxAttr);
+		}
+		
+		// the box border
+		box = renderer.rect(
+			0,
+			0,
+			buttonWidth, 
+			buttonHeight,
+			btnOptions.borderRadius,
+			borderWidth
+		)
+		//.translate(buttonLeft, buttonTop) // to allow gradients
+		.align(btnOptions, true)
+		.attr(extend({
+			fill: btnOptions.backgroundColor,
+			'stroke-width': borderWidth,
+			zIndex: 19
+		}, boxAttr)).add();
+		
+		// the invisible element to track the clicks
+		button = renderer.rect( 
+				0,
+				0,
+				buttonWidth,
+				buttonHeight,
+				0
+			)
+			.align(btnOptions)
+			.attr({
+				fill: 'rgba(255, 255, 255, 0.001)',
+				title: HC.getOptions().lang[btnOptions._titleKey],
+				zIndex: 21
+			}).css({
+				cursor: 'pointer'
+			})
+			.on('mouseover', function() {
+				symbol.attr({
+					stroke: btnOptions.hoverSymbolStroke,
+					fill: btnOptions.hoverSymbolFill
+				});
+				box.attr({
+					stroke: btnOptions.hoverBorderColor
+				});
+			})
+			.on('mouseout', revert)
+			.on('click', revert)
+			.add();
+		
+		//addEvent(button.element, 'click', revert);
+		
+		// add the click event
+		if (menuItems) {
+			onclick = function(e) {
+				revert();
+				var bBox = button.getBBox();
+				chart.contextMenu('export-menu', menuItems, bBox.x, bBox.y, buttonWidth, buttonHeight);
+			};
+		}
+		/*addEvent(button.element, 'click', function() {
+			onclick.apply(chart, arguments);
+		});*/
+		button.on('click', function() {
+			onclick.apply(chart, arguments);
+		});
+		
+		// the icon
+		symbol = renderer.symbol(
+				btnOptions.symbol, 
+				btnOptions.symbolX, 
+				btnOptions.symbolY, 
+				(btnOptions.symbolSize || 12) / 2
+			)
+			.align(btnOptions, true)
+			.attr(extend(symbolAttr, {
+				'stroke-width': btnOptions.symbolStrokeWidth || 1,
+				zIndex: 20		
+			})).add();
+		
+		
+		
+	}
+});
+
+// Create the export icon
+HC.Renderer.prototype.symbols.exportIcon = function(x, y, radius) {
+	return [
+		M, // the disk
+		x - radius, y + radius,
+		L,
+		x + radius, y + radius,
+		x + radius, y + radius * 0.5,
+		x - radius, y + radius * 0.5,
+		'Z',
+		M, // the arrow
+		x, y + radius * 0.5,
+		L,
+		x - radius * 0.5, y - radius / 3,
+		x - radius / 6, y - radius / 3,
+		x - radius / 6, y - radius,
+		x + radius / 6, y - radius,
+		x + radius / 6, y - radius / 3,
+		x + radius * 0.5, y - radius / 3,
+		'Z'
+	];
+};
+// Create the print icon
+HC.Renderer.prototype.symbols.printIcon = function(x, y, radius) {
+	return [
+		M, // the printer
+		x - radius, y + radius * 0.5,
+		L,
+		x + radius, y + radius * 0.5,
+		x + radius, y - radius / 3,
+		x - radius, y - radius / 3,
+		'Z',
+		M, // the upper sheet
+		x - radius * 0.5, y - radius / 3,
+		L,
+		x - radius * 0.5, y - radius,
+		x + radius * 0.5, y - radius,
+		x + radius * 0.5, y - radius / 3,
+		'Z',
+		M, // the lower sheet
+		x - radius * 0.5, y + radius * 0.5,
+		L,
+		x - radius * 0.75, y + radius,
+		x + radius * 0.75, y + radius,
+		x + radius * 0.5, y + radius * 0.5,
+		'Z'
+	];
+};
+
+
+// Add the buttons on chart load
+Chart.prototype.callbacks.push(function(chart) {
+	var n,
+		exportingOptions = chart.options.exporting,
+		buttons = exportingOptions.buttons;
+
+	if (exportingOptions.enabled !== false) {
+
+		for (n in buttons) {
+			chart.addButton(buttons[n]);
+		}
+	}
+});
+
+
+})();
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/highcharts/themes/dark-blue.js
----------------------------------------------------------------------
diff --git a/attachments/highcharts/themes/dark-blue.js b/attachments/highcharts/themes/dark-blue.js
new file mode 100755
index 0000000..a39d6ca
--- /dev/null
+++ b/attachments/highcharts/themes/dark-blue.js
@@ -0,0 +1,170 @@
+/**
+ * Dark blue theme for Highcharts JS
+ * @author Torstein Hønsi
+ */
+
+Highcharts.theme = {
+	colors: ["#DDDF0D", "#55BF3B", "#DF5353", "#7798BF", "#aaeeee", "#ff0066", "#eeaaee", 
+		"#55BF3B", "#DF5353", "#7798BF", "#aaeeee"],
+	chart: {
+		backgroundColor: {
+			linearGradient: [0, 0, 250, 500],
+			stops: [
+				[0, 'rgb(48, 48, 96)'],
+				[1, 'rgb(0, 0, 0)']
+			]
+		},
+		borderColor: '#000000',
+		borderWidth: 2,
+		className: 'dark-container',
+		plotBackgroundColor: 'rgba(255, 255, 255, .1)',
+		plotBorderColor: '#CCCCCC',
+		plotBorderWidth: 1
+	},
+	title: {
+		style: {
+			color: '#C0C0C0',
+			font: 'bold 16px "Trebuchet MS", Verdana, sans-serif'
+		}
+	},
+	subtitle: {
+		style: { 
+			color: '#666666',
+			font: 'bold 12px "Trebuchet MS", Verdana, sans-serif'
+		}
+	},
+	xAxis: {
+		gridLineColor: '#333333',
+		gridLineWidth: 1,
+		labels: {
+			style: {
+				color: '#A0A0A0'
+			}
+		},
+		lineColor: '#A0A0A0',
+		tickColor: '#A0A0A0',
+		title: {
+			style: {
+				color: '#CCC',
+				fontWeight: 'bold',
+				fontSize: '12px',
+				fontFamily: 'Trebuchet MS, Verdana, sans-serif'
+
+			}				
+		}
+	},
+	yAxis: {
+		gridLineColor: '#333333',
+		labels: {
+			style: {
+				color: '#A0A0A0'
+			}
+		},
+		lineColor: '#A0A0A0',
+		minorTickInterval: null,
+		tickColor: '#A0A0A0',
+		tickWidth: 1,
+		title: {
+			style: {
+				color: '#CCC',
+				fontWeight: 'bold',
+				fontSize: '12px',
+				fontFamily: 'Trebuchet MS, Verdana, sans-serif'
+			}				
+		}
+	},
+	legend: {
+		itemStyle: {
+			font: '9pt Trebuchet MS, Verdana, sans-serif',
+			color: '#A0A0A0'
+		}
+	},
+	tooltip: {
+		backgroundColor: 'rgba(0, 0, 0, 0.75)',
+		style: {
+			color: '#F0F0F0'
+		}
+	},
+	toolbar: {
+		itemStyle: { 
+			color: 'silver'
+		}
+	},
+	plotOptions: {
+		line: {
+			dataLabels: {
+				color: '#CCC'
+			},
+			marker: {
+				lineColor: '#333'
+			}
+		},
+		spline: {
+			marker: {
+				lineColor: '#333'
+			}
+		},
+		scatter: {
+			marker: {
+				lineColor: '#333'
+			}
+		}
+	},		
+	legend: {
+		itemStyle: {
+			color: '#CCC'
+		},
+		itemHoverStyle: {
+			color: '#FFF'
+		},
+		itemHiddenStyle: {
+			color: '#444'
+		}
+	},
+	credits: {
+		style: {
+			color: '#666'
+		}
+	},
+	labels: {
+		style: {
+			color: '#CCC'
+		}
+	},
+	
+	navigation: {
+		buttonOptions: {
+			backgroundColor: {
+				linearGradient: [0, 0, 0, 20],
+				stops: [
+					[0.4, '#606060'],
+					[0.6, '#333333']
+				]
+			},
+			borderColor: '#000000',
+			symbolStroke: '#C0C0C0',
+			hoverSymbolStroke: '#FFFFFF'
+		}
+	},
+	
+	exporting: {
+		buttons: {
+			exportButton: {
+				symbolFill: '#55BE3B'
+			},
+			printButton: {
+				symbolFill: '#7797BE'
+			}
+		}
+	},
+	
+	// special colors for some of the
+	legendBackgroundColor: 'rgba(0, 0, 0, 0.5)',
+	legendBackgroundColorSolid: 'rgb(35, 35, 70)',
+	dataLabelsColor: '#444',
+	textColor: '#C0C0C0',
+	maskColor: 'rgba(255,255,255,0.3)'
+};
+
+// Apply the theme
+var highchartsOptions = Highcharts.setOptions(Highcharts.theme);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/highcharts/themes/dark-green.js
----------------------------------------------------------------------
diff --git a/attachments/highcharts/themes/dark-green.js b/attachments/highcharts/themes/dark-green.js
new file mode 100755
index 0000000..cec50e7
--- /dev/null
+++ b/attachments/highcharts/themes/dark-green.js
@@ -0,0 +1,170 @@
+/**
+ * Dark blue theme for Highcharts JS
+ * @author Torstein Hønsi
+ */
+
+Highcharts.theme = {
+	colors: ["#DDDF0D", "#55BF3B", "#DF5353", "#7798BF", "#aaeeee", "#ff0066", "#eeaaee", 
+		"#55BF3B", "#DF5353", "#7798BF", "#aaeeee"],
+	chart: {
+		backgroundColor: {
+			linearGradient: [0, 0, 250, 500],
+			stops: [
+				[0, 'rgb(48, 96, 48)'],
+				[1, 'rgb(0, 0, 0)']
+			]
+		},
+		borderColor: '#000000',
+		borderWidth: 2,
+		className: 'dark-container',
+		plotBackgroundColor: 'rgba(255, 255, 255, .1)',
+		plotBorderColor: '#CCCCCC',
+		plotBorderWidth: 1
+	},
+	title: {
+		style: {
+			color: '#C0C0C0',
+			font: 'bold 16px "Trebuchet MS", Verdana, sans-serif'
+		}
+	},
+	subtitle: {
+		style: { 
+			color: '#666666',
+			font: 'bold 12px "Trebuchet MS", Verdana, sans-serif'
+		}
+	},
+	xAxis: {
+		gridLineColor: '#333333',
+		gridLineWidth: 1,
+		labels: {
+			style: {
+				color: '#A0A0A0'
+			}
+		},
+		lineColor: '#A0A0A0',
+		tickColor: '#A0A0A0',
+		title: {
+			style: {
+				color: '#CCC',
+				fontWeight: 'bold',
+				fontSize: '12px',
+				fontFamily: 'Trebuchet MS, Verdana, sans-serif'
+
+			}				
+		}
+	},
+	yAxis: {
+		gridLineColor: '#333333',
+		labels: {
+			style: {
+				color: '#A0A0A0'
+			}
+		},
+		lineColor: '#A0A0A0',
+		minorTickInterval: null,
+		tickColor: '#A0A0A0',
+		tickWidth: 1,
+		title: {
+			style: {
+				color: '#CCC',
+				fontWeight: 'bold',
+				fontSize: '12px',
+				fontFamily: 'Trebuchet MS, Verdana, sans-serif'
+			}				
+		}
+	},
+	legend: {
+		itemStyle: {
+			font: '9pt Trebuchet MS, Verdana, sans-serif',
+			color: '#A0A0A0'
+		}
+	},
+	tooltip: {
+		backgroundColor: 'rgba(0, 0, 0, 0.75)',
+		style: {
+			color: '#F0F0F0'
+		}
+	},
+	toolbar: {
+		itemStyle: { 
+			color: 'silver'
+		}
+	},
+	plotOptions: {
+		line: {
+			dataLabels: {
+				color: '#CCC'
+			},
+			marker: {
+				lineColor: '#333'
+			}
+		},
+		spline: {
+			marker: {
+				lineColor: '#333'
+			}
+		},
+		scatter: {
+			marker: {
+				lineColor: '#333'
+			}
+		}
+	},		
+	legend: {
+		itemStyle: {
+			color: '#CCC'
+		},
+		itemHoverStyle: {
+			color: '#FFF'
+		},
+		itemHiddenStyle: {
+			color: '#444'
+		}
+	},
+	credits: {
+		style: {
+			color: '#666'
+		}
+	},
+	labels: {
+		style: {
+			color: '#CCC'
+		}
+	},
+	
+	navigation: {
+		buttonOptions: {
+			backgroundColor: {
+				linearGradient: [0, 0, 0, 20],
+				stops: [
+					[0.4, '#606060'],
+					[0.6, '#333333']
+				]
+			},
+			borderColor: '#000000',
+			symbolStroke: '#C0C0C0',
+			hoverSymbolStroke: '#FFFFFF'
+		}
+	},
+	
+	exporting: {
+		buttons: {
+			exportButton: {
+				symbolFill: '#55BE3B'
+			},
+			printButton: {
+				symbolFill: '#7797BE'
+			}
+		}
+	},
+	
+	// special colors for some of the
+	legendBackgroundColor: 'rgba(0, 0, 0, 0.5)',
+	legendBackgroundColorSolid: 'rgb(35, 35, 70)',
+	dataLabelsColor: '#444',
+	textColor: '#C0C0C0',
+	maskColor: 'rgba(255,255,255,0.3)'
+};
+
+// Apply the theme
+var highchartsOptions = Highcharts.setOptions(Highcharts.theme);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/highcharts/themes/gray.js
----------------------------------------------------------------------
diff --git a/attachments/highcharts/themes/gray.js b/attachments/highcharts/themes/gray.js
new file mode 100755
index 0000000..a292a76
--- /dev/null
+++ b/attachments/highcharts/themes/gray.js
@@ -0,0 +1,164 @@
+/**
+ * Gray theme for Highcharts JS
+ * @author Torstein Hønsi
+ */
+
+Highcharts.theme = {
+	colors: ["#DDDF0D", "#7798BF", "#55BF3B", "#DF5353", "#aaeeee", "#ff0066", "#eeaaee", 
+		"#55BF3B", "#DF5353", "#7798BF", "#aaeeee"],
+	chart: {
+		backgroundColor: {
+			linearGradient: [0, 0, 0, 400],
+			stops: [
+				[0, 'rgb(96, 96, 96)'],
+				[1, 'rgb(16, 16, 16)']
+			]
+		},
+		borderWidth: 0,
+		borderRadius: 15,
+		plotBackgroundColor: null,
+		plotShadow: false,
+		plotBorderWidth: 0
+	},
+	title: {
+		style: { 
+			color: '#FFF',
+			font: '16px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
+		}
+	},
+	subtitle: {
+		style: { 
+			color: '#DDD',
+			font: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
+		}
+	},
+	xAxis: {
+		gridLineWidth: 0,
+		lineColor: '#999',
+		tickColor: '#999',
+		labels: {
+			style: {
+				color: '#999',
+				fontWeight: 'bold'
+			}
+		},
+		title: {
+			style: {
+				color: '#AAA',
+				font: 'bold 12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
+			}				
+		}
+	},
+	yAxis: {
+		alternateGridColor: null,
+		minorTickInterval: null,
+		gridLineColor: 'rgba(255, 255, 255, .1)',
+		lineWidth: 0,
+		tickWidth: 0,
+		labels: {
+			style: {
+				color: '#999',
+				fontWeight: 'bold'
+			}
+		},
+		title: {
+			style: {
+				color: '#AAA',
+				font: 'bold 12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
+			}				
+		}
+	},
+	legend: {
+		itemStyle: {
+			color: '#CCC'
+		},
+		itemHoverStyle: {
+			color: '#FFF'
+		},
+		itemHiddenStyle: {
+			color: '#333'
+		}
+	},
+	labels: {
+		style: {
+			color: '#CCC'
+		}
+	},
+	tooltip: {
+		backgroundColor: {
+			linearGradient: [0, 0, 0, 50],
+			stops: [
+				[0, 'rgba(96, 96, 96, .8)'],
+				[1, 'rgba(16, 16, 16, .8)']
+			]
+		},
+		borderWidth: 0,
+		style: {
+			color: '#FFF'
+		}
+	},
+	
+	
+	plotOptions: {
+		line: {
+			dataLabels: {
+				color: '#CCC'
+			},
+			marker: {
+				lineColor: '#333'
+			}
+		},
+		spline: {
+			marker: {
+				lineColor: '#333'
+			}
+		},
+		scatter: {
+			marker: {
+				lineColor: '#333'
+			}
+		}
+	},
+	
+	toolbar: {
+		itemStyle: {
+			color: '#CCC'
+		}
+	},
+	
+	navigation: {
+		buttonOptions: {
+			backgroundColor: {
+				linearGradient: [0, 0, 0, 20],
+				stops: [
+					[0.4, '#606060'],
+					[0.6, '#333333']
+				]
+			},
+			borderColor: '#000000',
+			symbolStroke: '#C0C0C0',
+			hoverSymbolStroke: '#FFFFFF'
+		}
+	},
+	
+	exporting: {
+		buttons: {
+			exportButton: {
+				symbolFill: '#55BE3B'
+			},
+			printButton: {
+				symbolFill: '#7797BE'
+			}
+		}
+	},	
+	
+	// special colors for some of the demo examples
+	legendBackgroundColor: 'rgba(48, 48, 48, 0.8)',
+	legendBackgroundColorSolid: 'rgb(70, 70, 70)',
+	dataLabelsColor: '#444',
+	textColor: '#E0E0E0',
+	maskColor: 'rgba(255,255,255,0.3)'
+};
+
+// Apply the theme
+var highchartsOptions = Highcharts.setOptions(Highcharts.theme);

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/highcharts/themes/grid.js
----------------------------------------------------------------------
diff --git a/attachments/highcharts/themes/grid.js b/attachments/highcharts/themes/grid.js
new file mode 100755
index 0000000..ab2011b
--- /dev/null
+++ b/attachments/highcharts/themes/grid.js
@@ -0,0 +1,97 @@
+/**
+ * Grid theme for Highcharts JS
+ * @author Torstein Hønsi
+ */
+
+Highcharts.theme = {
+	colors: ['#058DC7', '#50B432', '#ED561B', '#DDDF00', '#24CBE5', '#64E572', '#FF9655', '#FFF263', '#6AF9C4'],
+	chart: {
+		backgroundColor: {
+			linearGradient: [0, 0, 500, 500],
+			stops: [
+				[0, 'rgb(255, 255, 255)'],
+				[1, 'rgb(240, 240, 255)']
+			]
+		}
+,
+		borderWidth: 2,
+		plotBackgroundColor: 'rgba(255, 255, 255, .9)',
+		plotShadow: true,
+		plotBorderWidth: 1
+	},
+	title: {
+		style: { 
+			color: '#000',
+			font: 'bold 16px "Trebuchet MS", Verdana, sans-serif'
+		}
+	},
+	subtitle: {
+		style: { 
+			color: '#666666',
+			font: 'bold 12px "Trebuchet MS", Verdana, sans-serif'
+		}
+	},
+	xAxis: {
+		gridLineWidth: 1,
+		lineColor: '#000',
+		tickColor: '#000',
+		labels: {
+			style: {
+				color: '#000',
+				font: '11px Trebuchet MS, Verdana, sans-serif'
+			}
+		},
+		title: {
+			style: {
+				color: '#333',
+				fontWeight: 'bold',
+				fontSize: '12px',
+				fontFamily: 'Trebuchet MS, Verdana, sans-serif'
+
+			}				
+		}
+	},
+	yAxis: {
+		minorTickInterval: 'auto',
+		lineColor: '#000',
+		lineWidth: 1,
+		tickWidth: 1,
+		tickColor: '#000',
+		labels: {
+			style: {
+				color: '#000',
+				font: '11px Trebuchet MS, Verdana, sans-serif'
+			}
+		},
+		title: {
+			style: {
+				color: '#333',
+				fontWeight: 'bold',
+				fontSize: '12px',
+				fontFamily: 'Trebuchet MS, Verdana, sans-serif'
+			}				
+		}
+	},
+	legend: {
+		itemStyle: {			
+			font: '9pt Trebuchet MS, Verdana, sans-serif',
+			color: 'black'
+
+		},
+		itemHoverStyle: {
+			color: '#039'
+		},
+		itemHiddenStyle: {
+			color: 'gray'
+		}
+	},
+	labels: {
+		style: {
+			color: '#99b'
+		}
+	}
+};
+
+// Apply the theme
+var highchartsOptions = Highcharts.setOptions(Highcharts.theme);
+	

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/images/favicon.ico
----------------------------------------------------------------------
diff --git a/attachments/images/favicon.ico b/attachments/images/favicon.ico
new file mode 100644
index 0000000..b814449
Binary files /dev/null and b/attachments/images/favicon.ico differ

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/images/grid.png
----------------------------------------------------------------------
diff --git a/attachments/images/grid.png b/attachments/images/grid.png
new file mode 100644
index 0000000..5d97586
Binary files /dev/null and b/attachments/images/grid.png differ

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/index.html
----------------------------------------------------------------------
diff --git a/attachments/index.html b/attachments/index.html
new file mode 100644
index 0000000..528b133
--- /dev/null
+++ b/attachments/index.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+    <meta name="keywords" content="">
+    <meta name="description" content="">
+
+    <title>Cordova Plugin Registry</title>
+    <link href="/layout.css" rel="stylesheet" type="text/css">
+    <!-- could also go to
+         http://registry.npmjs.org/-/rss?descending=true&limit=50 -->
+    <link rel="alternate" type="application/rss+xml"
+      href="/api/_design/app/_rewrite/-/rss?descending=true&limit=50"
+      title="npm publish feed (RSS)">
+    <script language="javascript" type="text/javascript" src="jquery-1.4.4.min.js"></script>
+    <script language="javascript" type="text/javascript" src="sammy/sammy.js"></script>
+    <script language="javascript" type="text/javascript" src="site.js"></script>
+    <link href="images/favicon.ico" rel="shortcut icon" type="image/x-icon">
+  </head>
+
+  <body>
+    <div id="body-container">
+      <div id="header">
+        <div class="wrap">
+          <a href="/" title="Home" class="icon-cordova logo">Cordova Plugins</a>
+          <div id="howto" style="display:none;">
+            <a href="http://npmjs.org/doc/README.html"><span>How to</span>Install npm</a>
+            <a href="http://npmjs.org/doc/publish.html"><span>How to</span>Publish a package</a>
+          </div>
+        </div>
+      </div>
+      
+      <div id="totals">
+      </div>
+
+      <div class="grid">
+        <div id="tabs">
+          <a href="/" class="selected tab-find">Find packages</a>
+          <a href="/#/_browse/all" class="tab-browse">Browse packages</a>
+          <a href="/#/_more" class="tab-more">More</a>
+        </div>
+        <div id="content-wrapper" class="wrap">
+          <div id="content">
+          </div>
+        </div>
+      </div>
+
+    </div>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/install.html
----------------------------------------------------------------------
diff --git a/attachments/install.html b/attachments/install.html
new file mode 100644
index 0000000..75a38ea
--- /dev/null
+++ b/attachments/install.html
@@ -0,0 +1,20 @@
+<h2>One Line Install</h2>
+
+<code>curl http://npmjs.org/install.sh | sh</code>
+
+<h2>More Than One Line Install</h2>
+
+<ol>
+  <li><a href="https://github.com/isaacs/npm">Get the code.</a>
+  </li><li>Run <code>make install</code>
+</li></ol>
+
+<h2>Other Cool Stuff</h2>
+
+<ul>
+  <li><a href="https://github.com/isaacs/npm#readme">README</a>
+  </li><li><a href="https://github.com/isaacs/npm/blob/master/doc/faq.md#readme">FAQ</a>
+  </li><li><a href="http://search.npmjs.org/">Search for Packages</a>
+  </li><li><a href="http://groups.google.com/group/npm-">Mailing List</a>
+  </li><li><a href="https://github.com/isaacs/npm/issues">Bugs</a>
+</li></ul>