ultimate-base 0.3.2.1 → 0.3.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ultimate-base (0.3.2.1)
4
+ ultimate-base (0.3.3.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -4,13 +4,6 @@
4
4
 
5
5
  class Ultimate.Backbone.View extends Backbone.View
6
6
 
7
- @defaultLocales:
8
- en: {}
9
- ru: {}
10
-
11
- locale: "en"
12
- translations: {}
13
-
14
7
  loadingState: null
15
8
  loadingWidthMethodName: "innerWidth"
16
9
  loadingHeightMethodName: "innerHeight"
@@ -86,7 +79,6 @@ class Ultimate.Backbone.View extends Backbone.View
86
79
  # Overload parent method Backbone.View._configure() as hook for reflectOptions().
87
80
  _configure: (options) ->
88
81
  super
89
- @initTranslations()
90
82
  @reflectOptions()
91
83
 
92
84
  reflectOptions: (viewOptions = _.result(@, "viewOptions"), options = @options) ->
@@ -94,35 +86,6 @@ class Ultimate.Backbone.View extends Backbone.View
94
86
  @[attr] = value for attr, value of options when typeof @[attr] isnt "undefined"
95
87
  @
96
88
 
97
- updateOptions: (options) ->
98
- @_configure(options)
99
- @options
100
-
101
- # use I18n, and modify locale and translations in options
102
- # modify and return merged data
103
- initTranslations: (options = @options) ->
104
- # if global compatible I18n
105
- if I18n? and I18n.locale and I18n.t
106
- options["locale"] ||= I18n.locale
107
- if options["locale"] is I18n.locale
108
- # pointing to defaults locales of language specified in I18n
109
- _defaultLocales = @constructor.defaultLocales?[I18n.locale] ||= {}
110
- unless _defaultLocales["loaded"]
111
- _defaultLocales["loaded"] = true
112
- # try read localized strings
113
- if _localesFromI18n = I18n.t(options["i18nKey"] or _.underscored(@constructor.pluginName or @constructor.name))
114
- # fill it from I18n
115
- _.extend _defaultLocales, _localesFromI18n
116
- @locale = options["locale"] if options["locale"]
117
- translations = if @locale then @constructor.defaultLocales?[@locale] or {} else {}
118
- $.extend true, options, translations: translations, options
119
- options
120
-
121
- t: (key) ->
122
- # TODO maybe use I18n there
123
- @translations[key]
124
-
125
-
126
89
  # Overloadable getter for jQuery-container that will be blocked.
127
90
  getJLoadingContainer: -> @$el
128
91
 
@@ -18,7 +18,7 @@
18
18
  ).join("\n")
19
19
 
20
20
  options_from_collection_for_select: (collection, value_method, text_method, selected = null) ->
21
- options = _.map collection, (element) ->
21
+ options = @__mapCollection collection, (element) ->
22
22
  [@_value_for_collection(element, text_method), @_value_for_collection(element, value_method)]
23
23
  [selected, disabled] = @_extract_selected_and_disabled(selected)
24
24
  select_deselect =
@@ -26,6 +26,27 @@
26
26
  disabled: @_extract_values_from_collection(collection, value_method, disabled)
27
27
  @options_for_select(options, select_deselect)
28
28
 
29
+ option_groups_from_collection_for_select: (collection, group_method, group_label_method, option_key_method, option_value_method, selected_key = null) ->
30
+ @__mapCollection(collection, (group) ->
31
+ option_tags = @options_from_collection_for_select(_.result(group, group_method), option_key_method, option_value_method, selected_key)
32
+ Ultimate.Helpers.Tag.content_tag_string 'optgroup', option_tags, label: _.result(group, group_label_method), true, false
33
+ ).join('')
34
+
35
+ grouped_options_for_select: (grouped_options, selected_key = null, options = {}) ->
36
+ prompt = options['prompt']
37
+ divider = options['divider']
38
+ body = ""
39
+ if prompt
40
+ body += Ultimate.Helpers.Tag.content_tag_string('option', @_prompt_text(prompt), value: '')
41
+ grouped_options = _.outcasts.sortHash(grouped_options) if $.isPlainObject(grouped_options)
42
+ _.each grouped_options, (container) ->
43
+ if divider
44
+ label = divider
45
+ else
46
+ [label, container] = container
47
+ body += Ultimate.Helpers.Tag.content_tag_string('optgroup', @options_for_select(container, selected_key), label: label, true, false)
48
+ body
49
+
29
50
 
30
51
 
31
52
  _option_html_attributes: (element) ->
@@ -56,10 +77,30 @@
56
77
 
57
78
  _extract_values_from_collection: (collection, value_method, selected) ->
58
79
  if _.isFunction(selected)
59
- _.compact _.map collection, (element) ->
60
- _.result(element, value_method) if selected(element)
80
+ _.compact @__mapCollection collection, (element) ->
81
+ @__getValueFromElement(element, value_method) if selected(element)
61
82
  else
62
83
  selected
63
84
 
64
85
  _value_for_collection: (item, value) ->
65
- if _.isFunction(value) then value(item) else _.result(item, value)
86
+ if _.isFunction(value)
87
+ value(item)
88
+ else
89
+ @__getValueFromElement(item, value)
90
+
91
+ _prompt_text: (prompt) ->
92
+ prompt = if _.isString(prompt) then prompt else I18n?.translate('helpers.select.prompt', default: 'Please select') ? 'Please select'
93
+
94
+
95
+
96
+ __getValueFromElement: (element, property) ->
97
+ if _.isFunction(element.get)
98
+ element.get(property)
99
+ else
100
+ _.result(element, property)
101
+
102
+ __mapCollection: (collection, iterator) ->
103
+ if _.isFunction(collection.map)
104
+ collection.map(iterator)
105
+ else
106
+ _.map(collection, iterator)
@@ -8,7 +8,7 @@
8
8
 
