diff --git a/app/assets/javascripts/rails_admin/custom/ui.coffee b/app/assets/javascripts/rails_admin/custom/ui.coffee
deleted file mode 100644
index 28339364e5..0000000000
--- a/app/assets/javascripts/rails_admin/custom/ui.coffee
+++ /dev/null
@@ -1 +0,0 @@
-#= override this file in your application to add custom behaviour
\ No newline at end of file
diff --git a/app/assets/javascripts/rails_admin/custom/ui.js b/app/assets/javascripts/rails_admin/custom/ui.js
new file mode 100644
index 0000000000..9d6e5c7cb2
--- /dev/null
+++ b/app/assets/javascripts/rails_admin/custom/ui.js
@@ -0,0 +1 @@
+// override this file in your application to add custom behaviour
diff --git a/app/assets/javascripts/rails_admin/ra.i18n.coffee b/app/assets/javascripts/rails_admin/ra.i18n.coffee
deleted file mode 100644
index 57fe2827e1..0000000000
--- a/app/assets/javascripts/rails_admin/ra.i18n.coffee
+++ /dev/null
@@ -1,10 +0,0 @@
-@RailsAdmin ||= {}
-@RailsAdmin.I18n = class Locale
- @init: (@locale, @translations)->
- moment.locale(@locale)
- if typeof(@translations) == "string"
- @translations = JSON.parse(@translations)
-
- @t:(key) ->
- humanize = key.charAt(0).toUpperCase() + key.replace(/_/g, " ").slice(1)
- @translations[key] || humanize
diff --git a/app/assets/javascripts/rails_admin/ra.i18n.js b/app/assets/javascripts/rails_admin/ra.i18n.js
new file mode 100644
index 0000000000..ab42470e4e
--- /dev/null
+++ b/app/assets/javascripts/rails_admin/ra.i18n.js
@@ -0,0 +1,28 @@
+(function() {
+ var Locale;
+
+ this.RailsAdmin || (this.RailsAdmin = {});
+
+ this.RailsAdmin.I18n = Locale = (function() {
+ function Locale() {}
+
+ Locale.init = function(locale, translations) {
+ this.locale = locale;
+ this.translations = translations;
+ moment.locale(this.locale);
+ if (typeof this.translations === "string") {
+ this.translations = JSON.parse(this.translations);
+ }
+ };
+
+ Locale.t = function(key) {
+ var humanize;
+ humanize = key.charAt(0).toUpperCase() + key.replace(/_/g, " ").slice(1);
+ return this.translations[key] || humanize;
+ };
+
+ return Locale;
+
+ })();
+
+}).call(this);
diff --git a/app/assets/javascripts/rails_admin/ra.nested-form-hooks.coffee b/app/assets/javascripts/rails_admin/ra.nested-form-hooks.coffee
deleted file mode 100644
index 2a798276df..0000000000
--- a/app/assets/javascripts/rails_admin/ra.nested-form-hooks.coffee
+++ /dev/null
@@ -1,55 +0,0 @@
-$ = jQuery
-
-$(document).ready ->
- window.nestedFormEvents.insertFields = (content, assoc, link) ->
- tab_content = $(link).closest(".controls").siblings(".tab-content")
- tab_content.append content
- tab_content.children().last()
-
-$(document).on 'nested:fieldAdded', 'form', (content) ->
- field = content.field.addClass('tab-pane').attr('id', 'unique-id-' + (new Date().getTime()))
- new_tab = $('
' + field.children('.object-infos').data('object-label') + '')
- parent_group = field.closest('.control-group')
- controls = parent_group.children('.controls')
- one_to_one = controls.data('nestedone') != undefined
- nav = controls.children('.nav')
- content = parent_group.children('.tab-content')
- toggler = controls.find('.toggler')
- nav.append(new_tab)
- $(window.document).trigger('rails_admin.dom_ready', [field, parent_group]) # fire dom_ready for new player in town
- new_tab.children('a').tab('show') # activate added tab
- nav.select(':hidden').show('slow') unless one_to_one # show nav if hidden
- content.select(':hidden').show('slow') # show tabs content if hidden
- # toggler 'on' if inactive
- toggler.addClass('active').removeClass('disabled').children('i').addClass('icon-chevron-down').removeClass('icon-chevron-right')
-
- # Convert the "add nested field" button to just showing the title of the new model
- controls.find('.add_nested_fields').removeClass('add_nested_fields').html(field.children('.object-infos').data('object-label')) if one_to_one
-
-$(document).on 'nested:fieldRemoved', 'form', (content) ->
- field = content.field
- nav = field.closest(".control-group").children('.controls').children('.nav')
- current_li = nav.children('li').has('a[href="#' + field.attr('id') + '"]')
- parent_group = field.closest(".control-group")
- controls = parent_group.children('.controls')
- one_to_one = controls.data('nestedone') != undefined
- toggler = controls.find('.toggler')
-
- # try to activate another tab
- (if current_li.next().length then current_li.next() else current_li.prev()).children('a:first').tab('show')
-
- current_li.remove()
-
- if nav.children().length == 0 # removed last tab
- nav.select(':visible').hide('slow') # hide nav. No use anymore.
- # toggler 'off' if active
- toggler.removeClass('active').addClass('disabled').children('i').removeClass('icon-chevron-down').addClass('icon-chevron-right')
-
- if one_to_one
- # Converts the title button to an "add nested field" button
- add_button = toggler.next()
- add_button.addClass('add_nested_fields').html(add_button.data('add-label'))
-
- # Removing all required attributes from deleted child form to bypass browser validations.
- field.find('[required]').each ->
- $(this).removeAttr('required')
diff --git a/app/assets/javascripts/rails_admin/ra.nested-form-hooks.js b/app/assets/javascripts/rails_admin/ra.nested-form-hooks.js
new file mode 100644
index 0000000000..a7509a891e
--- /dev/null
+++ b/app/assets/javascripts/rails_admin/ra.nested-form-hooks.js
@@ -0,0 +1,57 @@
+(function($) {
+ $(document).ready(function() {
+ return window.nestedFormEvents.insertFields = function(content, assoc, link) {
+ var tab_content;
+ tab_content = $(link).closest(".controls").siblings(".tab-content");
+ tab_content.append(content);
+ return tab_content.children().last();
+ };
+ });
+
+ $(document).on('nested:fieldAdded', 'form', function(content) {
+ var controls, field, nav, new_tab, one_to_one, parent_group, toggler;
+ field = content.field.addClass('tab-pane').attr('id', 'unique-id-' + (new Date().getTime()));
+ new_tab = $('' + field.children('.object-infos').data('object-label') + '');
+ parent_group = field.closest('.control-group');
+ controls = parent_group.children('.controls');
+ one_to_one = controls.data('nestedone') !== void 0;
+ nav = controls.children('.nav');
+ content = parent_group.children('.tab-content');
+ toggler = controls.find('.toggler');
+ nav.append(new_tab);
+ $(window.document).trigger('rails_admin.dom_ready', [field, parent_group]);
+ new_tab.children('a').tab('show');
+ if (!one_to_one) {
+ nav.select(':hidden').show('slow');
+ }
+ content.select(':hidden').show('slow');
+ toggler.addClass('active').removeClass('disabled').children('i').addClass('icon-chevron-down').removeClass('icon-chevron-right');
+ if (one_to_one) {
+ controls.find('.add_nested_fields').removeClass('add_nested_fields').html(field.children('.object-infos').data('object-label'));
+ }
+ });
+
+ $(document).on('nested:fieldRemoved', 'form', function(content) {
+ var add_button, controls, current_li, field, nav, one_to_one, parent_group, toggler;
+ field = content.field;
+ nav = field.closest(".control-group").children('.controls').children('.nav');
+ current_li = nav.children('li').has('a[href="#' + field.attr('id') + '"]');
+ parent_group = field.closest(".control-group");
+ controls = parent_group.children('.controls');
+ one_to_one = controls.data('nestedone') !== void 0;
+ toggler = controls.find('.toggler');
+ (current_li.next().length ? current_li.next() : current_li.prev()).children('a:first').tab('show');
+ current_li.remove();
+ if (nav.children().length === 0) {
+ nav.select(':visible').hide('slow');
+ toggler.removeClass('active').addClass('disabled').children('i').removeClass('icon-chevron-down').addClass('icon-chevron-right');
+ }
+ if (one_to_one) {
+ add_button = toggler.next();
+ add_button.addClass('add_nested_fields').html(add_button.data('add-label'));
+ }
+ field.find('[required]').each(function() {
+ $(this).removeAttr('required');
+ });
+ });
+}(jQuery));
diff --git a/app/assets/javascripts/rails_admin/ra.sidescroll.coffee b/app/assets/javascripts/rails_admin/ra.sidescroll.coffee
deleted file mode 100644
index 4fcc3dc483..0000000000
--- a/app/assets/javascripts/rails_admin/ra.sidescroll.coffee
+++ /dev/null
@@ -1,19 +0,0 @@
-(->
- $ = jQuery
-
- setFrozenColPositions = ->
- $listForm = $('#bulk_form')
- return unless $listForm.is('.ra-sidescroll')
- frozenColumns = $listForm.data('ra-sidescroll')
- $listForm.find('table tr').each (index, tr) ->
- firstPosition = 0
- $(tr).children().slice(0, frozenColumns).each (idx, td) ->
- $(td).addClass('ra-sidescroll-frozen')
- $(td).addClass('last-of-frozen') if idx == frozenColumns - 1
- tdLeft = $(td).position().left
- firstPosition = tdLeft if idx == 0
- td.style.left = "#{tdLeft - firstPosition}px"
-
- $(window).on('load', setFrozenColPositions) # Update after link icons load.
- $(document).on('rails_admin.dom_ready', setFrozenColPositions)
-)()
diff --git a/app/assets/javascripts/rails_admin/ra.sidescroll.js b/app/assets/javascripts/rails_admin/ra.sidescroll.js
new file mode 100644
index 0000000000..7dfe516a8f
--- /dev/null
+++ b/app/assets/javascripts/rails_admin/ra.sidescroll.js
@@ -0,0 +1,31 @@
+(function($) {
+ function setFrozenColPositions() {
+ var $listForm, frozenColumns;
+
+ $listForm = $('#bulk_form');
+ if (!$listForm.is('.ra-sidescroll')) {
+ return;
+ }
+ frozenColumns = $listForm.data('ra-sidescroll');
+
+ $listForm.find('table tr').each(function(index, tr) {
+ var firstPosition = 0;
+
+ $(tr).children().slice(0, frozenColumns).each(function(idx, td) {
+ var tdLeft;
+ $(td).addClass('ra-sidescroll-frozen');
+ if (idx === frozenColumns - 1) {
+ $(td).addClass('last-of-frozen');
+ }
+ tdLeft = $(td).position().left;
+ if (idx === 0) {
+ firstPosition = tdLeft;
+ }
+ td.style.left = (tdLeft - firstPosition) + "px";
+ });
+ });
+ };
+
+ $(window).on('load', setFrozenColPositions);
+ $(document).on('rails_admin.dom_ready', setFrozenColPositions);
+})(jQuery);
diff --git a/app/assets/javascripts/rails_admin/ra.widgets.coffee b/app/assets/javascripts/rails_admin/ra.widgets.coffee
deleted file mode 100644
index 63172cea45..0000000000
--- a/app/assets/javascripts/rails_admin/ra.widgets.coffee
+++ /dev/null
@@ -1,360 +0,0 @@
-$(document).on 'rails_admin.dom_ready', (e, content) ->
-
- content = if content then content else $('form')
-
- if content.length # don't waste time otherwise
-
- # colorpicker
-
- content.find('[data-color]').each ->
- that = this
- $(this).ColorPicker
- color: $(that).val()
- onShow: (el) ->
- $(el).fadeIn(500)
- false
- onHide: (el) ->
- $(el).fadeOut(500)
- false
- onChange: (hsb, hex, rgb) ->
- $(that).val(hex)
- $(that).css('backgroundColor', '#' + hex)
-
- # datetime picker
- $.fn.datetimepicker.defaults.icons =
- time: 'fa fa-clock-o'
- date: 'fa fa-calendar'
- up: 'fa fa-chevron-up'
- down: 'fa fa-chevron-down'
- previous: 'fa fa-angle-double-left'
- next: 'fa fa-angle-double-right'
- today: 'fa fa-dot-circle-o'
- clear: 'fa fa-trash'
- close: 'fa fa-times'
-
- content.find('[data-datetimepicker]').each ->
- options = $(this).data('options')
- $.extend(options, {locale: RailsAdmin.I18n.locale})
- $(this).datetimepicker options
-
- # enumeration
-
- content.find('[data-enumeration]').each ->
- if $(this).is('[multiple]')
- $(this).filteringMultiselect $(this).data('options')
- else
- $(this).filteringSelect $(this).data('options')
-
- # fileupload
-
- content.find('[data-fileupload]').each ->
- parent = $(this).closest('.controls')
- parent.find('.btn-remove-image').on 'click', ->
- $(this).siblings('[type=checkbox]').click()
- parent.find('.toggle').toggle('slow')
- $(this).toggleClass('btn-danger btn-info')
- false
-
- # fileupload-preview
-
- content.find('[data-fileupload]').change ->
- input = this
- image_container = $("#" + input.id).parent().children(".preview")
- unless image_container.length
- image_container = $("#" + input.id).parent().prepend($('').addClass('preview').addClass('img-thumbnail')).find('img.preview')
- image_container.parent().find('img:not(.preview)').hide()
- ext = $("#" + input.id).val().split('.').pop().toLowerCase()
- if input.files and input.files[0] and $.inArray(ext, ['gif','png','jpg','jpeg','bmp']) != -1
- reader = new FileReader()
- reader.onload = (e) ->
- image_container.attr "src", e.target.result
- reader.readAsDataURL input.files[0]
- image_container.show()
- else
- image_container.hide()
-
- # multiple-fileupload
-
- content.find('[data-multiple-fileupload]').each ->
- $(this).closest('.controls').find('.btn-remove-image').on('click', ->
- $(this).siblings('[type=checkbox]').click()
- $(this).parent('.toggle').toggle('slow')
- $(this).toggleClass('btn-danger btn-info')
- false
- ).end().sortable(items: '.sortables')
-
- # multiple-fileupload-preview
-
- content.find('[data-multiple-fileupload]').change ->
- input = this
- $("#" + input.id).parent().children(".preview").remove()
- for file in input.files
- ext = file.name.split('.').pop().toLowerCase()
- if $.inArray(ext, ['gif','png','jpg','jpeg','bmp']) == -1
- continue
- image_container = $('').addClass('preview').addClass('img-thumbnail')
- do (image_container) ->
- reader = new FileReader()
- reader.onload = (e) ->
- image_container.attr "src", e.target.result
- reader.readAsDataURL file
- $("#" + input.id).parent().append($('').addClass('preview').append(image_container))
-
- # filtering-multiselect
-
- content.find('[data-filteringmultiselect]').each ->
- $(this).filteringMultiselect $(this).data('options')
- if $(this).parents("#modal").length # hide link if we already are inside a dialog (endless issues on nested dialogs with JS)
- $(this).siblings('.btn').remove()
- else
- $(this).parents('.control-group').first().remoteForm()
-
- # filtering-select
-
- content.find('[data-filteringselect]').each ->
- $(this).filteringSelect $(this).data('options')
- if $(this).parents("#modal").length # hide link if we already are inside a dialog (endless issues on nested dialogs with JS)
- $(this).siblings('.btn').remove()
- else
- $(this).parents('.control-group').first().remoteForm()
-
- # nested-many
-
- content.find('[data-nestedmany]').each ->
- field = $(this).parents('.control-group').first()
- nav = field.find('> .controls > .nav')
- tab_content = field.find('> .tab-content')
- toggler = field.find('> .controls > .btn-group > .toggler')
- # add each nested field to a tab-pane and reference it in the nav
- tab_content.children('.fields:not(.tab-pane)').addClass('tab-pane').each ->
- $(this).attr('id', 'unique-id-' + (new Date().getTime()) + Math.floor(Math.random()*100000)) # some elements are created on the same ms
- nav.append('' + $(this).children('.object-infos').data('object-label') + '')
- # only if no tab is set to active
- if nav.find("> li.active").length == 0
- # init first tab, toggler and tab_content/tabs visibility
- nav.find("> li > a[data-toggle='tab']:first").tab('show')
- if nav.children().length == 0
- nav.hide()
- tab_content.hide()
- toggler.addClass('disabled').removeClass('active').children('i').addClass('icon-chevron-right')
- else
- if toggler.hasClass('active')
- nav.show()
- tab_content.show()
- toggler.children('i').addClass('icon-chevron-down')
- else
- nav.hide()
- tab_content.hide()
- toggler.children('i').addClass('icon-chevron-right')
-
- # nested-one
-
- content.find('[data-nestedone]').each ->
- field = $(this).parents('.control-group').first()
- nav = field.find("> .controls > .nav")
- tab_content = field.find("> .tab-content")
- toggler = field.find('> .controls > .btn-group > .toggler')
- tab_content.children(".fields:not(.tab-pane)").addClass('tab-pane active').each ->
- # Convert the "add nested field" button to just showing the title of the new model
- field.find('> .controls .add_nested_fields').removeClass('add_nested_fields').html( $(this).children('.object-infos').data('object-label') )
- nav.append('' + $(this).children('.object-infos').data('object-label') + '')
- first_tab = nav.find("> li > a[data-toggle='tab']:first")
- first_tab.tab('show')
- field.find("> .controls > [data-target]:first").html(' ' + first_tab.html())
- nav.hide()
- if nav.children().length == 0
- nav.hide()
- tab_content.hide()
- toggler.addClass('disabled').removeClass('active').children('i').addClass('icon-chevron-right')
- else
- if toggler.hasClass('active')
- toggler.children('i').addClass('icon-chevron-down')
- tab_content.show()
- else
- toggler.children('i').addClass('icon-chevron-right')
- tab_content.hide()
-
- # polymorphic-association
-
- content.find('[data-polymorphic]').each ->
- type_select = $(this)
- field = type_select.parents('.control-group').first()
- object_select = field.find('select').last()
- urls = type_select.data('urls')
-
- type_select.on 'change', (e) ->
- selected_type = type_select.val().toLowerCase()
- selected_data = $("##{selected_type}-js-options").data('options')
- object_select.data('options', selected_data)
- object_select.filteringSelect("destroy")
- object_select.filteringSelect selected_data
-
-
- # simplemde
-
- goSimpleMDEs = ->
- content.find('[data-richtext=simplemde]').not('.simplemded').each (index, domEle) ->
- options = $(this).data('options')
- instance_config = options.instance_config
- new window.SimpleMDE($.extend(true, {
- element: document.getElementById(this.id),
- autosave: {
- uniqueId: this.id
- }
- }, instance_config))
- $(this).addClass('simplemded')
-
- $editors = content.find('[data-richtext=simplemde]').not('.simplemded')
- if $editors.length
- if not window.SimpleMDE
- options = $editors.first().data('options')
- $('head').append('')
- $.getScript options['js_location'], (script, textStatus, jqXHR) ->
- goSimpleMDEs()
- else
- goSimpleMDEs()
-
- # ckeditor
-
- goCkeditors = ->
- content.find('[data-richtext=ckeditor]').not('.ckeditored').each (index, domEle) ->
- try
- if instance = window.CKEDITOR.instances[this.id]
- instance.destroy(true)
- window.CKEDITOR.replace(this, $(this).data('options'))
- $(this).addClass('ckeditored')
-
- $editors = content.find('[data-richtext=ckeditor]').not('.ckeditored')
- if $editors.length
- if not window.CKEDITOR
- options = $editors.first().data('options')
- window.CKEDITOR_BASEPATH = options['base_location']
- $.getScript options['jspath'], (script, textStatus, jqXHR) =>
- goCkeditors()
- else
- goCkeditors()
-
- #codemirror
-
- goCodeMirrors = (array) =>
- array.each (index, domEle) ->
- options = $(this).data('options')
- textarea = this
- $.getScript options['locations']['mode'], (script, textStatus, jqXHR) ->
- options = $(domEle).data('options')
- $('head').append('')
- CodeMirror.fromTextArea(textarea,options['options'])
- $(textarea).addClass('codemirrored')
-
- array = content.find('[data-richtext=codemirror]').not('.codemirrored')
- if array.length
- @array = array
- if not window.CodeMirror
- options = $(array[0]).data('options')
- $('head').append('')
- $.getScript options['jspath'], (script, textStatus, jqXHR) =>
- goCodeMirrors(@array)
- else
- goCodeMirrors(@array)
-
- # bootstrap_wysihtml5
-
- goBootstrapWysihtml5s = (array, config_options) =>
- array.each ->
- $(@).addClass('bootstrap-wysihtml5ed')
- $(@).closest('.controls').addClass('well')
- $(@).wysihtml5(config_options)
-
- array = content.find('[data-richtext=bootstrap-wysihtml5]').not('.bootstrap-wysihtml5ed')
- if array.length
- @array = array
- options = $(array[0]).data('options')
- config_options = $.parseJSON(options['config_options'])
- if not window.wysihtml5
- $('head').append('')
- $.getScript options['jspath'], (script, textStatus, jqXHR) =>
- goBootstrapWysihtml5s(@array, config_options)
- else
- goBootstrapWysihtml5s(@array, config_options)
-
- # froala_wysiwyg
-
- goFroalaWysiwygs = (array) =>
- array.each ->
- options = $(@).data('options')
- config_options = $.parseJSON(options['config_options'])
- if config_options
- if !config_options['inlineMode']
- config_options['inlineMode'] = false
- else
- config_options = { inlineMode: false }
-
- uploadEnabled =
- if config_options['imageUploadURL']
- config_options['imageUploadParams'] =
- authenticity_token: $('meta[name=csrf-token]').attr('content')
-
- $(@).addClass('froala-wysiwyged')
- $(@).froalaEditor(config_options)
- if uploadEnabled
- $(@).on 'froalaEditor.image.error', (e, editor, error) ->
- alert("error uploading image: " + error.message);
- # Custom error message returned from the server.
- if error.code == 0
-
- # Bad link.
- else if error.code == 1
-
- # No link in upload response.
- else if error.code == 2
-
- # Error during image upload.
- else if error.code == 3
-
- # Parsing response failed.
- else if error.code == 4
-
- # Image too large.
- else if error.code == 5
-
- # Invalid image type.
- else if error.code == 6
-
- # Image can be uploaded only to same domain in IE 8 and IE 9.
- else if error.code == 7
-
- else
-
- return
-
- .on('froalaEditor.image.removed', (e, editor, $img) ->
- # Set the image source to the image delete params.
- editor.options.imageDeleteParams =
- src: $img.attr('src')
- authenticity_token: $('meta[name=csrf-token]').attr('content')
- # Make the delete request.
- editor.deleteImage $img
- return
- ).on('editable.imageDeleteSuccess', (e, editor, data) ->
- # handle success
- ).on 'editable.imageDeleteError', (e, editor, error) ->
- # handle error
- alert("error deleting image: " + error.message);
-
- array = content.find('[data-richtext=froala-wysiwyg]').not('.froala-wysiwyged')
- if array.length
- options = $(array[0]).data('options')
- if not $.isFunction($.fn.editable)
- $('head').append('')
- $.getScript options['jspath'], (script, textStatus, jqXHR) =>
- goFroalaWysiwygs(array)
- else
- goFroalaWysiwygs(array)
-
- # action_text
-
- content.find('trix-editor').each ->
- if !window.Trix
- options = $(this).data('options')
- $('head').append('')
- $.getScript options['jspath']
diff --git a/app/assets/javascripts/rails_admin/ra.widgets.js b/app/assets/javascripts/rails_admin/ra.widgets.js
new file mode 100644
index 0000000000..34c9910527
--- /dev/null
+++ b/app/assets/javascripts/rails_admin/ra.widgets.js
@@ -0,0 +1,371 @@
+(function($) {
+ $(document).on('rails_admin.dom_ready', function(e, content) {
+ var $editors, array, config_options, goBootstrapWysihtml5s, goCkeditors, goCodeMirrors, goFroalaWysiwygs, goSimpleMDEs, options;
+ content = content ? content : $('form');
+ if (content.length) {
+ content.find('[data-color]').each(function() {
+ var that;
+ that = this;
+ return $(this).ColorPicker({
+ color: $(that).val(),
+ onShow: function(el) {
+ $(el).fadeIn(500);
+ return false;
+ },
+ onHide: function(el) {
+ $(el).fadeOut(500);
+ return false;
+ },
+ onChange: function(hsb, hex, rgb) {
+ $(that).val(hex);
+ $(that).css('backgroundColor', '#' + hex);
+ }
+ });
+ });
+ $.fn.datetimepicker.defaults.icons = {
+ time: 'fa fa-clock-o',
+ date: 'fa fa-calendar',
+ up: 'fa fa-chevron-up',
+ down: 'fa fa-chevron-down',
+ previous: 'fa fa-angle-double-left',
+ next: 'fa fa-angle-double-right',
+ today: 'fa fa-dot-circle-o',
+ clear: 'fa fa-trash',
+ close: 'fa fa-times'
+ };
+ content.find('[data-datetimepicker]').each(function() {
+ var options;
+ options = $(this).data('options');
+ $.extend(options, {
+ locale: RailsAdmin.I18n.locale
+ });
+ $(this).datetimepicker(options);
+ });
+ content.find('[data-enumeration]').each(function() {
+ if ($(this).is('[multiple]')) {
+ $(this).filteringMultiselect($(this).data('options'));
+ } else {
+ $(this).filteringSelect($(this).data('options'));
+ }
+ });
+ content.find('[data-fileupload]').each(function() {
+ var parent;
+ parent = $(this).closest('.controls');
+ parent.find('.btn-remove-image').on('click', function() {
+ $(this).siblings('[type=checkbox]').click();
+ parent.find('.toggle').toggle('slow');
+ $(this).toggleClass('btn-danger btn-info');
+ return false;
+ });
+ });
+ content.find('[data-fileupload]').change(function() {
+ var ext, image_container, input, reader;
+ input = this;
+ image_container = $("#" + input.id).parent().children(".preview");
+ if (!image_container.length) {
+ image_container = $("#" + input.id).parent().prepend($('').addClass('preview').addClass('img-thumbnail')).find('img.preview');
+ image_container.parent().find('img:not(.preview)').hide();
+ }
+ ext = $("#" + input.id).val().split('.').pop().toLowerCase();
+ if (input.files && input.files[0] && $.inArray(ext, ['gif', 'png', 'jpg', 'jpeg', 'bmp']) !== -1) {
+ reader = new FileReader();
+ reader.onload = function(e) {
+ image_container.attr("src", e.target.result);
+ };
+ reader.readAsDataURL(input.files[0]);
+ image_container.show();
+ } else {
+ image_container.hide();
+ }
+ });
+ content.find('[data-multiple-fileupload]').each(function() {
+ $(this).closest('.controls').find('.btn-remove-image').on('click', function() {
+ $(this).siblings('[type=checkbox]').click();
+ $(this).parent('.toggle').toggle('slow');
+ $(this).toggleClass('btn-danger btn-info');
+ return false;
+ }).end().sortable({
+ items: '.sortables'
+ });
+ });
+ content.find('[data-multiple-fileupload]').change(function() {
+ var ext, file, i, image_container, input, len, ref, results;
+ input = this;
+ $("#" + input.id).parent().children(".preview").remove();
+ ref = input.files;
+ results = [];
+ for (i = 0, len = ref.length; i < len; i++) {
+ file = ref[i];
+ ext = file.name.split('.').pop().toLowerCase();
+ if ($.inArray(ext, ['gif', 'png', 'jpg', 'jpeg', 'bmp']) === -1) {
+ continue;
+ }
+ image_container = $('').addClass('preview').addClass('img-thumbnail');
+ results.push((function(image_container) {
+ var reader;
+ reader = new FileReader();
+ reader.onload = function(e) {
+ image_container.attr("src", e.target.result);
+ };
+ reader.readAsDataURL(file);
+ return $("#" + input.id).parent().append($('').addClass('preview').append(image_container));
+ })(image_container));
+ }
+ return results;
+ });
+ content.find('[data-filteringmultiselect]').each(function() {
+ $(this).filteringMultiselect($(this).data('options'));
+ if ($(this).parents("#modal").length) {
+ $(this).siblings('.btn').remove();
+ } else {
+ $(this).parents('.control-group').first().remoteForm();
+ }
+ });
+ content.find('[data-filteringselect]').each(function() {
+ $(this).filteringSelect($(this).data('options'));
+ if ($(this).parents("#modal").length) {
+ $(this).siblings('.btn').remove();
+ } else {
+ $(this).parents('.control-group').first().remoteForm();
+ }
+ });
+ content.find('[data-nestedmany]').each(function() {
+ var field, nav, tab_content, toggler;
+ field = $(this).parents('.control-group').first();
+ nav = field.find('> .controls > .nav');
+ tab_content = field.find('> .tab-content');
+ toggler = field.find('> .controls > .btn-group > .toggler');
+ tab_content.children('.fields:not(.tab-pane)').addClass('tab-pane').each(function() {
+ $(this).attr('id', 'unique-id-' + (new Date().getTime()) + Math.floor(Math.random() * 100000));
+ nav.append('' + $(this).children('.object-infos').data('object-label') + '');
+ });
+ if (nav.find("> li.active").length === 0) {
+ nav.find("> li > a[data-toggle='tab']:first").tab('show');
+ }
+ if (nav.children().length === 0) {
+ nav.hide();
+ tab_content.hide();
+ toggler.addClass('disabled').removeClass('active').children('i').addClass('icon-chevron-right');
+ } else {
+ if (toggler.hasClass('active')) {
+ nav.show();
+ tab_content.show();
+ toggler.children('i').addClass('icon-chevron-down');
+ } else {
+ nav.hide();
+ tab_content.hide();
+ toggler.children('i').addClass('icon-chevron-right');
+ }
+ }
+ });
+ content.find('[data-nestedone]').each(function() {
+ var field, first_tab, nav, tab_content, toggler;
+ field = $(this).parents('.control-group').first();
+ nav = field.find("> .controls > .nav");
+ tab_content = field.find("> .tab-content");
+ toggler = field.find('> .controls > .btn-group > .toggler');
+ tab_content.children(".fields:not(.tab-pane)").addClass('tab-pane active').each(function() {
+ field.find('> .controls .add_nested_fields').removeClass('add_nested_fields').html($(this).children('.object-infos').data('object-label'));
+ nav.append('' + $(this).children('.object-infos').data('object-label') + '');
+ });
+ first_tab = nav.find("> li > a[data-toggle='tab']:first");
+ first_tab.tab('show');
+ field.find("> .controls > [data-target]:first").html(' ' + first_tab.html());
+ nav.hide();
+ if (nav.children().length === 0) {
+ nav.hide();
+ tab_content.hide();
+ toggler.addClass('disabled').removeClass('active').children('i').addClass('icon-chevron-right');
+ } else {
+ if (toggler.hasClass('active')) {
+ toggler.children('i').addClass('icon-chevron-down');
+ tab_content.show();
+ } else {
+ toggler.children('i').addClass('icon-chevron-right');
+ tab_content.hide();
+ }
+ }
+ });
+ content.find('[data-polymorphic]').each(function() {
+ var field, object_select, type_select, urls;
+ type_select = $(this);
+ field = type_select.parents('.control-group').first();
+ object_select = field.find('select').last();
+ urls = type_select.data('urls');
+ type_select.on('change', function(e) {
+ var selected_data, selected_type;
+ selected_type = type_select.val().toLowerCase();
+ selected_data = $("#" + selected_type + "-js-options").data('options');
+ object_select.data('options', selected_data);
+ object_select.filteringSelect("destroy");
+ object_select.filteringSelect(selected_data);
+ });
+ });
+ goSimpleMDEs = function() {
+ return content.find('[data-richtext=simplemde]').not('.simplemded').each(function(index, domEle) {
+ var instance_config, options;
+ options = $(this).data('options');
+ instance_config = options.instance_config;
+ new window.SimpleMDE($.extend(true, {
+ element: document.getElementById(this.id),
+ autosave: {
+ uniqueId: this.id
+ }
+ }, instance_config));
+ $(this).addClass('simplemded');
+ });
+ };
+ $editors = content.find('[data-richtext=simplemde]').not('.simplemded');
+ if ($editors.length) {
+ if (!window.SimpleMDE) {
+ options = $editors.first().data('options');
+ $('head').append('');
+ $.getScript(options['js_location'], function(script, textStatus, jqXHR) {
+ return goSimpleMDEs();
+ });
+ } else {
+ goSimpleMDEs();
+ }
+ }
+ goCkeditors = function() {
+ return content.find('[data-richtext=ckeditor]').not('.ckeditored').each(function(index, domEle) {
+ var instance;
+ try {
+ if (instance = window.CKEDITOR.instances[this.id]) {
+ instance.destroy(true);
+ }
+ } catch (error1) {}
+ window.CKEDITOR.replace(this, $(this).data('options'));
+ $(this).addClass('ckeditored');
+ });
+ };
+ $editors = content.find('[data-richtext=ckeditor]').not('.ckeditored');
+ if ($editors.length) {
+ if (!window.CKEDITOR) {
+ options = $editors.first().data('options');
+ window.CKEDITOR_BASEPATH = options['base_location'];
+ $.getScript(options['jspath'], (function(_this) {
+ return function(script, textStatus, jqXHR) {
+ return goCkeditors();
+ };
+ })(this));
+ } else {
+ goCkeditors();
+ }
+ }
+ goCodeMirrors = (function(_this) {
+ return function(array) {
+ return array.each(function(index, domEle) {
+ var textarea;
+ options = $(this).data('options');
+ textarea = this;
+ $.getScript(options['locations']['mode'], function(script, textStatus, jqXHR) {
+ options = $(domEle).data('options');
+ $('head').append('');
+ CodeMirror.fromTextArea(textarea, options['options']);
+ return $(textarea).addClass('codemirrored');
+ });
+ });
+ };
+ })(this);
+ array = content.find('[data-richtext=codemirror]').not('.codemirrored');
+ if (array.length) {
+ this.array = array;
+ if (!window.CodeMirror) {
+ options = $(array[0]).data('options');
+ $('head').append('');
+ $.getScript(options['jspath'], (function(_this) {
+ return function(script, textStatus, jqXHR) {
+ return goCodeMirrors(_this.array);
+ };
+ })(this));
+ } else {
+ goCodeMirrors(this.array);
+ }
+ }
+ goBootstrapWysihtml5s = (function(_this) {
+ return function(array, config_options) {
+ return array.each(function() {
+ $(this).addClass('bootstrap-wysihtml5ed');
+ $(this).closest('.controls').addClass('well');
+ $(this).wysihtml5(config_options);
+ });
+ };
+ })(this);
+ array = content.find('[data-richtext=bootstrap-wysihtml5]').not('.bootstrap-wysihtml5ed');
+ if (array.length) {
+ this.array = array;
+ options = $(array[0]).data('options');
+ config_options = $.parseJSON(options['config_options']);
+ if (!window.wysihtml5) {
+ $('head').append('');
+ $.getScript(options['jspath'], (function(_this) {
+ return function(script, textStatus, jqXHR) {
+ return goBootstrapWysihtml5s(_this.array, config_options);
+ };
+ })(this));
+ } else {
+ goBootstrapWysihtml5s(this.array, config_options);
+ }
+ }
+ goFroalaWysiwygs = (function(_this) {
+ return function(array) {
+ return array.each(function() {
+ var uploadEnabled;
+ options = $(this).data('options');
+ config_options = $.parseJSON(options['config_options']);
+ if (config_options) {
+ if (!config_options['inlineMode']) {
+ config_options['inlineMode'] = false;
+ }
+ } else {
+ config_options = {
+ inlineMode: false
+ };
+ }
+ uploadEnabled = config_options['imageUploadURL'] ? config_options['imageUploadParams'] = {
+ authenticity_token: $('meta[name=csrf-token]').attr('content')
+ } : void 0;
+ $(this).addClass('froala-wysiwyged');
+ $(this).froalaEditor(config_options);
+ if (uploadEnabled) {
+ $(this).on('froalaEditor.image.error', function(e, editor, error) {
+ alert("error uploading image: " + error.message);
+ }).on('froalaEditor.image.removed', function(e, editor, $img) {
+ editor.options.imageDeleteParams = {
+ src: $img.attr('src'),
+ authenticity_token: $('meta[name=csrf-token]').attr('content')
+ };
+ editor.deleteImage($img);
+ }).on('editable.imageDeleteSuccess', function(e, editor, data) {}).on('editable.imageDeleteError', function(e, editor, error) {
+ alert("error deleting image: " + error.message);
+ });
+ }
+ });
+ };
+ })(this);
+ array = content.find('[data-richtext=froala-wysiwyg]').not('.froala-wysiwyged');
+ if (array.length) {
+ options = $(array[0]).data('options');
+ if (!$.isFunction($.fn.editable)) {
+ $('head').append('');
+ $.getScript(options['jspath'], (function(_this) {
+ return function(script, textStatus, jqXHR) {
+ return goFroalaWysiwygs(array);
+ };
+ })(this));
+ } else {
+ goFroalaWysiwygs(array);
+ }
+ }
+ return content.find('trix-editor').each(function() {
+ if (!window.Trix) {
+ options = $(this).data('options');
+ $('head').append('');
+ return $.getScript(options['jspath']);
+ }
+ });
+ }
+ });
+
+}(jQuery));
diff --git a/app/assets/javascripts/rails_admin/ui.coffee b/app/assets/javascripts/rails_admin/ui.coffee
deleted file mode 100644
index 99d4e413ea..0000000000
--- a/app/assets/javascripts/rails_admin/ui.coffee
+++ /dev/null
@@ -1,107 +0,0 @@
-$ = jQuery
-
-$(document).on "click", "#list input.toggle", ->
- $("#list [name='bulk_ids[]']").prop "checked", $(this).is(":checked")
-
-$(document).on 'click', '.pjax', (event) ->
- if event.which > 1 || event.metaKey || event.ctrlKey
- return
- else if $.support.pjax
- event.preventDefault()
- $.pjax
- container: $(this).data('pjax-container') || '[data-pjax-container]'
- url: $(this).data('href') || $(this).attr('href')
- timeout: 2000
- else if $(this).data('href') # not a native #href, need some help
- window.location = $(this).data('href')
-
-$(document).on 'submit', '.pjax-form', (event) ->
- if $.support.pjax
- event.preventDefault()
- $.pjax
- container: $(this).data('pjax-container') || '[data-pjax-container]'
- url: this.action + (if (this.action.indexOf('?') != -1) then '&' else '?') + $(this).serialize()
- timeout: 2000
-
-$(document)
- .on 'pjax:start', ->
- $('#loading').show()
- .on 'pjax:end', ->
- $('#loading').hide()
-
-$(document).on 'click', '[data-target]', ->
- if !$(this).hasClass('disabled')
- if $(this).has('i.icon-chevron-down').length
- $(this).removeClass('active').children('i').toggleClass('icon-chevron-down icon-chevron-right')
- $($(this).data('target')).select(':visible').hide('slow')
- else
- if $(this).has('i.icon-chevron-right').length
- $(this).addClass('active').children('i').toggleClass('icon-chevron-down icon-chevron-right')
- $($(this).data('target')).select(':hidden').show('slow')
-
-$(document).on 'click', '.form-horizontal legend', ->
- if $(this).has('i.icon-chevron-down').length
- $(this).siblings('.control-group:visible').hide('slow')
- $(this).children('i').toggleClass('icon-chevron-down icon-chevron-right')
- else
- if $(this).has('i.icon-chevron-right').length
- $(this).siblings('.control-group:hidden').show('slow')
- $(this).children('i').toggleClass('icon-chevron-down icon-chevron-right')
-
-$(document).on 'click', 'form .tab-content .tab-pane a.remove_nested_one_fields', ->
- $(this).children('input[type="hidden"]').val($(this).hasClass('active')).
- siblings('i').toggleClass('icon-check icon-trash')
-
-$(document).ready ->
- RailsAdmin.I18n.init $('html').attr('lang'), $("#admin-js").data('i18nOptions')
- $(document).trigger('rails_admin.dom_ready')
-
-$(document).on 'pjax:end', ->
- $(document).trigger('rails_admin.dom_ready')
-
-$(document).on 'rails_admin.dom_ready', ->
- $('.nav.nav-pills li.active').removeClass('active')
- $(".nav.nav-pills li[data-model=\"#{$('.page-header').data('model')}\"]").addClass('active')
-
- $('.animate-width-to').each ->
- length = $(this).data("animate-length")
- width = $(this).data("animate-width-to")
- $(this).animate(width: width, length, 'easeOutQuad')
-
- $('.form-horizontal legend').has('i.icon-chevron-right').each ->
- $(this).siblings('.control-group').hide()
-
- $(".table").tooltip selector: "th[rel=tooltip]"
-
- # Workaround for jquery-ujs formnovalidate issue:
- # https://github.com/rails/jquery-ujs/issues/316
- $('[formnovalidate]').on 'click', ->
- $(this).closest('form').attr('novalidate', true)
-
- $.each $('#filters_box').data('options'), ->
- $.filters.append(this)
-
-# Interactions for index action
-$(document).on 'click', ".bulk-link", (event) ->
- event.preventDefault()
- $('#bulk_action').val($(this).data('action'))
- $('#bulk_form').submit()
-
-$(document).on 'click', "#remove_filter", (event) ->
- event.preventDefault()
- $("#filters_box").html("")
- $("hr.filters_box").hide()
- $(this).parent().siblings("input[type='search']").val("")
- $(this).parents("form").submit()
-
-# Interactions for export action
-$(document).on 'click', '#fields_to_export label input#check_all', () ->
- elems = $('#fields_to_export label input')
- if $('#fields_to_export label input#check_all').is ':checked'
- $(elems).prop('checked', true)
- else
- $(elems).prop('checked',false)
-
-$(document).on 'click', '#fields_to_export .reverse-selection', () ->
- $(this).closest(".control-group").find(".controls").find("input").click()
-
diff --git a/app/assets/javascripts/rails_admin/ui.js b/app/assets/javascripts/rails_admin/ui.js
new file mode 100644
index 0000000000..f12fb77a13
--- /dev/null
+++ b/app/assets/javascripts/rails_admin/ui.js
@@ -0,0 +1,135 @@
+(function($) {
+ $(document).on("click", "#list input.toggle", function() {
+ $("#list [name='bulk_ids[]']").prop("checked", $(this).is(":checked"));
+ });
+
+ $(document).on('click', '.pjax', function(event) {
+ if (event.which > 1 || event.metaKey || event.ctrlKey) {
+ return;
+ }
+
+ if ($.support.pjax) {
+ event.preventDefault();
+ $.pjax({
+ container: $(this).data('pjax-container') || '[data-pjax-container]',
+ url: $(this).data('href') || $(this).attr('href'),
+ timeout: 2000
+ });
+ return;
+ }
+
+ if ($(this).data('href')) {
+ window.location = $(this).data('href');
+ }
+ });
+
+ $(document).on('submit', '.pjax-form', function(event) {
+ if ($.support.pjax) {
+ event.preventDefault();
+ $.pjax({
+ container: $(this).data('pjax-container') || '[data-pjax-container]',
+ url: this.action + (this.action.indexOf('?') !== -1 ? '&' : '?') + $(this).serialize(),
+ timeout: 2000
+ });
+ }
+ });
+
+ $(document).on('pjax:start', function() {
+ return $('#loading').show();
+ }).on('pjax:end', function() {
+ return $('#loading').hide();
+ });
+
+ $(document).on('click', '[data-target]', function() {
+ if (!$(this).hasClass('disabled')) {
+ if ($(this).has('i.icon-chevron-down').length) {
+ $(this).removeClass('active').children('i').toggleClass('icon-chevron-down icon-chevron-right');
+ $($(this).data('target')).select(':visible').hide('slow');
+ } else {
+ if ($(this).has('i.icon-chevron-right').length) {
+ $(this).addClass('active').children('i').toggleClass('icon-chevron-down icon-chevron-right');
+ $($(this).data('target')).select(':hidden').show('slow');
+ }
+ }
+ }
+ });
+
+ $(document).on('click', '.form-horizontal legend', function() {
+ if ($(this).has('i.icon-chevron-down').length) {
+ $(this).siblings('.control-group:visible').hide('slow');
+ $(this).children('i').toggleClass('icon-chevron-down icon-chevron-right');
+ } else {
+ if ($(this).has('i.icon-chevron-right').length) {
+ $(this).siblings('.control-group:hidden').show('slow');
+ $(this).children('i').toggleClass('icon-chevron-down icon-chevron-right');
+ }
+ }
+ });
+
+ $(document).on('click', 'form .tab-content .tab-pane a.remove_nested_one_fields', function() {
+ $(this).children('input[type="hidden"]').val($(this).hasClass('active')).siblings('i').toggleClass('icon-check icon-trash');
+ });
+
+ $(document).ready(function() {
+ RailsAdmin.I18n.init($('html').attr('lang'), $("#admin-js").data('i18nOptions'));
+ $(document).trigger('rails_admin.dom_ready');
+ });
+
+ $(document).on('pjax:end', function() {
+ $(document).trigger('rails_admin.dom_ready');
+ });
+
+ $(document).on('rails_admin.dom_ready', function() {
+ $('.nav.nav-pills li.active').removeClass('active');
+ $(".nav.nav-pills li[data-model=\"" + ($('.page-header').data('model')) + "\"]").addClass('active');
+ $('.animate-width-to').each(function() {
+ var length, width;
+ length = $(this).data("animate-length");
+ width = $(this).data("animate-width-to");
+ $(this).animate({
+ width: width
+ }, length, 'easeOutQuad');
+ });
+ $('.form-horizontal legend').has('i.icon-chevron-right').each(function() {
+ $(this).siblings('.control-group').hide();
+ });
+ $(".table").tooltip({
+ selector: "th[rel=tooltip]"
+ });
+ $('[formnovalidate]').on('click', function() {
+ $(this).closest('form').attr('novalidate', true);
+ });
+ $.each($('#filters_box').data('options'), function() {
+ $.filters.append(this);
+ });
+ });
+
+ $(document).on('click', ".bulk-link", function(event) {
+ event.preventDefault();
+ $('#bulk_action').val($(this).data('action'));
+ $('#bulk_form').submit();
+ });
+
+ $(document).on('click', "#remove_filter", function(event) {
+ event.preventDefault();
+ $("#filters_box").html("");
+ $("hr.filters_box").hide();
+ $(this).parent().siblings("input[type='search']").val("");
+ $(this).parents("form").submit();
+ });
+
+ $(document).on('click', '#fields_to_export label input#check_all', function() {
+ var elems;
+ elems = $('#fields_to_export label input');
+ if ($('#fields_to_export label input#check_all').is(':checked')) {
+ $(elems).prop('checked', true);
+ } else {
+ $(elems).prop('checked', false);
+ }
+ });
+
+ $(document).on('click', '#fields_to_export .reverse-selection', function() {
+ $(this).closest(".control-group").find(".controls").find("input").click();
+ });
+
+}(jQuery));
diff --git a/rails_admin.gemspec b/rails_admin.gemspec
index 33e759c94f..c6e5b87dd1 100644
--- a/rails_admin.gemspec
+++ b/rails_admin.gemspec
@@ -6,7 +6,6 @@ require 'rails_admin/version'
Gem::Specification.new do |spec|
# If you add a dependency, please maintain alphabetical order
spec.add_dependency 'builder', '~> 3.1'
- spec.add_dependency 'coffee-rails', ['>= 4.0', '< 6']
spec.add_dependency 'haml', '>= 4.0', '< 6'
spec.add_dependency 'jquery-rails', ['>= 3.0', '< 5']
spec.add_dependency 'jquery-ui-rails', ['>= 5.0', '< 7']