trestle 0.8.4 → 0.8.11

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.
Files changed (164) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +4 -0
  3. data/.travis.yml +14 -1
  4. data/Gemfile +6 -0
  5. data/README.md +15 -9
  6. data/app/assets/javascripts/trestle/admin.js +11 -10
  7. data/app/assets/javascripts/trestle/components/_confirmation.js +40 -0
  8. data/app/assets/javascripts/trestle/components/_datepicker.js +37 -0
  9. data/app/assets/javascripts/trestle/components/_dialog.js +136 -0
  10. data/app/assets/javascripts/trestle/{_errors.js → components/_errors.js} +2 -2
  11. data/app/assets/javascripts/trestle/components/_form.js +75 -0
  12. data/app/assets/javascripts/trestle/{_gallery.js → components/_gallery.js} +3 -3
  13. data/app/assets/javascripts/trestle/{_select.js → components/_select.js} +2 -2
  14. data/app/assets/javascripts/trestle/components/_sidebar.js +77 -0
  15. data/app/assets/javascripts/trestle/{_table.js → components/_table.js} +1 -1
  16. data/app/assets/javascripts/trestle/components/_tabs.js +25 -0
  17. data/app/assets/javascripts/trestle/components/_tooltips.js +19 -0
  18. data/app/assets/javascripts/trestle/core/_contexts.js +13 -0
  19. data/app/assets/javascripts/trestle/core/_cookies.js +24 -0
  20. data/app/assets/javascripts/trestle/core/_events.js +39 -0
  21. data/app/assets/javascripts/trestle/core/_l10n.js +23 -0
  22. data/app/assets/javascripts/trestle/core/_visit.js +10 -0
  23. data/app/assets/stylesheets/trestle/components/_alerts.scss +28 -0
  24. data/app/assets/stylesheets/trestle/components/_avatar.scss +23 -1
  25. data/app/assets/stylesheets/trestle/components/_breadcrumbs.scss +12 -0
  26. data/app/assets/stylesheets/trestle/components/_buttons.scss +111 -1
  27. data/app/assets/stylesheets/trestle/components/_content.scss +53 -21
  28. data/app/assets/stylesheets/trestle/components/_datepicker.scss +28 -0
  29. data/app/assets/stylesheets/trestle/components/_fields.scss +17 -0
  30. data/app/assets/stylesheets/trestle/components/_input-group.scss +26 -1
  31. data/app/assets/stylesheets/trestle/components/_modal.scss +108 -0
  32. data/app/assets/stylesheets/trestle/components/_navigation.scss +104 -14
  33. data/app/assets/stylesheets/trestle/components/_pagination.scss +3 -3
  34. data/app/assets/stylesheets/trestle/components/_scopes.scss +11 -2
  35. data/app/assets/stylesheets/trestle/components/_sidebar.scss +3 -2
  36. data/app/assets/stylesheets/trestle/components/_table.scss +34 -10
  37. data/app/assets/stylesheets/trestle/components/_tags.scss +9 -0
  38. data/app/assets/stylesheets/trestle/components/_timestamp.scss +4 -1
  39. data/app/assets/stylesheets/trestle/components/_toolbars.scss +55 -0
  40. data/app/assets/stylesheets/trestle/components/_wells.scss +9 -1
  41. data/app/assets/stylesheets/trestle/core/_defaults.scss +21 -6
  42. data/app/assets/stylesheets/trestle/core/_layout.scss +8 -0
  43. data/app/assets/stylesheets/trestle/core/_mixins.scss +11 -0
  44. data/app/assets/stylesheets/trestle/core/_typography.scss +39 -0
  45. data/app/controllers/concerns/trestle/controller/breadcrumbs.rb +21 -0
  46. data/app/controllers/concerns/trestle/controller/callbacks.rb +21 -0
  47. data/app/controllers/concerns/trestle/controller/dialog.rb +16 -0
  48. data/app/controllers/concerns/trestle/controller/helpers.rb +18 -0
  49. data/app/controllers/concerns/trestle/controller/layout.rb +16 -0
  50. data/app/controllers/concerns/trestle/controller/location.rb +15 -0
  51. data/app/controllers/trestle/application_controller.rb +6 -30
  52. data/app/helpers/trestle/avatar_helper.rb +9 -2
  53. data/app/helpers/trestle/flash_helper.rb +15 -0
  54. data/app/helpers/trestle/form_helper.rb +8 -5
  55. data/app/helpers/trestle/format_helper.rb +7 -3
  56. data/app/helpers/trestle/headings_helper.rb +27 -0
  57. data/app/helpers/trestle/hook_helper.rb +13 -4
  58. data/app/helpers/trestle/i18n_helper.rb +14 -0
  59. data/app/helpers/trestle/panel_helper.rb +24 -0
  60. data/app/helpers/trestle/tab_helper.rb +2 -2
  61. data/app/helpers/trestle/table_helper.rb +41 -2
  62. data/app/helpers/trestle/timestamp_helper.rb +49 -7
  63. data/app/helpers/trestle/toolbars_helper.rb +34 -0
  64. data/app/helpers/trestle/url_helper.rb +72 -8
  65. data/app/views/layouts/trestle/admin.html.erb +3 -5
  66. data/app/views/trestle/application/_dialog.html.erb +34 -0
  67. data/app/views/trestle/application/_header.html.erb +22 -20
  68. data/app/views/trestle/application/_layout.html.erb +1 -1
  69. data/app/views/trestle/application/_tabs.html.erb +8 -2
  70. data/app/views/trestle/{application → flash}/_alert.html.erb +7 -2
  71. data/app/views/trestle/flash/_debug.html.erb +8 -0
  72. data/app/views/trestle/flash/_flash.html.erb +7 -0
  73. data/app/views/trestle/resource/_scopes.html.erb +1 -1
  74. data/app/views/trestle/resource/edit.html.erb +8 -10
  75. data/app/views/trestle/resource/index.html.erb +16 -4
  76. data/app/views/trestle/resource/new.html.erb +6 -6
  77. data/app/views/trestle/resource/show.html.erb +8 -10
  78. data/app/views/trestle/shared/_sidebar.html.erb +10 -7
  79. data/app/views/trestle/shared/_title.html.erb +14 -0
  80. data/app/views/trestle/table/_table.html.erb +4 -6
  81. data/bower.json +1 -1
  82. data/config/locales/cs.rb +18 -0
  83. data/config/locales/cs.yml +95 -0
  84. data/config/locales/en.yml +65 -36
  85. data/config/locales/es-MX.yml +94 -0
  86. data/config/locales/es.yml +94 -0
  87. data/config/locales/fr.rb +18 -0
  88. data/config/locales/fr.yml +84 -0
  89. data/config/locales/lv.rb +18 -0
  90. data/config/locales/lv.yml +94 -0
  91. data/config/locales/nl.rb +18 -0
  92. data/config/locales/nl.yml +82 -0
  93. data/config/locales/pl.rb +18 -0
  94. data/config/locales/pl.yml +85 -0
  95. data/config/locales/pt-BR.rb +18 -0
  96. data/config/locales/pt-BR.yml +84 -0
  97. data/config/locales/zh-CN.rb +18 -0
  98. data/config/locales/zh-CN.yml +94 -0
  99. data/gemfiles/rails-4.2.gemfile +16 -0
  100. data/gemfiles/rails-5.0.gemfile +16 -0
  101. data/gemfiles/rails-5.1.gemfile +16 -0
  102. data/gemfiles/rails-5.2.gemfile +16 -0
  103. data/gemfiles/rails-edge.gemfile +17 -0
  104. data/lib/generators/trestle/install/templates/trestle.rb.erb +18 -2
  105. data/lib/generators/trestle/resource/templates/admin.rb.erb +2 -2
  106. data/lib/trestle/adapters/active_record_adapter.rb +2 -6
  107. data/lib/trestle/adapters/adapter.rb +40 -15
  108. data/lib/trestle/adapters/sequel_adapter.rb +2 -6
  109. data/lib/trestle/admin/builder.rb +42 -12
  110. data/lib/trestle/admin/controller.rb +3 -1
  111. data/lib/trestle/admin.rb +84 -3
  112. data/lib/trestle/breadcrumb.rb +16 -1
  113. data/lib/trestle/configurable.rb +6 -0
  114. data/lib/trestle/configuration.rb +28 -5
  115. data/lib/trestle/display.rb +1 -1
  116. data/lib/trestle/engine.rb +10 -4
  117. data/lib/trestle/form/automatic.rb +6 -3
  118. data/lib/trestle/form/builder.rb +5 -1
  119. data/lib/trestle/form/field.rb +1 -1
  120. data/lib/trestle/form/fields/date_picker.rb +2 -2
  121. data/lib/trestle/form/fields/form_control.rb +14 -4
  122. data/lib/trestle/form/fields/form_group.rb +14 -3
  123. data/lib/trestle/form/fields/select.rb +5 -1
  124. data/lib/trestle/form/fields/tag_select.rb +1 -1
  125. data/lib/trestle/form/renderer.rb +2 -2
  126. data/lib/trestle/form.rb +7 -3
  127. data/lib/trestle/hook.rb +27 -0
  128. data/lib/trestle/model_name.rb +64 -0
  129. data/lib/trestle/navigation/group.rb +16 -0
  130. data/lib/trestle/navigation/item.rb +11 -1
  131. data/lib/trestle/navigation.rb +24 -6
  132. data/lib/trestle/options.rb +7 -5
  133. data/lib/trestle/reloader.rb +1 -1
  134. data/lib/trestle/resource/adapter_methods.rb +62 -0
  135. data/lib/trestle/resource/builder.rb +43 -17
  136. data/lib/trestle/resource/collection.rb +68 -0
  137. data/lib/trestle/resource/controller.rb +70 -33
  138. data/lib/trestle/resource.rb +97 -105
  139. data/lib/trestle/scope.rb +13 -3
  140. data/lib/trestle/tab.rb +4 -0
  141. data/lib/trestle/table/actions_column.rb +41 -31
  142. data/lib/trestle/table/automatic.rb +1 -2
  143. data/lib/trestle/table/builder.rb +2 -2
  144. data/lib/trestle/table/column.rb +40 -9
  145. data/lib/trestle/table/row.rb +18 -2
  146. data/lib/trestle/table.rb +18 -2
  147. data/lib/trestle/toolbar/builder.rb +52 -0
  148. data/lib/trestle/toolbar/context.rb +39 -0
  149. data/lib/trestle/toolbar.rb +43 -0
  150. data/lib/trestle/version.rb +1 -1
  151. data/lib/trestle.rb +9 -4
  152. data/trestle.gemspec +5 -3
  153. data/vendor/assets/bower_components/trestle/select2/dist/js/select2.full.js +90 -69
  154. data/vendor/assets/javascripts/trestle/flatpickr.js.erb +2 -0
  155. data/vendor/assets/stylesheets/trestle/magnific-popup.scss +13 -1
  156. metadata +99 -22
  157. data/app/assets/javascripts/trestle/_confirmation.js +0 -23
  158. data/app/assets/javascripts/trestle/_datepicker.js +0 -22
  159. data/app/assets/javascripts/trestle/_form.js +0 -6
  160. data/app/assets/javascripts/trestle/_sidebar.js +0 -52
  161. data/app/assets/javascripts/trestle/_tabs.js +0 -13
  162. data/app/assets/javascripts/trestle/_tooltips.js +0 -3
  163. data/app/helpers/trestle/title_helper.rb +0 -26
  164. data/app/views/trestle/application/_flash.html.erb +0 -11