9
9
  content_tag_for: (tag_name, single_or_multiple_records, prefix = null, options = null, block = null) ->
10
10
  block = _.outcasts.blockGiven(arguments)
11
- if _.isFunction(single_or_multiple_records.map)
11
+ if _.isFunction(single_or_multiple_records?.map)
12
12
  single_or_multiple_records.map( (single_record) =>
13
13
  @content_tag_for_single_record(tag_name, single_record, prefix, options, block)
14
14
  ).join("\n")
@@ -16,6 +16,7 @@
16
16
  @content_tag_for_single_record(tag_name, single_or_multiple_records, prefix, options, block)
17
17
 
18
18
  content_tag_for_single_record: (tag_name, record, prefix, options, block = null) ->
19
+ return '' unless record?
19
20
  [options, prefix] = [prefix, null] if _.isObject(prefix)
20
21
  block = _.outcasts.blockGiven(arguments)
21
22
  options = if _.isObject(options) then _.clone(options) else {}
@@ -29,7 +30,7 @@
29
30
 
30
31
  # from ActionView::ModelNaming
31
32
  model_name_from_record_or_class: (record_or_class) ->
32
- modelClass = record_or_class.constructor ? record_or_class
33
+ modelClass = record_or_class?.constructor ? record_or_class
33
34
  if modelClass?
34
35
  modelClass.modelName or modelClass.className or modelClass.name or 'Model'
35
36
  else
@@ -77,4 +78,4 @@
77
78
  # protected
78
79
 
79
80
  _record_key_for_dom_id: (record) ->
80
- record.id
81
+ record?.id
@@ -24,8 +24,8 @@
24
24
  splitted = content.replace(/\]\]>/g, ']]]]><![CDATA[>')
25
25
  "<![CDATA[#{splitted}]]>"
26
26
 
27
- content_tag_string: (name, content = '', options = {}, escape = true) ->
28
- content = _.string.escapeHTML(content) if escape
27
+ content_tag_string: (name, content = '', options = {}, escape = true, _escapeContent = escape) ->
28
+ content = _.string.escapeHTML(content) if _escapeContent
29
29
  "<#{name}#{@tag_options(options, escape)}>#{@PRE_CONTENT_STRINGS[name] ? ''}#{content}</#{name}>"
30
30
 
31
31
  html_options_to_s: (html_options, escape = false, prefix = "") ->
@@ -58,24 +58,34 @@
58
58
  value = _.string.escapeHTML(value) if escape
59
59
  "#{key}=\"#{value}\""
60
60
 
61
+ concat_class: ->
62
+ flatten_classes = _.filter( _.flatten(arguments), (e) -> _.isString(e) ).join(' ')
63
+ _.uniq( _.string.words(flatten_classes) ).join(' ')
61
64
 
62
65
 
