# # request.rb # vienna # # Created by Adam Beynon. # Copyright 2010 Adam Beynon. # # 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. # require 'browser/event/trigger_events' # Request class # # ## Events # # ### request # # Triggered when request is initially sent. # # ### complete # # Triggered when the request completes. Last callback to be triggered (it is # fired after :success/:failure) # # ### cancel # # Triggered if request cancels # # ### success # # Triggered if the event completes successfully # # ### failure # # Triggered if the request failed (got a response, but it was an error code) # class Request include Event::TriggerEvents OPTIONS = { :url => '', :data => {}, # :headers => { # 'X-Requested-With' => 'XMLHttpRequest', # 'Accept' =>' text/javascript, text/html, application/xml, text/xml, */*' # }, :async => true, :format => nil, :method => 'POST', :link => 'ignore', :is_success => nil, :emulation => true, :url_encoded => true, :encoding => 'utf-8', :eval_scripts => false, :eval_response => false, :timeout => 0, :no_cache => false } # Get the current status of the request attr_reader :status attr_reader :text def initialize(options = {}) `#{self}.__xhr__ = opal.request();` @options = OPTIONS.merge options @headers = @options[:headers] @running = false @status = 0 @text = "" end # FIXME: Do we want lowercase? good practice to use uppercase? %W{get post put delete GET POST PUT DELETE}.each do |method| define_method(method) do |data| send :data => data, :method => method end end # Sends the request with the given data and options. Can also take a block # that acts as the on :complete proc callback handler. # # @example # request = Request.new :url => 'clients.html, :method => 'get' # # @param [Hash] options to set on receiver before sending # @return [Request] returns receiver def send(options = {}, &block) @running = true method = :post url = options[:url] || "" request = self `#{self}.__xhr__.onreadystatechange = function() { #{request}.$state_change(); };` `#{self}.__xhr__.open(#{method.to_s}.toUpperCase(), #{url}, true);` trigger :request, self `#{self}.__xhr__.send(null);` end # Returns +true+ if the +Request+ is running, +false+ otherwise # # @example # req = Request.new # req.running? # => false # req.send # req.running? # => true # # @return [true, false] def running? @running end # Returns +true+ if the request succeeded, +false+ otherwise # # @return [true, false] def success? `return (#{@status} >= 200 && #{@status} < 300) ? #{true} : #{false};` end # Returns +true+ if the request failed, +false+ otherwise # # @return [true, false] def failed? !success? end def state_change # only handle state change when request is done (state 4) `if (#{self}.__xhr__.readyState !== 4 || !#{@running}.r) return;` `#{self}.__xhr__.onreadystatechange = function() { };` @running = false @status = 0 begin @status = `#{self}.__xhr__.status` rescue Exception => e # warning? puts "warning" end puts "our status is now #{@status}" # should be: # @status = `#{@xhr}.status` rescue nil if success? # puts "success #{@status}" @text = `#{self}.__xhr__.responseText || ''` trigger :success, self trigger :complete, self else `console.log(#{@status});` puts "aww :( #{@status}" trigger :failure, self trigger :complete, self end end def cancel return self unless @running @running = false `#{self}.__xhr__.abort();` `#{self}.__xhr__.onreadystatechange = function() {};` `#{self}.__xhr__ = opal.request();` trigger :cancel self end end