@@ -31,24 +31,47 @@ module Trestle
31
31
  def header
32
32
  if options[:header]
33
33
  options[:header]
34
- elsif admin = table.options[:admin]
35
- admin.human_attribute_name(field)
34
+ elsif table.admin
35
+ table.admin.t("table.headers.#{field}", default: table.admin.human_attribute_name(field))
36
36
  else
37
- field.to_s.humanize.titleize
37
+ I18n.t("admin.table.headers.#{field}", default: field.to_s.humanize.titleize)
38
38
  end
39
39
  end
40
40
 
41
41
  class Renderer
42
- delegate :options, to: :@column
42
+ delegate :options, :table, to: :@column
43
43
 
44
44
  def initialize(column, template)
45
45
  @column, @template = column, template
46
46
  end
47
47
 
48
+ def render(instance)
49
+ @template.content_tag(:td, content(instance), class: classes, data: data)
50
+ end
51
+
52
+ def render?
53
+ if options.key?(:if)
54
+ if options[:if].respond_to?(:call)
55
+ @template.instance_exec(&options[:if])
56
+ else
57
+ options[:if]
58
+ end
59
+ elsif options.key?(:unless)
60
+ if options[:unless].respond_to?(:call)
61
+ !@template.instance_exec(&options[:unless])
62
+ else
63
+ !options[:unless]
64
+ end
65
+ else
66
+ true
67
+ end
68
+ end
69
+
48
70
  def header
