bootstrap_datepicker 0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +98 -0
- data/Rakefile +16 -0
- data/bootstrap_datepicker.gemspec +31 -0
- data/init.rb +1 -0
- data/lib/app/helpers/datepicker_helper.rb +18 -0
- data/lib/app/helpers/form_helper.rb +84 -0
- data/lib/bootstrap_datepicker.rb +15 -0
- data/lib/engine.rb +5 -0
- data/vendor/assets/javascripts/bootstrap-datepicker.js +416 -0
- data/vendor/assets/javascripts/index.js +1 -0
- data/vendor/assets/stylesheets/bootstrap-datepicker.css +156 -0
- metadata +84 -0
data/README.rdoc
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
= Bootstrap Datepicker Rails plugin
|
2
|
+
|
3
|
+
This simple gem allows you to add a date picker field into your views.
|
4
|
+
|
5
|
+
== Getting Started
|
6
|
+
|
7
|
+
Pre Rails 3.1:
|
8
|
+
|
9
|
+
1. Add into your Gemfile:
|
10
|
+
|
11
|
+
gem 'jquery-rails'
|
12
|
+
|
13
|
+
2. Execute this command to install the needed js files:
|
14
|
+
|
15
|
+
rails generate jquery:install --ui
|
16
|
+
|
17
|
+
|
18
|
+
3. Insert into your Gemfile:
|
19
|
+
|
20
|
+
gem 'bootstrap_datepicker'
|
21
|
+
|
22
|
+
Don't forget to install the CSS!
|
23
|
+
|
24
|
+
Rails 3.1:
|
25
|
+
|
26
|
+
1. Insert into your Gemfile:
|
27
|
+
|
28
|
+
gem 'bootstrap_datepicker'
|
29
|
+
|
30
|
+
2. If you are using Rails 3.1 with the asset pipeline enabled (default), the necessary files are already in your asset pipeline. Just add (if they are not already there) to your app/assets/javascripts/application.js:
|
31
|
+
|
32
|
+
//= require jquery
|
33
|
+
//= require jquery-ujs
|
34
|
+
//= require jquery-ui
|
35
|
+
|
36
|
+
(if you are using datetime picker, add also)
|
37
|
+
|
38
|
+
//= require jquery-ui-timepicker-addon.js
|
39
|
+
|
40
|
+
You can find it here:
|
41
|
+
|
42
|
+
https://github.com/trentrichardson/jQuery-Timepicker-Addon
|
43
|
+
|
44
|
+
|
45
|
+
== Usage
|
46
|
+
|
47
|
+
Add this to your view.
|
48
|
+
|
49
|
+
<%= datepicker_input "user","birthday" %>
|
50
|
+
|
51
|
+
|
52
|
+
Where "user" is your model name and "birthday" the name of the datefield.
|
53
|
+
|
54
|
+
You can also use it with the form helper like:
|
55
|
+
|
56
|
+
<% form_for(@user) do |f| %>
|
57
|
+
<%= f.datepicker 'birthday' %>
|
58
|
+
<%= f.submit 'Create' %>
|
59
|
+
<% end %>
|
60
|
+
|
61
|
+
Nested attributes are permitted as well:
|
62
|
+
|
63
|
+
<% form_for(@user) do |f| %>
|
64
|
+
<% f.fields_for(@nested) do |f2| %>
|
65
|
+
<%= f2.datepicker 'birthday' %>
|
66
|
+
<% end %>
|
67
|
+
<%= f.submit 'Create' %>
|
68
|
+
<% end %>
|
69
|
+
|
70
|
+
You can pass options as it would be a normal text_field, plus all the datepicker options available (http://jqueryui.com/demos/datepicker/#options)
|
71
|
+
|
72
|
+
<%= datepicker_input(:foo, :att1, :minDate => -20, :maxDate => "+1M +10D", :tabindex => 70) %>
|
73
|
+
|
74
|
+
== Use DateTime picker
|
75
|
+
|
76
|
+
If you want to use a datatime picker, download this plugin
|
77
|
+
|
78
|
+
https://github.com/trentrichardson/jQuery-Timepicker-Addon
|
79
|
+
|
80
|
+
and add it to your project (in the assets pipeline if you are using Rails 3.1 or manually otherwise).
|
81
|
+
Don't forget the CSS! This plugin assume you have installed a jquery-ui theme.
|
82
|
+
|
83
|
+
Then you can use in your views:
|
84
|
+
|
85
|
+
<%= datetime_picker_input "user","loged_in", :dateFormat => "yy-mm-dd" %>
|
86
|
+
|
87
|
+
or
|
88
|
+
|
89
|
+
<% form_for(@user) do |f| %>
|
90
|
+
<%= f.datetime_picker 'loged_in', :dateFormat => "yy-mm-dd" %>
|
91
|
+
<%= f.submit 'Create' %>
|
92
|
+
<% end %>
|
93
|
+
|
94
|
+
Important! Be aware the way Rails stores the datetime fields cause you'll need to specify the dateFormat to "yy-mm-dd" or pre-process your field value on the controller. The default format won't work.
|
95
|
+
|
96
|
+
== Support
|
97
|
+
|
98
|
+
Open an issue in https://github.com/albertopq/jquery_datepicker if you need further support or want to report a bug
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'echoe'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
Echoe.new('bootstrap_datepicker', '0.4') do |p|
|
7
|
+
p.description = "View helper that allows to select dates from a calendar (using jQuery and Twitter Bootstrap styles)"
|
8
|
+
p.url = "http://github.com/derekstavis/bootstrap_datepicker"
|
9
|
+
p.author = "Derek Stavis"
|
10
|
+
p.email = "dekestavis@gmail.com"
|
11
|
+
p.ignore_pattern = ["tmp/*", "script/*", "spec/*"]
|
12
|
+
p.development_dependencies = ['twitter-bootstrap-rails']
|
13
|
+
end
|
14
|
+
|
15
|
+
RSpec::Core::RakeTask.new(:spec)
|
16
|
+
task :default => :spec
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "bootstrap_datepicker"
|
5
|
+
s.version = "0.5"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Alberto Pastor", "Derek Willian Stavis"]
|
9
|
+
s.date = "2012-08-07"
|
10
|
+
s.description = "View helper that allows to select dates from a calendar (using jQuery and Twitter Bootstrap styles)"
|
11
|
+
s.email = "dekestavis@gmail.com"
|
12
|
+
s.extra_rdoc_files = ["README.rdoc", "lib/app/helpers/datepicker_helper.rb", "lib/app/helpers/form_helper.rb", "lib/bootstrap_datepicker.rb"]
|
13
|
+
s.files = ["README.rdoc", "Rakefile", "init.rb", "bootstrap_datepicker.gemspec", "lib/app/helpers/datepicker_helper.rb", "lib/app/helpers/form_helper.rb", "lib/bootstrap_datepicker.rb", "lib/engine.rb", "vendor/assets/javascripts/bootstrap-datepicker.js", "vendor/assets/javascripts/index.js", "vendor/assets/stylesheets/bootstrap-datepicker.css"]
|
14
|
+
|
15
|
+
s.homepage = "http://github.com/derekstavis/bootstrap_datepicker"
|
16
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "bootstrap_datepicker", "--main", "README.rdoc"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = "bootstrap_datepicker"
|
19
|
+
s.rubygems_version = "1.8.10"
|
20
|
+
s.summary = "View helper that allows to select dates from a calendar (using jQuery and Twitter Bootstrap styles)"
|
21
|
+
s.add_dependency "twitter-bootstrap-rails", "~> 2.1.1"
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
s.specification_version = 3
|
25
|
+
|
26
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
27
|
+
else
|
28
|
+
end
|
29
|
+
else
|
30
|
+
end
|
31
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bootstrap_datepicker'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'app/helpers/form_helper'
|
2
|
+
|
3
|
+
module BootstrapDatepicker
|
4
|
+
module DatepickerHelper
|
5
|
+
|
6
|
+
include BootstrapDatepicker::FormHelper
|
7
|
+
|
8
|
+
# Helper method that creates a datepicker input field
|
9
|
+
def datepicker_input(object_name, method, options = {})
|
10
|
+
datepicker(object_name, method, options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def datetime_picker_input(object_name, method, options = {})
|
14
|
+
datepicker(object_name, method, options, true)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
module BootstrapDatepicker
|
4
|
+
module FormHelper
|
5
|
+
|
6
|
+
include ActionView::Helpers::JavaScriptHelper
|
7
|
+
|
8
|
+
# Mehtod that generates datepicker input field inside a form
|
9
|
+
def datepicker(object_name, method, options = {}, timepicker = false)
|
10
|
+
input_tag = BootstrapDatepicker::InstanceTag.new(object_name, method, self, options.delete(:object))
|
11
|
+
dp_options, tf_options = input_tag.baked_options(options)
|
12
|
+
# tf_options[:value] = input_tag.format_date(tf_options[:value], String.new(dp_options[:dateFormat])) if tf_options[:value] && !tf_options[:value].empty? && dp_options.has_key?(:dateFormat)
|
13
|
+
html = input_tag.to_input_field_tag("text", tf_options)
|
14
|
+
method = timepicker ? "datetimepicker" : "datepicker"
|
15
|
+
# html += javascript_tag("jQuery(document).ready(function(){jQuery('##{input_tag.get_name_and_id["id"]}').#{method}(#{dp_options.to_json})});")
|
16
|
+
html.html_safe
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
module BootstrapDatepicker::FormBuilder
|
24
|
+
def datepicker(method, options = {})
|
25
|
+
@template.datepicker(@object_name, method, objectify_options(options))
|
26
|
+
end
|
27
|
+
|
28
|
+
def datetime_picker(method, options = {})
|
29
|
+
@template.datepicker(@object_name, method, objectify_options(options), true)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class BootstrapDatepicker::InstanceTag < ActionView::Helpers::InstanceTag
|
34
|
+
|
35
|
+
FORMAT_REPLACEMENTES = { "yy" => "%Y", "mm" => "%m", "dd" => "%d", "d" => "%-d", "m" => "%-m", "y" => "%y", "M" => "%b"}
|
36
|
+
|
37
|
+
# Extending ActionView::Helpers::InstanceTag module to make Rails build the name and id
|
38
|
+
# Just returns the options before generate the HTML in order to use the same id and name (see to_input_field_tag mehtod)
|
39
|
+
|
40
|
+
def get_name_and_id(options = {})
|
41
|
+
add_default_name_and_id(options)
|
42
|
+
options
|
43
|
+
end
|
44
|
+
|
45
|
+
def available_datepicker_options
|
46
|
+
[:format, :week_start, :view_mode, :min_view_mode, :class]
|
47
|
+
end
|
48
|
+
|
49
|
+
def baked_options(options)
|
50
|
+
tf_options = Hash.new
|
51
|
+
|
52
|
+
options.each do |key, value|
|
53
|
+
if available_datepicker_options.include? key
|
54
|
+
if key.to_s === "class"
|
55
|
+
tf_options[key.to_s] = value
|
56
|
+
else
|
57
|
+
new_key = ("data-" << key.to_s)
|
58
|
+
tf_options[new_key] = value
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
puts 'options'
|
64
|
+
puts options
|
65
|
+
puts 'tf_options'
|
66
|
+
puts tf_options
|
67
|
+
|
68
|
+
return options, tf_options
|
69
|
+
end
|
70
|
+
|
71
|
+
def format_date(tb_formatted, format)
|
72
|
+
new_format = translate_format(format)
|
73
|
+
Date.parse(tb_formatted).strftime(new_format)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Method that translates the datepicker date formats, defined in (http://docs.jquery.com/UI/Datepicker/formatDate)
|
77
|
+
# to the ruby standard format (http://www.ruby-doc.org/core-1.9.3/Time.html#method-i-strftime).
|
78
|
+
# This gem is not going to support all the options, just the most used.
|
79
|
+
|
80
|
+
def translate_format(format)
|
81
|
+
format.gsub!(/#{FORMAT_REPLACEMENTES.keys.join("|")}/) { |match| FORMAT_REPLACEMENTES[match] }
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# BootstrapDatepicker
|
2
|
+
require "app/helpers/datepicker_helper.rb"
|
3
|
+
require "app/helpers/form_helper.rb"
|
4
|
+
require "engine.rb"
|
5
|
+
|
6
|
+
module BootstrapDatepicker
|
7
|
+
class Railtie < Rails::Railtie
|
8
|
+
initializer "BootstrapDatepicker" do
|
9
|
+
ActionController::Base.helper(BootstrapDatepicker::DatepickerHelper)
|
10
|
+
ActionView::Helpers::FormHelper.send(:include, BootstrapDatepicker::FormHelper)
|
11
|
+
ActionView::Base.send(:include, BootstrapDatepicker::DatepickerHelper)
|
12
|
+
ActionView::Helpers::FormBuilder.send(:include,BootstrapDatepicker::FormBuilder)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/engine.rb
ADDED
@@ -0,0 +1,416 @@
|
|
1
|
+
/* =========================================================
|
2
|
+
* bootstrap-datepicker.js
|
3
|
+
* http://www.eyecon.ro/bootstrap-datepicker
|
4
|
+
* =========================================================
|
5
|
+
* Copyright 2012 Stefan Petre
|
6
|
+
*
|
7
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
* you may not use this file except in compliance with the License.
|
9
|
+
* You may obtain a copy of the License at
|
10
|
+
*
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
*
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
* See the License for the specific language governing permissions and
|
17
|
+
* limitations under the License.
|
18
|
+
* ========================================================= */
|
19
|
+
|
20
|
+
$(function() {
|
21
|
+
$('.datetime_select').each(function(index, element) {
|
22
|
+
attributes = $(element).data()
|
23
|
+
|
24
|
+
console.log(attributes)
|
25
|
+
|
26
|
+
delete attributes.datepicker
|
27
|
+
|
28
|
+
console.log(attributes)
|
29
|
+
|
30
|
+
$(element).datepicker(attributes)
|
31
|
+
})
|
32
|
+
|
33
|
+
})
|
34
|
+
|
35
|
+
!function( $ ) {
|
36
|
+
|
37
|
+
// Picker object
|
38
|
+
|
39
|
+
var Datepicker = function(element, options){
|
40
|
+
this.element = $(element);
|
41
|
+
this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||'mm/dd/yyyy');
|
42
|
+
this.picker = $(DPGlobal.template)
|
43
|
+
.appendTo('body')
|
44
|
+
.on({
|
45
|
+
click: $.proxy(this.click, this),
|
46
|
+
mousedown: $.proxy(this.mousedown, this)
|
47
|
+
});
|
48
|
+
this.isInput = this.element.is('input');
|
49
|
+
this.component = this.element.is('.date') ? this.element.find('.add-on') : false;
|
50
|
+
|
51
|
+
if (this.isInput) {
|
52
|
+
this.element.on({
|
53
|
+
focus: $.proxy(this.show, this),
|
54
|
+
blur: $.proxy(this.hide, this),
|
55
|
+
keyup: $.proxy(this.update, this)
|
56
|
+
});
|
57
|
+
} else {
|
58
|
+
if (this.component){
|
59
|
+
this.component.on('click', $.proxy(this.show, this));
|
60
|
+
} else {
|
61
|
+
this.element.on('click', $.proxy(this.show, this));
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
this.viewMode = 0;
|
66
|
+
this.weekStart = options.weekStart||this.element.data('date-weekstart')||0;
|
67
|
+
this.weekEnd = this.weekStart == 0 ? 6 : this.weekStart - 1;
|
68
|
+
this.fillDow();
|
69
|
+
this.fillMonths();
|
70
|
+
this.update();
|
71
|
+
this.showMode();
|
72
|
+
};
|
73
|
+
|
74
|
+
Datepicker.prototype = {
|
75
|
+
constructor: Datepicker,
|
76
|
+
|
77
|
+
show: function(e) {
|
78
|
+
this.picker.show();
|
79
|
+
this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
|
80
|
+
this.place();
|
81
|
+
$(window).on('resize', $.proxy(this.place, this));
|
82
|
+
if (e ) {
|
83
|
+
e.stopPropagation();
|
84
|
+
e.preventDefault();
|
85
|
+
}
|
86
|
+
if (!this.isInput) {
|
87
|
+
$(document).on('mousedown', $.proxy(this.hide, this));
|
88
|
+
}
|
89
|
+
this.element.trigger({
|
90
|
+
type: 'show',
|
91
|
+
date: this.date
|
92
|
+
});
|
93
|
+
},
|
94
|
+
|
95
|
+
hide: function(){
|
96
|
+
this.picker.hide();
|
97
|
+
$(window).off('resize', this.place);
|
98
|
+
this.viewMode = 0;
|
99
|
+
this.showMode();
|
100
|
+
if (!this.isInput) {
|
101
|
+
$(document).off('mousedown', this.hide);
|
102
|
+
}
|
103
|
+
this.setValue();
|
104
|
+
this.element.trigger({
|
105
|
+
type: 'hide',
|
106
|
+
date: this.date
|
107
|
+
});
|
108
|
+
},
|
109
|
+
|
110
|
+
setValue: function() {
|
111
|
+
var formated = DPGlobal.formatDate(this.date, this.format);
|
112
|
+
if (!this.isInput) {
|
113
|
+
if (this.component){
|
114
|
+
this.element.find('input').prop('value', formated);
|
115
|
+
}
|
116
|
+
this.element.data('date', formated);
|
117
|
+
} else {
|
118
|
+
this.element.prop('value', formated);
|
119
|
+
}
|
120
|
+
},
|
121
|
+
|
122
|
+
place: function(){
|
123
|
+
var offset = this.component ? this.component.offset() : this.element.offset();
|
124
|
+
this.picker.css({
|
125
|
+
top: offset.top + this.height,
|
126
|
+
left: offset.left
|
127
|
+
});
|
128
|
+
},
|
129
|
+
|
130
|
+
update: function(){
|
131
|
+
this.date = DPGlobal.parseDate(
|
132
|
+
this.isInput ? this.element.prop('value') : this.element.data('date'),
|
133
|
+
this.format
|
134
|
+
);
|
135
|
+
this.viewDate = new Date(this.date);
|
136
|
+
this.fill();
|
137
|
+
},
|
138
|
+
|
139
|
+
fillDow: function(){
|
140
|
+
var dowCnt = this.weekStart;
|
141
|
+
var html = '<tr>';
|
142
|
+
while (dowCnt < this.weekStart + 7) {
|
143
|
+
html += '<th class="dow">'+DPGlobal.dates.daysMin[(dowCnt++)%7]+'</th>';
|
144
|
+
}
|
145
|
+
html += '</tr>';
|
146
|
+
this.picker.find('.datepicker-days thead').append(html);
|
147
|
+
},
|
148
|
+
|
149
|
+
fillMonths: function(){
|
150
|
+
var html = '';
|
151
|
+
var i = 0
|
152
|
+
while (i < 12) {
|
153
|
+
html += '<span class="month">'+DPGlobal.dates.monthsShort[i++]+'</span>';
|
154
|
+
}
|
155
|
+
this.picker.find('.datepicker-months td').append(html);
|
156
|
+
},
|
157
|
+
|
158
|
+
fill: function() {
|
159
|
+
var d = new Date(this.viewDate),
|
160
|
+
year = d.getFullYear(),
|
161
|
+
month = d.getMonth(),
|
162
|
+
currentDate = this.date.valueOf();
|
163
|
+
this.picker.find('.datepicker-days th:eq(1)')
|
164
|
+
.text(DPGlobal.dates.months[month]+' '+year);
|
165
|
+
var prevMonth = new Date(year, month-1, 28,0,0,0,0),
|
166
|
+
day = DPGlobal.getDaysInMonth(prevMonth.getFullYear(), prevMonth.getMonth());
|
167
|
+
prevMonth.setDate(day);
|
168
|
+
prevMonth.setDate(day - (prevMonth.getDay() - this.weekStart + 7)%7);
|
169
|
+
var nextMonth = new Date(prevMonth);
|
170
|
+
nextMonth.setDate(nextMonth.getDate() + 42);
|
171
|
+
nextMonth = nextMonth.valueOf();
|
172
|
+
html = [];
|
173
|
+
var clsName;
|
174
|
+
while(prevMonth.valueOf() < nextMonth) {
|
175
|
+
if (prevMonth.getDay() == this.weekStart) {
|
176
|
+
html.push('<tr>');
|
177
|
+
}
|
178
|
+
clsName = '';
|
179
|
+
if (prevMonth.getMonth() < month) {
|
180
|
+
clsName += ' old';
|
181
|
+
} else if (prevMonth.getMonth() > month) {
|
182
|
+
clsName += ' new';
|
183
|
+
}
|
184
|
+
if (prevMonth.valueOf() == currentDate) {
|
185
|
+
clsName += ' active';
|
186
|
+
}
|
187
|
+
html.push('<td class="day'+clsName+'">'+prevMonth.getDate() + '</td>');
|
188
|
+
if (prevMonth.getDay() == this.weekEnd) {
|
189
|
+
html.push('</tr>');
|
190
|
+
}
|
191
|
+
prevMonth.setDate(prevMonth.getDate()+1);
|
192
|
+
}
|
193
|
+
this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
|
194
|
+
var currentYear = this.date.getFullYear();
|
195
|
+
|
196
|
+
var months = this.picker.find('.datepicker-months')
|
197
|
+
.find('th:eq(1)')
|
198
|
+
.text(year)
|
199
|
+
.end()
|
200
|
+
.find('span').removeClass('active');
|
201
|
+
if (currentYear == year) {
|
202
|
+
months.eq(this.date.getMonth()).addClass('active');
|
203
|
+
}
|
204
|
+
|
205
|
+
html = '';
|
206
|
+
year = parseInt(year/10, 10) * 10;
|
207
|
+
var yearCont = this.picker.find('.datepicker-years')
|
208
|
+
.find('th:eq(1)')
|
209
|
+
.text(year + '-' + (year + 9))
|
210
|
+
.end()
|
211
|
+
.find('td');
|
212
|
+
year -= 1;
|
213
|
+
for (var i = -1; i < 11; i++) {
|
214
|
+
html += '<span class="year'+(i == -1 || i == 10 ? ' old' : '')+(currentYear == year ? ' active' : '')+'">'+year+'</span>';
|
215
|
+
year += 1;
|
216
|
+
}
|
217
|
+
yearCont.html(html);
|
218
|
+
},
|
219
|
+
|
220
|
+
click: function(e) {
|
221
|
+
e.stopPropagation();
|
222
|
+
e.preventDefault();
|
223
|
+
var target = $(e.target).closest('span, td, th');
|
224
|
+
if (target.length == 1) {
|
225
|
+
switch(target[0].nodeName.toLowerCase()) {
|
226
|
+
case 'th':
|
227
|
+
switch(target[0].className) {
|
228
|
+
case 'switch':
|
229
|
+
this.showMode(1);
|
230
|
+
break;
|
231
|
+
case 'prev':
|
232
|
+
case 'next':
|
233
|
+
this.viewDate['set'+DPGlobal.modes[this.viewMode].navFnc].call(
|
234
|
+
this.viewDate,
|
235
|
+
this.viewDate['get'+DPGlobal.modes[this.viewMode].navFnc].call(this.viewDate) +
|
236
|
+
DPGlobal.modes[this.viewMode].navStep * (target[0].className == 'prev' ? -1 : 1)
|
237
|
+
);
|
238
|
+
this.fill();
|
239
|
+
break;
|
240
|
+
}
|
241
|
+
break;
|
242
|
+
case 'span':
|
243
|
+
if (target.is('.month')) {
|
244
|
+
var month = target.parent().find('span').index(target);
|
245
|
+
this.viewDate.setMonth(month);
|
246
|
+
} else {
|
247
|
+
var year = parseInt(target.text(), 10)||0;
|
248
|
+
this.viewDate.setFullYear(year);
|
249
|
+
}
|
250
|
+
this.showMode(-1);
|
251
|
+
this.fill();
|
252
|
+
break;
|
253
|
+
case 'td':
|
254
|
+
if (target.is('.day')){
|
255
|
+
var day = parseInt(target.text(), 10)||1;
|
256
|
+
var month = this.viewDate.getMonth();
|
257
|
+
if (target.is('.old')) {
|
258
|
+
month -= 1;
|
259
|
+
} else if (target.is('.new')) {
|
260
|
+
month += 1;
|
261
|
+
}
|
262
|
+
var year = this.viewDate.getFullYear();
|
263
|
+
this.date = new Date(year, month, day,0,0,0,0);
|
264
|
+
this.viewDate = new Date(year, month, day,0,0,0,0);
|
265
|
+
this.fill();
|
266
|
+
this.setValue();
|
267
|
+
this.element.trigger({
|
268
|
+
type: 'changeDate',
|
269
|
+
date: this.date
|
270
|
+
});
|
271
|
+
}
|
272
|
+
break;
|
273
|
+
}
|
274
|
+
}
|
275
|
+
},
|
276
|
+
|
277
|
+
mousedown: function(e){
|
278
|
+
e.stopPropagation();
|
279
|
+
e.preventDefault();
|
280
|
+
},
|
281
|
+
|
282
|
+
showMode: function(dir) {
|
283
|
+
if (dir) {
|
284
|
+
this.viewMode = Math.max(0, Math.min(2, this.viewMode + dir));
|
285
|
+
}
|
286
|
+
this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
|
287
|
+
}
|
288
|
+
};
|
289
|
+
|
290
|
+
$.fn.datepicker = function ( option ) {
|
291
|
+
return this.each(function () {
|
292
|
+
var $this = $(this),
|
293
|
+
data = $this.data('datepicker'),
|
294
|
+
options = typeof option == 'object' && option;
|
295
|
+
if (!data) {
|
296
|
+
$this.data('datepicker', (data = new Datepicker(this, $.extend({}, $.fn.datepicker.defaults,options))));
|
297
|
+
}
|
298
|
+
if (typeof option == 'string') data[option]();
|
299
|
+
});
|
300
|
+
};
|
301
|
+
|
302
|
+
$.fn.datepicker.defaults = {
|
303
|
+
};
|
304
|
+
$.fn.datepicker.Constructor = Datepicker;
|
305
|
+
|
306
|
+
var DPGlobal = {
|
307
|
+
modes: [
|
308
|
+
{
|
309
|
+
clsName: 'days',
|
310
|
+
navFnc: 'Month',
|
311
|
+
navStep: 1
|
312
|
+
},
|
313
|
+
{
|
314
|
+
clsName: 'months',
|
315
|
+
navFnc: 'FullYear',
|
316
|
+
navStep: 1
|
317
|
+
},
|
318
|
+
{
|
319
|
+
clsName: 'years',
|
320
|
+
navFnc: 'FullYear',
|
321
|
+
navStep: 10
|
322
|
+
}],
|
323
|
+
dates:{
|
324
|
+
days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
|
325
|
+
daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
|
326
|
+
daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
|
327
|
+
months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
|
328
|
+
monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
|
329
|
+
},
|
330
|
+
isLeapYear: function (year) {
|
331
|
+
return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0))
|
332
|
+
},
|
333
|
+
getDaysInMonth: function (year, month) {
|
334
|
+
return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
|
335
|
+
},
|
336
|
+
parseFormat: function(format){
|
337
|
+
var separator = format.match(/[.\/-].*?/),
|
338
|
+
parts = format.split(/\W+/);
|
339
|
+
if (!separator || !parts || parts.length == 0){
|
340
|
+
throw new Error("Invalid date format.");
|
341
|
+
}
|
342
|
+
return {separator: separator, parts: parts};
|
343
|
+
},
|
344
|
+
parseDate: function(date, format) {
|
345
|
+
var parts = date.split(format.separator),
|
346
|
+
date = new Date(1970, 1, 1, 0, 0, 0),
|
347
|
+
val;
|
348
|
+
if (parts.length == format.parts.length) {
|
349
|
+
for (var i=0, cnt = format.parts.length; i < cnt; i++) {
|
350
|
+
val = parseInt(parts[i], 10)||1;
|
351
|
+
switch(format.parts[i]) {
|
352
|
+
case 'dd':
|
353
|
+
case 'd':
|
354
|
+
date.setDate(val);
|
355
|
+
break;
|
356
|
+
case 'mm':
|
357
|
+
case 'm':
|
358
|
+
date.setMonth(val - 1);
|
359
|
+
break;
|
360
|
+
case 'yy':
|
361
|
+
date.setFullYear(2000 + val);
|
362
|
+
break;
|
363
|
+
case 'yyyy':
|
364
|
+
date.setFullYear(val);
|
365
|
+
break;
|
366
|
+
}
|
367
|
+
}
|
368
|
+
}
|
369
|
+
return date;
|
370
|
+
},
|
371
|
+
formatDate: function(date, format){
|
372
|
+
var val = {
|
373
|
+
d: date.getDate(),
|
374
|
+
m: date.getMonth() + 1,
|
375
|
+
yy: date.getFullYear().toString().substring(2),
|
376
|
+
yyyy: date.getFullYear()
|
377
|
+
};
|
378
|
+
val.dd = (val.d < 10 ? '0' : '') + val.d;
|
379
|
+
val.mm = (val.m < 10 ? '0' : '') + val.m;
|
380
|
+
var date = [];
|
381
|
+
for (var i=0, cnt = format.parts.length; i < cnt; i++) {
|
382
|
+
date.push(val[format.parts[i]]);
|
383
|
+
}
|
384
|
+
return date.join(format.separator);
|
385
|
+
},
|
386
|
+
headTemplate: '<thead>'+
|
387
|
+
'<tr>'+
|
388
|
+
'<th class="prev"><i class="icon-arrow-left"/></th>'+
|
389
|
+
'<th colspan="5" class="switch"></th>'+
|
390
|
+
'<th class="next"><i class="icon-arrow-right"/></th>'+
|
391
|
+
'</tr>'+
|
392
|
+
'</thead>',
|
393
|
+
contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>'
|
394
|
+
};
|
395
|
+
DPGlobal.template = '<div class="datepicker dropdown-menu">'+
|
396
|
+
'<div class="datepicker-days">'+
|
397
|
+
'<table class=" table-condensed">'+
|
398
|
+
DPGlobal.headTemplate+
|
399
|
+
'<tbody></tbody>'+
|
400
|
+
'</table>'+
|
401
|
+
'</div>'+
|
402
|
+
'<div class="datepicker-months">'+
|
403
|
+
'<table class="table-condensed">'+
|
404
|
+
DPGlobal.headTemplate+
|
405
|
+
DPGlobal.contTemplate+
|
406
|
+
'</table>'+
|
407
|
+
'</div>'+
|
408
|
+
'<div class="datepicker-years">'+
|
409
|
+
'<table class="table-condensed">'+
|
410
|
+
DPGlobal.headTemplate+
|
411
|
+
DPGlobal.contTemplate+
|
412
|
+
'</table>'+
|
413
|
+
'</div>'+
|
414
|
+
'</div>';
|
415
|
+
|
416
|
+
}( window.jQuery )
|
@@ -0,0 +1 @@
|
|
1
|
+
//= require ./bootstrap-datepicker
|
@@ -0,0 +1,156 @@
|
|
1
|
+
/*!
|
2
|
+
* Datepicker for Bootstrap
|
3
|
+
*
|
4
|
+
* Copyright 2012 Stefan Petre
|
5
|
+
* Licensed under the Apache License v2.0
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
7
|
+
*
|
8
|
+
*/
|
9
|
+
.datepicker {
|
10
|
+
top: 0;
|
11
|
+
left: 0;
|
12
|
+
padding: 4px;
|
13
|
+
margin-top: 1px;
|
14
|
+
-webkit-border-radius: 4px;
|
15
|
+
-moz-border-radius: 4px;
|
16
|
+
border-radius: 4px;
|
17
|
+
/*.dow {
|
18
|
+
border-top: 1px solid #ddd !important;
|
19
|
+
}*/
|
20
|
+
}
|
21
|
+
.datepicker:before {
|
22
|
+
content: '';
|
23
|
+
display: inline-block;
|
24
|
+
border-left: 7px solid transparent;
|
25
|
+
border-right: 7px solid transparent;
|
26
|
+
border-bottom: 7px solid #ccc;
|
27
|
+
border-bottom-color: rgba(0, 0, 0, 0.2);
|
28
|
+
position: absolute;
|
29
|
+
top: -7px;
|
30
|
+
left: 6px;
|
31
|
+
}
|
32
|
+
.datepicker:after {
|
33
|
+
content: '';
|
34
|
+
display: inline-block;
|
35
|
+
border-left: 6px solid transparent;
|
36
|
+
border-right: 6px solid transparent;
|
37
|
+
border-bottom: 6px solid #ffffff;
|
38
|
+
position: absolute;
|
39
|
+
top: -6px;
|
40
|
+
left: 7px;
|
41
|
+
}
|
42
|
+
.datepicker > div {
|
43
|
+
display: none;
|
44
|
+
}
|
45
|
+
.datepicker table {
|
46
|
+
width: 100%;
|
47
|
+
margin: 0;
|
48
|
+
}
|
49
|
+
.datepicker td, .datepicker th {
|
50
|
+
text-align: center;
|
51
|
+
width: 20px;
|
52
|
+
height: 20px;
|
53
|
+
-webkit-border-radius: 4px;
|
54
|
+
-moz-border-radius: 4px;
|
55
|
+
border-radius: 4px;
|
56
|
+
}
|
57
|
+
.datepicker td.day:hover {
|
58
|
+
background: #eeeeee;
|
59
|
+
cursor: pointer;
|
60
|
+
}
|
61
|
+
.datepicker td.old, .datepicker td.new {
|
62
|
+
color: #999999;
|
63
|
+
}
|
64
|
+
.datepicker td.active, .datepicker td.active:hover {
|
65
|
+
background-color: #006dcc;
|
66
|
+
background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
|
67
|
+
background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
|
68
|
+
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
|
69
|
+
background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
|
70
|
+
background-image: -o-linear-gradient(top, #0088cc, #0044cc);
|
71
|
+
background-image: linear-gradient(top, #0088cc, #0044cc);
|
72
|
+
background-repeat: repeat-x;
|
73
|
+
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
|
74
|
+
border-color: #0044cc #0044cc #002a80;
|
75
|
+
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
76
|
+
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
77
|
+
color: #fff;
|
78
|
+
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
79
|
+
}
|
80
|
+
.datepicker td.active:hover,
|
81
|
+
.datepicker td.active:hover:hover,
|
82
|
+
.datepicker td.active:active,
|
83
|
+
.datepicker td.active:hover:active,
|
84
|
+
.datepicker td.active.active,
|
85
|
+
.datepicker td.active:hover.active,
|
86
|
+
.datepicker td.active.disabled,
|
87
|
+
.datepicker td.active:hover.disabled,
|
88
|
+
.datepicker td.active[disabled],
|
89
|
+
.datepicker td.active:hover[disabled] {
|
90
|
+
background-color: #0044cc;
|
91
|
+
}
|
92
|
+
.datepicker td.active:active,
|
93
|
+
.datepicker td.active:hover:active,
|
94
|
+
.datepicker td.active.active,
|
95
|
+
.datepicker td.active:hover.active {
|
96
|
+
background-color: #003399 \9;
|
97
|
+
}
|
98
|
+
.datepicker td span {
|
99
|
+
display: block;
|
100
|
+
width: 47px;
|
101
|
+
height: 54px;
|
102
|
+
line-height: 54px;
|
103
|
+
float: left;
|
104
|
+
margin: 2px;
|
105
|
+
cursor: pointer;
|
106
|
+
-webkit-border-radius: 4px;
|
107
|
+
-moz-border-radius: 4px;
|
108
|
+
border-radius: 4px;
|
109
|
+
}
|
110
|
+
.datepicker td span:hover {
|
111
|
+
background: #eeeeee;
|
112
|
+
}
|
113
|
+
.datepicker td span.active {
|
114
|
+
background-color: #006dcc;
|
115
|
+
background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
|
116
|
+
background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
|
117
|
+
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
|
118
|
+
background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
|
119
|
+
background-image: -o-linear-gradient(top, #0088cc, #0044cc);
|
120
|
+
background-image: linear-gradient(top, #0088cc, #0044cc);
|
121
|
+
background-repeat: repeat-x;
|
122
|
+
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
|
123
|
+
border-color: #0044cc #0044cc #002a80;
|
124
|
+
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
125
|
+
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
126
|
+
color: #fff;
|
127
|
+
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
128
|
+
}
|
129
|
+
.datepicker td span.active:hover,
|
130
|
+
.datepicker td span.active:active,
|
131
|
+
.datepicker td span.active.active,
|
132
|
+
.datepicker td span.active.disabled,
|
133
|
+
.datepicker td span.active[disabled] {
|
134
|
+
background-color: #0044cc;
|
135
|
+
}
|
136
|
+
.datepicker td span.active:active, .datepicker td span.active.active {
|
137
|
+
background-color: #003399 \9;
|
138
|
+
}
|
139
|
+
.datepicker td span.old {
|
140
|
+
color: #999999;
|
141
|
+
}
|
142
|
+
.datepicker th.switch {
|
143
|
+
width: 145px;
|
144
|
+
}
|
145
|
+
.datepicker thead tr:first-child th {
|
146
|
+
cursor: pointer;
|
147
|
+
}
|
148
|
+
.datepicker thead tr:first-child th:hover {
|
149
|
+
background: #eeeeee;
|
150
|
+
}
|
151
|
+
.input-append.date .add-on i, .input-prepend.date .add-on i {
|
152
|
+
display: block;
|
153
|
+
cursor: pointer;
|
154
|
+
width: 16px;
|
155
|
+
height: 16px;
|
156
|
+
}
|
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bootstrap_datepicker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.5'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Alberto Pastor
|
9
|
+
- Derek Willian Stavis
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2012-08-07 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: twitter-bootstrap-rails
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.1.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ~>
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: 2.1.1
|
31
|
+
description: View helper that allows to select dates from a calendar (using jQuery
|
32
|
+
and Twitter Bootstrap styles)
|
33
|
+
email: dekestavis@gmail.com
|
34
|
+
executables: []
|
35
|
+
extensions: []
|
36
|
+
extra_rdoc_files:
|
37
|
+
- README.rdoc
|
38
|
+
- lib/app/helpers/datepicker_helper.rb
|
39
|
+
- lib/app/helpers/form_helper.rb
|
40
|
+
- lib/bootstrap_datepicker.rb
|
41
|
+
files:
|
42
|
+
- README.rdoc
|
43
|
+
- Rakefile
|
44
|
+
- init.rb
|
45
|
+
- bootstrap_datepicker.gemspec
|
46
|
+
- lib/app/helpers/datepicker_helper.rb
|
47
|
+
- lib/app/helpers/form_helper.rb
|
48
|
+
- lib/bootstrap_datepicker.rb
|
49
|
+
- lib/engine.rb
|
50
|
+
- vendor/assets/javascripts/bootstrap-datepicker.js
|
51
|
+
- vendor/assets/javascripts/index.js
|
52
|
+
- vendor/assets/stylesheets/bootstrap-datepicker.css
|
53
|
+
homepage: http://github.com/derekstavis/bootstrap_datepicker
|
54
|
+
licenses: []
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options:
|
57
|
+
- --line-numbers
|
58
|
+
- --inline-source
|
59
|
+
- --title
|
60
|
+
- bootstrap_datepicker
|
61
|
+
- --main
|
62
|
+
- README.rdoc
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '1.2'
|
77
|
+
requirements: []
|
78
|
+
rubyforge_project: bootstrap_datepicker
|
79
|
+
rubygems_version: 1.8.24
|
80
|
+
signing_key:
|
81
|
+
specification_version: 3
|
82
|
+
summary: View helper that allows to select dates from a calendar (using jQuery and
|
83
|
+
Twitter Bootstrap styles)
|
84
|
+
test_files: []
|