para 0.6.9 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/images/para/admin/tangram-mosaic.png +0 -0
- data/app/assets/images/para/admin/template-section.svg +23 -0
- data/app/assets/javascripts/para/admin.coffee +20 -0
- data/app/assets/javascripts/para/admin/tabs.coffee +22 -5
- data/app/assets/javascripts/para/admin/theme_actions.coffee +3 -3
- data/app/assets/javascripts/para/inputs/material-input.coffee +4 -0
- data/app/assets/javascripts/para/inputs/multi-select-input.coffee +173 -0
- data/app/assets/javascripts/para/inputs/nested_many.coffee +9 -9
- data/app/assets/stylesheets/para/admin.sass +5 -5
- data/app/assets/stylesheets/para/admin/main.sass +32 -0
- data/app/assets/stylesheets/para/admin/src/_alert.sass +17 -0
- data/app/assets/stylesheets/para/admin/src/_base.sass +51 -0
- data/app/assets/stylesheets/para/admin/src/_bootstrap-variables.scss +874 -0
- data/app/assets/stylesheets/para/admin/src/_breadcrumb.sass +22 -0
- data/app/assets/stylesheets/para/admin/src/_buttons.sass +107 -0
- data/app/assets/stylesheets/para/admin/src/_checkable.sass +94 -0
- data/app/assets/stylesheets/para/admin/src/_common.sass +203 -0
- data/app/assets/stylesheets/para/admin/src/_dropdown.sass +40 -0
- data/app/assets/stylesheets/para/admin/src/_form.sass +271 -0
- data/app/assets/stylesheets/para/admin/src/_list.sass +61 -0
- data/app/assets/stylesheets/para/admin/src/_mixins.sass +113 -0
- data/app/assets/stylesheets/para/admin/src/_multi-select.sass +91 -0
- data/app/assets/stylesheets/para/admin/src/_navigation.sass +150 -0
- data/app/assets/stylesheets/para/admin/src/_navtabs.sass +41 -0
- data/app/assets/stylesheets/para/admin/src/_nested-many.sass +69 -0
- data/app/assets/stylesheets/para/admin/src/_nested_one.sass +13 -0
- data/app/assets/stylesheets/para/admin/src/_orderable.sass +44 -0
- data/app/assets/stylesheets/para/admin/src/_page-loading.sass +39 -0
- data/app/assets/stylesheets/para/admin/src/_pagination.sass +34 -0
- data/app/assets/stylesheets/para/admin/src/_panel.sass +55 -0
- data/app/assets/stylesheets/para/admin/src/_responsive.sass +100 -0
- data/app/assets/stylesheets/para/admin/{theme → src}/_sorting.sass +11 -3
- data/app/assets/stylesheets/para/admin/src/_statcard.sass +41 -0
- data/app/assets/stylesheets/para/admin/src/_table.sass +33 -0
- data/app/assets/stylesheets/para/admin/src/_tree.sass +52 -0
- data/app/assets/stylesheets/para/admin/src/_variables.sass +37 -0
- data/app/assets/stylesheets/para/admin/src/_well.sass +12 -0
- data/app/assets/stylesheets/para/{admin/src → lib}/datetimepicker.sass +1 -3
- data/app/assets/stylesheets/para/{admin/src → lib}/fuelux.sass +3 -5
- data/app/assets/stylesheets/para/lib/jasny-bootstrap.sass +97 -0
- data/app/assets/stylesheets/para/{admin/src → lib}/redactor.sass +2 -5
- data/app/assets/stylesheets/para/lib/selectize.sass +112 -0
- data/app/assets/stylesheets/para/lib/slider.sass +12 -0
- data/app/controllers/concerns/para/admin/resource_controller_concerns.rb +14 -2
- data/app/controllers/para/admin/base_controller.rb +7 -0
- data/app/controllers/para/admin/crud_resources_controller.rb +13 -6
- data/app/controllers/para/admin/form_resources_controller.rb +5 -3
- data/app/controllers/para/admin/resources_controller.rb +9 -3
- data/app/controllers/para/admin/search_controller.rb +15 -0
- data/app/controllers/para/application_controller.rb +10 -2
- data/app/helpers/para/admin/page_helper.rb +9 -9
- data/app/helpers/para/application_helper.rb +1 -10
- data/app/helpers/para/form_helper.rb +5 -6
- data/app/helpers/para/model_helper.rb +13 -3
- data/app/helpers/para/ordering_helper.rb +1 -1
- data/app/helpers/para/search_results_helper.rb +16 -0
- data/app/helpers/para/tree_helper.rb +10 -6
- data/app/models/para/page.rb +5 -0
- data/app/models/para/page/section.rb +42 -0
- data/app/models/para/page/section_resource.rb +12 -0
- data/app/views/layouts/para/admin.html.haml +5 -8
- data/app/views/para/admin/dashboard.html.haml +21 -8
- data/app/views/para/admin/form_resources/show.html.haml +1 -1
- data/app/views/para/admin/imports/new.html.haml +2 -2
- data/app/views/para/admin/resources/_actions.html.haml +3 -3
- data/app/views/para/admin/resources/_add_button.html.haml +1 -1
- data/app/views/para/admin/resources/_exports_menu.html.haml +6 -6
- data/app/views/para/admin/resources/_filters.html.haml +7 -8
- data/app/views/para/admin/resources/_imports_menu.html.haml +6 -6
- data/app/views/para/admin/resources/_list.html.haml +14 -15
- data/app/views/para/admin/resources/_per_page_select.html.haml +4 -3
- data/app/views/para/admin/resources/_subclassable_add_button.html.haml +3 -3
- data/app/views/para/admin/resources/_tree.html.haml +7 -9
- data/app/views/para/admin/resources/_tree_item.html.haml +5 -6
- data/app/views/para/admin/resources/edit.html.haml +1 -1
- data/app/views/para/admin/resources/new.html.haml +1 -1
- data/app/views/para/admin/search/_result.html.haml +7 -0
- data/app/views/para/admin/search/index.html.haml +1 -0
- data/app/views/para/admin/settings_component/show.html.haml +1 -1
- data/app/views/para/admin/shared/_breadcrumbs.html.haml +2 -3
- data/app/views/para/admin/shared/_header.html.haml +16 -27
- data/app/views/para/admin/shared/_navigation.html.haml +20 -19
- data/app/views/para/form/_tabs.html.haml +6 -7
- data/app/views/para/inputs/_multi_select.html.haml +40 -0
- data/app/views/para/inputs/_nested_many.html.haml +4 -4
- data/app/views/para/inputs/multi_select/_no_items.html.haml +6 -0
- data/app/views/para/inputs/nested_many/_add.html.haml +1 -2
- data/app/views/para/inputs/nested_many/_add_with_subclasses.html.haml +4 -5
- data/app/views/para/inputs/nested_many/_container.html.haml +7 -8
- data/app/views/shared/_breadcrumbs.html.haml +4 -0
- data/config/locales/fr.yml +29 -4
- data/db/migrate/20170324125547_create_para_page_section_resources.rb +15 -0
- data/lib/generators/para/filters/templates/_filters.html.haml +3 -5
- data/lib/generators/para/install/templates/initializer.rb +12 -0
- data/lib/generators/para/page/section/section_generator.rb +13 -2
- data/lib/generators/para/page/section/templates/section.html.haml.erb +3 -0
- data/lib/generators/para/resource/resource_generator.rb +1 -1
- data/lib/para.rb +25 -21
- data/lib/para/attribute_field.rb +2 -0
- data/lib/para/attribute_field/base.rb +1 -1
- data/lib/para/attribute_field/belongs_to.rb +1 -1
- data/lib/para/attribute_field/boolean.rb +1 -1
- data/lib/para/attribute_field/friendly_id.rb +19 -0
- data/lib/para/attribute_field/has_many.rb +43 -4
- data/lib/para/attribute_field/nested_field.rb +46 -0
- data/lib/para/attribute_field/nested_many.rb +30 -9
- data/lib/para/attribute_field/nested_one.rb +28 -9
- data/lib/para/attribute_field/password.rb +1 -1
- data/lib/para/attribute_field/relation.rb +19 -1
- data/lib/para/attribute_field_mappings.rb +9 -3
- data/lib/para/breadcrumbs/breadcrumb.rb +57 -10
- data/lib/para/breadcrumbs/controller.rb +19 -6
- data/lib/para/breadcrumbs/manager.rb +9 -1
- data/lib/para/config.rb +3 -0
- data/lib/para/controller_resource.rb +34 -0
- data/lib/para/engine.rb +33 -14
- data/lib/para/exporter/base.rb +1 -1
- data/lib/para/ext.rb +1 -1
- data/lib/para/ext/active_record_nested_attributes.rb +51 -0
- data/lib/para/ext/paperclip.rb +2 -6
- data/lib/para/form_builder.rb +3 -0
- data/lib/para/form_builder/attributes_mappings_tracker.rb +45 -0
- data/lib/para/form_builder/containers.rb +13 -17
- data/lib/para/form_builder/nested_form.rb +2 -3
- data/lib/para/helpers.rb +8 -0
- data/lib/para/helpers/attributes_mappings.rb +13 -0
- data/lib/para/helpers/resource_name.rb +14 -0
- data/lib/para/inputs.rb +1 -0
- data/lib/para/inputs/multi_select_input.rb +90 -0
- data/lib/para/inputs/nested_many_input.rb +6 -1
- data/lib/para/markup/resources_table.rb +15 -11
- data/lib/para/model_field_parsers.rb +3 -2
- data/lib/para/model_field_parsers/base.rb +7 -2
- data/lib/para/model_field_parsers/friendly_id.rb +19 -0
- data/lib/para/model_field_parsers/relations.rb +20 -1
- data/lib/para/page/model.rb +3 -1
- data/lib/para/routes.rb +1 -0
- data/lib/para/simple_form_config.rb +85 -0
- data/lib/para/version.rb +1 -1
- data/lib/rails/routing_mapper.rb +5 -8
- data/vendor/assets/javascripts/jasny-bootstrap.js +577 -0
- data/vendor/assets/stylesheets/animate.css +3340 -0
- data/vendor/assets/stylesheets/hint.css +649 -0
- data/vendor/assets/stylesheets/jasny-bootstrap.css +287 -0
- metadata +114 -67
- data/app/assets/images/para/admin/bg.png +0 -0
- data/app/assets/javascripts/para/admin.js +0 -20
- data/app/assets/stylesheets/admin/theme.sass +0 -0
- data/app/assets/stylesheets/para/admin/src/jasny.bootstrap.sass +0 -40
- data/app/assets/stylesheets/para/admin/src/nested_many.sass +0 -5
- data/app/assets/stylesheets/para/admin/src/page-loading.sass +0 -24
- data/app/assets/stylesheets/para/admin/src/page-top-bar.sass +0 -9
- data/app/assets/stylesheets/para/admin/src/selectize.sass +0 -46
- data/app/assets/stylesheets/para/admin/src/slider.sass +0 -12
- data/app/assets/stylesheets/para/admin/theme.sass +0 -22
- data/app/assets/stylesheets/para/admin/theme/_base.sass +0 -176
- data/app/assets/stylesheets/para/admin/theme/_breadcrumb.sass +0 -75
- data/app/assets/stylesheets/para/admin/theme/_buttons.sass +0 -27
- data/app/assets/stylesheets/para/admin/theme/_checkable.sass +0 -108
- data/app/assets/stylesheets/para/admin/theme/_commonds.sass +0 -210
- data/app/assets/stylesheets/para/admin/theme/_dropdown.sass +0 -52
- data/app/assets/stylesheets/para/admin/theme/_form.sass +0 -150
- data/app/assets/stylesheets/para/admin/theme/_list.sass +0 -139
- data/app/assets/stylesheets/para/admin/theme/_navigation.sass +0 -229
- data/app/assets/stylesheets/para/admin/theme/_navtabs.sass +0 -151
- data/app/assets/stylesheets/para/admin/theme/_orderable.sass +0 -45
- data/app/assets/stylesheets/para/admin/theme/_panel.sass +0 -264
- data/app/assets/stylesheets/para/admin/theme/_responsive.sass +0 -123
- data/app/assets/stylesheets/para/admin/theme/_table.sass +0 -28
- data/app/assets/stylesheets/para/admin/theme/_tree.sass +0 -74
- data/app/assets/stylesheets/para/admin/theme/_variables.sass +0 -31
- data/app/assets/stylesheets/para/application.css +0 -15
- data/app/assets/stylesheets/para/lib/_variables.scss +0 -646
- data/app/assets/stylesheets/para/overrides/responsive.sass +0 -62
- data/app/assets/stylesheets/para/overrides/theme.sass +0 -172
- data/lib/para/ext/cancan.rb +0 -26
- data/vendor/assets/javascripts/jasny.bootstrap.min.js +0 -7
- data/vendor/assets/stylesheets/animate.min.css +0 -6
- data/vendor/assets/stylesheets/jasny.bootstrap.min.css +0 -7
@@ -27,7 +27,8 @@ module Para
|
|
27
27
|
resources: resources,
|
28
28
|
nested_locals: locals,
|
29
29
|
subclass: subclass,
|
30
|
-
subclasses: subclasses
|
30
|
+
subclasses: subclasses,
|
31
|
+
inset: inset?
|
31
32
|
}
|
32
33
|
)
|
33
34
|
end
|
@@ -59,6 +60,10 @@ module Para
|
|
59
60
|
(model.try(:descendants) || []).sort_by { |m| m.model_name.human }
|
60
61
|
)
|
61
62
|
end
|
63
|
+
|
64
|
+
def inset?
|
65
|
+
options.fetch(:inset, false)
|
66
|
+
end
|
62
67
|
end
|
63
68
|
end
|
64
69
|
end
|
@@ -44,7 +44,7 @@ module Para
|
|
44
44
|
# Append cells
|
45
45
|
cells << capture { block.call }
|
46
46
|
# Append actions empty cell
|
47
|
-
cells << content_tag(:th, '', class: 'actions'
|
47
|
+
cells << content_tag(:th, '', class: 'table-row-actions') if actions
|
48
48
|
|
49
49
|
# Output full header
|
50
50
|
content_tag(:thead) do
|
@@ -131,12 +131,10 @@ module Para
|
|
131
131
|
end
|
132
132
|
|
133
133
|
def actions_cell(resource)
|
134
|
-
content_tag(:td) do
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
end.compact.join.html_safe
|
139
|
-
end
|
134
|
+
content_tag(:td, class: 'table-row-actions') do
|
135
|
+
actions.map do |type|
|
136
|
+
send(:"#{ type }_button", resource)
|
137
|
+
end.compact.join.html_safe
|
140
138
|
end
|
141
139
|
end
|
142
140
|
|
@@ -149,7 +147,10 @@ module Para
|
|
149
147
|
|
150
148
|
options = {
|
151
149
|
method: :post,
|
152
|
-
class: 'btn btn-info'
|
150
|
+
class: 'btn btn-sm btn-icon-info btn-shadow hint--left',
|
151
|
+
aria: {
|
152
|
+
label: ::I18n.t('para.shared.copy')
|
153
|
+
}
|
153
154
|
}
|
154
155
|
|
155
156
|
view.link_to(path, options) do
|
@@ -162,7 +163,7 @@ module Para
|
|
162
163
|
resource, action: :edit, return_to: view.request.fullpath
|
163
164
|
)
|
164
165
|
|
165
|
-
view.link_to(path, class: 'btn btn-primary') do
|
166
|
+
view.link_to(path, class: 'btn btn-sm btn-icon-primary btn-shadow hint--left', aria: { label: ::I18n.t('para.shared.edit') }) do
|
166
167
|
content_tag(:i, '', class: 'fa fa-pencil')
|
167
168
|
end
|
168
169
|
end
|
@@ -175,11 +176,14 @@ module Para
|
|
175
176
|
data: {
|
176
177
|
confirm: ::I18n.t('para.list.delete_confirmation')
|
177
178
|
},
|
178
|
-
class: 'btn btn-danger'
|
179
|
+
class: 'btn btn-sm btn-icon-danger btn-shadow hint--left',
|
180
|
+
aria: {
|
181
|
+
label: ::I18n.t('para.shared.destroy')
|
182
|
+
}
|
179
183
|
}
|
180
184
|
|
181
185
|
view.link_to(path, options) do
|
182
|
-
content_tag(:i, '', class: 'fa fa-
|
186
|
+
content_tag(:i, '', class: 'fa fa-times')
|
183
187
|
end
|
184
188
|
end
|
185
189
|
|
@@ -4,9 +4,9 @@ module Para
|
|
4
4
|
@registered_parsers ||= {}
|
5
5
|
end
|
6
6
|
|
7
|
-
def self.parse!(model, fields_hash)
|
7
|
+
def self.parse!(model, fields_hash, mappings)
|
8
8
|
registered_parsers.each do |_, parser_class|
|
9
|
-
parser = parser_class.new(model, fields_hash)
|
9
|
+
parser = parser_class.new(model, fields_hash, mappings)
|
10
10
|
parser.parse! if parser.applicable?
|
11
11
|
end
|
12
12
|
end
|
@@ -20,6 +20,7 @@ require 'para/model_field_parsers/orderable'
|
|
20
20
|
require 'para/model_field_parsers/relations'
|
21
21
|
require 'para/model_field_parsers/redactor'
|
22
22
|
require 'para/model_field_parsers/globalize'
|
23
|
+
require 'para/model_field_parsers/friendly_id'
|
23
24
|
require 'para/model_field_parsers/store'
|
24
25
|
require 'para/model_field_parsers/enums'
|
25
26
|
require 'para/model_field_parsers/closure_tree'
|
@@ -5,16 +5,21 @@ module Para
|
|
5
5
|
ModelFieldParsers.registered_parsers[key] = parser
|
6
6
|
end
|
7
7
|
|
8
|
-
attr_reader :model, :fields_hash
|
8
|
+
attr_reader :model, :fields_hash, :mappings
|
9
9
|
|
10
|
-
def initialize(model, fields_hash)
|
10
|
+
def initialize(model, fields_hash, mappings)
|
11
11
|
@model = model
|
12
12
|
@fields_hash = fields_hash
|
13
|
+
@mappings = mappings
|
13
14
|
end
|
14
15
|
|
15
16
|
def applicable?
|
16
17
|
true
|
17
18
|
end
|
19
|
+
|
20
|
+
def find_attributes_for_mapping(type)
|
21
|
+
mappings.select { |k, v| v == type.to_s }.keys.map(&:to_sym)
|
22
|
+
end
|
18
23
|
end
|
19
24
|
end
|
20
25
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Para
|
2
|
+
module ModelFieldParsers
|
3
|
+
class FriendlyId < Para::ModelFieldParsers::Base
|
4
|
+
register :friendly_id, self
|
5
|
+
|
6
|
+
def parse!
|
7
|
+
key = model.friendly_id_config.slug_column
|
8
|
+
|
9
|
+
fields_hash[key] = AttributeField::FriendlyId.new(
|
10
|
+
model, name: key, type: 'friendly_id'
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def applicable?
|
15
|
+
!!model.try(:friendly_id_config)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -4,6 +4,20 @@ module Para
|
|
4
4
|
register :relations, self
|
5
5
|
|
6
6
|
def parse!
|
7
|
+
# Catch multi select inputs from form attributes mappings
|
8
|
+
find_attributes_for_mapping(:multi_select).each do |attribute|
|
9
|
+
fields_hash[attribute] = AttributeField::HasManyField.new(
|
10
|
+
model, name: attribute, type: 'has_many', field_type: 'multi_select'
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Catch multi select inputs from form attributes mappings
|
15
|
+
find_attributes_for_mapping(:nested_many).each do |attribute|
|
16
|
+
fields_hash[attribute] = AttributeField::NestedManyField.new(
|
17
|
+
model, name: attribute, type: 'has_many', field_type: 'nested_many'
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
7
21
|
model.reflections.each do |name, reflection|
|
8
22
|
# We ensure that name is a symbol and not a string for 4.2+
|
9
23
|
# versions of AR
|
@@ -11,11 +25,16 @@ module Para
|
|
11
25
|
# `fields_hash` is already a `HashWithIndifferentAccess`
|
12
26
|
name = name.to_sym
|
13
27
|
|
28
|
+
# Do not process component relations
|
14
29
|
next if name == :component
|
30
|
+
# Do not reprocess attributes that were already catched with
|
31
|
+
# attributes mappings above
|
32
|
+
next if AttributeField::RelationField == fields_hash[name]
|
15
33
|
|
16
34
|
# Remove foreign key, if existing, from fields
|
17
35
|
fields_hash.delete(reflection.foreign_key.to_s)
|
18
36
|
|
37
|
+
# Do not process polymorphic belongs to for now ...
|
19
38
|
if reflection.options[:polymorphic] == true
|
20
39
|
fields_hash.delete(reflection.foreign_type.to_s)
|
21
40
|
next
|
@@ -36,7 +55,7 @@ module Para
|
|
36
55
|
remove_counter_cache_column!(name, reflection)
|
37
56
|
|
38
57
|
fields_hash[name] = AttributeField::HasManyField.new(
|
39
|
-
model, name: name, type: 'has_many', field_type: '
|
58
|
+
model, name: name, type: 'has_many', field_type: 'multi_select'
|
40
59
|
)
|
41
60
|
elsif !reflection.options[:through]
|
42
61
|
fields_hash[name] = AttributeField::BelongsToField.new(
|
data/lib/para/page/model.rb
CHANGED
@@ -4,7 +4,9 @@ module Para
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
7
|
-
has_many :sections, -> { ordered }, class_name: '::Para::Page::Section',
|
7
|
+
has_many :sections, -> { ordered }, class_name: '::Para::Page::Section',
|
8
|
+
as: :page,
|
9
|
+
dependent: :destroy
|
8
10
|
accepts_nested_attributes_for :sections, allow_destroy: true
|
9
11
|
end
|
10
12
|
end
|
data/lib/para/routes.rb
CHANGED
@@ -0,0 +1,85 @@
|
|
1
|
+
# Default simple form bootstrap initializer mechanism
|
2
|
+
module Para
|
3
|
+
module SimpleFormConfig
|
4
|
+
def self.wrapper_mappings
|
5
|
+
{
|
6
|
+
check_boxes: :para_vertical_radio_and_checkboxes,
|
7
|
+
radio_buttons: :para_vertical_radio_and_checkboxes,
|
8
|
+
boolean: :para_vertical_radio_and_checkboxes,
|
9
|
+
datetime: :para_multi_select,
|
10
|
+
date: :para_multi_select,
|
11
|
+
time: :para_multi_select,
|
12
|
+
file: :para_vertical_file_input
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.configure
|
17
|
+
# Use this setup block to configure all options available in SimpleForm.
|
18
|
+
SimpleForm.setup do |config|
|
19
|
+
config.error_notification_class = 'alert alert-danger'
|
20
|
+
config.button_class = 'btn'
|
21
|
+
config.boolean_label_class = nil
|
22
|
+
|
23
|
+
config.wrappers :para_vertical_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
|
24
|
+
b.use :html5
|
25
|
+
b.use :placeholder
|
26
|
+
b.optional :maxlength
|
27
|
+
b.optional :minlength
|
28
|
+
b.optional :pattern
|
29
|
+
b.optional :min_max
|
30
|
+
b.optional :readonly
|
31
|
+
b.use :label, class: 'control-label'
|
32
|
+
|
33
|
+
b.use :input, class: 'form-control'
|
34
|
+
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
35
|
+
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
36
|
+
end
|
37
|
+
|
38
|
+
config.wrappers :para_vertical_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
|
39
|
+
b.use :html5
|
40
|
+
b.use :placeholder
|
41
|
+
b.optional :maxlength
|
42
|
+
b.optional :minlength
|
43
|
+
b.optional :readonly
|
44
|
+
b.use :label, class: 'control-label'
|
45
|
+
|
46
|
+
b.use :input
|
47
|
+
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
48
|
+
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
49
|
+
end
|
50
|
+
|
51
|
+
config.wrappers :para_vertical_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
|
52
|
+
b.use :html5
|
53
|
+
b.optional :readonly
|
54
|
+
|
55
|
+
b.wrapper tag: 'div', class: 'checkbox' do |ba|
|
56
|
+
ba.use :label_input
|
57
|
+
end
|
58
|
+
|
59
|
+
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
60
|
+
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
61
|
+
end
|
62
|
+
|
63
|
+
config.wrappers :para_vertical_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
|
64
|
+
b.use :html5
|
65
|
+
b.optional :readonly
|
66
|
+
b.use :label, class: 'control-label'
|
67
|
+
b.use :input
|
68
|
+
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
69
|
+
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
70
|
+
end
|
71
|
+
|
72
|
+
config.wrappers :para_multi_select, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
|
73
|
+
b.use :html5
|
74
|
+
b.optional :readonly
|
75
|
+
b.use :label, class: 'control-label'
|
76
|
+
b.wrapper tag: 'div', class: 'form-inline' do |ba|
|
77
|
+
ba.use :input, class: 'form-control'
|
78
|
+
ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
79
|
+
ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/lib/para/version.rb
CHANGED
data/lib/rails/routing_mapper.rb
CHANGED
@@ -15,16 +15,14 @@ module ActionDispatch
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def component(component_name, options = {}, &block)
|
18
|
-
as,
|
18
|
+
as, component, endpoint = component_informations_from(
|
19
19
|
component_name, options
|
20
20
|
)
|
21
21
|
|
22
|
-
|
23
|
-
|
22
|
+
controller = options.fetch(:controller, "#{ component_name }_component")
|
24
23
|
imports_controller = options.fetch(:imports_controller, '/para/admin/imports')
|
25
24
|
exports_controller = options.fetch(:exports_controller, '/para/admin/exports')
|
26
25
|
|
27
|
-
|
28
26
|
constraints Para::Routing::ComponentNameConstraint.new(component) do
|
29
27
|
namespace :admin do
|
30
28
|
defaults(component: component) do
|
@@ -54,7 +52,7 @@ module ActionDispatch
|
|
54
52
|
options[:scope] ||= ':model'
|
55
53
|
end
|
56
54
|
|
57
|
-
as,
|
55
|
+
as, component, endpoint = component_informations_from(
|
58
56
|
component_name, options
|
59
57
|
)
|
60
58
|
|
@@ -105,7 +103,7 @@ module ActionDispatch
|
|
105
103
|
options[:scope] ||= ':model'
|
106
104
|
end
|
107
105
|
|
108
|
-
as,
|
106
|
+
as, component, endpoint = component_informations_from(
|
109
107
|
component_name, options
|
110
108
|
)
|
111
109
|
|
@@ -151,10 +149,9 @@ module ActionDispatch
|
|
151
149
|
def component_informations_from(component_name, options)
|
152
150
|
component = options.fetch(:component, component_name.to_s)
|
153
151
|
as = options.fetch(:as, component_name)
|
154
|
-
controller = options.fetch(:controller, "#{ component_name }_component")
|
155
152
|
endpoint = ":component/:component_id"
|
156
153
|
|
157
|
-
[as,
|
154
|
+
[as, component, endpoint]
|
158
155
|
end
|
159
156
|
|
160
157
|
def add_extensions_for(type)
|
@@ -0,0 +1,577 @@
|
|
1
|
+
/*!
|
2
|
+
* Jasny Bootstrap v3.1.3 (http://jasny.github.io/bootstrap)
|
3
|
+
* Copyright 2012-2014 Arnold Daniels
|
4
|
+
* Licensed under Apache-2.0 (https://github.com/jasny/bootstrap/blob/master/LICENSE)
|
5
|
+
*/
|
6
|
+
|
7
|
+
if (typeof jQuery === 'undefined') { throw new Error('Jasny Bootstrap\'s JavaScript requires jQuery') }
|
8
|
+
|
9
|
+
/* ========================================================================
|
10
|
+
* Bootstrap: transition.js v3.1.3
|
11
|
+
* http://getbootstrap.com/javascript/#transitions
|
12
|
+
* ========================================================================
|
13
|
+
* Copyright 2011-2014 Twitter, Inc.
|
14
|
+
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
15
|
+
* ======================================================================== */
|
16
|
+
|
17
|
+
|
18
|
+
+function ($) {
|
19
|
+
'use strict';
|
20
|
+
|
21
|
+
// CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
|
22
|
+
// ============================================================
|
23
|
+
|
24
|
+
function transitionEnd() {
|
25
|
+
var el = document.createElement('bootstrap')
|
26
|
+
|
27
|
+
var transEndEventNames = {
|
28
|
+
WebkitTransition : 'webkitTransitionEnd',
|
29
|
+
MozTransition : 'transitionend',
|
30
|
+
OTransition : 'oTransitionEnd otransitionend',
|
31
|
+
transition : 'transitionend'
|
32
|
+
}
|
33
|
+
|
34
|
+
for (var name in transEndEventNames) {
|
35
|
+
if (el.style[name] !== undefined) {
|
36
|
+
return { end: transEndEventNames[name] }
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
return false // explicit for ie8 ( ._.)
|
41
|
+
}
|
42
|
+
|
43
|
+
if ($.support.transition !== undefined) return // Prevent conflict with Twitter Bootstrap
|
44
|
+
|
45
|
+
// http://blog.alexmaccaw.com/css-transitions
|
46
|
+
$.fn.emulateTransitionEnd = function (duration) {
|
47
|
+
var called = false, $el = this
|
48
|
+
$(this).one($.support.transition.end, function () { called = true })
|
49
|
+
var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
|
50
|
+
setTimeout(callback, duration)
|
51
|
+
return this
|
52
|
+
}
|
53
|
+
|
54
|
+
$(function () {
|
55
|
+
$.support.transition = transitionEnd()
|
56
|
+
})
|
57
|
+
|
58
|
+
}(window.jQuery);
|
59
|
+
|
60
|
+
/* ========================================================================
|
61
|
+
* Bootstrap: offcanvas.js v3.1.3
|
62
|
+
* http://jasny.github.io/bootstrap/javascript/#offcanvas
|
63
|
+
* ========================================================================
|
64
|
+
* Copyright 2013-2014 Arnold Daniels
|
65
|
+
*
|
66
|
+
* Licensed under the Apache License, Version 2.0 (the "License")
|
67
|
+
* you may not use this file except in compliance with the License.
|
68
|
+
* You may obtain a copy of the License at
|
69
|
+
*
|
70
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
71
|
+
*
|
72
|
+
* Unless required by applicable law or agreed to in writing, software
|
73
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
74
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
75
|
+
* See the License for the specific language governing permissions and
|
76
|
+
* limitations under the License.
|
77
|
+
* ======================================================================== */
|
78
|
+
|
79
|
+
+function ($) { "use strict";
|
80
|
+
|
81
|
+
// OFFCANVAS PUBLIC CLASS DEFINITION
|
82
|
+
// =================================
|
83
|
+
|
84
|
+
var OffCanvas = function (element, options) {
|
85
|
+
this.$element = $(element)
|
86
|
+
this.options = $.extend({}, OffCanvas.DEFAULTS, options)
|
87
|
+
this.state = null
|
88
|
+
this.placement = null
|
89
|
+
|
90
|
+
if (this.options.recalc) {
|
91
|
+
this.calcClone()
|
92
|
+
$(window).on('resize', $.proxy(this.recalc, this))
|
93
|
+
}
|
94
|
+
|
95
|
+
if (this.options.autohide)
|
96
|
+
$(document).on('click', $.proxy(this.autohide, this))
|
97
|
+
|
98
|
+
if (this.options.toggle) this.toggle()
|
99
|
+
|
100
|
+
if (this.options.disablescrolling) {
|
101
|
+
this.options.disableScrolling = this.options.disablescrolling
|
102
|
+
delete this.options.disablescrolling
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
OffCanvas.DEFAULTS = {
|
107
|
+
toggle: true,
|
108
|
+
placement: 'auto',
|
109
|
+
autohide: true,
|
110
|
+
recalc: true,
|
111
|
+
disableScrolling: true
|
112
|
+
}
|
113
|
+
|
114
|
+
OffCanvas.prototype.offset = function () {
|
115
|
+
switch (this.placement) {
|
116
|
+
case 'left':
|
117
|
+
case 'right': return this.$element.outerWidth()
|
118
|
+
case 'top':
|
119
|
+
case 'bottom': return this.$element.outerHeight()
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
OffCanvas.prototype.calcPlacement = function () {
|
124
|
+
if (this.options.placement !== 'auto') {
|
125
|
+
this.placement = this.options.placement
|
126
|
+
return
|
127
|
+
}
|
128
|
+
|
129
|
+
if (!this.$element.hasClass('in')) {
|
130
|
+
this.$element.css('visiblity', 'hidden !important').addClass('in')
|
131
|
+
}
|
132
|
+
|
133
|
+
var horizontal = $(window).width() / this.$element.width()
|
134
|
+
var vertical = $(window).height() / this.$element.height()
|
135
|
+
|
136
|
+
var element = this.$element
|
137
|
+
function ab(a, b) {
|
138
|
+
if (element.css(b) === 'auto') return a
|
139
|
+
if (element.css(a) === 'auto') return b
|
140
|
+
|
141
|
+
var size_a = parseInt(element.css(a), 10)
|
142
|
+
var size_b = parseInt(element.css(b), 10)
|
143
|
+
|
144
|
+
return size_a > size_b ? b : a
|
145
|
+
}
|
146
|
+
|
147
|
+
this.placement = horizontal >= vertical ? ab('left', 'right') : ab('top', 'bottom')
|
148
|
+
|
149
|
+
if (this.$element.css('visibility') === 'hidden !important') {
|
150
|
+
this.$element.removeClass('in').css('visiblity', '')
|
151
|
+
}
|
152
|
+
}
|
153
|
+
|
154
|
+
OffCanvas.prototype.opposite = function (placement) {
|
155
|
+
switch (placement) {
|
156
|
+
case 'top': return 'bottom'
|
157
|
+
case 'left': return 'right'
|
158
|
+
case 'bottom': return 'top'
|
159
|
+
case 'right': return 'left'
|
160
|
+
}
|
161
|
+
}
|
162
|
+
|
163
|
+
OffCanvas.prototype.getCanvasElements = function() {
|
164
|
+
// Return a set containing the canvas plus all fixed elements
|
165
|
+
var canvas = this.options.canvas ? $(this.options.canvas) : this.$element
|
166
|
+
|
167
|
+
var fixed_elements = canvas.find('*').filter(function() {
|
168
|
+
return $(this).css('position') === 'fixed'
|
169
|
+
}).not(this.options.exclude)
|
170
|
+
|
171
|
+
return canvas.add(fixed_elements)
|
172
|
+
}
|
173
|
+
|
174
|
+
OffCanvas.prototype.slide = function (elements, offset, callback) {
|
175
|
+
// Use jQuery animation if CSS transitions aren't supported
|
176
|
+
if (!$.support.transition) {
|
177
|
+
var anim = {}
|
178
|
+
anim[this.placement] = "+=" + offset
|
179
|
+
return elements.animate(anim, 350, callback)
|
180
|
+
}
|
181
|
+
|
182
|
+
var placement = this.placement
|
183
|
+
var opposite = this.opposite(placement)
|
184
|
+
|
185
|
+
elements.each(function() {
|
186
|
+
if ($(this).css(placement) !== 'auto')
|
187
|
+
$(this).css(placement, (parseInt($(this).css(placement), 10) || 0) + offset)
|
188
|
+
|
189
|
+
if ($(this).css(opposite) !== 'auto')
|
190
|
+
$(this).css(opposite, (parseInt($(this).css(opposite), 10) || 0) - offset)
|
191
|
+
})
|
192
|
+
|
193
|
+
this.$element
|
194
|
+
.one($.support.transition.end, callback)
|
195
|
+
.emulateTransitionEnd(350)
|
196
|
+
}
|
197
|
+
|
198
|
+
OffCanvas.prototype.disableScrolling = function() {
|
199
|
+
var bodyWidth = $('body').width()
|
200
|
+
var prop = 'padding-' + this.opposite(this.placement)
|
201
|
+
|
202
|
+
if ($('body').data('offcanvas-style') === undefined) {
|
203
|
+
$('body').data('offcanvas-style', $('body').attr('style') || '')
|
204
|
+
}
|
205
|
+
|
206
|
+
$('body').css('overflow', 'hidden')
|
207
|
+
|
208
|
+
if ($('body').width() > bodyWidth) {
|
209
|
+
var padding = parseInt($('body').css(prop), 10) + $('body').width() - bodyWidth
|
210
|
+
|
211
|
+
setTimeout(function() {
|
212
|
+
$('body').css(prop, padding)
|
213
|
+
}, 1)
|
214
|
+
}
|
215
|
+
}
|
216
|
+
|
217
|
+
OffCanvas.prototype.show = function () {
|
218
|
+
if (this.state) return
|
219
|
+
|
220
|
+
var startEvent = $.Event('show.bs.offcanvas')
|
221
|
+
this.$element.trigger(startEvent)
|
222
|
+
if (startEvent.isDefaultPrevented()) return
|
223
|
+
|
224
|
+
this.state = 'slide-in'
|
225
|
+
this.calcPlacement();
|
226
|
+
|
227
|
+
var elements = this.getCanvasElements()
|
228
|
+
var placement = this.placement
|
229
|
+
var opposite = this.opposite(placement)
|
230
|
+
var offset = this.offset()
|
231
|
+
|
232
|
+
if (elements.index(this.$element) !== -1) {
|
233
|
+
$(this.$element).data('offcanvas-style', $(this.$element).attr('style') || '')
|
234
|
+
this.$element.css(placement, -1 * offset)
|
235
|
+
this.$element.css(placement); // Workaround: Need to get the CSS property for it to be applied before the next line of code
|
236
|
+
}
|
237
|
+
|
238
|
+
elements.addClass('canvas-sliding').each(function() {
|
239
|
+
if ($(this).data('offcanvas-style') === undefined) $(this).data('offcanvas-style', $(this).attr('style') || '')
|
240
|
+
if ($(this).css('position') === 'static') $(this).css('position', 'relative')
|
241
|
+
if (($(this).css(placement) === 'auto' || $(this).css(placement) === '0px') &&
|
242
|
+
($(this).css(opposite) === 'auto' || $(this).css(opposite) === '0px')) {
|
243
|
+
$(this).css(placement, 0)
|
244
|
+
}
|
245
|
+
})
|
246
|
+
|
247
|
+
if (this.options.disableScrolling) this.disableScrolling()
|
248
|
+
|
249
|
+
var complete = function () {
|
250
|
+
if (this.state != 'slide-in') return
|
251
|
+
|
252
|
+
this.state = 'slid'
|
253
|
+
|
254
|
+
elements.removeClass('canvas-sliding').addClass('canvas-slid')
|
255
|
+
this.$element.trigger('shown.bs.offcanvas')
|
256
|
+
}
|
257
|
+
|
258
|
+
setTimeout($.proxy(function() {
|
259
|
+
this.$element.addClass('in')
|
260
|
+
this.slide(elements, offset, $.proxy(complete, this))
|
261
|
+
}, this), 1)
|
262
|
+
}
|
263
|
+
|
264
|
+
OffCanvas.prototype.hide = function (fast) {
|
265
|
+
if (this.state !== 'slid') return
|
266
|
+
|
267
|
+
var startEvent = $.Event('hide.bs.offcanvas')
|
268
|
+
this.$element.trigger(startEvent)
|
269
|
+
if (startEvent.isDefaultPrevented()) return
|
270
|
+
|
271
|
+
this.state = 'slide-out'
|
272
|
+
|
273
|
+
var elements = $('.canvas-slid')
|
274
|
+
var placement = this.placement
|
275
|
+
var offset = -1 * this.offset()
|
276
|
+
|
277
|
+
var complete = function () {
|
278
|
+
if (this.state != 'slide-out') return
|
279
|
+
|
280
|
+
this.state = null
|
281
|
+
this.placement = null
|
282
|
+
|
283
|
+
this.$element.removeClass('in')
|
284
|
+
|
285
|
+
elements.removeClass('canvas-sliding')
|
286
|
+
elements.add(this.$element).add('body').each(function() {
|
287
|
+
$(this).attr('style', $(this).data('offcanvas-style')).removeData('offcanvas-style')
|
288
|
+
})
|
289
|
+
|
290
|
+
this.$element.trigger('hidden.bs.offcanvas')
|
291
|
+
}
|
292
|
+
|
293
|
+
elements.removeClass('canvas-slid').addClass('canvas-sliding')
|
294
|
+
|
295
|
+
setTimeout($.proxy(function() {
|
296
|
+
this.slide(elements, offset, $.proxy(complete, this))
|
297
|
+
}, this), 1)
|
298
|
+
}
|
299
|
+
|
300
|
+
OffCanvas.prototype.toggle = function () {
|
301
|
+
if (this.state === 'slide-in' || this.state === 'slide-out') return
|
302
|
+
this[this.state === 'slid' ? 'hide' : 'show']()
|
303
|
+
}
|
304
|
+
|
305
|
+
OffCanvas.prototype.calcClone = function() {
|
306
|
+
this.$calcClone = this.$element.clone()
|
307
|
+
.html('')
|
308
|
+
.addClass('offcanvas-clone').removeClass('in')
|
309
|
+
.appendTo($('body'))
|
310
|
+
}
|
311
|
+
|
312
|
+
OffCanvas.prototype.recalc = function () {
|
313
|
+
if (this.$calcClone.css('display') === 'none' || (this.state !== 'slid' && this.state !== 'slide-in')) return
|
314
|
+
|
315
|
+
this.state = null
|
316
|
+
this.placement = null
|
317
|
+
var elements = this.getCanvasElements()
|
318
|
+
|
319
|
+
this.$element.removeClass('in')
|
320
|
+
|
321
|
+
elements.removeClass('canvas-slid')
|
322
|
+
elements.add(this.$element).add('body').each(function() {
|
323
|
+
$(this).attr('style', $(this).data('offcanvas-style')).removeData('offcanvas-style')
|
324
|
+
})
|
325
|
+
}
|
326
|
+
|
327
|
+
OffCanvas.prototype.autohide = function (e) {
|
328
|
+
if ($(e.target).closest(this.$element).length === 0) this.hide()
|
329
|
+
}
|
330
|
+
|
331
|
+
// OFFCANVAS PLUGIN DEFINITION
|
332
|
+
// ==========================
|
333
|
+
|
334
|
+
var old = $.fn.offcanvas
|
335
|
+
|
336
|
+
$.fn.offcanvas = function (option) {
|
337
|
+
return this.each(function () {
|
338
|
+
var $this = $(this)
|
339
|
+
var data = $this.data('bs.offcanvas')
|
340
|
+
var options = $.extend({}, OffCanvas.DEFAULTS, $this.data(), typeof option === 'object' && option)
|
341
|
+
|
342
|
+
if (!data) $this.data('bs.offcanvas', (data = new OffCanvas(this, options)))
|
343
|
+
if (typeof option === 'string') data[option]()
|
344
|
+
})
|
345
|
+
}
|
346
|
+
|
347
|
+
$.fn.offcanvas.Constructor = OffCanvas
|
348
|
+
|
349
|
+
|
350
|
+
// OFFCANVAS NO CONFLICT
|
351
|
+
// ====================
|
352
|
+
|
353
|
+
$.fn.offcanvas.noConflict = function () {
|
354
|
+
$.fn.offcanvas = old
|
355
|
+
return this
|
356
|
+
}
|
357
|
+
|
358
|
+
|
359
|
+
// OFFCANVAS DATA-API
|
360
|
+
// =================
|
361
|
+
|
362
|
+
$(document).on('click.bs.offcanvas.data-api', '[data-toggle=offcanvas]', function (e) {
|
363
|
+
var $this = $(this), href
|
364
|
+
var target = $this.attr('data-target')
|
365
|
+
|| e.preventDefault()
|
366
|
+
|| (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
|
367
|
+
var $canvas = $(target)
|
368
|
+
var data = $canvas.data('bs.offcanvas')
|
369
|
+
var option = data ? 'toggle' : $this.data()
|
370
|
+
|
371
|
+
e.stopPropagation()
|
372
|
+
|
373
|
+
if (data) data.toggle()
|
374
|
+
else $canvas.offcanvas(option)
|
375
|
+
})
|
376
|
+
|
377
|
+
}(window.jQuery);
|
378
|
+
|
379
|
+
|
380
|
+
/* ===========================================================
|
381
|
+
* Bootstrap: fileinput.js v3.1.3
|
382
|
+
* http://jasny.github.com/bootstrap/javascript/#fileinput
|
383
|
+
* ===========================================================
|
384
|
+
* Copyright 2012-2014 Arnold Daniels
|
385
|
+
*
|
386
|
+
* Licensed under the Apache License, Version 2.0 (the "License")
|
387
|
+
* you may not use this file except in compliance with the License.
|
388
|
+
* You may obtain a copy of the License at
|
389
|
+
*
|
390
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
391
|
+
*
|
392
|
+
* Unless required by applicable law or agreed to in writing, software
|
393
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
394
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
395
|
+
* See the License for the specific language governing permissions and
|
396
|
+
* limitations under the License.
|
397
|
+
* ========================================================== */
|
398
|
+
|
399
|
+
+function ($) { "use strict";
|
400
|
+
|
401
|
+
var isIE = window.navigator.appName == 'Microsoft Internet Explorer'
|
402
|
+
|
403
|
+
// FILEUPLOAD PUBLIC CLASS DEFINITION
|
404
|
+
// =================================
|
405
|
+
|
406
|
+
var Fileinput = function (element, options) {
|
407
|
+
this.$element = $(element)
|
408
|
+
|
409
|
+
this.$input = this.$element.find(':file')
|
410
|
+
if (this.$input.length === 0) return
|
411
|
+
|
412
|
+
this.name = this.$input.attr('name') || options.name
|
413
|
+
|
414
|
+
this.$hidden = this.$element.find('input[type=hidden][name="' + this.name + '"]')
|
415
|
+
if (this.$hidden.length === 0) {
|
416
|
+
this.$hidden = $('<input type="hidden">').insertBefore(this.$input)
|
417
|
+
}
|
418
|
+
|
419
|
+
this.$preview = this.$element.find('.fileinput-preview')
|
420
|
+
var height = this.$preview.css('height')
|
421
|
+
if (this.$preview.css('display') !== 'inline' && height !== '0px' && height !== 'none') {
|
422
|
+
this.$preview.css('line-height', height)
|
423
|
+
}
|
424
|
+
|
425
|
+
this.original = {
|
426
|
+
exists: this.$element.hasClass('fileinput-exists'),
|
427
|
+
preview: this.$preview.html(),
|
428
|
+
hiddenVal: this.$hidden.val()
|
429
|
+
}
|
430
|
+
|
431
|
+
this.listen()
|
432
|
+
}
|
433
|
+
|
434
|
+
Fileinput.prototype.listen = function() {
|
435
|
+
this.$input.on('change.bs.fileinput', $.proxy(this.change, this))
|
436
|
+
$(this.$input[0].form).on('reset.bs.fileinput', $.proxy(this.reset, this))
|
437
|
+
|
438
|
+
this.$element.find('[data-trigger="fileinput"]').on('click.bs.fileinput', $.proxy(this.trigger, this))
|
439
|
+
this.$element.find('[data-dismiss="fileinput"]').on('click.bs.fileinput', $.proxy(this.clear, this))
|
440
|
+
},
|
441
|
+
|
442
|
+
Fileinput.prototype.change = function(e) {
|
443
|
+
var files = e.target.files === undefined ? (e.target && e.target.value ? [{ name: e.target.value.replace(/^.+\\/, '')}] : []) : e.target.files
|
444
|
+
|
445
|
+
e.stopPropagation()
|
446
|
+
|
447
|
+
if (files.length === 0) {
|
448
|
+
this.clear()
|
449
|
+
return
|
450
|
+
}
|
451
|
+
|
452
|
+
this.$hidden.val('')
|
453
|
+
this.$hidden.attr('name', '')
|
454
|
+
this.$input.attr('name', this.name)
|
455
|
+
|
456
|
+
var file = files[0]
|
457
|
+
|
458
|
+
if (this.$preview.length > 0 && (typeof file.type !== "undefined" ? file.type.match(/^image\/(gif|png|jpeg)$/) : file.name.match(/\.(gif|png|jpe?g)$/i)) && typeof FileReader !== "undefined") {
|
459
|
+
var reader = new FileReader()
|
460
|
+
var preview = this.$preview
|
461
|
+
var element = this.$element
|
462
|
+
|
463
|
+
reader.onload = function(re) {
|
464
|
+
var $img = $('<img>')
|
465
|
+
$img[0].src = re.target.result
|
466
|
+
files[0].result = re.target.result
|
467
|
+
|
468
|
+
element.find('.fileinput-filename').text(file.name)
|
469
|
+
|
470
|
+
// if parent has max-height, using `(max-)height: 100%` on child doesn't take padding and border into account
|
471
|
+
if (preview.css('max-height') != 'none') $img.css('max-height', parseInt(preview.css('max-height'), 10) - parseInt(preview.css('padding-top'), 10) - parseInt(preview.css('padding-bottom'), 10) - parseInt(preview.css('border-top'), 10) - parseInt(preview.css('border-bottom'), 10))
|
472
|
+
|
473
|
+
preview.html($img)
|
474
|
+
element.addClass('fileinput-exists').removeClass('fileinput-new')
|
475
|
+
|
476
|
+
element.trigger('change.bs.fileinput', files)
|
477
|
+
}
|
478
|
+
|
479
|
+
reader.readAsDataURL(file)
|
480
|
+
} else {
|
481
|
+
this.$element.find('.fileinput-filename').text(file.name)
|
482
|
+
this.$preview.text(file.name)
|
483
|
+
|
484
|
+
this.$element.addClass('fileinput-exists').removeClass('fileinput-new')
|
485
|
+
|
486
|
+
this.$element.trigger('change.bs.fileinput')
|
487
|
+
}
|
488
|
+
},
|
489
|
+
|
490
|
+
Fileinput.prototype.clear = function(e) {
|
491
|
+
if (e) e.preventDefault()
|
492
|
+
|
493
|
+
this.$hidden.val('')
|
494
|
+
this.$hidden.attr('name', this.name)
|
495
|
+
this.$input.attr('name', '')
|
496
|
+
|
497
|
+
//ie8+ doesn't support changing the value of input with type=file so clone instead
|
498
|
+
if (isIE) {
|
499
|
+
var inputClone = this.$input.clone(true);
|
500
|
+
this.$input.after(inputClone);
|
501
|
+
this.$input.remove();
|
502
|
+
this.$input = inputClone;
|
503
|
+
} else {
|
504
|
+
this.$input.val('')
|
505
|
+
}
|
506
|
+
|
507
|
+
this.$preview.html('')
|
508
|
+
this.$element.find('.fileinput-filename').text('')
|
509
|
+
this.$element.addClass('fileinput-new').removeClass('fileinput-exists')
|
510
|
+
|
511
|
+
if (e !== undefined) {
|
512
|
+
this.$input.trigger('change')
|
513
|
+
this.$element.trigger('clear.bs.fileinput')
|
514
|
+
}
|
515
|
+
},
|
516
|
+
|
517
|
+
Fileinput.prototype.reset = function() {
|
518
|
+
this.clear()
|
519
|
+
|
520
|
+
this.$hidden.val(this.original.hiddenVal)
|
521
|
+
this.$preview.html(this.original.preview)
|
522
|
+
this.$element.find('.fileinput-filename').text('')
|
523
|
+
|
524
|
+
if (this.original.exists) this.$element.addClass('fileinput-exists').removeClass('fileinput-new')
|
525
|
+
else this.$element.addClass('fileinput-new').removeClass('fileinput-exists')
|
526
|
+
|
527
|
+
this.$element.trigger('reset.bs.fileinput')
|
528
|
+
},
|
529
|
+
|
530
|
+
Fileinput.prototype.trigger = function(e) {
|
531
|
+
this.$input.trigger('click')
|
532
|
+
e.preventDefault()
|
533
|
+
}
|
534
|
+
|
535
|
+
|
536
|
+
// FILEUPLOAD PLUGIN DEFINITION
|
537
|
+
// ===========================
|
538
|
+
|
539
|
+
var old = $.fn.fileinput
|
540
|
+
|
541
|
+
$.fn.fileinput = function (options) {
|
542
|
+
return this.each(function () {
|
543
|
+
var $this = $(this),
|
544
|
+
data = $this.data('bs.fileinput')
|
545
|
+
if (!data) $this.data('bs.fileinput', (data = new Fileinput(this, options)))
|
546
|
+
if (typeof options == 'string') data[options]()
|
547
|
+
})
|
548
|
+
}
|
549
|
+
|
550
|
+
$.fn.fileinput.Constructor = Fileinput
|
551
|
+
|
552
|
+
|
553
|
+
// FILEINPUT NO CONFLICT
|
554
|
+
// ====================
|
555
|
+
|
556
|
+
$.fn.fileinput.noConflict = function () {
|
557
|
+
$.fn.fileinput = old
|
558
|
+
return this
|
559
|
+
}
|
560
|
+
|
561
|
+
|
562
|
+
// FILEUPLOAD DATA-API
|
563
|
+
// ==================
|
564
|
+
|
565
|
+
$(document).on('click.fileinput.data-api', '[data-provides="fileinput"]', function (e) {
|
566
|
+
var $this = $(this)
|
567
|
+
if ($this.data('bs.fileinput')) return
|
568
|
+
$this.fileinput($this.data())
|
569
|
+
|
570
|
+
var $target = $(e.target).closest('[data-dismiss="fileinput"],[data-trigger="fileinput"]');
|
571
|
+
if ($target.length > 0) {
|
572
|
+
e.preventDefault()
|
573
|
+
$target.trigger('click.bs.fileinput')
|
574
|
+
}
|
575
|
+
})
|
576
|
+
|
577
|
+
}(window.jQuery);
|