pwnstyles_rails 0.1.8 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.8
1
+ 0.1.9
@@ -18,7 +18,7 @@ class PwnFxClass
18
18
 
19
19
  # Wires JS to elements with data-pwnfx attributes.
20
20
  #
21
- # @param [Element] root the element whose content is wired; use document at
21
+ # @param {Element} root the element whose content is wired; use document at
22
22
  # load time
23
23
  wire: (root) ->
24
24
  for effect in @effects
@@ -38,19 +38,19 @@ class PwnFxClass
38
38
 
39
39
  # Registers a PwnFx effect.
40
40
  #
41
- # @param [String] attrName string following data-pwnfx- in the effect's
41
+ # @param {String} attrName string following data-pwnfx- in the effect's
42
42
  # attribute names
43
43
  # @param klass the class that wraps the effect's implementation
44
44
  registerEffect: (attrPrefix, klass) ->
45
45
  if @effectsByName[attrPrefix]
46
- throw new Error("Effect name {attrPrefix} already registered")
46
+ throw new Error("PwnFx effect name {attrPrefix} already registered")
47
47
  @effects.push [attrPrefix, klass]
48
48
 
49
49
  # Finds a scoping container.
50
50
  #
51
- # @param [String] scopeId the scope ID to look for
52
- # @param [Element] element the element where the lookup starts
53
- # @return [Element] the closest parent of the given element whose
51
+ # @param {String} scopeId the scope ID to look for
52
+ # @param {HTMLElement} element the element where the lookup starts
53
+ # @return {HTMLElement} the closest parent of the given element whose
54
54
  # data-pwnfx-scope matches the scopeId argument; window.document is
55
55
  # returned if no such element exists or if scope is null
56
56
  resolveScope: (scopeId, element) ->
@@ -61,9 +61,9 @@ class PwnFxClass
61
61
 
62
62
  # Performs a scoped querySelectAll.
63
63
  #
64
- # @param [Element] scope the DOM element serving as the search scope
65
- # @param [String] selector the CSS selector to query
66
- # @return [NodeList, Array] the elements in the scope that match the CSS
64
+ # @param {HTMLElement} scope the DOM element serving as the search scope
65
+ # @param {String} selector the CSS selector to query
66
+ # @return {NodeList, Array} the elements in the scope that match the CSS
67
67
  # selector; the scope container can belong to the returned array
68
68
  queryScope: (scope, selector) ->
69
69
  scopeMatches = false
@@ -85,6 +85,64 @@ class PwnFxClass
85
85
  else
86
86
  scope.querySelectorAll selector
87
87
 
88
+ # Executes the JavaScript inside the <script> tags in a DOM subtree.
89
+ #
90
+ # @param {HTMLElement} element the DOM element rooting the subtree that will
91
+ # be searched for <script> tags
92
+ runScripts: (element) ->
93
+ # HACK: <script>s are removed and re-inserted so the browser runs them
94
+ for scriptElement in element.querySelectorAll('script')
95
+ parent = scriptElement.parentElement
96
+ nextSibling = scriptElement.nextSibling
97
+ parent.removeChild scriptElement
98
+ parent.insertBefore scriptElement.cloneNode(true), nextSibling
99
+ null
100
+
101
+ # Replaces an element's contents with some HTML.
102
+ #
103
+ # The JavaScript inside the HTML's <script> tags will be executed.
104
+ #
105
+ # @param {HTMLElement} element the element whose contents will be replaced
106
+ # @param {String}
107
+ replaceHtml: (element, html) ->
108
+ element.innerHTML = html
109
+ @runScripts element
110
+ @wire element
111
+
112
+ # The closest form element wrapping a node.
113
+ #
114
+ # @param {HTMLElement} element the element whose parent chain will be searched
115
+ # @return {HTMLFormElement} the element's closest parent form, or null if the
116
+ # element is not wrapped in a <form>
117
+ parentForm: (element) ->
118
+ while element
119
+ return element if element.nodeName == 'FORM'
120
+ element = element.parentNode
121
+ null
122
+
123
+ # Do AJAX.
124
+ #
125
+ # @param {String} url the request URL (e.g., "http://localhost/path/to.html")
126
+ # @param {String} method the request method (e.g., "POST")
127
+ # @param [HTMLFormElement] form the DOM form whose data will be submitted
128
+ # @param [function(data)] onData callback that receives the XHR data, if the
129
+ # XHR completes successfully
130
+ xhr: (url, method, form, onData) ->
131
+ xhr = new XMLHttpRequest
132
+ xhr.onload = @_xhr_onload
133
+ xhr.pwnfxOnData = onData
134
+ xhr.open method, url
135
+ xhr.setRequestHeader 'X-Requested-With', 'XMLHttpRequest'
136
+ if form
137
+ xhr.send new FormData(form)
138
+ else
139
+ xhr.send null
140
+
141
+ # Called when an XHR request issued by PwnFx.xhr works out.
142
+ _xhr_onload: ->
143
+ if @status < 200 || @status >= 300
144
+ throw new Error("XHR result ignored due to HTTP status: #{@statusText}")
145
+ @pwnfxOnData @responseText
88
146
 
