diff --git a/frappe/core/doctype/report/report.js b/frappe/core/doctype/report/report.js
index 9222c86974..903a9cbac4 100644
--- a/frappe/core/doctype/report/report.js
+++ b/frappe/core/doctype/report/report.js
@@ -54,7 +54,7 @@ cur_frm.cscript.refresh = function(doc) {
frappe.ui.form.on('Report', {
refresh: function(frm) {
- if(!frappe.boot.developer_mode && user != 'Administrator') {
+ if(!frappe.boot.developer_mode && frappe.session.user != 'Administrator') {
// make the document read-only
frm.set_read_only();
}
diff --git a/frappe/desk/report_dump.py b/frappe/desk/report_dump.py
index 296dc11baf..86b1765814 100644
--- a/frappe/desk/report_dump.py
+++ b/frappe/desk/report_dump.py
@@ -8,18 +8,16 @@ import json
import copy
@frappe.whitelist()
-def get_data(doctypes, last_modified):
+def get_data(doctypes, last_modified):
data_map = {}
for dump_report_map in frappe.get_hooks().dump_report_map:
data_map.update(frappe.get_attr(dump_report_map))
-
- import datetime
+
out = {}
-
+
doctypes = json.loads(doctypes)
last_modified = json.loads(last_modified)
-
- start = datetime.datetime.now()
+
for d in doctypes:
args = copy.deepcopy(data_map[d])
dt = d.find("[") != -1 and d[:d.find("[")] or d
@@ -29,7 +27,7 @@ def get_data(doctypes, last_modified):
modified_table = "item."
else:
modified_table = ""
-
+
conditions = order_by = ""
table = args.get("from") or ("`tab%s`" % dt)
@@ -39,30 +37,30 @@ def get_data(doctypes, last_modified):
args['conditions'].append(modified_table + "modified > '" + last_modified[d] + "'")
out[dt]["modified_names"] = frappe.db.sql_list("""select %sname from %s
where %smodified > %s""" % (modified_table, table, modified_table, "%s"), last_modified[d])
-
+
if args.get("force_index"):
conditions = " force index (%s) " % args["force_index"]
if args.get("conditions"):
conditions += " where " + " and ".join(args["conditions"])
if args.get("order_by"):
order_by = " order by " + args["order_by"]
-
+
out[dt]["data"] = [list(t) for t in frappe.db.sql("""select %s from %s %s %s""" \
% (",".join(args["columns"]), table, conditions, order_by))]
-
+
# last modified
modified_table = table
if "," in table:
modified_table = " ".join(table.split(",")[0].split(" ")[:-1])
-
- tmp = frappe.db.sql("""select `modified`
+
+ tmp = frappe.db.sql("""select `modified`
from %s order by modified desc limit 1""" % modified_table)
out[dt]["last_modified"] = tmp and tmp[0][0] or ""
- out[dt]["columns"] = map(lambda c: c.split(" as ")[-1], args["columns"])
-
+ out[dt]["columns"] = list(map(lambda c: c.split(" as ")[-1], args["columns"]))
+
if args.get("links"):
out[dt]["links"] = args["links"]
-
+
for d in out:
unused_links = []
# only compress full dumps (not partial)
@@ -70,25 +68,28 @@ def get_data(doctypes, last_modified):
for link_key in out[d]["links"]:
link = out[d]["links"][link_key]
if link[0] in out and (link[0] not in last_modified):
-
+
# make a map of link ids
# to index
link_map = {}
doctype_data = out[link[0]]
+
col_idx = doctype_data["columns"].index(link[1])
for row_idx in range(len(doctype_data["data"])):
row = doctype_data["data"][row_idx]
link_map[row[col_idx]] = row_idx
-
+
for row in out[d]["data"]:
- col_idx = out[d]["columns"].index(link_key)
- # replace by id
- if row[col_idx]:
- row[col_idx] = link_map.get(row[col_idx])
+ columns = list(out[d]["columns"])
+ if link_key in columns:
+ col_idx = columns.index(link_key)
+ # replace by id
+ if row[col_idx]:
+ row[col_idx] = link_map.get(row[col_idx])
else:
unused_links.append(link_key)
-
+
for link in unused_links:
del out[d]["links"][link]
-
+
return out
diff --git a/frappe/public/build.json b/frappe/public/build.json
index 4a532ef908..76180f99ef 100755
--- a/frappe/public/build.json
+++ b/frappe/public/build.json
@@ -357,7 +357,6 @@
],
"js/report.min.js": [
"public/js/lib/clusterize.min.js",
- "public/js/lib/frappe-datatable.js",
"public/js/frappe/views/reports/report_factory.js",
"public/js/frappe/views/reports/report_view.js",
"public/js/frappe/views/reports/reportview_footer.html",
diff --git a/frappe/public/css/slickgrid.css b/frappe/public/css/slickgrid.css
deleted file mode 100644
index 961da50b55..0000000000
--- a/frappe/public/css/slickgrid.css
+++ /dev/null
@@ -1,62 +0,0 @@
-.slick-header-column,
-.slick-cell {
- -webkit-box-sizing: content-box;
- -moz-box-sizing: content-box;
- box-sizing: content-box;
-}
-.slick-wrapper,
-.slick-header {
- border: none !important;
-}
-.slick-headerrow {
- border: none;
- border-bottom: 1px solid #d1d8dd;
-}
-.slick-headerrow-column {
- background-color: #F7FAFC !important;
- text-overflow: clip;
-}
-.slick-headerrow-column input {
- border: 1px solid #d1d8dd;
- border-radius: 3px;
- font-size: 12px;
- padding: 0px 3px !important;
- margin: 0;
- width: 100%;
- min-height: 20px;
-}
-.slick-cell,
-.slick-headerrow-column {
- font-size: 12px;
- border-color: transparent #d1d8dd #d1d8dd transparent !important;
- border-style: solid;
- color: inherit !important;
- margin-top: -1px;
-}
-.slick-cell pre {
- border: none;
- background-color: transparent;
- padding: 3px;
-}
-.slick-header-column,
-.slick-header-columns {
- font-size: 12px;
- font-weight: bold;
- background-color: #F7FAFC;
- border-color: #d1d8dd !important;
- color: #8D99A6 !important;
-}
-.slick-header-column:hover,
-.slick-header-column-active {
- background-image: none;
- background-color: #d9e7f1;
-}
-.slick-row.odd .slick-cell {
- background-color: #fafbfc;
-}
-.frappe-rtl .slick-wrapper {
- direction: ltr;
-}
-.slick-cell > span[data-field="_comments"] * {
- display: inline-block;
-}
diff --git a/frappe/public/js/frappe/views/reports/grid_report.js b/frappe/public/js/frappe/views/reports/grid_report.js
index df82757f82..a143c0464a 100644
--- a/frappe/public/js/frappe/views/reports/grid_report.js
+++ b/frappe/public/js/frappe/views/reports/grid_report.js
@@ -1,6 +1,7 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt
+import DataTable from 'frappe-datatable';
frappe.provide("frappe.report_dump");
$.extend(frappe.report_dump, {
@@ -34,15 +35,15 @@ $.extend(frappe.report_dump, {
} else {
row[link_key] = null;
}
- })
- })
+ });
+ });
}
}
});
callback();
}
- })
+ });
},
set_data: function(doctype, doctype_data) {
var data = [];
@@ -55,7 +56,7 @@ $.extend(frappe.report_dump, {
row.id = row.name;
row.doctype = doctype;
return row;
- }
+ };
if(frappe.report_dump.last_modified[doctype]) {
// partial loading, make a name dict
$.each(doctype_data.data, function(i, d) {
@@ -79,7 +80,7 @@ $.extend(frappe.report_dump, {
// add new records
$.each(replace_dict, function(name, d) {
data.push(d);
- })
+ });
} else {
// first loading
@@ -98,7 +99,6 @@ frappe.views.GridReport = Class.extend({
this.filter_inputs = {};
this.preset_checks = [];
this.tree_grid = {show: false};
- var me = this;
$.extend(this, opts);
this.wrapper = $('
")
+ this.grid_wrapper = $("
")
.appendTo(this.wrapper);
this.id = frappe.dom.set_unique_id(this.grid_wrapper.get(0));
- // zero-value check
- $('
\
-
').appendTo(this.wrapper);
-
this.bind_show();
frappe.cur_grid_report = this;
@@ -412,40 +404,33 @@ frappe.views.GridReport = Class.extend({
enableColumnReorder: false
},
render: function() {
- // new slick grid
- this.grid = new Slick.Grid("#"+this.id, this.dataView, this.dataview_columns, this.options);
- var me = this;
+ this.datatable = new DataTable('#' + this.id, {
+ columns: this.datatable_columns,
+ data: this.data,
+ layout: 'fixed',
+ inlineFilters: true,
+ treeView: true,
+ checkboxColumn: true,
+ checkedRowStatus: false,
+ events: {
+ onCheckRow: (row) => {
+ const rowIndex = row.meta.rowIndex;
+ const checked = this.datatable.rowmanager.checkMap[rowIndex];
+ const data = this.datatable.datamanager.getData(rowIndex);
+ data.checked = Boolean(checked);
- if (!frappe.dom.is_touchscreen()) {
- this.grid.setSelectionModel(new Slick.CellSelectionModel());
- this.grid.registerPlugin(new Slick.CellExternalCopyManager({
- dataItemColumnValueExtractor: function(item, columnDef, value) {
- return item[columnDef.field];
+ this.setup_chart && this.setup_chart();
}
- }));
- }
-
- // bind events
- this.dataView.onRowsChanged.subscribe(function (e, args) {
- me.grid.invalidateRows(args.rows);
- me.grid.render();
+ }
});
- this.dataView.onRowCountChanged.subscribe(function (e, args) {
- me.grid.updateRowCount();
- me.grid.render();
+ this.data.forEach((d, i) => {
+ if (d.checked) {
+ this.datatable.rowmanager.checkRow(i, true);
+ }
});
-
- this.tree_grid.show && this.add_tree_grid_events();
},
prepare_data_view: function() {
- // initialize the model
- this.dataView = new Slick.Data.DataView({ inlineFilters: true });
- this.dataView.beginUpdate();
- this.dataView.setItems(this.data);
- if(this.dataview_filter) this.dataView.setFilter(this.dataview_filter);
- if(this.tree_grid.show) this.dataView.setFilter(this.tree_dataview_filter);
- this.dataView.endUpdate();
},
export: function() {
frappe.tools.downloadify(frappe.slickgrid_tools.get_view_data(this.columns, this.dataView),
@@ -501,10 +486,11 @@ frappe.views.GridReport = Class.extend({
is_default: function(fieldname) {
return this[fieldname]==this[fieldname + "_default"];
},
- date_formatter: function(row, cell, value, columnDef, dataContext) {
+ date_formatter: function(row, cell, value) {
return frappe.datetime.str_to_user(value);
},
currency_formatter: function(row, cell, value, columnDef, dataContext) {
+ if (isNaN(value)) value = '';
return repl('
%(value)s
', {
_style: dataContext._style || "",
value: ((value==null || value==="") ? "" : format_number(value))
@@ -513,7 +499,7 @@ frappe.views.GridReport = Class.extend({
text_formatter: function(row, cell, value, columnDef, dataContext) {
return repl('
%(value)s', {
_style: dataContext._style || "",
- esc_value: cstr(value).replace(/"/g, '\"'),
+ esc_value: cstr(value).replace(/"/g, '\\"'),
value: cstr(value)
});
},
@@ -522,11 +508,10 @@ frappe.views.GridReport = Class.extend({
class="chart-check" %(checked)s>', {
"id": dataContext.id,
"checked": dataContext.checked ? 'checked="checked"' : ""
- })
+ });
},
apply_link_formatters: function() {
- var me = this;
- $.each(this.dataview_columns, function(i, col) {
+ $.each(this.columns, function(i, col) {
if(col.link_formatter) {
col.formatter = function(row, cell, value, columnDef, dataContext, for_print) {
// added link and open button to links
@@ -548,9 +533,10 @@ frappe.views.GridReport = Class.extend({
}
// make link to add a filter
+ var html;
var link_formatter = me.dataview_columns[cell].link_formatter;
if (link_formatter.filter_input) {
- var html = repl('
\
%(value)s', {
@@ -559,7 +545,7 @@ frappe.views.GridReport = Class.extend({
page_name: frappe.container.page.page_name
});
} else {
- var html = value;
+ html = value;
}
// make icon to open form
@@ -570,9 +556,9 @@ frappe.views.GridReport = Class.extend({
html += me.get_link_open_icon(doctype, value);
}
return html;
- }
+ };
}
- })
+ });
},
get_link_open_icon: function(doctype, name) {
return repl('
\
@@ -601,13 +587,13 @@ frappe.views.GridReport = Class.extend({
formatter: me.currency_formatter,
width: 100
});
- }
+ };
var build_columns = function(condition) {
// add column for each date range
for(var i=0; i <= date_diff; i++) {
var date = frappe.datetime.add_days(me.from_date, i);
- if(!condition) condition = function() { return true; }
+ if(!condition) condition = () => true;
if(condition(date)) add_column(date);
me.last_date = date;
@@ -616,7 +602,7 @@ frappe.views.GridReport = Class.extend({
me.column_map[date] = me.columns[me.columns.length-1];
}
}
- }
+ };
// make columns for all date ranges
if(range=='Daily') {
@@ -624,17 +610,17 @@ frappe.views.GridReport = Class.extend({
} else if(range=='Weekly') {
build_columns(function(date) {
if(!me.last_date) return true;
- return !(frappe.datetime.get_diff(date, me.from_date) % 7)
+ return !(frappe.datetime.get_diff(date, me.from_date) % 7);
});
} else if(range=='Monthly') {
build_columns(function(date) {
if(!me.last_date) return true;
- return frappe.datetime.str_to_obj(me.last_date).getMonth() != frappe.datetime.str_to_obj(date).getMonth()
+ return frappe.datetime.str_to_obj(me.last_date).getMonth() != frappe.datetime.str_to_obj(date).getMonth();
});
} else if(range=='Quarterly') {
build_columns(function(date) {
if(!me.last_date) return true;
- return frappe.datetime.str_to_obj(date).getDate()==1 && in_list([0,3,6,9], frappe.datetime.str_to_obj(date).getMonth())
+ return frappe.datetime.str_to_obj(date).getDate()==1 && in_list([0,3,6,9], frappe.datetime.str_to_obj(date).getMonth());
});
} else if(range=='Yearly') {
build_columns(function(date) {
@@ -665,7 +651,6 @@ frappe.views.GridReport = Class.extend({
frappe.views.GridReportWithPlot = frappe.views.GridReport.extend({
setup_chart: function() {
- var me = this;
if (in_list(["Daily", "Weekly"], this.filter_inputs.range.val())) {
this.chart_area.toggle(false);
return;
@@ -674,33 +659,14 @@ frappe.views.GridReportWithPlot = frappe.views.GridReport.extend({
}
var chart_data = this.get_chart_data ? this.get_chart_data() : null;
- this.chart = new Chart(".chart", {
+ const parent = this.wrapper.find('.chart')[0];
+ this.chart = new Chart(parent, {
height: 200,
data: chart_data,
type: 'line'
});
},
- setup_chart_check: function() {
- var me = this;
- me.wrapper.bind('make', function() {
- me.wrapper.on("click", ".chart-check", function() {
- var checked = $(this).prop("checked");
- var id = $(this).attr("data-id");
- if(me.item_by_name) {
- if(me.item_by_name[id]) {
- me.item_by_name[id].checked = checked ? true : false;
- }
- } else {
- $.each(me.data, function(i, d) {
- if(d.id==id) d.checked = checked;
- });
- }
- me.setup_chart();
- });
- });
- },
-
get_chart_data: function() {
var me = this;
var plottable_cols = [];
@@ -752,7 +718,7 @@ frappe.views.TreeGridReport = frappe.views.GridReportWithPlot.extend({
},
add_tree_grid_events: function() {
var me = this;
- this.grid.onClick.subscribe(function (e, args) {
+ this.grid.onClick.subscribe(function(e, args) {
if ($(e.target).hasClass("toggle")) {
var item = me.dataView.getItem(args.row);
if (item) {
@@ -768,7 +734,7 @@ frappe.views.TreeGridReport = frappe.views.GridReportWithPlot.extend({
}
});
},
- tree_formatter: function (row, cell, value, columnDef, dataContext) {
+ tree_formatter: function(row, cell, value, columnDef, dataContext) {
var me = frappe.cur_grid_report;
var data = me.data;
var spacer = "").appendTo(this.page.main);
- $('\
- \
- \
- \
-
\
-
\
-
\
-
\
-
\
- '+__('For comparative filters, start with')+' ">" or "<" or "!", e.g. >5 or >01-02-2012 or !0\
-
'+__('For ranges')+' ('+__('values and dates')+') use ":", \
- e.g. "5:10" (' + __("to filter values between 5 & 10") + ')
\
-
').appendTo(this.wrapper);
- this.wrapper.find(".expand-all").on("click", function() { me.toggle_all(false);});
- this.wrapper.find(".collapse-all").on("click", function() { me.toggle_all(true);});
- this.chart_area = this.wrapper.find(".chart-area");
- this.make_toolbar();
- },
- toggle_expand_collapse_buttons: function(show) {
- this.wrapper.find(".expand-all, .collapse-all").toggleClass('hidden', !!!show);
- },
- make_toolbar: function() {
- var me = this;
- this.page.set_secondary_action(__('Refresh'), function() { me.refresh(); });
-
- // Edit
- this.page.add_menu_item(__('Edit'), function() {
- if(!frappe.user.is_report_manager()) {
- frappe.msgprint(__("You are not allowed to create / edit reports"));
- return false;
- }
- frappe.set_route("Form", "Report", me.report_name);
- }, true);
-
- this.page.add_menu_item(__("Print"), function() {
- frappe.ui.get_print_settings(false, function(print_settings) {
- me.print_settings = print_settings;
- me.print_report();
- }, me.report_doc.letter_head);
- }, true);
-
- this.page.add_menu_item(__("PDF"), function() {
- frappe.ui.get_print_settings(true, function(print_settings) {
- me.print_settings = print_settings;
- me.pdf_report();
- }, me.report_doc.letter_head);
- }, true);
-
- this.page.add_menu_item(__('Export'), function() {
- me.make_export();
- }, true);
-
- this.page.add_menu_item(__("Setup Auto Email"), function() {
- frappe.set_route('List', 'Auto Email Report', {'report' : me.report_name});
- }, true);
-
- if(frappe.model.can_set_user_permissions("Report")) {
- this.page.add_menu_item(__("User Permissions"), function() {
- frappe.route_options = {
- doctype: "Report",
- name: me.report_name
- };
- frappe.set_route('List', 'User Permission');
- }, true);
- }
-
- // add to desktop
- this.page.add_menu_item(__("Add to Desktop"), function() {
- frappe.add_to_desktop(me.report_name, null, me.report_name);
- }, true);
- },
- load: function() {
- // load from route
- var route = frappe.get_route();
- var me = this;
- if(route[1]) {
- if((me.report_name!=route[1]) || frappe.route_options) {
- me.report_name = route[1];
- this.wrapper.find(".no-report-area").toggle(false);
- me.page.set_title(__(me.report_name));
-
- frappe.model.with_doc("Report", me.report_name, function() {
-
- me.report_doc = frappe.get_doc("Report", me.report_name);
-
- frappe.model.with_doctype(me.report_doc.ref_doctype, function() {
- var module = locals.DocType[me.report_doc.ref_doctype].module;
- frappe.breadcrumbs.add(module)
-
- if(!frappe.query_reports[me.report_name]) {
- return frappe.call({
- method:"frappe.desk.query_report.get_script",
- args: {
- report_name: me.report_name
- },
- callback: function(r) {
- frappe.dom.eval(r.message.script || "");
-
- frappe.after_ajax(function() {
- var report_settings = frappe.query_reports[me.report_name];
- me.html_format = r.message.html_format;
- report_settings["html_format"] = r.message.html_format;
-
- me.setup_report();
- });
- }
- });
- } else {
- me.setup_report();
- }
- });
- });
- }
- } else {
- var msg = __("No Report Loaded. Please use query-report/[Report Name] to run a report.")
- this.wrapper.find(".no-report-area").html(msg).toggle(true);
- }
- },
- setup_report: function() {
- var me = this;
- this.page.set_title(__(this.report_name));
- this.page.clear_inner_toolbar();
- this.setup_filters();
- this.chart_area.toggle(false);
- this.toggle_expand_collapse_buttons(false);
- this.is_tree_report = false;
-
- var report_settings = frappe.query_reports[this.report_name];
-
- $.when(function() {
- if (report_settings.onload) {
- return report_settings.onload(me);
- }
-
- }()).then(function() {
- me.refresh();
- });
- },
- print_report: function() {
- if(!frappe.model.can_print(this.report_doc.ref_doctype)) {
- frappe.msgprint(__("You are not allowed to print this report"));
- return false;
- }
- if(this.html_format) {
- var content = frappe.render(this.html_format, {
- data: frappe.slickgrid_tools.get_filtered_items(this.dataView),
- filters: this.get_values(),
- report: this,
- data_to_be_printed: this.data_to_be_printed
- });
-
- frappe.render_grid({
- content: content,
- title: __(this.report_name),
- print_settings: this.print_settings,
- columns: this.columns
- });
- } else {
- frappe.render_grid({
- grid: this.grid,
- report: this,
- title: __(this.report_name),
- print_settings: this.print_settings,
- });
- }
- },
- pdf_report: function() {
- var me = this;
- var base_url = frappe.urllib.get_base_url();
- var print_css = frappe.boot.print_css;
-
- if(!frappe.model.can_print(this.report_doc.ref_doctype)) {
- frappe.msgprint(__("You are not allowed to make PDF for this report"));
- return false;
- }
-
- var orientation = this.print_settings.orientation;
- var landscape = orientation == "Landscape" ? true: false
- var columns = this.grid.getColumns();
- if(this.html_format) {
- var content = frappe.render(this.html_format, {
- data: frappe.slickgrid_tools.get_filtered_items(this.dataView),
- filters:this.get_values(),
- report:this,
- data_to_be_printed: this.data_to_be_printed
- });
-
- //Render Report in HTML
- var html = frappe.render_template("print_template", {
- content:content,
- title:__(this.report_name),
- base_url: base_url,
- print_css: print_css,
- print_settings: this.print_settings,
- landscape: landscape,
- columns: columns
- });
- } else {
- // rows filtered by inline_filter of slickgrid
- var visible_idx = frappe.slickgrid_tools
- .get_view_data(this.columns, this.dataView)
- .map(row => row[0]).filter(idx => idx !== 'Sr No');
-
- var data = this.grid.getData().getItems();
- data = data.filter(d => visible_idx.includes(d._id));
-
- var content = frappe.render_template("print_grid", {
- columns:columns,
- data:data,
- title:__(this.report_name)
- })
-
- //Render Report in HTML
- var html = frappe.render_template("print_template",{
- content:content,
- title:__(this.report_name),
- base_url: base_url,
- print_css: print_css,
- print_settings: this.print_settings,
- landscape: landscape,
- columns: columns
- });
- }
-
- var orientation = this.print_settings.orientation;
- this.open_pdf_report(html, orientation)
- },
- open_pdf_report: function(html, orientation) {
- //Create a form to place the HTML content
- var formData = new FormData();
-
- //Push the HTML content into an element
- formData.append("html", html);
- formData.append("orientation", orientation);
- var blob = new Blob([], { type: "text/xml"});
- //formData.append("webmasterfile", blob);
- formData.append("blob", blob);
-
- var xhr = new XMLHttpRequest();
- xhr.open("POST", '/api/method/frappe.utils.print_format.report_to_pdf');
- xhr.setRequestHeader("X-Frappe-CSRF-Token", frappe.csrf_token);
- xhr.responseType = "arraybuffer";
-
- xhr.onload = function(success) {
- if (this.status === 200) {
- var blob = new Blob([success.currentTarget.response], {type: "application/pdf"});
- var objectUrl = URL.createObjectURL(blob);
-
- //Open report in a new window
- window.open(objectUrl);
- }
- };
- xhr.send(formData);
- },
- setup_filters: function() {
- if(this.setting_filters) return;
-
- this.clear_filters();
- var me = this;
- $.each(frappe.query_reports[this.report_name].filters || [], function(i, df) {
- if(df.fieldtype==="Break") {
- me.page.add_break();
- } else {
- var f = me.page.add_field(df);
- $(f.wrapper).addClass("filters pull-left");
- me.filters.push(f);
-
- if(df["default"]) {
- f.set_input(df["default"]);
- }
- if(df.fieldtype=="Check") {
- $(f.wrapper).find("input[type='checkbox']");
- }
-
- if(df.get_query) f.get_query = df.get_query;
- if(df.on_change) f.on_change = df.on_change;
- df.onchange = () => {
- if(!me.flags.filters_set) {
- // don't trigger change while setting filters
- return;
- }
- if (f.on_change) {
- f.on_change(me);
- } else {
- me.trigger_refresh();
- }
- }
- }
- });
-
- // hide page form if no filters
- var $filters = $(this.parent).find('.page-form .filters');
- $(this.parent).find('.page-form').toggle($filters.length ? true : false);
-
- // set the field 'query_report_filters_by_name' first as they can be used in
- // setting/triggering the filters
- this.set_filters_by_name();
-
- this.setting_filters = true;
- this.set_route_filters();
- this.setting_filters = false;
-
- this.flags.filters_set = true;
- },
- clear_filters: function() {
- this.filters = [];
- $(this.parent).find('.page-form .filters').remove();
- },
- set_filters_by_name: function() {
- frappe.query_report_filters_by_name = {};
- for(var i in this.filters) {
- frappe.query_report_filters_by_name[this.filters[i].df.fieldname] = this.filters[i];
- }
- },
- set_route_filters: function() {
- var me = this;
- if(frappe.route_options) {
- const fields = Object.keys(frappe.route_options);
- const filters_to_set = this.filters.filter(f => fields.includes(f.df.fieldname));
-
- const promises = filters_to_set.map(f => {
- return () => {
- const value = frappe.route_options[f.df.fieldname];
- return f.set_value(value);
- }
- });
- promises.push(() => {
- frappe.route_options = null;
- });
-
- return frappe.run_serially(promises);
- }
-
- },
- refresh: function() {
- // throttle
- // stop refresh from being called multiple times (from triggers ?)
- if (!this.request_refresh) {
- this.request_refresh = setTimeout(() => {
- this._refresh();
- this.request_refresh = null;
- }, 300);
- }
- },
- _refresh: function() {
- // Run
- var me = this;
-
- this.wrapper.find(".results").toggle(false);
- try {
- var filters = this.get_values(true);
- } catch(e) {
- // don't run report
- return;
- }
-
- this.waiting = frappe.messages.waiting(this.wrapper.find(".waiting-area").empty().toggle(true),
- __("Loading Report") + "...");
- this.wrapper.find(".no-report-area").toggle(false);
-
- if (this.report_ajax) {
- // abort previous request
- this.report_ajax.abort();
- }
-
- this.chart_area.toggle(false);
-
- this.report_ajax = frappe.call({
- method: "frappe.desk.query_report.run",
- type: "GET",
- args: {
- "report_name": me.report_name,
- filters: filters
- },
- callback: function(r) {
- me.report_ajax = undefined;
- me.make_results(r.message);
- }
- });
-
- return this.report_ajax;
- },
- trigger_refresh: function() {
- var me = this;
- var filters = me.get_values();
-
- // check if required filters are not missing
- var missing = false;
- $.each(me.filters, function(k, _f) {
- if (_f.df.reqd && !filters[_f.df.fieldname]) {
- missing = true;
- return;
- }
- });
-
- if (!missing) {
- me.refresh();
- }
- },
- get_values: function(raise) {
- var filters = {};
- var mandatory_fields = [];
- $.each(this.filters || [], function(i, f) {
- var v = f.get_value();
- // TODO: hidden fields dont have $input
- if(f.df.hidden) v = f.value;
- if(v === '%') v = null;
- if(f.df.reqd && !v) mandatory_fields.push(f.df.label);
- if(v) filters[f.df.fieldname] = v;
- })
- if(raise && mandatory_fields.length) {
- this.chart_area.hide();
- this.wrapper.find(".waiting-area").empty().toggle(false);
- this.wrapper.find(".no-report-area").html(__("Please set filters")).toggle(true);
- if(raise) {
- console.log('filter missing: ' + mandatory_fields);
- throw "Filters required";
- }
- }
-
- return filters;
- },
- make_results: function(res) {
- this.wrapper.find(".waiting-area, .no-report-area").empty().toggle(false);
- this.wrapper.find(".results").toggle(true);
- this.make_columns(res.columns);
- this.make_data(res.result, res.columns);
- this.filter_hidden_columns();
- this.render(res);
- },
- render: function(res) {
- this.columnFilters = {};
- this.make_dataview();
- this.id = frappe.dom.set_unique_id(this.wrapper.find(".result-area").addClass("slick-wrapper").get(0));
-
- this.grid = new Slick.Grid("#"+this.id, this.dataView, this.columns,
- this.slickgrid_options);
-
- if (!frappe.dom.is_touchscreen()) {
- this.grid.setSelectionModel(new Slick.CellSelectionModel());
- this.grid.registerPlugin(new Slick.CellExternalCopyManager({
- dataItemColumnValueExtractor: function(item, columnDef, value) {
- return item[columnDef.field];
- }
- }));
- }
-
- this.setup_header_row();
- this.grid.init();
- this.setup_sort();
-
- // further setup of grid like click subscription for tree
- if (this.get_query_report_opts().tree) {
- this.setup_tree();
- }
-
- this.set_message(res.message);
- this.setup_chart(res);
- this.set_print_data(res.data_to_be_printed);
-
- this.toggle_expand_collapse_buttons(this.is_tree_report);
- },
-
- make_columns: function(columns) {
- var me = this;
- var formatter = this.get_formatter();
-
- this.columns = [{id: "_id", field: "_id", name: __("Sr No"), width: 60}]
- .concat($.map(columns, function(c, i) {
- if ($.isPlainObject(c)) {
- var df = c;
- } else if (c.indexOf(":")!==-1) {
- var opts = c.split(":");
- var df = {
- label: opts.length<=2 ? opts[0] : opts.slice(0, opts.length - 2).join(":"),
- fieldtype: opts.length<=2 ? opts[1] : opts[opts.length - 2],
- width: opts.length<=2 ? opts[2] : opts[opts.length - 1]
- };
- if (df.fieldtype.indexOf("/")!==-1) {
- var tmp = df.fieldtype.split("/");
- df.fieldtype = tmp[0];
- df.options = tmp[1];
- }
- df.width = cint(df.width);
- } else {
- var df = {
- label: c,
- fieldtype: "Data"
- };
- }
-
- if (!df.fieldtype) df.fieldtype = "Data";
- if (!cint(df.width)) df.width = 80;
-
- var col = $.extend({}, df, {
- label: df.label || (df.fieldname && __(toTitle(df.fieldname.replace(/_/g, " ")))) || "",
- sortable: true,
- df: df,
- formatter: formatter
- });
-
- col.field = df.fieldname || df.label;
- df.label = __(df.label);
- col.name = col.id = col.label = df.label;
-
- if(df.width < 0) {
- col.hidden = true;
- }
-
- return col
- }));
- },
- filter_hidden_columns: function() {
- this.columns = $.map(this.columns, function(c, i) {
- return (c.hidden==1 ? null : c);
- });
- },
- get_query_report_opts: function() {
- return frappe.query_reports[this.report_name] || {};
- },
- get_formatter: function() {
- var formatter = function(row, cell, value, columnDef, dataContext, for_print) {
- var value = frappe.format(value, columnDef.df, {for_print: for_print, always_show_decimals: true}, dataContext);
-
- if (columnDef.df.is_tree) {
- value = frappe.query_report.tree_formatter(row, cell, value, columnDef, dataContext);
- }
-
- return value;
- };
-
- var query_report_opts = this.get_query_report_opts();
- if (query_report_opts.formatter) {
- var default_formatter = formatter;
-
- // custom formatter
- formatter = function(row, cell, value, columnDef, dataContext) {
- return query_report_opts.formatter(row, cell, value, columnDef, dataContext, default_formatter);
- }
- }
-
- return formatter;
- },
- make_data: function(result, columns) {
- var me = this;
- this.data = [];
- for(var row_idx=0, l=result.length; row_idx < l; row_idx++) {
- var row = result[row_idx];
- if ($.isPlainObject(row)) {
- var newrow = row;
- } else {
- var newrow = {};
- for(var i=1, j=this.columns.length; i number_fields.includes(col.fieldtype))
- .map(col => col.field);
-
- // reset numeric fields
- let updated_totals = Object.assign({}, this.dataView.getItemById(this.total_row_id));
- fields.map(field => {
- updated_totals[field] = 0.0;
- });
-
- const data_length = this.dataView.getLength();
- // loop all the rows except the last Total row
- for (let i = 0; i < data_length - 1; i++) {
- const item = this.dataView.getItem(i);
- fields.map(field => {
- updated_totals[field] += item[field];
- });
- }
- this.dataView.updateItem(updated_totals.id, updated_totals);
- },
- inline_filter: function (item) {
- var me = frappe.container.page.query_report;
- if(me.report_doc.add_total_row) {
- // always show totals row
- if(item.id === me.total_row_id) return true;
- }
- for (var columnId in me.columnFilters) {
- if (columnId !== undefined && me.columnFilters[columnId] !== "") {
- var c = me.grid.getColumns()[me.grid.getColumnIndex(columnId)];
- if (!me.compare_values(item[c.field], me.columnFilters[columnId],
- me.columns[me.grid.getColumnIndex(columnId)])) {
- return false;
- }
- }
- }
- return true;
- },
- setup_item_by_name: function() {
- this.item_by_name = {};
- this.name_field = this.get_query_report_opts().name_field;
- this.parent_field = this.get_query_report_opts().parent_field;
- var initial_depth = this.get_query_report_opts().initial_depth;
- for (var i=0, l=this.data.length; i=(initial_depth - 1)) {
- item._collapsed = true;
- }
- }
-
- },
- toggle_all: function(collapse) {
- var me = this;
- for(var i=0, l=this.data.length; i")
- .css("padding-left", (cint(dataContext.indent) * 21) + "px")
- .html(value);
-
- var idx = me.dataView.getIdxById(dataContext.id);
- var show_toggle = me.data[idx + 1] && (me.data[idx + 1].indent > me.data[idx].indent)
-
- if (dataContext[me.name_field] && show_toggle) {
- $('')
- .addClass(dataContext._collapsed ? "expand" : "collapse")
- .css("margin-right", "7px")
- .prependTo($span);
- }
-
- return $span.wrap("").parent().html();
- },
- compare_values: function(value, filter, columnDef) {
- var invert = false;
-
- // check if invert
- if(filter[0]=="!") {
- invert = true;
- filter = filter.substr(1);
- }
-
- var out = false;
- var cond = "=="
-
- // parse condition
- if(filter[0]==">") {
- filter = filter.substr(1);
- cond = ">"
- } else if(filter[0]=="<") {
- filter = filter.substr(1);
- cond = "<"
- }
-
- if(in_list(['Float', 'Currency', 'Int', 'Date'], columnDef.df.fieldtype)) {
- // non strings
- if(filter.indexOf(":")==-1) {
- if(columnDef.df.fieldtype=="Date") {
- filter = frappe.datetime.user_to_str(filter);
- }
-
- if(in_list(["Float", "Currency", "Int"], columnDef.df.fieldtype)) {
- value = flt(value);
- filter = flt(filter);
- }
-
- out = eval("value" + cond + "filter");
- } else {
- // range
- filter = filter.split(":");
- if(columnDef.df.fieldtype=="Date") {
- filter[0] = frappe.datetime.user_to_str(filter[0]);
- filter[1] = frappe.datetime.user_to_str(filter[1]);
- }
-
- if(in_list(["Float", "Currency", "Int"], columnDef.df.fieldtype)) {
- value = flt(value);
- filter[0] = flt(filter[0]);
- filter[1] = flt(filter[1]);
- }
-
- out = value >= filter[0] && value <= filter[1];
- }
- } else {
- // string
- value = value + "";
- value = value.toLowerCase();
- filter = filter.toLowerCase();
- out = value.indexOf(filter) != -1;
- }
-
- if(invert)
- return !out;
- else
- return out;
- },
- setup_header_row: function() {
- var me = this;
-
- $(this.grid.getHeaderRow()).delegate(":input", "change keyup", function (e) {
- var columnId = $(this).data("columnId");
- if (columnId != null) {
- me.columnFilters[columnId] = $.trim($(this).val());
- me.dataView.refresh();
- }
- });
-
- this.grid.onHeaderRowCellRendered.subscribe(function(e, args) {
- $(args.node).empty();
- $("")
- .data("columnId", args.column.id)
- .val(me.columnFilters[args.column.id])
- .appendTo(args.node);
- });
- },
- setup_sort: function() {
- var me = this;
- this.grid.onSort.subscribe(function (e, args) {
- var cols = args.sortCols;
-
- me.data.sort(function (dataRow1, dataRow2) {
- // Totals row should always be last
- if(me.report_doc.add_total_row) {
- if(dataRow1.id === me.total_row_id) {
- return 1;
- }
- if(dataRow2.id === me.total_row_id) {
- return -1;
- }
- }
-
- for (var i = 0, l = cols.length; i < l; i++) {
- var field = cols[i].sortCol.field;
- var sign = cols[i].sortAsc ? 1 : -1;
- var value1 = dataRow1[field], value2 = dataRow2[field];
- var result = (value1 == value2 ? 0 : (value1 > value2 ? 1 : -1)) * sign;
- if (result != 0) {
- return result;
- }
- }
- return 0;
- });
- me.dataView.beginUpdate();
- me.dataView.setItems(me.data);
- me.dataView.endUpdate();
- me.dataView.refresh();
- });
- },
- setup_tree: function() {
- // set these in frappe.query_reports[report_name]
- // "tree": true,
- // "name_field": "account",
- // "parent_field": "parent_account",
- // "initial_depth": 3
-
- // also set "is_tree" true for ColumnDef
-
- var me = this;
- this.grid.onClick.subscribe(function (e, args) {
- if ($(e.target).hasClass("toggle")) {
- var item = me.dataView.getItem(args.row);
- if (item) {
- if (!item._collapsed) {
- item._collapsed = true;
- } else {
- item._collapsed = false;
- }
-
- me.dataView.updateItem(item.id, item);
- }
- e.stopImmediatePropagation();
- }
- });
- },
-
- make_export: function() {
-
- var me = this;
- this.title = this.report_name;
-
- if(!frappe.model.can_export(this.report_doc.ref_doctype)) {
- frappe.msgprint(__("You are not allowed to export this report"));
- return false;
- }
-
- frappe.prompt({fieldtype:"Select", label: __("Select File Type"), fieldname:"file_format_type",
- options:"Excel\nCSV", default:"Excel", reqd: 1},
- function(data) {
- var view_data = frappe.slickgrid_tools.get_view_data(me.columns, me.dataView);
- var result = view_data.map(row => row.splice(1));
-
- // to download only visible rows
- var visible_idx = view_data.map(row => row[0]).filter(sr_no => sr_no !== 'Sr No');
-
- if (data.file_format_type == "CSV") {
- frappe.tools.downloadify(result, null, me.title);
- }
-
- else if (data.file_format_type == "Excel") {
- try {
- var filters = me.get_values(true);
- } catch(e) {
- return;
- }
- var args = {
- cmd: 'frappe.desk.query_report.export_query',
- report_name: me.report_name,
- file_format_type: data.file_format_type,
- filters: filters,
- visible_idx: visible_idx,
- }
-
- open_url_post(frappe.request.url, args);
- }
- }, __("Export Report: "+ me.title), __("Download"));
-
- return false;
- },
-
- set_message: function(msg) {
- if(msg) {
- this.wrapper.find(".help-msg").html(msg).toggle(true);
- } else {
- this.wrapper.find(".help-msg").empty().toggle(false);
- }
- },
-
- setup_chart: function(res) {
- this.chart_area.toggle(false);
-
- if (this.get_query_report_opts().get_chart_data) {
- var opts = this.get_query_report_opts().get_chart_data(res.columns, res.result);
- } else if (res.chart) {
- var opts = res.chart;
- } else {
- return;
- }
-
- $.extend(opts, {
- height: 200
- });
-
- if(opts.data && opts.data.labels && opts.data.labels.length) {
- this.chart_area.toggle(true);
- this.chart = new Chart(".chart-area", opts);
- }
- },
-
- set_print_data: function(data_to_be_printed) {
- this.data_to_be_printed = data_to_be_printed;
- }
-})
diff --git a/frappe/public/js/frappe/views/reports/report_view.js b/frappe/public/js/frappe/views/reports/report_view.js
index b1c2936389..c4a8138201 100644
--- a/frappe/public/js/frappe/views/reports/report_view.js
+++ b/frappe/public/js/frappe/views/reports/report_view.js
@@ -147,9 +147,6 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
this.datatable = new DataTable(this.$datatable_wrapper[0], {
columns: this.columns,
data: this.get_data(values),
- enableClusterize: true,
- addCheckbox: this.can_delete,
- takeAvailableSpace: true,
getEditor: this.get_editing_object.bind(this),
events: {
onRemoveColumn: (column) => {
diff --git a/frappe/public/js/lib/slickgrid/images/actions.gif b/frappe/public/js/lib/slickgrid/images/actions.gif
deleted file mode 100644
index 026dd108ed..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/actions.gif and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/ajax-loader-small.gif b/frappe/public/js/lib/slickgrid/images/ajax-loader-small.gif
deleted file mode 100644
index 5b33f7e54f..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/ajax-loader-small.gif and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/arrow_redo.png b/frappe/public/js/lib/slickgrid/images/arrow_redo.png
deleted file mode 100644
index 4f7f55d6f2..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/arrow_redo.png and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/arrow_right_peppermint.png b/frappe/public/js/lib/slickgrid/images/arrow_right_peppermint.png
deleted file mode 100644
index 8722567866..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/arrow_right_peppermint.png and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/arrow_right_spearmint.png b/frappe/public/js/lib/slickgrid/images/arrow_right_spearmint.png
deleted file mode 100644
index 277ddde384..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/arrow_right_spearmint.png and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/arrow_undo.png b/frappe/public/js/lib/slickgrid/images/arrow_undo.png
deleted file mode 100644
index bc9924ac07..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/arrow_undo.png and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/bullet_blue.png b/frappe/public/js/lib/slickgrid/images/bullet_blue.png
deleted file mode 100644
index 79d978c36a..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/bullet_blue.png and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/bullet_star.png b/frappe/public/js/lib/slickgrid/images/bullet_star.png
deleted file mode 100644
index 142ea482a5..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/bullet_star.png and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/bullet_toggle_minus.png b/frappe/public/js/lib/slickgrid/images/bullet_toggle_minus.png
deleted file mode 100644
index f5aa0450d4..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/bullet_toggle_minus.png and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/bullet_toggle_plus.png b/frappe/public/js/lib/slickgrid/images/bullet_toggle_plus.png
deleted file mode 100644
index a965053423..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/bullet_toggle_plus.png and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/calendar.gif b/frappe/public/js/lib/slickgrid/images/calendar.gif
deleted file mode 100644
index 90fd2e17fe..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/calendar.gif and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/collapse.gif b/frappe/public/js/lib/slickgrid/images/collapse.gif
deleted file mode 100644
index 01e691450c..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/collapse.gif and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/comment_yellow.gif b/frappe/public/js/lib/slickgrid/images/comment_yellow.gif
deleted file mode 100644
index df7158a477..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/comment_yellow.gif and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/down.gif b/frappe/public/js/lib/slickgrid/images/down.gif
deleted file mode 100644
index 9bd9447552..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/down.gif and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/drag-handle.png b/frappe/public/js/lib/slickgrid/images/drag-handle.png
deleted file mode 100644
index ad7531cf04..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/drag-handle.png and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/editor-helper-bg.gif b/frappe/public/js/lib/slickgrid/images/editor-helper-bg.gif
deleted file mode 100644
index 2daa973bc5..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/editor-helper-bg.gif and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/expand.gif b/frappe/public/js/lib/slickgrid/images/expand.gif
deleted file mode 100644
index 1b24ef1248..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/expand.gif and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/header-bg.gif b/frappe/public/js/lib/slickgrid/images/header-bg.gif
deleted file mode 100644
index fe7dd1c1eb..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/header-bg.gif and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/header-columns-bg.gif b/frappe/public/js/lib/slickgrid/images/header-columns-bg.gif
deleted file mode 100644
index 8d459a304e..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/header-columns-bg.gif and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/header-columns-over-bg.gif b/frappe/public/js/lib/slickgrid/images/header-columns-over-bg.gif
deleted file mode 100644
index f9c07af134..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/header-columns-over-bg.gif and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/help.png b/frappe/public/js/lib/slickgrid/images/help.png
deleted file mode 100644
index 85eca0950f..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/help.png and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/info.gif b/frappe/public/js/lib/slickgrid/images/info.gif
deleted file mode 100644
index 5769434fb2..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/info.gif and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/listview.gif b/frappe/public/js/lib/slickgrid/images/listview.gif
deleted file mode 100644
index 3ec25ca719..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/listview.gif and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/pencil.gif b/frappe/public/js/lib/slickgrid/images/pencil.gif
deleted file mode 100644
index 29f78f433d..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/pencil.gif and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/row-over-bg.gif b/frappe/public/js/lib/slickgrid/images/row-over-bg.gif
deleted file mode 100644
index b288e38739..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/row-over-bg.gif and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/sort-asc.gif b/frappe/public/js/lib/slickgrid/images/sort-asc.gif
deleted file mode 100644
index 67a2a4c669..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/sort-asc.gif and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/sort-asc.png b/frappe/public/js/lib/slickgrid/images/sort-asc.png
deleted file mode 100644
index 8604ff4e07..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/sort-asc.png and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/sort-desc.gif b/frappe/public/js/lib/slickgrid/images/sort-desc.gif
deleted file mode 100644
index 34db47c3b1..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/sort-desc.gif and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/sort-desc.png b/frappe/public/js/lib/slickgrid/images/sort-desc.png
deleted file mode 100644
index a2a6adf936..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/sort-desc.png and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/stripes.png b/frappe/public/js/lib/slickgrid/images/stripes.png
deleted file mode 100644
index c3c4b28a80..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/stripes.png and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/tag_red.png b/frappe/public/js/lib/slickgrid/images/tag_red.png
deleted file mode 100644
index d290fcd791..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/tag_red.png and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/tick.png b/frappe/public/js/lib/slickgrid/images/tick.png
deleted file mode 100644
index 3899d71dfa..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/tick.png and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/user_identity.gif b/frappe/public/js/lib/slickgrid/images/user_identity.gif
deleted file mode 100644
index 095831ba42..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/user_identity.gif and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/images/user_identity_plus.gif b/frappe/public/js/lib/slickgrid/images/user_identity_plus.gif
deleted file mode 100644
index b276a81c78..0000000000
Binary files a/frappe/public/js/lib/slickgrid/images/user_identity_plus.gif and /dev/null differ
diff --git a/frappe/public/js/lib/slickgrid/jquery.event.drag.js b/frappe/public/js/lib/slickgrid/jquery.event.drag.js
deleted file mode 100755
index f7d6245838..0000000000
--- a/frappe/public/js/lib/slickgrid/jquery.event.drag.js
+++ /dev/null
@@ -1,408 +0,0 @@
-/*!
- * jquery.event.drag - v 2.2
- * Copyright (c) 2010 Three Dub Media - http://threedubmedia.com
- * Open Source MIT License - http://threedubmedia.com/code/license
- */
-// Created: 2008-06-04
-// Updated: 2012-05-21
-// REQUIRES: jquery 1.7.x
-
-;(function( $ ){
-
-// add the jquery instance method
-$.fn.drag = function( str, arg, opts ){
- // figure out the event type
- var type = typeof str == "string" ? str : "",
- // figure out the event handler...
- fn = $.isFunction( str ) ? str : $.isFunction( arg ) ? arg : null;
- // fix the event type
- if ( type.indexOf("drag") !== 0 )
- type = "drag"+ type;
- // were options passed
- opts = ( str == fn ? arg : opts ) || {};
- // trigger or bind event handler
- return fn ? this.bind( type, opts, fn ) : this.trigger( type );
-};
-
-// local refs (increase compression)
-var $event = $.event,
-$special = $event.special,
-// configure the drag special event
-drag = $special.drag = {
-
- // these are the default settings
- defaults: {
- which: 1, // mouse button pressed to start drag sequence
- distance: 0, // distance dragged before dragstart
- not: ':input', // selector to suppress dragging on target elements
- handle: null, // selector to match handle target elements
- relative: false, // true to use "position", false to use "offset"
- drop: true, // false to suppress drop events, true or selector to allow
- click: false // false to suppress click events after dragend (no proxy)
- },
-
- // the key name for stored drag data
- datakey: "dragdata",
-
- // prevent bubbling for better performance
- noBubble: true,
-
- // count bound related events
- add: function( obj ){
- // read the interaction data
- var data = $.data( this, drag.datakey ),
- // read any passed options
- opts = obj.data || {};
- // count another realted event
- data.related += 1;
- // extend data options bound with this event
- // don't iterate "opts" in case it is a node
- $.each( drag.defaults, function( key, def ){
- if ( opts[ key ] !== undefined )
- data[ key ] = opts[ key ];
- });
- },
-
- // forget unbound related events
- remove: function(){
- $.data( this, drag.datakey ).related -= 1;
- },
-
- // configure interaction, capture settings
- setup: function(){
-
- // check for related events
- if ( $.data( this, drag.datakey ) )
- return;
- // initialize the drag data with copied defaults
- var data = $.extend({ related:0 }, drag.defaults );
- // store the interaction data
- $.data( this, drag.datakey, data );
- // bind the mousedown event, which starts drag interactions
-
- // don't attached drag event via special for fullcalendar
- // return false to attach the normal way
- if(this===document) return false;
-
- $event.add( this, "touchstart mousedown", drag.init, data );
- // prevent image dragging in IE...
- if ( this.attachEvent )
- this.attachEvent("ondragstart", drag.dontstart );
- },
-
- // destroy configured interaction
- teardown: function(){
- var data = $.data( this, drag.datakey ) || {};
- // check for related events
- if ( data.related )
- return;
- // remove the stored data
- $.removeData( this, drag.datakey );
- // remove the mousedown event
- $event.remove( this, "touchstart mousedown", drag.init );
- // enable text selection
- drag.textselect( true );
- // un-prevent image dragging in IE...
- if ( this.detachEvent )
- this.detachEvent("ondragstart", drag.dontstart );
- },
-
- // initialize the interaction
- init: function( event ){
- // sorry, only one touch at a time
- if ( drag.touched )
- return;
- // the drag/drop interaction data
- var dd = event.data, results;
- // check the which directive
- if ( event.which != 0 && dd.which > 0 && event.which != dd.which )
- return;
- // check for suppressed selector
- if ( $( event.target ).is( dd.not ) )
- return;
- // check for handle selector
- if ( dd.handle && !$( event.target ).closest( dd.handle, event.currentTarget ).length )
- return;
-
- drag.touched = event.type == 'touchstart' ? this : null;
- dd.propagates = 1;
- dd.mousedown = this;
- dd.interactions = [ drag.interaction( this, dd ) ];
- dd.target = event.target;
- dd.pageX = event.pageX;
- dd.pageY = event.pageY;
- dd.dragging = null;
- // handle draginit event...
- results = drag.hijack( event, "draginit", dd );
- // early cancel
- if ( !dd.propagates )
- return;
- // flatten the result set
- results = drag.flatten( results );
- // insert new interaction elements
- if ( results && results.length ){
- dd.interactions = [];
- $.each( results, function(){
- dd.interactions.push( drag.interaction( this, dd ) );
- });
- }
- // remember how many interactions are propagating
- dd.propagates = dd.interactions.length;
- // locate and init the drop targets
- if ( dd.drop !== false && $special.drop )
- $special.drop.handler( event, dd );
- // disable text selection
- drag.textselect( false );
- // bind additional events...
- if ( drag.touched )
- $event.add( drag.touched, "touchmove touchend", drag.handler, dd );
- else
- $event.add( document, "mousemove mouseup", drag.handler, dd );
- // helps prevent text selection or scrolling
- if ( !drag.touched || dd.live )
- return false;
- },
-
- // returns an interaction object
- interaction: function( elem, dd ){
- var offset = $( elem )[ dd.relative ? "position" : "offset" ]() || { top:0, left:0 };
- return {
- drag: elem,
- callback: new drag.callback(),
- droppable: [],
- offset: offset
- };
- },
-
- // handle drag-releatd DOM events
- handler: function( event ){
- // read the data before hijacking anything
- var dd = event.data;
- // handle various events
- switch ( event.type ){
- // mousemove, check distance, start dragging
- case !dd.dragging && 'touchmove':
- event.preventDefault();
- case !dd.dragging && 'mousemove':
- // drag tolerance, x² + y² = distance²
- if ( Math.pow( event.pageX-dd.pageX, 2 ) + Math.pow( event.pageY-dd.pageY, 2 ) < Math.pow( dd.distance, 2 ) )
- break; // distance tolerance not reached
- event.target = dd.target; // force target from "mousedown" event (fix distance issue)
- drag.hijack( event, "dragstart", dd ); // trigger "dragstart"
- if ( dd.propagates ) // "dragstart" not rejected
- dd.dragging = true; // activate interaction
- // mousemove, dragging
- case 'touchmove':
- event.preventDefault();
- case 'mousemove':
- if ( dd.dragging ){
- // trigger "drag"
- drag.hijack( event, "drag", dd );
- if ( dd.propagates ){
- // manage drop events
- if ( dd.drop !== false && $special.drop )
- $special.drop.handler( event, dd ); // "dropstart", "dropend"
- break; // "drag" not rejected, stop
- }
- event.type = "mouseup"; // helps "drop" handler behave
- }
- // mouseup, stop dragging
- case 'touchend':
- case 'mouseup':
- default:
- if ( drag.touched )
- $event.remove( drag.touched, "touchmove touchend", drag.handler ); // remove touch events
- else
- $event.remove( document, "mousemove mouseup", drag.handler ); // remove page events
- if ( dd.dragging ){
- if ( dd.drop !== false && $special.drop )
- $special.drop.handler( event, dd ); // "drop"
- drag.hijack( event, "dragend", dd ); // trigger "dragend"
- }
- drag.textselect( true ); // enable text selection
- // if suppressing click events...
- if ( dd.click === false && dd.dragging )
- $.data( dd.mousedown, "suppress.click", new Date().getTime() + 5 );
- dd.dragging = drag.touched = false; // deactivate element
- break;
- }
- },
-
- // re-use event object for custom events
- hijack: function( event, type, dd, x, elem ){
- // not configured
- if ( !dd )
- return;
- // remember the original event and type
- var orig = { event:event.originalEvent, type:event.type },
- // is the event drag related or drog related?
- mode = type.indexOf("drop") ? "drag" : "drop",
- // iteration vars
- result, i = x || 0, ia, $elems, callback,
- len = !isNaN( x ) ? x : dd.interactions.length;
- // modify the event type
- event.type = type;
- // remove the original event
- event.originalEvent = null;
- // initialize the results
- dd.results = [];
- // handle each interacted element
- do if ( ia = dd.interactions[ i ] ){
- // validate the interaction
- if ( type !== "dragend" && ia.cancelled )
- continue;
- // set the dragdrop properties on the event object
- callback = drag.properties( event, dd, ia );
- // prepare for more results
- ia.results = [];
- // handle each element
- $( elem || ia[ mode ] || dd.droppable ).each(function( p, subject ){
- // identify drag or drop targets individually
- callback.target = subject;
- // force propagtion of the custom event
- event.isPropagationStopped = function(){ return false; };
- // handle the event
- result = subject ? $event.dispatch.call( subject, event, callback ) : null;
- // stop the drag interaction for this element
- if ( result === false ){
- if ( mode == "drag" ){
- ia.cancelled = true;
- dd.propagates -= 1;
- }
- if ( type == "drop" ){
- ia[ mode ][p] = null;
- }
- }
- // assign any dropinit elements
- else if ( type == "dropinit" )
- ia.droppable.push( drag.element( result ) || subject );
- // accept a returned proxy element
- if ( type == "dragstart" )
- ia.proxy = $( drag.element( result ) || ia.drag )[0];
- // remember this result
- ia.results.push( result );
- // forget the event result, for recycling
- delete event.result;
- // break on cancelled handler
- if ( type !== "dropinit" )
- return result;
- });
- // flatten the results
- dd.results[ i ] = drag.flatten( ia.results );
- // accept a set of valid drop targets
- if ( type == "dropinit" )
- ia.droppable = drag.flatten( ia.droppable );
- // locate drop targets
- if ( type == "dragstart" && !ia.cancelled )
- callback.update();
- }
- while ( ++i < len )
- // restore the original event & type
- event.type = orig.type;
- event.originalEvent = orig.event;
- // return all handler results
- return drag.flatten( dd.results );
- },
-
- // extend the callback object with drag/drop properties...
- properties: function( event, dd, ia ){
- var obj = ia.callback;
- // elements
- obj.drag = ia.drag;
- obj.proxy = ia.proxy || ia.drag;
- // starting mouse position
- obj.startX = dd.pageX;
- obj.startY = dd.pageY;
- // current distance dragged
- obj.deltaX = event.pageX - dd.pageX;
- obj.deltaY = event.pageY - dd.pageY;
- // original element position
- obj.originalX = ia.offset.left;
- obj.originalY = ia.offset.top;
- // adjusted element position
- obj.offsetX = obj.originalX + obj.deltaX;
- obj.offsetY = obj.originalY + obj.deltaY;
- // assign the drop targets information
- obj.drop = drag.flatten( ( ia.drop || [] ).slice() );
- obj.available = drag.flatten( ( ia.droppable || [] ).slice() );
- return obj;
- },
-
- // determine is the argument is an element or jquery instance
- element: function( arg ){
- if ( arg && ( arg.jquery || arg.nodeType == 1 ) )
- return arg;
- },
-
- // flatten nested jquery objects and arrays into a single dimension array
- flatten: function( arr ){
- return $.map( arr, function( member ){
- return member && member.jquery ? $.makeArray( member ) :
- member && member.length ? drag.flatten( member ) : member;
- });
- },
-
- // toggles text selection attributes ON (true) or OFF (false)
- textselect: function( bool ){
- $( document )[ bool ? "unbind" : "bind" ]("selectstart", drag.dontstart )
- .css("MozUserSelect", bool ? "" : "none" );
- // .attr("unselectable", bool ? "off" : "on" )
- document.unselectable = bool ? "off" : "on";
- },
-
- // suppress "selectstart" and "ondragstart" events
- dontstart: function(){
- return false;
- },
-
- // a callback instance contructor
- callback: function(){}
-
-};
-
-// callback methods
-drag.callback.prototype = {
- update: function(){
- if ( $special.drop && this.available.length )
- $.each( this.available, function( i ){
- $special.drop.locate( this, i );
- });
- }
-};
-
-// patch $.event.$dispatch to allow suppressing clicks
-var $dispatch = $event.dispatch;
-$event.dispatch = function( event ){
- if ( $.data( this, "suppress."+ event.type ) - new Date().getTime() > 0 ){
- $.removeData( this, "suppress."+ event.type );
- return;
- }
- return $dispatch.apply( this, arguments );
-};
-
-// event fix hooks for touch events...
-var touchHooks =
-$event.fixHooks.touchstart =
-$event.fixHooks.touchmove =
-$event.fixHooks.touchend =
-$event.fixHooks.touchcancel = {
- props: "clientX clientY pageX pageY screenX screenY".split( " " ),
- filter: function( event, orig ) {
- if ( orig ){
- var touched = ( orig.touches && orig.touches[0] )
- || ( orig.changedTouches && orig.changedTouches[0] )
- || null;
- // iOS webkit: touchstart, touchmove, touchend
- if ( touched )
- $.each( touchHooks.props, function( i, prop ){
- event[ prop ] = touched[ prop ];
- });
- }
- return event;
- }
-};
-
-// share the same special event configuration with related events...
-$special.draginit = $special.dragstart = $special.dragend = drag;
-
-})( jQuery );
diff --git a/frappe/public/js/lib/slickgrid/plugins/slick.autotooltips.js b/frappe/public/js/lib/slickgrid/plugins/slick.autotooltips.js
deleted file mode 100644
index 955684f2aa..0000000000
--- a/frappe/public/js/lib/slickgrid/plugins/slick.autotooltips.js
+++ /dev/null
@@ -1,83 +0,0 @@
-(function ($) {
- // Register namespace
- $.extend(true, window, {
- "Slick": {
- "AutoTooltips": AutoTooltips
- }
- });
-
- /**
- * AutoTooltips plugin to show/hide tooltips when columns are too narrow to fit content.
- * @constructor
- * @param {boolean} [options.enableForCells=true] - Enable tooltip for grid cells
- * @param {boolean} [options.enableForHeaderCells=false] - Enable tooltip for header cells
- * @param {number} [options.maxToolTipLength=null] - The maximum length for a tooltip
- */
- function AutoTooltips(options) {
- var _grid;
- var _self = this;
- var _defaults = {
- enableForCells: true,
- enableForHeaderCells: false,
- maxToolTipLength: null
- };
-
- /**
- * Initialize plugin.
- */
- function init(grid) {
- options = $.extend(true, {}, _defaults, options);
- _grid = grid;
- if (options.enableForCells) _grid.onMouseEnter.subscribe(handleMouseEnter);
- if (options.enableForHeaderCells) _grid.onHeaderMouseEnter.subscribe(handleHeaderMouseEnter);
- }
-
- /**
- * Destroy plugin.
- */
- function destroy() {
- if (options.enableForCells) _grid.onMouseEnter.unsubscribe(handleMouseEnter);
- if (options.enableForHeaderCells) _grid.onHeaderMouseEnter.unsubscribe(handleHeaderMouseEnter);
- }
-
- /**
- * Handle mouse entering grid cell to add/remove tooltip.
- * @param {jQuery.Event} e - The event
- */
- function handleMouseEnter(e) {
- var cell = _grid.getCellFromEvent(e);
- if (cell) {
- var $node = $(_grid.getCellNode(cell.row, cell.cell));
- var text;
- if ($node.innerWidth() < $node[0].scrollWidth) {
- text = $.trim($node.text());
- if (options.maxToolTipLength && text.length > options.maxToolTipLength) {
- text = text.substr(0, options.maxToolTipLength - 3) + "...";
- }
- } else {
- text = "";
- }
- $node.attr("title", text);
- }
- }
-
- /**
- * Handle mouse entering header cell to add/remove tooltip.
- * @param {jQuery.Event} e - The event
- * @param {object} args.column - The column definition
- */
- function handleHeaderMouseEnter(e, args) {
- var column = args.column,
- $node = $(e.target).closest(".slick-header-column");
- if (!column.toolTip) {
- $node.attr("title", ($node.innerWidth() < $node[0].scrollWidth) ? column.name : "");
- }
- }
-
- // Public API
- $.extend(this, {
- "init": init,
- "destroy": destroy
- });
- }
-})(jQuery);
\ No newline at end of file
diff --git a/frappe/public/js/lib/slickgrid/plugins/slick.cellcopymanager.js b/frappe/public/js/lib/slickgrid/plugins/slick.cellcopymanager.js
deleted file mode 100644
index 2d8ecc8e71..0000000000
--- a/frappe/public/js/lib/slickgrid/plugins/slick.cellcopymanager.js
+++ /dev/null
@@ -1,86 +0,0 @@
-(function ($) {
- // register namespace
- $.extend(true, window, {
- "Slick": {
- "CellCopyManager": CellCopyManager
- }
- });
-
-
- function CellCopyManager() {
- var _grid;
- var _self = this;
- var _copiedRanges;
-
- function init(grid) {
- _grid = grid;
- _grid.onKeyDown.subscribe(handleKeyDown);
- }
-
- function destroy() {
- _grid.onKeyDown.unsubscribe(handleKeyDown);
- }
-
- function handleKeyDown(e, args) {
- var ranges;
- if (!_grid.getEditorLock().isActive()) {
- if (e.which == frappe.ui.keyCode.ESCAPE) {
- if (_copiedRanges) {
- e.preventDefault();
- clearCopySelection();
- _self.onCopyCancelled.notify({ranges: _copiedRanges});
- _copiedRanges = null;
- }
- }
-
- if (e.which == 67 && (e.ctrlKey || e.metaKey)) {
- ranges = _grid.getSelectionModel().getSelectedRanges();
- if (ranges.length != 0) {
- e.preventDefault();
- _copiedRanges = ranges;
- markCopySelection(ranges);
- _self.onCopyCells.notify({ranges: ranges});
- }
- }
-
- if (e.which == 86 && (e.ctrlKey || e.metaKey)) {
- if (_copiedRanges) {
- e.preventDefault();
- clearCopySelection();
- ranges = _grid.getSelectionModel().getSelectedRanges();
- _self.onPasteCells.notify({from: _copiedRanges, to: ranges});
- _copiedRanges = null;
- }
- }
- }
- }
-
- function markCopySelection(ranges) {
- var columns = _grid.getColumns();
- var hash = {};
- for (var i = 0; i < ranges.length; i++) {
- for (var j = ranges[i].fromRow; j <= ranges[i].toRow; j++) {
- hash[j] = {};
- for (var k = ranges[i].fromCell; k <= ranges[i].toCell; k++) {
- hash[j][columns[k].id] = "copied";
- }
- }
- }
- _grid.setCellCssStyles("copy-manager", hash);
- }
-
- function clearCopySelection() {
- _grid.removeCellCssStyles("copy-manager");
- }
-
- $.extend(this, {
- "init": init,
- "destroy": destroy,
- "clearCopySelection": clearCopySelection,
-
- "onCopyCells": new Slick.Event(),
- "onCopyCancelled": new Slick.Event(),
- "onPasteCells": new Slick.Event()
- });
- }
-})(jQuery);
\ No newline at end of file
diff --git a/frappe/public/js/lib/slickgrid/plugins/slick.cellexternalcopymanager.js b/frappe/public/js/lib/slickgrid/plugins/slick.cellexternalcopymanager.js
deleted file mode 100644
index bf6645eb02..0000000000
--- a/frappe/public/js/lib/slickgrid/plugins/slick.cellexternalcopymanager.js
+++ /dev/null
@@ -1,274 +0,0 @@
-(function ($) {
- // register namespace
- $.extend(true, window, {
- "Slick": {
- "CellExternalCopyManager": CellExternalCopyManager
- }
- });
-
-
- function CellExternalCopyManager(options) {
- /*
- This manager enables users to copy/paste data from/to an external Spreadsheet application
-
- Since it is not possible to access directly the clipboard in javascript, the plugin uses
- a trick to do it's job. After detecting the keystroke, we dynamically create a textarea
- where the browser copies/pastes the serialized data.
-
- options:
- copiedCellStyle : sets the css className used for copied cells. default : "copied"
- copiedCellStyleLayerKey : sets the layer key for setting css values of copied cells. default : "copy-manager"
- dataItemColumnValueExtractor : option to specify a custom column value extractor function
- dataItemColumnValueSetter : option to specify a custom column value setter function
- */
- var _grid;
- var _self = this;
- var _copiedRanges;
- var _options = options || {};
- var _copiedCellStyleLayerKey = _options.copiedCellStyleLayerKey || "copy-manager";
- var _copiedCellStyle = _options.copiedCellStyle || "copied";
- var _clearCopyTI = 0;
-
- var keyCodes = {
- 'C':67,
- 'V':86
- }
-
- function init(grid) {
- _grid = grid;
- _grid.onKeyDown.subscribe(handleKeyDown);
-
- // we need a cell selection model
- var cellSelectionModel = grid.getSelectionModel();
- if (!cellSelectionModel){
- throw new Error("Selection model is mandatory for this plugin. Please set a selection model on the grid before adding this plugin: grid.setSelectionModel(new Slick.CellSelectionModel())");
- }
- // we give focus on the grid when a selection is done on it.
- // without this, if the user selects a range of cell without giving focus on a particular cell, the grid doesn't get the focus and key stroke handles (ctrl+c) don't work
- cellSelectionModel.onSelectedRangesChanged.subscribe(function(e, args){
- _grid.focus();
- });
- }
-
- function destroy() {
- _grid.onKeyDown.unsubscribe(handleKeyDown);
- }
-
- function getDataItemValueForColumn(item, columnDef) {
- if (_options.dataItemColumnValueExtractor) {
- return _options.dataItemColumnValueExtractor(item, columnDef);
- }
- // if a custom getter is not defined, we call serializeValue of the editor to serialize
- var editorArgs = {
- 'container':$(document), // a dummy container
- 'column':columnDef
- };
- var editor = new columnDef.editor(editorArgs);
- var retVal = '';
- editor.loadValue(item);
- retVal = editor.serializeValue();
- editor.destroy();
-
- return retVal;
- }
-
- function setDataItemValueForColumn(item, columnDef, value) {
- if (_options.dataItemColumnValueSetter) {
- return _options.dataItemColumnValueSetter(item, columnDef, value);
- }
- // if a custom setter is not defined, we call applyValue of the editor to unserialize
- var editorArgs = {
- 'container':$(document), // a dummy container
- 'column':columnDef
- };
- var editor = new columnDef.editor(editorArgs);
- editor.loadValue(item);
- editor.applyValue(item, value);
- editor.destroy();
- }
-
-
- function _createTextBox(innerText){
- var ta = document.createElement('textarea');
- ta.style.position = 'absolute';
- ta.style.left = '-1000px';
- ta.style.top = '-1000px';
- ta.value = innerText;
- document.body.appendChild(ta);
- ta.focus();
-
- return ta;
- }
-
- function _decodeTabularData(_grid, ta){
- var columns = _grid.getColumns();
- var clipText = ta.value;
- var clipRows = clipText.split(/[\n\f\r]/);
- var clippedRange = [];
-
- document.body.removeChild(ta);
-
- for (var i=0; i", {css: options.selectionCss})
- .addClass(options.selectionCssClass)
- .css("position", "absolute")
- .appendTo(grid.getCanvasNode());
- }
-
- var from = grid.getCellNodeBox(range.fromRow, range.fromCell);
- var to = grid.getCellNodeBox(range.toRow, range.toCell);
-
- _elem.css({
- top: from.top - 1,
- left: from.left - 1,
- height: to.bottom - from.top - 2,
- width: to.right - from.left - 2
- });
-
- return _elem;
- }
-
- function hide() {
- if (_elem) {
- _elem.remove();
- _elem = null;
- }
- }
-
- $.extend(this, {
- "show": show,
- "hide": hide
- });
- }
-})(jQuery);
diff --git a/frappe/public/js/lib/slickgrid/plugins/slick.cellrangeselector.js b/frappe/public/js/lib/slickgrid/plugins/slick.cellrangeselector.js
deleted file mode 100644
index 520b17f3c4..0000000000
--- a/frappe/public/js/lib/slickgrid/plugins/slick.cellrangeselector.js
+++ /dev/null
@@ -1,113 +0,0 @@
-(function ($) {
- // register namespace
- $.extend(true, window, {
- "Slick": {
- "CellRangeSelector": CellRangeSelector
- }
- });
-
-
- function CellRangeSelector(options) {
- var _grid;
- var _canvas;
- var _dragging;
- var _decorator;
- var _self = this;
- var _handler = new Slick.EventHandler();
- var _defaults = {
- selectionCss: {
- "border": "2px dashed blue"
- }
- };
-
-
- function init(grid) {
- options = $.extend(true, {}, _defaults, options);
- _decorator = new Slick.CellRangeDecorator(grid, options);
- _grid = grid;
- _canvas = _grid.getCanvasNode();
- _handler
- .subscribe(_grid.onDragInit, handleDragInit)
- .subscribe(_grid.onDragStart, handleDragStart)
- .subscribe(_grid.onDrag, handleDrag)
- .subscribe(_grid.onDragEnd, handleDragEnd);
- }
-
- function destroy() {
- _handler.unsubscribeAll();
- }
-
- function handleDragInit(e, dd) {
- // prevent the grid from cancelling drag'n'drop by default
- e.stopImmediatePropagation();
- }
-
- function handleDragStart(e, dd) {
- var cell = _grid.getCellFromEvent(e);
- if (_self.onBeforeCellRangeSelected.notify(cell) !== false) {
- if (_grid.canCellBeSelected(cell.row, cell.cell)) {
- _dragging = true;
- e.stopImmediatePropagation();
- }
- }
- if (!_dragging) {
- return;
- }
-
- _grid.focus();
-
- var start = _grid.getCellFromPoint(
- dd.startX - $(_canvas).offset().left,
- dd.startY - $(_canvas).offset().top);
-
- dd.range = {start: start, end: {}};
-
- return _decorator.show(new Slick.Range(start.row, start.cell));
- }
-
- function handleDrag(e, dd) {
- if (!_dragging) {
- return;
- }
- e.stopImmediatePropagation();
-
- var end = _grid.getCellFromPoint(
- e.pageX - $(_canvas).offset().left,
- e.pageY - $(_canvas).offset().top);
-
- if (!_grid.canCellBeSelected(end.row, end.cell)) {
- return;
- }
-
- dd.range.end = end;
- _decorator.show(new Slick.Range(dd.range.start.row, dd.range.start.cell, end.row, end.cell));
- }
-
- function handleDragEnd(e, dd) {
- if (!_dragging) {
- return;
- }
-
- _dragging = false;
- e.stopImmediatePropagation();
-
- _decorator.hide();
- _self.onCellRangeSelected.notify({
- range: new Slick.Range(
- dd.range.start.row,
- dd.range.start.cell,
- dd.range.end.row,
- dd.range.end.cell
- )
- });
- }
-
- $.extend(this, {
- "init": init,
- "destroy": destroy,
-
- "onBeforeCellRangeSelected": new Slick.Event(),
- "onCellRangeSelected": new Slick.Event()
- });
- }
-})(jQuery);
\ No newline at end of file
diff --git a/frappe/public/js/lib/slickgrid/plugins/slick.cellselectionmodel.js b/frappe/public/js/lib/slickgrid/plugins/slick.cellselectionmodel.js
deleted file mode 100644
index 74bc3eb70e..0000000000
--- a/frappe/public/js/lib/slickgrid/plugins/slick.cellselectionmodel.js
+++ /dev/null
@@ -1,154 +0,0 @@
-(function ($) {
- // register namespace
- $.extend(true, window, {
- "Slick": {
- "CellSelectionModel": CellSelectionModel
- }
- });
-
-
- function CellSelectionModel(options) {
- var _grid;
- var _canvas;
- var _ranges = [];
- var _self = this;
- var _selector = new Slick.CellRangeSelector({
- "selectionCss": {
- "border": "2px solid black"
- }
- });
- var _options;
- var _defaults = {
- selectActiveCell: true
- };
-
-
- function init(grid) {
- _options = $.extend(true, {}, _defaults, options);
- _grid = grid;
- _canvas = _grid.getCanvasNode();
- _grid.onActiveCellChanged.subscribe(handleActiveCellChange);
- _grid.onKeyDown.subscribe(handleKeyDown);
- grid.registerPlugin(_selector);
- _selector.onCellRangeSelected.subscribe(handleCellRangeSelected);
- _selector.onBeforeCellRangeSelected.subscribe(handleBeforeCellRangeSelected);
- }
-
- function destroy() {
- _grid.onActiveCellChanged.unsubscribe(handleActiveCellChange);
- _grid.onKeyDown.unsubscribe(handleKeyDown);
- _selector.onCellRangeSelected.unsubscribe(handleCellRangeSelected);
- _selector.onBeforeCellRangeSelected.unsubscribe(handleBeforeCellRangeSelected);
- _grid.unregisterPlugin(_selector);
- }
-
- function removeInvalidRanges(ranges) {
- var result = [];
-
- for (var i = 0; i < ranges.length; i++) {
- var r = ranges[i];
- if (_grid.canCellBeSelected(r.fromRow, r.fromCell) && _grid.canCellBeSelected(r.toRow, r.toCell)) {
- result.push(r);
- }
- }
-
- return result;
- }
-
- function setSelectedRanges(ranges) {
- _ranges = removeInvalidRanges(ranges);
- _self.onSelectedRangesChanged.notify(_ranges);
- }
-
- function getSelectedRanges() {
- return _ranges;
- }
-
- function handleBeforeCellRangeSelected(e, args) {
- if (_grid.getEditorLock().isActive()) {
- e.stopPropagation();
- return false;
- }
- }
-
- function handleCellRangeSelected(e, args) {
- setSelectedRanges([args.range]);
- }
-
- function handleActiveCellChange(e, args) {
- if (_options.selectActiveCell && args.row != null && args.cell != null) {
- setSelectedRanges([new Slick.Range(args.row, args.cell)]);
- }
- }
-
- function handleKeyDown(e) {
- /***
- * Кey codes
- * 37 left
- * 38 up
- * 39 right
- * 40 down
- */
- var ranges, last;
- var active = _grid.getActiveCell();
-
- if ( active && e.shiftKey && !e.ctrlKey && !e.altKey &&
- (e.which == 37 || e.which == 39 || e.which == 38 || e.which == 40) ) {
-
- ranges = getSelectedRanges();
- if (!ranges.length)
- ranges.push(new Slick.Range(active.row, active.cell));
-
- // keyboard can work with last range only
- last = ranges.pop();
-
- // can't handle selection out of active cell
- if (!last.contains(active.row, active.cell))
- last = new Slick.Range(active.row, active.cell);
-
- var dRow = last.toRow - last.fromRow,
- dCell = last.toCell - last.fromCell,
- // walking direction
- dirRow = active.row == last.fromRow ? 1 : -1,
- dirCell = active.cell == last.fromCell ? 1 : -1;
-
- if (e.which == 37) {
- dCell -= dirCell;
- } else if (e.which == 39) {
- dCell += dirCell ;
- } else if (e.which == 38) {
- dRow -= dirRow;
- } else if (e.which == 40) {
- dRow += dirRow;
- }
-
- // define new selection range
- var new_last = new Slick.Range(active.row, active.cell, active.row + dirRow*dRow, active.cell + dirCell*dCell);
- if (removeInvalidRanges([new_last]).length) {
- ranges.push(new_last);
- var viewRow = dirRow > 0 ? new_last.toRow : new_last.fromRow;
- var viewCell = dirCell > 0 ? new_last.toCell : new_last.fromCell;
- _grid.scrollRowIntoView(viewRow);
- _grid.scrollCellIntoView(viewRow, viewCell);
- }
- else
- ranges.push(last);
-
- setSelectedRanges(ranges);
-
- e.preventDefault();
- e.stopPropagation();
- }
- }
-
- $.extend(this, {
- "getSelectedRanges": getSelectedRanges,
- "setSelectedRanges": setSelectedRanges,
-
- "init": init,
- "destroy": destroy,
-
- "onSelectedRangesChanged": new Slick.Event()
- });
- }
-})(jQuery);
diff --git a/frappe/public/js/lib/slickgrid/plugins/slick.checkboxselectcolumn.js b/frappe/public/js/lib/slickgrid/plugins/slick.checkboxselectcolumn.js
deleted file mode 100644
index 83d8d5008e..0000000000
--- a/frappe/public/js/lib/slickgrid/plugins/slick.checkboxselectcolumn.js
+++ /dev/null
@@ -1,153 +0,0 @@
-(function ($) {
- // register namespace
- $.extend(true, window, {
- "Slick": {
- "CheckboxSelectColumn": CheckboxSelectColumn
- }
- });
-
-
- function CheckboxSelectColumn(options) {
- var _grid;
- var _self = this;
- var _handler = new Slick.EventHandler();
- var _selectedRowsLookup = {};
- var _defaults = {
- columnId: "_checkbox_selector",
- cssClass: null,
- toolTip: "Select/Deselect All",
- width: 30
- };
-
- var _options = $.extend(true, {}, _defaults, options);
-
- function init(grid) {
- _grid = grid;
- _handler
- .subscribe(_grid.onSelectedRowsChanged, handleSelectedRowsChanged)
- .subscribe(_grid.onClick, handleClick)
- .subscribe(_grid.onHeaderClick, handleHeaderClick)
- .subscribe(_grid.onKeyDown, handleKeyDown);
- }
-
- function destroy() {
- _handler.unsubscribeAll();
- }
-
- function handleSelectedRowsChanged(e, args) {
- var selectedRows = _grid.getSelectedRows();
- var lookup = {}, row, i;
- for (i = 0; i < selectedRows.length; i++) {
- row = selectedRows[i];
- lookup[row] = true;
- if (lookup[row] !== _selectedRowsLookup[row]) {
- _grid.invalidateRow(row);
- delete _selectedRowsLookup[row];
- }
- }
- for (i in _selectedRowsLookup) {
- _grid.invalidateRow(i);
- }
- _selectedRowsLookup = lookup;
- _grid.render();
-
- if (selectedRows.length && selectedRows.length == _grid.getDataLength()) {
- _grid.updateColumnHeader(_options.columnId, "
", _options.toolTip);
- } else {
- _grid.updateColumnHeader(_options.columnId, "
", _options.toolTip);
- }
- }
-
- function handleKeyDown(e, args) {
- if (e.which == 32) {
- if (_grid.getColumns()[args.cell].id === _options.columnId) {
- // if editing, try to commit
- if (!_grid.getEditorLock().isActive() || _grid.getEditorLock().commitCurrentEdit()) {
- toggleRowSelection(args.row);
- }
- e.preventDefault();
- e.stopImmediatePropagation();
- }
- }
- }
-
- function handleClick(e, args) {
- // clicking on a row select checkbox
- if (_grid.getColumns()[args.cell].id === _options.columnId && $(e.target).is(":checkbox")) {
- // if editing, try to commit
- if (_grid.getEditorLock().isActive() && !_grid.getEditorLock().commitCurrentEdit()) {
- e.preventDefault();
- e.stopImmediatePropagation();
- return;
- }
-
- toggleRowSelection(args.row);
- e.stopPropagation();
- e.stopImmediatePropagation();
- }
- }
-
- function toggleRowSelection(row) {
- if (_selectedRowsLookup[row]) {
- _grid.setSelectedRows($.grep(_grid.getSelectedRows(), function (n) {
- return n != row
- }));
- } else {
- _grid.setSelectedRows(_grid.getSelectedRows().concat(row));
- }
- }
-
- function handleHeaderClick(e, args) {
- if (args.column.id == _options.columnId && $(e.target).is(":checkbox")) {
- // if editing, try to commit
- if (_grid.getEditorLock().isActive() && !_grid.getEditorLock().commitCurrentEdit()) {
- e.preventDefault();
- e.stopImmediatePropagation();
- return;
- }
-
- if ($(e.target).is(":checked")) {
- var rows = [];
- for (var i = 0; i < _grid.getDataLength(); i++) {
- rows.push(i);
- }
- _grid.setSelectedRows(rows);
- } else {
- _grid.setSelectedRows([]);
- }
- e.stopPropagation();
- e.stopImmediatePropagation();
- }
- }
-
- function getColumnDefinition() {
- return {
- id: _options.columnId,
- name: "
",
- toolTip: _options.toolTip,
- field: "sel",
- width: _options.width,
- resizable: false,
- sortable: false,
- cssClass: _options.cssClass,
- formatter: checkboxSelectionFormatter
- };
- }
-
- function checkboxSelectionFormatter(row, cell, value, columnDef, dataContext) {
- if (dataContext) {
- return _selectedRowsLookup[row]
- ? "
"
- : "
";
- }
- return null;
- }
-
- $.extend(this, {
- "init": init,
- "destroy": destroy,
-
- "getColumnDefinition": getColumnDefinition
- });
- }
-})(jQuery);
\ No newline at end of file
diff --git a/frappe/public/js/lib/slickgrid/plugins/slick.headerbuttons.css b/frappe/public/js/lib/slickgrid/plugins/slick.headerbuttons.css
deleted file mode 100644
index 0ba79ea0df..0000000000
--- a/frappe/public/js/lib/slickgrid/plugins/slick.headerbuttons.css
+++ /dev/null
@@ -1,39 +0,0 @@
-.slick-column-name,
-.slick-sort-indicator {
- /**
- * This makes all "float:right" elements after it that spill over to the next line
- * display way below the lower boundary of the column thus hiding them.
- */
- display: inline-block;
- float: left;
- margin-bottom: 100px;
-}
-
-.slick-header-button {
- display: inline-block;
- float: right;
- vertical-align: top;
- margin: 1px;
- /**
- * This makes all "float:right" elements after it that spill over to the next line
- * display way below the lower boundary of the column thus hiding them.
- */
- margin-bottom: 100px;
- height: 15px;
- width: 15px;
- background-repeat: no-repeat;
- background-position: center center;
- cursor: pointer;
-}
-
-.slick-header-button-hidden {
- width: 0;
-
- -webkit-transition: 0.2s width;
- -ms-transition: 0.2s width;
- transition: 0.2s width;
-}
-
-.slick-header-column:hover > .slick-header-button {
- width: 15px;
-}
\ No newline at end of file
diff --git a/frappe/public/js/lib/slickgrid/plugins/slick.headerbuttons.js b/frappe/public/js/lib/slickgrid/plugins/slick.headerbuttons.js
deleted file mode 100644
index 8e612735e6..0000000000
--- a/frappe/public/js/lib/slickgrid/plugins/slick.headerbuttons.js
+++ /dev/null
@@ -1,177 +0,0 @@
-(function ($) {
- // register namespace
- $.extend(true, window, {
- "Slick": {
- "Plugins": {
- "HeaderButtons": HeaderButtons
- }
- }
- });
-
-
- /***
- * A plugin to add custom buttons to column headers.
- *
- * USAGE:
- *
- * Add the plugin .js & .css files and register it with the grid.
- *
- * To specify a custom button in a column header, extend the column definition like so:
- *
- * var columns = [
- * {
- * id: 'myColumn',
- * name: 'My column',
- *
- * // This is the relevant part
- * header: {
- * buttons: [
- * {
- * // button options
- * },
- * {
- * // button options
- * }
- * ]
- * }
- * }
- * ];
- *
- * Available button options:
- * cssClass: CSS class to add to the button.
- * image: Relative button image path.
- * tooltip: Button tooltip.
- * showOnHover: Only show the button on hover.
- * handler: Button click handler.
- * command: A command identifier to be passed to the onCommand event handlers.
- *
- * The plugin exposes the following events:
- * onCommand: Fired on button click for buttons with 'command' specified.
- * Event args:
- * grid: Reference to the grid.
- * column: Column definition.
- * command: Button command identified.
- * button: Button options. Note that you can change the button options in your
- * event handler, and the column header will be automatically updated to
- * reflect them. This is useful if you want to implement something like a
- * toggle button.
- *
- *
- * @param options {Object} Options:
- * buttonCssClass: a CSS class to use for buttons (default 'slick-header-button')
- * @class Slick.Plugins.HeaderButtons
- * @constructor
- */
- function HeaderButtons(options) {
- var _grid;
- var _self = this;
- var _handler = new Slick.EventHandler();
- var _defaults = {
- buttonCssClass: "slick-header-button"
- };
-
-
- function init(grid) {
- options = $.extend(true, {}, _defaults, options);
- _grid = grid;
- _handler
- .subscribe(_grid.onHeaderCellRendered, handleHeaderCellRendered)
- .subscribe(_grid.onBeforeHeaderCellDestroy, handleBeforeHeaderCellDestroy);
-
- // Force the grid to re-render the header now that the events are hooked up.
- _grid.setColumns(_grid.getColumns());
- }
-
-
- function destroy() {
- _handler.unsubscribeAll();
- }
-
-
- function handleHeaderCellRendered(e, args) {
- var column = args.column;
-
- if (column.header && column.header.buttons) {
- // Append buttons in reverse order since they are floated to the right.
- var i = column.header.buttons.length;
- while (i--) {
- var button = column.header.buttons[i];
- var btn = $("
")
- .addClass(options.buttonCssClass)
- .data("column", column)
- .data("button", button);
-
- if (button.showOnHover) {
- btn.addClass("slick-header-button-hidden");
- }
-
- if (button.image) {
- btn.css("backgroundImage", "url(" + button.image + ")");
- }
-
- if (button.cssClass) {
- btn.addClass(button.cssClass);
- }
-
- if (button.tooltip) {
- btn.attr("title", button.tooltip);
- }
-
- if (button.command) {
- btn.data("command", button.command);
- }
-
- if (button.handler) {
- btn.bind("click", button.handler);
- }
-
- btn
- .bind("click", handleButtonClick)
- .appendTo(args.node);
- }
- }
- }
-
-
- function handleBeforeHeaderCellDestroy(e, args) {
- var column = args.column;
-
- if (column.header && column.header.buttons) {
- // Removing buttons via jQuery will also clean up any event handlers and data.
- // NOTE: If you attach event handlers directly or using a different framework,
- // you must also clean them up here to avoid memory leaks.
- $(args.node).find("." + options.buttonCssClass).remove();
- }
- }
-
-
- function handleButtonClick(e) {
- var command = $(this).data("command");
- var columnDef = $(this).data("column");
- var button = $(this).data("button");
-
- if (command != null) {
- _self.onCommand.notify({
- "grid": _grid,
- "column": columnDef,
- "command": command,
- "button": button
- }, e, _self);
-
- // Update the header in case the user updated the button definition in the handler.
- _grid.updateColumnHeader(columnDef.id);
- }
-
- // Stop propagation so that it doesn't register as a header click event.
- e.preventDefault();
- e.stopPropagation();
- }
-
- $.extend(this, {
- "init": init,
- "destroy": destroy,
-
- "onCommand": new Slick.Event()
- });
- }
-})(jQuery);
\ No newline at end of file
diff --git a/frappe/public/js/lib/slickgrid/plugins/slick.headermenu.css b/frappe/public/js/lib/slickgrid/plugins/slick.headermenu.css
deleted file mode 100644
index 8b0b6a9f7b..0000000000
--- a/frappe/public/js/lib/slickgrid/plugins/slick.headermenu.css
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Menu button */
-.slick-header-menubutton {
- position: absolute;
- right: 0;
- top: 0;
- bottom: 0;
- width: 14px;
- background-repeat: no-repeat;
- background-position: left center;
- background-image: url(../images/down.gif);
- cursor: pointer;
-
- display: none;
- border-left: thin ridge silver;
-}
-
-.slick-header-column:hover > .slick-header-menubutton,
-.slick-header-column-active .slick-header-menubutton {
- display: inline-block;
-}
-
-/* Menu */
-.slick-header-menu {
- position: absolute;
- display: inline-block;
- margin: 0;
- padding: 2px;
- cursor: default;
-}
-
-
-/* Menu items */
-.slick-header-menuitem {
- list-style: none;
- margin: 0;
- padding: 0;
- cursor: pointer;
-}
-
-.slick-header-menuicon {
- display: inline-block;
- width: 16px;
- height: 16px;
- vertical-align: middle;
- margin-right: 4px;
- background-repeat: no-repeat;
- background-position: center center;
-}
-
-.slick-header-menucontent {
- display: inline-block;
- vertical-align: middle;
-}
-
-
-/* Disabled */
-.slick-header-menuitem-disabled {
- color: silver;
-}
diff --git a/frappe/public/js/lib/slickgrid/plugins/slick.headermenu.js b/frappe/public/js/lib/slickgrid/plugins/slick.headermenu.js
deleted file mode 100644
index ec8244daa6..0000000000
--- a/frappe/public/js/lib/slickgrid/plugins/slick.headermenu.js
+++ /dev/null
@@ -1,275 +0,0 @@
-(function ($) {
- // register namespace
- $.extend(true, window, {
- "Slick": {
- "Plugins": {
- "HeaderMenu": HeaderMenu
- }
- }
- });
-
-
- /***
- * A plugin to add drop-down menus to column headers.
- *
- * USAGE:
- *
- * Add the plugin .js & .css files and register it with the grid.
- *
- * To specify a menu in a column header, extend the column definition like so:
- *
- * var columns = [
- * {
- * id: 'myColumn',
- * name: 'My column',
- *
- * // This is the relevant part
- * header: {
- * menu: {
- * items: [
- * {
- * // menu item options
- * },
- * {
- * // menu item options
- * }
- * ]
- * }
- * }
- * }
- * ];
- *
- *
- * Available menu options:
- * tooltip: Menu button tooltip.
- *
- *
- * Available menu item options:
- * title: Menu item text.
- * disabled: Whether the item is disabled.
- * tooltip: Item tooltip.
- * command: A command identifier to be passed to the onCommand event handlers.
- * iconCssClass: A CSS class to be added to the menu item icon.
- * iconImage: A url to the icon image.
- *
- *
- * The plugin exposes the following events:
- * onBeforeMenuShow: Fired before the menu is shown. You can customize the menu or dismiss it by returning false.
- * Event args:
- * grid: Reference to the grid.
- * column: Column definition.
- * menu: Menu options. Note that you can change the menu items here.
- *
- * onCommand: Fired on menu item click for buttons with 'command' specified.
- * Event args:
- * grid: Reference to the grid.
- * column: Column definition.
- * command: Button command identified.
- * button: Button options. Note that you can change the button options in your
- * event handler, and the column header will be automatically updated to
- * reflect them. This is useful if you want to implement something like a
- * toggle button.
- *
- *
- * @param options {Object} Options:
- * buttonCssClass: an extra CSS class to add to the menu button
- * buttonImage: a url to the menu button image (default '../images/down.gif')
- * @class Slick.Plugins.HeaderButtons
- * @constructor
- */
- function HeaderMenu(options) {
- var _grid;
- var _self = this;
- var _handler = new Slick.EventHandler();
- var _defaults = {
- buttonCssClass: null,
- buttonImage: null
- };
- var $menu;
- var $activeHeaderColumn;
-
-
- function init(grid) {
- options = $.extend(true, {}, _defaults, options);
- _grid = grid;
- _handler
- .subscribe(_grid.onHeaderCellRendered, handleHeaderCellRendered)
- .subscribe(_grid.onBeforeHeaderCellDestroy, handleBeforeHeaderCellDestroy);
-
- // Force the grid to re-render the header now that the events are hooked up.
- _grid.setColumns(_grid.getColumns());
-
- // Hide the menu on outside click.
- $(document.body).bind("mousedown", handleBodyMouseDown);
- }
-
-
- function destroy() {
- _handler.unsubscribeAll();
- $(document.body).unbind("mousedown", handleBodyMouseDown);
- }
-
-
- function handleBodyMouseDown(e) {
- if ($menu && $menu[0] != e.target && !$.contains($menu[0], e.target)) {
- hideMenu();
- }
- }
-
-
- function hideMenu() {
- if ($menu) {
- $menu.remove();
- $menu = null;
- $activeHeaderColumn
- .removeClass("slick-header-column-active");
- }
- }
-
- function handleHeaderCellRendered(e, args) {
- var column = args.column;
- var menu = column.header && column.header.menu;
-
- if (menu) {
- var $el = $("
")
- .addClass("slick-header-menubutton")
- .data("column", column)
- .data("menu", menu);
-
- if (options.buttonCssClass) {
- $el.addClass(options.buttonCssClass);
- }
-
- if (options.buttonImage) {
- $el.css("background-image", "url(" + options.buttonImage + ")");
- }
-
- if (menu.tooltip) {
- $el.attr("title", menu.tooltip);
- }
-
- $el
- .bind("click", showMenu)
- .appendTo(args.node);
- }
- }
-
-
- function handleBeforeHeaderCellDestroy(e, args) {
- var column = args.column;
-
- if (column.header && column.header.menu) {
- $(args.node).find(".slick-header-menubutton").remove();
- }
- }
-
-
- function showMenu(e) {
- var $menuButton = $(this);
- var menu = $menuButton.data("menu");
- var columnDef = $menuButton.data("column");
-
- // Let the user modify the menu or cancel altogether,
- // or provide alternative menu implementation.
- if (_self.onBeforeMenuShow.notify({
- "grid": _grid,
- "column": columnDef,
- "menu": menu
- }, e, _self) == false) {
- return;
- }
-
-
- if (!$menu) {
- $menu = $("")
- .appendTo(_grid.getContainerNode());
- }
- $menu.empty();
-
-
- // Construct the menu items.
- for (var i = 0; i < menu.items.length; i++) {
- var item = menu.items[i];
-
- var $li = $("")
- .data("command", item.command || '')
- .data("column", columnDef)
- .data("item", item)
- .bind("click", handleMenuItemClick)
- .appendTo($menu);
-
- if (item.disabled) {
- $li.addClass("slick-header-menuitem-disabled");
- }
-
- if (item.tooltip) {
- $li.attr("title", item.tooltip);
- }
-
- var $icon = $("")
- .appendTo($li);
-
- if (item.iconCssClass) {
- $icon.addClass(item.iconCssClass);
- }
-
- if (item.iconImage) {
- $icon.css("background-image", "url(" + item.iconImage + ")");
- }
-
- $("")
- .text(item.title)
- .appendTo($li);
- }
-
-
- // Position the menu.
- $menu
- .offset({ top: $(this).offset().top + $(this).height(), left: $(this).offset().left });
-
-
- // Mark the header as active to keep the highlighting.
- $activeHeaderColumn = $menuButton.closest(".slick-header-column");
- $activeHeaderColumn
- .addClass("slick-header-column-active");
-
- // Stop propagation so that it doesn't register as a header click event.
- e.preventDefault();
- e.stopPropagation();
- }
-
-
- function handleMenuItemClick(e) {
- var command = $(this).data("command");
- var columnDef = $(this).data("column");
- var item = $(this).data("item");
-
- if (item.disabled) {
- return;
- }
-
- hideMenu();
-
- if (command != null && command != '') {
- _self.onCommand.notify({
- "grid": _grid,
- "column": columnDef,
- "command": command,
- "item": item
- }, e, _self);
- }
-
- // Stop propagation so that it doesn't register as a header click event.
- e.preventDefault();
- e.stopPropagation();
- }
-
- $.extend(this, {
- "init": init,
- "destroy": destroy,
-
- "onBeforeMenuShow": new Slick.Event(),
- "onCommand": new Slick.Event()
- });
- }
-})(jQuery);
diff --git a/frappe/public/js/lib/slickgrid/plugins/slick.rowmovemanager.js b/frappe/public/js/lib/slickgrid/plugins/slick.rowmovemanager.js
deleted file mode 100644
index 5f87a1eddf..0000000000
--- a/frappe/public/js/lib/slickgrid/plugins/slick.rowmovemanager.js
+++ /dev/null
@@ -1,138 +0,0 @@
-(function ($) {
- // register namespace
- $.extend(true, window, {
- "Slick": {
- "RowMoveManager": RowMoveManager
- }
- });
-
- function RowMoveManager(options) {
- var _grid;
- var _canvas;
- var _dragging;
- var _self = this;
- var _handler = new Slick.EventHandler();
- var _defaults = {
- cancelEditOnDrag: false
- };
-
- function init(grid) {
- options = $.extend(true, {}, _defaults, options);
- _grid = grid;
- _canvas = _grid.getCanvasNode();
- _handler
- .subscribe(_grid.onDragInit, handleDragInit)
- .subscribe(_grid.onDragStart, handleDragStart)
- .subscribe(_grid.onDrag, handleDrag)
- .subscribe(_grid.onDragEnd, handleDragEnd);
- }
-
- function destroy() {
- _handler.unsubscribeAll();
- }
-
- function handleDragInit(e, dd) {
- // prevent the grid from cancelling drag'n'drop by default
- e.stopImmediatePropagation();
- }
-
- function handleDragStart(e, dd) {
- var cell = _grid.getCellFromEvent(e);
-
- if (options.cancelEditOnDrag && _grid.getEditorLock().isActive()) {
- _grid.getEditorLock().cancelCurrentEdit();
- }
-
- if (_grid.getEditorLock().isActive() || !/move|selectAndMove/.test(_grid.getColumns()[cell.cell].behavior)) {
- return false;
- }
-
- _dragging = true;
- e.stopImmediatePropagation();
-
- var selectedRows = _grid.getSelectedRows();
-
- if (selectedRows.length == 0 || $.inArray(cell.row, selectedRows) == -1) {
- selectedRows = [cell.row];
- _grid.setSelectedRows(selectedRows);
- }
-
- var rowHeight = _grid.getOptions().rowHeight;
-
- dd.selectedRows = selectedRows;
-
- dd.selectionProxy = $("
")
- .css("position", "absolute")
- .css("zIndex", "99999")
- .css("width", $(_canvas).innerWidth())
- .css("height", rowHeight * selectedRows.length)
- .appendTo(_canvas);
-
- dd.guide = $("
")
- .css("position", "absolute")
- .css("zIndex", "99998")
- .css("width", $(_canvas).innerWidth())
- .css("top", -1000)
- .appendTo(_canvas);
-
- dd.insertBefore = -1;
- }
-
- function handleDrag(e, dd) {
- if (!_dragging) {
- return;
- }
-
- e.stopImmediatePropagation();
-
- var top = e.pageY - $(_canvas).offset().top;
- dd.selectionProxy.css("top", top - 5);
-
- var insertBefore = Math.max(0, Math.min(Math.round(top / _grid.getOptions().rowHeight), _grid.getDataLength()));
- if (insertBefore !== dd.insertBefore) {
- var eventData = {
- "rows": dd.selectedRows,
- "insertBefore": insertBefore
- };
-
- if (_self.onBeforeMoveRows.notify(eventData) === false) {
- dd.guide.css("top", -1000);
- dd.canMove = false;
- } else {
- dd.guide.css("top", insertBefore * _grid.getOptions().rowHeight);
- dd.canMove = true;
- }
-
- dd.insertBefore = insertBefore;
- }
- }
-
- function handleDragEnd(e, dd) {
- if (!_dragging) {
- return;
- }
- _dragging = false;
- e.stopImmediatePropagation();
-
- dd.guide.remove();
- dd.selectionProxy.remove();
-
- if (dd.canMove) {
- var eventData = {
- "rows": dd.selectedRows,
- "insertBefore": dd.insertBefore
- };
- // TODO: _grid.remapCellCssClasses ?
- _self.onMoveRows.notify(eventData);
- }
- }
-
- $.extend(this, {
- "onBeforeMoveRows": new Slick.Event(),
- "onMoveRows": new Slick.Event(),
-
- "init": init,
- "destroy": destroy
- });
- }
-})(jQuery);
\ No newline at end of file
diff --git a/frappe/public/js/lib/slickgrid/plugins/slick.rowselectionmodel.js b/frappe/public/js/lib/slickgrid/plugins/slick.rowselectionmodel.js
deleted file mode 100644
index 0de8dd3a40..0000000000
--- a/frappe/public/js/lib/slickgrid/plugins/slick.rowselectionmodel.js
+++ /dev/null
@@ -1,187 +0,0 @@
-(function ($) {
- // register namespace
- $.extend(true, window, {
- "Slick": {
- "RowSelectionModel": RowSelectionModel
- }
- });
-
- function RowSelectionModel(options) {
- var _grid;
- var _ranges = [];
- var _self = this;
- var _handler = new Slick.EventHandler();
- var _inHandler;
- var _options;
- var _defaults = {
- selectActiveRow: true
- };
-
- function init(grid) {
- _options = $.extend(true, {}, _defaults, options);
- _grid = grid;
- _handler.subscribe(_grid.onActiveCellChanged,
- wrapHandler(handleActiveCellChange));
- _handler.subscribe(_grid.onKeyDown,
- wrapHandler(handleKeyDown));
- _handler.subscribe(_grid.onClick,
- wrapHandler(handleClick));
- }
-
- function destroy() {
- _handler.unsubscribeAll();
- }
-
- function wrapHandler(handler) {
- return function () {
- if (!_inHandler) {
- _inHandler = true;
- handler.apply(this, arguments);
- _inHandler = false;
- }
- };
- }
-
- function rangesToRows(ranges) {
- var rows = [];
- for (var i = 0; i < ranges.length; i++) {
- for (var j = ranges[i].fromRow; j <= ranges[i].toRow; j++) {
- rows.push(j);
- }
- }
- return rows;
- }
-
- function rowsToRanges(rows) {
- var ranges = [];
- var lastCell = _grid.getColumns().length - 1;
- for (var i = 0; i < rows.length; i++) {
- ranges.push(new Slick.Range(rows[i], 0, rows[i], lastCell));
- }
- return ranges;
- }
-
- function getRowsRange(from, to) {
- var i, rows = [];
- for (i = from; i <= to; i++) {
- rows.push(i);
- }
- for (i = to; i < from; i++) {
- rows.push(i);
- }
- return rows;
- }
-
- function getSelectedRows() {
- return rangesToRows(_ranges);
- }
-
- function setSelectedRows(rows) {
- setSelectedRanges(rowsToRanges(rows));
- }
-
- function setSelectedRanges(ranges) {
- _ranges = ranges;
- _self.onSelectedRangesChanged.notify(_ranges);
- }
-
- function getSelectedRanges() {
- return _ranges;
- }
-
- function handleActiveCellChange(e, data) {
- if (_options.selectActiveRow && data.row != null) {
- setSelectedRanges([new Slick.Range(data.row, 0, data.row, _grid.getColumns().length - 1)]);
- }
- }
-
- function handleKeyDown(e) {
- var activeRow = _grid.getActiveCell();
- if (activeRow && e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey && (e.which == 38 || e.which == 40)) {
- var selectedRows = getSelectedRows();
- selectedRows.sort(function (x, y) {
- return x - y
- });
-
- if (!selectedRows.length) {
- selectedRows = [activeRow.row];
- }
-
- var top = selectedRows[0];
- var bottom = selectedRows[selectedRows.length - 1];
- var active;
-
- if (e.which == 40) {
- active = activeRow.row < bottom || top == bottom ? ++bottom : ++top;
- } else {
- active = activeRow.row < bottom ? --bottom : --top;
- }
-
- if (active >= 0 && active < _grid.getDataLength()) {
- _grid.scrollRowIntoView(active);
- _ranges = rowsToRanges(getRowsRange(top, bottom));
- setSelectedRanges(_ranges);
- }
-
- e.preventDefault();
- e.stopPropagation();
- }
- }
-
- function handleClick(e) {
- var cell = _grid.getCellFromEvent(e);
- if (!cell || !_grid.canCellBeActive(cell.row, cell.cell)) {
- return false;
- }
-
- if (!_grid.getOptions().multiSelect || (
- !e.ctrlKey && !e.shiftKey && !e.metaKey)) {
- return false;
- }
-
- var selection = rangesToRows(_ranges);
- var idx = $.inArray(cell.row, selection);
-
- if (idx === -1 && (e.ctrlKey || e.metaKey)) {
- selection.push(cell.row);
- _grid.setActiveCell(cell.row, cell.cell);
- } else if (idx !== -1 && (e.ctrlKey || e.metaKey)) {
- selection = $.grep(selection, function (o, i) {
- return (o !== cell.row);
- });
- _grid.setActiveCell(cell.row, cell.cell);
- } else if (selection.length && e.shiftKey) {
- var last = selection.pop();
- var from = Math.min(cell.row, last);
- var to = Math.max(cell.row, last);
- selection = [];
- for (var i = from; i <= to; i++) {
- if (i !== last) {
- selection.push(i);
- }
- }
- selection.push(last);
- _grid.setActiveCell(cell.row, cell.cell);
- }
-
- _ranges = rowsToRanges(selection);
- setSelectedRanges(_ranges);
- e.stopImmediatePropagation();
-
- return true;
- }
-
- $.extend(this, {
- "getSelectedRows": getSelectedRows,
- "setSelectedRows": setSelectedRows,
-
- "getSelectedRanges": getSelectedRanges,
- "setSelectedRanges": setSelectedRanges,
-
- "init": init,
- "destroy": destroy,
-
- "onSelectedRangesChanged": new Slick.Event()
- });
- }
-})(jQuery);
\ No newline at end of file
diff --git a/frappe/public/js/lib/slickgrid/slick-default-theme.css b/frappe/public/js/lib/slickgrid/slick-default-theme.css
deleted file mode 100644
index 572f184406..0000000000
--- a/frappe/public/js/lib/slickgrid/slick-default-theme.css
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
-IMPORTANT:
-In order to preserve the uniform grid appearance, all cell styles need to have padding, margin and border sizes.
-No built-in (selected, editable, highlight, flashing, invalid, loading, :focus) or user-specified CSS
-classes should alter those!
-*/
-
-.slick-header-columns {
- /*background: url('images/header-columns-bg.gif') repeat-x center bottom;*/
- border-bottom: 1px solid silver;
-}
-
-.slick-header-column {
- /*background: url('images/header-columns-bg.gif') repeat-x center bottom;*/
- border-right: 1px solid silver;
-}
-
-.slick-header-column:hover, .slick-header-column-active {
- /*background: white url('images/header-columns-over-bg.gif') repeat-x center bottom;*/
-}
-
-.slick-headerrow {
- background: #fafafa;
-}
-
-.slick-headerrow-column {
- background: #fafafa;
- border-bottom: 0;
- height: 100%;
-}
-
-.slick-row.ui-state-active {
- background: #F5F7D7;
-}
-
-.slick-row {
- position: absolute;
- background: white;
- border: 0px;
- line-height: 20px;
-}
-
-.slick-row.selected {
- z-index: 10;
- background: #DFE8F6;
-}
-
-.slick-cell {
- padding-left: 4px;
- padding-right: 4px;
-}
-
-.slick-group {
- border-bottom: 2px solid silver;
-}
-
-.slick-group-toggle {
- width: 9px;
- height: 9px;
- margin-right: 5px;
-}
-
-.slick-group-toggle.expanded {
- background: url(images/collapse.gif) no-repeat center center;
-}
-
-.slick-group-toggle.collapsed {
- background: url(images/expand.gif) no-repeat center center;
-}
-
-.slick-group-totals {
- color: gray;
- background: white;
-}
-
-.slick-cell.selected {
- background-color: #fffce7 !important;
-}
-
-.slick-cell.active {
- border-color: gray;
- border-style: solid;
-}
-
-.slick-sortable-placeholder {
- background: silver !important;
-}
-
-.slick-row.odd {
- background: #fafafa;
-}
-
-.slick-row.ui-state-active {
- background: #F5F7D7;
-}
-
-.slick-row.loading {
- opacity: 0.5;
- /* filter: alpha(opacity = 50); */
-}
-
-.slick-cell.invalid {
- border-color: red;
- -moz-animation-duration: 0.2s;
- -webkit-animation-duration: 0.2s;
- -moz-animation-name: slickgrid-invalid-hilite;
- -webkit-animation-name: slickgrid-invalid-hilite;
-}
-
-@-moz-keyframes slickgrid-invalid-hilite {
- from { box-shadow: 0 0 6px red; }
- to { box-shadow: none; }
-}
-
-@-webkit-keyframes slickgrid-invalid-hilite {
- from { box-shadow: 0 0 6px red; }
- to { box-shadow: none; }
-}
diff --git a/frappe/public/js/lib/slickgrid/slick.core.js b/frappe/public/js/lib/slickgrid/slick.core.js
deleted file mode 100644
index 2f097b1db6..0000000000
--- a/frappe/public/js/lib/slickgrid/slick.core.js
+++ /dev/null
@@ -1,467 +0,0 @@
-/***
- * Contains core SlickGrid classes.
- * @module Core
- * @namespace Slick
- */
-
-(function ($) {
- // register namespace
- $.extend(true, window, {
- "Slick": {
- "Event": Event,
- "EventData": EventData,
- "EventHandler": EventHandler,
- "Range": Range,
- "NonDataRow": NonDataItem,
- "Group": Group,
- "GroupTotals": GroupTotals,
- "EditorLock": EditorLock,
-
- /***
- * A global singleton editor lock.
- * @class GlobalEditorLock
- * @static
- * @constructor
- */
- "GlobalEditorLock": new EditorLock()
- }
- });
-
- /***
- * An event object for passing data to event handlers and letting them control propagation.
- *
This is pretty much identical to how W3C and jQuery implement events.
- * @class EventData
- * @constructor
- */
- function EventData() {
- var isPropagationStopped = false;
- var isImmediatePropagationStopped = false;
-
- /***
- * Stops event from propagating up the DOM tree.
- * @method stopPropagation
- */
- this.stopPropagation = function () {
- isPropagationStopped = true;
- };
-
- /***
- * Returns whether stopPropagation was called on this event object.
- * @method isPropagationStopped
- * @return {Boolean}
- */
- this.isPropagationStopped = function () {
- return isPropagationStopped;
- };
-
- /***
- * Prevents the rest of the handlers from being executed.
- * @method stopImmediatePropagation
- */
- this.stopImmediatePropagation = function () {
- isImmediatePropagationStopped = true;
- };
-
- /***
- * Returns whether stopImmediatePropagation was called on this event object.\
- * @method isImmediatePropagationStopped
- * @return {Boolean}
- */
- this.isImmediatePropagationStopped = function () {
- return isImmediatePropagationStopped;
- }
- }
-
- /***
- * A simple publisher-subscriber implementation.
- * @class Event
- * @constructor
- */
- function Event() {
- var handlers = [];
-
- /***
- * Adds an event handler to be called when the event is fired.
- *
Event handler will receive two arguments - an EventData and the data
- * object the event was fired with.
- * @method subscribe
- * @param fn {Function} Event handler.
- */
- this.subscribe = function (fn) {
- handlers.push(fn);
- };
-
- /***
- * Removes an event handler added with subscribe(fn).
- * @method unsubscribe
- * @param fn {Function} Event handler to be removed.
- */
- this.unsubscribe = function (fn) {
- for (var i = handlers.length - 1; i >= 0; i--) {
- if (handlers[i] === fn) {
- handlers.splice(i, 1);
- }
- }
- };
-
- /***
- * Fires an event notifying all subscribers.
- * @method notify
- * @param args {Object} Additional data object to be passed to all handlers.
- * @param e {EventData}
- * Optional.
- * An EventData object to be passed to all handlers.
- * For DOM events, an existing W3C/jQuery event object can be passed in.
- * @param scope {Object}
- * Optional.
- * The scope ("this") within which the handler will be executed.
- * If not specified, the scope will be set to the Event instance.
- */
- this.notify = function (args, e, scope) {
- e = e || new EventData();
- scope = scope || this;
-
- var returnValue;
- for (var i = 0; i < handlers.length && !(e.isPropagationStopped() || e.isImmediatePropagationStopped()); i++) {
- returnValue = handlers[i].call(scope, e, args);
- }
-
- return returnValue;
- };
- }
-
- function EventHandler() {
- var handlers = [];
-
- this.subscribe = function (event, handler) {
- handlers.push({
- event: event,
- handler: handler
- });
- event.subscribe(handler);
-
- return this; // allow chaining
- };
-
- this.unsubscribe = function (event, handler) {
- var i = handlers.length;
- while (i--) {
- if (handlers[i].event === event &&
- handlers[i].handler === handler) {
- handlers.splice(i, 1);
- event.unsubscribe(handler);
- return;
- }
- }
-
- return this; // allow chaining
- };
-
- this.unsubscribeAll = function () {
- var i = handlers.length;
- while (i--) {
- handlers[i].event.unsubscribe(handlers[i].handler);
- }
- handlers = [];
-
- return this; // allow chaining
- }
- }
-
- /***
- * A structure containing a range of cells.
- * @class Range
- * @constructor
- * @param fromRow {Integer} Starting row.
- * @param fromCell {Integer} Starting cell.
- * @param toRow {Integer} Optional. Ending row. Defaults to fromRow.
- * @param toCell {Integer} Optional. Ending cell. Defaults to fromCell.
- */
- function Range(fromRow, fromCell, toRow, toCell) {
- if (toRow === undefined && toCell === undefined) {
- toRow = fromRow;
- toCell = fromCell;
- }
-
- /***
- * @property fromRow
- * @type {Integer}
- */
- this.fromRow = Math.min(fromRow, toRow);
-
- /***
- * @property fromCell
- * @type {Integer}
- */
- this.fromCell = Math.min(fromCell, toCell);
-
- /***
- * @property toRow
- * @type {Integer}
- */
- this.toRow = Math.max(fromRow, toRow);
-
- /***
- * @property toCell
- * @type {Integer}
- */
- this.toCell = Math.max(fromCell, toCell);
-
- /***
- * Returns whether a range represents a single row.
- * @method isSingleRow
- * @return {Boolean}
- */
- this.isSingleRow = function () {
- return this.fromRow == this.toRow;
- };
-
- /***
- * Returns whether a range represents a single cell.
- * @method isSingleCell
- * @return {Boolean}
- */
- this.isSingleCell = function () {
- return this.fromRow == this.toRow && this.fromCell == this.toCell;
- };
-
- /***
- * Returns whether a range contains a given cell.
- * @method contains
- * @param row {Integer}
- * @param cell {Integer}
- * @return {Boolean}
- */
- this.contains = function (row, cell) {
- return row >= this.fromRow && row <= this.toRow &&
- cell >= this.fromCell && cell <= this.toCell;
- };
-
- /***
- * Returns a readable representation of a range.
- * @method toString
- * @return {String}
- */
- this.toString = function () {
- if (this.isSingleCell()) {
- return "(" + this.fromRow + ":" + this.fromCell + ")";
- }
- else {
- return "(" + this.fromRow + ":" + this.fromCell + " - " + this.toRow + ":" + this.toCell + ")";
- }
- }
- }
-
-
- /***
- * A base class that all special / non-data rows (like Group and GroupTotals) derive from.
- * @class NonDataItem
- * @constructor
- */
- function NonDataItem() {
- this.__nonDataRow = true;
- }
-
-
- /***
- * Information about a group of rows.
- * @class Group
- * @extends Slick.NonDataItem
- * @constructor
- */
- function Group() {
- this.__group = true;
-
- /**
- * Grouping level, starting with 0.
- * @property level
- * @type {Number}
- */
- this.level = 0;
-
- /***
- * Number of rows in the group.
- * @property count
- * @type {Integer}
- */
- this.count = 0;
-
- /***
- * Grouping value.
- * @property value
- * @type {Object}
- */
- this.value = null;
-
- /***
- * Formatted display value of the group.
- * @property title
- * @type {String}
- */
- this.title = null;
-
- /***
- * Whether a group is collapsed.
- * @property collapsed
- * @type {Boolean}
- */
- this.collapsed = false;
-
- /***
- * GroupTotals, if any.
- * @property totals
- * @type {GroupTotals}
- */
- this.totals = null;
-
- /**
- * Rows that are part of the group.
- * @property rows
- * @type {Array}
- */
- this.rows = [];
-
- /**
- * Sub-groups that are part of the group.
- * @property groups
- * @type {Array}
- */
- this.groups = null;
-
- /**
- * A unique key used to identify the group. This key can be used in calls to DataView
- * collapseGroup() or expandGroup().
- * @property groupingKey
- * @type {Object}
- */
- this.groupingKey = null;
- }
-
- Group.prototype = new NonDataItem();
-
- /***
- * Compares two Group instances.
- * @method equals
- * @return {Boolean}
- * @param group {Group} Group instance to compare to.
- */
- Group.prototype.equals = function (group) {
- return this.value === group.value &&
- this.count === group.count &&
- this.collapsed === group.collapsed &&
- this.title === group.title;
- };
-
- /***
- * Information about group totals.
- * An instance of GroupTotals will be created for each totals row and passed to the aggregators
- * so that they can store arbitrary data in it. That data can later be accessed by group totals
- * formatters during the display.
- * @class GroupTotals
- * @extends Slick.NonDataItem
- * @constructor
- */
- function GroupTotals() {
- this.__groupTotals = true;
-
- /***
- * Parent Group.
- * @param group
- * @type {Group}
- */
- this.group = null;
-
- /***
- * Whether the totals have been fully initialized / calculated.
- * Will be set to false for lazy-calculated group totals.
- * @param initialized
- * @type {Boolean}
- */
- this.initialized = false;
- }
-
- GroupTotals.prototype = new NonDataItem();
-
- /***
- * A locking helper to track the active edit controller and ensure that only a single controller
- * can be active at a time. This prevents a whole class of state and validation synchronization
- * issues. An edit controller (such as SlickGrid) can query if an active edit is in progress
- * and attempt a commit or cancel before proceeding.
- * @class EditorLock
- * @constructor
- */
- function EditorLock() {
- var activeEditController = null;
-
- /***
- * Returns true if a specified edit controller is active (has the edit lock).
- * If the parameter is not specified, returns true if any edit controller is active.
- * @method isActive
- * @param editController {EditController}
- * @return {Boolean}
- */
- this.isActive = function (editController) {
- return (editController ? activeEditController === editController : activeEditController !== null);
- };
-
- /***
- * Sets the specified edit controller as the active edit controller (acquire edit lock).
- * If another edit controller is already active, and exception will be thrown.
- * @method activate
- * @param editController {EditController} edit controller acquiring the lock
- */
- this.activate = function (editController) {
- if (editController === activeEditController) { // already activated?
- return;
- }
- if (activeEditController !== null) {
- throw "SlickGrid.EditorLock.activate: an editController is still active, can't activate another editController";
- }
- if (!editController.commitCurrentEdit) {
- throw "SlickGrid.EditorLock.activate: editController must implement .commitCurrentEdit()";
- }
- if (!editController.cancelCurrentEdit) {
- throw "SlickGrid.EditorLock.activate: editController must implement .cancelCurrentEdit()";
- }
- activeEditController = editController;
- };
-
- /***
- * Unsets the specified edit controller as the active edit controller (release edit lock).
- * If the specified edit controller is not the active one, an exception will be thrown.
- * @method deactivate
- * @param editController {EditController} edit controller releasing the lock
- */
- this.deactivate = function (editController) {
- if (activeEditController !== editController) {
- throw "SlickGrid.EditorLock.deactivate: specified editController is not the currently active one";
- }
- activeEditController = null;
- };
-
- /***
- * Attempts to commit the current edit by calling "commitCurrentEdit" method on the active edit
- * controller and returns whether the commit attempt was successful (commit may fail due to validation
- * errors, etc.). Edit controller's "commitCurrentEdit" must return true if the commit has succeeded
- * and false otherwise. If no edit controller is active, returns true.
- * @method commitCurrentEdit
- * @return {Boolean}
- */
- this.commitCurrentEdit = function () {
- return (activeEditController ? activeEditController.commitCurrentEdit() : true);
- };
-
- /***
- * Attempts to cancel the current edit by calling "cancelCurrentEdit" method on the active edit
- * controller and returns whether the edit was successfully cancelled. If no edit controller is
- * active, returns true.
- * @method cancelCurrentEdit
- * @return {Boolean}
- */
- this.cancelCurrentEdit = function cancelCurrentEdit() {
- return (activeEditController ? activeEditController.cancelCurrentEdit() : true);
- };
- }
-})(jQuery);
-
-
diff --git a/frappe/public/js/lib/slickgrid/slick.dataview.js b/frappe/public/js/lib/slickgrid/slick.dataview.js
deleted file mode 100644
index 989250c401..0000000000
--- a/frappe/public/js/lib/slickgrid/slick.dataview.js
+++ /dev/null
@@ -1,1126 +0,0 @@
-(function ($) {
- $.extend(true, window, {
- Slick: {
- Data: {
- DataView: DataView,
- Aggregators: {
- Avg: AvgAggregator,
- Min: MinAggregator,
- Max: MaxAggregator,
- Sum: SumAggregator
- }
- }
- }
- });
-
-
- /***
- * A sample Model implementation.
- * Provides a filtered view of the underlying data.
- *
- * Relies on the data item having an "id" property uniquely identifying it.
- */
- function DataView(options) {
- var self = this;
-
- var defaults = {
- groupItemMetadataProvider: null,
- inlineFilters: false
- };
-
-
- // private
- var idProperty = "id"; // property holding a unique row id
- var items = []; // data by index
- var rows = []; // data by row
- var idxById = {}; // indexes by id
- var rowsById = null; // rows by id; lazy-calculated
- var filter = null; // filter function
- var updated = null; // updated item ids
- var suspend = false; // suspends the recalculation
- var sortAsc = true;
- var fastSortField;
- var sortComparer;
- var refreshHints = {};
- var prevRefreshHints = {};
- var filterArgs;
- var filteredItems = [];
- var compiledFilter;
- var compiledFilterWithCaching;
- var filterCache = [];
-
- // grouping
- var groupingInfoDefaults = {
- getter: null,
- formatter: null,
- comparer: function(a, b) { return a.value - b.value; },
- predefinedValues: [],
- aggregators: [],
- aggregateEmpty: false,
- aggregateCollapsed: false,
- aggregateChildGroups: false,
- collapsed: false,
- displayTotalsRow: true,
- lazyTotalsCalculation: false
- };
- var groupingInfos = [];
- var groups = [];
- var toggledGroupsByLevel = [];
- var groupingDelimiter = ':|:';
-
- var pagesize = 0;
- var pagenum = 0;
- var totalRows = 0;
-
- // events
- var onRowCountChanged = new Slick.Event();
- var onRowsChanged = new Slick.Event();
- var onPagingInfoChanged = new Slick.Event();
-
- options = $.extend(true, {}, defaults, options);
-
-
- function beginUpdate() {
- suspend = true;
- }
-
- function endUpdate() {
- suspend = false;
- refresh();
- }
-
- function setRefreshHints(hints) {
- refreshHints = hints;
- }
-
- function setFilterArgs(args) {
- filterArgs = args;
- }
-
- function updateIdxById(startingIndex) {
- startingIndex = startingIndex || 0;
- var id;
- for (var i = startingIndex, l = items.length; i < l; i++) {
- id = items[i][idProperty];
- if (id === undefined) {
- throw "Each data element must implement a unique 'id' property";
- }
- idxById[id] = i;
- }
- }
-
- function ensureIdUniqueness() {
- var id;
- for (var i = 0, l = items.length; i < l; i++) {
- id = items[i][idProperty];
- if (id === undefined || idxById[id] !== i) {
- throw "Each data element must implement a unique 'id' property";
- }
- }
- }
-
- function getItems() {
- return items;
- }
-
- function setItems(data, objectIdProperty) {
- if (objectIdProperty !== undefined) {
- idProperty = objectIdProperty;
- }
- items = filteredItems = data;
- idxById = {};
- updateIdxById();
- ensureIdUniqueness();
- refresh();
- }
-
- function setPagingOptions(args) {
- if (args.pageSize != undefined) {
- pagesize = args.pageSize;
- pagenum = pagesize ? Math.min(pagenum, Math.max(0, Math.ceil(totalRows / pagesize) - 1)) : 0;
- }
-
- if (args.pageNum != undefined) {
- pagenum = Math.min(args.pageNum, Math.max(0, Math.ceil(totalRows / pagesize) - 1));
- }
-
- onPagingInfoChanged.notify(getPagingInfo(), null, self);
-
- refresh();
- }
-
- function getPagingInfo() {
- var totalPages = pagesize ? Math.max(1, Math.ceil(totalRows / pagesize)) : 1;
- return {pageSize: pagesize, pageNum: pagenum, totalRows: totalRows, totalPages: totalPages};
- }
-
- function sort(comparer, ascending) {
- sortAsc = ascending;
- sortComparer = comparer;
- fastSortField = null;
- if (ascending === false) {
- items.reverse();
- }
- items.sort(comparer);
- if (ascending === false) {
- items.reverse();
- }
- idxById = {};
- updateIdxById();
- refresh();
- }
-
- /***
- * Provides a workaround for the extremely slow sorting in IE.
- * Does a [lexicographic] sort on a give column by temporarily overriding Object.prototype.toString
- * to return the value of that field and then doing a native Array.sort().
- */
- function fastSort(field, ascending) {
- sortAsc = ascending;
- fastSortField = field;
- sortComparer = null;
- var oldToString = Object.prototype.toString;
- Object.prototype.toString = (typeof field == "function") ? field : function () {
- return this[field]
- };
- // an extra reversal for descending sort keeps the sort stable
- // (assuming a stable native sort implementation, which isn't true in some cases)
- if (ascending === false) {
- items.reverse();
- }
- items.sort();
- Object.prototype.toString = oldToString;
- if (ascending === false) {
- items.reverse();
- }
- idxById = {};
- updateIdxById();
- refresh();
- }
-
- function reSort() {
- if (sortComparer) {
- sort(sortComparer, sortAsc);
- } else if (fastSortField) {
- fastSort(fastSortField, sortAsc);
- }
- }
-
- function setFilter(filterFn) {
- filter = filterFn;
- if (options.inlineFilters) {
- compiledFilter = compileFilter();
- compiledFilterWithCaching = compileFilterWithCaching();
- }
- refresh();
- }
-
- function getGrouping() {
- return groupingInfos;
- }
-
- function setGrouping(groupingInfo) {
- if (!options.groupItemMetadataProvider) {
- options.groupItemMetadataProvider = new Slick.Data.GroupItemMetadataProvider();
- }
-
- groups = [];
- toggledGroupsByLevel = [];
- groupingInfo = groupingInfo || [];
- groupingInfos = (groupingInfo instanceof Array) ? groupingInfo : [groupingInfo];
-
- for (var i = 0; i < groupingInfos.length; i++) {
- var gi = groupingInfos[i] = $.extend(true, {}, groupingInfoDefaults, groupingInfos[i]);
- gi.getterIsAFn = typeof gi.getter === "function";
-
- // pre-compile accumulator loops
- gi.compiledAccumulators = [];
- var idx = gi.aggregators.length;
- while (idx--) {
- gi.compiledAccumulators[idx] = compileAccumulatorLoop(gi.aggregators[idx]);
- }
-
- toggledGroupsByLevel[i] = {};
- }
-
- refresh();
- }
-
- /**
- * @deprecated Please use {@link setGrouping}.
- */
- function groupBy(valueGetter, valueFormatter, sortComparer) {
- if (valueGetter == null) {
- setGrouping([]);
- return;
- }
-
- setGrouping({
- getter: valueGetter,
- formatter: valueFormatter,
- comparer: sortComparer
- });
- }
-
- /**
- * @deprecated Please use {@link setGrouping}.
- */
- function setAggregators(groupAggregators, includeCollapsed) {
- if (!groupingInfos.length) {
- throw new Error("At least one grouping must be specified before calling setAggregators().");
- }
-
- groupingInfos[0].aggregators = groupAggregators;
- groupingInfos[0].aggregateCollapsed = includeCollapsed;
-
- setGrouping(groupingInfos);
- }
-
- function getItemByIdx(i) {
- return items[i];
- }
-
- function getIdxById(id) {
- return idxById[id];
- }
-
- function ensureRowsByIdCache() {
- if (!rowsById) {
- rowsById = {};
- for (var i = 0, l = rows.length; i < l; i++) {
- rowsById[rows[i][idProperty]] = i;
- }
- }
- }
-
- function getRowById(id) {
- ensureRowsByIdCache();
- return rowsById[id];
- }
-
- function getItemById(id) {
- return items[idxById[id]];
- }
-
- function mapIdsToRows(idArray) {
- var rows = [];
- ensureRowsByIdCache();
- for (var i = 0, l = idArray.length; i < l; i++) {
- var row = rowsById[idArray[i]];
- if (row != null) {
- rows[rows.length] = row;
- }
- }
- return rows;
- }
-
- function mapRowsToIds(rowArray) {
- var ids = [];
- for (var i = 0, l = rowArray.length; i < l; i++) {
- if (rowArray[i] < rows.length) {
- ids[ids.length] = rows[rowArray[i]][idProperty];
- }
- }
- return ids;
- }
-
- function updateItem(id, item) {
- if (idxById[id] === undefined || id !== item[idProperty]) {
- throw "Invalid or non-matching id";
- }
- items[idxById[id]] = item;
- if (!updated) {
- updated = {};
- }
- updated[id] = true;
- refresh();
- }
-
- function insertItem(insertBefore, item) {
- items.splice(insertBefore, 0, item);
- updateIdxById(insertBefore);
- refresh();
- }
-
- function addItem(item) {
- items.push(item);
- updateIdxById(items.length - 1);
- refresh();
- }
-
- function deleteItem(id) {
- var idx = idxById[id];
- if (idx === undefined) {
- throw "Invalid id";
- }
- delete idxById[id];
- items.splice(idx, 1);
- updateIdxById(idx);
- refresh();
- }
-
- function getLength() {
- return rows.length;
- }
-
- function getItem(i) {
- var item = rows[i];
-
- // if this is a group row, make sure totals are calculated and update the title
- if (item && item.__group && item.totals && !item.totals.initialized) {
- var gi = groupingInfos[item.level];
- if (!gi.displayTotalsRow) {
- calculateTotals(item.totals);
- item.title = gi.formatter ? gi.formatter(item) : item.value;
- }
- }
- // if this is a totals row, make sure it's calculated
- else if (item && item.__groupTotals && !item.initialized) {
- calculateTotals(item);
- }
-
- return item;
- }
-
- function getItemMetadata(i) {
- var item = rows[i];
- if (item === undefined) {
- return null;
- }
-
- // overrides for grouping rows
- if (item.__group) {
- return options.groupItemMetadataProvider.getGroupRowMetadata(item);
- }
-
- // overrides for totals rows
- if (item.__groupTotals) {
- return options.groupItemMetadataProvider.getTotalsRowMetadata(item);
- }
-
- return null;
- }
-
- function expandCollapseAllGroups(level, collapse) {
- if (level == null) {
- for (var i = 0; i < groupingInfos.length; i++) {
- toggledGroupsByLevel[i] = {};
- groupingInfos[i].collapsed = collapse;
- }
- } else {
- toggledGroupsByLevel[level] = {};
- groupingInfos[level].collapsed = collapse;
- }
- refresh();
- }
-
- /**
- * @param level {Number} Optional level to collapse. If not specified, applies to all levels.
- */
- function collapseAllGroups(level) {
- expandCollapseAllGroups(level, true);
- }
-
- /**
- * @param level {Number} Optional level to expand. If not specified, applies to all levels.
- */
- function expandAllGroups(level) {
- expandCollapseAllGroups(level, false);
- }
-
- function expandCollapseGroup(level, groupingKey, collapse) {
- toggledGroupsByLevel[level][groupingKey] = groupingInfos[level].collapsed ^ collapse;
- refresh();
- }
-
- /**
- * @param varArgs Either a Slick.Group's "groupingKey" property, or a
- * variable argument list of grouping values denoting a unique path to the row. For
- * example, calling collapseGroup('high', '10%') will collapse the '10%' subgroup of
- * the 'high' group.
- */
- function collapseGroup(varArgs) {
- var args = Array.prototype.slice.call(arguments);
- var arg0 = args[0];
- if (args.length == 1 && arg0.indexOf(groupingDelimiter) != -1) {
- expandCollapseGroup(arg0.split(groupingDelimiter).length - 1, arg0, true);
- } else {
- expandCollapseGroup(args.length - 1, args.join(groupingDelimiter), true);
- }
- }
-
- /**
- * @param varArgs Either a Slick.Group's "groupingKey" property, or a
- * variable argument list of grouping values denoting a unique path to the row. For
- * example, calling expandGroup('high', '10%') will expand the '10%' subgroup of
- * the 'high' group.
- */
- function expandGroup(varArgs) {
- var args = Array.prototype.slice.call(arguments);
- var arg0 = args[0];
- if (args.length == 1 && arg0.indexOf(groupingDelimiter) != -1) {
- expandCollapseGroup(arg0.split(groupingDelimiter).length - 1, arg0, false);
- } else {
- expandCollapseGroup(args.length - 1, args.join(groupingDelimiter), false);
- }
- }
-
- function getGroups() {
- return groups;
- }
-
- function extractGroups(rows, parentGroup) {
- var group;
- var val;
- var groups = [];
- var groupsByVal = {};
- var r;
- var level = parentGroup ? parentGroup.level + 1 : 0;
- var gi = groupingInfos[level];
-
- for (var i = 0, l = gi.predefinedValues.length; i < l; i++) {
- val = gi.predefinedValues[i];
- group = groupsByVal[val];
- if (!group) {
- group = new Slick.Group();
- group.value = val;
- group.level = level;
- group.groupingKey = (parentGroup ? parentGroup.groupingKey + groupingDelimiter : '') + val;
- groups[groups.length] = group;
- groupsByVal[val] = group;
- }
- }
-
- for (var i = 0, l = rows.length; i < l; i++) {
- r = rows[i];
- val = gi.getterIsAFn ? gi.getter(r) : r[gi.getter];
- group = groupsByVal[val];
- if (!group) {
- group = new Slick.Group();
- group.value = val;
- group.level = level;
- group.groupingKey = (parentGroup ? parentGroup.groupingKey + groupingDelimiter : '') + val;
- groups[groups.length] = group;
- groupsByVal[val] = group;
- }
-
- group.rows[group.count++] = r;
- }
-
- if (level < groupingInfos.length - 1) {
- for (var i = 0; i < groups.length; i++) {
- group = groups[i];
- group.groups = extractGroups(group.rows, group);
- }
- }
-
- groups.sort(groupingInfos[level].comparer);
-
- return groups;
- }
-
- function calculateTotals(totals) {
- var group = totals.group;
- var gi = groupingInfos[group.level];
- var isLeafLevel = (group.level == groupingInfos.length);
- var agg, idx = gi.aggregators.length;
-
- if (!isLeafLevel && gi.aggregateChildGroups) {
- // make sure all the subgroups are calculated
- var i = group.groups.length;
- while (i--) {
- if (!group.groups[i].initialized) {
- calculateTotals(group.groups[i]);
- }
- }
- }
-
- while (idx--) {
- agg = gi.aggregators[idx];
- agg.init();
- if (!isLeafLevel && gi.aggregateChildGroups) {
- gi.compiledAccumulators[idx].call(agg, group.groups);
- } else {
- gi.compiledAccumulators[idx].call(agg, group.rows);
- }
- agg.storeResult(totals);
- }
- totals.initialized = true;
- }
-
- function addGroupTotals(group) {
- var gi = groupingInfos[group.level];
- var totals = new Slick.GroupTotals();
- totals.group = group;
- group.totals = totals;
- if (!gi.lazyTotalsCalculation) {
- calculateTotals(totals);
- }
- }
-
- function addTotals(groups, level) {
- level = level || 0;
- var gi = groupingInfos[level];
- var groupCollapsed = gi.collapsed;
- var toggledGroups = toggledGroupsByLevel[level];
- var idx = groups.length, g;
- while (idx--) {
- g = groups[idx];
-
- if (g.collapsed && !gi.aggregateCollapsed) {
- continue;
- }
-
- // Do a depth-first aggregation so that parent group aggregators can access subgroup totals.
- if (g.groups) {
- addTotals(g.groups, level + 1);
- }
-
- if (gi.aggregators.length && (
- gi.aggregateEmpty || g.rows.length || (g.groups && g.groups.length))) {
- addGroupTotals(g);
- }
-
- g.collapsed = groupCollapsed ^ toggledGroups[g.groupingKey];
- g.title = gi.formatter ? gi.formatter(g) : g.value;
- }
- }
-
- function flattenGroupedRows(groups, level) {
- level = level || 0;
- var gi = groupingInfos[level];
- var groupedRows = [], rows, gl = 0, g;
- for (var i = 0, l = groups.length; i < l; i++) {
- g = groups[i];
- groupedRows[gl++] = g;
-
- if (!g.collapsed) {
- rows = g.groups ? flattenGroupedRows(g.groups, level + 1) : g.rows;
- for (var j = 0, jj = rows.length; j < jj; j++) {
- groupedRows[gl++] = rows[j];
- }
- }
-
- if (g.totals && gi.displayTotalsRow && (!g.collapsed || gi.aggregateCollapsed)) {
- groupedRows[gl++] = g.totals;
- }
- }
- return groupedRows;
- }
-
- function getFunctionInfo(fn) {
- var fnRegex = /^function[^(]*\(([^)]*)\)\s*{([\s\S]*)}$/;
- var matches = fn.toString().match(fnRegex);
- return {
- params: matches[1].split(","),
- body: matches[2]
- };
- }
-
- function compileAccumulatorLoop(aggregator) {
- var accumulatorInfo = getFunctionInfo(aggregator.accumulate);
- var fn = new Function(
- "_items",
- "for (var " + accumulatorInfo.params[0] + ", _i=0, _il=_items.length; _i<_il; _i++) {" +
- accumulatorInfo.params[0] + " = _items[_i]; " +
- accumulatorInfo.body +
- "}"
- );
- fn.displayName = "compiledAccumulatorLoop";
- return fn;
- }
-
- function compileFilter() {
- var filterInfo = getFunctionInfo(filter);
-
- var filterBody = filterInfo.body
- .replace(/return false\s*([;}]|$)/gi, "{ continue _coreloop; }$1")
- .replace(/return true\s*([;}]|$)/gi, "{ _retval[_idx++] = $item$; continue _coreloop; }$1")
- .replace(/return ([^;}]+?)\s*([;}]|$)/gi,
- "{ if ($1) { _retval[_idx++] = $item$; }; continue _coreloop; }$2");
-
- // This preserves the function template code after JS compression,
- // so that replace() commands still work as expected.
- var tpl = [
- //"function(_items, _args) { ",
- "var _retval = [], _idx = 0; ",
- "var $item$, $args$ = _args; ",
- "_coreloop: ",
- "for (var _i = 0, _il = _items.length; _i < _il; _i++) { ",
- "$item$ = _items[_i]; ",
- "$filter$; ",
- "} ",
- "return _retval; "
- //"}"
- ].join("");
- tpl = tpl.replace(/\$filter\$/gi, filterBody);
- tpl = tpl.replace(/\$item\$/gi, filterInfo.params[0]);
- tpl = tpl.replace(/\$args\$/gi, filterInfo.params[1]);
-
- var fn = new Function("_items,_args", tpl);
- fn.displayName = "compiledFilter";
- return fn;
- }
-
- function compileFilterWithCaching() {
- var filterInfo = getFunctionInfo(filter);
-
- var filterBody = filterInfo.body
- .replace(/return false\s*([;}]|$)/gi, "{ continue _coreloop; }$1")
- .replace(/return true\s*([;}]|$)/gi, "{ _cache[_i] = true;_retval[_idx++] = $item$; continue _coreloop; }$1")
- .replace(/return ([^;}]+?)\s*([;}]|$)/gi,
- "{ if ((_cache[_i] = $1)) { _retval[_idx++] = $item$; }; continue _coreloop; }$2");
-
- // This preserves the function template code after JS compression,
- // so that replace() commands still work as expected.
- var tpl = [
- //"function(_items, _args, _cache) { ",
- "var _retval = [], _idx = 0; ",
- "var $item$, $args$ = _args; ",
- "_coreloop: ",
- "for (var _i = 0, _il = _items.length; _i < _il; _i++) { ",
- "$item$ = _items[_i]; ",
- "if (_cache[_i]) { ",
- "_retval[_idx++] = $item$; ",
- "continue _coreloop; ",
- "} ",
- "$filter$; ",
- "} ",
- "return _retval; "
- //"}"
- ].join("");
- tpl = tpl.replace(/\$filter\$/gi, filterBody);
- tpl = tpl.replace(/\$item\$/gi, filterInfo.params[0]);
- tpl = tpl.replace(/\$args\$/gi, filterInfo.params[1]);
-
- var fn = new Function("_items,_args,_cache", tpl);
- fn.displayName = "compiledFilterWithCaching";
- return fn;
- }
-
- function uncompiledFilter(items, args) {
- var retval = [], idx = 0;
-
- for (var i = 0, ii = items.length; i < ii; i++) {
- if (filter(items[i], args)) {
- retval[idx++] = items[i];
- }
- }
-
- return retval;
- }
-
- function uncompiledFilterWithCaching(items, args, cache) {
- var retval = [], idx = 0, item;
-
- for (var i = 0, ii = items.length; i < ii; i++) {
- item = items[i];
- if (cache[i]) {
- retval[idx++] = item;
- } else if (filter(item, args)) {
- retval[idx++] = item;
- cache[i] = true;
- }
- }
-
- return retval;
- }
-
- function getFilteredAndPagedItems(items) {
- if (filter) {
- var batchFilter = options.inlineFilters ? compiledFilter : uncompiledFilter;
- var batchFilterWithCaching = options.inlineFilters ? compiledFilterWithCaching : uncompiledFilterWithCaching;
-
- if (refreshHints.isFilterNarrowing) {
- filteredItems = batchFilter(filteredItems, filterArgs);
- } else if (refreshHints.isFilterExpanding) {
- filteredItems = batchFilterWithCaching(items, filterArgs, filterCache);
- } else if (!refreshHints.isFilterUnchanged) {
- filteredItems = batchFilter(items, filterArgs);
- }
- } else {
- // special case: if not filtering and not paging, the resulting
- // rows collection needs to be a copy so that changes due to sort
- // can be caught
- filteredItems = pagesize ? items : items.concat();
- }
-
- // get the current page
- var paged;
- if (pagesize) {
- if (filteredItems.length < pagenum * pagesize) {
- pagenum = Math.floor(filteredItems.length / pagesize);
- }
- paged = filteredItems.slice(pagesize * pagenum, pagesize * pagenum + pagesize);
- } else {
- paged = filteredItems;
- }
-
- return {totalRows: filteredItems.length, rows: paged};
- }
-
- function getRowDiffs(rows, newRows) {
- var item, r, eitherIsNonData, diff = [];
- var from = 0, to = newRows.length;
-
- if (refreshHints && refreshHints.ignoreDiffsBefore) {
- from = Math.max(0,
- Math.min(newRows.length, refreshHints.ignoreDiffsBefore));
- }
-
- if (refreshHints && refreshHints.ignoreDiffsAfter) {
- to = Math.min(newRows.length,
- Math.max(0, refreshHints.ignoreDiffsAfter));
- }
-
- for (var i = from, rl = rows.length; i < to; i++) {
- if (i >= rl) {
- diff[diff.length] = i;
- } else {
- item = newRows[i];
- r = rows[i];
-
- if ((groupingInfos.length && (eitherIsNonData = (item.__nonDataRow) || (r.__nonDataRow)) &&
- item.__group !== r.__group ||
- item.__group && !item.equals(r))
- || (eitherIsNonData &&
- // no good way to compare totals since they are arbitrary DTOs
- // deep object comparison is pretty expensive
- // always considering them 'dirty' seems easier for the time being
- (item.__groupTotals || r.__groupTotals))
- || item[idProperty] != r[idProperty]
- || (updated && updated[item[idProperty]])
- ) {
- diff[diff.length] = i;
- }
- }
- }
- return diff;
- }
-
- function recalc(_items) {
- rowsById = null;
-
- if (refreshHints.isFilterNarrowing != prevRefreshHints.isFilterNarrowing ||
- refreshHints.isFilterExpanding != prevRefreshHints.isFilterExpanding) {
- filterCache = [];
- }
-
- var filteredItems = getFilteredAndPagedItems(_items);
- totalRows = filteredItems.totalRows;
- var newRows = filteredItems.rows;
-
- groups = [];
- if (groupingInfos.length) {
- groups = extractGroups(newRows);
- if (groups.length) {
- addTotals(groups);
- newRows = flattenGroupedRows(groups);
- }
- }
-
- var diff = getRowDiffs(rows, newRows);
-
- rows = newRows;
-
- return diff;
- }
-
- function refresh() {
- if (suspend) {
- return;
- }
-
- var countBefore = rows.length;
- var totalRowsBefore = totalRows;
-
- var diff = recalc(items, filter); // pass as direct refs to avoid closure perf hit
-
- // if the current page is no longer valid, go to last page and recalc
- // we suffer a performance penalty here, but the main loop (recalc) remains highly optimized
- if (pagesize && totalRows < pagenum * pagesize) {
- pagenum = Math.max(0, Math.ceil(totalRows / pagesize) - 1);
- diff = recalc(items, filter);
- }
-
- updated = null;
- prevRefreshHints = refreshHints;
- refreshHints = {};
-
- if (totalRowsBefore != totalRows) {
- onPagingInfoChanged.notify(getPagingInfo(), null, self);
- }
- if (countBefore != rows.length) {
- onRowCountChanged.notify({previous: countBefore, current: rows.length}, null, self);
- }
- if (diff.length > 0) {
- onRowsChanged.notify({rows: diff}, null, self);
- }
- }
-
- /***
- * Wires the grid and the DataView together to keep row selection tied to item ids.
- * This is useful since, without it, the grid only knows about rows, so if the items
- * move around, the same rows stay selected instead of the selection moving along
- * with the items.
- *
- * NOTE: This doesn't work with cell selection model.
- *
- * @param grid {Slick.Grid} The grid to sync selection with.
- * @param preserveHidden {Boolean} Whether to keep selected items that go out of the
- * view due to them getting filtered out.
- * @param preserveHiddenOnSelectionChange {Boolean} Whether to keep selected items
- * that are currently out of the view (see preserveHidden) as selected when selection
- * changes.
- * @return {Slick.Event} An event that notifies when an internal list of selected row ids
- * changes. This is useful since, in combination with the above two options, it allows
- * access to the full list selected row ids, and not just the ones visible to the grid.
- * @method syncGridSelection
- */
- function syncGridSelection(grid, preserveHidden, preserveHiddenOnSelectionChange) {
- var self = this;
- var inHandler;
- var selectedRowIds = self.mapRowsToIds(grid.getSelectedRows());
- var onSelectedRowIdsChanged = new Slick.Event();
-
- function setSelectedRowIds(rowIds) {
- if (selectedRowIds.join(",") == rowIds.join(",")) {
- return;
- }
-
- selectedRowIds = rowIds;
-
- onSelectedRowIdsChanged.notify({
- "grid": grid,
- "ids": selectedRowIds
- }, new Slick.EventData(), self);
- }
-
- function update() {
- if (selectedRowIds.length > 0) {
- inHandler = true;
- var selectedRows = self.mapIdsToRows(selectedRowIds);
- if (!preserveHidden) {
- setSelectedRowIds(self.mapRowsToIds(selectedRows));
- }
- grid.setSelectedRows(selectedRows);
- inHandler = false;
- }
- }
-
- grid.onSelectedRowsChanged.subscribe(function(e, args) {
- if (inHandler) { return; }
- var newSelectedRowIds = self.mapRowsToIds(grid.getSelectedRows());
- if (!preserveHiddenOnSelectionChange || !grid.getOptions().multiSelect) {
- setSelectedRowIds(newSelectedRowIds);
- } else {
- // keep the ones that are hidden
- var existing = $.grep(selectedRowIds, function(id) { return self.getRowById(id) === undefined; });
- // add the newly selected ones
- setSelectedRowIds(existing.concat(newSelectedRowIds));
- }
- });
-
- this.onRowsChanged.subscribe(update);
-
- this.onRowCountChanged.subscribe(update);
-
- return onSelectedRowIdsChanged;
- }
-
- function syncGridCellCssStyles(grid, key) {
- var hashById;
- var inHandler;
-
- // since this method can be called after the cell styles have been set,
- // get the existing ones right away
- storeCellCssStyles(grid.getCellCssStyles(key));
-
- function storeCellCssStyles(hash) {
- hashById = {};
- for (var row in hash) {
- var id = rows[row][idProperty];
- hashById[id] = hash[row];
- }
- }
-
- function update() {
- if (hashById) {
- inHandler = true;
- ensureRowsByIdCache();
- var newHash = {};
- for (var id in hashById) {
- var row = rowsById[id];
- if (row != undefined) {
- newHash[row] = hashById[id];
- }
- }
- grid.setCellCssStyles(key, newHash);
- inHandler = false;
- }
- }
-
- grid.onCellCssStylesChanged.subscribe(function(e, args) {
- if (inHandler) { return; }
- if (key != args.key) { return; }
- if (args.hash) {
- storeCellCssStyles(args.hash);
- }
- });
-
- this.onRowsChanged.subscribe(update);
-
- this.onRowCountChanged.subscribe(update);
- }
-
- $.extend(this, {
- // methods
- "beginUpdate": beginUpdate,
- "endUpdate": endUpdate,
- "setPagingOptions": setPagingOptions,
- "getPagingInfo": getPagingInfo,
- "getItems": getItems,
- "setItems": setItems,
- "setFilter": setFilter,
- "sort": sort,
- "fastSort": fastSort,
- "reSort": reSort,
- "setGrouping": setGrouping,
- "getGrouping": getGrouping,
- "groupBy": groupBy,
- "setAggregators": setAggregators,
- "collapseAllGroups": collapseAllGroups,
- "expandAllGroups": expandAllGroups,
- "collapseGroup": collapseGroup,
- "expandGroup": expandGroup,
- "getGroups": getGroups,
- "getIdxById": getIdxById,
- "getRowById": getRowById,
- "getItemById": getItemById,
- "getItemByIdx": getItemByIdx,
- "mapRowsToIds": mapRowsToIds,
- "mapIdsToRows": mapIdsToRows,
- "setRefreshHints": setRefreshHints,
- "setFilterArgs": setFilterArgs,
- "refresh": refresh,
- "updateItem": updateItem,
- "insertItem": insertItem,
- "addItem": addItem,
- "deleteItem": deleteItem,
- "syncGridSelection": syncGridSelection,
- "syncGridCellCssStyles": syncGridCellCssStyles,
-
- // data provider methods
- "getLength": getLength,
- "getItem": getItem,
- "getItemMetadata": getItemMetadata,
-
- // events
- "onRowCountChanged": onRowCountChanged,
- "onRowsChanged": onRowsChanged,
- "onPagingInfoChanged": onPagingInfoChanged
- });
- }
-
- function AvgAggregator(field) {
- this.field_ = field;
-
- this.init = function () {
- this.count_ = 0;
- this.nonNullCount_ = 0;
- this.sum_ = 0;
- };
-
- this.accumulate = function (item) {
- var val = item[this.field_];
- this.count_++;
- if (val != null && val !== "" && val !== NaN) {
- this.nonNullCount_++;
- this.sum_ += parseFloat(val);
- }
- };
-
- this.storeResult = function (groupTotals) {
- if (!groupTotals.avg) {
- groupTotals.avg = {};
- }
- if (this.nonNullCount_ != 0) {
- groupTotals.avg[this.field_] = this.sum_ / this.nonNullCount_;
- }
- };
- }
-
- function MinAggregator(field) {
- this.field_ = field;
-
- this.init = function () {
- this.min_ = null;
- };
-
- this.accumulate = function (item) {
- var val = item[this.field_];
- if (val != null && val !== "" && val !== NaN) {
- if (this.min_ == null || val < this.min_) {
- this.min_ = val;
- }
- }
- };
-
- this.storeResult = function (groupTotals) {
- if (!groupTotals.min) {
- groupTotals.min = {};
- }
- groupTotals.min[this.field_] = this.min_;
- }
- }
-
- function MaxAggregator(field) {
- this.field_ = field;
-
- this.init = function () {
- this.max_ = null;
- };
-
- this.accumulate = function (item) {
- var val = item[this.field_];
- if (val != null && val !== "" && val !== NaN) {
- if (this.max_ == null || val > this.max_) {
- this.max_ = val;
- }
- }
- };
-
- this.storeResult = function (groupTotals) {
- if (!groupTotals.max) {
- groupTotals.max = {};
- }
- groupTotals.max[this.field_] = this.max_;
- }
- }
-
- function SumAggregator(field) {
- this.field_ = field;
-
- this.init = function () {
- this.sum_ = null;
- };
-
- this.accumulate = function (item) {
- var val = item[this.field_];
- if (val != null && val !== "" && val !== NaN) {
- this.sum_ += parseFloat(val);
- }
- };
-
- this.storeResult = function (groupTotals) {
- if (!groupTotals.sum) {
- groupTotals.sum = {};
- }
- groupTotals.sum[this.field_] = this.sum_;
- }
- }
-
- // TODO: add more built-in aggregators
- // TODO: merge common aggregators in one to prevent needles iterating
-
-})(jQuery);
diff --git a/frappe/public/js/lib/slickgrid/slick.editors.js b/frappe/public/js/lib/slickgrid/slick.editors.js
deleted file mode 100644
index 4ef21e6e54..0000000000
--- a/frappe/public/js/lib/slickgrid/slick.editors.js
+++ /dev/null
@@ -1,512 +0,0 @@
-/***
- * Contains basic SlickGrid editors.
- * @module Editors
- * @namespace Slick
- */
-
-(function ($) {
- // register namespace
- $.extend(true, window, {
- "Slick": {
- "Editors": {
- "Text": TextEditor,
- "Integer": IntegerEditor,
- "Date": DateEditor,
- "YesNoSelect": YesNoSelectEditor,
- "Checkbox": CheckboxEditor,
- "PercentComplete": PercentCompleteEditor,
- "LongText": LongTextEditor
- }
- }
- });
-
- function TextEditor(args) {
- var $input;
- var defaultValue;
- var scope = this;
-
- this.init = function () {
- $input = $("")
- .appendTo(args.container)
- .bind("keydown.nav", function (e) {
- if (e.keyCode === frappe.ui.keyCode.LEFT || e.keyCode === frappe.ui.keyCode.RIGHT) {
- e.stopImmediatePropagation();
- }
- })
- .focus()
- .select();
- };
-
- this.destroy = function () {
- $input.remove();
- };
-
- this.focus = function () {
- $input.focus();
- };
-
- this.getValue = function () {
- return $input.val();
- };
-
- this.setValue = function (val) {
- $input.val(val);
- };
-
- this.loadValue = function (item) {
- defaultValue = item[args.column.field] || "";
- $input.val(defaultValue);
- $input[0].defaultValue = defaultValue;
- $input.select();
- };
-
- this.serializeValue = function () {
- return $input.val();
- };
-
- this.applyValue = function (item, state) {
- item[args.column.field] = state;
- };
-
- this.isValueChanged = function () {
- return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
- };
-
- this.validate = function () {
- if (args.column.validator) {
- var validationResults = args.column.validator($input.val());
- if (!validationResults.valid) {
- return validationResults;
- }
- }
-
- return {
- valid: true,
- msg: null
- };
- };
-
- this.init();
- }
-
- function IntegerEditor(args) {
- var $input;
- var defaultValue;
- var scope = this;
-
- this.init = function () {
- $input = $("");
-
- $input.bind("keydown.nav", function (e) {
- if (e.keyCode === frappe.ui.keyCode.LEFT || e.keyCode === frappe.ui.keyCode.RIGHT) {
- e.stopImmediatePropagation();
- }
- });
-
- $input.appendTo(args.container);
- $input.focus().select();
- };
-
- this.destroy = function () {
- $input.remove();
- };
-
- this.focus = function () {
- $input.focus();
- };
-
- this.loadValue = function (item) {
- defaultValue = item[args.column.field];
- $input.val(defaultValue);
- $input[0].defaultValue = defaultValue;
- $input.select();
- };
-
- this.serializeValue = function () {
- return parseInt($input.val(), 10) || 0;
- };
-
- this.applyValue = function (item, state) {
- item[args.column.field] = state;
- };
-
- this.isValueChanged = function () {
- return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
- };
-
- this.validate = function () {
- if (isNaN($input.val())) {
- return {
- valid: false,
- msg: "Please enter a valid integer"
- };
- }
-
- return {
- valid: true,
- msg: null
- };
- };
-
- this.init();
- }
-
- function DateEditor(args) {
- var $input;
- var defaultValue;
- var scope = this;
- var calendarOpen = false;
-
- this.init = function () {
- $input = $("");
- $input.appendTo(args.container);
- $input.focus().select();
- $input.datepicker({
- showOn: "button",
- buttonImageOnly: true,
- buttonImage: "../images/calendar.gif",
- beforeShow: function () {
- calendarOpen = true
- },
- onClose: function () {
- calendarOpen = false
- }
- });
- $input.width($input.width() - 18);
- };
-
- this.destroy = function () {
- $.datepicker.dpDiv.stop(true, true);
- $input.datepicker("hide");
- $input.datepicker("destroy");
- $input.remove();
- };
-
- this.show = function () {
- if (calendarOpen) {
- $.datepicker.dpDiv.stop(true, true).show();
- }
- };
-
- this.hide = function () {
- if (calendarOpen) {
- $.datepicker.dpDiv.stop(true, true).hide();
- }
- };
-
- this.position = function (position) {
- if (!calendarOpen) {
- return;
- }
- $.datepicker.dpDiv
- .css("top", position.top + 30)
- .css("left", position.left);
- };
-
- this.focus = function () {
- $input.focus();
- };
-
- this.loadValue = function (item) {
- defaultValue = item[args.column.field];
- $input.val(defaultValue);
- $input[0].defaultValue = defaultValue;
- $input.select();
- };
-
- this.serializeValue = function () {
- return $input.val();
- };
-
- this.applyValue = function (item, state) {
- item[args.column.field] = state;
- };
-
- this.isValueChanged = function () {
- return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
- };
-
- this.validate = function () {
- return {
- valid: true,
- msg: null
- };
- };
-
- this.init();
- }
-
- function YesNoSelectEditor(args) {
- var $select;
- var defaultValue;
- var scope = this;
-
- this.init = function () {
- $select = $("");
- $select.appendTo(args.container);
- $select.focus();
- };
-
- this.destroy = function () {
- $select.remove();
- };
-
- this.focus = function () {
- $select.focus();
- };
-
- this.loadValue = function (item) {
- $select.val((defaultValue = item[args.column.field]) ? "yes" : "no");
- $select.select();
- };
-
- this.serializeValue = function () {
- return ($select.val() == "yes");
- };
-
- this.applyValue = function (item, state) {
- item[args.column.field] = state;
- };
-
- this.isValueChanged = function () {
- return ($select.val() != defaultValue);
- };
-
- this.validate = function () {
- return {
- valid: true,
- msg: null
- };
- };
-
- this.init();
- }
-
- function CheckboxEditor(args) {
- var $select;
- var defaultValue;
- var scope = this;
-
- this.init = function () {
- $select = $("");
- $select.appendTo(args.container);
- $select.focus();
- };
-
- this.destroy = function () {
- $select.remove();
- };
-
- this.focus = function () {
- $select.focus();
- };
-
- this.loadValue = function (item) {
- defaultValue = !!item[args.column.field];
- if (defaultValue) {
- $select.prop('checked', true);
- } else {
- $select.prop('checked', false);
- }
- };
-
- this.serializeValue = function () {
- return $select.prop('checked');
- };
-
- this.applyValue = function (item, state) {
- item[args.column.field] = state;
- };
-
- this.isValueChanged = function () {
- return (this.serializeValue() !== defaultValue);
- };
-
- this.validate = function () {
- return {
- valid: true,
- msg: null
- };
- };
-
- this.init();
- }
-
- function PercentCompleteEditor(args) {
- var $input, $picker;
- var defaultValue;
- var scope = this;
-
- this.init = function () {
- $input = $("");
- $input.width($(args.container).innerWidth() - 25);
- $input.appendTo(args.container);
-
- $picker = $("
").appendTo(args.container);
- $picker.append("
");
-
- $picker.find(".editor-percentcomplete-buttons").append("
");
-
- $input.focus().select();
-
- $picker.find(".editor-percentcomplete-slider").slider({
- orientation: "vertical",
- range: "min",
- value: defaultValue,
- slide: function (event, ui) {
- $input.val(ui.value)
- }
- });
-
- $picker.find(".editor-percentcomplete-buttons button").bind("click", function (e) {
- $input.val($(this).attr("val"));
- $picker.find(".editor-percentcomplete-slider").slider("value", $(this).attr("val"));
- })
- };
-
- this.destroy = function () {
- $input.remove();
- $picker.remove();
- };
-
- this.focus = function () {
- $input.focus();
- };
-
- this.loadValue = function (item) {
- $input.val(defaultValue = item[args.column.field]);
- $input.select();
- };
-
- this.serializeValue = function () {
- return parseInt($input.val(), 10) || 0;
- };
-
- this.applyValue = function (item, state) {
- item[args.column.field] = state;
- };
-
- this.isValueChanged = function () {
- return (!($input.val() == "" && defaultValue == null)) && ((parseInt($input.val(), 10) || 0) != defaultValue);
- };
-
- this.validate = function () {
- if (isNaN(parseInt($input.val(), 10))) {
- return {
- valid: false,
- msg: "Please enter a valid positive number"
- };
- }
-
- return {
- valid: true,
- msg: null
- };
- };
-
- this.init();
- }
-
- /*
- * An example of a "detached" editor.
- * The UI is added onto document BODY and .position(), .show() and .hide() are implemented.
- * KeyDown events are also handled to provide handling for Tab, Shift-Tab, Esc and Ctrl-Enter.
- */
- function LongTextEditor(args) {
- var $input, $wrapper;
- var defaultValue;
- var scope = this;
-
- this.init = function () {
- var $container = $("body");
-
- $wrapper = $("
")
- .appendTo($container);
-
- $input = $("