63
- # # TODO more zen features: +, *x, {content}
64
- # # TODO cache
65
- # selectorToHtml: (selector) ->
66
- # if matches = selector.match(/^[\s>]*([\w\.]+)(.*)$/)
67
- # selector = matches[1]
68
- # continuation = matches[2]#{(if open then ">" else " />")}
69
- # classes = selector.split(".")
70
- # tag_name = classes.shift() or "div"
71
- # html_options = {}
72
- # html_options["class"] = classes.join(" ") if classes.length
73
- # if continuation
74
- # @content_tag(tag_name, @selectorToHtml(continuation), html_options)
75
- # else
76
- # @tag(tag_name, html_options)
77
- # else
78
- # ""
79
- #
80
- concat_class: ->
81
- _.uniq(_.compact(arguments).join(' ').split(/\s+/)).join(' ')
66
+
67
+ selfClosedTags: _.string.words('area base br col command embed hr img input keygen link meta param source track wbr')
68
+
69
+ # Generate html from zen-selector. Ninja tool.
70
+ # TODO more zen features: +, *x, {content}
71
+ # TODO cache
72
+ selectorToHtml: (selector) ->
73
+ if matches = selector.match(/^[\s>]*([\w\.#]+)(.*)$/)
74
+ selector = matches[1]
75
+ continuation = matches[2] # in v1 {(if continuation then ">" + content else " />")}
76
+ tag_name = selector.match(/^\w+/)?[0] or 'div'
77
+ id = selector.match(/#(\w+)/)?[1]
78
+ classes = _.map( selector.match(/\.\w+/g), (c) -> _.string.ltrim(c, '.') )
79
+ html_options = {}
80
+ html_options['id'] = id if id
81
+ html_options['class'] = classes.join(' ') if classes.length
82
+ if _.contains(@selfClosedTags, tag_name)
83
+ @tag(tag_name, html_options)
84
+ else
85
+ continuation = @selectorToHtml(continuation) if continuation
86
+ @content_tag(tag_name, continuation, html_options)
87
+ # else if matches = selector.match(/^\s*\+\s*(.*)$/) # /^\s*\+\s*([\w\.#]+)(.*)$/)
88
+ # continuation = matches[1]
89
+ # if continuation then @selectorToHtml(continuation) else continuation
90
+ else
91
+ ''
@@ -3,7 +3,7 @@
3
3
  #= require ./javascript
4
4
 
5
5
  __char_encode = (char) -> "%#{char.charCodeAt(0).toString(16)}"
6
- escape_path = (str) -> str.replace(/[^*\-.0-9A-Z_a-z]/g, __char_encode).replace(/\+/g, '%20')
6
+ __escape_path = (str) -> str.replace(/[^*\-.0-9A-Z_a-z]/g, __char_encode).replace(/\+/g, '%20')
7
7
  __string_encode = (str) -> _.map(str, (char) -> "&##{char.charCodeAt(0)};" ).join('')
8
8
 
9
9
  @Ultimate.Helpers.Url =
@@ -41,7 +41,38 @@ __string_encode = (str) -> _.map(str, (char) -> "&##{char.charCodeAt(0)};" ).joi
41
41
  [options, name] = [name, null] if block = _.outcasts.blockGiven(arguments)
42
42
  @link_to [name, options, html_options, block]...
43
43
 
44
+ # TODO tests
45
+ link_to_unless_current_span: (name, options = null, html_options = null, block = null) ->
46
+ [html_options, options] = [options, name] if block = _.outcasts.blockGiven(arguments)
47
+ url = @url_for(options)
48
+ if @current_page_(url)
49
+ if block
50
+ Ultimate.Helpers.Tag.content_tag('span', html_options, null, false, block)
51
+ else
52
+ Ultimate.Helpers.Tag.content_tag('span', name ? url, html_options, false)
53
+ else
54
+ if block
55
+ @link_to options, html_options, block
56
+ else
57
+ @link_to name, options, html_options
58
+
59
+ # TODO tests
60
+ link_to_unless_current: (name, options = {}, html_options = {}, block = null) ->
61
+ @link_to_unless @current_page_(options), name, options, html_options, block
62
+
63
+ # TODO tests
64
+ link_to_unless: (condition, name, options = {}, html_options = {}, block = null) ->
65
+ if condition
66
+ if block = _.outcasts.blockGiven(arguments)
67
+ block(name, options, html_options)
68
+ else
69
+ name
70
+ else
71
+ @link_to name, options, html_options, block
44
72
 
73
+ # TODO tests
74
+ link_to_if: (condition, name, options = {}, html_options = {}, block = null) ->
75
+ @link_to_unless not condition, name, options, html_options, block
45
76
 
46
77
  mail_to: (email_address, name = null, html_options = {}) ->
47
78
  email_address = _.string.escapeHTML(email_address)
@@ -49,7 +80,7 @@ __string_encode = (str) -> _.map(str, (char) -> "&##{char.charCodeAt(0)};" ).joi
49
80
  extras = _.compact _.map _.string.words('cc bcc body subject'), (item) ->
50
81
  option = _.outcasts.delete(html_options, item)
51
82
  if option?
52
- "#{item}=#{escape_path(option)}"
83
+ "#{item}=#{__escape_path(option)}"
53
84
  extras = if _.isEmpty(extras) then '' else '?' + _.string.escapeHTML(extras.join('&'))
54
85
  email_address_obfuscated = email_address
55
86
  email_address_obfuscated = email_address_obfuscated.replace('@', _.outcasts.delete(html_options, 'replace_at')) if 'replace_at' of html_options
@@ -67,6 +98,15 @@ __string_encode = (str) -> _.map(str, (char) -> "&##{char.charCodeAt(0)};" ).joi
67
98
  else
68
99
  @link_to name or email_address_obfuscated, "mailto:#{email_address}#{extras}", html_options
69
100
 
101
+ # TODO tests
102
+ current_page_: (options) ->
103
+ url_string = @url_for(options)
104
+ request_uri = location.pathname
105
+ if /^\w+:\/\//.test(url_string)
106
+ url_string == "#{location.protocol}#{location.host}#{request_uri}"
107
+ else
108
+ url_string == request_uri
109
+
70
110
 
71
111
 
72
112
  _convert_options_to_data_attributes: (options, html_options) ->
@@ -91,8 +131,16 @@ __string_encode = (str) -> _.map(str, (char) -> "&##{char.charCodeAt(0)};" ).joi
91
131
  html_options
92
132
 
93
133
  __protect_against_forgery: false
94
- __form_authenticity_token: 'secret'
95
134
  __request_forgery_protection_token: 'form_token'
135
+ __form_authenticity_token: 'secret'
136
+
137
+ __init_request_forgery_protection: ->
138
+ param = $('head meta[name="csrf-param"]').attr('content')
139
+ token = $('head meta[name="csrf-token"]').attr('content')
140
+ if param and token
141
+ @__protect_against_forgery = true
142
+ @__request_forgery_protection_token = param
143
+ @__form_authenticity_token = token
96
144
 
97
145
  _token_tag: (token = @__form_authenticity_token) ->
98
146
  if token isnt false and @__protect_against_forgery
@@ -1,5 +1,13 @@
1
1
  #= require ./base
2
2
 
3
+ # TODO minimize requirements
4
+ # requirements stats:
5
+ # 1 _.extend
6
+ # 1 _.isString
7
+ # 1 _.isBoolean
8
+ # 1 _.toArray
9
+ # 1 _.last
10
+
3
11
  ###*
4
12
  * Make $.fn.pluginName() as adapter to plugin object (instance of Ultimate.Plugin or Backbone.View).
5
13
  * First call on jQuery object invoke View functionality for the first element in the set of matched elements.
@@ -13,7 +21,7 @@
13
21
  ###
14
22
 
15
23
  Ultimate.createJQueryPlugin = (pluginName, pluginClass) ->
16
- Ultimate.debug(".createJQueryPlugin()", pluginName, pluginClass) if _.isFunction(Ultimate.debug)
24
+ Ultimate.debug(".createJQueryPlugin()", pluginName, pluginClass) if $.isFunction(Ultimate.debug)
17
25
  pluginClass.pluginName ||= pluginName
18
26
  jQuery.fn[pluginName] = -> @ultimatePluginAdapter pluginName, pluginClass, arguments
19
27
 
@@ -46,7 +54,7 @@ do ($ = jQuery) ->
46
54
  return if _returnPlugin then plugin else jContainer
47
55
  if command of plugin
48
56
  value = plugin[command]
49
- return if _.isFunction(value)
57
+ return if $.isFunction(value)
50
58
  plugin.$el.removeData(pluginName) if command is "destroy"
51
59
  result = value.apply(plugin, args)
52
60
  if command is "_configure" then plugin.options else result
@@ -25,26 +25,24 @@ class Ultimate.Plugin
25
25
 
26
26
  options: {}
27
27
 
28
- locale: "en"
28
+ # @defaultLocales: { en: {} }
29
+ locale: 'en'
29
30
  translations: {}
30
31
 
31
32
  constructor: (options) ->
32
- @_configure(options || {});
33
+ throw new Error('Property `el` must be specified at first argument of Ultimate.Plugin.constructor') unless options?.el
34
+ @cid = _.uniqueId('ultimatePlugin_')
35
+ @_configure options
33
36
  @$el = $(@el)
34
37
  @findNodes()
35
- @initialize arguments...
38
+ @initialize? arguments...
36
39
  @delegateEvents()
37
40
 
38
-
39
41
  # jQuery delegate for element lookup, scoped to DOM elements within the
40
42
  # current plugin. This should be prefered to global lookups where possible.
41
43
  $: (selector) ->
42
44
  @$el.find(selector)
43
45
 
44
- # Initialize is an empty function by default. Override it with your own
45
- # initialization logic.
46
- initialize: ->
47
-
48
46
  findNodes: (jRoot = @$el, nodes = @nodes) ->
49
47
  jNodes = {}
50
48
  nodes = if _.isFunction(nodes) then @nodes.call(@) else _.clone(nodes)
@@ -53,18 +51,24 @@ class Ultimate.Plugin
53
51
  _isObject = _.isObject(selector)
54
52
  if _isObject
55
53
  nestedNodes = selector
56
- selector = _.outcasts.delete(nestedNodes, "selector")
54
+ selector = _.outcasts.delete(nestedNodes, 'selector')
57
55
  jNodes[nodeName] = @[nodeName] = jRoot.find(selector)
58
56
  if _isObject
59
57
  _.extend jNodes, @findNodes(jNodes[nodeName], nestedNodes)
60
58
  jNodes
61
59
 
62
60
  undelegateEvents: ->
63
- @$el.unbind ".delegateEvents#{@cid}"
61
+ @$el.unbind ".delegateEvents_#{@cid}"
64
62
 
65
63
  # Cached regex to split keys for `delegate`, from backbone.js.
66
64
  delegateEventSplitter = /^(\S+)\s*(.*)$/
67
65
 
66
+ # Overload and proxy parent method Backbone.View.delegateEvents() as hook for normalizeEvents().
67
+ delegateEvents: (events) ->
68
+ args = _.toArray(arguments)
69
+ args[0] = @_normalizeEvents(events)
70
+ @_delegateEvents args...
71
+
68
72
  # delegateEvents() from backbone.js
69
73
  _delegateEvents: (events = _.result(@, "events")) ->
70
74
  return unless events
@@ -74,20 +78,13 @@ class Ultimate.Plugin
74
78
  throw new Error("Method \"#{events[key]}\" does not exist") unless method
75
79
  [[], eventName, selector] = key.match(delegateEventSplitter)
76
80
  method = _.bind(method, @)
77
- eventName += ".delegateEvents#{@cid}"
81
+ eventName += ".delegateEvents_#{@cid}"
78
82
  if selector is ''
79
83
  @$el.bind(eventName, method)
80
84
  else
81
85
  @$el.delegate(selector, eventName, method)
82
86
 
83
- # Overload and proxy parent method Backbone.View.delegateEvents() as hook for normalizeEvents().
84
- delegateEvents: (events) ->
85
- args = []
86
- Array::push.apply args, arguments if arguments.length > 0
87
- args[0] = @normalizeEvents(events)
88
- @_delegateEvents args...
89
-
90
- normalizeEvents: (events) ->
87
+ _normalizeEvents: (events) ->
91
88
  events = _.result(@, "events") unless events
92
89
  if events
93
90
  normalizedEvents = {}
@@ -104,31 +101,24 @@ class Ultimate.Plugin
104
101
 
105
102
  _configure: (options) ->
106
103
  _.extend @options, options
107
- @initTranslations()
108
- @reflectOptions()
104
+ #cout '@options', @options
105
+ @_reflectOptions()
106
+ @_initTranslations()
109
107
 
110
- reflectOptions: (reflectableOptions = _.result(@, "reflectableOptions"), options = @options) ->
108
+ _reflectOptions: (reflectableOptions = _.result(@, "reflectableOptions"), options = @options) ->
111
109
  if _.isArray(reflectableOptions)
112
- @[attr] = options[attr] for attr in reflectableOptions when typeof options[attr] isnt "undefined"
113
- @[attr] = value for attr, value of options when typeof @[attr] isnt "undefined"
114
- @
115
-
116
- # use I18n, and modify locale and translations in options
117
- # modify and return merged data
118
- initTranslations: (options = @options) ->
119
- # if global compatible I18n
120
- # if I18n? and I18n.locale and I18n.t
121
- # options["locale"] ||= I18n.locale
122
- # if options["locale"] is I18n.locale
123
- # # pointing to defaults locales of language specified in I18n
124
- # _defaultLocales = @constructor.defaultLocales?[I18n.locale] ||= {}
125
- # unless _defaultLocales["loaded"]
126
- # _defaultLocales["loaded"] = true
127
- # # try read localized strings
128
- # if _localesFromI18n = I18n.t(options["i18nKey"] or _.string.underscored(@constructor.pluginName or @constructor.name))
129
- # # fill it from I18n
130
- # _.extend _defaultLocales, _localesFromI18n
131
- @locale = options["locale"] if options["locale"]
132
- translations = if @locale then @constructor.defaultLocales?[@locale] or {} else {}
133
- $.extend true, options, translations: translations, options
134
- options
110
+ @[attr] = options[attr] for attr in reflectableOptions when not _.isUndefined(options[attr])
111
+ @[attr] = value for attr, value of options when not _.isUndefined(@[attr])
112
+
113
+ # use I18n, and modify locale and translations
114
+ _initTranslations: ->
115
+ if @constructor.defaultLocales?
116
+ if not @options["locale"] and I18n?.locale of @constructor.defaultLocales
117
+ @locale = I18n.locale
118
+ #cout '!!!Set LOCALE FROM I18N ', @locale
119
+ defaultTranslations = if @locale then @constructor.defaultLocales[@locale] or {} else {}
120
+ #cout '!!!defaultTranslations', @locale, defaultTranslations
121
+ _.defaults @translations, defaultTranslations
122
+
123
+ t: (key) ->
124
+ @translations[key] or _.string.humanize(key)
@@ -4,7 +4,7 @@
4
4
  Underscore.outcasts is freely distributable under the terms of the MIT license.
5
5
  Documentation: https://github.com/KODerFunk/underscore.outcasts
6
6
  Some code is borrowed from outcasts pull requests to Underscore.
7
- Version '0.1.3'
7
+ Version '0.1.4'
8
8
  ###
9
9
 
10
10
  'use strict'
@@ -15,7 +15,7 @@
15
15
 
16
16
  UnderscoreOutcasts =
17
17
 
18
- VERSION: '0.1.3'
18
+ VERSION: '0.1.4'
19
19
 
20
20
  delete: (object, key) ->
21
21
  value = object[key]
@@ -73,6 +73,16 @@ UnderscoreOutcasts =
73
73
  else
74
74
  [object]
75
75
 
76
+ # http://coderwall.com/p/krcdig
77
+ deepBindAll: (obj) ->
78
+ target = _.last(arguments)
79
+ for key, value of obj
80
+ if _.isFunction(value)
81
+ obj[key] = _.bind(value, target)
82
+ else if _.isObject(value)
83
+ obj[key] = _.deepBindAll(value, target)
84
+ obj
85
+
76
86
  ###
77
87
  Split array into slices of <number> elements.
78
88
  Map result by iterator if last given.
@@ -33,6 +33,7 @@
33
33
  }
34
34
  }
35
35
 
36
+ // TODO docs
36
37
  @mixin vendors-full($vendors, $property, $params, $origin: true) {
37
38
  @each $vendor in $vendors {
38
39
  -#{$vendor}-#{$property}: -#{$vendor}-#{$params};
@@ -1,3 +1,6 @@
1
+
2
+ $support-ie: true !default;
3
+
1
4
  // Provide cross-browser CSS text-shadow with hardcore ie-hack.
2
5
  // example:
3
6
  // @include text-shadow(#3b3b3b 1px 1px 1px);
@@ -1,12 +1,11 @@
1
1
  // Use compatibility tables from http://caniuse.com/
2
- // http://css3pie.com/documentation/supported-css3-features/#pie-watch-ancestors
3
2
  // http://css3pie.com/documentation/supported-css3-features/#pie-lazy-init
4
- // TODO use !default http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#variable_defaults_
5
3
 
6
4
  $support-ie: true !default;
7
5
  $pie-url: asset-url("polyfills/PIE.htc", '') !default;
8
6
  $boxsizing-url: asset-url("polyfills/boxsizing.htc", '') !default;
9
7
 
8
+
10
9
  @mixin pie($poll: none, $watch-ancestors: 0) {
11
10
  @if $support-ie and $pie-url {
12
11
  behavior: $pie-url;
@@ -65,6 +65,21 @@ $support-ie: true !default;
65
65
  }
66
66
  }
67
67
 
68
+ @mixin position($top: false, $right: false, $bottom: false, $left: false, $position: absolute) {
69
+ @if length($top) == 4 {
70
+ $left : nth($top, 4);
71
+ $bottom : nth($top, 3);
72
+ $right : nth($top, 2);
73
+ $top : nth($top, 1);
74
+ @if isset($right) { $position: $right; }
75
+ }
76
+ @if isset($position) { position: $position; }
77
+ @if isset($top) { top: $top; }
78
+ @if isset($right) { right: $right; }
79
+ @if isset($bottom) { botttom: $bottom; }
80
+ @if isset($left) { left: $left; }
81
+ }
82
+
68
83
  @mixin before($display: block, $content: '') {
69
84
  &:before {
70
85
  display: $display;
@@ -1,5 +1,5 @@
1
1
  module Ultimate
2
2
  module Base
3
- VERSION = "0.3.2.1"
3
+ VERSION = "0.3.3.0"
4
4
  end
5
5
  end
@@ -1,6 +1,7 @@
1
1
  #= require ultimate/underscore/underscore
2
2
  #= require ultimate/underscore/underscore.string
3
3
  #= require ultimate/underscore/underscore.outcasts
4
+ #= require ultimate/backbone/lib/backbone
4
5
  #= require ultimate/helpers/form_options
5
6
 
6
7
  module "Ultimate.Helpers.FormOptions"
@@ -53,31 +54,24 @@ test "options_for_select", ->
53
54
 
54
55
 
55
56
 
56
- class Post
57
- title : null
58
- author_name : null
59
- body : null
60
- secret : null
61
- written_on : null
62
- category : null
63
- origin : null
64
- allow_comments : null
65
-
57
+ class Struct
66
58
  constructor: ->
67
- keys = ['title', 'author_name', 'body', 'secret', 'written_on', 'category', 'origin', 'allow_comments']
68
- for a, i in arguments
69
- @[keys[i]] = a
59
+ for key, index in @constructor.keys
60
+ @[key] = arguments[index] ? null
61
+
62
+ class Post extends Struct
63
+ @keys = ['title', 'author_name', 'body', 'secret', 'written_on', 'category', 'origin', 'allow_comments']
70
64
 
71
65
  dummy_posts =
72
66
  [ new Post("<Abe> went home", "<Abe>", "To a little house", "shh!"),
73
67
  new Post("Babe went home", "Babe", "To a little house", "shh!"),
74
- new Post("Cabe went home", "Cabe", "To a little house", "shh!") ]
68
+ new Post("Cabe went home", "Cabe", (-> "To a little house"), (-> "shh!")) ]
75
69
 
76
70
  test "options_from_collection_for_select", ->
77
71
  equal options_from_collection_for_select(dummy_posts, "author_name", "title"),
78
72
  "<option value=\"&lt;Abe&gt;\">&lt;Abe&gt; went home</option>\n<option value=\"Babe\">Babe went home</option>\n<option value=\"Cabe\">Cabe went home</option>"
79
73
  equal options_from_collection_for_select(dummy_posts, "author_name", "title", "Babe"),
80
- "<option value=\"&lt;Abe&gt;\">&lt;Abe&gt; went home</option>\n<option selected=\"selected\" value=\"Babe\">Babe went home</option>\n<option value=\"Cabe\">Cabe went home</option>"
74
+ "<option value=\"&lt;Abe&gt;\">&lt;Abe&gt; went home</option>\n<option selected=\"selected\" value=\"Babe\">Babe went home</option>\n<option value=\"Cabe\">Cabe went home</option>"
81
75
  equal options_from_collection_for_select(dummy_posts, "author_name", "title", [ "Babe", "Cabe" ]),
82
76
  "<option value=\"&lt;Abe&gt;\">&lt;Abe&gt; went home</option>\n<option selected=\"selected\" value=\"Babe\">Babe went home</option>\n<option selected=\"selected\" value=\"Cabe\">Cabe went home</option>"
83
77
  equal options_from_collection_for_select(dummy_posts, "author_name", "title", (p) -> p.author_name is 'Babe'),
@@ -94,3 +88,83 @@ test "options_from_collection_for_select", ->
94
88
  "<option value=\"&lt;Abe&gt;\">&lt;Abe&gt; went home</option>\n<option value=\"Babe\">Babe went home</option>\n<option value=\"Cabe\">Cabe went home</option>"
95
89
  equal options_from_collection_for_select(dummy_posts, "author_name", (p) -> p.title),
96
90
  "<option value=\"&lt;Abe&gt;\">&lt;Abe&gt; went home</option>\n<option value=\"Babe\">Babe went home</option>\n<option value=\"Cabe\">Cabe went home</option>"
91
+
92
+
93
+
94
+ _objectsArrayToHashesArray = (objectsArray) ->
95
+ _.map objectsArray, (element) ->
96
+ hash = {}
97
+ for key in element.constructor.keys
98
+ hash[key] = element[key]
99
+ hash
100
+
101
+ test "options_from_collection_for_select with array of hashes", ->
102
+ equal options_from_collection_for_select(_objectsArrayToHashesArray(dummy_posts), "author_name", "title", "Babe"),
103
+ "<option value=\"&lt;Abe&gt;\">&lt;Abe&gt; went home</option>\n<option selected=\"selected\" value=\"Babe\">Babe went home</option>\n<option value=\"Cabe\">Cabe went home</option>"
104
+
105
+
106
+
107
+ class BBPost extends Backbone.Model
108
+
109
+ class BBPosts extends Backbone.Collection
110
+ model: BBPost
111
+
112
+ test "options_from_collection_for_select with Backbone.Collection", ->
113
+ bbPosts = new BBPosts(_objectsArrayToHashesArray(dummy_posts))
114
+ equal options_from_collection_for_select(bbPosts, "author_name", "title", "Babe"),
115
+ "<option value=\"&lt;Abe&gt;\">&lt;Abe&gt; went home</option>\n<option selected=\"selected\" value=\"Babe\">Babe went home</option>\n<option value=\"Cabe\">Cabe went home</option>"
116
+ equal options_from_collection_for_select(bbPosts, "author_name", "title", disabled: (p) -> p.get('author_name') in ['Babe', 'Cabe']),
117
+ "<option value=\"&lt;Abe&gt;\">&lt;Abe&gt; went home</option>\n<option disabled=\"disabled\" value=\"Babe\">Babe went home</option>\n<option disabled=\"disabled\" value=\"Cabe\">Cabe went home</option>"
118
+ equal options_from_collection_for_select(bbPosts, ((p) -> p.get('author_name')), "title"),
119
+ "<option value=\"&lt;Abe&gt;\">&lt;Abe&gt; went home</option>\n<option value=\"Babe\">Babe went home</option>\n<option value=\"Cabe\">Cabe went home</option>"
120
+ equal options_from_collection_for_select(bbPosts, "author_name", (p) -> p.get('title')),
121
+ "<option value=\"&lt;Abe&gt;\">&lt;Abe&gt; went home</option>\n<option value=\"Babe\">Babe went home</option>\n<option value=\"Cabe\">Cabe went home</option>"
122
+
123
+
124
+
125
+ class Continent extends Struct
126
+ @keys = ['continent_name', 'countries']
127
+
128
+ class Country extends Struct
129
+ @keys = ['country_id', 'country_name']
130
+
131
+ dummy_continents =
132
+ [ new Continent("<Africa>", [new Country("<sa>", "<South Africa>"), new Country("so", "Somalia")]),
133
+ new Continent("Europe", [new Country("dk", "Denmark"), new Country("ie", "Ireland")]) ]
134
+
135
+ test "option_groups_from_collection_for_select", ->
136
+ equal option_groups_from_collection_for_select(dummy_continents, "countries", "continent_name", "country_id", "country_name", "dk"),
137
+ "<optgroup label=\"&lt;Africa&gt;\"><option value=\"&lt;sa&gt;\">&lt;South Africa&gt;</option>\n<option value=\"so\">Somalia</option></optgroup><optgroup label=\"Europe\"><option selected=\"selected\" value=\"dk\">Denmark</option>\n<option value=\"ie\">Ireland</option></optgroup>"
138
+
139
+
140
+
141
+ class BBContinent extends Backbone.Model
142
+
143
+ class BBContinents extends Backbone.Collection
144
+ model: BBContinent
145
+
146
+ test "option_groups_from_collection_for_select with Backbone.Collection", ->
147
+ BBContinents = new BBContinents(_objectsArrayToHashesArray(dummy_continents))
148
+ equal option_groups_from_collection_for_select(dummy_continents, "countries", "continent_name", "country_id", "country_name", "dk"),
149
+ "<optgroup label=\"&lt;Africa&gt;\"><option value=\"&lt;sa&gt;\">&lt;South Africa&gt;</option>\n<option value=\"so\">Somalia</option></optgroup><optgroup label=\"Europe\"><option selected=\"selected\" value=\"dk\">Denmark</option>\n<option value=\"ie\">Ireland</option></optgroup>"
150
+
151
+
152
+
153
+ test "grouped_options_for_select", ->
154
+ equal grouped_options_for_select([
155
+ ["North America",
156
+ [['United States','US'],"Canada"]],
157
+ ["Europe",
158
+ [["Great Britain","GB"], "Germany"]]
159
+ ]),
160
+ "<optgroup label=\"North America\"><option value=\"US\">United States</option>\n<option value=\"Canada\">Canada</option></optgroup><optgroup label=\"Europe\"><option value=\"GB\">Great Britain</option>\n<option value=\"Germany\">Germany</option></optgroup>"
161
+ equal grouped_options_for_select([['US',"Canada"] , ["GB", "Germany"]], null, divider: "----------"),
162
+ "<optgroup label=\"----------\"><option value=\"US\">US</option>\n<option value=\"Canada\">Canada</option></optgroup><optgroup label=\"----------\"><option value=\"GB\">GB</option>\n<option value=\"Germany\">Germany</option></optgroup>"
163
+ equal grouped_options_for_select([["Hats", ["Baseball Cap","Cowboy Hat"]]], "Cowboy Hat", prompt: "Choose a product..."),
164
+ "<option value=\"\">Choose a product...</option><optgroup label=\"Hats\"><option value=\"Baseball Cap\">Baseball Cap</option>\n<option selected=\"selected\" value=\"Cowboy Hat\">Cowboy Hat</option></optgroup>"
165
+ equal grouped_options_for_select([["Hats", ["Baseball Cap","Cowboy Hat"]]], "Cowboy Hat", prompt: true),
166
+ "<option value=\"\">Please select</option><optgroup label=\"Hats\"><option value=\"Baseball Cap\">Baseball Cap</option>\n<option selected=\"selected\" value=\"Cowboy Hat\">Cowboy Hat</option></optgroup>"
167
+ equal grouped_options_for_select([["Hats", ["Baseball Cap","Cowboy Hat"]]], null, prompt: '<Choose One>'),
168
+ "<option value=\"\">&lt;Choose One&gt;</option><optgroup label=\"Hats\"><option value=\"Baseball Cap\">Baseball Cap</option>\n<option value=\"Cowboy Hat\">Cowboy Hat</option></optgroup>"
169
+ equal grouped_options_for_select({'North America': ['United States','Canada'], 'Europe': ['Denmark','Germany']}),
170
+ "<optgroup label=\"Europe\"><option value=\"Denmark\">Denmark</option>\n<option value=\"Germany\">Germany</option></optgroup><optgroup label=\"North America\"><option value=\"United States\">United States</option>\n<option value=\"Canada\">Canada</option></optgroup>"
@@ -47,6 +47,8 @@ test "content_tag_for", ->
47
47
  options = class: 'important'
48
48
  content_tag_for('li', record, options)
49
49
  deepEqual options, class: 'important'
50
+ strictEqual content_tag_for('tr', null), ""
51
+ strictEqual content_tag_for('tr', [null, null]), "\n"
50
52
 
51
53
  test "div_for", ->
52
54
  record.id = 36
@@ -36,3 +36,22 @@ test "cdata_section", ->
36
36
  equal cdata_section("<hello world>"), "<![CDATA[<hello world>]]>"
37
37
  equal cdata_section("hello]]>world"), "<![CDATA[hello]]]]><![CDATA[>world]]>"
38
38
  equal cdata_section("hello]]>world]]>again"), "<![CDATA[hello]]]]><![CDATA[>world]]]]><![CDATA[>again]]>"
39
+
40
+ test "concat_class", ->
41
+ strictEqual concat_class(), ''
42
+ strictEqual concat_class(null), ''
43
+ strictEqual concat_class([]), ''
44
+ equal concat_class('lol', 0), 'lol'
45
+ equal concat_class(' lol ', false, ' wow '), 'lol wow'
46
+ equal concat_class('lol', null, 'rofl lol wow ', ' wow '), 'lol rofl wow'
47
+ equal concat_class([['lol', [null]], 'rofl lol wow '], ' wow '), 'lol rofl wow'
48
+
49
+ test "selectorToHtml", ->
50
+ equal selectorToHtml(''), ''
51
+ equal selectorToHtml('.lol'), '<div class="lol"></div>'
52
+ equal selectorToHtml('tr.lol'), '<tr class="lol"></tr>'
53
+ equal selectorToHtml('tr.lol#rofl'), '<tr class="lol" id="rofl"></tr>'
54
+ equal selectorToHtml('#rofl.lol'), '<div class="lol" id="rofl"></div>'
55
+ equal selectorToHtml('.lol.wow'), '<div class="lol wow"></div>'
56
+ equal selectorToHtml('.wow#rofl.lol'), '<div class="wow lol" id="rofl"></div>'
57
+ # equal selectorToHtml('h1.one+p.two'), '<h1 class="one"></h1><p class="two"></p>'
@@ -0,0 +1,66 @@
1
+ #= require ultimate/jquery-plugin-class
2
+
3
+ module "Ultimate.Plugin"
4
+
5
+ class EmptyPlugin extends Ultimate.Plugin
6
+
7
+ test "EmptyPlugin", ->
8
+ cout 'EmptyPlugin'
9
+ $('#qunit-fixture').html '<div class="test-plugin"><div class="test-plugin__inner"></div></div>'
10
+ plugin = new EmptyPlugin(el: '.test-plugin')
11
+
12
+ throws (-> new EmptyPlugin), "plugin can't build without `el` as option"
13
+ ok /^ultimatePlugin_\d+$/.test(plugin.cid)
14
+ ok plugin.$el.length is 1
15
+ jDiv = plugin.$('div')
16
+ ok jDiv.length is 1
17
+ ok jDiv.hasClass('test-plugin__inner')
18
+ strictEqual plugin.locale, 'en'
19
+ strictEqual plugin.t('smokeString'), 'Smoke string'
20
+
21
+
22
+
23
+ class TestPlugin extends Ultimate.Plugin
24
+ someOption: null
25
+ reflectableOptions: -> ['thirdOption']
26
+ @defaultLocales =
27
+ en:
28
+ someMessage: 'English message.'
29
+ ru:
30
+ someMessage: 'Сообщение на русском.'
31
+
32
+
33
+ test "TestPlugin", ->
34
+ cout 'warn', 'TestPlugin'
35
+ $('#qunit-fixture').html '<div class="test-plugin"><a class="action one" href="javascript:;">action one</a><div class="test-plugin__inner"></div></div>'
36
+ plugin = new TestPlugin
37
+ el: '.test-plugin'
38
+ someOption: 'bingo!'
39
+ otherOption: 'ringo!'
40
+ thirdOption: 'dingo!'
41
+ locale: 'de'
42
+
43
+ equal plugin.someOption, 'bingo!'
44
+ ok typeof plugin.otherOption is 'undefined'
45
+ equal plugin.thirdOption, 'dingo!'
46
+ equal plugin.locale, 'de'
47
+ deepEqual plugin.translations, {}
48
+ # equal plugin.t('someMessage'), 'Some message'
49
+ # plugin._configure locale: 'ru'
50
+ # deepEqual plugin.translations, {someMessage: 'Сообщение на русском.'}
51
+ # equal plugin.t('someMessage'), 'Сообщение на русском.'
52
+
53
+ #test "TestPlugin locale from I18n", ->
54
+ # cout 'warn', 'TestPlugin locale from I18n'
55
+ # window.I18n ||= {}
56
+ # _storedI18nLocale = I18n.locale
57
+ # cout '_storeI18nLocale', _storedI18nLocale
58
+ # I18n.locale = 'de'
59
+ # plugin = new TestPlugin el: '.test-plugin'
60
+ # strictEqual plugin.locale, 'en'
61
+ # equal plugin.t('someMessage'), 'English message.'
62
+ ## I18n.locale = 'ru'
63
+ ## plugin = new TestPlugin el: '.test-plugin'
64
+ ## strictEqual plugin.locale, 'ru'
65
+ ## equal plugin.t('someMessage'), 'Сообщение на русском.'
66
+ # I18n.locale = _storedI18nLocale
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ultimate-base
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2.1
4
+ version: 0.3.3.0
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-10-12 00:00:00.000000000 Z
12
+ date: 2012-10-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
16
- requirement: !ruby/object:Gem::Requirement
16
+ requirement: &21675360 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,15 +21,10 @@ dependencies:
21
21
  version: 3.2.8
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ~>
28
- - !ruby/object:Gem::Version
29
- version: 3.2.8
24
+ version_requirements: *21675360
30
25
  - !ruby/object:Gem::Dependency
31
26
  name: sqlite3
32
- requirement: !ruby/object:Gem::Requirement
27
+ requirement: &21672200 !ruby/object:Gem::Requirement
33
28
  none: false
34
29
  requirements:
35
30
  - - ! '>='
@@ -37,15 +32,10 @@ dependencies:
37
32
  version: '0'
38
33
  type: :development
39
34
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ! '>='
44
- - !ruby/object:Gem::Version
45
- version: '0'
35
+ version_requirements: *21672200
46
36
  - !ruby/object:Gem::Dependency
47
37
  name: coffee-rails
48
- requirement: !ruby/object:Gem::Requirement
38
+ requirement: &21669100 !ruby/object:Gem::Requirement
49
39
  none: false
50
40
  requirements:
51
41
  - - ~>
@@ -53,12 +43,7 @@ dependencies:
53
43
  version: 3.2.1
54
44
  type: :development
55
45
  prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ~>
60
- - !ruby/object:Gem::Version
61
- version: 3.2.1
46
+ version_requirements: *21669100
62
47
  description: Ultimate UI core, base helpers and improves for Ruby on Rails Front-end
63
48
  email:
64
49
  - koderfunk@gmail.com
@@ -194,6 +179,7 @@ files:
194
179
  - test/javascripts/tests/helpers_test.js.coffee
195
180
  - test/javascripts/tests/improves/i18n-lite_test.js.coffee
196
181
  - test/javascripts/tests/jquery-plugin-adapter_test.js.coffee
182
+ - test/javascripts/tests/jquery-plugin-class_test.js.coffee
197
183
  - test/javascripts/tests/underscore/underscore.outcasts.test.js.coffee
198
184
  - test/stylesheets/test_helper.css
199
185
  - ultimate-base.gemspec
@@ -217,7 +203,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
217
203
  version: '0'
218
204
  requirements: []
219
205
  rubyforge_project: ultimate-base
220
- rubygems_version: 1.8.24
206
+ rubygems_version: 1.8.10
221
207
  signing_key:
222
208
  specification_version: 3
223
209
  summary: Ultimate UI core, base helpers and improves for Ruby on Rails Front-end