89
147
  # Singleton instance.
90
148
  PwnFx = new PwnFxClass
@@ -96,11 +154,24 @@ PwnFx = new PwnFxClass
96
154
  # data-pwnfx-move: an identifier connecting the move's target element
97
155
  # data-pwnfx-move-target: set to the same value as data-pwnfx-move on the
98
156
  # element that will receive the moved element as its last child
157
+ # data-pwnfx-move-method: 'append' adds the moved as the element as the
158
+ # target's last child, 'replace' clears the target element, then adds the
159
+ # moved element as the target's only child
99
160
  class PwnFxMove
100
161
  constructor: (element, identifier, scopeId) ->
101
162
  scope = PwnFx.resolveScope scopeId, element
163
+ method = element.getAttribute('data-pwnfx-move-method') || 'append'
102
164
  target = document.querySelector "[data-pwnfx-move-target=\"#{identifier}\"]"
103
- target.appendChild element
165
+
166
+ switch method
167
+ when 'append'
168
+ target.appendChild element
169
+ when 'replace'
170
+ target.innerHTML = ''
171
+ target.appendChild element
172
+ else
173
+ throw new Error("pwnfx-move-method #{method} not implemented")
174
+
104
175
 
105
176
  PwnFx.registerEffect 'move', PwnFxMove
106
177
 
@@ -146,68 +217,85 @@ class PwnFxRender
146
217
  PwnFx.registerEffect 'render', PwnFxRender
147
218
 
148
219
 
220
+ # Loads some content after the main page load via an AJAX request.
221
+ #
222
+ # The text / HTML returned by the request is placed in another element. Scripts
223
+ # in <script> tags are executed.
224
+ #
225
+ # Element attributes:
226
+ # data-pwnfx-delayed: identifier connecting the AJAX data receiver
227
+ # data-pwnfx-delayed-url: URL to perform an AJAX request to
228
+ # data-pwnfx-delayed-method: the HTTP method of AJAX request (default: POST)
229
+ # data-pwnfx-delayed-ms: the delay between the page load and the issuing of
230
+ # the AJAX request (default: 1000ms)
231
+ # data-pwnfx-delayed-target: set to the value of data-pwnfx-delayed on the
232
+ # element populated with the AJAX response
233
+ class PwnFxDelayed
234
+ constructor: (element, identifier, scopeId) ->
235
+ targetSelector = "[data-pwnfx-delayed-target=\"#{identifier}\"]"
236
+ xhrUrl = element.getAttribute('data-pwnfx-delayed-url')
237
+ xhrMethod = element.getAttribute('data-pwnfx-delayed-method') || 'POST'
238
+ xhrForm = PwnFx.parentForm element
239
+ delay = parseInt(
240
+ element.getAttribute('data-pwnfx-delayed-ms') || '1000');
241
+
242
+ ajaxLoad = ->
243
+ PwnFx.xhr xhrUrl, xhrMethod, xhrForm, (data) ->
244
+ scope = PwnFx.resolveScope scopeId, element
245
+ for targetElement in PwnFx.queryScope(scope, targetSelector)
246
+ PwnFx.replaceHtml targetElement, data
247
+
248
+ window.setTimeout ajaxLoad, delay
249
+
250
+ PwnFx.registerEffect 'delayed', PwnFxDelayed
251
+
252
+
149
253
  # Fires off an AJAX request (almost) every time when an element changes.
