├── test
├── dummy
│ ├── log
│ │ └── .keep
│ ├── app
│ │ ├── mailers
│ │ │ └── .keep
│ │ ├── models
│ │ │ ├── .keep
│ │ │ ├── concerns
│ │ │ │ └── .keep
│ │ │ └── page.rb
│ │ ├── assets
│ │ │ ├── images
│ │ │ │ └── .keep
│ │ │ ├── stylesheets
│ │ │ │ └── application.css.sass
│ │ │ └── javascripts
│ │ │ │ └── application.js.coffee
│ │ ├── controllers
│ │ │ ├── concerns
│ │ │ │ └── .keep
│ │ │ ├── welcome_controller.rb
│ │ │ ├── application_controller.rb
│ │ │ └── pages_controller.rb
│ │ ├── helpers
│ │ │ └── application_helper.rb
│ │ └── views
│ │ │ ├── layouts
│ │ │ └── application.html.haml
│ │ │ ├── welcome
│ │ │ └── index.html.haml
│ │ │ └── pages
│ │ │ └── _page.html.haml
│ ├── lib
│ │ └── assets
│ │ │ └── .keep
│ ├── public
│ │ ├── favicon.ico
│ │ ├── 500.html
│ │ ├── 422.html
│ │ └── 404.html
│ ├── bin
│ │ ├── rake
│ │ ├── bundle
│ │ └── rails
│ ├── config.ru
│ ├── config
│ │ ├── initializers
│ │ │ ├── session_store.rb
│ │ │ ├── filter_parameter_logging.rb
│ │ │ ├── mime_types.rb
│ │ │ ├── backtrace_silencers.rb
│ │ │ ├── wrap_parameters.rb
│ │ │ ├── secret_token.rb
│ │ │ └── inflections.rb
│ │ ├── environment.rb
│ │ ├── boot.rb
│ │ ├── database.yml
│ │ ├── locales
│ │ │ └── en.yml
│ │ ├── application.rb
│ │ ├── environments
│ │ │ ├── development.rb
│ │ │ ├── test.rb
│ │ │ └── production.rb
│ │ └── routes.rb
│ ├── db
│ │ ├── seeds.rb
│ │ ├── migrate
│ │ │ └── 20131115152536_create_pages.rb
│ │ └── schema.rb
│ ├── Rakefile
│ └── README.rdoc
├── x-editable-rails_test.rb
├── test_helper.rb
└── view_helpers_test.rb
├── Procfile
├── gemfiles
├── rails_4_0.gemfile
├── rails_4_1.gemfile
└── rails_4_2.gemfile
├── vendor
└── assets
│ ├── images
│ └── editable
│ │ ├── clear.png
│ │ └── loading.gif
│ ├── javascripts
│ └── editable
│ │ ├── rails.js.coffee
│ │ ├── rails
│ │ ├── error_handling.js.coffee
│ │ ├── data_classes.js.coffee
│ │ └── editable_form.js.coffee
│ │ └── inputs-ext
│ │ ├── typeahead-editable.js
│ │ ├── wysihtml5-editable.js
│ │ ├── address.js
│ │ └── bootstrap-wysihtml5.js
│ └── stylesheets
│ └── editable
│ ├── inputs-ext
│ ├── address.css
│ ├── wysiwyg-color.css
│ ├── bootstrap-typeahead.css
│ └── bootstrap-wysihtml5.css
│ ├── jquery-editable.scss
│ ├── jqueryui-editable.scss
│ ├── bootstrap-editable.scss
│ └── bootstrap2-editable.scss
├── lib
├── x-editable-rails
│ ├── version.rb
│ ├── configuration.rb
│ └── view_helpers.rb
├── generators
│ └── x_editable_rails
│ │ ├── install_generator.rb
│ │ └── templates
│ │ └── x-editable.yml
└── x-editable-rails.rb
├── .travis.yml
├── Gemfile
├── .gitignore
├── Rakefile
├── x-editable-rails.gemspec
├── LICENSE.txt
├── Gemfile.lock
└── README.md
/test/dummy/log/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/app/mailers/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/app/models/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/lib/assets/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/public/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/app/assets/images/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/app/models/concerns/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/dummy/app/controllers/concerns/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: cd test/dummy && bin/rails server -p $PORT
2 |
--------------------------------------------------------------------------------
/test/dummy/app/helpers/application_helper.rb:
--------------------------------------------------------------------------------
1 | module ApplicationHelper
2 | end
3 |
--------------------------------------------------------------------------------
/gemfiles/rails_4_0.gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gemspec path: '..'
4 |
5 | gem 'rails', '~> 4.0.0'
6 |
--------------------------------------------------------------------------------
/gemfiles/rails_4_1.gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gemspec path: '..'
4 |
5 | gem 'rails', '~> 4.1.0'
6 |
--------------------------------------------------------------------------------
/gemfiles/rails_4_2.gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gemspec path: '..'
4 |
5 | gem 'rails', '~> 4.2.0'
6 |
--------------------------------------------------------------------------------
/test/dummy/bin/rake:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require_relative '../config/boot'
3 | require 'rake'
4 | Rake.application.run
5 |
--------------------------------------------------------------------------------
/vendor/assets/images/editable/clear.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/werein/x-editable-rails/HEAD/vendor/assets/images/editable/clear.png
--------------------------------------------------------------------------------
/vendor/assets/images/editable/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/werein/x-editable-rails/HEAD/vendor/assets/images/editable/loading.gif
--------------------------------------------------------------------------------
/lib/x-editable-rails/version.rb:
--------------------------------------------------------------------------------
1 | module X
2 | module Editable
3 | module Rails
4 | VERSION = "1.5.5.1"
5 | end
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/test/dummy/app/controllers/welcome_controller.rb:
--------------------------------------------------------------------------------
1 | class WelcomeController < ApplicationController
2 | def index
3 | @pages = Page.all
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/test/dummy/bin/bundle:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
3 | load Gem.bin_path('bundler', 'bundle')
4 |
--------------------------------------------------------------------------------
/test/dummy/bin/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | APP_PATH = File.expand_path('../../config/application', __FILE__)
3 | require_relative '../config/boot'
4 | require 'rails/commands'
5 |
--------------------------------------------------------------------------------
/vendor/assets/javascripts/editable/rails.js.coffee:
--------------------------------------------------------------------------------
1 | #= require editable/rails/editable_form
2 | #= require editable/rails/data_classes
3 | #= require editable/rails/error_handling
4 |
--------------------------------------------------------------------------------
/test/dummy/config.ru:
--------------------------------------------------------------------------------
1 | # This file is used by Rack-based servers to start the application.
2 |
3 | require ::File.expand_path('../config/environment', __FILE__)
4 | run Rails.application
5 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/session_store.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | Dummy::Application.config.session_store :cookie_store, key: '_dummy_session'
4 |
--------------------------------------------------------------------------------
/test/dummy/config/environment.rb:
--------------------------------------------------------------------------------
1 | # Load the Rails application.
2 | require File.expand_path('../application', __FILE__)
3 |
4 | # Initialize the Rails application.
5 | Dummy::Application.initialize!
6 |
--------------------------------------------------------------------------------
/test/x-editable-rails_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | class XEditableRailsTest < ActiveSupport::TestCase
4 | test "truth" do
5 | assert_kind_of Module, X::Editable::Rails
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/test/dummy/app/models/page.rb:
--------------------------------------------------------------------------------
1 | class Page < ActiveRecord::Base
2 | translates :title
3 | accepts_nested_attributes_for :translations, allow_destroy: true
4 | validates :name, length: { minimum: 5 }, allow_blank: true
5 | end
6 |
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/editable/inputs-ext/address.css:
--------------------------------------------------------------------------------
1 | .editable-address {
2 | display: block;
3 | margin-bottom: 5px;
4 | }
5 |
6 | .editable-address span {
7 | width: 70px;
8 | display: inline-block;
9 | }
--------------------------------------------------------------------------------
/test/dummy/db/seeds.rb:
--------------------------------------------------------------------------------
1 | Page.create!(
2 | active: true, name: 'Apple iPhone', description: 'AppleiPhone is a ...',
3 | translations_attributes: [{ title: 'Apple CS', locale: 'cs' }, { title: 'Apple EN', locale: 'en' } ])
--------------------------------------------------------------------------------
/vendor/assets/javascripts/editable/rails/error_handling.js.coffee:
--------------------------------------------------------------------------------
1 | $.fn.editable.defaults.error = (response, newValue) ->
2 | field_name = $(this).data("name")
3 | error_msgs = response.responseJSON.errors[field_name]
4 | error_msgs.join "; "
--------------------------------------------------------------------------------
/test/dummy/config/initializers/filter_parameter_logging.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Configure sensitive parameters which will be filtered from the log file.
4 | Rails.application.config.filter_parameters += [:password]
5 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/mime_types.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new mime types for use in respond_to blocks:
4 | # Mime::Type.register "text/richtext", :rtf
5 | # Mime::Type.register_alias "text/html", :iphone
6 |
--------------------------------------------------------------------------------
/test/dummy/config/boot.rb:
--------------------------------------------------------------------------------
1 | # Set up gems listed in the Gemfile.
2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __FILE__)
3 |
4 | require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
5 | $LOAD_PATH.unshift File.expand_path('../../../../lib', __FILE__)
6 |
--------------------------------------------------------------------------------
/test/dummy/Rakefile:
--------------------------------------------------------------------------------
1 | # Add your own tasks in files placed in lib/tasks ending in .rake,
2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3 |
4 | require File.expand_path('../config/application', __FILE__)
5 |
6 | Dummy::Application.load_tasks
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | branches: master
2 | cache: bundler
3 | gemfile:
4 | - gemfiles/rails_4_0.gemfile
5 | - gemfiles/rails_4_1.gemfile
6 | - gemfiles/rails_4_2.gemfile
7 | language: ruby
8 | matrix:
9 | allow_failures:
10 | - rvm: ruby-head
11 | rvm:
12 | - "2.0"
13 | - "2.1"
14 | - "2.2"
15 | - ruby-head
16 | sudo: false
17 |
--------------------------------------------------------------------------------
/test/dummy/app/views/layouts/application.html.haml:
--------------------------------------------------------------------------------
1 | !!!
2 | %html
3 | %head
4 | %title Dummy
5 | = stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true
6 | = csrf_meta_tags
7 | %body
8 | .container
9 | = yield
10 | = javascript_include_tag "application", "data-turbolinks-track" => true
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | # Specify your gem's dependencies in x-editable-rails.gemspec
4 | gemspec
5 |
6 | gem 'sprockets'
7 | gem 'sass-rails'
8 | gem 'bootstrap-sass'
9 | gem 'coffee-rails'
10 | gem 'jquery-rails'
11 | gem 'haml'
12 | gem 'globalize'
13 | gem 'responders'
14 | gem 'pg'
15 | gem 'rails_12factor'
16 | gem 'uglifier'
17 |
--------------------------------------------------------------------------------
/test/dummy/app/views/welcome/index.html.haml:
--------------------------------------------------------------------------------
1 | %h1 Welcome#index
2 | %p Find me in app/views/welcome/index.html.haml
3 |
4 | .pull-right
5 | = link_to 'Denied access', root_path(denied: true)
6 | |
7 | = link_to 'Enabled access', root_path
8 |
9 | %table.table.table-striped
10 | %thead
11 | %tr
12 | %th Description
13 | %th Example
14 | %th Code
15 | %tbody
16 | = render @pages
--------------------------------------------------------------------------------
/lib/generators/x_editable_rails/install_generator.rb:
--------------------------------------------------------------------------------
1 | module XEditableRails
2 | module Generators
3 | class InstallGenerator < Rails::Generators::Base
4 | source_root File.expand_path('../templates', __FILE__)
5 |
6 | desc 'Copy example of x-editable config'
7 | def copy_x_editable_yml
8 | template 'x-editable.yml', 'config/x-editable.yml'
9 | end
10 | end
11 | end
12 | end
--------------------------------------------------------------------------------
/lib/x-editable-rails.rb:
--------------------------------------------------------------------------------
1 | require 'x-editable-rails/version'
2 | require 'x-editable-rails/configuration'
3 | require 'x-editable-rails/view_helpers'
4 |
5 | module X
6 | module Editable
7 | module Rails
8 | class Engine < ::Rails::Engine
9 | initializer 'x-editable-rails.view_helpers' do
10 | ActionView::Base.send :include, ViewHelpers
11 | end
12 | end
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.gem
2 | *.rbc
3 | .bundle
4 | .config
5 | .yardoc
6 | .idea
7 | .DS_Store
8 | gemfiles/*.gemfile.lock
9 | InstalledFiles
10 | _yardoc
11 | coverage
12 | doc/
13 | lib/bundler/man
14 | pkg
15 | rdoc
16 | spec/reports
17 | test/tmp
18 | test/version_tmp
19 | test/dummy/db/*.sqlite3
20 | test/dummy/db/*.sqlite3-journal
21 | test/dummy/log/*.log
22 | test/dummy/tmp/
23 | test/dummy/.sass-cache
24 | test/dummy/public/uploads/
25 | coverage/
26 | tmp
27 | .project
--------------------------------------------------------------------------------
/test/dummy/config/initializers/backtrace_silencers.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
5 |
6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
7 | # Rails.backtrace_cleaner.remove_silencers!
8 |
--------------------------------------------------------------------------------
/lib/generators/x_editable_rails/templates/x-editable.yml:
--------------------------------------------------------------------------------
1 | # More informations you can find here: https://github.com/werein/x-editable-rails
2 | class_options:
3 | MailingList:
4 | name: Mailing list name
5 | enabled:
6 | type: select
7 | source:
8 | - Active
9 | - Disabled
10 | reply_email:
11 | type: email
12 | title: Reply-to email
13 | User:
14 | email:
15 | type: email
16 | password:
17 | type: password
18 | mailing_lists:
19 | type: select
--------------------------------------------------------------------------------
/test/dummy/app/controllers/application_controller.rb:
--------------------------------------------------------------------------------
1 | class ApplicationController < ActionController::Base
2 | # Prevent CSRF attacks by raising an exception.
3 | # For APIs, you may want to use :null_session instead.
4 | # protect_from_forgery with: :exception
5 |
6 | def xeditable? object = nil
7 | xeditable = params[:denied] ? false : true
8 | can?(:edit, object) and xeditable ? true : false
9 | end
10 | helper_method :xeditable?
11 |
12 | def can? edit, model
13 | true
14 | end
15 | helper_method :can?
16 | end
--------------------------------------------------------------------------------
/test/dummy/db/migrate/20131115152536_create_pages.rb:
--------------------------------------------------------------------------------
1 | class CreatePages < ActiveRecord::Migration
2 | def change
3 | create_table :pages do |t|
4 | t.boolean :active
5 | t.string :name
6 | t.text :description
7 |
8 | t.timestamps
9 | end
10 |
11 | create_table :page_translations do |t|
12 | t.references :page, index: true
13 | t.string :locale, null: false
14 | t.string :title
15 | t.timestamps
16 | end
17 |
18 | add_index :page_translations, :locale
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/test/test_helper.rb:
--------------------------------------------------------------------------------
1 | # Configure Rails Environment
2 | ENV["RAILS_ENV"] = "test"
3 |
4 | require File.expand_path("../dummy/config/environment.rb", __FILE__)
5 | require "rails/test_help"
6 |
7 | Rails.backtrace_cleaner.remove_silencers!
8 |
9 | # Load support files
10 | Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
11 |
12 | # Load fixtures from the engine
13 | if ActiveSupport::TestCase.method_defined?(:fixture_path=)
14 | ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__)
15 | end
16 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/wrap_parameters.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # This file contains settings for ActionController::ParamsWrapper which
4 | # is enabled by default.
5 |
6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7 | ActiveSupport.on_load(:action_controller) do
8 | wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
9 | end
10 |
11 | # To enable root element in JSON for ActiveRecord objects.
12 | # ActiveSupport.on_load(:active_record) do
13 | # self.include_root_in_json = true
14 | # end
15 |
--------------------------------------------------------------------------------
/test/dummy/README.rdoc:
--------------------------------------------------------------------------------
1 | == README
2 |
3 | This README would normally document whatever steps are necessary to get the
4 | application up and running.
5 |
6 | Things you may want to cover:
7 |
8 | * Ruby version
9 |
10 | * System dependencies
11 |
12 | * Configuration
13 |
14 | * Database creation
15 |
16 | * Database initialization
17 |
18 | * How to run the test suite
19 |
20 | * Services (job queues, cache servers, search engines, etc.)
21 |
22 | * Deployment instructions
23 |
24 | * ...
25 |
26 |
27 | Please feel free to use a different markup language if you do not plan to run
28 | rake doc:app.
29 |
--------------------------------------------------------------------------------
/test/dummy/config/database.yml:
--------------------------------------------------------------------------------
1 | # SQLite version 3.x
2 | # gem install sqlite3
3 | #
4 | # Ensure the SQLite 3 gem is defined in your Gemfile
5 | # gem 'sqlite3'
6 | development:
7 | adapter: sqlite3
8 | database: db/development.sqlite3
9 | pool: 5
10 | timeout: 5000
11 |
12 | # Warning: The database defined as "test" will be erased and
13 | # re-generated from your development database when you run "rake".
14 | # Do not set this db to the same as development or production.
15 | test:
16 | adapter: sqlite3
17 | database: db/test.sqlite3
18 | pool: 5
19 | timeout: 5000
20 |
21 | production:
22 | adapter: sqlite3
23 | database: db/production.sqlite3
24 | pool: 5
25 | timeout: 5000
26 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | begin
2 | require 'bundler/setup'
3 | rescue LoadError
4 | puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5 | end
6 |
7 | require 'rdoc/task'
8 |
9 | RDoc::Task.new(:rdoc) do |rdoc|
10 | rdoc.rdoc_dir = 'rdoc'
11 | rdoc.title = 'X::Editable::Rails'
12 | rdoc.options << '--line-numbers'
13 | rdoc.rdoc_files.include('README.rdoc')
14 | rdoc.rdoc_files.include('lib/**/*.rb')
15 | end
16 |
17 |
18 |
19 |
20 | Bundler::GemHelper.install_tasks
21 |
22 | require 'rake/testtask'
23 |
24 | Rake::TestTask.new(:test) do |t|
25 | t.libs << 'lib'
26 | t.libs << 'test'
27 | t.pattern = 'test/**/*_test.rb'
28 | t.verbose = false
29 | end
30 |
31 |
32 | task default: :test
33 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/secret_token.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Your secret key is used for verifying the integrity of signed cookies.
4 | # If you change this key, all old signed cookies will become invalid!
5 |
6 | # Make sure the secret is at least 30 characters and all random,
7 | # no regular words or you'll be exposed to dictionary attacks.
8 | # You can use `rake secret` to generate a secure secret key.
9 |
10 | # Make sure your secret_key_base is kept private
11 | # if you're sharing your code publicly.
12 | Dummy::Application.config.secret_key_base = '029c36f961f43fec4a2b2d75900636c7dcd45d8f2a046245d77971f6930c44919246db38e63ffdf4caf72725528f79278c93fc5a0ce3cf0426a228a75b5c2f03'
13 |
--------------------------------------------------------------------------------
/test/dummy/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new inflection rules using the following format. Inflections
4 | # are locale specific, and you may define rules for as many different
5 | # locales as you wish. All of these examples are active by default:
6 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
7 | # inflect.plural /^(ox)$/i, '\1en'
8 | # inflect.singular /^(ox)en/i, '\1'
9 | # inflect.irregular 'person', 'people'
10 | # inflect.uncountable %w( fish sheep )
11 | # end
12 |
13 | # These inflection rules are supported but not enabled by default:
14 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
15 | # inflect.acronym 'RESTful'
16 | # end
17 |
--------------------------------------------------------------------------------
/test/dummy/config/locales/en.yml:
--------------------------------------------------------------------------------
1 | # Files in the config/locales directory are used for internationalization
2 | # and are automatically loaded by Rails. If you want to use locales other
3 | # than English, add the necessary files in this directory.
4 | #
5 | # To use the locales, use `I18n.t`:
6 | #
7 | # I18n.t 'hello'
8 | #
9 | # In views, this is aliased to just `t`:
10 | #
11 | # <%= t('hello') %>
12 | #
13 | # To use a different locale, set it with `I18n.locale`:
14 | #
15 | # I18n.locale = :es
16 | #
17 | # This would use the information in config/locales/es.yml.
18 | #
19 | # To learn more, please read the Rails Internationalization guide
20 | # available at http://guides.rubyonrails.org/i18n.html.
21 |
22 | en:
23 | hello: "Hello world"
24 |
--------------------------------------------------------------------------------
/test/dummy/app/assets/stylesheets/application.css.sass:
--------------------------------------------------------------------------------
1 | // This is a manifest file that'll be compiled into application.css, which will include all the files
2 | // listed below.
3 | //
4 | // Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
5 | // or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
6 | //
7 | // You're free to add application-wide styles to this file and they'll appear at the top of the
8 | // compiled file, but it's generally better to create a new file per style scope.
9 | //
10 | //= require_self
11 | //= require_tree .
12 |
13 | @import "bootstrap"
14 | @import "editable/bootstrap-editable"
15 | @import "editable/inputs-ext/bootstrap-wysihtml5"
16 | @import "editable/inputs-ext/wysiwyg-color"
--------------------------------------------------------------------------------
/vendor/assets/javascripts/editable/rails/data_classes.js.coffee:
--------------------------------------------------------------------------------
1 |
2 | # make things editable that can be edited
3 |
4 | # $('.editable').editable(
5 | # success: (response, value) ->
6 | # element = $(this)
7 | # css = element.data('classes') || {}
8 | # element.removeClass(class_name) for key, class_name of css
9 | # element.addClass(css[value])
10 | # element.css('background-color', '')
11 | # )
12 |
13 | # swap CSS classes when the value changes
14 |
15 | jQuery ($) ->
16 | $("[data-classes]").on "save", (e, data) ->
17 | value = data.newValue
18 | element = $(this)
19 | css = element.data('classes') || {}
20 | element.removeClass(class_name) for key, class_name of css
21 | element.addClass(css[value])
22 | element.css('background-color', '')
23 |
24 |
--------------------------------------------------------------------------------
/test/dummy/app/assets/javascripts/application.js.coffee:
--------------------------------------------------------------------------------
1 | # This is a manifest file that'll be compiled into application.js, which will include all the files
2 | # listed below.
3 | #
4 | # Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5 | # or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6 | #
7 | # It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8 | # compiled file.
9 | #
10 | # Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11 | # about supported directives.
12 | #
13 | #= require jquery
14 | #= require bootstrap
15 | #= require editable/bootstrap-editable
16 | #= require editable/inputs-ext/wysihtml5
17 | #= require editable/inputs-ext/bootstrap-wysihtml5
18 | #= require editable/inputs-ext/wysihtml5-editable
19 | #= require editable/rails
20 | #= require_tree .
21 |
22 | $('.editable').editable()
--------------------------------------------------------------------------------
/test/dummy/config/application.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path('../boot', __FILE__)
2 |
3 | require 'rails/all'
4 |
5 | Bundler.require(*Rails.groups)
6 | require "x-editable-rails"
7 |
8 | module Dummy
9 | class Application < Rails::Application
10 | # Settings in config/environments/* take precedence over those specified here.
11 | # Application configuration should go into files in config/initializers
12 | # -- all .rb files in that directory are automatically loaded.
13 |
14 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
15 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
16 | # config.time_zone = 'Central Time (US & Canada)'
17 |
18 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
19 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
20 | # config.i18n.default_locale = :de
21 |
22 | config.i18n.available_locales = [:en, :cs]
23 | end
24 | end
25 |
26 |
--------------------------------------------------------------------------------
/x-editable-rails.gemspec:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 | lib = File.expand_path('../lib', __FILE__)
3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4 | require 'x-editable-rails/version'
5 |
6 | Gem::Specification.new do |spec|
7 | spec.name = "x-editable-rails"
8 | spec.version = X::Editable::Rails::VERSION
9 | spec.authors = ["We're in"]
10 | spec.email = ["info@wereinhq.com"]
11 | spec.description = %q{X-editable for Rails}
12 | spec.summary = %q{X-editable for Rails}
13 | spec.homepage = "https://github.com/werein/x-editable-rails"
14 | spec.license = "MIT"
15 |
16 | spec.files = Dir["{lib,vendor}/**/*"] + ["LICENSE.txt", "README.md"]
17 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19 | spec.require_paths = ["lib", "vendor"]
20 |
21 | spec.add_dependency "railties"
22 |
23 | spec.add_development_dependency "rails", "~> 4.0"
24 | spec.add_development_dependency "sqlite3"
25 | end
26 |
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/editable/inputs-ext/wysiwyg-color.css:
--------------------------------------------------------------------------------
1 | .wysiwyg-color-black {
2 | color: black;
3 | }
4 |
5 | .wysiwyg-color-silver {
6 | color: silver;
7 | }
8 |
9 | .wysiwyg-color-gray {
10 | color: gray;
11 | }
12 |
13 | .wysiwyg-color-white {
14 | color: white;
15 | }
16 |
17 | .wysiwyg-color-maroon {
18 | color: maroon;
19 | }
20 |
21 | .wysiwyg-color-red {
22 | color: red;
23 | }
24 |
25 | .wysiwyg-color-purple {
26 | color: purple;
27 | }
28 |
29 | .wysiwyg-color-fuchsia {
30 | color: fuchsia;
31 | }
32 |
33 | .wysiwyg-color-green {
34 | color: green;
35 | }
36 |
37 | .wysiwyg-color-lime {
38 | color: lime;
39 | }
40 |
41 | .wysiwyg-color-olive {
42 | color: olive;
43 | }
44 |
45 | .wysiwyg-color-yellow {
46 | color: yellow;
47 | }
48 |
49 | .wysiwyg-color-navy {
50 | color: navy;
51 | }
52 |
53 | .wysiwyg-color-blue {
54 | color: blue;
55 | }
56 |
57 | .wysiwyg-color-teal {
58 | color: teal;
59 | }
60 |
61 | .wysiwyg-color-aqua {
62 | color: aqua;
63 | }
64 |
65 | .wysiwyg-color-orange {
66 | color: orange;
67 | }
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013 Jiri Kolarik
2 |
3 | MIT License
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | "Software"), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/test/dummy/config/environments/development.rb:
--------------------------------------------------------------------------------
1 | Dummy::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb.
3 |
4 | # In the development environment your application's code is reloaded on
5 | # every request. This slows down response time but is perfect for development
6 | # since you don't have to restart the web server when you make code changes.
7 | config.cache_classes = false
8 |
9 | # Do not eager load code on boot.
10 | config.eager_load = false
11 |
12 | # Show full error reports and disable caching.
13 | config.consider_all_requests_local = true
14 | config.action_controller.perform_caching = false
15 |
16 | # Don't care if the mailer can't send.
17 | config.action_mailer.raise_delivery_errors = false
18 |
19 | # Print deprecation notices to the Rails logger.
20 | config.active_support.deprecation = :log
21 |
22 | # Raise an error on page load if there are pending migrations
23 | config.active_record.migration_error = :page_load
24 |
25 | # Debug mode disables concatenation and preprocessing of assets.
26 | # This option may cause significant delays in view rendering with a large
27 | # number of complex assets.
28 | config.assets.debug = true
29 | end
30 |
--------------------------------------------------------------------------------
/test/dummy/app/controllers/pages_controller.rb:
--------------------------------------------------------------------------------
1 | class PagesController < ApplicationController
2 | respond_to :html, :json
3 | before_action :set_page, only: [:show, :edit, :update, :destroy]
4 |
5 | # GET /pages
6 | def index
7 | @pages = Page.all
8 | respond_with @pages
9 | end
10 |
11 | # GET /pages/1
12 | def show
13 | respond_with @page
14 | end
15 |
16 | # GET /pages/new
17 | def new
18 | @page = Page.new
19 | respond_with @page
20 | end
21 |
22 | # GET /pages/1/edit
23 | def edit
24 | respond_with @page
25 | end
26 |
27 | # POST /pages
28 | def create
29 | @page = Page.new(page_params)
30 | flash[:notice] = 'Page was successfully created.' if @page.save
31 | respond_with @page
32 | end
33 |
34 | # PATCH/PUT /pages/1
35 | def update
36 | flash[:notice] = 'Page was successfully updated.' if @page.update(page_params)
37 | respond_with @page
38 | end
39 |
40 | # DELETE /pages/1
41 | def destroy
42 | @page.destroy
43 | redirect_to pages_url, notice: 'Page was successfully destroyed.'
44 | end
45 |
46 | private
47 | # Use callbacks to share common setup or constraints between actions.
48 | def set_page
49 | @page = Page.find(params[:id])
50 | end
51 |
52 | # Only allow a trusted parameter "white list" through.
53 | def page_params
54 | params.require(:page).permit(:active, :name, :description, translations_attributes: [:id, :title, :locale, :_destroy])
55 | end
56 | end
57 |
--------------------------------------------------------------------------------
/test/dummy/db/schema.rb:
--------------------------------------------------------------------------------
1 | # encoding: UTF-8
2 | # This file is auto-generated from the current state of the database. Instead
3 | # of editing this file, please use the migrations feature of Active Record to
4 | # incrementally modify your database, and then regenerate this schema definition.
5 | #
6 | # Note that this schema.rb definition is the authoritative source for your
7 | # database schema. If you need to create the application database on another
8 | # system, you should be using db:schema:load, not running all the migrations
9 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10 | # you'll amass, the slower it'll run and the greater likelihood for issues).
11 | #
12 | # It's strongly recommended that you check this file into your version control system.
13 |
14 | ActiveRecord::Schema.define(version: 20131115152536) do
15 |
16 | create_table "page_translations", force: true do |t|
17 | t.integer "page_id"
18 | t.string "locale", null: false
19 | t.string "title"
20 | t.datetime "created_at"
21 | t.datetime "updated_at"
22 | end
23 |
24 | add_index "page_translations", ["locale"], name: "index_page_translations_on_locale"
25 | add_index "page_translations", ["page_id"], name: "index_page_translations_on_page_id"
26 |
27 | create_table "pages", force: true do |t|
28 | t.boolean "active"
29 | t.string "name"
30 | t.text "description"
31 | t.datetime "created_at"
32 | t.datetime "updated_at"
33 | end
34 |
35 | end
36 |
--------------------------------------------------------------------------------
/test/dummy/public/500.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | We're sorry, but something went wrong (500)
5 |
48 |
49 |
50 |
51 |
52 |
53 |
We're sorry, but something went wrong.
54 |
55 | If you are the application owner check the logs for more information.
56 |
57 |
58 |
--------------------------------------------------------------------------------
/test/dummy/public/422.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The change you wanted was rejected (422)
5 |
48 |
49 |
50 |
51 |
52 |
53 |
The change you wanted was rejected.
54 |
Maybe you tried to change something you didn't have access to.
55 |
56 | If you are the application owner check the logs for more information.
57 |
58 |
59 |
--------------------------------------------------------------------------------
/test/dummy/public/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The page you were looking for doesn't exist (404)
5 |
48 |
49 |
50 |
51 |
52 |
53 |
The page you were looking for doesn't exist.
54 |
You may have mistyped the address or the page may have moved.
55 |
56 | If you are the application owner check the logs for more information.
57 |
58 |
59 |
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/editable/inputs-ext/bootstrap-typeahead.css:
--------------------------------------------------------------------------------
1 | .twitter-typeahead .tt-query,
2 | .twitter-typeahead .tt-hint {
3 | margin-bottom: 0;
4 | }
5 |
6 | .tt-dropdown-menu {
7 | min-width: 160px;
8 | margin-top: 2px;
9 | padding: 5px 0;
10 | background-color: #fff;
11 | border: 1px solid #ccc;
12 | border: 1px solid rgba(0,0,0,.2);
13 | *border-right-width: 2px;
14 | *border-bottom-width: 2px;
15 | -webkit-border-radius: 6px;
16 | -moz-border-radius: 6px;
17 | border-radius: 6px;
18 | -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
19 | -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
20 | box-shadow: 0 5px 10px rgba(0,0,0,.2);
21 | -webkit-background-clip: padding-box;
22 | -moz-background-clip: padding;
23 | background-clip: padding-box;
24 | }
25 |
26 | .tt-suggestion {
27 | display: block;
28 | padding: 3px 20px;
29 | }
30 |
31 | .tt-suggestion.tt-is-under-cursor {
32 | color: #fff;
33 | background-color: #0081c2;
34 | background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
35 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
36 | background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
37 | background-image: -o-linear-gradient(top, #0088cc, #0077b3);
38 | background-image: linear-gradient(to bottom, #0088cc, #0077b3);
39 | background-repeat: repeat-x;
40 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0)
41 | }
42 |
43 | .tt-suggestion.tt-is-under-cursor a {
44 | color: #fff;
45 | }
46 |
47 | .tt-suggestion p {
48 | margin: 0;
49 | }
50 |
--------------------------------------------------------------------------------
/test/dummy/config/environments/test.rb:
--------------------------------------------------------------------------------
1 | Dummy::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb.
3 |
4 | # The test environment is used exclusively to run your application's
5 | # test suite. You never need to work with it otherwise. Remember that
6 | # your test database is "scratch space" for the test suite and is wiped
7 | # and recreated between test runs. Don't rely on the data there!
8 | config.cache_classes = true
9 |
10 | # Do not eager load code on boot. This avoids loading your whole application
11 | # just for the purpose of running a single test. If you are using a tool that
12 | # preloads Rails for running tests, you may have to set it to true.
13 | config.eager_load = false
14 |
15 | # Configure static asset server for tests with Cache-Control for performance.
16 | # config.serve_static_assets = true
17 | # config.static_cache_control = "public, max-age=3600"
18 |
19 | # Show full error reports and disable caching.
20 | config.consider_all_requests_local = true
21 | config.action_controller.perform_caching = false
22 |
23 | # Raise exceptions instead of rendering exception templates.
24 | config.action_dispatch.show_exceptions = false
25 |
26 | # Disable request forgery protection in test environment.
27 | config.action_controller.allow_forgery_protection = false
28 |
29 | # Tell Action Mailer not to deliver emails to the real world.
30 | # The :test delivery method accumulates sent emails in the
31 | # ActionMailer::Base.deliveries array.
32 | config.action_mailer.delivery_method = :test
33 |
34 | # Print deprecation notices to the stderr.
35 | config.active_support.deprecation = :stderr
36 |
37 | config.active_support.test_order = :random
38 | end
39 |
--------------------------------------------------------------------------------
/vendor/assets/javascripts/editable/rails/editable_form.js.coffee:
--------------------------------------------------------------------------------
1 | unless EditableForm
2 | EditableForm = $.fn.editableform.Constructor
3 | EditableForm.prototype.saveWithUrlHook = (value) ->
4 | originalUrl = @options.url
5 | model = @options.model
6 | nestedName = @options.nested
7 | nestedId = @options.nid
8 | nestedLocale = @options.locale
9 |
10 | @options.url = (params) =>
11 | if typeof originalUrl == 'function'
12 | originalUrl.call(@options.scope, params)
13 | else if originalUrl? && @options.send != 'never'
14 | myName = params.name
15 | myValue = params.value
16 |
17 | # if there are no values in a list, add a blank value so Rails knows all values were removed
18 | if Object.prototype.toString.call(params.value) == '[object Array]' && params.value.length == 0
19 | params.value.push("")
20 |
21 | obj = {}
22 |
23 | if nestedName
24 | nested = {}
25 | nested[myName] = myValue
26 | nested['id'] = nestedId
27 |
28 | if nestedLocale
29 | nested['locale'] = nestedLocale
30 |
31 | obj[nestedName + '_attributes'] = nested
32 | else
33 | obj[myName] = myValue
34 |
35 | params[model] = obj
36 |
37 | delete params.name
38 | delete params.value
39 | delete params.pk
40 |
41 | $.ajax($.extend({
42 | url: originalUrl
43 | data: params
44 | type: 'PUT'
45 | dataType: 'json'
46 | }, @options.ajaxOptions))
47 |
48 | @saveWithoutUrlHook(value)
49 |
50 | EditableForm.prototype.saveWithoutUrlHook = EditableForm.prototype.save
51 | EditableForm.prototype.save = EditableForm.prototype.saveWithUrlHook
52 |
--------------------------------------------------------------------------------
/test/dummy/config/routes.rb:
--------------------------------------------------------------------------------
1 | Dummy::Application.routes.draw do
2 |
3 | root "welcome#index"
4 | resources :pages
5 |
6 | # The priority is based upon order of creation: first created -> highest priority.
7 | # See how all your routes lay out with "rake routes".
8 |
9 | # You can have the root of your site routed with "root"
10 | # root 'welcome#index'
11 |
12 | # Example of regular route:
13 | # get 'products/:id' => 'catalog#view'
14 |
15 | # Example of named route that can be invoked with purchase_url(id: product.id)
16 | # get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
17 |
18 | # Example resource route (maps HTTP verbs to controller actions automatically):
19 | # resources :products
20 |
21 | # Example resource route with options:
22 | # resources :products do
23 | # member do
24 | # get 'short'
25 | # post 'toggle'
26 | # end
27 | #
28 | # collection do
29 | # get 'sold'
30 | # end
31 | # end
32 |
33 | # Example resource route with sub-resources:
34 | # resources :products do
35 | # resources :comments, :sales
36 | # resource :seller
37 | # end
38 |
39 | # Example resource route with more complex sub-resources:
40 | # resources :products do
41 | # resources :comments
42 | # resources :sales do
43 | # get 'recent', on: :collection
44 | # end
45 | # end
46 |
47 | # Example resource route with concerns:
48 | # concern :toggleable do
49 | # post 'toggle'
50 | # end
51 | # resources :posts, concerns: :toggleable
52 | # resources :photos, concerns: :toggleable
53 |
54 | # Example resource route within a namespace:
55 | # namespace :admin do
56 | # # Directs /admin/products/* to Admin::ProductsController
57 | # # (app/controllers/admin/products_controller.rb)
58 | # resources :products
59 | # end
60 | end
61 |
--------------------------------------------------------------------------------
/lib/x-editable-rails/configuration.rb:
--------------------------------------------------------------------------------
1 | module X
2 | module Editable
3 | module Rails
4 | module Configuration
5 |
6 | def method_options_for(object, method)
7 | class_options_for(object).fetch(method, {})
8 | end
9 |
10 | def class_options_for(object)
11 | class_options = options.fetch(:class_options, {})
12 | class_options.fetch(object.class.name, {})
13 | end
14 |
15 | def class_options
16 | options.fetch(:class_options, {})
17 | end
18 |
19 | def options
20 | config_fn = ::Rails.root.join("config", "x-editable.yml")
21 | if File.file?(config_fn)
22 | @options ||= begin
23 | options = load_yaml_file config_fn
24 | format_class_options! options
25 | end
26 | else
27 | @options = {}
28 | end
29 | end
30 |
31 | def load_yaml_file(path)
32 | source = File.read path
33 | source = ERB.new(source).result
34 |
35 | result = YAML.load(source)
36 | result = {} if result.blank?
37 |
38 | result.with_indifferent_access
39 | end
40 |
41 | private
42 |
43 | # if the specified options are a string, convert to Hash and make the string the title
44 | def format_class_options!(options)
45 | if class_options = options[:class_options]
46 | class_options.each do |class_name, methods|
47 | methods.each do |method, method_options|
48 | unless method_options.is_a? Hash
49 | methods[method] = { title: method_options }.with_indifferent_access
50 | end
51 | end
52 | end
53 | end
54 |
55 | options
56 | end
57 |
58 | extend self
59 | end
60 | end
61 | end
62 | end
--------------------------------------------------------------------------------
/test/dummy/app/views/pages/_page.html.haml:
--------------------------------------------------------------------------------
1 | %tr{id: 'default'}
2 | %td String attribute
3 | %td= editable page, :name
4 | %td
5 | %code = editable page, :name
6 | %tr{id: 'boolean'}
7 | %td Boolean attribute Yes/no
8 | %td= editable page, :active
9 | %td
10 | %code = editable page, :active
11 | %tr{id: 'boolean_source'}
12 | %td Boolean attribute with custom source
13 | %td= editable page, :active, data: { source: ['Active', 'Disabled'] }
14 | %td
15 | %code = editable page, :active,
16 | %br/
17 | %code data: { source: ['Active', 'Disabled'] }
18 | %tr{id: 'nested_translations'}
19 | %td Globalize gem example
20 | %td= editable page, :title, nested: :translations, nid: page.translation.id
21 | %td
22 | %code = editable page, :title, nested: :translations, nid: page.translation.id
23 | %tr{id: 'select_source'}
24 | %td Select from given source
25 | %td= editable page, :name, type: :select, data: { source: ['iPhone', 'iPad', 'MacBook'] }
26 | %td
27 | %code = editable page, :name, type: :select,
28 | %br/
29 | %code data: { source: ['iPhone', 'iPad', 'MacBook'] }
30 | %tr{id: 'custom_value'}
31 | %td Custom value (Upcased name)
32 | %td= editable page, :name, value: page.name.upcase
33 | %td
34 | %code = editable page, :name, value: page.name.upcase
35 | %tr{id: 'exception'}
36 | %td Custom exception
37 | %td= editable page, :name, e: "You're not authorized"
38 | %td
39 | %code = editable page, :name, e: "You're not authorized"
40 | %tr{id: 'custom_title'}
41 | %td Custom title
42 | %td= editable page, :name, title: 'Your name please :)'
43 | %td
44 | %code = editable page, :name, title: 'Your name please :)'
45 | %tr{id: 'custom_class'}
46 | %td Custom class (float right)
47 | %td= editable page, :name, class: 'pull-right'
48 | %td
49 | %code = editable page, :name, class: 'pull-right'
50 | %tr{id: 'custom_tag'}
51 | %td Custom tag (its header)
52 | %td= editable page, :name, tag: 'h3'
53 | %td
54 | %code = editable page, :name, tag: 'h3'
55 | %tr{id: 'type_textarea'}
56 | %td Textarea
57 | %td= editable page, :description, type: :textarea
58 | %td
59 | %code = editable page, :description, type: :textarea
60 | %tr{id: 'type_wysihtml5'}
61 | %td Wysihtml5
62 | %td= editable page, :description, type: :wysihtml5
63 | %td
64 | %code = editable page, :description, type: :wysihtml5
--------------------------------------------------------------------------------
/vendor/assets/javascripts/editable/inputs-ext/typeahead-editable.js:
--------------------------------------------------------------------------------
1 | /**
2 | Typeahead.js input, based on [Twitter Typeahead](http://twitter.github.io/typeahead.js).
3 | It is mainly replacement of typeahead in Bootstrap 3.
4 |
5 |
6 | @class typeaheadjs
7 | @extends text
8 | @since 1.5.0
9 | @final
10 | @example
11 |
12 |
30 | **/
31 | (function ($) {
32 | "use strict";
33 |
34 | var Constructor = function (options) {
35 | this.init('typeaheadjs', options, Constructor.defaults);
36 | };
37 |
38 | $.fn.editableutils.inherit(Constructor, $.fn.editabletypes.text);
39 |
40 | $.extend(Constructor.prototype, {
41 | render: function() {
42 | this.renderClear();
43 | this.setClass();
44 | this.setAttr('placeholder');
45 | this.$input.typeahead(this.options.typeahead);
46 |
47 | // copy `input-sm | input-lg` classes to placeholder input
48 | if($.fn.editableform.engine === 'bs3') {
49 | if(this.$input.hasClass('input-sm')) {
50 | this.$input.siblings('input.tt-hint').addClass('input-sm');
51 | }
52 | if(this.$input.hasClass('input-lg')) {
53 | this.$input.siblings('input.tt-hint').addClass('input-lg');
54 | }
55 | }
56 | }
57 | });
58 |
59 | Constructor.defaults = $.extend({}, $.fn.editabletypes.list.defaults, {
60 | /**
61 | @property tpl
62 | @default
63 | **/
64 | tpl:'',
65 | /**
66 | Configuration of typeahead itself.
67 | [Full list of options](https://github.com/twitter/typeahead.js#dataset).
68 |
69 | @property typeahead
70 | @type object
71 | @default null
72 | **/
73 | typeahead: null,
74 | /**
75 | Whether to show `clear` button
76 |
77 | @property clear
78 | @type boolean
79 | @default true
80 | **/
81 | clear: true
82 | });
83 |
84 | $.fn.editabletypes.typeaheadjs = Constructor;
85 |
86 | }(window.jQuery));
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/editable/inputs-ext/bootstrap-wysihtml5.css:
--------------------------------------------------------------------------------
1 | ul.wysihtml5-toolbar {
2 | margin: 0;
3 | padding: 0;
4 | display: block;
5 | }
6 |
7 | ul.wysihtml5-toolbar::after {
8 | clear: both;
9 | display: table;
10 | content: "";
11 | }
12 |
13 | ul.wysihtml5-toolbar > li {
14 | float: left;
15 | display: list-item;
16 | list-style: none;
17 | margin: 0 5px 10px 0;
18 | }
19 |
20 | ul.wysihtml5-toolbar a[data-wysihtml5-command=bold] {
21 | font-weight: bold;
22 | }
23 |
24 | ul.wysihtml5-toolbar a[data-wysihtml5-command=italic] {
25 | font-style: italic;
26 | }
27 |
28 | ul.wysihtml5-toolbar a[data-wysihtml5-command=underline] {
29 | text-decoration: underline;
30 | }
31 |
32 | ul.wysihtml5-toolbar a.btn.wysihtml5-command-active {
33 | background-image: none;
34 | -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);
35 | -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);
36 | box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);
37 | background-color: #E6E6E6;
38 | background-color: #D9D9D9;
39 | outline: 0;
40 | }
41 |
42 | ul.wysihtml5-commands-disabled .dropdown-menu {
43 | display: none !important;
44 | }
45 |
46 | ul.wysihtml5-toolbar div.wysihtml5-colors {
47 | display:block;
48 | width: 50px;
49 | height: 20px;
50 | margin-top: 2px;
51 | margin-left: 5px;
52 | position: absolute;
53 | pointer-events: none;
54 | }
55 |
56 | ul.wysihtml5-toolbar a.wysihtml5-colors-title {
57 | padding-left: 70px;
58 | }
59 |
60 | ul.wysihtml5-toolbar div[data-wysihtml5-command-value="black"] {
61 | background: black !important;
62 | }
63 |
64 | ul.wysihtml5-toolbar div[data-wysihtml5-command-value="silver"] {
65 | background: silver !important;
66 | }
67 |
68 | ul.wysihtml5-toolbar div[data-wysihtml5-command-value="gray"] {
69 | background: gray !important;
70 | }
71 |
72 | ul.wysihtml5-toolbar div[data-wysihtml5-command-value="maroon"] {
73 | background: maroon !important;
74 | }
75 |
76 | ul.wysihtml5-toolbar div[data-wysihtml5-command-value="red"] {
77 | background: red !important;
78 | }
79 |
80 | ul.wysihtml5-toolbar div[data-wysihtml5-command-value="purple"] {
81 | background: purple !important;
82 | }
83 |
84 | ul.wysihtml5-toolbar div[data-wysihtml5-command-value="green"] {
85 | background: green !important;
86 | }
87 |
88 | ul.wysihtml5-toolbar div[data-wysihtml5-command-value="olive"] {
89 | background: olive !important;
90 | }
91 |
92 | ul.wysihtml5-toolbar div[data-wysihtml5-command-value="navy"] {
93 | background: navy !important;
94 | }
95 |
96 | ul.wysihtml5-toolbar div[data-wysihtml5-command-value="blue"] {
97 | background: blue !important;
98 | }
99 |
100 | ul.wysihtml5-toolbar div[data-wysihtml5-command-value="orange"] {
101 | background: orange !important;
102 | }
103 |
--------------------------------------------------------------------------------
/test/dummy/config/environments/production.rb:
--------------------------------------------------------------------------------
1 | Dummy::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb.
3 |
4 | # Code is not reloaded between requests.
5 | config.cache_classes = true
6 |
7 | # Eager load code on boot. This eager loads most of Rails and
8 | # your application in memory, allowing both thread web servers
9 | # and those relying on copy on write to perform better.
10 | # Rake tasks automatically ignore this option for performance.
11 | config.eager_load = true
12 |
13 | # Full error reports are disabled and caching is turned on.
14 | config.consider_all_requests_local = false
15 | config.action_controller.perform_caching = true
16 |
17 | # Enable Rack::Cache to put a simple HTTP cache in front of your application
18 | # Add `rack-cache` to your Gemfile before enabling this.
19 | # For large-scale production use, consider using a caching reverse proxy like nginx, varnish or squid.
20 | # config.action_dispatch.rack_cache = true
21 |
22 | # Disable Rails's static asset server (Apache or nginx will already do this).
23 | # config.serve_static_assets = false
24 |
25 | # Compress JavaScripts and CSS.
26 | config.assets.js_compressor = :uglifier
27 | # config.assets.css_compressor = :sass
28 |
29 | # Do not fallback to assets pipeline if a precompiled asset is missed.
30 | config.assets.compile = true
31 |
32 | # Generate digests for assets URLs.
33 | config.assets.digest = false
34 |
35 | # Version of your assets, change this if you want to expire all your assets.
36 | config.assets.version = '1.0'
37 |
38 | # Specifies the header that your server uses for sending files.
39 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
40 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
41 |
42 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
43 | # config.force_ssl = true
44 |
45 | # Set to :debug to see everything in the log.
46 | config.log_level = :info
47 |
48 | # Prepend all log lines with the following tags.
49 | # config.log_tags = [ :subdomain, :uuid ]
50 |
51 | # Use a different logger for distributed setups.
52 | # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
53 |
54 | # Use a different cache store in production.
55 | # config.cache_store = :mem_cache_store
56 |
57 | # Enable serving of images, stylesheets, and JavaScripts from an asset server.
58 | # config.action_controller.asset_host = "http://assets.example.com"
59 |
60 | # Precompile additional assets.
61 | # application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
62 | # config.assets.precompile += %w( search.js )
63 |
64 | # Ignore bad email addresses and do not raise email delivery errors.
65 | # Set this to true and configure the email server for immediate delivery to raise delivery errors.
66 | # config.action_mailer.raise_delivery_errors = false
67 |
68 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
69 | # the I18n.default_locale when a translation can not be found).
70 | config.i18n.fallbacks = true
71 |
72 | # Send deprecation notices to registered listeners.
73 | config.active_support.deprecation = :notify
74 |
75 | # Disable automatic flushing of the log to improve performance.
76 | # config.autoflush_log = false
77 |
78 | # Use default logging formatter so that PID and timestamp are not suppressed.
79 | config.log_formatter = ::Logger::Formatter.new
80 | end
81 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | PATH
2 | remote: .
3 | specs:
4 | x-editable-rails (1.5.5)
5 | railties
6 |
7 | GEM
8 | remote: https://rubygems.org/
9 | specs:
10 | actionmailer (4.2.4)
11 | actionpack (= 4.2.4)
12 | actionview (= 4.2.4)
13 | activejob (= 4.2.4)
14 | mail (~> 2.5, >= 2.5.4)
15 | rails-dom-testing (~> 1.0, >= 1.0.5)
16 | actionpack (4.2.4)
17 | actionview (= 4.2.4)
18 | activesupport (= 4.2.4)
19 | rack (~> 1.6)
20 | rack-test (~> 0.6.2)
21 | rails-dom-testing (~> 1.0, >= 1.0.5)
22 | rails-html-sanitizer (~> 1.0, >= 1.0.2)
23 | actionview (4.2.4)
24 | activesupport (= 4.2.4)
25 | builder (~> 3.1)
26 | erubis (~> 2.7.0)
27 | rails-dom-testing (~> 1.0, >= 1.0.5)
28 | rails-html-sanitizer (~> 1.0, >= 1.0.2)
29 | activejob (4.2.4)
30 | activesupport (= 4.2.4)
31 | globalid (>= 0.3.0)
32 | activemodel (4.2.4)
33 | activesupport (= 4.2.4)
34 | builder (~> 3.1)
35 | activerecord (4.2.4)
36 | activemodel (= 4.2.4)
37 | activesupport (= 4.2.4)
38 | arel (~> 6.0)
39 | activesupport (4.2.4)
40 | i18n (~> 0.7)
41 | json (~> 1.7, >= 1.7.7)
42 | minitest (~> 5.1)
43 | thread_safe (~> 0.3, >= 0.3.4)
44 | tzinfo (~> 1.1)
45 | arel (6.0.3)
46 | autoprefixer-rails (6.0.3)
47 | execjs
48 | json
49 | bootstrap-sass (3.3.5)
50 | autoprefixer-rails (>= 5.0.0.1)
51 | sass (>= 3.2.19)
52 | builder (3.2.2)
53 | coffee-rails (4.1.0)
54 | coffee-script (>= 2.2.0)
55 | railties (>= 4.0.0, < 5.0)
56 | coffee-script (2.4.1)
57 | coffee-script-source
58 | execjs
59 | coffee-script-source (1.9.1.1)
60 | erubis (2.7.0)
61 | execjs (2.6.0)
62 | globalid (0.3.6)
63 | activesupport (>= 4.1.0)
64 | globalize (4.0.3)
65 | activemodel (>= 4.0.0, < 5)
66 | activerecord (>= 4.0.0, < 5)
67 | haml (4.0.7)
68 | tilt
69 | i18n (0.7.0)
70 | jquery-rails (4.2.1)
71 | rails-dom-testing (>= 1, < 3)
72 | railties (>= 4.2.0)
73 | thor (>= 0.14, < 2.0)
74 | json (1.8.3)
75 | loofah (2.0.3)
76 | nokogiri (>= 1.5.9)
77 | mail (2.6.3)
78 | mime-types (>= 1.16, < 3)
79 | mime-types (2.6.2)
80 | mini_portile (0.6.2)
81 | minitest (5.8.0)
82 | nokogiri (1.6.6.2)
83 | mini_portile (~> 0.6.0)
84 | pg (0.18.4)
85 | rack (1.6.4)
86 | rack-test (0.6.3)
87 | rack (>= 1.0)
88 | rails (4.2.4)
89 | actionmailer (= 4.2.4)
90 | actionpack (= 4.2.4)
91 | actionview (= 4.2.4)
92 | activejob (= 4.2.4)
93 | activemodel (= 4.2.4)
94 | activerecord (= 4.2.4)
95 | activesupport (= 4.2.4)
96 | bundler (>= 1.3.0, < 2.0)
97 | railties (= 4.2.4)
98 | sprockets-rails
99 | rails-deprecated_sanitizer (1.0.3)
100 | activesupport (>= 4.2.0.alpha)
101 | rails-dom-testing (1.0.7)
102 | activesupport (>= 4.2.0.beta, < 5.0)
103 | nokogiri (~> 1.6.0)
104 | rails-deprecated_sanitizer (>= 1.0.1)
105 | rails-html-sanitizer (1.0.2)
106 | loofah (~> 2.0)
107 | rails_12factor (0.0.3)
108 | rails_serve_static_assets
109 | rails_stdout_logging
110 | rails_serve_static_assets (0.0.4)
111 | rails_stdout_logging (0.0.4)
112 | railties (4.2.4)
113 | actionpack (= 4.2.4)
114 | activesupport (= 4.2.4)
115 | rake (>= 0.8.7)
116 | thor (>= 0.18.1, < 2.0)
117 | rake (10.4.2)
118 | responders (2.1.0)
119 | railties (>= 4.2.0, < 5)
120 | sass (3.4.19)
121 | sass-rails (5.0.6)
122 | railties (>= 4.0.0, < 6)
123 | sass (~> 3.1)
124 | sprockets (>= 2.8, < 4.0)
125 | sprockets-rails (>= 2.0, < 4.0)
126 | tilt (>= 1.1, < 3)
127 | sprockets (3.3.4)
128 | rack (~> 1.0)
129 | sprockets-rails (2.3.3)
130 | actionpack (>= 3.0)
131 | activesupport (>= 3.0)
132 | sprockets (>= 2.8, < 4.0)
133 | sqlite3 (1.3.10)
134 | thor (0.19.1)
135 | thread_safe (0.3.5)
136 | tilt (2.0.1)
137 | tzinfo (1.2.2)
138 | thread_safe (~> 0.1)
139 | uglifier (2.7.2)
140 | execjs (>= 0.3.0)
141 | json (>= 1.8.0)
142 |
143 | PLATFORMS
144 | ruby
145 |
146 | DEPENDENCIES
147 | bootstrap-sass
148 | coffee-rails
149 | globalize
150 | haml
151 | jquery-rails
152 | pg
153 | rails (~> 4.0)
154 | rails_12factor
155 | responders
156 | sass-rails
157 | sprockets
158 | sqlite3
159 | uglifier
160 | x-editable-rails!
161 |
162 | BUNDLED WITH
163 | 1.10.6
164 |
--------------------------------------------------------------------------------
/vendor/assets/javascripts/editable/inputs-ext/wysihtml5-editable.js:
--------------------------------------------------------------------------------
1 | /**
2 | Bootstrap wysihtml5 editor. Based on [bootstrap-wysihtml5](https://github.com/jhollingworth/bootstrap-wysihtml5).
3 | You should include **manually** distributives of `wysihtml5` and `bootstrap-wysihtml5`:
4 |
5 |
6 |
7 |
8 |
9 | And also include `wysihtml5.js` from `inputs-ext` directory of x-editable:
10 |
11 |
12 |
13 | **Note:** It's better to use fresh bootstrap-wysihtml5 from it's [master branch](https://github.com/jhollingworth/bootstrap-wysihtml5/tree/master/src) as there is update for correct image insertion.
14 |
15 | @class wysihtml5
16 | @extends abstractinput
17 | @final
18 | @since 1.4.0
19 | @example
20 |
21 |
29 | **/
30 | (function ($) {
31 | "use strict";
32 |
33 | var Wysihtml5 = function (options) {
34 | this.init('wysihtml5', options, Wysihtml5.defaults);
35 |
36 | //extend wysihtml5 manually as $.extend not recursive
37 | this.options.wysihtml5 = $.extend({}, Wysihtml5.defaults.wysihtml5, options.wysihtml5);
38 | };
39 |
40 | $.fn.editableutils.inherit(Wysihtml5, $.fn.editabletypes.abstractinput);
41 |
42 | $.extend(Wysihtml5.prototype, {
43 | render: function () {
44 | var deferred = $.Deferred(),
45 | msieOld;
46 |
47 | //generate unique id as it required for wysihtml5
48 | this.$input.attr('id', 'textarea_'+(new Date()).getTime());
49 |
50 | this.setClass();
51 | this.setAttr('placeholder');
52 |
53 | //resolve deffered when widget loaded
54 | $.extend(this.options.wysihtml5, {
55 | events: {
56 | load: function() {
57 | deferred.resolve();
58 | }
59 | }
60 | });
61 |
62 | this.$input.wysihtml5(this.options.wysihtml5);
63 |
64 | /*
65 | In IE8 wysihtml5 iframe stays on the same line with buttons toolbar (inside popover).
66 | The only solution I found is to add
. If you fine better way, please send PR.
67 | */
68 | msieOld = /msie\s*(8|7|6)/.test(navigator.userAgent.toLowerCase());
69 | if(msieOld) {
70 | this.$input.before('
');
71 | }
72 |
73 | return deferred.promise();
74 | },
75 |
76 | valueIsEncoded: true,
77 |
78 | value2html: function(value, element) {
79 | $(element).html(value);
80 | this.valueIsEncoded = false;
81 | },
82 |
83 | html2value: function(html) {
84 | return html;
85 | },
86 |
87 | value2input: function(value) {
88 | value = (this.valueIsEncoded ? this.base65decode(value) : value);
89 | this.$input.data("wysihtml5").editor.setValue(value, true);
90 | },
91 |
92 | base65decode: function(value) {
93 | return decodeURIComponent( escape( atob( value.replace(/\s/g, ''))));
94 | },
95 |
96 | activate: function() {
97 | this.$input.data("wysihtml5").editor.focus();
98 | },
99 |
100 | isEmpty: function($element) {
101 | if($.trim($element.html()) === '') {
102 | return true;
103 | } else if($.trim($element.text()) !== '') {
104 | return false;
105 | } else {
106 | //e.g. '
', '
', ''
107 | return !$element.height() || !$element.width();
108 | }
109 | }
110 | });
111 |
112 | Wysihtml5.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
113 | /**
114 | @property tpl
115 | @default
116 | **/
117 | tpl:'',
118 | /**
119 | @property inputclass
120 | @default editable-wysihtml5
121 | **/
122 | inputclass: 'editable-wysihtml5',
123 | /**
124 | Placeholder attribute of input. Shown when input is empty.
125 |
126 | @property placeholder
127 | @type string
128 | @default null
129 | **/
130 | placeholder: null,
131 | /**
132 | Wysihtml5 default options.
133 | See https://github.com/jhollingworth/bootstrap-wysihtml5#options
134 |
135 | @property wysihtml5
136 | @type object
137 | @default {stylesheets: false}
138 | **/
139 | wysihtml5: {
140 | stylesheets: false //see https://github.com/jhollingworth/bootstrap-wysihtml5/issues/183
141 | }
142 | });
143 |
144 | $.fn.editabletypes.wysihtml5 = Wysihtml5;
145 |
146 | }(window.jQuery));
147 |
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/editable/jquery-editable.scss:
--------------------------------------------------------------------------------
1 | /*! X-editable - v1.5.0
2 | * In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
3 | * http://github.com/vitalets/x-editable
4 | * Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */
5 | .editableform {
6 | margin-bottom: 0; /* overwrites bootstrap margin */
7 | }
8 |
9 | .editableform .control-group {
10 | margin-bottom: 0; /* overwrites bootstrap margin */
11 | white-space: nowrap; /* prevent wrapping buttons on new line */
12 | line-height: 20px; /* overwriting bootstrap line-height. See #133 */
13 | }
14 |
15 | .editable-buttons {
16 | display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
17 | vertical-align: top;
18 | margin-left: 7px;
19 | /* inline-block emulation for IE7*/
20 | zoom: 1;
21 | *display: inline;
22 | }
23 |
24 | .editable-buttons.editable-buttons-bottom {
25 | display: block;
26 | margin-top: 7px;
27 | margin-left: 0;
28 | }
29 |
30 | .editable-input {
31 | vertical-align: top;
32 | display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
33 | width: auto; /* bootstrap-responsive has width: 100% that breakes layout */
34 | white-space: normal; /* reset white-space decalred in parent*/
35 | /* display-inline emulation for IE7*/
36 | zoom: 1;
37 | *display: inline;
38 | }
39 |
40 | .editable-buttons .editable-cancel {
41 | margin-left: 7px;
42 | }
43 |
44 | /*for jquery-ui buttons need set height to look more pretty*/
45 | .editable-buttons button.ui-button-icon-only {
46 | height: 24px;
47 | width: 30px;
48 | }
49 |
50 | .editableform-loading {
51 | background: image-url('editable/loading.gif') center center no-repeat;
52 | height: 25px;
53 | width: auto;
54 | min-width: 25px;
55 | }
56 |
57 | .editable-inline .editableform-loading {
58 | background-position: left 5px;
59 | }
60 |
61 | .editable-error-block {
62 | max-width: 300px;
63 | margin: 5px 0 0 0;
64 | width: auto;
65 | white-space: normal;
66 | }
67 |
68 | /*add padding for jquery ui*/
69 | .editable-error-block.ui-state-error {
70 | padding: 3px;
71 | }
72 |
73 | .editable-error {
74 | color: red;
75 | }
76 |
77 | /* ---- For specific types ---- */
78 |
79 | .editableform .editable-date {
80 | padding: 0;
81 | margin: 0;
82 | float: left;
83 | }
84 |
85 | /* move datepicker icon to center of add-on button. See https://github.com/vitalets/x-editable/issues/183 */
86 | .editable-inline .add-on .icon-th {
87 | margin-top: 3px;
88 | margin-left: 1px;
89 | }
90 |
91 |
92 | /* checklist vertical alignment */
93 | .editable-checklist label input[type="checkbox"],
94 | .editable-checklist label span {
95 | vertical-align: middle;
96 | margin: 0;
97 | }
98 |
99 | .editable-checklist label {
100 | white-space: nowrap;
101 | }
102 |
103 | /* set exact width of textarea to fit buttons toolbar */
104 | .editable-wysihtml5 {
105 | width: 566px;
106 | height: 250px;
107 | }
108 |
109 | /* clear button shown as link in date inputs */
110 | .editable-clear {
111 | clear: both;
112 | font-size: 0.9em;
113 | text-decoration: none;
114 | text-align: right;
115 | }
116 |
117 | /* IOS-style clear button for text inputs */
118 | .editable-clear-x {
119 | background: image-url('editable/clear.png') center center no-repeat;
120 | display: block;
121 | width: 13px;
122 | height: 13px;
123 | position: absolute;
124 | opacity: 0.6;
125 | z-index: 100;
126 |
127 | top: 50%;
128 | right: 6px;
129 | margin-top: -6px;
130 |
131 | }
132 |
133 | .editable-clear-x:hover {
134 | opacity: 1;
135 | }
136 |
137 | .editable-pre-wrapped {
138 | white-space: pre-wrap;
139 | }
140 | .editable-container.editable-popup {
141 | max-width: none !important; /* without this rule poshytip/tooltip does not stretch */
142 | }
143 |
144 | .editable-container.popover {
145 | width: auto; /* without this rule popover does not stretch */
146 | }
147 |
148 | .editable-container.editable-inline {
149 | display: inline-block;
150 | vertical-align: middle;
151 | width: auto;
152 | /* inline-block emulation for IE7*/
153 | zoom: 1;
154 | *display: inline;
155 | }
156 |
157 | .editable-container.ui-widget {
158 | font-size: inherit; /* jqueryui widget font 1.1em too big, overwrite it */
159 | z-index: 9990; /* should be less than select2 dropdown z-index to close dropdown first when click */
160 | }
161 | .editable-click,
162 | a.editable-click,
163 | a.editable-click:hover {
164 | text-decoration: none;
165 | border-bottom: dashed 1px #0088cc;
166 | }
167 |
168 | .editable-click.editable-disabled,
169 | a.editable-click.editable-disabled,
170 | a.editable-click.editable-disabled:hover {
171 | color: #585858;
172 | cursor: default;
173 | border-bottom: none;
174 | }
175 |
176 | .editable-empty, .editable-empty:hover, .editable-empty:focus{
177 | font-style: italic;
178 | color: #DD1144;
179 | /* border-bottom: none; */
180 | text-decoration: none;
181 | }
182 |
183 | .editable-unsaved {
184 | font-weight: bold;
185 | }
186 |
187 | .editable-unsaved:after {
188 | /* content: '*'*/
189 | }
190 |
191 | .editable-bg-transition {
192 | -webkit-transition: background-color 1400ms ease-out;
193 | -moz-transition: background-color 1400ms ease-out;
194 | -o-transition: background-color 1400ms ease-out;
195 | -ms-transition: background-color 1400ms ease-out;
196 | transition: background-color 1400ms ease-out;
197 | }
198 |
199 | /*see https://github.com/vitalets/x-editable/issues/139 */
200 | .form-horizontal .editable
201 | {
202 | padding-top: 5px;
203 | display:inline-block;
204 | }
205 |
206 |
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/editable/jqueryui-editable.scss:
--------------------------------------------------------------------------------
1 | /*! X-editable - v1.5.0
2 | * In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
3 | * http://github.com/vitalets/x-editable
4 | * Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */
5 | .editableform {
6 | margin-bottom: 0; /* overwrites bootstrap margin */
7 | }
8 |
9 | .editableform .control-group {
10 | margin-bottom: 0; /* overwrites bootstrap margin */
11 | white-space: nowrap; /* prevent wrapping buttons on new line */
12 | line-height: 20px; /* overwriting bootstrap line-height. See #133 */
13 | }
14 |
15 | .editable-buttons {
16 | display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
17 | vertical-align: top;
18 | margin-left: 7px;
19 | /* inline-block emulation for IE7*/
20 | zoom: 1;
21 | *display: inline;
22 | }
23 |
24 | .editable-buttons.editable-buttons-bottom {
25 | display: block;
26 | margin-top: 7px;
27 | margin-left: 0;
28 | }
29 |
30 | .editable-input {
31 | vertical-align: top;
32 | display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
33 | width: auto; /* bootstrap-responsive has width: 100% that breakes layout */
34 | white-space: normal; /* reset white-space decalred in parent*/
35 | /* display-inline emulation for IE7*/
36 | zoom: 1;
37 | *display: inline;
38 | }
39 |
40 | .editable-buttons .editable-cancel {
41 | margin-left: 7px;
42 | }
43 |
44 | /*for jquery-ui buttons need set height to look more pretty*/
45 | .editable-buttons button.ui-button-icon-only {
46 | height: 24px;
47 | width: 30px;
48 | }
49 |
50 | .editableform-loading {
51 | background: image-url('editable/loading.gif') center center no-repeat;
52 | height: 25px;
53 | width: auto;
54 | min-width: 25px;
55 | }
56 |
57 | .editable-inline .editableform-loading {
58 | background-position: left 5px;
59 | }
60 |
61 | .editable-error-block {
62 | max-width: 300px;
63 | margin: 5px 0 0 0;
64 | width: auto;
65 | white-space: normal;
66 | }
67 |
68 | /*add padding for jquery ui*/
69 | .editable-error-block.ui-state-error {
70 | padding: 3px;
71 | }
72 |
73 | .editable-error {
74 | color: red;
75 | }
76 |
77 | /* ---- For specific types ---- */
78 |
79 | .editableform .editable-date {
80 | padding: 0;
81 | margin: 0;
82 | float: left;
83 | }
84 |
85 | /* move datepicker icon to center of add-on button. See https://github.com/vitalets/x-editable/issues/183 */
86 | .editable-inline .add-on .icon-th {
87 | margin-top: 3px;
88 | margin-left: 1px;
89 | }
90 |
91 |
92 | /* checklist vertical alignment */
93 | .editable-checklist label input[type="checkbox"],
94 | .editable-checklist label span {
95 | vertical-align: middle;
96 | margin: 0;
97 | }
98 |
99 | .editable-checklist label {
100 | white-space: nowrap;
101 | }
102 |
103 | /* set exact width of textarea to fit buttons toolbar */
104 | .editable-wysihtml5 {
105 | width: 566px;
106 | height: 250px;
107 | }
108 |
109 | /* clear button shown as link in date inputs */
110 | .editable-clear {
111 | clear: both;
112 | font-size: 0.9em;
113 | text-decoration: none;
114 | text-align: right;
115 | }
116 |
117 | /* IOS-style clear button for text inputs */
118 | .editable-clear-x {
119 | background: image-url('editable/clear.png') center center no-repeat;
120 | display: block;
121 | width: 13px;
122 | height: 13px;
123 | position: absolute;
124 | opacity: 0.6;
125 | z-index: 100;
126 |
127 | top: 50%;
128 | right: 6px;
129 | margin-top: -6px;
130 |
131 | }
132 |
133 | .editable-clear-x:hover {
134 | opacity: 1;
135 | }
136 |
137 | .editable-pre-wrapped {
138 | white-space: pre-wrap;
139 | }
140 | .editable-container.editable-popup {
141 | max-width: none !important; /* without this rule poshytip/tooltip does not stretch */
142 | }
143 |
144 | .editable-container.popover {
145 | width: auto; /* without this rule popover does not stretch */
146 | }
147 |
148 | .editable-container.editable-inline {
149 | display: inline-block;
150 | vertical-align: middle;
151 | width: auto;
152 | /* inline-block emulation for IE7*/
153 | zoom: 1;
154 | *display: inline;
155 | }
156 |
157 | .editable-container.ui-widget {
158 | font-size: inherit; /* jqueryui widget font 1.1em too big, overwrite it */
159 | z-index: 9990; /* should be less than select2 dropdown z-index to close dropdown first when click */
160 | }
161 | .editable-click,
162 | a.editable-click,
163 | a.editable-click:hover {
164 | text-decoration: none;
165 | border-bottom: dashed 1px #0088cc;
166 | }
167 |
168 | .editable-click.editable-disabled,
169 | a.editable-click.editable-disabled,
170 | a.editable-click.editable-disabled:hover {
171 | color: #585858;
172 | cursor: default;
173 | border-bottom: none;
174 | }
175 |
176 | .editable-empty, .editable-empty:hover, .editable-empty:focus{
177 | font-style: italic;
178 | color: #DD1144;
179 | /* border-bottom: none; */
180 | text-decoration: none;
181 | }
182 |
183 | .editable-unsaved {
184 | font-weight: bold;
185 | }
186 |
187 | .editable-unsaved:after {
188 | /* content: '*'*/
189 | }
190 |
191 | .editable-bg-transition {
192 | -webkit-transition: background-color 1400ms ease-out;
193 | -moz-transition: background-color 1400ms ease-out;
194 | -o-transition: background-color 1400ms ease-out;
195 | -ms-transition: background-color 1400ms ease-out;
196 | transition: background-color 1400ms ease-out;
197 | }
198 |
199 | /*see https://github.com/vitalets/x-editable/issues/139 */
200 | .form-horizontal .editable
201 | {
202 | padding-top: 5px;
203 | display:inline-block;
204 | }
205 |
206 |
--------------------------------------------------------------------------------
/vendor/assets/javascripts/editable/inputs-ext/address.js:
--------------------------------------------------------------------------------
1 | /**
2 | Address editable input.
3 | Internally value stored as {city: "Moscow", street: "Lenina", building: "15"}
4 |
5 | @class address
6 | @extends abstractinput
7 | @final
8 | @example
9 | awesome
10 |
23 | **/
24 | (function ($) {
25 | "use strict";
26 |
27 | var Address = function (options) {
28 | this.init('address', options, Address.defaults);
29 | };
30 |
31 | //inherit from Abstract input
32 | $.fn.editableutils.inherit(Address, $.fn.editabletypes.abstractinput);
33 |
34 | $.extend(Address.prototype, {
35 | /**
36 | Renders input from tpl
37 |
38 | @method render()
39 | **/
40 | render: function() {
41 | this.$input = this.$tpl.find('input');
42 | },
43 |
44 | /**
45 | Default method to show value in element. Can be overwritten by display option.
46 |
47 | @method value2html(value, element)
48 | **/
49 | value2html: function(value, element) {
50 | if(!value) {
51 | $(element).empty();
52 | return;
53 | }
54 | var html = $('').text(value.city).html() + ', ' + $('
').text(value.street).html() + ' st., bld. ' + $('
').text(value.building).html();
55 | $(element).html(html);
56 | },
57 |
58 | /**
59 | Gets value from element's html
60 |
61 | @method html2value(html)
62 | **/
63 | html2value: function(html) {
64 | /*
65 | you may write parsing method to get value by element's html
66 | e.g. "Moscow, st. Lenina, bld. 15" => {city: "Moscow", street: "Lenina", building: "15"}
67 | but for complex structures it's not recommended.
68 | Better set value directly via javascript, e.g.
69 | editable({
70 | value: {
71 | city: "Moscow",
72 | street: "Lenina",
73 | building: "15"
74 | }
75 | });
76 | */
77 | return null;
78 | },
79 |
80 | /**
81 | Converts value to string.
82 | It is used in internal comparing (not for sending to server).
83 |
84 | @method value2str(value)
85 | **/
86 | value2str: function(value) {
87 | var str = '';
88 | if(value) {
89 | for(var k in value) {
90 | str = str + k + ':' + value[k] + ';';
91 | }
92 | }
93 | return str;
94 | },
95 |
96 | /*
97 | Converts string to value. Used for reading value from 'data-value' attribute.
98 |
99 | @method str2value(str)
100 | */
101 | str2value: function(str) {
102 | /*
103 | this is mainly for parsing value defined in data-value attribute.
104 | If you will always set value by javascript, no need to overwrite it
105 | */
106 | return str;
107 | },
108 |
109 | /**
110 | Sets value of input.
111 |
112 | @method value2input(value)
113 | @param {mixed} value
114 | **/
115 | value2input: function(value) {
116 | if(!value) {
117 | return;
118 | }
119 | this.$input.filter('[name="city"]').val(value.city);
120 | this.$input.filter('[name="street"]').val(value.street);
121 | this.$input.filter('[name="building"]').val(value.building);
122 | },
123 |
124 | /**
125 | Returns value of input.
126 |
127 | @method input2value()
128 | **/
129 | input2value: function() {
130 | return {
131 | city: this.$input.filter('[name="city"]').val(),
132 | street: this.$input.filter('[name="street"]').val(),
133 | building: this.$input.filter('[name="building"]').val()
134 | };
135 | },
136 |
137 | /**
138 | Activates input: sets focus on the first field.
139 |
140 | @method activate()
141 | **/
142 | activate: function() {
143 | this.$input.filter('[name="city"]').focus();
144 | },
145 |
146 | /**
147 | Attaches handler to submit form in case of 'showbuttons=false' mode
148 |
149 | @method autosubmit()
150 | **/
151 | autosubmit: function() {
152 | this.$input.keydown(function (e) {
153 | if (e.which === 13) {
154 | $(this).closest('form').submit();
155 | }
156 | });
157 | }
158 | });
159 |
160 | Address.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
161 | tpl: '
'+
162 | '
'+
163 | '
',
164 |
165 | inputclass: ''
166 | });
167 |
168 | $.fn.editabletypes.address = Address;
169 |
170 | }(window.jQuery));
--------------------------------------------------------------------------------
/test/view_helpers_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | class ViewHelpersTest < ActionView::TestCase
4 | include X::Editable::Rails::ViewHelpers
5 |
6 | class Subject < OpenStruct
7 | include ActiveModel::Model
8 |
9 | attr_accessor :id, :name, :content, :active
10 |
11 | def self.model_name
12 | ActiveModel::Name.new(self, nil, "Page")
13 | end
14 |
15 | def initialize(attributes={})
16 | super(attributes.merge(id: 1, name: "test subject"))
17 | end
18 | end
19 |
20 | test "editable should escape unsafe values" do
21 | subject = Subject.new(content: "
unsafe content
")
22 | assert_match %r{<h1>unsafe content</h1>},
23 | editable(subject, :content),
24 | "ViewHelpers#editable should escape unsafe content"
25 | end
26 |
27 | test "editable should NOT escape safe values" do
28 | subject = Subject.new(content: "
html_safe'd content
".html_safe)
29 | assert_match %r{
html_safe'd content
},
30 | editable(subject, :content),
31 | "ViewHelpers#editable should not escape safe content"
32 |
33 | subject.content = "safe content"
34 | assert_match %r{safe content},
35 | editable(subject, :content),
36 | "ViewHelpers#editable should not escape safe content"
37 | end
38 |
39 | test "editable should generate content tag with html options" do
40 | subject = Subject.new
41 |
42 | assert_match %r{
]+id="subject-id"},
43 | editable(subject, :name, html: { id: 'subject-id' }),
44 | "ViewHelpers#editable should generate content tag with html options"
45 |
46 | assert_match %r{]+name="subject\[name\]"},
47 | editable(subject, :name, html: { name: 'subject[name]' }),
48 | "ViewHelpers#editable should generate content tag with html options"
49 |
50 | assert_match %r{]+title="First Title"},
51 | editable(subject, :name, title: "First Title", html: { title: 'Second Title' }),
52 | "ViewHelpers#editable should generate content tag with html options"
53 | end
54 |
55 | test "editable should generate content tag with data attributes" do
56 | subject = Subject.new
57 |
58 | assert_match %r{]+data-model="page"},
59 | editable(subject, :name),
60 | "ViewHelpers#editable should generate content tag with data attributes"
61 |
62 | assert_no_match %r{]+data-model="page"},
63 | editable(subject, :name, model: "custom"),
64 | "ViewHelpers#editable should generate content tag with data attributes"
65 | end
66 |
67 | test "editable should generate content tag with the current value" do
68 | subject_1 = Subject.new(content: "foo")
69 |
70 | assert_match %r{]+>foo},
71 | editable(subject_1, :content),
72 | "ViewHelpers#editable should generate content tag with the current value"
73 |
74 | assert_match %r{]+>foo},
75 | editable(subject_1, :content, type: "select", source: ["foo", "bar"]),
76 | "ViewHelpers#editable should generate content tag with the current value"
77 |
78 | assert_match %r{]+>Foo},
79 | editable(subject_1, :content, type: "select", source: [["foo", "Foo"], ["bar", "Bar"]]),
80 | "ViewHelpers#editable should generate content tag with the current value"
81 |
82 | assert_match %r{]+>Foo},
83 | editable(subject_1, :content, type: "select", source: { "foo" => "Foo", "bar" => "Bar" }),
84 | "ViewHelpers#editable should generate content tag with the current value"
85 |
86 | assert_match %r{]+>Foo},
87 | editable(subject_1, :content, type: "select", source: [{ text: "Foo", value: "foo" }, { text: "Bar", value: "bar" }]),
88 | "ViewHelpers#editable should generate content tag with the current value"
89 |
90 | refute_match %r{data-source=},
91 | editable(subject_1, :content, type: "select"),
92 | "ViewHelpers#editable should generate content tag without source"
93 |
94 | subject_2 = Subject.new(active: true)
95 |
96 | assert_match %r{]+>Yes},
97 | editable(subject_2, :active),
98 | "ViewHelpers#editable should generate content tag with the current value"
99 | end
100 |
101 | test "editable should store the source url as a data attribute" do
102 | subject = Subject.new
103 | assert_match %r{]+data-source="http://example.org"},
104 | editable(subject, :name, type: "select",
105 | source: "http://example.org"),
106 | "ViewHelpers#editable should generate content tag with url source as a data attribute"
107 | end
108 |
109 | test "editable should generate content tag without current value" do
110 | subject_1 = Subject.new(content: nil)
111 |
112 | assert_match %r{]+>},
113 | editable(subject_1, :content),
114 | "ViewHelpers#editable should generate content tag with the current value"
115 |
116 | assert_match %r{]+>},
117 | editable(subject_1, :content, type: "select", source: ["foo", "bar"]),
118 | "ViewHelpers#editable should generate content tag with the current value"
119 |
120 | assert_match %r{]+>},
121 | editable(subject_1, :content, type: "select", source: [["foo", "Foo"], ["bar", "Bar"]]),
122 | "ViewHelpers#editable should generate content tag with the current value"
123 |
124 | assert_match %r{]+>},
125 | editable(subject_1, :content, type: "select", source: { "foo" => "Foo", "bar" => "Bar" }),
126 | "ViewHelpers#editable should generate content tag with the current value"
127 |
128 | assert_match %r{]+>},
129 | editable(subject_1, :content, type: "select", source: [{ text: "Foo", value: "foo" }, { text: "Bar", value: "bar" }]),
130 | "ViewHelpers#editable should generate content tag with the current value"
131 | end
132 |
133 | private
134 |
135 | def view_helpers_test_subject_path(subject)
136 | "/#{subject.to_param}"
137 | end
138 |
139 | def xeditable?(*args)
140 | true
141 | end
142 | end
143 |
--------------------------------------------------------------------------------
/lib/x-editable-rails/view_helpers.rb:
--------------------------------------------------------------------------------
1 | require 'base64'
2 |
3 | module X
4 | module Editable
5 | module Rails
6 | module ViewHelpers
7 | #
8 | # Options determine how the HTML tag is rendered and the remaining options are converted to data-* attributes.
9 | #
10 | # options:
11 | # tag: tag name of element returned
12 | # class: "class" attribute on element
13 | # placeholder: "placeholder" attribute on element
14 | # title: "title" attribute on element (defaults to placeholder)
15 | # data: "data-*" attributes on element
16 | # source: a Hash of friendly display values used by input elements based on (object) value
17 | # - boolean shorthand ['Enabled', 'Disabled'] becomes { '1' => 'Enabled', '0' => 'Disabled' }
18 | # - enumerable shorthand ['Yes', 'No', 'Maybe'] becomes { 'Yes' => 'Yes', 'No' => 'No', 'Maybe' => 'Maybe' }
19 | # classes: a Hash of classes to add based on the value (same format and shorthands as source)
20 | # value: override the object's value
21 | #
22 | def editable(object, method, options = {})
23 | options = Configuration.method_options_for(object, method).deep_merge(options).with_indifferent_access
24 | # merge data attributes for backwards-compatibility
25 | options.merge! options.delete(:data){ Hash.new }
26 |
27 | url = options.delete(:url){ polymorphic_path(object) }
28 | object = object.last if object.kind_of?(Array)
29 | value = options.delete(:value){ object.send(method) }
30 | source = options[:source] ? format_source(options.delete(:source), value) : default_source_for(value)
31 | classes = format_source(options.delete(:classes), value)
32 | error = options.delete(:e)
33 | html_options = options.delete(:html){ Hash.new }
34 |
35 | if xeditable?(object)
36 | model = object.class.model_name.param_key
37 | nid = options.delete(:nid)
38 | nested = options.delete(:nested)
39 | title = options.delete(:title) do
40 | klass = nested ? object.class.const_get(nested.to_s.classify) : object.class
41 | klass.human_attribute_name(method)
42 | end
43 |
44 | output_value = output_value_for(value)
45 | css_list = options.delete(:class).to_s.split(/\s+/).unshift('editable')
46 | css_list << classes[output_value] if classes
47 | type = options.delete(:type){ default_type_for(value) }
48 | css = css_list.compact.uniq.join(' ')
49 | tag = options.delete(:tag){ 'span' }
50 | placeholder = options.delete(:placeholder){ title }
51 |
52 | # any remaining options become data attributes
53 | data = {
54 | type: type,
55 | model: model,
56 | name: method,
57 | value: ( type == 'wysihtml5' ? Base64.encode64(output_value) : output_value ),
58 | placeholder: placeholder,
59 | classes: classes,
60 | source: source,
61 | url: url,
62 | nested: nested,
63 | nid: nid
64 | }.merge(options.symbolize_keys)
65 |
66 | data.reject!{|_, value| value.nil?}
67 |
68 | html_options.update({
69 | class: css,
70 | title: title,
71 | data: data
72 | })
73 |
74 | content_tag tag, html_options do
75 | if %w(select checklist).include?(data[:type].to_s) && !source.is_a?(String)
76 | source = normalize_source(source)
77 | content = source.detect { |t| output_value == output_value_for(t[0]) }
78 | content.present? ? content[1] : ""
79 | else
80 | safe_join(source_values_for(value, source), tag(:br))
81 | end
82 | end
83 | else
84 | error || safe_join(source_values_for(value || options[:emptytext], source), tag(:br))
85 | end
86 | end
87 |
88 | private
89 |
90 | def normalize_source(source)
91 | return [] unless source
92 | source.map do |el|
93 | if el.is_a? Array
94 | el
95 | else
96 | [el[:value], el[:text]]
97 | end
98 | end
99 | end
100 |
101 | def output_value_for(value)
102 | value = case value
103 | when TrueClass
104 | '1'
105 | when FalseClass
106 | '0'
107 | when NilClass
108 | ''
109 | when Array
110 | value.map{|item| output_value_for item}.join(',')
111 | else
112 | value.to_s
113 | end
114 |
115 | value
116 | end
117 |
118 | def source_values_for(value, source = nil)
119 | source ||= default_source_for value
120 |
121 | values = Array.wrap(value)
122 |
123 | if source && ( source.first.is_a?(String) || source.kind_of?(Hash) )
124 | values.map{|item| source[output_value_for item]}
125 | else
126 | values
127 | end
128 | end
129 |
130 | def default_type_for(value)
131 | case value
132 | when TrueClass, FalseClass
133 | 'select'
134 | when Array
135 | 'checklist'
136 | else
137 | 'text'
138 | end
139 | end
140 |
141 | def default_source_for(value)
142 | case value
143 | when TrueClass, FalseClass
144 | { '1' => 'Yes', '0' => 'No' }
145 | end
146 | end
147 |
148 | # helper method that take some shorthand source definitions and reformats them
149 | def format_source(source, value)
150 | formatted_source = case value
151 | when TrueClass, FalseClass
152 | if source.is_a?(Array) && source.first.is_a?(String) && source.size == 2
153 | { '1' => source[0], '0' => source[1] }
154 | end
155 | else
156 | if source.is_a?(Array) && source.first.is_a?(String)
157 | source.map { |v| { value: v, text: v } }
158 | end
159 | end
160 |
161 | formatted_source || source
162 | end
163 |
164 | end
165 | end
166 | end
167 | end
168 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # X::Editable::Rails
2 |
3 | [](https://travis-ci.org/werein/x-editable-rails) [](https://codeclimate.com/github/werein/x-editable-rails) [](https://codeclimate.com/github/werein/x-editable-rails) [](https://badge.fury.io/rb/x-editable-rails) [](https://gemnasium.com/werein/x-editable-rails)
4 |
5 | X-editable for Rails
6 |
7 | ## Live demo
8 |
9 | Checkout live demo [here](https://x-editable-rails.herokuapp.com/?denied=true)
10 |
11 | ## Installation
12 |
13 | Add this line to your application's Gemfile:
14 |
15 | gem 'x-editable-rails'
16 |
17 | And then execute:
18 |
19 | $ bundle
20 |
21 | Or install it yourself as:
22 |
23 | $ gem install x-editable-rails
24 |
25 | ## Usage
26 |
27 | ### Assets
28 |
29 | Choose between the following javascripts:
30 |
31 | * bootstrap-editable
32 | * bootstrap2-editable
33 | * jqueryui-editable
34 | * jquery-editable-poshytip
35 |
36 | You'll also need to include editable/rails in your scripts for this to work.
37 |
38 | ```coffee
39 | #= require editable/bootstrap-editable
40 | #= require editable/rails
41 | ```
42 |
43 | Choose the corresponding stylesheets:
44 |
45 | * bootstrap-editable
46 | * bootstrap2-editable
47 | * jqueryui-editable
48 | * jquery-editable
49 |
50 | ```scss
51 | // as CSS
52 | *= require editable/bootstrap-editable
53 |
54 | // or SCSS
55 | @import "editable/bootstrap-editable";
56 | ```
57 |
58 | Enable editing with jQuery:
59 |
60 | ```coffee
61 | $('.editable').editable()
62 | ```
63 |
64 | For custom inputs like the Wysihtml5 editor, add these dependencies:
65 |
66 | ```coffee
67 | #= require editable/bootstrap-editable
68 | #= require editable/inputs-ext/wysihtml5
69 | #= require editable/inputs-ext/bootstrap-wysihtml5
70 | #= require editable/inputs-ext/wysihtml5-editable
71 | #= require editable/rails
72 | ```
73 |
74 | And related stylesheets:
75 |
76 | ```css
77 | //= require editable/bootstrap-editable
78 | //= require editable/inputs-ext/bootstrap-wysihtml5
79 | //= require editable/inputs-ext/wysiwyg-color
80 | ```
81 |
82 | ### Making Things Editable
83 |
84 | `x-editable-rails` provides a helper method in your view to make your model values editable.
85 | By default, you need to specify the model and property that should be editable.
86 | A `span` element is rendered with `data-*` attributes used by `x-editable`.
87 |
88 | ```ruby
89 | # the editable object and the attribute to edit
90 | %h1= editable @model, :name
91 | ```
92 |
93 | You can customize the tag name and title attribute:
94 |
95 | * **tag** - `span` by default.
96 | * **title** - The model and attribute name are used to create a capitalized title
97 |
98 | The `editable` helper method automatically adds these `data-*` attributes used by [x-editable](http://vitalets.github.io/x-editable/docs.html).
99 |
100 | * **url** - Uses the `polymorphic_path(model)` helper method.
101 | * **source** - Only populated if the value is a boolean to convert `true` or `false` to "Yes" and "No".
102 | * **value** - Uses `model.name`. If `model.name` were a boolean value or if a `source` is specified, the `source` text would be displayed rather than the raw value. (Presumably the value is an ID and the source would have the text associated with that value.)
103 | * **placeholder** - Uses the `title` value by default
104 |
105 | ```ruby
106 | # editable object, what_you_want_update, e: exception - when is xeditable? false or can? :edit, object is false
107 | %h1= editable @model, :name, url: model_path, value: @model.name.upcase
108 | ```
109 |
110 | Here are some special features to enhance what's baked into [x-editable](http://vitalets.github.io/x-editable/docs.html):
111 |
112 | * **type** - The type of input is automatically detected. By default, if the value is a boolean, the `type` is "select" with a built-in `source` that outputs "Yes" and "No" (unless another `source` is specified).
113 | * **source** - In addition to hashes or arrays of hashes, you can also use an array of strings for a simpler structure if the name and value are the same:
114 |
115 | ```ruby
116 | source = [ "Active", "Disabled" ]
117 | editable @model, :enabled, source: source
118 | ```
119 |
120 | * **value** - This option will override the `model.name` value
121 | * **classes** - This is a custom option for `x-editable-rails` that will change the editable element's CSS class based on the selected value. Use the `source` hash structure to map a CSS class name to a value. (This [functionality](vendor/assets/javascripts/editable/rails/data_classes.js.coffee) is toggled when the value changes and the "save" event is triggered.)
122 |
123 | ```ruby
124 | source = [ "Active", "Disabled" ]
125 | classes = { "Active" => "label-success", "Disabled" => "label-default" }
126 | editable @model, :enabled, source: source, classes: classes, class: "label"
127 | ```
128 |
129 | * **nested** - Name of a nested attributes (such as [globalize](https://github.com/globalize/globalize)'s `translations`)
130 | * **nid** - ID of the nested attribute
131 |
132 | ```ruby
133 | %h1= editable @model, :name, nested: :translations, nid: @model.translation.id
134 |
135 | # example of nested resource
136 | %h1= editable [picture.gallery, picture], :name, nested: :translations, nid: picture.translation.id
137 | ```
138 |
139 | ### Authorization
140 |
141 | Add a helper method to your controllers to indicate if `x-editable` should be enabled.
142 |
143 | ```ruby
144 | def xeditable? object = nil
145 | true # Or something like current_user.xeditable?
146 | end
147 | ```
148 |
149 | You can use [CanCan](https://github.com/ryanb/cancan) and checks the `:edit` permission for the model being edited.
150 |
151 | ```ruby
152 | def xeditable? object = nil
153 | can?(:edit, object) ? true : false
154 | end
155 | ```
156 |
157 | * **e** - Specify a custom (error) message to display if the value isn't editable
158 |
159 | ### "Don't Repeat Yourself" Templates
160 |
161 | To make your views cleaner, you can specify all your options for each class and attribute in a YAML configuration file.
162 | Attributes where the `title` or `placeholder` are not different except maybe capitalized can be left out because they are automatically capitalized when rendered (see above).
163 |
164 | This example uses the `MailingList` class and its attributes.
165 | The attribute value can be a string, which is used as the `title` and `placeholder`.
166 | If you want to specify other options, create a hash of options.
167 |
168 | Install configuration file like this: `rails g x_editable_rails:install`, this step is not necessary
169 |
170 | ```yaml
171 | class_options:
172 | MailingList:
173 | # Specify placeholder text for each attribute or a Hash of options
174 | name: Mailing list name
175 | enabled:
176 | type: select
177 | source:
178 | - Active
179 | - Disabled
180 | reply_email:
181 | type: email
182 | title: Reply-to email
183 | User:
184 | email:
185 | type: email
186 | password:
187 | type: password
188 | mailing_lists:
189 | type: select
190 | # specify a URL to get source via AJAX (see x-editable docs)
191 | source: <%= ::Rails.application.routes.url_helpers.mailing_lists_source_path %>
192 | ```
193 |
194 | Now you can specify your editable fields without options because they will be inherited from your YAML config.
195 |
196 | ```ruby
197 | model = MailingList.new
198 |
199 | editable model, :name # type: "text", title: "Mailing list name"
200 | editable model, :enabled # type: "select", title: "Enabled", source: [ "Active", "Disabled" ]
201 | ```
202 |
203 | ### Examples
204 |
205 | Gem also contains demo application with integrated x-editable
206 |
207 | ```
208 | cd test/dummy
209 | rake db:migrate
210 | rake db:seed
211 | rails g x_editable_rails:install # optional, it generate config example
212 | rails s
213 | ```
214 |
215 | ## Contributing
216 |
217 | 1. Fork it
218 | 2. Create your feature branch (`git checkout -b my-new-feature`)
219 | 3. Commit your changes (`git commit -am 'Add some feature'`)
220 | 4. Push to the branch (`git push origin my-new-feature`)
221 | 5. Create new Pull Request
222 |
--------------------------------------------------------------------------------
/vendor/assets/javascripts/editable/inputs-ext/bootstrap-wysihtml5.js:
--------------------------------------------------------------------------------
1 | !function($, wysi) {
2 | "use strict";
3 |
4 | var tpl = {
5 | "font-styles": function(locale, options) {
6 | var size = (options && options.size) ? ' btn-'+options.size : '';
7 | return "" +
8 | "" +
9 | " " + locale.font_styles.normal + " " +
10 | "" +
11 | "" +
17 | "";
18 | },
19 |
20 | "emphasis": function(locale, options) {
21 | var size = (options && options.size) ? ' btn-'+options.size : '';
22 | return "" +
23 | "" +
28 | "";
29 | },
30 |
31 | "lists": function(locale, options) {
32 | var size = (options && options.size) ? ' btn-'+options.size : '';
33 | return "" +
34 | "" +
35 | "
" +
36 | "
" +
37 | "
" +
38 | "
" +
39 | "
" +
40 | "";
41 | },
42 |
43 | "link": function(locale, options) {
44 | var size = (options && options.size) ? ' btn-'+options.size : '';
45 | return "" +
46 | "" +
47 | "" +
51 | "
" +
52 | "" +
53 | "
" +
54 | "" +
58 | "
" +
59 | "" +
60 | "";
61 | },
62 |
63 | "image": function(locale, options) {
64 | var size = (options && options.size) ? ' btn-'+options.size : '';
65 | return "" +
66 | "" +
67 | "" +
71 | "
" +
72 | "" +
73 | "
" +
74 | "" +
78 | "
" +
79 | "" +
80 | "";
81 | },
82 |
83 | "html": function(locale, options) {
84 | var size = (options && options.size) ? ' btn-'+options.size : '';
85 | return "" +
86 | "" +
89 | "";
90 | },
91 |
92 | "color": function(locale, options) {
93 | var size = (options && options.size) ? ' btn-'+options.size : '';
94 | return "" +
95 | "" +
96 | "" + locale.colours.black + " " +
97 | "" +
98 | "" +
111 | "";
112 | }
113 | };
114 |
115 | var templates = function(key, locale, options) {
116 | return tpl[key](locale, options);
117 | };
118 |
119 |
120 | var Wysihtml5 = function(el, options) {
121 | this.el = el;
122 | var toolbarOpts = options || defaultOptions;
123 | for(var t in toolbarOpts.customTemplates) {
124 | tpl[t] = toolbarOpts.customTemplates[t];
125 | }
126 | this.toolbar = this.createToolbar(el, toolbarOpts);
127 | this.editor = this.createEditor(options);
128 |
129 | window.editor = this.editor;
130 |
131 | $('iframe.wysihtml5-sandbox').each(function(i, el){
132 | $(el.contentWindow).off('focus.wysihtml5').on({
133 | 'focus.wysihtml5' : function(){
134 | $('li.dropdown').removeClass('open');
135 | }
136 | });
137 | });
138 | };
139 |
140 | Wysihtml5.prototype = {
141 |
142 | constructor: Wysihtml5,
143 |
144 | createEditor: function(options) {
145 | options = options || {};
146 |
147 | // Add the toolbar to a clone of the options object so multiple instances
148 | // of the WYISYWG don't break because "toolbar" is already defined
149 | options = $.extend(true, {}, options);
150 | options.toolbar = this.toolbar[0];
151 |
152 | var editor = new wysi.Editor(this.el[0], options);
153 |
154 | if(options && options.events) {
155 | for(var eventName in options.events) {
156 | editor.on(eventName, options.events[eventName]);
157 | }
158 | }
159 | return editor;
160 | },
161 |
162 | createToolbar: function(el, options) {
163 | var self = this;
164 | var toolbar = $("", {
165 | 'class' : "wysihtml5-toolbar",
166 | 'style': "display:none"
167 | });
168 | var culture = options.locale || defaultOptions.locale || "en";
169 | for(var key in defaultOptions) {
170 | var value = false;
171 |
172 | if(options[key] !== undefined) {
173 | if(options[key] === true) {
174 | value = true;
175 | }
176 | } else {
177 | value = defaultOptions[key];
178 | }
179 |
180 | if(value === true) {
181 | toolbar.append(templates(key, locale[culture], options));
182 |
183 | if(key === "html") {
184 | this.initHtml(toolbar);
185 | }
186 |
187 | if(key === "link") {
188 | this.initInsertLink(toolbar);
189 | }
190 |
191 | if(key === "image") {
192 | this.initInsertImage(toolbar);
193 | }
194 | }
195 | }
196 |
197 | if(options.toolbar) {
198 | for(key in options.toolbar) {
199 | toolbar.append(options.toolbar[key]);
200 | }
201 | }
202 |
203 | toolbar.find("a[data-wysihtml5-command='formatBlock']").click(function(e) {
204 | var target = e.target || e.srcElement;
205 | var el = $(target);
206 | self.toolbar.find('.current-font').text(el.html());
207 | });
208 |
209 | toolbar.find("a[data-wysihtml5-command='foreColor']").click(function(e) {
210 | var target = e.target || e.srcElement;
211 | var el = $(target);
212 | self.toolbar.find('.current-color').text(el.html());
213 | });
214 |
215 | this.el.before(toolbar);
216 |
217 | return toolbar;
218 | },
219 |
220 | initHtml: function(toolbar) {
221 | var changeViewSelector = "a[data-wysihtml5-action='change_view']";
222 | toolbar.find(changeViewSelector).click(function(e) {
223 | toolbar.find('a.btn').not(changeViewSelector).toggleClass('disabled');
224 | });
225 | },
226 |
227 | initInsertImage: function(toolbar) {
228 | var self = this;
229 | var insertImageModal = toolbar.find('.bootstrap-wysihtml5-insert-image-modal');
230 | var urlInput = insertImageModal.find('.bootstrap-wysihtml5-insert-image-url');
231 | var insertButton = insertImageModal.find('a.btn-primary');
232 | var initialValue = urlInput.val();
233 | var caretBookmark;
234 |
235 | var insertImage = function() {
236 | var url = urlInput.val();
237 | urlInput.val(initialValue);
238 | self.editor.currentView.element.focus();
239 | if (caretBookmark) {
240 | self.editor.composer.selection.setBookmark(caretBookmark);
241 | caretBookmark = null;
242 | }
243 | self.editor.composer.commands.exec("insertImage", url);
244 | };
245 |
246 | urlInput.keypress(function(e) {
247 | if(e.which == 13) {
248 | insertImage();
249 | insertImageModal.modal('hide');
250 | }
251 | });
252 |
253 | insertButton.click(insertImage);
254 |
255 | insertImageModal.on('shown', function() {
256 | urlInput.focus();
257 | });
258 |
259 | insertImageModal.on('hide', function() {
260 | self.editor.currentView.element.focus();
261 | });
262 |
263 | toolbar.find('a[data-wysihtml5-command=insertImage]').click(function() {
264 | var activeButton = $(this).hasClass("wysihtml5-command-active");
265 |
266 | if (!activeButton) {
267 | self.editor.currentView.element.focus(false);
268 | caretBookmark = self.editor.composer.selection.getBookmark();
269 | insertImageModal.appendTo('body').modal('show');
270 | insertImageModal.on('click.dismiss.modal', '[data-dismiss="modal"]', function(e) {
271 | e.stopPropagation();
272 | });
273 | return false;
274 | }
275 | else {
276 | return true;
277 | }
278 | });
279 | },
280 |
281 | initInsertLink: function(toolbar) {
282 | var self = this;
283 | var insertLinkModal = toolbar.find('.bootstrap-wysihtml5-insert-link-modal');
284 | var urlInput = insertLinkModal.find('.bootstrap-wysihtml5-insert-link-url');
285 | var insertButton = insertLinkModal.find('a.btn-primary');
286 | var initialValue = urlInput.val();
287 | var caretBookmark;
288 |
289 | var insertLink = function() {
290 | var url = urlInput.val();
291 | urlInput.val(initialValue);
292 | self.editor.currentView.element.focus();
293 | if (caretBookmark) {
294 | self.editor.composer.selection.setBookmark(caretBookmark);
295 | caretBookmark = null;
296 | }
297 | self.editor.composer.commands.exec("createLink", {
298 | href: url,
299 | target: "_blank",
300 | rel: "nofollow"
301 | });
302 | };
303 | var pressedEnter = false;
304 |
305 | urlInput.keypress(function(e) {
306 | if(e.which == 13) {
307 | insertLink();
308 | insertLinkModal.modal('hide');
309 | }
310 | });
311 |
312 | insertButton.click(insertLink);
313 |
314 | insertLinkModal.on('shown', function() {
315 | urlInput.focus();
316 | });
317 |
318 | insertLinkModal.on('hide', function() {
319 | self.editor.currentView.element.focus();
320 | });
321 |
322 | toolbar.find('a[data-wysihtml5-command=createLink]').click(function() {
323 | var activeButton = $(this).hasClass("wysihtml5-command-active");
324 |
325 | if (!activeButton) {
326 | self.editor.currentView.element.focus(false);
327 | caretBookmark = self.editor.composer.selection.getBookmark();
328 | insertLinkModal.appendTo('body').modal('show');
329 | insertLinkModal.on('click.dismiss.modal', '[data-dismiss="modal"]', function(e) {
330 | e.stopPropagation();
331 | });
332 | return false;
333 | }
334 | else {
335 | return true;
336 | }
337 | });
338 | }
339 | };
340 |
341 | // these define our public api
342 | var methods = {
343 | resetDefaults: function() {
344 | $.fn.wysihtml5.defaultOptions = $.extend(true, {}, $.fn.wysihtml5.defaultOptionsCache);
345 | },
346 | bypassDefaults: function(options) {
347 | return this.each(function () {
348 | var $this = $(this);
349 | $this.data('wysihtml5', new Wysihtml5($this, options));
350 | });
351 | },
352 | shallowExtend: function (options) {
353 | var settings = $.extend({}, $.fn.wysihtml5.defaultOptions, options || {});
354 | var that = this;
355 | return methods.bypassDefaults.apply(that, [settings]);
356 | },
357 | deepExtend: function(options) {
358 | var settings = $.extend(true, {}, $.fn.wysihtml5.defaultOptions, options || {});
359 | var that = this;
360 | return methods.bypassDefaults.apply(that, [settings]);
361 | },
362 | init: function(options) {
363 | var that = this;
364 | return methods.shallowExtend.apply(that, [options]);
365 | }
366 | };
367 |
368 | $.fn.wysihtml5 = function ( method ) {
369 | if ( methods[method] ) {
370 | return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
371 | } else if ( typeof method === 'object' || ! method ) {
372 | return methods.init.apply( this, arguments );
373 | } else {
374 | $.error( 'Method ' + method + ' does not exist on jQuery.wysihtml5' );
375 | }
376 | };
377 |
378 | $.fn.wysihtml5.Constructor = Wysihtml5;
379 |
380 | var defaultOptions = $.fn.wysihtml5.defaultOptions = {
381 | "font-styles": true,
382 | "color": false,
383 | "emphasis": true,
384 | "lists": true,
385 | "html": false,
386 | "link": true,
387 | "image": true,
388 | events: {},
389 | parserRules: {
390 | classes: {
391 | // (path_to_project/lib/css/wysiwyg-color.css)
392 | "wysiwyg-color-silver" : 1,
393 | "wysiwyg-color-gray" : 1,
394 | "wysiwyg-color-white" : 1,
395 | "wysiwyg-color-maroon" : 1,
396 | "wysiwyg-color-red" : 1,
397 | "wysiwyg-color-purple" : 1,
398 | "wysiwyg-color-fuchsia" : 1,
399 | "wysiwyg-color-green" : 1,
400 | "wysiwyg-color-lime" : 1,
401 | "wysiwyg-color-olive" : 1,
402 | "wysiwyg-color-yellow" : 1,
403 | "wysiwyg-color-navy" : 1,
404 | "wysiwyg-color-blue" : 1,
405 | "wysiwyg-color-teal" : 1,
406 | "wysiwyg-color-aqua" : 1,
407 | "wysiwyg-color-orange" : 1
408 | },
409 | tags: {
410 | "b": {},
411 | "i": {},
412 | "br": {},
413 | "ol": {},
414 | "ul": {},
415 | "li": {},
416 | "h1": {},
417 | "h2": {},
418 | "h3": {},
419 | "blockquote": {},
420 | "u": 1,
421 | "img": {
422 | "check_attributes": {
423 | "width": "numbers",
424 | "alt": "alt",
425 | "src": "url",
426 | "height": "numbers"
427 | }
428 | },
429 | "a": {
430 | set_attributes: {
431 | target: "_blank",
432 | rel: "nofollow"
433 | },
434 | check_attributes: {
435 | href: "url" // important to avoid XSS
436 | }
437 | },
438 | "span": 1,
439 | "div": 1,
440 | // to allow save and edit files with code tag hacks
441 | "code": 1,
442 | "pre": 1
443 | }
444 | },
445 | stylesheets: ["./lib/css/wysiwyg-color.css"], // (path_to_project/lib/css/wysiwyg-color.css)
446 | locale: "en"
447 | };
448 |
449 | if (typeof $.fn.wysihtml5.defaultOptionsCache === 'undefined') {
450 | $.fn.wysihtml5.defaultOptionsCache = $.extend(true, {}, $.fn.wysihtml5.defaultOptions);
451 | }
452 |
453 | var locale = $.fn.wysihtml5.locale = {
454 | en: {
455 | font_styles: {
456 | normal: "Normal text",
457 | h1: "Heading 1",
458 | h2: "Heading 2",
459 | h3: "Heading 3"
460 | },
461 | emphasis: {
462 | bold: "Bold",
463 | italic: "Italic",
464 | underline: "Underline"
465 | },
466 | lists: {
467 | unordered: "Unordered list",
468 | ordered: "Ordered list",
469 | outdent: "Outdent",
470 | indent: "Indent"
471 | },
472 | link: {
473 | insert: "Insert link",
474 | cancel: "Cancel"
475 | },
476 | image: {
477 | insert: "Insert image",
478 | cancel: "Cancel"
479 | },
480 | html: {
481 | edit: "Edit HTML"
482 | },
483 | colours: {
484 | black: "Black",
485 | silver: "Silver",
486 | gray: "Grey",
487 | maroon: "Maroon",
488 | red: "Red",
489 | purple: "Purple",
490 | green: "Green",
491 | olive: "Olive",
492 | navy: "Navy",
493 | blue: "Blue",
494 | orange: "Orange"
495 | }
496 | }
497 | };
498 |
499 | }(window.jQuery, window.wysihtml5);
500 |
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/editable/bootstrap-editable.scss:
--------------------------------------------------------------------------------
1 | /*! X-editable - v1.5.0
2 | * In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
3 | * http://github.com/vitalets/x-editable
4 | * Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */
5 | .editableform {
6 | margin-bottom: 0; /* overwrites bootstrap margin */
7 | }
8 |
9 | .editableform .control-group {
10 | margin-bottom: 0; /* overwrites bootstrap margin */
11 | white-space: nowrap; /* prevent wrapping buttons on new line */
12 | line-height: 20px; /* overwriting bootstrap line-height. See #133 */
13 | }
14 |
15 | .editable-buttons {
16 | display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
17 | vertical-align: top;
18 | margin-left: 7px;
19 | /* inline-block emulation for IE7*/
20 | zoom: 1;
21 | *display: inline;
22 | }
23 |
24 | .editable-buttons.editable-buttons-bottom {
25 | display: block;
26 | margin-top: 7px;
27 | margin-left: 0;
28 | }
29 |
30 | .editable-input {
31 | vertical-align: top;
32 | display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
33 | width: auto; /* bootstrap-responsive has width: 100% that breakes layout */
34 | white-space: normal; /* reset white-space decalred in parent*/
35 | /* display-inline emulation for IE7*/
36 | zoom: 1;
37 | *display: inline;
38 | }
39 |
40 | .editable-buttons .editable-cancel {
41 | margin-left: 7px;
42 | }
43 |
44 | /*for jquery-ui buttons need set height to look more pretty*/
45 | .editable-buttons button.ui-button-icon-only {
46 | height: 24px;
47 | width: 30px;
48 | }
49 |
50 | .editableform-loading {
51 | background: image-url('editable/loading.gif') center center no-repeat;
52 | height: 25px;
53 | width: auto;
54 | min-width: 25px;
55 | }
56 |
57 | .editable-inline .editableform-loading {
58 | background-position: left 5px;
59 | }
60 |
61 | .editable-error-block {
62 | max-width: 300px;
63 | margin: 5px 0 0 0;
64 | width: auto;
65 | white-space: normal;
66 | }
67 |
68 | /*add padding for jquery ui*/
69 | .editable-error-block.ui-state-error {
70 | padding: 3px;
71 | }
72 |
73 | .editable-error {
74 | color: red;
75 | }
76 |
77 | /* ---- For specific types ---- */
78 |
79 | .editableform .editable-date {
80 | padding: 0;
81 | margin: 0;
82 | float: left;
83 | }
84 |
85 | /* move datepicker icon to center of add-on button. See https://github.com/vitalets/x-editable/issues/183 */
86 | .editable-inline .add-on .icon-th {
87 | margin-top: 3px;
88 | margin-left: 1px;
89 | }
90 |
91 |
92 | /* checklist vertical alignment */
93 | .editable-checklist label input[type="checkbox"],
94 | .editable-checklist label span {
95 | vertical-align: middle;
96 | margin: 0;
97 | }
98 |
99 | .editable-checklist label {
100 | white-space: nowrap;
101 | }
102 |
103 | /* set exact width of textarea to fit buttons toolbar */
104 | .editable-wysihtml5 {
105 | width: 566px;
106 | height: 250px;
107 | }
108 |
109 | /* clear button shown as link in date inputs */
110 | .editable-clear {
111 | clear: both;
112 | font-size: 0.9em;
113 | text-decoration: none;
114 | text-align: right;
115 | }
116 |
117 | /* IOS-style clear button for text inputs */
118 | .editable-clear-x {
119 | background: image-url('editable/clear.png') center center no-repeat;
120 | display: block;
121 | width: 13px;
122 | height: 13px;
123 | position: absolute;
124 | opacity: 0.6;
125 | z-index: 100;
126 |
127 | top: 50%;
128 | right: 6px;
129 | margin-top: -6px;
130 |
131 | }
132 |
133 | .editable-clear-x:hover {
134 | opacity: 1;
135 | }
136 |
137 | .editable-pre-wrapped {
138 | white-space: pre-wrap;
139 | }
140 | .editable-container.editable-popup {
141 | max-width: none !important; /* without this rule poshytip/tooltip does not stretch */
142 | }
143 |
144 | .editable-container.popover {
145 | width: auto; /* without this rule popover does not stretch */
146 | }
147 |
148 | .editable-container.editable-inline {
149 | display: inline-block;
150 | vertical-align: middle;
151 | width: auto;
152 | /* inline-block emulation for IE7*/
153 | zoom: 1;
154 | *display: inline;
155 | }
156 |
157 | .editable-container.ui-widget {
158 | font-size: inherit; /* jqueryui widget font 1.1em too big, overwrite it */
159 | z-index: 9990; /* should be less than select2 dropdown z-index to close dropdown first when click */
160 | }
161 | .editable-click,
162 | a.editable-click,
163 | a.editable-click:hover {
164 | text-decoration: none;
165 | border-bottom: dashed 1px #0088cc;
166 | }
167 |
168 | .editable-click.editable-disabled,
169 | a.editable-click.editable-disabled,
170 | a.editable-click.editable-disabled:hover {
171 | color: #585858;
172 | cursor: default;
173 | border-bottom: none;
174 | }
175 |
176 | .editable-empty, .editable-empty:hover, .editable-empty:focus{
177 | font-style: italic;
178 | color: #DD1144;
179 | /* border-bottom: none; */
180 | text-decoration: none;
181 | }
182 |
183 | .editable-unsaved {
184 | font-weight: bold;
185 | }
186 |
187 | .editable-unsaved:after {
188 | /* content: '*'*/
189 | }
190 |
191 | .editable-bg-transition {
192 | -webkit-transition: background-color 1400ms ease-out;
193 | -moz-transition: background-color 1400ms ease-out;
194 | -o-transition: background-color 1400ms ease-out;
195 | -ms-transition: background-color 1400ms ease-out;
196 | transition: background-color 1400ms ease-out;
197 | }
198 |
199 | /*see https://github.com/vitalets/x-editable/issues/139 */
200 | .form-horizontal .editable
201 | {
202 | padding-top: 5px;
203 | display:inline-block;
204 | }
205 |
206 |
207 | /*!
208 | * Datepicker for Bootstrap
209 | *
210 | * Copyright 2012 Stefan Petre
211 | * Improvements by Andrew Rowls
212 | * Licensed under the Apache License v2.0
213 | * http://www.apache.org/licenses/LICENSE-2.0
214 | *
215 | */
216 | .datepicker {
217 | padding: 4px;
218 | -webkit-border-radius: 4px;
219 | -moz-border-radius: 4px;
220 | border-radius: 4px;
221 | direction: ltr;
222 | /*.dow {
223 | border-top: 1px solid #ddd !important;
224 | }*/
225 |
226 | }
227 | .datepicker-inline {
228 | width: 220px;
229 | }
230 | .datepicker.datepicker-rtl {
231 | direction: rtl;
232 | }
233 | .datepicker.datepicker-rtl table tr td span {
234 | float: right;
235 | }
236 | .datepicker-dropdown {
237 | top: 0;
238 | left: 0;
239 | }
240 | .datepicker-dropdown:before {
241 | content: '';
242 | display: inline-block;
243 | border-left: 7px solid transparent;
244 | border-right: 7px solid transparent;
245 | border-bottom: 7px solid #ccc;
246 | border-bottom-color: rgba(0, 0, 0, 0.2);
247 | position: absolute;
248 | top: -7px;
249 | left: 6px;
250 | }
251 | .datepicker-dropdown:after {
252 | content: '';
253 | display: inline-block;
254 | border-left: 6px solid transparent;
255 | border-right: 6px solid transparent;
256 | border-bottom: 6px solid #ffffff;
257 | position: absolute;
258 | top: -6px;
259 | left: 7px;
260 | }
261 | .datepicker > div {
262 | display: none;
263 | }
264 | .datepicker.days div.datepicker-days {
265 | display: block;
266 | }
267 | .datepicker.months div.datepicker-months {
268 | display: block;
269 | }
270 | .datepicker.years div.datepicker-years {
271 | display: block;
272 | }
273 | .datepicker table {
274 | margin: 0;
275 | }
276 | .datepicker td,
277 | .datepicker th {
278 | text-align: center;
279 | width: 20px;
280 | height: 20px;
281 | -webkit-border-radius: 4px;
282 | -moz-border-radius: 4px;
283 | border-radius: 4px;
284 | border: none;
285 | }
286 | .table-striped .datepicker table tr td,
287 | .table-striped .datepicker table tr th {
288 | background-color: transparent;
289 | }
290 | .datepicker table tr td.day:hover {
291 | background: #eeeeee;
292 | cursor: pointer;
293 | }
294 | .datepicker table tr td.old,
295 | .datepicker table tr td.new {
296 | color: #999999;
297 | }
298 | .datepicker table tr td.disabled,
299 | .datepicker table tr td.disabled:hover {
300 | background: none;
301 | color: #999999;
302 | cursor: default;
303 | }
304 | .datepicker table tr td.today,
305 | .datepicker table tr td.today:hover,
306 | .datepicker table tr td.today.disabled,
307 | .datepicker table tr td.today.disabled:hover {
308 | background-color: #fde19a;
309 | background-image: -moz-linear-gradient(to bottom, #fdd49a, #fdf59a);
310 | background-image: -ms-linear-gradient(to bottom, #fdd49a, #fdf59a);
311 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));
312 | background-image: -webkit-linear-gradient(to bottom, #fdd49a, #fdf59a);
313 | background-image: -o-linear-gradient(to bottom, #fdd49a, #fdf59a);
314 | background-image: linear-gradient(to bottom, #fdd49a, #fdf59a);
315 | background-repeat: repeat-x;
316 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);
317 | border-color: #fdf59a #fdf59a #fbed50;
318 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
319 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
320 | color: #000;
321 | }
322 | .datepicker table tr td.today:hover,
323 | .datepicker table tr td.today:hover:hover,
324 | .datepicker table tr td.today.disabled:hover,
325 | .datepicker table tr td.today.disabled:hover:hover,
326 | .datepicker table tr td.today:active,
327 | .datepicker table tr td.today:hover:active,
328 | .datepicker table tr td.today.disabled:active,
329 | .datepicker table tr td.today.disabled:hover:active,
330 | .datepicker table tr td.today.active,
331 | .datepicker table tr td.today:hover.active,
332 | .datepicker table tr td.today.disabled.active,
333 | .datepicker table tr td.today.disabled:hover.active,
334 | .datepicker table tr td.today.disabled,
335 | .datepicker table tr td.today:hover.disabled,
336 | .datepicker table tr td.today.disabled.disabled,
337 | .datepicker table tr td.today.disabled:hover.disabled,
338 | .datepicker table tr td.today[disabled],
339 | .datepicker table tr td.today:hover[disabled],
340 | .datepicker table tr td.today.disabled[disabled],
341 | .datepicker table tr td.today.disabled:hover[disabled] {
342 | background-color: #fdf59a;
343 | }
344 | .datepicker table tr td.today:active,
345 | .datepicker table tr td.today:hover:active,
346 | .datepicker table tr td.today.disabled:active,
347 | .datepicker table tr td.today.disabled:hover:active,
348 | .datepicker table tr td.today.active,
349 | .datepicker table tr td.today:hover.active,
350 | .datepicker table tr td.today.disabled.active,
351 | .datepicker table tr td.today.disabled:hover.active {
352 | background-color: #fbf069 \9;
353 | }
354 | .datepicker table tr td.today:hover:hover {
355 | color: #000;
356 | }
357 | .datepicker table tr td.today.active:hover {
358 | color: #fff;
359 | }
360 | .datepicker table tr td.range,
361 | .datepicker table tr td.range:hover,
362 | .datepicker table tr td.range.disabled,
363 | .datepicker table tr td.range.disabled:hover {
364 | background: #eeeeee;
365 | -webkit-border-radius: 0;
366 | -moz-border-radius: 0;
367 | border-radius: 0;
368 | }
369 | .datepicker table tr td.range.today,
370 | .datepicker table tr td.range.today:hover,
371 | .datepicker table tr td.range.today.disabled,
372 | .datepicker table tr td.range.today.disabled:hover {
373 | background-color: #f3d17a;
374 | background-image: -moz-linear-gradient(to bottom, #f3c17a, #f3e97a);
375 | background-image: -ms-linear-gradient(to bottom, #f3c17a, #f3e97a);
376 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a));
377 | background-image: -webkit-linear-gradient(to bottom, #f3c17a, #f3e97a);
378 | background-image: -o-linear-gradient(to bottom, #f3c17a, #f3e97a);
379 | background-image: linear-gradient(to bottom, #f3c17a, #f3e97a);
380 | background-repeat: repeat-x;
381 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);
382 | border-color: #f3e97a #f3e97a #edde34;
383 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
384 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
385 | -webkit-border-radius: 0;
386 | -moz-border-radius: 0;
387 | border-radius: 0;
388 | }
389 | .datepicker table tr td.range.today:hover,
390 | .datepicker table tr td.range.today:hover:hover,
391 | .datepicker table tr td.range.today.disabled:hover,
392 | .datepicker table tr td.range.today.disabled:hover:hover,
393 | .datepicker table tr td.range.today:active,
394 | .datepicker table tr td.range.today:hover:active,
395 | .datepicker table tr td.range.today.disabled:active,
396 | .datepicker table tr td.range.today.disabled:hover:active,
397 | .datepicker table tr td.range.today.active,
398 | .datepicker table tr td.range.today:hover.active,
399 | .datepicker table tr td.range.today.disabled.active,
400 | .datepicker table tr td.range.today.disabled:hover.active,
401 | .datepicker table tr td.range.today.disabled,
402 | .datepicker table tr td.range.today:hover.disabled,
403 | .datepicker table tr td.range.today.disabled.disabled,
404 | .datepicker table tr td.range.today.disabled:hover.disabled,
405 | .datepicker table tr td.range.today[disabled],
406 | .datepicker table tr td.range.today:hover[disabled],
407 | .datepicker table tr td.range.today.disabled[disabled],
408 | .datepicker table tr td.range.today.disabled:hover[disabled] {
409 | background-color: #f3e97a;
410 | }
411 | .datepicker table tr td.range.today:active,
412 | .datepicker table tr td.range.today:hover:active,
413 | .datepicker table tr td.range.today.disabled:active,
414 | .datepicker table tr td.range.today.disabled:hover:active,
415 | .datepicker table tr td.range.today.active,
416 | .datepicker table tr td.range.today:hover.active,
417 | .datepicker table tr td.range.today.disabled.active,
418 | .datepicker table tr td.range.today.disabled:hover.active {
419 | background-color: #efe24b \9;
420 | }
421 | .datepicker table tr td.selected,
422 | .datepicker table tr td.selected:hover,
423 | .datepicker table tr td.selected.disabled,
424 | .datepicker table tr td.selected.disabled:hover {
425 | background-color: #9e9e9e;
426 | background-image: -moz-linear-gradient(to bottom, #b3b3b3, #808080);
427 | background-image: -ms-linear-gradient(to bottom, #b3b3b3, #808080);
428 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(#808080));
429 | background-image: -webkit-linear-gradient(to bottom, #b3b3b3, #808080);
430 | background-image: -o-linear-gradient(to bottom, #b3b3b3, #808080);
431 | background-image: linear-gradient(to bottom, #b3b3b3, #808080);
432 | background-repeat: repeat-x;
433 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);
434 | border-color: #808080 #808080 #595959;
435 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
436 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
437 | color: #fff;
438 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
439 | }
440 | .datepicker table tr td.selected:hover,
441 | .datepicker table tr td.selected:hover:hover,
442 | .datepicker table tr td.selected.disabled:hover,
443 | .datepicker table tr td.selected.disabled:hover:hover,
444 | .datepicker table tr td.selected:active,
445 | .datepicker table tr td.selected:hover:active,
446 | .datepicker table tr td.selected.disabled:active,
447 | .datepicker table tr td.selected.disabled:hover:active,
448 | .datepicker table tr td.selected.active,
449 | .datepicker table tr td.selected:hover.active,
450 | .datepicker table tr td.selected.disabled.active,
451 | .datepicker table tr td.selected.disabled:hover.active,
452 | .datepicker table tr td.selected.disabled,
453 | .datepicker table tr td.selected:hover.disabled,
454 | .datepicker table tr td.selected.disabled.disabled,
455 | .datepicker table tr td.selected.disabled:hover.disabled,
456 | .datepicker table tr td.selected[disabled],
457 | .datepicker table tr td.selected:hover[disabled],
458 | .datepicker table tr td.selected.disabled[disabled],
459 | .datepicker table tr td.selected.disabled:hover[disabled] {
460 | background-color: #808080;
461 | }
462 | .datepicker table tr td.selected:active,
463 | .datepicker table tr td.selected:hover:active,
464 | .datepicker table tr td.selected.disabled:active,
465 | .datepicker table tr td.selected.disabled:hover:active,
466 | .datepicker table tr td.selected.active,
467 | .datepicker table tr td.selected:hover.active,
468 | .datepicker table tr td.selected.disabled.active,
469 | .datepicker table tr td.selected.disabled:hover.active {
470 | background-color: #666666 \9;
471 | }
472 | .datepicker table tr td.active,
473 | .datepicker table tr td.active:hover,
474 | .datepicker table tr td.active.disabled,
475 | .datepicker table tr td.active.disabled:hover {
476 | background-color: #006dcc;
477 | background-image: -moz-linear-gradient(to bottom, #0088cc, #0044cc);
478 | background-image: -ms-linear-gradient(to bottom, #0088cc, #0044cc);
479 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
480 | background-image: -webkit-linear-gradient(to bottom, #0088cc, #0044cc);
481 | background-image: -o-linear-gradient(to bottom, #0088cc, #0044cc);
482 | background-image: linear-gradient(to bottom, #0088cc, #0044cc);
483 | background-repeat: repeat-x;
484 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
485 | border-color: #0044cc #0044cc #002a80;
486 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
487 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
488 | color: #fff;
489 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
490 | }
491 | .datepicker table tr td.active:hover,
492 | .datepicker table tr td.active:hover:hover,
493 | .datepicker table tr td.active.disabled:hover,
494 | .datepicker table tr td.active.disabled:hover:hover,
495 | .datepicker table tr td.active:active,
496 | .datepicker table tr td.active:hover:active,
497 | .datepicker table tr td.active.disabled:active,
498 | .datepicker table tr td.active.disabled:hover:active,
499 | .datepicker table tr td.active.active,
500 | .datepicker table tr td.active:hover.active,
501 | .datepicker table tr td.active.disabled.active,
502 | .datepicker table tr td.active.disabled:hover.active,
503 | .datepicker table tr td.active.disabled,
504 | .datepicker table tr td.active:hover.disabled,
505 | .datepicker table tr td.active.disabled.disabled,
506 | .datepicker table tr td.active.disabled:hover.disabled,
507 | .datepicker table tr td.active[disabled],
508 | .datepicker table tr td.active:hover[disabled],
509 | .datepicker table tr td.active.disabled[disabled],
510 | .datepicker table tr td.active.disabled:hover[disabled] {
511 | background-color: #0044cc;
512 | }
513 | .datepicker table tr td.active:active,
514 | .datepicker table tr td.active:hover:active,
515 | .datepicker table tr td.active.disabled:active,
516 | .datepicker table tr td.active.disabled:hover:active,
517 | .datepicker table tr td.active.active,
518 | .datepicker table tr td.active:hover.active,
519 | .datepicker table tr td.active.disabled.active,
520 | .datepicker table tr td.active.disabled:hover.active {
521 | background-color: #003399 \9;
522 | }
523 | .datepicker table tr td span {
524 | display: block;
525 | width: 23%;
526 | height: 54px;
527 | line-height: 54px;
528 | float: left;
529 | margin: 1%;
530 | cursor: pointer;
531 | -webkit-border-radius: 4px;
532 | -moz-border-radius: 4px;
533 | border-radius: 4px;
534 | }
535 | .datepicker table tr td span:hover {
536 | background: #eeeeee;
537 | }
538 | .datepicker table tr td span.disabled,
539 | .datepicker table tr td span.disabled:hover {
540 | background: none;
541 | color: #999999;
542 | cursor: default;
543 | }
544 | .datepicker table tr td span.active,
545 | .datepicker table tr td span.active:hover,
546 | .datepicker table tr td span.active.disabled,
547 | .datepicker table tr td span.active.disabled:hover {
548 | background-color: #006dcc;
549 | background-image: -moz-linear-gradient(to bottom, #0088cc, #0044cc);
550 | background-image: -ms-linear-gradient(to bottom, #0088cc, #0044cc);
551 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
552 | background-image: -webkit-linear-gradient(to bottom, #0088cc, #0044cc);
553 | background-image: -o-linear-gradient(to bottom, #0088cc, #0044cc);
554 | background-image: linear-gradient(to bottom, #0088cc, #0044cc);
555 | background-repeat: repeat-x;
556 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
557 | border-color: #0044cc #0044cc #002a80;
558 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
559 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
560 | color: #fff;
561 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
562 | }
563 | .datepicker table tr td span.active:hover,
564 | .datepicker table tr td span.active:hover:hover,
565 | .datepicker table tr td span.active.disabled:hover,
566 | .datepicker table tr td span.active.disabled:hover:hover,
567 | .datepicker table tr td span.active:active,
568 | .datepicker table tr td span.active:hover:active,
569 | .datepicker table tr td span.active.disabled:active,
570 | .datepicker table tr td span.active.disabled:hover:active,
571 | .datepicker table tr td span.active.active,
572 | .datepicker table tr td span.active:hover.active,
573 | .datepicker table tr td span.active.disabled.active,
574 | .datepicker table tr td span.active.disabled:hover.active,
575 | .datepicker table tr td span.active.disabled,
576 | .datepicker table tr td span.active:hover.disabled,
577 | .datepicker table tr td span.active.disabled.disabled,
578 | .datepicker table tr td span.active.disabled:hover.disabled,
579 | .datepicker table tr td span.active[disabled],
580 | .datepicker table tr td span.active:hover[disabled],
581 | .datepicker table tr td span.active.disabled[disabled],
582 | .datepicker table tr td span.active.disabled:hover[disabled] {
583 | background-color: #0044cc;
584 | }
585 | .datepicker table tr td span.active:active,
586 | .datepicker table tr td span.active:hover:active,
587 | .datepicker table tr td span.active.disabled:active,
588 | .datepicker table tr td span.active.disabled:hover:active,
589 | .datepicker table tr td span.active.active,
590 | .datepicker table tr td span.active:hover.active,
591 | .datepicker table tr td span.active.disabled.active,
592 | .datepicker table tr td span.active.disabled:hover.active {
593 | background-color: #003399 \9;
594 | }
595 | .datepicker table tr td span.old,
596 | .datepicker table tr td span.new {
597 | color: #999999;
598 | }
599 | .datepicker th.datepicker-switch {
600 | width: 145px;
601 | }
602 | .datepicker thead tr:first-child th,
603 | .datepicker tfoot tr th {
604 | cursor: pointer;
605 | }
606 | .datepicker thead tr:first-child th:hover,
607 | .datepicker tfoot tr th:hover {
608 | background: #eeeeee;
609 | }
610 | .datepicker .cw {
611 | font-size: 10px;
612 | width: 12px;
613 | padding: 0 2px 0 5px;
614 | vertical-align: middle;
615 | }
616 | .datepicker thead tr:first-child th.cw {
617 | cursor: default;
618 | background-color: transparent;
619 | }
620 | .input-append.date .add-on i,
621 | .input-prepend.date .add-on i {
622 | display: block;
623 | cursor: pointer;
624 | width: 16px;
625 | height: 16px;
626 | }
627 | .input-daterange input {
628 | text-align: center;
629 | }
630 | .input-daterange input:first-child {
631 | -webkit-border-radius: 3px 0 0 3px;
632 | -moz-border-radius: 3px 0 0 3px;
633 | border-radius: 3px 0 0 3px;
634 | }
635 | .input-daterange input:last-child {
636 | -webkit-border-radius: 0 3px 3px 0;
637 | -moz-border-radius: 0 3px 3px 0;
638 | border-radius: 0 3px 3px 0;
639 | }
640 | .input-daterange .add-on {
641 | display: inline-block;
642 | width: auto;
643 | min-width: 16px;
644 | height: 18px;
645 | padding: 4px 5px;
646 | font-weight: normal;
647 | line-height: 18px;
648 | text-align: center;
649 | text-shadow: 0 1px 0 #ffffff;
650 | vertical-align: middle;
651 | background-color: #eeeeee;
652 | border: 1px solid #ccc;
653 | margin-left: -5px;
654 | margin-right: -5px;
655 | }
656 |
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/editable/bootstrap2-editable.scss:
--------------------------------------------------------------------------------
1 | /*! X-editable - v1.5.0
2 | * In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
3 | * http://github.com/vitalets/x-editable
4 | * Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */
5 | .editableform {
6 | margin-bottom: 0; /* overwrites bootstrap margin */
7 | }
8 |
9 | .editableform .control-group {
10 | margin-bottom: 0; /* overwrites bootstrap margin */
11 | white-space: nowrap; /* prevent wrapping buttons on new line */
12 | line-height: 20px; /* overwriting bootstrap line-height. See #133 */
13 | }
14 |
15 | .editable-buttons {
16 | display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
17 | vertical-align: top;
18 | margin-left: 7px;
19 | /* inline-block emulation for IE7*/
20 | zoom: 1;
21 | *display: inline;
22 | }
23 |
24 | .editable-buttons.editable-buttons-bottom {
25 | display: block;
26 | margin-top: 7px;
27 | margin-left: 0;
28 | }
29 |
30 | .editable-input {
31 | vertical-align: top;
32 | display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
33 | width: auto; /* bootstrap-responsive has width: 100% that breakes layout */
34 | white-space: normal; /* reset white-space decalred in parent*/
35 | /* display-inline emulation for IE7*/
36 | zoom: 1;
37 | *display: inline;
38 | }
39 |
40 | .editable-buttons .editable-cancel {
41 | margin-left: 7px;
42 | }
43 |
44 | /*for jquery-ui buttons need set height to look more pretty*/
45 | .editable-buttons button.ui-button-icon-only {
46 | height: 24px;
47 | width: 30px;
48 | }
49 |
50 | .editableform-loading {
51 | background: image-url('editable/loading.gif') center center no-repeat;
52 | height: 25px;
53 | width: auto;
54 | min-width: 25px;
55 | }
56 |
57 | .editable-inline .editableform-loading {
58 | background-position: left 5px;
59 | }
60 |
61 | .editable-error-block {
62 | max-width: 300px;
63 | margin: 5px 0 0 0;
64 | width: auto;
65 | white-space: normal;
66 | }
67 |
68 | /*add padding for jquery ui*/
69 | .editable-error-block.ui-state-error {
70 | padding: 3px;
71 | }
72 |
73 | .editable-error {
74 | color: red;
75 | }
76 |
77 | /* ---- For specific types ---- */
78 |
79 | .editableform .editable-date {
80 | padding: 0;
81 | margin: 0;
82 | float: left;
83 | }
84 |
85 | /* move datepicker icon to center of add-on button. See https://github.com/vitalets/x-editable/issues/183 */
86 | .editable-inline .add-on .icon-th {
87 | margin-top: 3px;
88 | margin-left: 1px;
89 | }
90 |
91 |
92 | /* checklist vertical alignment */
93 | .editable-checklist label input[type="checkbox"],
94 | .editable-checklist label span {
95 | vertical-align: middle;
96 | margin: 0;
97 | }
98 |
99 | .editable-checklist label {
100 | white-space: nowrap;
101 | }
102 |
103 | /* set exact width of textarea to fit buttons toolbar */
104 | .editable-wysihtml5 {
105 | width: 566px;
106 | height: 250px;
107 | }
108 |
109 | /* clear button shown as link in date inputs */
110 | .editable-clear {
111 | clear: both;
112 | font-size: 0.9em;
113 | text-decoration: none;
114 | text-align: right;
115 | }
116 |
117 | /* IOS-style clear button for text inputs */
118 | .editable-clear-x {
119 | background: image-url('editable/clear.png') center center no-repeat;
120 | display: block;
121 | width: 13px;
122 | height: 13px;
123 | position: absolute;
124 | opacity: 0.6;
125 | z-index: 100;
126 |
127 | top: 50%;
128 | right: 6px;
129 | margin-top: -6px;
130 |
131 | }
132 |
133 | .editable-clear-x:hover {
134 | opacity: 1;
135 | }
136 |
137 | .editable-pre-wrapped {
138 | white-space: pre-wrap;
139 | }
140 | .editable-container.editable-popup {
141 | max-width: none !important; /* without this rule poshytip/tooltip does not stretch */
142 | }
143 |
144 | .editable-container.popover {
145 | width: auto; /* without this rule popover does not stretch */
146 | }
147 |
148 | .editable-container.editable-inline {
149 | display: inline-block;
150 | vertical-align: middle;
151 | width: auto;
152 | /* inline-block emulation for IE7*/
153 | zoom: 1;
154 | *display: inline;
155 | }
156 |
157 | .editable-container.ui-widget {
158 | font-size: inherit; /* jqueryui widget font 1.1em too big, overwrite it */
159 | z-index: 9990; /* should be less than select2 dropdown z-index to close dropdown first when click */
160 | }
161 | .editable-click,
162 | a.editable-click,
163 | a.editable-click:hover {
164 | text-decoration: none;
165 | border-bottom: dashed 1px #0088cc;
166 | }
167 |
168 | .editable-click.editable-disabled,
169 | a.editable-click.editable-disabled,
170 | a.editable-click.editable-disabled:hover {
171 | color: #585858;
172 | cursor: default;
173 | border-bottom: none;
174 | }
175 |
176 | .editable-empty, .editable-empty:hover, .editable-empty:focus{
177 | font-style: italic;
178 | color: #DD1144;
179 | /* border-bottom: none; */
180 | text-decoration: none;
181 | }
182 |
183 | .editable-unsaved {
184 | font-weight: bold;
185 | }
186 |
187 | .editable-unsaved:after {
188 | /* content: '*'*/
189 | }
190 |
191 | .editable-bg-transition {
192 | -webkit-transition: background-color 1400ms ease-out;
193 | -moz-transition: background-color 1400ms ease-out;
194 | -o-transition: background-color 1400ms ease-out;
195 | -ms-transition: background-color 1400ms ease-out;
196 | transition: background-color 1400ms ease-out;
197 | }
198 |
199 | /*see https://github.com/vitalets/x-editable/issues/139 */
200 | .form-horizontal .editable
201 | {
202 | padding-top: 5px;
203 | display:inline-block;
204 | }
205 |
206 |
207 | /*!
208 | * Datepicker for Bootstrap
209 | *
210 | * Copyright 2012 Stefan Petre
211 | * Improvements by Andrew Rowls
212 | * Licensed under the Apache License v2.0
213 | * http://www.apache.org/licenses/LICENSE-2.0
214 | *
215 | */
216 | .datepicker {
217 | padding: 4px;
218 | -webkit-border-radius: 4px;
219 | -moz-border-radius: 4px;
220 | border-radius: 4px;
221 | direction: ltr;
222 | /*.dow {
223 | border-top: 1px solid #ddd !important;
224 | }*/
225 |
226 | }
227 | .datepicker-inline {
228 | width: 220px;
229 | }
230 | .datepicker.datepicker-rtl {
231 | direction: rtl;
232 | }
233 | .datepicker.datepicker-rtl table tr td span {
234 | float: right;
235 | }
236 | .datepicker-dropdown {
237 | top: 0;
238 | left: 0;
239 | }
240 | .datepicker-dropdown:before {
241 | content: '';
242 | display: inline-block;
243 | border-left: 7px solid transparent;
244 | border-right: 7px solid transparent;
245 | border-bottom: 7px solid #ccc;
246 | border-bottom-color: rgba(0, 0, 0, 0.2);
247 | position: absolute;
248 | top: -7px;
249 | left: 6px;
250 | }
251 | .datepicker-dropdown:after {
252 | content: '';
253 | display: inline-block;
254 | border-left: 6px solid transparent;
255 | border-right: 6px solid transparent;
256 | border-bottom: 6px solid #ffffff;
257 | position: absolute;
258 | top: -6px;
259 | left: 7px;
260 | }
261 | .datepicker > div {
262 | display: none;
263 | }
264 | .datepicker.days div.datepicker-days {
265 | display: block;
266 | }
267 | .datepicker.months div.datepicker-months {
268 | display: block;
269 | }
270 | .datepicker.years div.datepicker-years {
271 | display: block;
272 | }
273 | .datepicker table {
274 | margin: 0;
275 | }
276 | .datepicker td,
277 | .datepicker th {
278 | text-align: center;
279 | width: 20px;
280 | height: 20px;
281 | -webkit-border-radius: 4px;
282 | -moz-border-radius: 4px;
283 | border-radius: 4px;
284 | border: none;
285 | }
286 | .table-striped .datepicker table tr td,
287 | .table-striped .datepicker table tr th {
288 | background-color: transparent;
289 | }
290 | .datepicker table tr td.day:hover {
291 | background: #eeeeee;
292 | cursor: pointer;
293 | }
294 | .datepicker table tr td.old,
295 | .datepicker table tr td.new {
296 | color: #999999;
297 | }
298 | .datepicker table tr td.disabled,
299 | .datepicker table tr td.disabled:hover {
300 | background: none;
301 | color: #999999;
302 | cursor: default;
303 | }
304 | .datepicker table tr td.today,
305 | .datepicker table tr td.today:hover,
306 | .datepicker table tr td.today.disabled,
307 | .datepicker table tr td.today.disabled:hover {
308 | background-color: #fde19a;
309 | background-image: -moz-linear-gradient(to bottom, #fdd49a, #fdf59a);
310 | background-image: -ms-linear-gradient(to bottom, #fdd49a, #fdf59a);
311 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));
312 | background-image: -webkit-linear-gradient(to bottom, #fdd49a, #fdf59a);
313 | background-image: -o-linear-gradient(to bottom, #fdd49a, #fdf59a);
314 | background-image: linear-gradient(to bottom, #fdd49a, #fdf59a);
315 | background-repeat: repeat-x;
316 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);
317 | border-color: #fdf59a #fdf59a #fbed50;
318 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
319 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
320 | color: #000;
321 | }
322 | .datepicker table tr td.today:hover,
323 | .datepicker table tr td.today:hover:hover,
324 | .datepicker table tr td.today.disabled:hover,
325 | .datepicker table tr td.today.disabled:hover:hover,
326 | .datepicker table tr td.today:active,
327 | .datepicker table tr td.today:hover:active,
328 | .datepicker table tr td.today.disabled:active,
329 | .datepicker table tr td.today.disabled:hover:active,
330 | .datepicker table tr td.today.active,
331 | .datepicker table tr td.today:hover.active,
332 | .datepicker table tr td.today.disabled.active,
333 | .datepicker table tr td.today.disabled:hover.active,
334 | .datepicker table tr td.today.disabled,
335 | .datepicker table tr td.today:hover.disabled,
336 | .datepicker table tr td.today.disabled.disabled,
337 | .datepicker table tr td.today.disabled:hover.disabled,
338 | .datepicker table tr td.today[disabled],
339 | .datepicker table tr td.today:hover[disabled],
340 | .datepicker table tr td.today.disabled[disabled],
341 | .datepicker table tr td.today.disabled:hover[disabled] {
342 | background-color: #fdf59a;
343 | }
344 | .datepicker table tr td.today:active,
345 | .datepicker table tr td.today:hover:active,
346 | .datepicker table tr td.today.disabled:active,
347 | .datepicker table tr td.today.disabled:hover:active,
348 | .datepicker table tr td.today.active,
349 | .datepicker table tr td.today:hover.active,
350 | .datepicker table tr td.today.disabled.active,
351 | .datepicker table tr td.today.disabled:hover.active {
352 | background-color: #fbf069 \9;
353 | }
354 | .datepicker table tr td.today:hover:hover {
355 | color: #000;
356 | }
357 | .datepicker table tr td.today.active:hover {
358 | color: #fff;
359 | }
360 | .datepicker table tr td.range,
361 | .datepicker table tr td.range:hover,
362 | .datepicker table tr td.range.disabled,
363 | .datepicker table tr td.range.disabled:hover {
364 | background: #eeeeee;
365 | -webkit-border-radius: 0;
366 | -moz-border-radius: 0;
367 | border-radius: 0;
368 | }
369 | .datepicker table tr td.range.today,
370 | .datepicker table tr td.range.today:hover,
371 | .datepicker table tr td.range.today.disabled,
372 | .datepicker table tr td.range.today.disabled:hover {
373 | background-color: #f3d17a;
374 | background-image: -moz-linear-gradient(to bottom, #f3c17a, #f3e97a);
375 | background-image: -ms-linear-gradient(to bottom, #f3c17a, #f3e97a);
376 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a));
377 | background-image: -webkit-linear-gradient(to bottom, #f3c17a, #f3e97a);
378 | background-image: -o-linear-gradient(to bottom, #f3c17a, #f3e97a);
379 | background-image: linear-gradient(to bottom, #f3c17a, #f3e97a);
380 | background-repeat: repeat-x;
381 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);
382 | border-color: #f3e97a #f3e97a #edde34;
383 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
384 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
385 | -webkit-border-radius: 0;
386 | -moz-border-radius: 0;
387 | border-radius: 0;
388 | }
389 | .datepicker table tr td.range.today:hover,
390 | .datepicker table tr td.range.today:hover:hover,
391 | .datepicker table tr td.range.today.disabled:hover,
392 | .datepicker table tr td.range.today.disabled:hover:hover,
393 | .datepicker table tr td.range.today:active,
394 | .datepicker table tr td.range.today:hover:active,
395 | .datepicker table tr td.range.today.disabled:active,
396 | .datepicker table tr td.range.today.disabled:hover:active,
397 | .datepicker table tr td.range.today.active,
398 | .datepicker table tr td.range.today:hover.active,
399 | .datepicker table tr td.range.today.disabled.active,
400 | .datepicker table tr td.range.today.disabled:hover.active,
401 | .datepicker table tr td.range.today.disabled,
402 | .datepicker table tr td.range.today:hover.disabled,
403 | .datepicker table tr td.range.today.disabled.disabled,
404 | .datepicker table tr td.range.today.disabled:hover.disabled,
405 | .datepicker table tr td.range.today[disabled],
406 | .datepicker table tr td.range.today:hover[disabled],
407 | .datepicker table tr td.range.today.disabled[disabled],
408 | .datepicker table tr td.range.today.disabled:hover[disabled] {
409 | background-color: #f3e97a;
410 | }
411 | .datepicker table tr td.range.today:active,
412 | .datepicker table tr td.range.today:hover:active,
413 | .datepicker table tr td.range.today.disabled:active,
414 | .datepicker table tr td.range.today.disabled:hover:active,
415 | .datepicker table tr td.range.today.active,
416 | .datepicker table tr td.range.today:hover.active,
417 | .datepicker table tr td.range.today.disabled.active,
418 | .datepicker table tr td.range.today.disabled:hover.active {
419 | background-color: #efe24b \9;
420 | }
421 | .datepicker table tr td.selected,
422 | .datepicker table tr td.selected:hover,
423 | .datepicker table tr td.selected.disabled,
424 | .datepicker table tr td.selected.disabled:hover {
425 | background-color: #9e9e9e;
426 | background-image: -moz-linear-gradient(to bottom, #b3b3b3, #808080);
427 | background-image: -ms-linear-gradient(to bottom, #b3b3b3, #808080);
428 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(#808080));
429 | background-image: -webkit-linear-gradient(to bottom, #b3b3b3, #808080);
430 | background-image: -o-linear-gradient(to bottom, #b3b3b3, #808080);
431 | background-image: linear-gradient(to bottom, #b3b3b3, #808080);
432 | background-repeat: repeat-x;
433 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);
434 | border-color: #808080 #808080 #595959;
435 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
436 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
437 | color: #fff;
438 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
439 | }
440 | .datepicker table tr td.selected:hover,
441 | .datepicker table tr td.selected:hover:hover,
442 | .datepicker table tr td.selected.disabled:hover,
443 | .datepicker table tr td.selected.disabled:hover:hover,
444 | .datepicker table tr td.selected:active,
445 | .datepicker table tr td.selected:hover:active,
446 | .datepicker table tr td.selected.disabled:active,
447 | .datepicker table tr td.selected.disabled:hover:active,
448 | .datepicker table tr td.selected.active,
449 | .datepicker table tr td.selected:hover.active,
450 | .datepicker table tr td.selected.disabled.active,
451 | .datepicker table tr td.selected.disabled:hover.active,
452 | .datepicker table tr td.selected.disabled,
453 | .datepicker table tr td.selected:hover.disabled,
454 | .datepicker table tr td.selected.disabled.disabled,
455 | .datepicker table tr td.selected.disabled:hover.disabled,
456 | .datepicker table tr td.selected[disabled],
457 | .datepicker table tr td.selected:hover[disabled],
458 | .datepicker table tr td.selected.disabled[disabled],
459 | .datepicker table tr td.selected.disabled:hover[disabled] {
460 | background-color: #808080;
461 | }
462 | .datepicker table tr td.selected:active,
463 | .datepicker table tr td.selected:hover:active,
464 | .datepicker table tr td.selected.disabled:active,
465 | .datepicker table tr td.selected.disabled:hover:active,
466 | .datepicker table tr td.selected.active,
467 | .datepicker table tr td.selected:hover.active,
468 | .datepicker table tr td.selected.disabled.active,
469 | .datepicker table tr td.selected.disabled:hover.active {
470 | background-color: #666666 \9;
471 | }
472 | .datepicker table tr td.active,
473 | .datepicker table tr td.active:hover,
474 | .datepicker table tr td.active.disabled,
475 | .datepicker table tr td.active.disabled:hover {
476 | background-color: #006dcc;
477 | background-image: -moz-linear-gradient(to bottom, #0088cc, #0044cc);
478 | background-image: -ms-linear-gradient(to bottom, #0088cc, #0044cc);
479 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
480 | background-image: -webkit-linear-gradient(to bottom, #0088cc, #0044cc);
481 | background-image: -o-linear-gradient(to bottom, #0088cc, #0044cc);
482 | background-image: linear-gradient(to bottom, #0088cc, #0044cc);
483 | background-repeat: repeat-x;
484 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
485 | border-color: #0044cc #0044cc #002a80;
486 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
487 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
488 | color: #fff;
489 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
490 | }
491 | .datepicker table tr td.active:hover,
492 | .datepicker table tr td.active:hover:hover,
493 | .datepicker table tr td.active.disabled:hover,
494 | .datepicker table tr td.active.disabled:hover:hover,
495 | .datepicker table tr td.active:active,
496 | .datepicker table tr td.active:hover:active,
497 | .datepicker table tr td.active.disabled:active,
498 | .datepicker table tr td.active.disabled:hover:active,
499 | .datepicker table tr td.active.active,
500 | .datepicker table tr td.active:hover.active,
501 | .datepicker table tr td.active.disabled.active,
502 | .datepicker table tr td.active.disabled:hover.active,
503 | .datepicker table tr td.active.disabled,
504 | .datepicker table tr td.active:hover.disabled,
505 | .datepicker table tr td.active.disabled.disabled,
506 | .datepicker table tr td.active.disabled:hover.disabled,
507 | .datepicker table tr td.active[disabled],
508 | .datepicker table tr td.active:hover[disabled],
509 | .datepicker table tr td.active.disabled[disabled],
510 | .datepicker table tr td.active.disabled:hover[disabled] {
511 | background-color: #0044cc;
512 | }
513 | .datepicker table tr td.active:active,
514 | .datepicker table tr td.active:hover:active,
515 | .datepicker table tr td.active.disabled:active,
516 | .datepicker table tr td.active.disabled:hover:active,
517 | .datepicker table tr td.active.active,
518 | .datepicker table tr td.active:hover.active,
519 | .datepicker table tr td.active.disabled.active,
520 | .datepicker table tr td.active.disabled:hover.active {
521 | background-color: #003399 \9;
522 | }
523 | .datepicker table tr td span {
524 | display: block;
525 | width: 23%;
526 | height: 54px;
527 | line-height: 54px;
528 | float: left;
529 | margin: 1%;
530 | cursor: pointer;
531 | -webkit-border-radius: 4px;
532 | -moz-border-radius: 4px;
533 | border-radius: 4px;
534 | }
535 | .datepicker table tr td span:hover {
536 | background: #eeeeee;
537 | }
538 | .datepicker table tr td span.disabled,
539 | .datepicker table tr td span.disabled:hover {
540 | background: none;
541 | color: #999999;
542 | cursor: default;
543 | }
544 | .datepicker table tr td span.active,
545 | .datepicker table tr td span.active:hover,
546 | .datepicker table tr td span.active.disabled,
547 | .datepicker table tr td span.active.disabled:hover {
548 | background-color: #006dcc;
549 | background-image: -moz-linear-gradient(to bottom, #0088cc, #0044cc);
550 | background-image: -ms-linear-gradient(to bottom, #0088cc, #0044cc);
551 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
552 | background-image: -webkit-linear-gradient(to bottom, #0088cc, #0044cc);
553 | background-image: -o-linear-gradient(to bottom, #0088cc, #0044cc);
554 | background-image: linear-gradient(to bottom, #0088cc, #0044cc);
555 | background-repeat: repeat-x;
556 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
557 | border-color: #0044cc #0044cc #002a80;
558 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
559 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
560 | color: #fff;
561 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
562 | }
563 | .datepicker table tr td span.active:hover,
564 | .datepicker table tr td span.active:hover:hover,
565 | .datepicker table tr td span.active.disabled:hover,
566 | .datepicker table tr td span.active.disabled:hover:hover,
567 | .datepicker table tr td span.active:active,
568 | .datepicker table tr td span.active:hover:active,
569 | .datepicker table tr td span.active.disabled:active,
570 | .datepicker table tr td span.active.disabled:hover:active,
571 | .datepicker table tr td span.active.active,
572 | .datepicker table tr td span.active:hover.active,
573 | .datepicker table tr td span.active.disabled.active,
574 | .datepicker table tr td span.active.disabled:hover.active,
575 | .datepicker table tr td span.active.disabled,
576 | .datepicker table tr td span.active:hover.disabled,
577 | .datepicker table tr td span.active.disabled.disabled,
578 | .datepicker table tr td span.active.disabled:hover.disabled,
579 | .datepicker table tr td span.active[disabled],
580 | .datepicker table tr td span.active:hover[disabled],
581 | .datepicker table tr td span.active.disabled[disabled],
582 | .datepicker table tr td span.active.disabled:hover[disabled] {
583 | background-color: #0044cc;
584 | }
585 | .datepicker table tr td span.active:active,
586 | .datepicker table tr td span.active:hover:active,
587 | .datepicker table tr td span.active.disabled:active,
588 | .datepicker table tr td span.active.disabled:hover:active,
589 | .datepicker table tr td span.active.active,
590 | .datepicker table tr td span.active:hover.active,
591 | .datepicker table tr td span.active.disabled.active,
592 | .datepicker table tr td span.active.disabled:hover.active {
593 | background-color: #003399 \9;
594 | }
595 | .datepicker table tr td span.old,
596 | .datepicker table tr td span.new {
597 | color: #999999;
598 | }
599 | .datepicker th.datepicker-switch {
600 | width: 145px;
601 | }
602 | .datepicker thead tr:first-child th,
603 | .datepicker tfoot tr th {
604 | cursor: pointer;
605 | }
606 | .datepicker thead tr:first-child th:hover,
607 | .datepicker tfoot tr th:hover {
608 | background: #eeeeee;
609 | }
610 | .datepicker .cw {
611 | font-size: 10px;
612 | width: 12px;
613 | padding: 0 2px 0 5px;
614 | vertical-align: middle;
615 | }
616 | .datepicker thead tr:first-child th.cw {
617 | cursor: default;
618 | background-color: transparent;
619 | }
620 | .input-append.date .add-on i,
621 | .input-prepend.date .add-on i {
622 | display: block;
623 | cursor: pointer;
624 | width: 16px;
625 | height: 16px;
626 | }
627 | .input-daterange input {
628 | text-align: center;
629 | }
630 | .input-daterange input:first-child {
631 | -webkit-border-radius: 3px 0 0 3px;
632 | -moz-border-radius: 3px 0 0 3px;
633 | border-radius: 3px 0 0 3px;
634 | }
635 | .input-daterange input:last-child {
636 | -webkit-border-radius: 0 3px 3px 0;
637 | -moz-border-radius: 0 3px 3px 0;
638 | border-radius: 0 3px 3px 0;
639 | }
640 | .input-daterange .add-on {
641 | display: inline-block;
642 | width: auto;
643 | min-width: 16px;
644 | height: 18px;
645 | padding: 4px 5px;
646 | font-weight: normal;
647 | line-height: 18px;
648 | text-align: center;
649 | text-shadow: 0 1px 0 #ffffff;
650 | vertical-align: middle;
651 | background-color: #eeeeee;
652 | border: 1px solid #ccc;
653 | margin-left: -5px;
654 | margin-right: -5px;
655 | }
656 |
--------------------------------------------------------------------------------
awesome
comment!