49
- return if options.has_key?(:header) && options[:header].in?([nil, false])
71
+ return if options.key?(:header) && options[:header].in?([nil, false])
50
72
 
51
- header = I18n.t("admin.table.headers.#{@column.field}", default: @column.header)
73
+ header = @column.header
74
+ header = @template.instance_exec(&header) if header.respond_to?(:call)
52
75
  header = @template.sort_link(header, @column.sort_field, @column.sort_options) if @column.sortable?
53
76
  header
54
77
  end
@@ -58,11 +81,12 @@ module Trestle
58
81
  content = @template.format_value(value, options)
59
82
 
60
83
  if value.respond_to?(:id) && options[:link] != false
84
+ # Column value was a model instance (e.g. from an association).
61
85
  # Automatically link to instance's admin if available
62
86
  content = @template.admin_link_to(content, value)
63
87
  elsif options[:link]
64
88
  # Explicitly link to the specified admin, or the table's admin
65
- content = @template.admin_link_to(content, instance, admin: options[:admin] || @column.table.options[:admin])
89
+ content = @template.admin_link_to(content, instance, admin: options[:admin] || table.admin)
66
90
  end
67
91
 
68
92
  content
@@ -86,10 +110,17 @@ module Trestle
86
110
  # evaluate the block using instance_exec, we need to set this up manually.