150
254
  #
151
- # The text / HTML returned by the request is placed in another element.
255
+ # The text / HTML returned by the request is placed in another element. Scripts
256
+ # in <script> tags are executed.
152
257
  #
153
258
  # Element attributes:
154
- # data-pwnfx-refresh: URL to perform an AJAX request to
259
+ # data-pwnfx-refresh: identifier connecting the AJAX data receiver
260
+ # data-pwnfx-refresh-url: URL to perform an AJAX request to
155
261
  # data-pwnfx-refresh-method: the HTTP method of AJAX request (default: POST)
156
- # data-pwnfx-refresh-ms: interval between a change on the source element and
262
+ # data-pwnfx-refresh-ms: delay between a change on the source element and
157
263
  # AJAX refresh requests (default: 200ms)
158
- # data-pwnfx-target: the element populated with the AJAX response
264
+ # data-pwnfx-refresh-target: set to the value of data-pwnfx-refresh on the
265
+ # element populated with the AJAX response
159
266
  class PwnFxRefresh
160
- constructor: (element, xhrUrl, scopeId) ->
161
- targetSelector = '#' + element.getAttribute('data-pwnfx-refresh-target')
162
- refreshInterval = parseInt(
163
- element.getAttribute('data-pwnfx-refresh-ms') || '200');
267
+ constructor: (element, identifier, scopeId) ->
268
+ targetSelector = "[data-pwnfx-refresh-target=\"#{identifier}\"]"
269
+ xhrUrl = element.getAttribute('data-pwnfx-refresh-url')
164
270
  xhrMethod = element.getAttribute('data-pwnfx-refresh-method') || 'POST'
165
- xhrForm = @parentForm element
271
+ xhrForm = PwnFx.parentForm element
272
+ refreshDelay = parseInt(
273
+ element.getAttribute('data-pwnfx-refresh-ms') || '200');
166
274
 
167
- onXhrSuccess = ->
168
- data = @responseText
275
+ onXhrData = (data) ->
169
276
  scope = PwnFx.resolveScope scopeId, element
170
277
  for targetElement in PwnFx.queryScope(scope, targetSelector)
171
- targetElement.innerHTML = data
172
- # HACK: <script>s are removed and re-inserted so the browser runs them
173
- for scriptElement in targetElement.querySelectorAll('script')
174
- parent = scriptElement.parentElement
175
- nextSibling = scriptElement.nextSibling
176
- parent.removeChild scriptElement
177
- parent.insertBefore scriptElement.cloneNode(true), nextSibling
178
- PwnFx.wire targetElement
278
+ PwnFx.replaceHtml targetElement, data
179
279
 
180
- refreshPending = false
280
+ changeTimeout = null
181
281
  refreshOldValue = null
182
282
  ajaxRefresh = ->
183
- refreshPending = false
184
- xhr = new XMLHttpRequest
185
- xhr.onload = onXhrSuccess
186
- xhr.open xhrMethod, xhrUrl
187
- xhr.send new FormData(xhrForm)
283
+ changeTimeout = null
284
+ PwnFx.xhr xhrUrl, xhrMethod, xhrForm, onXhrData
188
285
 
189
286
  onChange = ->
190
287
  value = element.value
191
288
  return true if value == refreshOldValue
192
289
  refreshOldValue = value
