switch_access-rails 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,10 @@
1
+ Copyright (c) 2012, Leif Ringstad
2
+ All rights reserved.
3
+
4
+ Please not that Switch-Access from version 1.1 is dual licensed under GPL or a commercial license.
5
+
6
+ You can either
7
+ a) License it under GPL (See LICENSE.GPL for details)
8
+ b) Obtain a commercial license (Contact leifcr@gmail.com for details)
9
+
10
+ Switch Access library version 1.0 was licensed under the BSD 2-clause license.
data/README.md ADDED
@@ -0,0 +1,121 @@
1
+ # Rails 3.2 Integration for switch_access
2
+
3
+ The `switch_access-rails` gem integrates the [Switch Access](http://leifcr.github.com/switch_access) library with the Rails 3.2 asset pipeline.
4
+
5
+
6
+ ## Usage
7
+
8
+ ### Installation
9
+
10
+ **1. Add `switch_access-rails` to your Gemfile**
11
+
12
+ gem 'switch_access-rails'
13
+
14
+ **2. Run `bundle install`.**
15
+
16
+ **3. Using**
17
+
18
+ Add to your application.js:
19
+ _jQuery_ is only needed if you haven't included them already
20
+
21
+ ```js
22
+ //= require jquery
23
+ //= require switch_access
24
+ ```
25
+ ### Helper methods
26
+ Four helper methods that should be used when creating switch-elements, and initializing the library
27
+
28
+ ```ruby
29
+ # Reset counters to 0, this is done before rendering
30
+ sw_element_reset_counters()
31
+
32
+ # get the next "group" classname with an id appended (increments automatically)
33
+ sw_element_begin_group()
34
+
35
+ # get the next "element" classname with an id appended (increments automatically)
36
+ sw_element_next_class()
37
+
38
+ # ends the group that was started.
39
+ sw_element_end_group()
40
+
41
+ # Get javascript initializer with given options.
42
+ # (Recommended to have as late as possible on the page)
43
+ sw_element_js_initializer(options = {})
44
+
45
+ # finalizes the switch access. Note: Must be done on the end of each page for now...
46
+ sw_element_fini()
47
+
48
+ ```
49
+
50
+ ## Example
51
+
52
+ Example in a ERB view
53
+
54
+ ```erb
55
+ <%=
56
+ content_tag :div, :class => sw_element_begin_group() do
57
+ content_tag(:div, "Switch element 1 in group 1", :class => sw_element_next_class()) +
58
+ content_tag(:div, "Switch element 2 in group 1", :class => sw_element_next_class()) +
59
+ content_tag(:div, "Switch element 3 in group 1", :class => sw_element_next_class())
60
+ end
61
+
62
+ %>
63
+ <% sw_element_end_group() %>
64
+
65
+ <%=
66
+ content_tag :div, :class => sw_element_begin_group() do
67
+ content_tag(:div, "Switch element 1 in group 2", :class => sw_element_next_class()) +
68
+ content_tag(:div, "Switch element 2 in group 2", :class => sw_element_next_class())
69
+ end
70
+ %>
71
+ <% sw_element_end_group() %>
72
+
73
+ <%= content_tag :div, "Switch element 3 outside groups", :class => sw_element_next_class() %>
74
+ <%= sw_element_js_initializer({
75
+ :debug => false, # can be removed if value is false
76
+ :switches => {
77
+ :number_of_switches => 2,
78
+ :groups => true,
79
+ :delay_for_allowed_keypress => 0
80
+ }
81
+ }) %>
82
+ <%= sw_element_fini() %>
83
+ ```
84
+
85
+ See [leifcr.github.com/switch_access](http://leifcr.github.com/switch_access) for examples, unit tests of the library and documentation.
86
+
87
+ ### Example CSS
88
+
89
+ You can include sample CSS stylesheets to see how highlighters/classes work
90
+ ```css
91
+ /* Complete example
92
+ *= require switch_access/example
93
+ *
94
+ * Only highlighters
95
+ *= require switch_access/example_highlighter
96
+ *
97
+ * Only switch element
98
+ *= require switch_access/example_switch_element
99
+ */
100
+ ```
101
+
102
+ ### Debugging
103
+
104
+ If you need to debug, log4javascript is included in the gem To avoid issues with log4javascript in other gems, it's namespaced under switch_access
105
+
106
+ First, add log4javascript to your application.js or other .js
107
+ ```js
108
+ //= require switch_access/log4javascript
109
+ ```
110
+
111
+ Second, set debug to true, and a log4javascript Appender/console should show up.
112
+
113
+ If you have a div with id set to "logger" the appender/console will be created inside that div.
114
+
115
+ ## License
116
+ This GEM is dual licensed under the GPL license and a commercial license. See LICENSE and LICENSE.GPL for details. For commercial usage, please contact leifcr@gmail.com
117
+
118
+ ## Contact
119
+ Feel free to contact me at @leifcr (twitter).
120
+
121
+ Copyright (c) 2012 Leif Ringstad
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rubygems/package_task'
4
+
5
+ $:.push File.expand_path('../lib', __FILE__)
6
+ require 'switch_access/rails/version'
7
+
8
+ gemspec = eval(File.read('switch_access-rails.gemspec'))
9
+ Gem::PackageTask.new(gemspec) do |pkg|
10
+ pkg.gem_spec = gemspec
11
+ end
12
+
13
+ desc 'build the gem and release it to rubygems.org'
14
+ task :release => :gem do
15
+ sh "gem push pkg/switch_access-rails-#{SwitchAccess::Rails::VERSION}.gem"
16
+ end
@@ -0,0 +1 @@
1
+ require 'switch_access/rails'
@@ -0,0 +1,3 @@
1
+ require 'switch_access/rails/version'
2
+ require 'switch_access/rails/engine'
3
+ require 'switch_access/rails/railtie'
@@ -0,0 +1,6 @@
1
+ module SwitchAccess
2
+ module Rails
3
+ class Engine < ::Rails::Engine
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,14 @@
1
+ require 'switch_access/rails/view_helpers'
2
+
3
+ module SwitchAccess
4
+ module Rails
5
+ class Railtie < ::Rails::Railtie
6
+ ActiveSupport.on_load(:action_view) do
7
+ include SwitchAccess::Rails::ViewHelpers
8
+ end
9
+ # initializer "switch_access.rails.view_helpers" do |app|
10
+ # ActionView::Base.send :include, ViewHelpers
11
+ # end
12
+ end # class Railtie < Rails::Railtie
13
+ end # module Rails
14
+ end # module SwitchAccess
@@ -0,0 +1,5 @@
1
+ module SwitchAccess
2
+ module Rails
3
+ VERSION = '1.1.4'
4
+ end
5
+ end
@@ -0,0 +1,109 @@
1
+ module SwitchAccess
2
+ module Rails
3
+ module ViewHelpers
4
+
5
+ @@_sw_element_sci_class = nil
6
+
7
+ def sw_element_init(options = {})
8
+ sw_element_fini()
9
+ sw_element_sci(options)
10
+ end
11
+
12
+ def sw_element_sci(options = {})
13
+ @@_sw_element_sci_class = SwitchElements.new(options) if @@_sw_element_sci_class == nil
14
+ @@_sw_element_sci_class
15
+ end
16
+
17
+ #
18
+ # Reset counters
19
+ #
20
+ def sw_element_reset_counters
21
+ sw_element_sci().reset_counters()
22
+ end
23
+
24
+ #
25
+ # Begin a switch element group
26
+ #
27
+ def sw_element_begin_group
28
+ sw_element_sci().begin_group()
29
+ end
30
+
31
+ def sw_element_fini
32
+ @@_sw_element_sci_class = nil
33
+ end
34
+
35
+ #
36
+ # End a switch element group
37
+ #
38
+ def sw_element_end_group
39
+ ret = sw_element_sci().end_group()
40
+ if (ret < 0)
41
+ sw_element_fini()
42
+ end
43
+ ret
44
+ end
45
+
46
+ #
47
+ # Get the next switch element class
48
+ #
49
+ def sw_element_next_class
50
+ sw_element_sci().next_element_class()
51
+ end
52
+
53
+ #
54
+ # Get javascript initializer for switch access
55
+ #
56
+ def sw_element_js_initializer(options = {})
57
+ str =
58
+ <<-js
59
+ $(document).ready(function() {
60
+ if (typeof window._railsaccess == 'undefined') {
61
+ window._rails_sw_access = new SwitchAccess(#{options.to_json});
62
+ }
63
+ });
64
+ js
65
+ javascript_tag str.html_safe
66
+ end
67
+
68
+ class SwitchElements
69
+ def initialize(options = {})
70
+ @options = options
71
+ @options[:element_class_name] = "switch-element-" if !options.has_key?(:element_class_name)
72
+ reset_counters()
73
+ end
74
+
75
+ def reset_counters()
76
+ @parent_next_element_id = 0
77
+ @next_element_id = 0
78
+ @level = 0
79
+ end
80
+
81
+ def begin_group
82
+ @parent_next_element_id = @next_element_id + 1
83
+ @next_element_id = 1
84
+ @level += 1
85
+ "#{@options[:element_class_name]}#{@parent_next_element_id}"
86
+ end
87
+
88
+ def end_group
89
+ @level -= 1
90
+ @next_element_id = @parent_next_element_id
91
+ end
92
+
93
+ #
94
+ # Get the next switch element class
95
+ #
96
+ def next_element_class
97
+ "#{@options[:element_class_name]}#{increase_next_id()}"
98
+ end
99
+ #
100
+ # Increase the switch element id and return it
101
+ #
102
+ def increase_next_id
103
+ @next_element_id += 1
104
+ end
105
+ end # class SwitchElements
106
+
107
+ end # module ViewHelpers
108
+ end # module Rails
109
+ end # module SwitchAccess
@@ -0,0 +1,3 @@
1
+ //= require switch_access/execute_method
2
+ //= require switch_access/jquery.csswatch
3
+ //= require switch_access/switch_access
@@ -0,0 +1,107 @@
1
+ ###
2
+ # Execute Method
3
+ # (c) 2012 Leif Ringstad
4
+ # Licensed under the freeBSD license (see LICENSE.txt for details)
5
+ #
6
+ # Source: http://github.com/leifcr/execute_method
7
+ # v 1.0.0
8
+ ###
9
+
10
+ ExecuteMethod =
11
+ getFunctionsAndProperties: (str) ->
12
+ # console.log"getFunctionsAndProperties"
13
+ arr = str.split(".")
14
+ i = 0
15
+ ret = []
16
+ while i < arr.length
17
+ ret.push ExecuteMethod.getFunctionAndParameters(arr[i])
18
+ i++
19
+ # console.log ret
20
+ ret
21
+
22
+ getFunctionAndParameters: (str) ->
23
+ # console.log "getFunctionAndParameters"
24
+ if ExecuteMethod.isFunction(str)
25
+ params = str.substring(str.indexOf("(")+1, str.indexOf(")"))
26
+ if params.length > 0
27
+ params = ExecuteMethod.splitAndTypeCastParameters(params)
28
+ else
29
+ params = []
30
+ func = str.substring(0, str.indexOf ("\(") )
31
+ isfunc = true
32
+ else
33
+ func = str
34
+ params = null
35
+ isfunc = false
36
+
37
+ {func: func, params: params, isfunc: isfunc}
38
+
39
+ splitAndTypeCastParameters: (params) ->
40
+ # console.log"splitAndTypeCastParameters"
41
+ arr = params.split(",")
42
+ ret = []
43
+ i = 0
44
+ ret = []
45
+ while i < arr.length
46
+ ret.push ExecuteMethod.typecastParameter(arr[i])
47
+ i++
48
+ ret
49
+
50
+ isFunction: (str) ->
51
+ # console.log "isFunction"
52
+ if ExecuteMethod.regexIndexOf(str, /(\([\d|\D]+\))|(\(\))/, 0) != -1
53
+ return true
54
+ false
55
+
56
+ regexIndexOf: (string, regex, startpos) ->
57
+ # console.log "regexIndexOf"
58
+ indexOf = string.substring(startpos || 0).search(regex);
59
+ if (indexOf >= 0) then (indexOf + (startpos || 0)) else indexOf;
60
+
61
+ typecastParameter: (param) ->
62
+ param = param.trim()
63
+ param = param.replace(/^"/, "")
64
+ param = param.replace(/"$/m, "")
65
+ if param.search(/^\d+$/) == 0
66
+ # only numbers, parse to integer
67
+ return parseInt(param)
68
+ else if param.search(/^\d+\.\d+$/) == 0
69
+ return parseFloat(param)
70
+ else if param == "false"
71
+ return false
72
+ else if param == "true"
73
+ return true
74
+
75
+ param # just return the param as a string otherwise
76
+
77
+ executeSingleFunction: (func, params, context, _that) ->
78
+ context[func].apply(_that, params)
79
+
80
+ getSingleProperty: (property, context) ->
81
+ context[property]
82
+
83
+ ###
84
+ # @param {String} Provide a string on what to execute (e.g. this.is.something(true).to_run() or myFunction().property or myFunction())
85
+ # @param {Object} Provide a object to run the string provided on
86
+ # @param {Object} Provide an object that points to the "this" pointer which
87
+ ###
88
+ executeMethodByFunctionName: (str, context) ->
89
+ func_data = ExecuteMethod.getFunctionsAndProperties(str)
90
+ # since it's possible to chain functions and/or properties, and it's not possible to chain properly do a loop
91
+ i = 0
92
+ current_context = context
93
+ current_val = null
94
+ while i < func_data.length
95
+ if (func_data[i]["isfunc"] == true)
96
+ current_context = ExecuteMethod.executeSingleFunction(func_data[i]["func"], func_data[i]["params"], current_context, context)
97
+ else
98
+ current_context = ExecuteMethod.getSingleProperty(func_data[i]["func"], current_context)
99
+ i++
100
+ current_context
101
+
102
+ if (!String.prototype.trim)
103
+ String.prototype.trim = ->
104
+ this.replace(/^\s+|\s+$/g,'');
105
+
106
+ if (window.ExecuteMethod == "undefined" || window.ExecuteMethod == null || window.ExecuteMethod == undefined)
107
+ window.ExecuteMethod = ExecuteMethod
@@ -0,0 +1,264 @@
1
+ ###
2
+ jQuery css-watch event Coffeescript v1.2 - 11/20/2012
3
+ http://github.com/leifcr/jquery-csswatch/
4
+ (c) 2012 Leif Ringstad
5
+
6
+ @author Leif Ringstad
7
+ @version 1.0
8
+
9
+ Licensed under the freeBSD license
10
+ ###
11
+
12
+ # Note that with this pattern, as per Alex Sexton's, the plugin logic
13
+ # hasn't been nested in a jQuery plugin. Instead, we just use
14
+ # jQuery for its instantiation.
15
+
16
+ (($, window, document) ->
17
+
18
+ ###
19
+ Plugin constructor
20
+ ###
21
+ CssWatch = (elem, options) ->
22
+ @elem = elem
23
+ @$elem = $(elem)
24
+ @options = options
25
+ @cb_timer_id = null
26
+ @cached_function_name = ""
27
+ @stop_requested = false
28
+ return
29
+
30
+ ###
31
+ Plugin prototype
32
+ ###
33
+ CssWatch:: =
34
+ defaults:
35
+ event_name: "css-change"
36
+ data_attr_name: "css-watch-data"
37
+ use_event: true
38
+ callback: null
39
+ props: ""
40
+ props_functions: {}
41
+
42
+
43
+ ###
44
+ Initializer
45
+ ###
46
+ init: ->
47
+ @config = $.extend({}, @defaults, @options, @metadata)
48
+ @config.props = @splitAndTrimProps(@config.props)
49
+ if @config.props.length > 0
50
+ @setInitialData()
51
+ @start()
52
+
53
+ @
54
+
55
+ ###
56
+ split and trim properties
57
+ ###
58
+ splitAndTrimProps: (props) ->
59
+ arr = props.split(",")
60
+ ret = []
61
+ i = 0
62
+ while i < arr.length
63
+ ret.push arr[i].trim()
64
+ i++
65
+ ret
66
+
67
+ ###
68
+ set initial data
69
+ ###
70
+ setInitialData: ->
71
+ i = 0
72
+ while i < @config.props.length
73
+ @setData @config.props[i], @getPropertyValue(@config.props[i])
74
+ i++
75
+ return
76
+
77
+ ###
78
+ set a data element for a css property on the current element
79
+ ###
80
+ setData: (property, value) ->
81
+ @$elem.data("#{@config.data_attr_name}-#{property}", value)
82
+
83
+ ###
84
+ update data attributes from changes
85
+ ###
86
+ updateDataFromChanges: (changes) ->
87
+ @setData property, changes[property] for property, value in Object.keys(changes)
88
+ return
89
+
90
+ ###
91
+ get the datavalue stored for a property
92
+ ###
93
+ getDataValue: (property) ->
94
+ @$elem.data("#{@config.data_attr_name}-#{property}")
95
+
96
+ ###
97
+ get css property value (from jquery css or from custom function if needed)
98
+ ###
99
+ getPropertyValue: (property) ->
100
+ return @$elem.css(property) if (@cached_function_name == null) || (Object.keys(@config.props_functions).length == 0)
101
+
102
+ if @cached_function_name == ""
103
+ keys = Object.keys(@config.props_functions)
104
+ if property in keys
105
+ @cached_function_name = @config.props_functions[property]
106
+ else
107
+ @cached_function_name == null
108
+
109
+ if (@cached_function_name != "") && (@cached_function_name != null)
110
+ if (window.ExecuteMethod)
111
+ return ExecuteMethod.executeMethodByFunctionName(@cached_function_name, @$elem)
112
+ else
113
+ console.log "You are missing the ExecuteMethod library."
114
+ else
115
+ return @$elem.css(property)
116
+
117
+ ###
118
+ get object of changes
119
+ ###
120
+ changedProperties: ->
121
+ i = 0
122
+ ret = {}
123
+ while i < @config.props.length
124
+ if (@getPropertyValue(@config.props[i]) != @getDataValue(@config.props[i]))
125
+ ret[@config.props[i]] = @getPropertyValue(@config.props[i])
126
+ i++
127
+ ret
128
+
129
+ ###
130
+ stop csswatch / checking of css attributes
131
+ ###
132
+ stop: ->
133
+ return if (typeof @config == "undefined" || @config == null)
134
+ stop_requested = true
135
+ # stop the timer/windowanimate cb for this object
136
+ window.cssWatchCancelAnimationFrame(@cb_timer_id)
137
+
138
+
139
+ ###
140
+ start csswatch / checking of css attributes
141
+ ###
142
+ start: ->
143
+ return if (typeof @config == "undefined" || @config == null)
144
+ @stop_requested = false
145
+ # start the timer/windowanimate cb for this object if it isn't running
146
+ @cb_timer_id = window.cssWatchRequestAnimationFrame(=> @check(); return)
147
+ return
148
+
149
+ ###
150
+ the actual checking of changes
151
+ ###
152
+ check: ->
153
+ return false if (typeof @config == "undefined" || @config == null)
154
+ return false if @stop_requested == true
155
+ changes = @changedProperties()
156
+
157
+ if (Object.keys(changes).length > 0)
158
+ if @config.use_event
159
+ @$elem.trigger(@config.event_name, changes)
160
+
161
+ if @config.callback != null
162
+ @config.callback.apply(null, [changes])
163
+ # @config.callback.call({changes})
164
+ # set new data for each changed property
165
+ @updateDataFromChanges(changes)
166
+
167
+ @cb_timer_id = window.cssWatchRequestAnimationFrame(=> @check(); return)
168
+ false
169
+
170
+ ###
171
+ destroy plugin (stop/remove data)
172
+ ###
173
+ destroy: ->
174
+ @stop()
175
+ @$elem.removeData("css-watch-object")
176
+ @$elem.removeData(@config.data_attr_name)
177
+ return null
178
+
179
+ ###
180
+ Set defaults
181
+ ###
182
+ CssWatch.defaults = CssWatch::defaults
183
+
184
+ ###
185
+ Jquery extension for plugin
186
+ Plugin funcitonality is in the class above
187
+ ###
188
+ $.fn.csswatch = (options) ->
189
+ @each ->
190
+ if typeof options is "object" or not options
191
+ # check if there is an object existing, if so, delete it!
192
+ data = $(@).data("css-watch-object")
193
+ unless data
194
+ obj = new CssWatch(@, options)
195
+ $(@).data("css-watch-object", obj)
196
+ obj.init()
197
+ return
198
+ else if typeof options is "string"
199
+ obj = $(@).data("css-watch-object")
200
+ if obj && obj[options]
201
+ obj[options].apply this
202
+
203
+ return
204
+
205
+ #optional: window.Plugin = Plugin;
206
+
207
+ ) jQuery, window, document
208
+
209
+ ###
210
+ #
211
+ # Cross browser Object.keys implementation
212
+ #
213
+ # This is suggested implementation from Mozilla for supporting browser that do not implement Object.keys
214
+ # if object doesn't have .keys function
215
+ # if(!Object.keys) Object.keys = function(o){
216
+ # if (o !== Object(o))
217
+ # throw new TypeError('Object.keys called on non-object');
218
+ # var ret=[],p;
219
+ # for(p in o) if(Object.prototype.hasOwnProperty.call(o,p)) ret.push(p);
220
+ # return ret;
221
+ # }
222
+ ###
223
+
224
+ unless Object.keys
225
+ Object.keys = (o) ->
226
+ throw new TypeError("Object.keys called on non-object") if o isnt Object(o)
227
+ ret = []
228
+ p = undefined
229
+ for p of o
230
+ ret.push p if Object::hasOwnProperty.call(o, p)
231
+ ret
232
+
233
+ ###
234
+ Cross browser requestAnimationFrame
235
+ Not including settimeout as it will have a static value for timeout
236
+ ###
237
+
238
+ unless window.cssWatchRequestAnimationFrame
239
+ window.cssWatchRequestAnimationFrame = (->
240
+ window.webkitAnimationFrame or
241
+ window.webkitRequestAnimationFrame or
242
+ window.mozRequestAnimationFrame or
243
+ window.oRequestAnimationFrame or
244
+ window.msRequestAnimationFrame or
245
+ window.requestAnimationFrame or
246
+ (callback, element) ->
247
+ window.setTimeout(callback, 1000/60)
248
+ )()
249
+
250
+ ###
251
+ Cross browser cancelAnimationFrame
252
+ ###
253
+ unless window.cssWatchCancelAnimationFrame
254
+ window.cssWatchCancelAnimationFrame = (->
255
+ window.cancelAnimationFrame or
256
+ window.webkitCancelAnimationFrame or
257
+ window.webkitCancelRequestAnimationFrame or
258
+ window.mozCancelAnimationFrame or
259
+ window.mozCancelRequestAnimationFrame or
260
+ window.oCancelRequestAnimationFrame or
261
+ window.msCancelRequestAnimationFrame or
262
+ (timeout_id) -> # function FrameRequestCallback
263
+ window.clearTimeout timeout_id
264
+ )()