Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding custom javascript #340

Closed
tobyhede opened this issue Aug 4, 2011 · 31 comments
Closed

Adding custom javascript #340

tobyhede opened this issue Aug 4, 2011 · 31 comments

Comments

@tobyhede
Copy link
Contributor

tobyhede commented Aug 4, 2011

I was wondering if there was a mechanism for adding custom javascript to the admin UI?
Was thinking it might be a useful way of injecting features without requiring massive updates of the ruby code?

An example would be adding a plugin like jquery chosen [http://harvesthq.github.com/chosen/] to enhance certain filters and drop downs on forms.

@panva
Copy link

panva commented Aug 4, 2011

There is such mechanism, all you need to do is read the docs or browse to the config file in your project

@tobyhede
Copy link
Contributor Author

tobyhede commented Aug 4, 2011

right, awesome, cheers

@tobyhede
Copy link
Contributor Author

tobyhede commented Aug 4, 2011

is there other documentation than here: http://activeadmin.info/documentation.html

@panva
Copy link

panva commented Aug 4, 2011

just check the active_admin.rb file

# config/active_admin.rb

# == Register Stylesheets & Javascripts
#
# We recommend using the built in Active Admin layout and loading
# up your own stylesheets / javascripts to customize the look
# and feel.
#
# To load a stylesheet:
  config.register_stylesheet 'my_stylesheet.css'
#
# To load a javascript file:
  config.register_javascript 'my_javascript.js'

@pcreux pcreux closed this as completed Aug 5, 2011
@wejrowski
Copy link

How would you do this on certain pages only though?

@mull
Copy link

mull commented Mar 29, 2012

It would indeed be lovely to be able to insert javascript on only certain pages. @wejrowski did you come up with a good solution?

@wejrowski
Copy link

No I have not.. I basically just have a bunch of jquery that applies events and changes to specific elements that won't get called if they don't exist.

@benben
Copy link

benben commented Jul 16, 2012

would love to see a possibilty to include js only on certain pages/views! :)

@scottbaggett
Copy link

+1 for per-page javascript/css

@carlos-a-crespo
Copy link

+1 for per-page javascript/css too...

@ffscalco
Copy link

+1 for per-page javascript/css

1 similar comment
@haikoschol
Copy link

+1 for per-page javascript/css

@seanlinsley
Copy link
Contributor

You guys do realize that this is the going against rails best practices, right? The asset pipeline compiles all of your JS into a single file so it's more efficient for the client to grab. If you still want this feature, you can always call javascript_include_tag from a partial.

Note that you can also scope JS to only act upon pages based on the URL (document.location.href).

Last of all, here's some info specific to the asset pipeline.

@haikoschol
Copy link

Understood. The scoping is what I started to do, but then I found a way to achieve what I needed without any JavaScript.

@unrealhoang
Copy link

@haikoschol can you share your solution here?
I also tried to use Paul Irish's solution but i don't know if there is a way to add those data-* to the body element of active admin.
http://viget.com/inspire/extending-paul-irishs-comprehensive-dom-ready-execution

@haikoschol
Copy link

@unrealhoang Unfortunately I don't even remember what exactly the problem was I tried to solve with per-page JavaScript, let alone where to look for my workaround in the code. But it didn't involve any JavaScript, so it probably wouldn't be useful to you anyway.

@loicginoux
Copy link

This is how I manage to run certain piece of javascript per page:

in app/assets/active_admin.js:

//= require jquery
//= require jquery_ujs
//= require jquery-ui
//= require ./init
// = require_tree ./admin

in app/assets/init.js:

// initialize your global object will all your model names
YOUR_APP = {
    contracts:{},
    products:{},
    purchases:{},
    rentals:{},
    users:{}
}

jQuery(document).ready(function($) {
       // get the page action
    var action,model, b = $("body");
    if (b.hasClass("edit")) {
        action = "edit";
    } else if(b.hasClass("view")){
        action = "view";
    } else if(b.hasClass("index")){
        action = "index"
    } else if(b.hasClass("new")){
        action = "new"
    }

        // run the code specific to a model and an action
    for (var m in YOUR_APP) {
        if (b.hasClass("admin_"+m)) {
            if (YOUR_APP[m][action] && typeof YOUR_APP[m][action] == "function") {
                YOUR_APP[m][action]();
                break;
            }
        }
    }
});

And then inside my directory app/assets/admin I have one js file per model with for example for the user model something like that:
in app/assets/admin/user/js

YOUR_APP.users = {
    index: function() { alert("this code run only on the user index page"); },
    view: function() { alert("this code run only on the user view page"); },
    edit: function() { alert("this code run only on the user edit page"); }
};

I hope this will be useful for those who are looking for a solution. It's not the best but it works.

@seanlinsley
Copy link
Contributor

Interesting approach @loicginoux

@batamire
Copy link

batamire commented Dec 3, 2013

@unrealhoang this is how I did it: app/admin/layout_hacks.rb