87
111
  -> {
88
112
  _hamlout = eval('_hamlout', @column.block.binding)
89
- @template.capture { @template.instance_exec(instance, &@column.block).to_s }
113
+ value = nil
114
+ buffer = @template.capture { value = @template.instance_exec(instance, &@column.block) }
115
+ value.is_a?(String) ? buffer : value
90
116
  }.call
91
117
  else
92
- @template.capture { @template.instance_exec(instance, &@column.block).to_s }
118
+ # Capture both the immediate value and captured output of the block.
119
+ # If the result of the block is a string, then use the contents of the buffer.
120
+ # Otherwise return the result of the block as a raw value (for auto-formatting).
121
+ value = nil
122
+ buffer = @template.capture { value = @template.instance_exec(instance, &@column.block) }
123
+ value.is_a?(String) ? buffer : value
93
124
  end
94
125
  else
95
126
  instance.send(@column.field)
@@ -19,17 +19,33 @@ module Trestle
19
19
  @row, @template = row, template
20
20
  end
21
21
 
22
+ def columns
23
+ table.columns.map { |column| column.renderer(@template) }.select(&:render?)
24
+ end
25
+
26
+ def render(instance)
27
+ @template.content_tag(:tr, options(instance)) do
28
+ @template.safe_join(columns.map { |column| column.render(instance) }, "\n")
29
+ end
30
+ end
31
+
22
32
  def options(instance)
23
33
  options = Trestle::Options.new
24
- options.merge!(data: { url: admin_url_for(instance) }) if table.options[:admin]
34
+
35
+ if table.admin && table.autolink? && table.admin.actions.include?(:show)
36
+ options.merge!(data: { url: admin_url_for(instance) })
37
+ options.merge!(data: { behavior: "dialog" }) if table.admin.form.dialog?
38
+ end
39
+
25
40
  options.merge!(@row.options)
26
41
  options.merge!(@template.instance_exec(instance, &@row.block)) if @row.block
42
+
27
43
  options
28
44
  end
29
45
 
30
46
  protected
31
47
  def admin_url_for(instance)
32
- @template.admin_url_for(instance, admin: table.options[:admin])
48
+ @template.admin_url_for(instance, admin: table.admin)
33
49
  end
34
50
  end
35
51
  end
data/lib/trestle/table.rb CHANGED
@@ -17,10 +17,22 @@ module Trestle
17
17
  @columns = []
18
18
  end
19
19
 
20
+ def admin
21
+ Trestle.lookup(options[:admin]) if options.key?(:admin)
22
+ end
23
+
20
24
  def sortable?
21
25
  options[:sortable] == true
22
26
  end
23
27
 
28
+ def autolink?
29
+ options[:autolink] != false
30
+ end
31
+
32
+ def header?
33
+ options[:header] != false
34
+ end
35
+
24
36
  def renderer(template)
25
37
  Renderer.new(self, template)
26
38
  end
@@ -30,7 +42,7 @@ module Trestle
30
42
  end
31
43
 
32
44
  class Renderer
33
- delegate :options, to: :@table
45
+ delegate :options, :header?, to: :@table
34
46
 
35
47
  def initialize(table, template)
36
48
  @table, @template = table, template
@@ -41,7 +53,11 @@ module Trestle
41
53
  end
42
54
 
43
55
  def columns
44
- @columns ||= @table.columns.map { |column| column.renderer(@template) }
56
+ @columns ||= row.columns
57
+ end
58
+
59
+ def id
60
+ options[:id]
45
61
  end
46
62
 
47
63
  def classes