193
290
 
194
- return true if refreshPending
195
- refreshPending = true
196
- window.setTimeout ajaxRefresh, refreshInterval
291
+ window.clearTimeout changeTimeout if changeTimeout != null
292
+ changeTimeout = window.setTimeout ajaxRefresh, refreshDelay
197
293
  true
198
294
 
199
295
  element.addEventListener 'change', onChange, false
200
296
  element.addEventListener 'keydown', onChange, false
201
297
  element.addEventListener 'keyup', onChange, false
202
298
 
203
-
204
- # The closest form element wrapping a node.
205
- parentForm: (element) ->
206
- while element
207
- return element if element.nodeName == 'FORM'
208
- element = element.parentNode
209
- null
210
-
211
299
  PwnFx.registerEffect 'refresh', PwnFxRefresh
212
300
 
213
301
 
@@ -300,7 +388,7 @@ class PwnFxHide
300
388
  element.addEventListener 'change', onChange, false
301
389
  onChange()
302
390
  else
303
- throw new Error("Unimplemented trigger #{trigger}")
391
+ throw new Error("Unimplemented pwnfx-hide trigger #{trigger}")
304
392
 
305
393
  PwnFx.registerEffect 'hide', PwnFxHide
306
394
 
@@ -1,6 +1,6 @@
1
- <% if flash[:error] %>
1
+ <% if flash[:alert] %>
2
2
  <p class="status-bar error" data-pwnfx-hide-positive="status-bar">
3
- <%= flash[:error] %>
3
+ <%= flash[:alert] %>
4
4
 
5
5
  <span class="actions">
6
6
  <%= link_to 'Hide', '#', 'data-pwnfx-hide' => 'status-bar' %>
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "pwnstyles_rails"
8
- s.version = "0.1.8"
8
+ s.version = "0.1.9"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Victor Costan"]
12
- s.date = "2012-02-06"
12
+ s.date = "2012-02-08"
13
13
  s.description = "Included CSS was designed for reuse across pwnb.us apps."
14
14
  s.email = "victor@costan.us"
15
15
  s.extra_rdoc_files = [
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pwnstyles_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.1.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-06 00:00:00.000000000Z
12
+ date: 2012-02-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
16
- requirement: &19937980 !ruby/object:Gem::Requirement
16
+ requirement: &11333680 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 3.2.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *19937980
24
+ version_requirements: *11333680
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: sass-rails
27
- requirement: &19937220 !ruby/object:Gem::Requirement
27
+ requirement: &11332740 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 3.2.4
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *19937220
35
+ version_requirements: *11332740
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: shoulda
38
- requirement: &19936520 !ruby/object:Gem::Requirement
38
+ requirement: &11331580 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *19936520
46
+ version_requirements: *11331580
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: bundler
49
- requirement: &19935800 !ruby/object:Gem::Requirement
49
+ requirement: &11330960 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 1.0.0
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *19935800
57
+ version_requirements: *11330960
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: jeweler
60
- requirement: &19934980 !ruby/object:Gem::Requirement
60
+ requirement: &11330260 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 1.8.0
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *19934980
68
+ version_requirements: *11330260
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rcov
71
- requirement: &19934260 !ruby/object:Gem::Requirement
71
+ requirement: &11329560 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *19934260
79
+ version_requirements: *11329560
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: simplecov
82
- requirement: &19933540 !ruby/object:Gem::Requirement
82
+ requirement: &11328840 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,7 +87,7 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *19933540
90
+ version_requirements: *11328840
91
91
  description: Included CSS was designed for reuse across pwnb.us apps.
92
92
  email: victor@costan.us
93
93
  executables: []
@@ -152,7 +152,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
152
152
  version: '0'
153
153
  segments:
154
154
  - 0
155
- hash: -1644724603097624457
155
+ hash: -1561629047696915926
156
156
  required_rubygems_version: !ruby/object:Gem::Requirement
157
157
  none: false
158
158
  requirements: