rails_slickgrid 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE +20 -0
- data/README.md +24 -0
- data/Rakefile +58 -0
- data/lib/generators/rails_slickgrid/install/install_generator.rb +17 -0
- data/lib/generators/rails_slickgrid/install/javascripts/slick.columnpicker.js +105 -0
- data/lib/generators/rails_slickgrid/install/javascripts/slick.editors.js +608 -0
- data/lib/generators/rails_slickgrid/install/javascripts/slick.grid.js +2504 -0
- data/lib/generators/rails_slickgrid/install/javascripts/slick.model.js +294 -0
- data/lib/generators/rails_slickgrid/install/javascripts/slick.pager.js +146 -0
- data/lib/generators/rails_slickgrid/install/stylesheets/slick.columnpicker.css +30 -0
- data/lib/generators/rails_slickgrid/install/stylesheets/slick.grid.css +153 -0
- data/lib/generators/rails_slickgrid/install/stylesheets/slick.pager.css +48 -0
- data/lib/rails_slickgrid.rb +7 -0
- data/lib/rails_slickgrid/action_view.rb +22 -0
- data/lib/rails_slickgrid/railtie.rb +11 -0
- data/lib/rails_slickgrid/utils.rb +37 -0
- data/lib/rails_slickgrid/version.rb +3 -0
- metadata +83 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2011 Joe Martinez
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# Rails Slickgrid #
|
2
|
+
|
3
|
+
Rails Slickgrid is an effort to make the fast javascript grid/spreadsheet [SlickGrid](https://github.com/mleibman/SlickGrid) easier to use in rails.
|
4
|
+
|
5
|
+
It currently only generates the static assets into your `javascripts` and `stylesheets` but automatic grid generation is under development.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
1. Add `gem 'rails_slickgrid'` to your Gemfile
|
10
|
+
2. `bundle install`
|
11
|
+
3. `rails generate rails_slickgrid:install`
|
12
|
+
4. In your layout or view call `slickgrid_assets`
|
13
|
+
|
14
|
+
## TODO
|
15
|
+
1. Automatic grid generation
|
16
|
+
2. Column Detection
|
17
|
+
3. Editable Grids
|
18
|
+
4. Client side filters
|
19
|
+
5. Server side filters
|
20
|
+
|
21
|
+
## Copyright
|
22
|
+
|
23
|
+
SlickGrid itself is Copyright (c) 2010 Michael Leibman, http://github.com/mleibman/slickgrid
|
24
|
+
Rails Slickgrid is Copyright (c) 2011 Joe Martinez, https://github.com/capitalist/rails_slickgrid
|
data/Rakefile
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
3
|
+
require 'rubygems'
|
4
|
+
require 'awesome_print'
|
5
|
+
|
6
|
+
begin require 'bundler/setup'
|
7
|
+
rescue LoadError
|
8
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'rake'
|
12
|
+
require 'rake/rdoctask'
|
13
|
+
|
14
|
+
require 'rspec/core'
|
15
|
+
require 'rspec/core/rake_task'
|
16
|
+
|
17
|
+
RSpec::Core::RakeTask.new(:spec)
|
18
|
+
|
19
|
+
task :default => :spec
|
20
|
+
|
21
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
22
|
+
rdoc.rdoc_dir = 'rdoc'
|
23
|
+
rdoc.title = 'Rails Slickgrid'
|
24
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
25
|
+
rdoc.rdoc_files.include('README.rdoc')
|
26
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
27
|
+
end
|
28
|
+
|
29
|
+
require "rails_slickgrid/version"
|
30
|
+
task :build do
|
31
|
+
system "gem build rails_slickgrid.gemspec"
|
32
|
+
end
|
33
|
+
|
34
|
+
task :release => :build do
|
35
|
+
system "gem push rails_slickgrid-#{RailsSlickgrid::VERSION}.gem"
|
36
|
+
end
|
37
|
+
|
38
|
+
require 'rails_slickgrid/utils'
|
39
|
+
desc 'Download slickgrid assets'
|
40
|
+
task :download_slickgrid do
|
41
|
+
stylesheets = {
|
42
|
+
'https://github.com/mleibman/SlickGrid/raw/1.4.3/slick.columnpicker.css' => 'lib/generators/rails_slickgrid/install/stylesheets/:name',
|
43
|
+
'https://github.com/mleibman/SlickGrid/raw/1.4.3/slick.grid.css' => 'lib/generators/rails_slickgrid/install/stylesheets/:name',
|
44
|
+
'https://github.com/mleibman/SlickGrid/raw/1.4.3/slick.pager.css' => 'lib/generators/rails_slickgrid/install/stylesheets/:name',
|
45
|
+
}
|
46
|
+
|
47
|
+
javascripts = {
|
48
|
+
'https://github.com/mleibman/SlickGrid/raw/1.4.3/slick.columnpicker.js' => 'lib/generators/rails_slickgrid/install/javascripts/:name',
|
49
|
+
'https://github.com/mleibman/SlickGrid/raw/1.4.3/slick.editors.js' => 'lib/generators/rails_slickgrid/install/javascripts/:name',
|
50
|
+
'https://github.com/mleibman/SlickGrid/raw/1.4.3/slick.model.js' => 'lib/generators/rails_slickgrid/install/javascripts/:name',
|
51
|
+
'https://github.com/mleibman/SlickGrid/raw/1.4.3/slick.grid.js' => 'lib/generators/rails_slickgrid/install/javascripts/:name',
|
52
|
+
'https://github.com/mleibman/SlickGrid/raw/1.4.3/slick.pager.js' => 'lib/generators/rails_slickgrid/install/javascripts/:name',
|
53
|
+
}
|
54
|
+
|
55
|
+
stylesheets.merge(javascripts).each do |url,path|
|
56
|
+
RailsSlickgrid::Utils.curl url, '-o', path.gsub(/:name/,url.split('/').last)
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module RailsSlickgrid
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
source_root File.expand_path("..", __FILE__)
|
5
|
+
desc "Copies Slickgrid assets into your public directory."
|
6
|
+
|
7
|
+
def copy_stylesheets
|
8
|
+
directory 'stylesheets', 'public/stylesheets/slickgrid'
|
9
|
+
end
|
10
|
+
|
11
|
+
def copy_javascripts
|
12
|
+
directory 'javascripts', 'public/javascripts/slickgrid'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,105 @@
|
|
1
|
+
(function($) {
|
2
|
+
function SlickColumnPicker(columns,grid,options)
|
3
|
+
{
|
4
|
+
var $menu;
|
5
|
+
|
6
|
+
var defaults = {
|
7
|
+
fadeSpeed: 250
|
8
|
+
};
|
9
|
+
|
10
|
+
function init() {
|
11
|
+
grid.onHeaderContextMenu = displayContextMenu;
|
12
|
+
options = $.extend({}, defaults, options);
|
13
|
+
|
14
|
+
$menu = $("<span class='slick-columnpicker' style='display:none;position:absolute;z-index:20;' />").appendTo(document.body);
|
15
|
+
|
16
|
+
$menu.bind("mouseleave", function(e) { $(this).fadeOut(options.fadeSpeed) });
|
17
|
+
$menu.bind("click", updateColumn);
|
18
|
+
|
19
|
+
}
|
20
|
+
|
21
|
+
function displayContextMenu(e)
|
22
|
+
{
|
23
|
+
$menu.empty();
|
24
|
+
|
25
|
+
var visibleColumns = grid.getColumns();
|
26
|
+
var $li, $input;
|
27
|
+
for (var i=0; i<columns.length; i++) {
|
28
|
+
$li = $("<li />").appendTo($menu);
|
29
|
+
|
30
|
+
$input = $("<input type='checkbox' />")
|
31
|
+
.attr("id", "columnpicker_" + i)
|
32
|
+
.data("id", columns[i].id)
|
33
|
+
.appendTo($li);
|
34
|
+
|
35
|
+
if (grid.getColumnIndex(columns[i].id) != null)
|
36
|
+
$input.attr("checked","checked");
|
37
|
+
|
38
|
+
$("<label for='columnpicker_" + i + "' />")
|
39
|
+
.text(columns[i].name)
|
40
|
+
.appendTo($li);
|
41
|
+
}
|
42
|
+
|
43
|
+
$("<hr/>").appendTo($menu);
|
44
|
+
$li = $("<li />").appendTo($menu);
|
45
|
+
$input = $("<input type='checkbox' id='autoresize' />").appendTo($li);
|
46
|
+
$("<label for='autoresize'>Force Fit Columns</label>").appendTo($li);
|
47
|
+
if (grid.getOptions().forceFitColumns)
|
48
|
+
$input.attr("checked", "checked");
|
49
|
+
|
50
|
+
$li = $("<li />").appendTo($menu);
|
51
|
+
$input = $("<input type='checkbox' id='syncresize' />").appendTo($li);
|
52
|
+
$("<label for='syncresize'>Synchronous Resizing</label>").appendTo($li);
|
53
|
+
if (grid.getOptions().syncColumnCellResize)
|
54
|
+
$input.attr("checked", "checked");
|
55
|
+
|
56
|
+
$menu
|
57
|
+
.css("top", e.pageY - 10)
|
58
|
+
.css("left", e.pageX - 10)
|
59
|
+
.fadeIn(options.fadeSpeed);
|
60
|
+
}
|
61
|
+
|
62
|
+
function updateColumn(e)
|
63
|
+
{
|
64
|
+
if (e.target.id == 'autoresize') {
|
65
|
+
if (e.target.checked) {
|
66
|
+
grid.setOptions({forceFitColumns: true});
|
67
|
+
grid.autosizeColumns();
|
68
|
+
} else {
|
69
|
+
grid.setOptions({forceFitColumns: false});
|
70
|
+
}
|
71
|
+
return;
|
72
|
+
}
|
73
|
+
|
74
|
+
if (e.target.id == 'syncresize') {
|
75
|
+
if (e.target.checked) {
|
76
|
+
grid.setOptions({syncColumnCellResize: true});
|
77
|
+
} else {
|
78
|
+
grid.setOptions({syncColumnCellResize: false});
|
79
|
+
}
|
80
|
+
return;
|
81
|
+
}
|
82
|
+
|
83
|
+
if ($(e.target).is(":checkbox")) {
|
84
|
+
if ($menu.find(":checkbox:checked").length == 0) {
|
85
|
+
$(e.target).attr("checked","checked");
|
86
|
+
return;
|
87
|
+
}
|
88
|
+
|
89
|
+
var visibleColumns = [];
|
90
|
+
$menu.find(":checkbox[id^=columnpicker]").each(function(i,e) {
|
91
|
+
if ($(this).is(":checked")) {
|
92
|
+
visibleColumns.push(columns[i]);
|
93
|
+
}
|
94
|
+
});
|
95
|
+
grid.setColumns(visibleColumns);
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
|
100
|
+
init();
|
101
|
+
}
|
102
|
+
|
103
|
+
// Slick.Controls.ColumnPicker
|
104
|
+
$.extend(true, window, { Slick: { Controls: { ColumnPicker: SlickColumnPicker }}});
|
105
|
+
})(jQuery);
|
@@ -0,0 +1,608 @@
|
|
1
|
+
/* THESE FORMATTERS & EDITORS ARE JUST SAMPLES! */
|
2
|
+
|
3
|
+
(function($) {
|
4
|
+
|
5
|
+
var SlickEditor = {
|
6
|
+
|
7
|
+
SelectorCellFormatter : function(row, cell, value, columnDef, dataContext) {
|
8
|
+
return (!dataContext ? "" : row);
|
9
|
+
},
|
10
|
+
|
11
|
+
PercentCompleteCellFormatter : function(row, cell, value, columnDef, dataContext) {
|
12
|
+
if (value == null || value === "")
|
13
|
+
return "-";
|
14
|
+
else if (value < 50)
|
15
|
+
return "<span style='color:red;font-weight:bold;'>" + value + "%</span>";
|
16
|
+
else
|
17
|
+
return "<span style='color:green'>" + value + "%</span>";
|
18
|
+
},
|
19
|
+
|
20
|
+
GraphicalPercentCompleteCellFormatter : function(row, cell, value, columnDef, dataContext) {
|
21
|
+
if (value == null || value === "")
|
22
|
+
return "";
|
23
|
+
|
24
|
+
var color;
|
25
|
+
|
26
|
+
if (value < 30)
|
27
|
+
color = "red";
|
28
|
+
else if (value < 70)
|
29
|
+
color = "silver";
|
30
|
+
else
|
31
|
+
color = "green";
|
32
|
+
|
33
|
+
return "<span class='percent-complete-bar' style='background:" + color + ";width:" + value + "%'></span>";
|
34
|
+
},
|
35
|
+
|
36
|
+
YesNoCellFormatter : function(row, cell, value, columnDef, dataContext) {
|
37
|
+
return value ? "Yes" : "No";
|
38
|
+
},
|
39
|
+
|
40
|
+
BoolCellFormatter : function(row, cell, value, columnDef, dataContext) {
|
41
|
+
return value ? "<img src='../images/tick.png'>" : "";
|
42
|
+
},
|
43
|
+
|
44
|
+
TaskNameFormatter : function(row, cell, value, columnDef, dataContext) {
|
45
|
+
// todo: html encode
|
46
|
+
var spacer = "<span style='display:inline-block;height:1px;width:" + (2 + 15 * dataContext["indent"]) + "px'></span>";
|
47
|
+
return spacer + " <img src='../images/expand.gif'> " + value;
|
48
|
+
},
|
49
|
+
|
50
|
+
ResourcesFormatter : function(row, cell, value, columnDef, dataContext) {
|
51
|
+
var resources = dataContext["resources"];
|
52
|
+
|
53
|
+
if (!resources || resources.length == 0)
|
54
|
+
return "";
|
55
|
+
|
56
|
+
if (columnDef.width < 50)
|
57
|
+
return (resources.length > 1 ? "<center><img src='../images/user_identity_plus.gif' " : "<center><img src='../images/user_identity.gif' ") +
|
58
|
+
" title='" + resources.join(", ") + "'></center>";
|
59
|
+
else
|
60
|
+
return resources.join(", ");
|
61
|
+
},
|
62
|
+
|
63
|
+
StarFormatter : function(row, cell, value, columnDef, dataContext) {
|
64
|
+
return (value) ? "<img src='../images/bullet_star.png' align='absmiddle'>" : "";
|
65
|
+
},
|
66
|
+
|
67
|
+
|
68
|
+
TextCellEditor : function(args) {
|
69
|
+
var $input;
|
70
|
+
var defaultValue;
|
71
|
+
var scope = this;
|
72
|
+
|
73
|
+
this.init = function() {
|
74
|
+
$input = $("<INPUT type=text class='editor-text' />")
|
75
|
+
.appendTo(args.container)
|
76
|
+
.bind("keydown.nav", function(e) {
|
77
|
+
if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) {
|
78
|
+
e.stopImmediatePropagation();
|
79
|
+
}
|
80
|
+
})
|
81
|
+
.focus()
|
82
|
+
.select();
|
83
|
+
};
|
84
|
+
|
85
|
+
this.destroy = function() {
|
86
|
+
$input.remove();
|
87
|
+
};
|
88
|
+
|
89
|
+
this.focus = function() {
|
90
|
+
$input.focus();
|
91
|
+
};
|
92
|
+
|
93
|
+
this.loadValue = function(item) {
|
94
|
+
defaultValue = item[args.column.field] || "";
|
95
|
+
$input.val(defaultValue);
|
96
|
+
$input[0].defaultValue = defaultValue;
|
97
|
+
$input.select();
|
98
|
+
};
|
99
|
+
|
100
|
+
this.serializeValue = function() {
|
101
|
+
return $input.val();
|
102
|
+
};
|
103
|
+
|
104
|
+
this.applyValue = function(item,state) {
|
105
|
+
item[args.column.field] = state;
|
106
|
+
};
|
107
|
+
|
108
|
+
this.isValueChanged = function() {
|
109
|
+
return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
|
110
|
+
};
|
111
|
+
|
112
|
+
this.validate = function() {
|
113
|
+
if (args.column.validator) {
|
114
|
+
var validationResults = args.column.validator($input.val());
|
115
|
+
if (!validationResults.valid)
|
116
|
+
return validationResults;
|
117
|
+
}
|
118
|
+
|
119
|
+
return {
|
120
|
+
valid: true,
|
121
|
+
msg: null
|
122
|
+
};
|
123
|
+
};
|
124
|
+
|
125
|
+
this.init();
|
126
|
+
},
|
127
|
+
|
128
|
+
IntegerCellEditor : function(args) {
|
129
|
+
var $input;
|
130
|
+
var defaultValue;
|
131
|
+
var scope = this;
|
132
|
+
|
133
|
+
this.init = function() {
|
134
|
+
$input = $("<INPUT type=text class='editor-text' />");
|
135
|
+
|
136
|
+
$input.bind("keydown.nav", function(e) {
|
137
|
+
if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) {
|
138
|
+
e.stopImmediatePropagation();
|
139
|
+
}
|
140
|
+
});
|
141
|
+
|
142
|
+
$input.appendTo(args.container);
|
143
|
+
$input.focus().select();
|
144
|
+
};
|
145
|
+
|
146
|
+
this.destroy = function() {
|
147
|
+
$input.remove();
|
148
|
+
};
|
149
|
+
|
150
|
+
this.focus = function() {
|
151
|
+
$input.focus();
|
152
|
+
};
|
153
|
+
|
154
|
+
this.loadValue = function(item) {
|
155
|
+
defaultValue = item[args.column.field];
|
156
|
+
$input.val(defaultValue);
|
157
|
+
$input[0].defaultValue = defaultValue;
|
158
|
+
$input.select();
|
159
|
+
};
|
160
|
+
|
161
|
+
this.serializeValue = function() {
|
162
|
+
return parseInt($input.val(),10) || 0;
|
163
|
+
};
|
164
|
+
|
165
|
+
this.applyValue = function(item,state) {
|
166
|
+
item[args.column.field] = state;
|
167
|
+
};
|
168
|
+
|
169
|
+
this.isValueChanged = function() {
|
170
|
+
return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
|
171
|
+
};
|
172
|
+
|
173
|
+
this.validate = function() {
|
174
|
+
if (isNaN($input.val()))
|
175
|
+
return {
|
176
|
+
valid: false,
|
177
|
+
msg: "Please enter a valid integer"
|
178
|
+
};
|
179
|
+
|
180
|
+
return {
|
181
|
+
valid: true,
|
182
|
+
msg: null
|
183
|
+
};
|
184
|
+
};
|
185
|
+
|
186
|
+
this.init();
|
187
|
+
},
|
188
|
+
|
189
|
+
DateCellEditor : function(args) {
|
190
|
+
var $input;
|
191
|
+
var defaultValue;
|
192
|
+
var scope = this;
|
193
|
+
var calendarOpen = false;
|
194
|
+
|
195
|
+
this.init = function() {
|
196
|
+
$input = $("<INPUT type=text class='editor-text' />");
|
197
|
+
$input.appendTo(args.container);
|
198
|
+
$input.focus().select();
|
199
|
+
$input.datepicker({
|
200
|
+
showOn: "button",
|
201
|
+
buttonImageOnly: true,
|
202
|
+
buttonImage: "../images/calendar.gif",
|
203
|
+
beforeShow: function() { calendarOpen = true },
|
204
|
+
onClose: function() { calendarOpen = false }
|
205
|
+
});
|
206
|
+
$input.width($input.width() - 18);
|
207
|
+
};
|
208
|
+
|
209
|
+
this.destroy = function() {
|
210
|
+
$.datepicker.dpDiv.stop(true,true);
|
211
|
+
$input.datepicker("hide");
|
212
|
+
$input.datepicker("destroy");
|
213
|
+
$input.remove();
|
214
|
+
};
|
215
|
+
|
216
|
+
this.show = function() {
|
217
|
+
if (calendarOpen) {
|
218
|
+
$.datepicker.dpDiv.stop(true,true).show();
|
219
|
+
}
|
220
|
+
};
|
221
|
+
|
222
|
+
this.hide = function() {
|
223
|
+
if (calendarOpen) {
|
224
|
+
$.datepicker.dpDiv.stop(true,true).hide();
|
225
|
+
}
|
226
|
+
};
|
227
|
+
|
228
|
+
this.position = function(position) {
|
229
|
+
if (!calendarOpen) return;
|
230
|
+
$.datepicker.dpDiv
|
231
|
+
.css("top", position.top + 30)
|
232
|
+
.css("left", position.left);
|
233
|
+
};
|
234
|
+
|
235
|
+
this.focus = function() {
|
236
|
+
$input.focus();
|
237
|
+
};
|
238
|
+
|
239
|
+
this.loadValue = function(item) {
|
240
|
+
defaultValue = item[args.column.field];
|
241
|
+
$input.val(defaultValue);
|
242
|
+
$input[0].defaultValue = defaultValue;
|
243
|
+
$input.select();
|
244
|
+
};
|
245
|
+
|
246
|
+
this.serializeValue = function() {
|
247
|
+
return $input.val();
|
248
|
+
};
|
249
|
+
|
250
|
+
this.applyValue = function(item,state) {
|
251
|
+
item[args.column.field] = state;
|
252
|
+
};
|
253
|
+
|
254
|
+
this.isValueChanged = function() {
|
255
|
+
return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
|
256
|
+
};
|
257
|
+
|
258
|
+
this.validate = function() {
|
259
|
+
return {
|
260
|
+
valid: true,
|
261
|
+
msg: null
|
262
|
+
};
|
263
|
+
};
|
264
|
+
|
265
|
+
this.init();
|
266
|
+
},
|
267
|
+
|
268
|
+
YesNoSelectCellEditor : function(args) {
|
269
|
+
var $select;
|
270
|
+
var defaultValue;
|
271
|
+
var scope = this;
|
272
|
+
|
273
|
+
this.init = function() {
|
274
|
+
$select = $("<SELECT tabIndex='0' class='editor-yesno'><OPTION value='yes'>Yes</OPTION><OPTION value='no'>No</OPTION></SELECT>");
|
275
|
+
$select.appendTo(args.container);
|
276
|
+
$select.focus();
|
277
|
+
};
|
278
|
+
|
279
|
+
this.destroy = function() {
|
280
|
+
$select.remove();
|
281
|
+
};
|
282
|
+
|
283
|
+
this.focus = function() {
|
284
|
+
$select.focus();
|
285
|
+
};
|
286
|
+
|
287
|
+
this.loadValue = function(item) {
|
288
|
+
$select.val((defaultValue = item[args.column.field]) ? "yes" : "no");
|
289
|
+
$select.select();
|
290
|
+
};
|
291
|
+
|
292
|
+
this.serializeValue = function() {
|
293
|
+
return ($select.val() == "yes");
|
294
|
+
};
|
295
|
+
|
296
|
+
this.applyValue = function(item,state) {
|
297
|
+
item[args.column.field] = state;
|
298
|
+
};
|
299
|
+
|
300
|
+
this.isValueChanged = function() {
|
301
|
+
return ($select.val() != defaultValue);
|
302
|
+
};
|
303
|
+
|
304
|
+
this.validate = function() {
|
305
|
+
return {
|
306
|
+
valid: true,
|
307
|
+
msg: null
|
308
|
+
};
|
309
|
+
};
|
310
|
+
|
311
|
+
this.init();
|
312
|
+
},
|
313
|
+
|
314
|
+
YesNoCheckboxCellEditor : function(args) {
|
315
|
+
var $select;
|
316
|
+
var defaultValue;
|
317
|
+
var scope = this;
|
318
|
+
|
319
|
+
this.init = function() {
|
320
|
+
$select = $("<INPUT type=checkbox value='true' class='editor-checkbox' hideFocus>");
|
321
|
+
$select.appendTo(args.container);
|
322
|
+
$select.focus();
|
323
|
+
};
|
324
|
+
|
325
|
+
this.destroy = function() {
|
326
|
+
$select.remove();
|
327
|
+
};
|
328
|
+
|
329
|
+
this.focus = function() {
|
330
|
+
$select.focus();
|
331
|
+
};
|
332
|
+
|
333
|
+
this.loadValue = function(item) {
|
334
|
+
defaultValue = item[args.column.field];
|
335
|
+
if (defaultValue)
|
336
|
+
$select.attr("checked", "checked");
|
337
|
+
else
|
338
|
+
$select.removeAttr("checked");
|
339
|
+
};
|
340
|
+
|
341
|
+
this.serializeValue = function() {
|
342
|
+
return $select.attr("checked");
|
343
|
+
};
|
344
|
+
|
345
|
+
this.applyValue = function(item,state) {
|
346
|
+
item[args.column.field] = state;
|
347
|
+
};
|
348
|
+
|
349
|
+
this.isValueChanged = function() {
|
350
|
+
return ($select.attr("checked") != defaultValue);
|
351
|
+
};
|
352
|
+
|
353
|
+
this.validate = function() {
|
354
|
+
return {
|
355
|
+
valid: true,
|
356
|
+
msg: null
|
357
|
+
};
|
358
|
+
};
|
359
|
+
|
360
|
+
this.init();
|
361
|
+
},
|
362
|
+
|
363
|
+
PercentCompleteCellEditor : function(args) {
|
364
|
+
var $input, $picker;
|
365
|
+
var defaultValue;
|
366
|
+
var scope = this;
|
367
|
+
|
368
|
+
this.init = function() {
|
369
|
+
$input = $("<INPUT type=text class='editor-percentcomplete' />");
|
370
|
+
$input.width($(args.container).innerWidth() - 25);
|
371
|
+
$input.appendTo(args.container);
|
372
|
+
|
373
|
+
$picker = $("<div class='editor-percentcomplete-picker' />").appendTo(args.container);
|
374
|
+
$picker.append("<div class='editor-percentcomplete-helper'><div class='editor-percentcomplete-wrapper'><div class='editor-percentcomplete-slider' /><div class='editor-percentcomplete-buttons' /></div></div>");
|
375
|
+
|
376
|
+
$picker.find(".editor-percentcomplete-buttons").append("<button val=0>Not started</button><br/><button val=50>In Progress</button><br/><button val=100>Complete</button>");
|
377
|
+
|
378
|
+
$input.focus().select();
|
379
|
+
|
380
|
+
$picker.find(".editor-percentcomplete-slider").slider({
|
381
|
+
orientation: "vertical",
|
382
|
+
range: "min",
|
383
|
+
value: defaultValue,
|
384
|
+
slide: function(event, ui) {
|
385
|
+
$input.val(ui.value)
|
386
|
+
}
|
387
|
+
});
|
388
|
+
|
389
|
+
$picker.find(".editor-percentcomplete-buttons button").bind("click", function(e) {
|
390
|
+
$input.val($(this).attr("val"));
|
391
|
+
$picker.find(".editor-percentcomplete-slider").slider("value", $(this).attr("val"));
|
392
|
+
})
|
393
|
+
};
|
394
|
+
|
395
|
+
this.destroy = function() {
|
396
|
+
$input.remove();
|
397
|
+
$picker.remove();
|
398
|
+
};
|
399
|
+
|
400
|
+
this.focus = function() {
|
401
|
+
$input.focus();
|
402
|
+
};
|
403
|
+
|
404
|
+
this.loadValue = function(item) {
|
405
|
+
$input.val(defaultValue = item[args.column.field]);
|
406
|
+
$input.select();
|
407
|
+
};
|
408
|
+
|
409
|
+
this.serializeValue = function() {
|
410
|
+
return parseInt($input.val(),10) || 0;
|
411
|
+
};
|
412
|
+
|
413
|
+
this.applyValue = function(item,state) {
|
414
|
+
item[args.column.field] = state;
|
415
|
+
};
|
416
|
+
|
417
|
+
this.isValueChanged = function() {
|
418
|
+
return (!($input.val() == "" && defaultValue == null)) && ((parseInt($input.val(),10) || 0) != defaultValue);
|
419
|
+
};
|
420
|
+
|
421
|
+
this.validate = function() {
|
422
|
+
if (isNaN(parseInt($input.val(),10)))
|
423
|
+
return {
|
424
|
+
valid: false,
|
425
|
+
msg: "Please enter a valid positive number"
|
426
|
+
};
|
427
|
+
|
428
|
+
return {
|
429
|
+
valid: true,
|
430
|
+
msg: null
|
431
|
+
};
|
432
|
+
};
|
433
|
+
|
434
|
+
this.init();
|
435
|
+
},
|
436
|
+
|
437
|
+
StarCellEditor : function(args) {
|
438
|
+
var $input;
|
439
|
+
var defaultValue;
|
440
|
+
var scope = this;
|
441
|
+
|
442
|
+
function toggle(e) {
|
443
|
+
if (e.type == "keydown" && e.which != 32) return;
|
444
|
+
|
445
|
+
if ($input.css("opacity") == "1")
|
446
|
+
$input.css("opacity", 0.5);
|
447
|
+
else
|
448
|
+
$input.css("opacity", 1);
|
449
|
+
|
450
|
+
e.preventDefault();
|
451
|
+
e.stopPropagation();
|
452
|
+
return false;
|
453
|
+
}
|
454
|
+
|
455
|
+
this.init = function() {
|
456
|
+
$input = $("<IMG src='../images/bullet_star.png' align=absmiddle tabIndex=0 title='Click or press Space to toggle' />")
|
457
|
+
.bind("click keydown", toggle)
|
458
|
+
.appendTo(args.container)
|
459
|
+
.focus();
|
460
|
+
};
|
461
|
+
|
462
|
+
this.destroy = function() {
|
463
|
+
$input.unbind("click keydown", toggle);
|
464
|
+
$input.remove();
|
465
|
+
};
|
466
|
+
|
467
|
+
this.focus = function() {
|
468
|
+
$input.focus();
|
469
|
+
};
|
470
|
+
|
471
|
+
this.loadValue = function(item) {
|
472
|
+
defaultValue = item[args.column.field];
|
473
|
+
$input.css("opacity", defaultValue ? 1 : 0.2);
|
474
|
+
};
|
475
|
+
|
476
|
+
this.serializeValue = function() {
|
477
|
+
return ($input.css("opacity") == "1");
|
478
|
+
};
|
479
|
+
|
480
|
+
this.applyValue = function(item,state) {
|
481
|
+
item[args.column.field] = state;
|
482
|
+
};
|
483
|
+
|
484
|
+
this.isValueChanged = function() {
|
485
|
+
return defaultValue != ($input.css("opacity") == "1");
|
486
|
+
};
|
487
|
+
|
488
|
+
this.validate = function() {
|
489
|
+
return {
|
490
|
+
valid: true,
|
491
|
+
msg: null
|
492
|
+
};
|
493
|
+
};
|
494
|
+
|
495
|
+
this.init();
|
496
|
+
},
|
497
|
+
|
498
|
+
/*
|
499
|
+
* An example of a "detached" editor.
|
500
|
+
* The UI is added onto document BODY and .position(), .show() and .hide() are implemented.
|
501
|
+
* KeyDown events are also handled to provide handling for Tab, Shift-Tab, Esc and Ctrl-Enter.
|
502
|
+
*/
|
503
|
+
LongTextCellEditor : function (args) {
|
504
|
+
var $input, $wrapper;
|
505
|
+
var defaultValue;
|
506
|
+
var scope = this;
|
507
|
+
|
508
|
+
this.init = function() {
|
509
|
+
var $container = $("body");
|
510
|
+
|
511
|
+
$wrapper = $("<DIV style='z-index:10000;position:absolute;background:white;padding:5px;border:3px solid gray; -moz-border-radius:10px; border-radius:10px;'/>")
|
512
|
+
.appendTo($container);
|
513
|
+
|
514
|
+
$input = $("<TEXTAREA hidefocus rows=5 style='backround:white;width:250px;height:80px;border:0;outline:0'>")
|
515
|
+
.appendTo($wrapper);
|
516
|
+
|
517
|
+
$("<DIV style='text-align:right'><BUTTON>Save</BUTTON><BUTTON>Cancel</BUTTON></DIV>")
|
518
|
+
.appendTo($wrapper);
|
519
|
+
|
520
|
+
$wrapper.find("button:first").bind("click", this.save);
|
521
|
+
$wrapper.find("button:last").bind("click", this.cancel);
|
522
|
+
$input.bind("keydown", this.handleKeyDown);
|
523
|
+
|
524
|
+
scope.position(args.position);
|
525
|
+
$input.focus().select();
|
526
|
+
};
|
527
|
+
|
528
|
+
this.handleKeyDown = function(e) {
|
529
|
+
if (e.which == $.ui.keyCode.ENTER && e.ctrlKey) {
|
530
|
+
scope.save();
|
531
|
+
}
|
532
|
+
else if (e.which == $.ui.keyCode.ESCAPE) {
|
533
|
+
e.preventDefault();
|
534
|
+
scope.cancel();
|
535
|
+
}
|
536
|
+
else if (e.which == $.ui.keyCode.TAB && e.shiftKey) {
|
537
|
+
e.preventDefault();
|
538
|
+
grid.navigatePrev();
|
539
|
+
}
|
540
|
+
else if (e.which == $.ui.keyCode.TAB) {
|
541
|
+
e.preventDefault();
|
542
|
+
grid.navigateNext();
|
543
|
+
}
|
544
|
+
};
|
545
|
+
|
546
|
+
this.save = function() {
|
547
|
+
args.commitChanges();
|
548
|
+
};
|
549
|
+
|
550
|
+
this.cancel = function() {
|
551
|
+
$input.val(defaultValue);
|
552
|
+
args.cancelChanges();
|
553
|
+
};
|
554
|
+
|
555
|
+
this.hide = function() {
|
556
|
+
$wrapper.hide();
|
557
|
+
};
|
558
|
+
|
559
|
+
this.show = function() {
|
560
|
+
$wrapper.show();
|
561
|
+
};
|
562
|
+
|
563
|
+
this.position = function(position) {
|
564
|
+
$wrapper
|
565
|
+
.css("top", position.top - 5)
|
566
|
+
.css("left", position.left - 5)
|
567
|
+
};
|
568
|
+
|
569
|
+
this.destroy = function() {
|
570
|
+
$wrapper.remove();
|
571
|
+
};
|
572
|
+
|
573
|
+
this.focus = function() {
|
574
|
+
$input.focus();
|
575
|
+
};
|
576
|
+
|
577
|
+
this.loadValue = function(item) {
|
578
|
+
$input.val(defaultValue = item[args.column.field]);
|
579
|
+
$input.select();
|
580
|
+
};
|
581
|
+
|
582
|
+
this.serializeValue = function() {
|
583
|
+
return $input.val();
|
584
|
+
};
|
585
|
+
|
586
|
+
this.applyValue = function(item,state) {
|
587
|
+
item[args.column.field] = state;
|
588
|
+
};
|
589
|
+
|
590
|
+
this.isValueChanged = function() {
|
591
|
+
return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
|
592
|
+
};
|
593
|
+
|
594
|
+
this.validate = function() {
|
595
|
+
return {
|
596
|
+
valid: true,
|
597
|
+
msg: null
|
598
|
+
};
|
599
|
+
};
|
600
|
+
|
601
|
+
this.init();
|
602
|
+
}
|
603
|
+
|
604
|
+
};
|
605
|
+
|
606
|
+
$.extend(window, SlickEditor);
|
607
|
+
|
608
|
+
})(jQuery);
|