@@ -0,0 +1,52 @@
1
+ module Trestle
2
+ class Toolbar
3
+ class Builder
4
+ def initialize(template)
5
+ @template = template
6
+ end
7
+
8
+ def button(content, options={})
9
+ options[:class] = button_classes_from_options(options)
10
+
11
+ button_tag(button_label(content, options), options)
12
+ end
13
+
14
+ def link(content, instance_or_url={}, options={})
15
+ options = instance_or_url if instance_or_url.is_a?(Hash)
16
+ options[:class] = button_classes_from_options(options)
17
+
18
+ admin_link_to(button_label(content, options), instance_or_url, options)
19
+ end
20
+
21
+ # Only methods explicitly tagged as builder methods will be automatically
22
+ # appended to the toolbar when called by Toolbar::Context.
23
+
24
+ class_attribute :builder_methods
25
+ self.builder_methods = []
26
+
27
+ def self.builder_method(*methods)
28
+ self.builder_methods += methods
29
+ end
30
+
31
+ builder_method :button, :link
32
+
33
+ private
34
+ delegate :admin_link_to, :button_tag, :content_tag, :safe_join, :icon, to: :@template
35
+
36
+ def button_classes_from_options(options)
37
+ classes = (options[:class] || "").split("\s")
38
+ classes.unshift("btn-#{options.delete(:style) || "default"}")
39
+ classes.unshift("btn") unless classes.include?("btn")
40
+ classes.push("has-icon") if options[:icon]
41
+ classes
42
+ end
43
+
44
+ def button_label(content, options)
45
+ icon = icon(options.delete(:icon)) if options[:icon]
46
+ label = content_tag(:span, content, class: "btn-label")
47
+
48
+ safe_join([icon, label].compact, " ")
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,39 @@
1
+ module Trestle
2
+ class Toolbar
3
+ # The toolbar Context is the object that is yielded to a toolbar block and handles the delegation of builder methods.
4
+ class Context
5
+ attr_reader :builder
6
+
7
+ def initialize(builder, enumerator, *args)
8
+ @builder, @enumerator = builder, enumerator
9
+ @args = args
10
+ end
11
+
12
+ def group
13
+ if @current_group
14
+ yield
15
+ else
16
+ @current_group = []
17
+ yield
18
+ @enumerator << @current_group
19
+ @current_group = nil
20
+ end
21
+ end
22
+
23
+ private
24
+ def respond_to_missing?(name, include_all=false)
25
+ builder.respond_to?(name) || super
26
+ end
27
+
28
+ def method_missing(name, *args, &block)
29
+ result = builder.send(name, *args, &block)
30
+
31
+ if builder.builder_methods.include?(name)
32
+ group { @current_group << result }
33
+ else
34
+ result
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,43 @@
1
+ module Trestle
2
+ class Toolbar
3
+ extend ActiveSupport::Autoload
4
+
5
+ autoload :Builder
6
+ autoload :Context
7
+
8
+ def initialize(builder=Builder)
9
+ @builder = builder
10
+ @blocks = []
11
+ end
12
+
13
+ def groups(template, *args)
14
+ Enumerator.new do |y|
15
+ @blocks.each do |block|
16
+ builder = @builder.new(template, *args)
17
+ block.evaluate(builder, template, y, *args)
18
+ end
19
+ end
20
+ end
21
+
22
+ def append(&block)
23
+ @blocks.push(Block.new(&block))
24
+ end
25
+
26
+ def prepend(&block)
27
+ @blocks.unshift(Block.new(&block))
28
+ end
29
+
30
+ # Wraps a toolbar block to provide evaluation within the context of a template and enumerator
31
+ class Block
32
+ def initialize(&block)
33
+ @block = block
34
+ end
35
+
36
+ def evaluate(builder, template, enumerator, *args)
37
+ context = Context.new(builder, enumerator, *args)
38
+ result = template.capture { template.instance_exec(context, *args, &@block) }
39
+ enumerator << [result] if result.present?
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,3 +1,3 @@
1
1
  module Trestle
2
- VERSION = "0.8.4"
2
+ VERSION = "0.8.11"
3
3
  end
data/lib/trestle.rb CHANGED
@@ -18,6 +18,8 @@ module Trestle
18
18
  autoload :Configuration
19
19
  autoload :Display
20
20
  autoload :Form
21
+ autoload :Hook
22
+ autoload :ModelName
21
23
  autoload :Navigation
22
24
  autoload :Options
23
25
  autoload :Reloader
@@ -25,17 +27,20 @@ module Trestle
25
27
  autoload :Scope
26
28
  autoload :Tab
27
29
  autoload :Table
30
+ autoload :Toolbar
28
31
 
29
32
  mattr_accessor :admins
30
33
  self.admins = {}
31
34
 
32
35
  def self.admin(name, options={}, &block)
33
- admin = Admin::Builder.build(name, options, &block)
34
- self.admins[admin.admin_name] = admin
36
+ register(Admin::Builder.create(name, options, &block))
35
37
  end
36
38
 
37
39
  def self.resource(name, options={}, &block)
38
- admin = Resource::Builder.build(name, options, &block)
40
+ register(Resource::Builder.create(name, options, &block))
41
+ end
42
+
43
+ def self.register(admin)
39
44
  self.admins[admin.admin_name] = admin