# ruby 2.0 only, visit link below for more information
# http://stackoverflow.com/questions/4470108/when-monkey-patching-a-method-can-you-call-the-overridden-method-from-the-new-i
module ActiveAdmin::Views::Pages::BaseExtension
  def add_classes_to_body
    super
    @body.set_attribute "data-controller", params[:controller].gsub(/^admin\//, '')
    @body.set_attribute "data-action",     params[:action]
  end
end
class ActiveAdmin::Views::Pages::Base
  # mixes in the module directly below the class
  prepend ActiveAdmin::Views::Pages::BaseExtension
end

@apoorvparijat
Copy link

Compiling the solutions by @batamire and @loicginoux

# app/admin/layout_hacks.rb

module ActiveAdmin::Views::Pages::BaseExtension
  def add_classes_to_body
    super
    @body.set_attribute "data-controller", params[:controller].gsub(/^admin\//, '')
    @body.set_attribute "data-action",     params[:action]
  end
end
class ActiveAdmin::Views::Pages::Base
  # mixes in the module directly below the class
  prepend ActiveAdmin::Views::Pages::BaseExtension
end
# app/assets/javascripts/active_admin.js.coffee

#= require active_admin/base
ActiveAdmin = {
  dashboard: {},
  user: {}
}

ActiveAdmin.dashboard.index = () ->
  console.log 'Hello'

$(() ->
  controller = $('body').data('controller')
  action = $('body').data('action')
  ActiveAdmin[controller][action]() if ActiveAdmin[controller][action]?
)

@ivanyv
Copy link

ivanyv commented Apr 13, 2015

My hack to add scripts at the top (added at the top of the ActiveAdmin initializer):

Rails.application.config.after_initialize do
  javascripts = [] 
  javascripts << "//maps.googleapis.com/maps/api/js?sensor=false&key="
  javascripts += ActiveAdmin.application.javascripts.to_a
  ActiveAdmin.application.javascripts.replace javascripts
end

@serradura
Copy link

@ivanyv You can do this too.

Add in your config/initializers/active_admin.rb.

ActiveAdmin.setup do |config|

  config.register_stylesheet "//cdn.foo.net/example.css"

  config.register_javascript "//cdn.foo.net/example.js"

  # ...
end

@ivanyv
Copy link

ivanyv commented Jun 6, 2015

@serradura Yeah but that appends the scripts at the bottom and some scripts I need at the top.

@serradura
Copy link

@ivanyv I understood now. Thanks for sharing! 😄

@workgena
Copy link

workgena commented Sep 21, 2016

My solution to load additional JS before closing </body> tag, for each controller:

Create file /lib/active_admin/views/footer.rb

module ActiveAdmin
  module Views
    class Footer < Component

      private

      def powered_by_message
        para I18n.t('active_admin.powered_by', active_admin: link_to("Active Admin", "http://www.activeadmin.info"), version: ActiveAdmin::VERSION).html_safe

        if MyApplicationName::Application.assets.find_asset("ui/#{params[:controller]}.js")
          render text: javascript_include_tag("ui/#{params[:controller]}")
        end
      end

    end
  end
end

This will patch AA-view with our code. It includes JS-file it it exists.

For example we have controller /app/admin/customer.rb

ActiveAdmin.register Customer, as: 'Customer' do
  # ...
end

Then create relevant JS-file:
/app/assets/javascripts/ui/admin/customers.js

alert('controller_name is: admin/customers');

This works in development mode.

To get this work in production you need:

  1. in application.js and active_admin.js not to use "require_tree ." (IMPORTANT)
  2. /config/environments/production.rb add this
config.assets.precompile += %w(ui/admin/*.js)

Compile assets with:
RAILS_ENV=production bundle exec rake assets:precompile

@jtomaszewski
Copy link

My solution:

ActiveAdmin::Views::Pages::Base.class_eval do
  def build_active_admin_head_with_js_script
    build_active_admin_head_without_js_script
    add_js_config_to_head
  end

  def add_js_config_to_head
    within @head do
      script """
      I18n = window.I18n || {};
      I18n.defaultLocale = \"en\";
      I18n.locale = \"#{I18n.locale}\";
      """.html_safe
    end
  end

  alias_method_chain :build_active_admin_head, :js_script
end

@yaaase
Copy link

yaaase commented Oct 23, 2017

Since config.register_javascript now appears deprecated, is there a prescribed mechanism for including an external JS? Specifically google maps, with a key.

@dchersey
Copy link

I think you may be able to use arbre script tags to link in the google map scripts, and initialize.

for example

    script src: 'url for google maps'

and for inline initialization

    script do
      raw '$(document).ready(function($) {console.log("insert page initialization code here");})'
    end

@rivella50
Copy link

And if you need to use ruby variables in the script part switch the quotation marks:

script do
    raw "$('.link-delete').bind('ajax:complete', function() {
      $('#content').load('#{customer_id}/customer_data');
    });"
end

@davidwparker
Copy link

Is there a way to add JS per namespace?

@Ritesh-Katare
Copy link

@dchersey @rivella50 Thanks for inline js stuff,
Could you please help to append html element from inline js in active admin with "script" helper?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests