ajax.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. MIME_TYPES =
  2. json: 'application/json'
  3. html: 'text/html'
  4. @ajax = (options) ->
  5. applyDefaults(options)
  6. serializeData(options)
  7. xhr = new XMLHttpRequest()
  8. xhr.open(options.type, options.url, options.async)
  9. applyCallbacks(xhr, options)
  10. applyHeaders(xhr, options)
  11. xhr.send(options.data)
  12. if options.async
  13. abort: abort.bind(undefined, xhr)
  14. else
  15. parseResponse(xhr, options)
  16. ajax.defaults =
  17. async: true
  18. dataType: 'json'
  19. timeout: 30
  20. type: 'GET'
  21. # contentType
  22. # context
  23. # data
  24. # error
  25. # headers
  26. # progress
  27. # success
  28. # url
  29. applyDefaults = (options) ->
  30. for key of ajax.defaults
  31. options[key] ?= ajax.defaults[key]
  32. return
  33. serializeData = (options) ->
  34. return unless options.data
  35. if options.type is 'GET'
  36. options.url += '?' + serializeParams(options.data)
  37. options.data = null
  38. else
  39. options.data = serializeParams(options.data)
  40. return
  41. serializeParams = (params) ->
  42. ("#{encodeURIComponent key}=#{encodeURIComponent value}" for key, value of params).join '&'
  43. applyCallbacks = (xhr, options) ->
  44. return unless options.async
  45. xhr.timer = setTimeout onTimeout.bind(undefined, xhr, options), options.timeout * 1000
  46. xhr.onprogress = options.progress if options.progress
  47. xhr.onreadystatechange = ->
  48. if xhr.readyState is 4
  49. clearTimeout(xhr.timer)
  50. onComplete(xhr, options)
  51. return
  52. return
  53. applyHeaders = (xhr, options) ->
  54. options.headers or= {}
  55. if options.contentType
  56. options.headers['Content-Type'] = options.contentType
  57. if not options.headers['Content-Type'] and options.data and options.type isnt 'GET'
  58. options.headers['Content-Type'] = 'application/x-www-form-urlencoded'
  59. if options.dataType
  60. options.headers['Accept'] = MIME_TYPES[options.dataType] or options.dataType
  61. for key, value of options.headers
  62. xhr.setRequestHeader(key, value)
  63. return
  64. onComplete = (xhr, options) ->
  65. if 200 <= xhr.status < 300
  66. if (response = parseResponse(xhr, options))?
  67. onSuccess response, xhr, options
  68. else
  69. onError 'invalid', xhr, options
  70. else
  71. onError 'error', xhr, options
  72. return
  73. onSuccess = (response, xhr, options) ->
  74. options.success?.call options.context, response, xhr, options
  75. return
  76. onError = (type, xhr, options) ->
  77. options.error?.call options.context, type, xhr, options
  78. return
  79. onTimeout = (xhr, options) ->
  80. xhr.abort()
  81. onError 'timeout', xhr, options
  82. return
  83. abort = (xhr) ->
  84. clearTimeout(xhr.timer)
  85. xhr.onreadystatechange = null
  86. xhr.abort()
  87. return
  88. parseResponse = (xhr, options) ->
  89. if options.dataType is 'json'
  90. parseJSON(xhr.responseText)
  91. else
  92. xhr.responseText
  93. parseJSON = (json) ->
  94. try JSON.parse(json) catch