40
45
  end
41
46
 
@@ -53,7 +58,7 @@ module Trestle
53
58
  end
54
59
 
55
60
  def self.navigation
56
- Navigation.new(config.menus + admins.values.map(&:menu).compact)
61
+ Navigation.build(config.menus + admins.values.map(&:menu).compact)
57
62
  end
58
63
  end
59
64
 
data/trestle.gemspec CHANGED
@@ -34,14 +34,16 @@ Gem::Specification.new do |spec|
34
34
  spec.required_ruby_version = ">= 2.2.2"
35
35
 
36
36
  spec.add_dependency "railties", ">= 4.2.0"
37
- spec.add_dependency "sass-rails", "~> 5.0.6"
38
- spec.add_dependency "autoprefixer-rails", "~> 7.1.2"
39
- spec.add_dependency "kaminari", "~> 1.0.1"
37
+ spec.add_dependency "activemodel", ">= 4.2.0"
38
+ spec.add_dependency "sass-rails", ">= 5.0.6"
39
+ spec.add_dependency "autoprefixer-rails", ">= 7.1.2"
40
+ spec.add_dependency "kaminari", "~> 1.1.0"
40
41
 
41
42
  spec.add_development_dependency "bundler", "~> 1.12"
42
43
  spec.add_development_dependency "rake", "~> 10.0"
43
44
  spec.add_development_dependency "rspec-rails", "~> 3.5"
44
45
  spec.add_development_dependency "rspec-html-matchers", "~> 0.7.1"
46
+ spec.add_development_dependency "database_cleaner", "~> 1.6.2"
45
47
 
46
48
  spec.add_development_dependency "sqlite3"
47
49
  spec.add_development_dependency "turbolinks"
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Select2 4.0.3
2
+ * Select2 4.0.5
3
3
  * https://select2.github.io
4
4
  *
5
5
  * Released under the MIT license
@@ -9,19 +9,33 @@
9
9
  if (typeof define === 'function' && define.amd) {
10
10
  // AMD. Register as an anonymous module.
11
11
  define(['jquery'], factory);
12
- } else if (typeof exports === 'object') {
12
+ } else if (typeof module === 'object' && module.exports) {
13
13
  // Node/CommonJS
14
- factory(require('jquery'));
14
+ module.exports = function (root, jQuery) {
15
+ if (jQuery === undefined) {
16
+ // require('jQuery') returns a factory that requires window to
17
+ // build a jQuery instance, we normalize how we use modules
18
+ // that require this pattern but the window provided is a noop
19
+ // if it's defined (how jquery works)
20
+ if (typeof window !== 'undefined') {
21
+ jQuery = require('jquery');
22
+ }
23
+ else {
24
+ jQuery = require('jquery')(root);
25
+ }
26
+ }
27
+ factory(jQuery);
28
+ return jQuery;
29
+ };
15
30
  } else {
16
31
  // Browser globals
17
32
  factory(jQuery);
18
33
  }
