Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Redesigned landing page

  • Loading branch information...
commit 8119951d90cf6c5bd0099dd32749f2a9126c4c97 1 parent 195097d
@toantran authored
Showing with 3,231 additions and 871 deletions.
  1. +2 −0  app.js
  2. +1 −0  coffee/app.coffee
  3. +84 −10 coffee/public/js/index.coffee
  4. +0 −1  coffee/repository/base.coffee
  5. +17 −0 coffee/routes/index.coffee
  6. +10 −3 coffee/services/customer.coffee
  7. +21 −349 coffee/services/user.coffee
  8. +3 −0  node_modules/geocoder/.npmignore
  9. +20 −0 node_modules/geocoder/LICENSE
  10. +52 −0 node_modules/geocoder/README.markdown
  11. +122 −0 node_modules/geocoder/index.js
  12. +191 −0 node_modules/geocoder/node_modules/hashish/README.markdown
  13. +9 −0 node_modules/geocoder/node_modules/hashish/examples/chain.js
  14. +7 −0 node_modules/geocoder/node_modules/hashish/examples/map.js
  15. +253 −0 node_modules/geocoder/node_modules/hashish/index.js
  16. +1 −0  node_modules/geocoder/node_modules/hashish/node_modules/traverse/.npmignore
  17. +24 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/LICENSE
  18. +256 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/README.markdown
  19. +16 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/examples/json.js
  20. +15 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/examples/leaves.js
  21. +8 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/examples/negative.js
  22. +10 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/examples/scrub.js
  23. +38 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/examples/stringify.js
  24. +279 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/index.js
  25. +18 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/package.json
  26. +115 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/test/circular.js
  27. +35 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/test/date.js
  28. +220 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/test/equal.js
  29. +13 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/test/has.js
  30. +17 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/test/instance.js
  31. +42 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/test/interface.js
  32. +47 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/test/json.js
  33. +29 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/test/keys.js
  34. +21 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/test/leaves.js
  35. +92 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/test/lib/deep_equal.js
  36. +252 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/test/mutability.js
  37. +20 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/test/negative.js
  38. +15 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/test/obj.js
  39. +35 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/test/siblings.js
  40. +41 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/test/stop.js
  41. +36 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/test/stringify.js
  42. +34 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/test/subexpr.js
  43. +55 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/test/super_deep.js
  44. +22 −0 node_modules/geocoder/node_modules/hashish/node_modules/traverse/testling/leaves.js
  45. +33 −0 node_modules/geocoder/node_modules/hashish/package.json
  46. +250 −0 node_modules/geocoder/node_modules/hashish/test/hash.js
  47. +69 −0 node_modules/geocoder/node_modules/hashish/test/property.js
  48. +18 −0 node_modules/geocoder/package.json
  49. +28 −0 node_modules/geocoder/test/geocoder-test.js
  50. BIN  public/images/glyphicons-halflings-white.png
  51. BIN  public/images/glyphicons-halflings.png
  52. BIN  public/images/imgs8.png
  53. BIN  public/images/m1.png
  54. BIN  public/images/m3.png
  55. BIN  public/images/mapslt.png
  56. +110 −14 public/js/index.js
  57. +23 −1 public/stylesheets/style.less
  58. +0 −1  repository/base.js
  59. +21 −0 routes/index.js
  60. +18 −5 services/customer.js
  61. +35 −478 services/user.js
  62. +3 −1 views/add.jade
  63. +10 −7 views/data.jade
  64. +15 −1 views/index.jade
