ultimate-base 0.3.2.1 → 0.3.3.0

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/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