19
- }(function (jQuery) {
34
+ } (function (jQuery) {
20
35
  // This is needed so we can catch the AMD loader configuration and use it
21
36
  // The inner file should be wrapped (by `banner.start.js`) in a function that
22
37
  // returns the AMD loader references.
23
- var S2 =
24
- (function () {
38
+ var S2 =(function () {
25
39
  // Restore the Select2 AMD loader so it can be used
26
40
  // Needed mostly in the language files, where the loader is not inserted
27
41
  if (jQuery && jQuery.fn && jQuery.fn.select2 && jQuery.fn.select2.amd) {
@@ -30,13 +44,11 @@
30
44
  var S2;(function () { if (!S2 || !S2.requirejs) {
31
45
  if (!S2) { S2 = {}; } else { require = S2; }
32
46
  /**
33
- * @license almond 0.3.1 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved.
34
- * Available via the MIT or new BSD license.
35
- * see: http://github.com/jrburke/almond for details
47
+ * @license almond 0.3.3 Copyright jQuery Foundation and other contributors.
48
+ * Released under MIT license, http://github.com/requirejs/almond/LICENSE
36
49
  */
37
50
  //Going sloppy to avoid 'use strict' string cost, but strict practices should
38
51
  //be followed.
39
- /*jslint sloppy: true */
40
52
  /*global setTimeout: false */
41
53
 
42
54
  var requirejs, require, define;
@@ -64,60 +76,58 @@ var requirejs, require, define;
64
76
  */
65
77
  function normalize(name, baseName) {
66
78
  var nameParts, nameSegment, mapValue, foundMap, lastIndex,
67
- foundI, foundStarMap, starI, i, j, part,
79
+ foundI, foundStarMap, starI, i, j, part, normalizedBaseParts,
68
80
  baseParts = baseName && baseName.split("/"),
69
81
  map = config.map,
70
82
  starMap = (map && map['*']) || {};
71
83
 
72
84
  //Adjust any relative paths.
73
- if (name && name.charAt(0) === ".") {
74
- //If have a base name, try to normalize against it,
75
- //otherwise, assume it is a top-level require that will
76
- //be relative to baseUrl in the end.
77
- if (baseName) {
78
- name = name.split('/');
79
- lastIndex = name.length - 1;
80
-
81
- // Node .js allowance:
82
- if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
83
- name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
84
- }
85
+ if (name) {
86
+ name = name.split('/');
87
+ lastIndex = name.length - 1;
88
+
89
+ // If wanting node ID compatibility, strip .js from end
90
+ // of IDs. Have to do this here, and not in nameToUrl
91
+ // because node allows either .js or non .js to map
92
+ // to same file.
93
+ if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
94
+ name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
95
+ }
85
96
 
86
- //Lop off the last part of baseParts, so that . matches the
87
- //"directory" and not name of the baseName's module. For instance,
88
- //baseName of "one/two/three", maps to "one/two/three.js", but we
89
- //want the directory, "one/two" for this normalization.
90
- name = baseParts.slice(0, baseParts.length - 1).concat(name);
91
-
92
- //start trimDots
93
- for (i = 0; i < name.length; i += 1) {
94
- part = name[i];
95
- if (part === ".") {
96
- name.splice(i, 1);
97
- i -= 1;
98
- } else if (part === "..") {
99
- if (i === 1 && (name[2] === '..' || name[0] === '..')) {
100
- //End of the line. Keep at least one non-dot
101
- //path segment at the front so it can be mapped
102
- //correctly to disk. Otherwise, there is likely
103
- //no path mapping for a path starting with '..'.
104
- //This can still fail, but catches the most reasonable
105
- //uses of ..
106
- break;
107
- } else if (i > 0) {
108
- name.splice(i - 1, 2);
109
- i -= 2;
110
- }
97
+ // Starts with a '.' so need the baseName
98
+ if (name[0].charAt(0) === '.' && baseParts) {
99
+ //Convert baseName to array, and lop off the last part,
100
+ //so that . matches that 'directory' and not name of the baseName's
101
+ //module. For instance, baseName of 'one/two/three', maps to
102
+ //'one/two/three.js', but we want the directory, 'one/two' for
103
+ //this normalization.
104
+ normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);
105
+ name = normalizedBaseParts.concat(name);
106
+ }
107
+
108
+ //start trimDots
109
+ for (i = 0; i < name.length; i++) {
110
+ part = name[i];
111
+ if (part === '.') {
112
+ name.splice(i, 1);
113
+ i -= 1;
114
+ } else if (part === '..') {
115
+ // If at the start, or previous value is still ..,
116
+ // keep them so that when converted to a path it may
117
+ // still work when converted to a path, even though
118
+ // as an ID it is less than ideal. In larger point
119
+ // releases, may be better to just kick out an error.
120
+ if (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') {
121
+ continue;
122
+ } else if (i > 0) {
123
+ name.splice(i - 1, 2);
124
+ i -= 2;
111
125
  }
112
126
  }
113
- //end trimDots
114
-
115
- name = name.join("/");
116
- } else if (name.indexOf('./') === 0) {
117
- // No baseName, so this is ID is resolved relative
118
- // to baseUrl, pull off the leading dot.
119
- name = name.substring(2);
120
127
  }
128
+ //end trimDots
129
+
130
+ name = name.join('/');
121
131
  }
122
132
 
123
133
  //Apply map config if available.
@@ -230,32 +240,39 @@ var requirejs, require, define;
230
240
  return [prefix, name];
231
241
  }
232
242
 
243
+ //Creates a parts array for a relName where first part is plugin ID,
244
+ //second part is resource ID. Assumes relName has already been normalized.
245
+ function makeRelParts(relName) {
246
+ return relName ? splitPrefix(relName) : [];
247
+ }
248
+
233
249
  /**
234
250
  * Makes a name map, normalizing the name, and using a plugin
235
251
  * for normalization if necessary. Grabs a ref to plugin
236
252
  * too, as an optimization.
237
253
  */
238
- makeMap = function (name, relName) {
254
+ makeMap = function (name, relParts) {
239
255
  var plugin,
240
256
  parts = splitPrefix(name),
241
- prefix = parts[0];
257
+ prefix = parts[0],
258
+ relResourceName = relParts[1];
242
259
 
243
260
  name = parts[1];
244
261
 
245
262
  if (prefix) {
246
- prefix = normalize(prefix, relName);
263
+ prefix = normalize(prefix, relResourceName);
247
264
  plugin = callDep(prefix);
248
265
  }
249
266
 
250
267
  //Normalize according
251
268
  if (prefix) {
252
269
  if (plugin && plugin.normalize) {
253
- name = plugin.normalize(name, makeNormalize(relName));
270
+ name = plugin.normalize(name, makeNormalize(relResourceName));
254
271
  } else {
255
- name = normalize(name, relName);
272
+ name = normalize(name, relResourceName);
256
273
  }
257
274
  } else {
258
- name = normalize(name, relName);
275
+ name = normalize(name, relResourceName);
259
276
  parts = splitPrefix(name);
260
277
  prefix = parts[0];
261
278
  name = parts[1];
@@ -302,13 +319,14 @@ var requirejs, require, define;
302
319
  };
303
320
 
304
321
  main = function (name, deps, callback, relName) {
305
- var cjsModule, depName, ret, map, i,
322
+ var cjsModule, depName, ret, map, i, relParts,
306
323
  args = [],
307
324
  callbackType = typeof callback,
308
325
  usingExports;
309
326
 
310
327
  //Use name if no relName
311
328
  relName = relName || name;
329
+ relParts = makeRelParts(relName);
312
330
 
313
331
  //Call the callback to define the module, if necessary.
314
332
  if (callbackType === 'undefined' || callbackType === 'function') {
@@ -317,7 +335,7 @@ var requirejs, require, define;
317
335
  //Default to [require, exports, module] if no deps
318
336
  deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
319
337
  for (i = 0; i < deps.length; i += 1) {
320
- map = makeMap(deps[i], relName);
338
+ map = makeMap(deps[i], relParts);
321
339
  depName = map.f;
322
340
 
323
341
  //Fast path CommonJS standard dependencies.
@@ -373,7 +391,7 @@ var requirejs, require, define;
373
391
  //deps arg is the module name, and second arg (if passed)
374
392
  //is just the relName.
375
393
  //Normalize module name, if it contains . or ..
376
- return callDep(makeMap(deps, callback).f);
394
+ return callDep(makeMap(deps, makeRelParts(callback)).f);
377
395
  } else if (!deps.splice) {
378
396
  //deps is a config object, not an array.
379
397
  config = deps;
@@ -1837,7 +1855,7 @@ S2.define('select2/selection/search',[
1837
1855
  var $search = $(
1838
1856
  '<li class="select2-search select2-search--inline">' +
1839
1857
  '<input class="select2-search__field" type="search" tabindex="-1"' +
1840
- ' autocomplete="off" autocorrect="off" autocapitalize="off"' +
1858
+ ' autocomplete="off" autocorrect="off" autocapitalize="none"' +
1841
1859
  ' spellcheck="false" role="textbox" aria-autocomplete="list" />' +
1842
1860
  '</li>'
1843
1861
  );
@@ -3191,7 +3209,7 @@ S2.define('select2/data/select',[
3191
3209
  }
3192
3210
  }
3193
3211
 
3194
- if (data.id) {
3212
+ if (data.id !== undefined) {
3195
3213
  option.value = data.id;
3196
3214
  }
3197
3215
 
@@ -3550,7 +3568,10 @@ S2.define('select2/data/tags',[
3550
3568
  }, true)
3551
3569
  );
3552
3570
 
3553
- var checkText = option.text === params.term;
3571
+ var optionText = (option.text || '').toUpperCase();
3572
+ var paramsTerm = (params.term || '').toUpperCase();
3573
+
3574
+ var checkText = optionText === paramsTerm;
3554
3575
 
3555
3576
  if (checkText || checkChildren) {
3556
3577
  if (child) {
@@ -3888,7 +3909,7 @@ S2.define('select2/dropdown/search',[
3888
3909
  var $search = $(
3889
3910
  '<span class="select2-search select2-search--dropdown">' +
3890
3911
  '<input class="select2-search__field" type="search" tabindex="-1"' +
3891
- ' autocomplete="off" autocorrect="off" autocapitalize="off"' +
3912
+ ' autocomplete="off" autocorrect="off" autocapitalize="none"' +
3892
3913
  ' spellcheck="false" role="textbox" />' +
3893
3914
  '</span>'
3894
3915
  );
@@ -3941,7 +3962,7 @@ S2.define('select2/dropdown/search',[
3941
3962
  });
3942
3963
 
3943
3964
  container.on('focus', function () {
3944
- if (container.isOpen()) {
3965
+ if (!container.isOpen()) {
3945
3966
  self.$search.focus();
3946
3967
  }
3947
3968
  });