View
2  app.js
@@ -71,6 +71,8 @@
}
};
+ app.get('/defloc', restrict, routes.defaultLocation);
+
app.get('/accountadd', routes.accountadd);
app.post('/accountadd', routes.createaccount);
View
1  coffee/app.coffee
@@ -55,6 +55,7 @@ restrict = (req, res, next) ->
# Routes
+app.get '/defloc', restrict, routes.defaultLocation
app.get '/accountadd', routes.accountadd
app.post '/accountadd', routes.createaccount
app.get '/data', restrict, routes.data
View
94 coffee/public/js/index.coffee
@@ -17,11 +17,13 @@ jQuery ($) ->
popLatLong = (customer, callback = ->) ->
if customer?.latlng?
callback customer
+ else if customer?.location?
+ customer.latlng = new google.maps.LatLng(customer?.location?.lat, customer?.location?.lng, true)
+ callback customer
else if customer?.lat? and customer?.lng?
customer.latlng = new google.maps.LatLng(customer?.lat, customer?.lng, true)
callback customer
else
-
@geo.geocode
address: customer?.address
, (results, status) ->
@@ -32,7 +34,7 @@ jQuery ($) ->
createMarker = (customer, map) ->
if customer?.latlng?
- marker = new google.maps.Marker({map: map, position: customer?.latlng, title: customer.name, visible: true})
+ marker = new google.maps.Marker({map: map, position: customer?.latlng, title: customer.name, visible: true, icon: @icon})
contentString = buildDetailInfo customer
@@ -41,21 +43,62 @@ jQuery ($) ->
@infoWindow?.setContent contentString
@infoWindow.open map, marker
+ return marker
+
+
+ showInGrid = (customer) ->
+ el = $.el('tr.client-row', {customerid: customer._id}, [
+ $.el('td', {}, [
+ $.el('div.client-name', {}, [customer?.name]),
+ $.el('div.client-address', {}, [customer?.address])
+ ])
+ ])
+ $('.clientlist-container tbody').append el
+
displayCustomer = (customer) ->
- popLatLong customer, (cust) ->
+ popLatLong customer, (cust) =>
marker = createMarker cust, @map
-
+ cust?.marker = marker
+ showInGrid cust
+
+ displayCustomers = (customers) ->
+ displayCustomer customer for customer in customers if customers?.length
+
+ clearMarkers = ->
+ if @customers?.length
+ for customer in @customers
+ do (customer) ->
+ if customer?.marker
+ customer?.marker.setMap null
+
+
+ clearGrid = ->
+ $('.clientlist-container tbody').empty()
+
loadCustomers = ->
$.get('customers')
- .success (data) ->
-
- if data?.success
- displayCustomer customer for customer in data?.customers
+ .success (data) =>
+ if data?.success
+ clearMarkers()
+ clearGrid()
+ @customers = data?.customers
+ displayCustomers @customers
+
+
+ loadDefaultLocation = ->
+ $.get('/defloc')
+ .success (data) =>
+ if data?.success and data?.location
+ loc = new google.maps.LatLng(data?.location?.lat, data?.location?.lng)
+ @map.setCenter loc
+ onMapLoad = ->
+ loadDefaultLocation()
+ loadCustomers()
initialize = ->
mapOptions =
@@ -65,8 +108,39 @@ jQuery ($) ->
@map = new google.maps.Map( document.getElementById("map_canvas"), mapOptions )
@geo = new google.maps.Geocoder()
+ @icon = new google.maps.MarkerImage('/images/mapslt.png', new google.maps.Size(9,9), new google.maps.Point(138, 227))
+ @hlicon = new google.maps.MarkerImage('/images/m3.png')
@infoWindow = new google.maps.InfoWindow()
-
- google.maps.event.addListener @map, 'tilesloaded', loadCustomers
+ loadDefaultLocation()
+ loadCustomers()
+ #google.maps.event.addListener @map, 'tilesloaded', onMapLoad
initialize()
+
+
+ highlightCustomerLocation= (id) ->
+ icon = @icon
+ map = @map
+ if @customers?.length
+ for customer in @customers when customer._id is id
+ do (customer) =>
+ marker = customer?.marker
+ if marker?
+ #marker.setIcon @hlicon
+ map.setCenter marker.getPosition()
+ ###
+ window.setTimeout =>
+ console.log icon
+ marker.setIcon icon
+ marker.setVisible true
+ , 1000
+ ###
+
+
+ onclientrowclick = (e) ->
+ customerid = $(e.target).closest('tr.client-row').attr('customerid')
+
+ highlightCustomerLocation customerid
+
+
+ $('.clientlist-container').on 'click', onclientrowclick
View
1  coffee/repository/base.coffee
@@ -59,7 +59,6 @@ Repository::setCollectionName = (@collectionName) ->
Repository::getDb = (callback = ->) ->
- console.log 'db = ', root?.db
if root?.db?.state isnt 'connected'
db_connector.open (err, db) =>
root.db = db
View
17 coffee/routes/index.coffee
@@ -1,3 +1,19 @@
+exports.defaultLocation = (req, res, next) ->
+ userSvc = require '../services/user'
+
+ try
+ userSvc.getById req.user._id, (err, user) ->
+ res.send
+ success: !!! (err)
+ location: user?.location
+ error: err
+ catch e
+ console.trace e
+ res.send
+ success: false
+ error: e
+
+
exports.accountadd = (req, res, next) ->
res.render 'add',
layout: true
@@ -10,6 +26,7 @@ exports.createaccount = (req, res, next) ->
account.username = req.param 'username', ''
account.password = req.param 'password', ''
account.passwordconfirm = req.param 'passwordconfirm' ,''
+ account.address = req.param 'address' ,''
userSvc = require '../services/user'
try
View
13 coffee/services/customer.coffee
@@ -8,8 +8,16 @@ exports.add = (customer, callback = ->) ->
customer?.userid = new repo.ObjectId(customer?.userid) if customer?.userid? and typeof customer?.userid is 'string'
try
- repo.create customer, (err, addedcustomers) ->
- callback err, addedcustomers?[0]
+ if customer?.address
+ geocoder = require 'geocoder'
+ geocoder.geocode customer?.address, (err, data) ->
+ if data?.status is 'OK'
+ customer.location = data?.results?[0]?.geometry?.location
+ repo.create customer, (err, addedcustomers) ->
+ callback err, addedcustomers?[0]
+ else
+ repo.create customer, (err, addedcustomers) ->
+ callback err, addedcustomers?[0]
catch e
console.trace e
throw e
@@ -45,7 +53,6 @@ exports.getAll = (userid, filter, callback = ->) ->
db = cursor.db
callback.apply null, [toarrayerr, customers]
cursor.close()
- db.close()
else
callback()
View
370 coffee/services/user.coffee
@@ -46,34 +46,6 @@ exports.notifyChallenge = (userid, data, callback = ->) ->
console.trace e
callback e
-###
-###
-exports.getrecords = (userid, callback = ->) ->
- console.assert userid, 'userid cannot be null or 0'
- throw 'userid is null or empty' unless userid?
-
- try
- utils.execute( newUserRepo.getById, userid )
- .then (err, user, cb = ->) ->
- return callback(err) if err
-
- if user?.records?.length
- teamsvc = require './team'
- utils.mapAsync user?.records, (rec, iteratorcb = ->) ->
- rec?.result = if rec?.data?.result is 'win' then 'W' else 'L'
- rec?.teamid = rec?.data?.opponentid
- teamsvc.getById rec?.data?.opponentid, (getteamerr, team) ->
- rec?.teamname = team?.teamname
- iteratorcb getteamerr, rec
- , cb
- else
- cb()
- .then (err, recs, cb = ->) ->
- callback err, recs
-
- catch e
- console.trace e
- callback e
###
Authenticate a user login
@@ -106,91 +78,7 @@ exports.getById = (userid, callback = ->) ->
newUserRepo.getById userid, callback
catch e
console.trace e
- callback e
-
-
-###
-Update player's stats
-###
-exports.resetStats = (userid, callback = ->) ->
- console.assert userid, 'userid cannot be null or 0'
- throw 'userid is null or empty' unless userid?
-
- userid = new newUserRepo.ObjectId( userid ) if typeof userid is 'string'
- findObj = _id : userid
- updateObj =
- $unset:
- stats: 1
- records: 1
-
- try
- newUserRepo.update findObj, updateObj, {}, callback
- catch e
- console.trace e
- callback e
-
-
-###
-Update player's stats
-###
-exports.updateStats = (userid, opponentid, win, callback = ->) ->
- console.assert userid, 'userid cannot be null or 0'
- throw 'userid is null or empty' unless userid?
-
- userid = new newUserRepo.ObjectId( userid ) if typeof userid is 'string'
- opponentid = String opponentid if typeof opponentid isnt 'string'
- findObj = _id : userid
- incObj = if win then {'stats.win':1} else {'stats.loss': 1}
- statLog =
- id: new newUserRepo.ObjectId()
- type: 'matchresult'
- data:
- opponentid: opponentid
- result: if win then 'win' else 'lose'
- createdat: new Date()
- updateObj =
- $inc: incObj
- $set:
- updatedat: new Date()
- $addToSet:
- posts: statLog
- records: statLog
-
- try
- newUserRepo.update findObj, updateObj, {}, callback
- catch e
- console.trace e
- callback e
-
-
-###
-Update player's stats. Silently
-###
-exports.updateStatsSilent = (userid, opponentid, win, callback = ->) ->
- console.assert userid, 'userid cannot be null or 0'
- throw 'userid is null or empty' unless userid?
-
- userid = new newUserRepo.ObjectId( userid ) if typeof userid is 'string'
- opponentid = String opponentid if typeof opponentid isnt 'string'
- findObj = _id : userid
- incObj = if win then {'stats.win':1} else {'stats.loss': 1}
- statLog =
- id: new newUserRepo.ObjectId()
- type: 'matchresult'
- data:
- opponentid: opponentid
- result: if win then 'win' else 'lose'
- createdat: new Date()
- updateObj =
- $inc: incObj
- $addToSet:
- records: statLog
-
- try
- newUserRepo.update findObj, updateObj, {}, callback
- catch e
- console.trace e
- callback e
+ callback e
@@ -216,240 +104,20 @@ exports.updatePicture = (userid, pictureurl, callback = ->) ->
-###
-Add a vote record into player's record
-###
-exports.addVote = (userid, vote, callback = ->) ->
- console.assert userid, 'userid cannot be null or 0'
- throw 'userid is null or empty' unless userid?
-
- userid = new newUserRepo.ObjectId( userid ) if typeof userid is 'string'
- findObj = _id : userid
- logObj =
- type: 'matchresult'
- data:
- matchid: vote.matchid
- teamid: vote.teamid
- createdat: new Date()
- updateObj =
- $set:
- updatedat: new Date()
- $addToSet:
- votes: vote
- logs: logObj
-
- try
- newUserRepo.update findObj, updateObj, {}, callback
- catch e
- console.trace e
- callback e
-
-
-###
-Set a team to a player
-###
-exports.setTeam = (userid, team, callback = ->) ->
- console.assert userid, 'userid cannot be null or 0'
- throw 'userid is null or empty' unless userid?
-
- userid = new newUserRepo.ObjectId( userid ) if typeof userid is 'string'
- findObj = _id : userid
- post =
- id: new newUserRepo.ObjectId()
- type: 'jointeam'
- data:
- teamid: String(team._id)
- createdat: new Date()
- updateObj =
- $set:
- team: team
- updatedat: new Date()
- $unset:
- invites: 1
- $addToSet:
- posts: post
-
- try
- newUserRepo.update findObj, updateObj, {}, callback
- catch e
- console.trace e
- callback e
-
-
-###
-Add a post record into player's record
-###
-exports.addPost = (userid, post, callback= ->) ->
- console.assert userid, 'userid cannot be null or 0'
- throw 'userid is null or empty' unless userid?
-
- userid = new newUserRepo.ObjectId( userid ) if typeof userid is 'string'
-
- findObj = _id : userid
- post or= {}
- post.createdat = new Date()
- post.id = new newUserRepo.ObjectId()
- updateObj =
- $set:
- updatedat: new Date()
- $addToSet:
- posts: post
-
- try
- newUserRepo.update findObj, updateObj, {}, callback
- catch e
- console.trace e
- callback e
-
-
-###
-Remove a post from player's record
-###
-exports.removePost = (userid, postid, callback = ->) ->
- console.assert userid, 'userid cannot be null or 0'
- throw 'userid is null or empty' unless userid?
- console.assert postid, 'postid cannot be null or 0'
- throw 'postid is null or empty' unless postid?
-
- userid = new newUserRepo.ObjectId( userid ) if typeof userid is 'string'
- postid = new newUserRepo.ObjectId( postid ) if typeof postid is 'string'
- findObj = _id : userid
- updateObj =
- $set:
- updatedat: new Date()
- $pull:
- posts:
- id: postid
-
- try
- newUserRepo.update findObj, updateObj, {}, callback
- catch e
- console.trace e
- callback e
-
-
-###
-Add a comment record into player's record
-###
-exports.addComment = (userid, postid, data, callback = ->) ->
- console.assert userid, 'userid cannot be null or 0'
- throw 'userid is null or empty' unless userid?
- console.assert postid, 'postid cannot be null or 0'
- throw 'postid is null or empty' unless postid?
-
- userid = new newUserRepo.ObjectId( userid ) if typeof userid is 'string'
- postid = new newUserRepo.ObjectId( postid ) if typeof postid is 'string'
-
- data or= {}
- data.id = new newUserRepo.ObjectId()
- data.createdat = new Date()
-
- findObj = _id : userid
-
- try
- newUserRepo.getById userid, (getErr, user) ->
- return callback( getErr ) if getErr?
- for post in user?.posts when post?.id?.equals( postid )
- do (post) ->
- post.comments or= []
- post.comments.push data
- updateObj =
- $set:
- posts: user?.posts
- updatedat: new Date()
- newUserRepo.update findObj, updateObj, {}, callback
- catch e
- console.trace e
- callback e
-
-
-###
-Remove a comment
-###
-exports.removeComment = (userid, postid, commentid, callback = ->) ->
- console.assert userid, 'userid cannot be null or 0'
- throw 'userid is null or empty' unless userid?
- console.assert postid, 'postid cannot be null or 0'
- throw 'postid is null or empty' unless postid?
- console.assert commentid, 'commentid cannot be null or 0'
- throw 'commentid is null or empty' unless commentid?
-
- userid = new newUserRepo.ObjectId( userid ) if typeof userid is 'string'
- postid = new newUserRepo.ObjectId( postid ) if typeof postid is 'string'
- commentid = new newUserRepo.ObjectId( commentid ) if typeof commentid is 'string'
+exports.updateLocation = updateLocation = (user, callback = ->) ->
+ console.assert user, 'user cannot be null'
+ throw 'user cannot be null' unless user?
+ console.assert user?.address, 'address cannot be empty'
- findObj = _id : userid
+ geocoder = require 'geocoder'
+ geocoder.geocode user?.address, (err, data) ->
+ if data?.status is 'OK'
+ user.location = data?.results?[0]?.geometry?.location
+ newUserRepo.update {_id: user?._id}, {$set: {location: user.location}}, {}, callback
+ else
+ callback err
- try
- newUserRepo.getById userid, (getErr, user) ->
- return callback( getErr ) if getErr?
- for post in user?.posts when post?.id?.equals( postid )
- do (post) ->
- for comment, index in post?.comments
- do (comment, index) ->
- if comment?.id?.equals(commentid)
- post?.comments.splice index, 1
- updateObj =
- $set:
- posts: user?.posts
- updatedat: new Date()
- newUserRepo.update findObj, updateObj, {}, callback
- catch e
- console.trace e
- callback e
-###
-Add a vote record into player's record
-###
-exports.addTeamInvite = (userid, teamid, callback = ->) ->
- console.assert userid, 'userid cannot be null or 0'
- throw 'userid is null or empty' unless userid?
- console.assert teamid, 'teamid cannot be null or 0'
- throw 'teamid is null or empty' unless teamid?
-
- userid = new newUserRepo.ObjectId( userid ) if typeof userid is 'string'
- teamid = new newUserRepo.ObjectId( teamid ) if typeof teamid is 'string'
-
- findObj = _id : userid
- invite =
- teamid: teamid
- invitedPost =
- id: new newUserRepo.ObjectId()
- type: 'invite'
- data:
- teamid: teamid
- createdat: new Date()
- updateObj =
- $set:
- updatedat: new Date()
- $addToSet:
- invites: invite
- posts: invitedPost
-
- try
- newUserRepo.update findObj, updateObj, {}, callback
- catch e
- console.trace e
- callback e
-
-
-exports.sortingPlayers = (player1, player2) ->
- win1 = player1?.stats?.win ? 0
- loss1 = player1?.stats?.loss ? 0
- total1 = win1 + loss1
- avg1 = if total1 then (win1 / total1) else 0
- win2 = player2?.stats?.win ? 0
- loss2 = player2?.stats?.loss ? 0
- total2 = win2 + loss2
- avg2 = if total2 then (win2 / total2) else 0
-
- if avg1 isnt avg2
- -avg1 + avg2
- else if win1 isnt win2
- -win1 + win2
- else
- loss1 - loss2
-
exports.insert = (user, callback = ->) ->
console.assert user, 'user cannot be null'
@@ -462,7 +130,7 @@ exports.insert = (user, callback = ->) ->
throw 'Password cannot be null or empty' unless user?.password
utils.execute(newUserRepo.getByUsername, user.username)
- .then (err, existingUser, cb) ->
+ .then (err, existingUser, cb = ->) ->
if err?
callback err
else if existingUser?
@@ -476,8 +144,14 @@ exports.insert = (user, callback = ->) ->
catch e
console.trace e
callback e
- .then (err, newUsers, cb) ->
- callback err, newUsers?[0]
+ .then (err, newUsers, cb = ->) =>
+ @addedUser = newUsers?[0]
+ if @addedUser?.address and not @addedUser?.location
+ updateLocation @addedUser, cb
+ else
+ callback err, @addedUser
+ .then (err, updatedUser, cb = ->) =>
+ callback err, @addedUser
exports.getAllPlayers = (callback = ->) ->
@@ -491,7 +165,6 @@ exports.getAllPlayers = (callback = ->) ->
db = cursor.db
callback.apply null, arguments
cursor.close()
- db.close()
else
callback()
@@ -540,7 +213,6 @@ exports.getUserByToken = (token, callback = ->) ->
db = cursor.db
callback.apply null, arguments
cursor.close()
- db.close()
.then (err, users, cb = ->) ->
if err
View
3  node_modules/geocoder/.npmignore
@@ -0,0 +1,3 @@
+.*.sw*
+node_modules
+scrap.js
View
20 node_modules/geocoder/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2011 Stephen Wyatt Bush
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
52 node_modules/geocoder/README.markdown
@@ -0,0 +1,52 @@
+# Geocoder
+
+###Installation:
+
+ npm install geocoder
+
+### Usage
+
+You can pass a string representation of a location and a callback function to `geocoder.geocode`. It will accept anything that Google will accept: cities, streets, countries, etc.
+
+###Example:
+
+```javascript
+var geocoder = require('geocoder');
+
+// Geocoding
+geocoder.geocode("Atlanta, GA", function ( err, data ) {
+ // do something with data
+});
+
+// Reverse Geocoding
+geocoder.reverseGeocode( 33.7489, -84.3789, function ( err, data ) {
+ // do something with data
+});
+
+// Setting sensor to true
+geocoder.reverseGeocode( 33.7489, -84.3789, function ( err, data ) {
+ // do something with data
+}, { sensor: true });
+
+// Setting language to German
+geocoder.reverseGeocode( 33.7489, -84.3789, function ( err, data ) {
+ // do something with data
+}, { language: 'de' });
+
+
+
+```
+
+Results will look like standard [Google JSON Output](http://code.google.com/apis/maps/documentation/geocoding/#JSON)
+
+You can pass in an optional options hash as a last argument, useful for setting sensor to true (it defaults to false) and the language (default is empty which means that google geocoder will guess it by geo ip data). For details see the [Google Geocoding API Docs](http://code.google.com/intl/en-US/apis/maps/documentation/geocoding/#GeocodingRequests)
+
+###Testing:
+`nodeunit test`
+
+## Roadmap
+- Complete Test Suite
+- Better options handling
+
+## Further Reading
+- [Blog post](http://blog.stephenwyattbush.com/2011/07/16/geocoding-with-nodejs/)
View
122 node_modules/geocoder/index.js
@@ -0,0 +1,122 @@
+/**
+ * Geocoder
+ */
+
+/**
+ * Module Dependencies
+ */
+
+var http = require( 'http' );
+var Hash = require('hashish');
+var querystring = require('querystring');
+
+/**
+ * Version
+ */
+
+var version = '0.1.0';
+
+/**
+ * Makes request to Google API and passes result to a callback
+ *
+ * @param {Object} options, required
+ * @param {Function} callback, required
+ * @api private
+ */
+
+function request ( options, cbk ) {
+
+ http.get( options, function ( response ) {
+ var data = "", result;
+
+ response.on("error", function ( err ) {
+ return cbk( err );
+ });
+
+ response.on("data", function ( chunk ) {
+ data += chunk;
+ });
+
+ response.on("end", function ( argument ) {
+ result = JSON.parse( data );
+ return cbk( null, result );
+ });
+
+ }).on("error", function (err) {
+ return cbk( err );
+ });
+
+}
+
+/**
+ * Geocoder
+ */
+
+function Geocoder () {}
+
+/**
+ * Geocoder prototype
+ */
+
+Geocoder.prototype = {
+
+ /**
+ * Request geocoordinates of given `loc` from Google
+ *
+ * @param {String} loc, required
+ * @param {Function} cbk, required
+ * @param {Object} opts, optional
+ * @api public
+ */
+
+ geocode: function ( loc, cbk, opts ) {
+
+ if ( ! loc ) {
+ return cbk( new Error( "Geocoder.geocode requires a location.") );
+ }
+
+ var options = Hash.merge({sensor: false, address: loc}, opts || {});
+
+ var params = {
+ host: 'maps.googleapis.com',
+ port: 80,
+ path: '/maps/api/geocode/json?' + querystring.stringify(options),
+ headers: {}
+ };
+
+ return request( params, cbk );
+ },
+
+ reverseGeocode: function ( lat, lng, cbk, opts ) {
+ if ( !lat || !lng ) {
+ return cbk( new Error( "Geocoder.reverseGeocode requires a latitude and longitude." ) );
+ }
+
+ var options = Hash.merge({sensor: false, latlng: lat + ',' + lng}, opts || {});
+
+ var params = {
+ host: 'maps.googleapis.com',
+ port: 80,
+ path: '/maps/api/geocode/json?' + querystring.stringify(options),
+ headers: {}
+ };
+
+ return request( params, cbk );
+
+ },
+
+ /**
+ * Return Geocoder version
+ *
+ * @api public
+ */
+
+ version: version
+
+};
+
+/**
+ * Export
+ */
+
+module.exports = new Geocoder();
View
191 node_modules/geocoder/node_modules/hashish/README.markdown
@@ -0,0 +1,191 @@
+Hashish
+=======
+
+Hashish is a node.js library for manipulating hash data structures.
+It is distilled from the finest that ruby, perl, and haskell have to offer by
+way of hash/map interfaces.
+
+Hashish provides a chaining interface, where you can do:
+
+ var Hash = require('hashish');
+
+ Hash({ a : 1, b : 2, c : 3, d : 4 })
+ .map(function (x) { return x * 10 })
+ .filter(function (x) { return x < 30 })
+ .forEach(function (x, key) {
+ console.log(key + ' => ' + x);
+ })
+ ;
+
+Output:
+
+ a => 10
+ b => 20
+
+Some functions and attributes in the chaining interface are terminal, like
+`.items` or `.detect()`. They return values of their own instead of the chain
+context.
+
+Each function in the chainable interface is also attached to `Hash` in chainless
+form:
+
+ var Hash = require('hashish');
+ var obj = { a : 1, b : 2, c : 3, d : 4 };
+
+ var mapped = Hash.map(obj, function (x) {
+ return x * 10
+ });
+
+ console.dir(mapped);
+
+Output:
+
+ { a: 10, b: 20, c: 30, d: 40 }
+
+In either case, the 'this' context of the function calls is the same object that
+the chained functions return, so you can make nested chains.
+
+Methods
+=======
+
+forEach(cb)
+-----------
+
+For each key/value in the hash, calls `cb(value, key)`.
+
+map(cb)
+-------
+
+For each key/value in the hash, calls `cb(value, key)`.
+The return value of `cb` is the new value at `key` in the resulting hash.
+
+filter(cb)
+----------
+
+For each key/value in the hash, calls `cb(value, key)`.
+The resulting hash omits key/value pairs where `cb` returned a falsy value.
+
+detect(cb)
+----------
+
+Returns the first value in the hash for which `cb(value, key)` is non-falsy.
+Order of hashes is not well-defined so watch out for that.
+
+reduce(cb)
+----------
+
+Returns the accumulated value of a left-fold over the key/value pairs.
+
+some(cb)
+--------
+
+Returns a boolean: whether or not `cb(value, key)` ever returned a non-falsy
+value.
+
+update(obj1, [obj2, obj3, ...])
+-----------
+
+Mutate the context hash, merging the key/value pairs from the passed objects
+and overwriting keys from the context hash if the current `obj` has keys of
+the same name. Falsy arguments are silently ignored.
+
+updateAll([ obj1, obj2, ... ])
+------------------------------
+
+Like multi-argument `update()` but operate on an array directly.
+
+merge(obj1, [obj2, obj3, ...])
+----------
+
+Merge the key/value pairs from the passed objects into the resultant hash
+without modifying the context hash. Falsy arguments are silently ignored.
+
+mergeAll([ obj1, obj2, ... ])
+------------------------------
+
+Like multi-argument `merge()` but operate on an array directly.
+
+has(key)
+--------
+
+Return whether the hash has a key, `key`.
+
+valuesAt(keys)
+--------------
+
+Return an Array with the values at the keys from `keys`.
+
+tap(cb)
+-------
+
+Call `cb` with the present raw hash.
+This function is chainable.
+
+extract(keys)
+-------------
+
+Filter by including only those keys in `keys` in the resulting hash.
+
+exclude(keys)
+-------------
+
+Filter by excluding those keys in `keys` in the resulting hash.
+
+Attributes
+==========
+
+These are attributes in the chaining interface and functions in the `Hash.xxx`
+interface.
+
+keys
+----
+
+Return all the enumerable attribute keys in the hash.
+
+values
+------
+
+Return all the enumerable attribute values in the hash.
+
+compact
+-------
+
+Filter out values which are `=== undefined`.
+
+clone
+-----
+
+Make a deep copy of the hash.
+
+copy
+----
+
+Make a shallow copy of the hash.
+
+length
+------
+
+Return the number of key/value pairs in the hash.
+Note: use `Hash.size()` for non-chain mode.
+
+size
+----
+
+Alias for `length` since `Hash.length` is masked by `Function.prototype`.
+
+See Also
+========
+
+See also [creationix's pattern/hash](http://github.com/creationix/pattern),
+which does a similar thing except with hash inputs and array outputs.
+
+Installation
+============
+
+To install with [npm](http://github.com/isaacs/npm):
+
+ npm install hashish
+
+To run the tests with [expresso](http://github.com/visionmedia/expresso):
+
+ expresso
View
9 node_modules/geocoder/node_modules/hashish/examples/chain.js
@@ -0,0 +1,9 @@
+var Hash = require('hashish');
+
+Hash({ a : 1, b : 2, c : 3, d : 4 })
+ .map(function (x) { return x * 10 })
+ .filter(function (x) { return x < 30 })
+ .forEach(function (x, key) {
+ console.log(key + ' => ' + x);
+ })
+;
View
7 node_modules/geocoder/node_modules/hashish/examples/map.js
@@ -0,0 +1,7 @@
+var Hash = require('hashish');
+var obj = { a : 1, b : 2, c : 3, d : 4 };
+
+var mapped = Hash.map(obj, function (x) {
+ return x * 10
+});
+console.dir(mapped);
View
253 node_modules/geocoder/node_modules/hashish/index.js
@@ -0,0 +1,253 @@
+module.exports = Hash;
+var Traverse = require('traverse');
+
+function Hash (hash, xs) {
+ if (Array.isArray(hash) && Array.isArray(xs)) {
+ var to = Math.min(hash.length, xs.length);
+ var acc = {};
+ for (var i = 0; i < to; i++) {
+ acc[hash[i]] = xs[i];
+ }
+ return Hash(acc);
+ }
+
+ if (hash === undefined) return Hash({});
+
+ var self = {
+ map : function (f) {
+ var acc = { __proto__ : hash.__proto__ };
+ Object.keys(hash).forEach(function (key) {
+ acc[key] = f.call(self, hash[key], key);
+ });
+ return Hash(acc);
+ },
+ forEach : function (f) {
+ Object.keys(hash).forEach(function (key) {
+ f.call(self, hash[key], key);
+ });
+ return self;
+ },
+ filter : function (f) {
+ var acc = { __proto__ : hash.__proto__ };
+ Object.keys(hash).forEach(function (key) {
+ if (f.call(self, hash[key], key)) {
+ acc[key] = hash[key];
+ }
+ });
+ return Hash(acc);
+ },
+ detect : function (f) {
+ for (var key in hash) {
+ if (f.call(self, hash[key], key)) {
+ return hash[key];
+ }
+ }
+ return undefined;
+ },
+ reduce : function (f, acc) {
+ var keys = Object.keys(hash);
+ if (acc === undefined) acc = keys.shift();
+ keys.forEach(function (key) {
+ acc = f.call(self, acc, hash[key], key);
+ });
+ return acc;
+ },
+ some : function (f) {
+ for (var key in hash) {
+ if (f.call(self, hash[key], key)) return true;
+ }
+ return false;
+ },
+ update : function (obj) {
+ if (arguments.length > 1) {
+ self.updateAll([].slice.call(arguments));
+ }
+ else {
+ Object.keys(obj).forEach(function (key) {
+ hash[key] = obj[key];
+ });
+ }
+ return self;
+ },
+ updateAll : function (xs) {
+ xs.filter(Boolean).forEach(function (x) {
+ self.update(x);
+ });
+ return self;
+ },
+ merge : function (obj) {
+ if (arguments.length > 1) {
+ return self.copy.updateAll([].slice.call(arguments));
+ }
+ else {
+ return self.copy.update(obj);
+ }
+ },
+ mergeAll : function (xs) {
+ return self.copy.updateAll(xs);
+ },
+ has : function (key) { // only operates on enumerables
+ return Array.isArray(key)
+ ? key.every(function (k) { return self.has(k) })
+ : self.keys.indexOf(key.toString()) >= 0;
+ },
+ valuesAt : function (keys) {
+ return Array.isArray(keys)
+ ? keys.map(function (key) { return hash[key] })
+ : hash[keys]
+ ;
+ },
+ tap : function (f) {
+ f.call(self, hash);
+ return self;
+ },
+ extract : function (keys) {
+ var acc = {};
+ keys.forEach(function (key) {
+ acc[key] = hash[key];
+ });
+ return Hash(acc);
+ },
+ exclude : function (keys) {
+ return self.filter(function (_, key) {
+ return keys.indexOf(key) < 0
+ });
+ },
+ end : hash,
+ items : hash
+ };
+
+ var props = {
+ keys : function () { return Object.keys(hash) },
+ values : function () {
+ return Object.keys(hash).map(function (key) { return hash[key] });
+ },
+ compact : function () {
+ return self.filter(function (x) { return x !== undefined });
+ },
+ clone : function () { return Hash(Hash.clone(hash)) },
+ copy : function () { return Hash(Hash.copy(hash)) },
+ length : function () { return Object.keys(hash).length },
+ size : function () { return self.length }
+ };
+
+ if (Object.defineProperty) {
+ // es5-shim has an Object.defineProperty but it throws for getters
+ try {
+ for (var key in props) {
+ Object.defineProperty(self, key, { get : props[key] });
+ }
+ }
+ catch (err) {
+ for (var key in props) {
+ if (key !== 'clone' && key !== 'copy' && key !== 'compact') {
+ // ^ those keys use Hash() so can't call them without
+ // a stack overflow
+ self[key] = props[key]();
+ }
+ }
+ }
+ }
+ else if (self.__defineGetter__) {
+ for (var key in props) {
+ self.__defineGetter__(key, props[key]);
+ }
+ }
+ else {
+ // non-lazy version for browsers that suck >_<
+ for (var key in props) {
+ self[key] = props[key]();
+ }
+ }
+
+ return self;
+};
+
+// deep copy
+Hash.clone = function (ref) {
+ return Traverse.clone(ref);
+};
+
+// shallow copy
+Hash.copy = function (ref) {
+ var hash = { __proto__ : ref.__proto__ };
+ Object.keys(ref).forEach(function (key) {
+ hash[key] = ref[key];
+ });
+ return hash;
+};
+
+Hash.map = function (ref, f) {
+ return Hash(ref).map(f).items;
+};
+
+Hash.forEach = function (ref, f) {
+ Hash(ref).forEach(f);
+};
+
+Hash.filter = function (ref, f) {
+ return Hash(ref).filter(f).items;
+};
+
+Hash.detect = function (ref, f) {
+ return Hash(ref).detect(f);
+};
+
+Hash.reduce = function (ref, f, acc) {
+ return Hash(ref).reduce(f, acc);
+};
+
+Hash.some = function (ref, f) {
+ return Hash(ref).some(f);
+};
+
+Hash.update = function (a /*, b, c, ... */) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ var hash = Hash(a);
+ return hash.update.apply(hash, args).items;
+};
+
+Hash.merge = function (a /*, b, c, ... */) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ var hash = Hash(a);
+ return hash.merge.apply(hash, args).items;
+};
+
+Hash.has = function (ref, key) {
+ return Hash(ref).has(key);
+};
+
+Hash.valuesAt = function (ref, keys) {
+ return Hash(ref).valuesAt(keys);
+};
+
+Hash.tap = function (ref, f) {
+ return Hash(ref).tap(f).items;
+};
+
+Hash.extract = function (ref, keys) {
+ return Hash(ref).extract(keys).items;
+};
+
+Hash.exclude = function (ref, keys) {
+ return Hash(ref).exclude(keys).items;
+};
+
+Hash.concat = function (xs) {
+ var hash = Hash({});
+ xs.forEach(function (x) { hash.update(x) });
+ return hash.items;
+};
+
+Hash.zip = function (xs, ys) {
+ return Hash(xs, ys).items;
+};
+
+// .length is already defined for function prototypes
+Hash.size = function (ref) {
+ return Hash(ref).size;
+};
+
+Hash.compact = function (ref) {
+ return Hash(ref).compact.items;
+};
View
1  node_modules/geocoder/node_modules/hashish/node_modules/traverse/.npmignore
@@ -0,0 +1 @@
+node_modules
View
24 node_modules/geocoder/node_modules/hashish/node_modules/traverse/LICENSE
@@ -0,0 +1,24 @@
+Copyright 2010 James Halliday (mail@substack.net)
+
+This project is free software released under the MIT/X11 license:
+http://www.opensource.org/licenses/mit-license.php
+
+Copyright 2010 James Halliday (mail@substack.net)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
View
256 node_modules/geocoder/node_modules/hashish/node_modules/traverse/README.markdown
@@ -0,0 +1,256 @@
+traverse
+========
+
+Traverse and transform objects by visiting every node on a recursive walk.
+
+examples
+========
+
+transform negative numbers in-place
+-----------------------------------
+
+negative.js
+
+````javascript
+var traverse = require('traverse');
+var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];
+
+traverse(obj).forEach(function (x) {
+ if (x < 0) this.update(x + 128);
+});
+
+console.dir(obj);
+````
+
+Output:
+
+ [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ]
+
+collect leaf nodes
+------------------
+
+leaves.js
+
+````javascript
+var traverse = require('traverse');
+
+var obj = {
+ a : [1,2,3],
+ b : 4,
+ c : [5,6],
+ d : { e : [7,8], f : 9 },
+};
+
+var leaves = traverse(obj).reduce(function (acc, x) {
+ if (this.isLeaf) acc.push(x);
+ return acc;
+}, []);
+
+console.dir(leaves);
+````
+
+Output:
+
+ [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
+
+scrub circular references
+-------------------------
+
+scrub.js:
+
+````javascript
+var traverse = require('traverse');
+
+var obj = { a : 1, b : 2, c : [ 3, 4 ] };
+obj.c.push(obj);
+
+var scrubbed = traverse(obj).map(function (x) {
+ if (this.circular) this.remove()
+});
+console.dir(scrubbed);
+````
+
+output:
+
+ { a: 1, b: 2, c: [ 3, 4 ] }
+
+methods
+=======
+
+Each method that takes an `fn` uses the context documented below in the context
+section.
+
+.map(fn)
+--------
+
+Execute `fn` for each node in the object and return a new object with the
+results of the walk. To update nodes in the result use `this.update(value)`.
+
+.forEach(fn)
+------------
+
+Execute `fn` for each node in the object but unlike `.map()`, when
+`this.update()` is called it updates the object in-place.
+
+.reduce(fn, acc)
+----------------
+
+For each node in the object, perform a
+[left-fold](http://en.wikipedia.org/wiki/Fold_(higher-order_function))
+with the return value of `fn(acc, node)`.
+
+If `acc` isn't specified, `acc` is set to the root object for the first step
+and the root element is skipped.
+
+.paths()
+--------
+
+Return an `Array` of every possible non-cyclic path in the object.
+Paths are `Array`s of string keys.
+
+.nodes()
+--------
+
+Return an `Array` of every node in the object.
+
+.clone()
+--------
+
+Create a deep clone of the object.
+
+.get(path)
+----------
+
+Get the element at the array `path`.
+
+.set(path, value)
+-----------------
+
+Set the element at the array `path` to `value`.
+
+.has(path)
+----------
+
+Return whether the element at the array `path` exists.
+
+context
+=======
+
+Each method that takes a callback has a context (its `this` object) with these
+attributes:
+
+this.node
+---------
+
+The present node on the recursive walk
+
+this.path
+---------
+
+An array of string keys from the root to the present node
+
+this.parent
+-----------
+
+The context of the node's parent.
+This is `undefined` for the root node.
+
+this.key
+--------
+
+The name of the key of the present node in its parent.
+This is `undefined` for the root node.
+
+this.isRoot, this.notRoot
+-------------------------
+
+Whether the present node is the root node
+
+this.isLeaf, this.notLeaf
+-------------------------
+
+Whether or not the present node is a leaf node (has no children)
+
+this.level
+----------
+
+Depth of the node within the traversal
+
+this.circular
+-------------
+
+If the node equals one of its parents, the `circular` attribute is set to the
+context of that parent and the traversal progresses no deeper.
+
+this.update(value, stopHere=false)
+----------------------------------
+
+Set a new value for the present node.
+
+All the elements in `value` will be recursively traversed unless `stopHere` is
+true.
+
+this.remove(stopHere=false)
+-------------
+
+Remove the current element from the output. If the node is in an Array it will
+be spliced off. Otherwise it will be deleted from its parent.
+
+this.delete(stopHere=false)
+-------------
+
+Delete the current element from its parent in the output. Calls `delete` even on
+Arrays.
+
+this.before(fn)
+---------------
+
+Call this function before any of the children are traversed.
+
+You can assign into `this.keys` here to traverse in a custom order.
+
+this.after(fn)
+--------------
+
+Call this function after any of the children are traversed.
+
+this.pre(fn)
+------------
+
+Call this function before each of the children are traversed.
+
+this.post(fn)
+-------------
+
+Call this function after each of the children are traversed.
+
+
+install
+=======
+
+Using [npm](http://npmjs.org) do:
+
+ $ npm install traverse
+
+test
+====
+
+Using [expresso](http://github.com/visionmedia/expresso) do:
+
+ $ expresso
+
+ 100% wahoo, your stuff is not broken!
+
+in the browser
+==============
+
+Use [browserify](https://github.com/substack/node-browserify) to run traverse in
+the browser.
+
+traverse has been tested and works with:
+
+* Internet Explorer 5.5, 6.0, 7.0, 8.0, 9.0
+* Firefox 3.5
+* Chrome 6.0
+* Opera 10.6
+* Safari 5.0
View
16 node_modules/geocoder/node_modules/hashish/node_modules/traverse/examples/json.js
@@ -0,0 +1,16 @@
+var traverse = require('traverse');
+
+var id = 54;
+var callbacks = {};
+var obj = { moo : function () {}, foo : [2,3,4, function () {}] };
+
+var scrubbed = traverse(obj).map(function (x) {
+ if (typeof x === 'function') {
+ callbacks[id] = { id : id, f : x, path : this.path };
+ this.update('[Function]');
+ id++;
+ }
+});
+
+console.dir(scrubbed);
+console.dir(callbacks);
View
15 node_modules/geocoder/node_modules/hashish/node_modules/traverse/examples/leaves.js
@@ -0,0 +1,15 @@
+var traverse = require('traverse');
+
+var obj = {
+ a : [1,2,3],
+ b : 4,
+ c : [5,6],
+ d : { e : [7,8], f : 9 },
+};
+
+var leaves = traverse(obj).reduce(function (acc, x) {
+ if (this.isLeaf) acc.push(x);
+ return acc;
+}, []);
+
+console.dir(leaves);
View
8 node_modules/geocoder/node_modules/hashish/node_modules/traverse/examples/negative.js
@@ -0,0 +1,8 @@
+var traverse = require('traverse');
+var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];
+
+traverse(obj).forEach(function (x) {
+ if (x < 0) this.update(x + 128);
+});
+
+console.dir(obj);
View
10 node_modules/geocoder/node_modules/hashish/node_modules/traverse/examples/scrub.js
@@ -0,0 +1,10 @@
+// scrub out circular references
+var traverse = require('traverse');
+
+var obj = { a : 1, b : 2, c : [ 3, 4 ] };
+obj.c.push(obj);
+
+var scrubbed = traverse(obj).map(function (x) {
+ if (this.circular) this.remove()
+});
+console.dir(scrubbed);
View
38 node_modules/geocoder/node_modules/hashish/node_modules/traverse/examples/stringify.js
@@ -0,0 +1,38 @@
+#!/usr/bin/env node
+var traverse = require('traverse');
+
+var obj = [ 'five', 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];
+
+var s = '';
+traverse(obj).forEach(function to_s (node) {
+ if (Array.isArray(node)) {
+ this.before(function () { s += '[' });
+ this.post(function (child) {
+ if (!child.isLast) s += ',';
+ });
+ this.after(function () { s += ']' });
+ }
+ else if (typeof node == 'object') {
+ this.before(function () { s += '{' });
+ this.pre(function (x, key) {
+ to_s(key);
+ s += ':';
+ });
+ this.post(function (child) {
+ if (!child.isLast) s += ',';
+ });
+ this.after(function () { s += '}' });
+ }
+ else if (typeof node == 'string') {
+ s += '"' + node.toString().replace(/"/g, '\\"') + '"';
+ }
+ else if (typeof node == 'function') {
+ s += 'null';
+ }
+ else {
+ s += node.toString();
+ }
+});
+
+console.log('JSON.stringify: ' + JSON.stringify(obj));
+console.log('this stringify: ' + s);
View
279 node_modules/geocoder/node_modules/hashish/node_modules/traverse/index.js
@@ -0,0 +1,279 @@
+module.exports = Traverse;
+function Traverse (obj) {
+ if (!(this instanceof Traverse)) return new Traverse(obj);
+ this.value = obj;
+}
+
+Traverse.prototype.get = function (ps) {
+ var node = this.value;
+ for (var i = 0; i < ps.length; i ++) {
+ var key = ps[i];
+ if (!Object.hasOwnProperty.call(node, key)) {
+ node = undefined;
+ break;
+ }
+ node = node[key];
+ }
+ return node;
+};
+
+Traverse.prototype.has = function (ps) {
+ var node = this.value;
+ for (var i = 0; i < ps.length; i ++) {
+ var key = ps[i];
+ if (!Object.hasOwnProperty.call(node, key)) {
+ return false;
+ }
+ node = node[key];
+ }
+ return true;
+};
+
+Traverse.prototype.set = function (ps, value) {
+ var node = this.value;
+ for (var i = 0; i < ps.length - 1; i ++) {
+ var key = ps[i];
+ if (!Object.hasOwnProperty.call(node, key)) node[key] = {};
+ node = node[key];
+ }
+ node[ps[i]] = value;
+ return value;
+};
+
+Traverse.prototype.map = function (cb) {
+ return walk(this.value, cb, true);
+};
+
+Traverse.prototype.forEach = function (cb) {
+ this.value = walk(this.value, cb, false);
+ return this.value;
+};
+
+Traverse.prototype.reduce = function (cb, init) {
+ var skip = arguments.length === 1;
+ var acc = skip ? this.value : init;
+ this.forEach(function (x) {
+ if (!this.isRoot || !skip) {
+ acc = cb.call(this, acc, x);
+ }
+ });
+ return acc;
+};
+
+Traverse.prototype.paths = function () {
+ var acc = [];
+ this.forEach(function (x) {
+ acc.push(this.path);
+ });
+ return acc;
+};
+
+Traverse.prototype.nodes = function () {
+ var acc = [];
+ this.forEach(function (x) {
+ acc.push(this.node);
+ });
+ return acc;
+};
+
+Traverse.prototype.clone = function () {
+ var parents = [], nodes = [];
+
+ return (function clone (src) {
+ for (var i = 0; i < parents.length; i++) {
+ if (parents[i] === src) {
+ return nodes[i];
+ }
+ }
+
+ if (typeof src === 'object' && src !== null) {
+ var dst = copy(src);
+
+ parents.push(src);
+ nodes.push(dst);
+
+ forEach(Object_keys(src), function (key) {
+ dst[key] = clone(src[key]);
+ });
+
+ parents.pop();
+ nodes.pop();
+ return dst;
+ }
+ else {
+ return src;
+ }
+ })(this.value);
+};
+
+function walk (root, cb, immutable) {
+ var path = [];
+ var parents = [];
+ var alive = true;
+
+ return (function walker (node_) {
+ var node = immutable ? copy(node_) : node_;
+ var modifiers = {};
+
+ var keepGoing = true;
+
+ var state = {
+ node : node,
+ node_ : node_,
+ path : [].concat(path),
+ parent : parents[parents.length - 1],
+ parents : parents,
+ key : path.slice(-1)[0],
+ isRoot : path.length === 0,
+ level : path.length,
+ circular : null,
+ update : function (x, stopHere) {
+ if (!state.isRoot) {
+ state.parent.node[state.key] = x;
+ }
+ state.node = x;
+ if (stopHere) keepGoing = false;
+ },
+ 'delete' : function (stopHere) {
+ delete state.parent.node[state.key];
+ if (stopHere) keepGoing = false;
+ },
+ remove : function (stopHere) {
+ if (Array_isArray(state.parent.node)) {
+ state.parent.node.splice(state.key, 1);
+ }
+ else {
+ delete state.parent.node[state.key];
+ }
+ if (stopHere) keepGoing = false;
+ },
+ keys : null,
+ before : function (f) { modifiers.before = f },
+ after : function (f) { modifiers.after = f },
+ pre : function (f) { modifiers.pre = f },
+ post : function (f) { modifiers.post = f },
+ stop : function () { alive = false },
+ block : function () { keepGoing = false }
+ };
+
+ if (!alive) return state;
+
+ if (typeof node === 'object' && node !== null) {
+ state.keys = Object_keys(node);
+
+ state.isLeaf = state.keys.length == 0;
+
+ for (var i = 0; i < parents.length; i++) {
+ if (parents[i].node_ === node_) {
+ state.circular = parents[i];
+ break;
+ }
+ }
+ }
+ else {
+ state.isLeaf = true;
+ }
+
+ state.notLeaf = !state.isLeaf;
+ state.notRoot = !state.isRoot;
+
+ // use return values to update if defined
+ var ret = cb.call(state, state.node);
+ if (ret !== undefined && state.update) state.update(ret);
+
+ if (modifiers.before) modifiers.before.call(state, state.node);
+
+ if (!keepGoing) return state;
+
+ if (typeof state.node == 'object'
+ && state.node !== null && !state.circular) {
+ parents.push(state);
+
+ forEach(state.keys, function (key, i) {
+ path.push(key);
+
+ if (modifiers.pre) modifiers.pre.call(state, state.node[key], key);
+
+ var child = walker(state.node[key]);
+ if (immutable && Object.hasOwnProperty.call(state.node, key)) {
+ state.node[key] = child.node;
+ }
+
+ child.isLast = i == state.keys.length - 1;
+ child.isFirst = i == 0;
+
+ if (modifiers.post) modifiers.post.call(state, child);
+
+ path.pop();
+ });
+ parents.pop();
+ }
+
+ if (modifiers.after) modifiers.after.call(state, state.node);
+
+ return state;
+ })(root).node;
+}
+
+function copy (src) {
+ if (typeof src === 'object' && src !== null) {
+ var dst;
+
+ if (Array_isArray(src)) {
+ dst = [];
+ }
+ else if (src instanceof Date) {
+ dst = new Date(src);
+ }
+ else if (src instanceof Boolean) {
+ dst = new Boolean(src);
+ }
+ else if (src instanceof Number) {
+ dst = new Number(src);
+ }
+ else if (src instanceof String) {
+ dst = new String(src);
+ }
+ else if (Object.create && Object.getPrototypeOf) {
+ dst = Object.create(Object.getPrototypeOf(src));
+ }
+ else if (src.__proto__ || src.constructor.prototype) {
+ var proto = src.__proto__ || src.constructor.prototype || {};
+ var T = function () {};
+ T.prototype = proto;
+ dst = new T;
+ if (!dst.__proto__) dst.__proto__ = proto;
+ }
+
+ forEach(Object_keys(src), function (key) {
+ dst[key] = src[key];
+ });
+ return dst;
+ }
+ else return src;
+}
+
+var Object_keys = Object.keys || function keys (obj) {
+ var res = [];
+ for (var key in obj) res.push(key)
+ return res;
+};
+
+var Array_isArray = Array.isArray || function isArray (xs) {
+ return Object.prototype.toString.call(xs) === '[object Array]';
+};
+
+var forEach = function (xs, fn) {
+ if (xs.forEach) return xs.forEach(fn)
+ else for (var i = 0; i < xs.length; i++) {
+ fn(xs[i], i, xs);
+ }
+};
+
+forEach(Object_keys(Traverse.prototype), function (key) {
+ Traverse[key] = function (obj) {
+ var args = [].slice.call(arguments, 1);
+ var t = Traverse(obj);
+ return t[key].apply(t, args);
+ };
+});
View
18 node_modules/geocoder/node_modules/hashish/node_modules/traverse/package.json
@@ -0,0 +1,18 @@
+{
+ "name" : "traverse",
+ "version" : "0.6.0",
+ "description" : "Traverse and transform objects by visiting every node on a recursive walk",
+ "author" : "James Halliday",
+ "license" : "MIT/X11",
+ "main" : "./index",
+ "repository" : {
+ "type" : "git",
+ "url" : "http://github.com/substack/js-traverse.git"
+ },
+ "devDependencies" : {
+ "expresso" : "0.7.x"
+ },
+ "scripts" : {
+ "test" : "expresso"
+ }
+}
View
115 node_modules/geocoder/node_modules/hashish/node_modules/traverse/test/circular.js
@@ -0,0 +1,115 @@
+var assert = require('assert');
+var Traverse = require('../');
+var deepEqual = require('./lib/deep_equal');
+var util = require('util');
+
+exports.circular = function () {
+ var obj = { x : 3 };
+ obj.y = obj;
+ var foundY = false;
+ Traverse(obj).forEach(function (x) {
+ if (this.path.join('') == 'y') {
+ assert.equal(
+ util.inspect(this.circular.node),
+ util.inspect(obj)
+ );
+ foundY = true;
+ }
+ });
+ assert.ok(foundY);
+};
+
+exports.deepCirc = function () {
+ var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] };
+ obj.y[2] = obj;
+
+ var times = 0;
+ Traverse(obj).forEach(function (x) {
+ if (this.circular) {
+ assert.deepEqual(this.circular.path, []);
+ assert.deepEqual(this.path, [ 'y', 2 ]);
+ times ++;
+ }
+ });
+
+ assert.deepEqual(times, 1);
+};
+
+exports.doubleCirc = function () {
+ var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] };
+ obj.y[2] = obj;
+ obj.x.push(obj.y);
+
+ var circs = [];
+ Traverse(obj).forEach(function (x) {
+ if (this.circular) {
+ circs.push({ circ : this.circular, self : this, node : x });
+ }
+ });
+
+ assert.deepEqual(circs[0].self.path, [ 'x', 3, 2 ]);
+ assert.deepEqual(circs[0].circ.path, []);
+
+ assert.deepEqual(circs[1].self.path, [ 'y', 2 ]);
+ assert.deepEqual(circs[1].circ.path, []);
+
+ assert.deepEqual(circs.length, 2);
+};
+
+exports.circDubForEach = function () {
+ var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] };
+ obj.y[2] = obj;
+ obj.x.push(obj.y);
+
+ Traverse(obj).forEach(function (x) {
+ if (this.circular) this.update('...');
+ });
+
+ assert.deepEqual(obj, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] });
+};
+
+exports.circDubMap = function () {
+ var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] };
+ obj.y[2] = obj;
+ obj.x.push(obj.y);
+
+ var c = Traverse(obj).map(function (x) {
+ if (this.circular) {
+ this.update('...');
+ }
+ });
+
+ assert.deepEqual(c, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] });
+};
+
+exports.circClone = function () {
+ var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] };
+ obj.y[2] = obj;
+ obj.x.push(obj.y);
+
+ var clone = Traverse.clone(obj);
+ assert.ok(obj !== clone);
+
+ assert.ok(clone.y[2] === clone);
+ assert.ok(clone.y[2] !== obj);
+ assert.ok(clone.x[3][2] === clone);
+ assert.ok(clone.x[3][2] !== obj);
+ assert.deepEqual(clone.x.slice(0,3), [1,2,3]);
+ assert.deepEqual(clone.y.slice(0,2), [4,5]);
+};
+
+exports.circMapScrub = function () {
+ var obj = { a : 1, b : 2 };
+ obj.c = obj;
+
+ var scrubbed = Traverse(obj).map(function (node) {
+ if (this.circular) this.remove();
+ });
+ assert.deepEqual(
+ Object.keys(scrubbed).sort(),
+ [ 'a', 'b' ]
+ );
+ assert.ok(deepEqual(scrubbed, { a : 1, b : 2 }));
+
+ assert.equal(obj.c, obj);
+};
View
35 node_modules/geocoder/node_modules/hashish/node_modules/traverse/test/date.js
@@ -0,0 +1,35 @@
+var assert = require('assert');
+var Traverse = require('../');
+
+exports.dateEach = function () {
+ var obj = { x : new Date, y : 10, z : 5 };
+
+ var counts = {};
+
+ Traverse(obj).forEach(function (node) {
+ var t = (node instanceof Date && 'Date') || typeof node;
+ counts[t] = (counts[t] || 0) + 1;
+ });
+
+ assert.deepEqual(counts, {
+ object : 1,
+ Date : 1,
+ number : 2,
+ });
+};
+
+exports.dateMap = function () {
+ var obj = { x : new Date, y : 10, z : 5 };
+
+ var res = Traverse(obj).map(function (node) {
+ if (typeof node === 'number') this.update(node + 100);
+ });
+
+ assert.ok(obj.x !== res.x);
+ assert.deepEqual(res, {
+ x : obj.x,
+ y : 110,
+ z : 105,
+ });
+};
+
View
220 node_modules/geocoder/node_modules/hashish/node_modules/traverse/test/equal.js
@@ -0,0 +1,220 @@
+var assert = require('assert');
+var traverse = require('../');
+var deepEqual = require('./lib/deep_equal');
+
+exports.deepDates = function () {
+ assert.ok(
+ deepEqual(
+ { d : new Date, x : [ 1, 2, 3 ] },
+ { d : new Date, x : [ 1, 2, 3 ] }
+ ),
+ 'dates should be equal'
+ );
+
+ var d0 = new Date;
+ setTimeout(function () {
+ assert.ok(
+ !deepEqual(
+ { d : d0, x : [ 1, 2, 3 ], },
+ { d : new Date, x : [ 1, 2, 3 ] }
+ ),
+ 'microseconds should count in date equality'
+ );
+ }, 5);
+};
+
+exports.deepCircular = function () {
+ var a = [1];
+ a.push(a); // a = [ 1, *a ]
+
+ var b = [1];
+ b.push(a); // b = [ 1, [ 1, *a ] ]
+
+ assert.ok(
+ !deepEqual(a, b),
+ 'circular ref mount points count towards equality'
+ );
+
+ var c = [1];
+ c.push(c); // c = [ 1, *c ]
+ assert.ok(
+ deepEqual(a, c),
+ 'circular refs are structurally the same here'
+ );
+
+ var d = [1];
+ d.push(a); // c = [ 1, [ 1, *d ] ]
+ assert.ok(
+ deepEqual(b, d),
+ 'non-root circular ref structural comparison'
+ );
+};
+
+exports.deepInstances = function () {
+ assert.ok(
+ !deepEqual([ new Boolean(false) ], [ false ]),
+ 'boolean instances are not real booleans'
+ );
+
+ assert.ok(
+ !deepEqual([ new String('x') ], [ 'x' ]),
+ 'string instances are not real strings'
+ );
+
+ assert.ok(
+ !deepEqual([ new Number(4) ], [ 4 ]),
+ 'number instances are not real numbers'
+ );
+
+ assert.ok(
+ deepEqual([ new RegExp('x') ], [ /x/ ]),
+ 'regexp instances are real regexps'
+ );
+
+ assert.ok(
+ !deepEqual([ new RegExp(/./) ], [ /../ ]),
+ 'these regexps aren\'t the same'
+ );
+
+ assert.ok(
+ !deepEqual(
+ [ function (x) { return x * 2 } ],
+ [ function (x) { return x * 2 } ]
+ ),
+ 'functions with the same .toString() aren\'t necessarily the same'
+ );
+
+ var f = function (x) { return x * 2 };
+ assert.ok(
+ deepEqual([ f ], [ f ]),
+ 'these functions are actually equal'
+ );
+};
+
+exports.deepEqual = function () {
+ assert.ok(
+ !deepEqual([ 1, 2, 3 ], { 0 : 1, 1 : 2, 2 : 3 }),