architect 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5a8eaf51e9027f92886fc6f7a80a32962314d6b3
4
+ data.tar.gz: c9e08da85647823e5191dcbf95d0efa5e82eef14
5
+ SHA512:
6
+ metadata.gz: 5e01127c50ab864af2b781d6ee9a8d54fb2dbdc639a9857a8ef711ce06e6d86883e51a42e6c1b2f17e665941a819743c991ee3d6a3fcb910d6426b2a62ec1dd9
7
+ data.tar.gz: 03257ade602761acedb3c484973aba2a436daeeefe761f65bfe60a9f041557d969690338947f451ac57c2c3e594b1f01045ec189e8edb9bb839419b1c4937049
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2013 Etienne Lemay
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,59 @@
1
+ **Architect** is a JavaScript library built on top of [Web Workers][].<br>
2
+ He will manage them workers so you don’t have to.
3
+
4
+ ## Methods
5
+ ### proxy
6
+ Returns anything it receives in a background process. Useful when dealing with heavy DOM manipulation (i.e. Infinite scroll). It greatly improves initial page load speed, especially on mobiles.
7
+
8
+ ```js
9
+ images = ['foo.png', 'bar.png', 'twiz.png', 'foozle.png', 'barzle.png', 'twizle.png']
10
+ Architect.proxy(images, function(data) {
11
+ console.log(data)
12
+ // => ['foo.png', 'bar.png', 'twiz.png', 'foozle.png', 'barzle.png', 'twizle.png']
13
+
14
+ data.forEach(function(image) {
15
+ img = document.createElement('img')
16
+ img.src = image
17
+
18
+ document.body.appendChild(img)
19
+ })
20
+ })
21
+ ```
22
+
23
+ ### ajax
24
+ Makes an Ajax request in a background process.
25
+
26
+ ```js
27
+ Architect.ajax('/users/1', function(data) {
28
+ console.log(data);
29
+ // => { id: 1, name: 'Foo', email: 'foo@bar.com' }
30
+ })
31
+ ```
32
+
33
+ ### jsonp
34
+ Makes a JSONP request in a background process. **Do not add `?callback=foo` to your URL**, Architect will handle JSONP callbacks himself.
35
+
36
+ ```js
37
+ Architect.jsonp('https://api.github.com/users/etiennelem', function(data) {
38
+ console.log(data);
39
+ // => { meta: { status: 200, … }, data: { login: 'EtienneLem', company: 'Heliom', … } }
40
+ })
41
+ ```
42
+
43
+ See the [request Architect makes](https://api.github.com/users/etiennelem?callback=architect_jsonp).
44
+
45
+ ## Setup
46
+ ### Rails
47
+ 1. Add `gem 'architect'` to your Gemfile.
48
+ 2. Add `//= require architect` to your JavaScript manifest file (usually found at `app/assets/javascripts/application.js`).
49
+ 3. Restart your server and you'll have access to your very own Architect!
50
+
51
+ ### Other
52
+ You’ll need to serve the [worker files](/static/workers) at `/architect` (i.e. `http://foo.com/architect/proxy_worker.min.js`) and manually add [architect.min.js](/static/architect.min.js) to your HTML page.
53
+
54
+ ## Todo
55
+ - A way to reuse the same worker (and stop it)
56
+ - Support [Shared workers][]
57
+
58
+ [Web Workers]: http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html
59
+ [Shared workers]: http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html#shared-workers
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), *%w[lib])
2
+ require 'tasks/task_helpers'
3
+
4
+ require 'uglifier'
5
+ require 'architect'
6
+ require 'sprockets'
7
+
8
+ desc 'Merge, compiles and minify CoffeeScript files'
9
+ task :compile do
10
+ @environment = Sprockets::Environment.new
11
+ @environment.append_path 'app/assets/javascripts'
12
+ @environment.js_compressor = Uglifier.new(mangle: true)
13
+
14
+ compile('architect.js')
15
+ compile('workers/proxy_worker.js')
16
+ compile('workers/ajax_worker.js')
17
+ compile('workers/jsonp_worker.js')
18
+ end
19
+
20
+ task :default => :compile
21
+
22
+ def compile(file)
23
+ minjs = @environment[file].to_s
24
+ out = "static/#{file.sub('.js', '.min.js')}"
25
+ File.open(out, 'w') { |f| f.write(minjs) }
26
+ success "Compiled #{out}"
27
+ end
@@ -0,0 +1,5 @@
1
+ Architect = {}
2
+ Architect.VERSION = '<%= Architect::VERSION %>'
3
+
4
+ # Global scope
5
+ window.Architect = Architect
@@ -0,0 +1,29 @@
1
+ #= require_self
2
+ #= require_tree ./workers
3
+
4
+ class Architect.Worker
5
+
6
+ constructor: ->
7
+ @callbacks = {}
8
+ @callbacksQueue = {}
9
+
10
+ addEventListener: (type, callback) ->
11
+ @callbacks[type] = callback
12
+
13
+ return unless data = @callbacksQueue[type]
14
+ delete @callbacksQueue[type]
15
+ this.dispatch(type, data)
16
+
17
+ dispatch: (type, data) ->
18
+ if @callbacks[type]
19
+ @callbacks[type]({data: data})
20
+ else
21
+ @callbacksQueue[type] = data
22
+
23
+ handleRequest: (data) ->
24
+ this.dispatch('message', data)
25
+
26
+ terminate: -> # This is meant to be empty
27
+
28
+ # Global scope
29
+ window.Architect.Worker = Architect.Worker
@@ -0,0 +1,14 @@
1
+ class Architect.AjaxWorker extends Architect.Worker
2
+
3
+ postMessage: (url) ->
4
+ xhr = new XMLHttpRequest
5
+ xhr.open('GET', url)
6
+
7
+ xhr.onreadystatechange = (e) =>
8
+ return unless xhr.readyState is 4 && xhr.status is 200
9
+ this.handleRequest(xhr.responseText)
10
+
11
+ xhr.send()
12
+
13
+ # Global scope
14
+ window.Architect.AjaxWorker = Architect.AjaxWorker
@@ -0,0 +1,24 @@
1
+ class Architect.JSONPWorker extends Architect.Worker
2
+
3
+ constructor: ->
4
+ super()
5
+ @jsonpID = 0
6
+
7
+ postMessage: (url) ->
8
+ tmpScript = document.createElement('script')
9
+
10
+ callbackName = 'architect_jsonp' + (++@jsonpID)
11
+ window[callbackName] = (data) =>
12
+ delete window[callbackName]
13
+ document.head.removeChild(tmpScript)
14
+
15
+ this.handleRequest(data)
16
+
17
+ tmpScript.src = this.appendQuery(url, "callback=#{callbackName}")
18
+ document.head.appendChild(tmpScript)
19
+
20
+ appendQuery: (url, query) ->
21
+ (url + '&' + query).replace(/[&?]{1,2}/, '?')
22
+
23
+ # Global scope
24
+ window.Architect.JSONPWorker = Architect.JSONPWorker
@@ -0,0 +1,7 @@
1
+ class Architect.ProxyWorker extends Architect.Worker
2
+
3
+ postMessage: (data) ->
4
+ this.handleRequest(data)
5
+
6
+ # Global scope
7
+ window.Architect.ProxyWorker = Architect.ProxyWorker
@@ -0,0 +1,37 @@
1
+ #= require ./architect/version
2
+ #= require ./architect/worker
3
+
4
+ class _Architect
5
+
6
+ constructor: ->
7
+ @VERSION = Architect.VERSION
8
+
9
+ @SUPPORT_WORKER = !!window.Worker
10
+ @WORKERS =
11
+ proxy: { class: Architect.ProxyWorker, workerPath: '<%= Architect.worker_path("proxy") %>' }
12
+ ajax: { class: Architect.AjaxWorker, workerPath: '<%= Architect.worker_path("ajax") %>' }
13
+ jsonp: { class: Architect.JSONPWorker, workerPath: '<%= Architect.worker_path("jsonp") %>' }
14
+
15
+ proxy: (data, callback) -> this.work(data, 'proxy', callback)
16
+ ajax: (url, callback) -> this.work(url, 'ajax', callback)
17
+ jsonp: (url, callback) -> this.work(url, 'jsonp', callback)
18
+
19
+ work: (data, type, callback) ->
20
+ if typeof type is 'function'
21
+ callback = type
22
+ type = undefined
23
+
24
+ type = 'proxy' if type is undefined
25
+
26
+ worker = this.spawnWorker(type)
27
+ worker.postMessage(data)
28
+ worker.addEventListener 'message', (e) =>
29
+ worker.terminate()
30
+ callback(e.data)
31
+
32
+ spawnWorker: (type) ->
33
+ return new @WORKERS[type].class unless @SUPPORT_WORKER
34
+ worker = new Worker(@WORKERS[type].workerPath)
35
+
36
+ # Singleton
37
+ window.Architect = new _Architect
@@ -0,0 +1,11 @@
1
+ handleRequest = (data) ->
2
+ postMessage(data)
3
+
4
+ addEventListener 'message', (e) ->
5
+ xhr = new XMLHttpRequest
6
+ xhr.open('GET', e.data)
7
+ xhr.onreadystatechange = (e) ->
8
+ return unless xhr.readyState is 4 && xhr.status is 200
9
+ handleRequest(xhr.responseText)
10
+
11
+ xhr.send()
@@ -0,0 +1,9 @@
1
+ self.handleRequest = (data) ->
2
+ postMessage(data)
3
+
4
+ appendQuery = (url, query) ->
5
+ (url + '&' + query).replace(/[&?]{1,2}/, '?')
6
+
7
+ addEventListener 'message', (e) ->
8
+ url = appendQuery(e.data, 'callback=handleRequest')
9
+ importScripts(url)
@@ -0,0 +1,2 @@
1
+ addEventListener 'message', (e) ->
2
+ postMessage(e.data)
@@ -0,0 +1,4 @@
1
+ module Architect
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,12 @@
1
+ module Architect
2
+ def self.worker_path(type)
3
+ worker_filename = "#{type}_worker.js"
4
+ return "architect/#{worker_filename.sub('.js', '.min.js')}" unless defined?(Rails)
5
+
6
+ # Cacheable digest path on main domain because of same-origin policy
7
+ File.join(
8
+ Rails.application.config.assets.prefix,
9
+ Rails.application.assets["workers/#{worker_filename}"].digest_path
10
+ )
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module Architect
2
+ VERSION = '0.0.1'
3
+ end
data/lib/architect.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'architect/version'
2
+ require 'architect/helpers'
3
+ require 'architect/engine' if defined?(Rails) && Rails::VERSION::MAJOR >= 3
@@ -0,0 +1,18 @@
1
+ def colorize(text, color_code)
2
+ "\e[#{color_code}m#{text}\e[0m"
3
+ end
4
+
5
+ { # See: http://kpumuk.info/ruby-on-rails/colorizing-console-ruby-script-output/
6
+ 31 => 'red',
7
+ 32 => 'green',
8
+ 33 => 'yellow',
9
+ 34 => 'blue',
10
+ 35 => 'magenta',
11
+ 36 => 'cyan',
12
+ }.each do |code, color|
13
+ define_method(color) { |text| colorize(text, code) }
14
+ end
15
+
16
+ def error(text); puts red('ERROR: ') + text; end
17
+ def success(text); puts green('SUCCESS: ') + text; end
18
+ def warn(text); puts yellow('WARNING: ') + text; end
@@ -0,0 +1 @@
1
+ !function(){var t;t={},t.VERSION="0.0.1",window.Architect=t}.call(this),function(){Architect.Worker=function(){function t(){this.callbacks={},this.callbacksQueue={}}return t.prototype.addEventListener=function(t,r){var e;return this.callbacks[t]=r,(e=this.callbacksQueue[t])?(delete this.callbacksQueue[t],this.dispatch(t,e)):void 0},t.prototype.dispatch=function(t,r){return this.callbacks[t]?this.callbacks[t]({data:r}):this.callbacksQueue[t]=r},t.prototype.handleRequest=function(t){return this.dispatch("message",t)},t.prototype.terminate=function(){},t}(),window.Architect.Worker=Architect.Worker}.call(this),function(){var t,r={}.hasOwnProperty,e=function(t,e){function o(){this.constructor=t}for(var n in e)r.call(e,n)&&(t[n]=e[n]);return o.prototype=e.prototype,t.prototype=new o,t.__super__=e.prototype,t};Architect.AjaxWorker=function(r){function o(){return t=o.__super__.constructor.apply(this,arguments)}return e(o,r),o.prototype.postMessage=function(t){var r,e=this;return r=new XMLHttpRequest,r.open("GET",t),r.onreadystatechange=function(){return 4===r.readyState&&200===r.status?e.handleRequest(r.responseText):void 0},r.send()},o}(Architect.Worker),window.Architect.AjaxWorker=Architect.AjaxWorker}.call(this),function(){var t={}.hasOwnProperty,r=function(r,e){function o(){this.constructor=r}for(var n in e)t.call(e,n)&&(r[n]=e[n]);return o.prototype=e.prototype,r.prototype=new o,r.__super__=e.prototype,r};Architect.JSONPWorker=function(t){function e(){e.__super__.constructor.call(this),this.jsonpID=0}return r(e,t),e.prototype.postMessage=function(t){var r,e,o=this;return e=document.createElement("script"),r="architect_jsonp"+ ++this.jsonpID,window[r]=function(t){return delete window[r],document.head.removeChild(e),o.handleRequest(t)},e.src=this.appendQuery(t,"callback="+r),document.head.appendChild(e)},e.prototype.appendQuery=function(t,r){return(t+"&"+r).replace(/[&?]{1,2}/,"?")},e}(Architect.Worker),window.Architect.JSONPWorker=Architect.JSONPWorker}.call(this),function(){var t,r={}.hasOwnProperty,e=function(t,e){function o(){this.constructor=t}for(var n in e)r.call(e,n)&&(t[n]=e[n]);return o.prototype=e.prototype,t.prototype=new o,t.__super__=e.prototype,t};Architect.ProxyWorker=function(r){function o(){return t=o.__super__.constructor.apply(this,arguments)}return e(o,r),o.prototype.postMessage=function(t){return this.handleRequest(t)},o}(Architect.Worker),window.Architect.ProxyWorker=Architect.ProxyWorker}.call(this),function(){var t;t=function(){function t(){this.VERSION=Architect.VERSION,this.SUPPORT_WORKER=!!window.Worker,this.WORKERS={proxy:{"class":Architect.ProxyWorker,workerPath:"architect/proxy_worker.min.js"},ajax:{"class":Architect.AjaxWorker,workerPath:"architect/ajax_worker.min.js"},jsonp:{"class":Architect.JSONPWorker,workerPath:"architect/jsonp_worker.min.js"}}}return t.prototype.proxy=function(t,r){return this.work(t,"proxy",r)},t.prototype.ajax=function(t,r){return this.work(t,"ajax",r)},t.prototype.jsonp=function(t,r){return this.work(t,"jsonp",r)},t.prototype.work=function(t,r,e){var o;return"function"==typeof r&&(e=r,r=void 0),void 0===r&&(r="proxy"),o=this.spawnWorker(r),o.postMessage(t),o.addEventListener("message",function(t){return o.terminate(),e(t.data)})},t.prototype.spawnWorker=function(t){var r;return this.SUPPORT_WORKER?r=new Worker(this.WORKERS[t].workerPath):new this.WORKERS[t]["class"]},t}(),window.Architect=new t}.call(this);
@@ -0,0 +1 @@
1
+ !function(){var e;e=function(e){return postMessage(e)},addEventListener("message",function(t){var n;return n=new XMLHttpRequest,n.open("GET",t.data),n.onreadystatechange=function(){return 4===n.readyState&&200===n.status?e(n.responseText):void 0},n.send()})}.call(this);
@@ -0,0 +1 @@
1
+ !function(){var e;self.handleRequest=function(e){return postMessage(e)},e=function(e,t){return(e+"&"+t).replace(/[&?]{1,2}/,"?")},addEventListener("message",function(t){var n;return n=e(t.data,"callback=handleRequest"),importScripts(n)})}.call(this);
@@ -0,0 +1 @@
1
+ !function(){addEventListener("message",function(e){return postMessage(e.data)})}.call(this);
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: architect
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Etienne Lemay
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-07-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: coffee-rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: uglifier
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sprockets
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Architect is a JavaScript library built on top of Web Workers that will
70
+ handle and polyfill HTML Web Workers.
71
+ email:
72
+ - etienne@heliom.ca
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - app/assets/javascripts/architect/version.coffee.erb
78
+ - app/assets/javascripts/architect/worker.coffee
79
+ - app/assets/javascripts/architect/workers/ajax_worker.coffee
80
+ - app/assets/javascripts/architect/workers/jsonp_worker.coffee
81
+ - app/assets/javascripts/architect/workers/proxy_worker.coffee
82
+ - app/assets/javascripts/architect.coffee.erb
83
+ - app/assets/javascripts/workers/ajax_worker.coffee
84
+ - app/assets/javascripts/workers/jsonp_worker.coffee
85
+ - app/assets/javascripts/workers/proxy_worker.coffee
86
+ - lib/architect/engine.rb
87
+ - lib/architect/helpers.rb
88
+ - lib/architect/version.rb
89
+ - lib/architect.rb
90
+ - lib/tasks/task_helpers.rb
91
+ - static/architect.min.js
92
+ - static/workers/ajax_worker.min.js
93
+ - static/workers/jsonp_worker.min.js
94
+ - static/workers/proxy_worker.min.js
95
+ - Rakefile
96
+ - MIT-LICENSE
97
+ - README.md
98
+ homepage: https://github.com/EtienneLem/architect
99
+ licenses:
100
+ - MIT
101
+ metadata: {}
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - '>='
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ requirements: []
117
+ rubyforge_project:
118
+ rubygems_version: 2.0.0
119
+ signing_key:
120
+ specification_version: 4
121
+ summary: Your web workers’ supervisor
122
+ test_files: []