Add backgrid extensions for use in various tools: select-all, paginator and filter
parent
3b2ef2961b
commit
b3ff96d2db
|
@ -1,24 +1,28 @@
|
|||
This is a list of the third party libraries/code used in the application, not
|
||||
including Python modules installed via Pip which are listed in requirements.txt.
|
||||
|
||||
Library Version Licence URL
|
||||
======= ======= ======= ===
|
||||
QT 4.6.2+ LGPL v2.1/3 http://www.qt.io/
|
||||
Bootstrap 3.3.4 MIT http://getbootstrap.com/
|
||||
jQuery 1.11.1 MIT http://jquery.com/
|
||||
Modernizr 2.6.2 MIT/BSD http://modernizr.com/
|
||||
AlertifyJS 1.1.0 MIT http://alertifyjs.com/
|
||||
CodeMirror 4.12 MIT http://codemirror.net/
|
||||
aciTree 4.5.0-rc.7 MIT/GPL http://acoderinsights.ro/en/aciTree-tree-view-with-jQuery
|
||||
wcDocker 8b84d55415 MIT/GPL https://github.com/WebCabin/wcDocker
|
||||
Require.js 2.1.18 BSD/MIT http://requirejs.org/
|
||||
Underscore.js 1.8.3 MIT http://underscorejs.org/
|
||||
Underscore.string 387ab72d49 MIT http://epeli.github.io/underscore.string/
|
||||
Backform.js 5859b4f9db MIT https://github.com/AmiliaApp/backform
|
||||
Backbone 1.1.2 MIT http://backbonejs.org
|
||||
font-Awesome 4.3 SIL OFL http://fortawesome.github.io/Font-Awesome/
|
||||
font-mfizz 1.2 MIT http://fizzed.com/oss/font-mfizz
|
||||
backgrid.js 0.3.5 MIT http://backgridjs.com/
|
||||
backbone.undo 0.2 MIT http://backbone.undojs.com/
|
||||
bootstrap-switch 3.3.2 MIT http://www.bootstrap-switch.org/
|
||||
select2 4.0.1 MIT https://select2.github.io/
|
||||
Library Version Licence URL
|
||||
======= ======= ======= ===
|
||||
QT 4.6.2+ LGPL v2.1/3 http://www.qt.io/
|
||||
Bootstrap 3.3.4 MIT http://getbootstrap.com/
|
||||
jQuery 1.11.1 MIT http://jquery.com/
|
||||
Modernizr 2.6.2 MIT/BSD http://modernizr.com/
|
||||
AlertifyJS 1.1.0 MIT http://alertifyjs.com/
|
||||
CodeMirror 4.12 MIT http://codemirror.net/
|
||||
aciTree 4.5.0-rc.7 MIT/GPL http://acoderinsights.ro/en/aciTree-tree-view-with-jQuery
|
||||
wcDocker 8b84d55415 MIT/GPL https://github.com/WebCabin/wcDocker
|
||||
Require.js 2.1.18 BSD/MIT http://requirejs.org/
|
||||
Underscore.js 1.8.3 MIT http://underscorejs.org/
|
||||
Underscore.string 387ab72d49 MIT http://epeli.github.io/underscore.string/
|
||||
Backform.js 5859b4f9db MIT https://github.com/AmiliaApp/backform
|
||||
Backbone 1.1.2 MIT http://backbonejs.org
|
||||
font-Awesome 4.3 SIL OFL http://fortawesome.github.io/Font-Awesome/
|
||||
font-mfizz 1.2 MIT http://fizzed.com/oss/font-mfizz
|
||||
backgrid.js 0.3.5 MIT http://backgridjs.com/
|
||||
backbone.undo 0.2 MIT http://backbone.undojs.com/
|
||||
bootstrap-switch 3.3.2 MIT http://www.bootstrap-switch.org/
|
||||
select2 4.0.1 MIT https://select2.github.io/
|
||||
backgrid-filter 01b2b21 MIT https://github.com/wyuenho/backgrid-filter
|
||||
backbone.paginator 2.0.3 MIT http://github.com/backbone-paginator/backbone.paginator
|
||||
backgrid-paginator 03632df MIT https://github.com/wyuenho/backgrid-paginator
|
||||
backgrid-select-all 1a00053 MIT https://github.com/wyuenho/backgrid-select-all
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
backgrid-filter
|
||||
http://github.com/wyuenho/backgrid
|
||||
|
||||
Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
|
||||
Licensed under the MIT @license.
|
||||
*/
|
||||
|
||||
/*
|
||||
Search Icon CSS derived from:
|
||||
|
||||
PURE CSS GUI ICONS
|
||||
by Nicolas Gallagher
|
||||
- http://nicolasgallagher.com/pure-css-gui-icons/
|
||||
|
||||
http://nicolasgallagher.com
|
||||
http://twitter.com/necolas
|
||||
|
||||
Created: 29 July 2010
|
||||
Version: 1.0.1
|
||||
|
||||
Dual licensed under MIT and GNU GPLv2 (c) Nicolas Gallagher
|
||||
*/
|
||||
|
||||
.backgrid-filter.form-search {
|
||||
position: relative;
|
||||
width: 248px;
|
||||
height: 30px;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
/*
|
||||
Search Icon
|
||||
*/
|
||||
|
||||
.backgrid-filter .search {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 6px;
|
||||
z-index: 1000;
|
||||
width: 10px;
|
||||
height: 20px;
|
||||
margin-top: -10px;
|
||||
-webkit-box-sizing: content-box;
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.backgrid-filter .search:before {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
margin-top: -6px;
|
||||
background: transparent;
|
||||
border: 3px solid gray;
|
||||
-webkit-border-radius: 12px;
|
||||
-moz-border-radius: 12px;
|
||||
border-radius: 12px;
|
||||
content: "";
|
||||
-webkit-box-sizing: content-box;
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.backgrid-filter .search:after {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 10px;
|
||||
width: 3px;
|
||||
height: 7px;
|
||||
margin-top: 2px;
|
||||
background-color: gray;
|
||||
content: "";
|
||||
-webkit-transform: rotate(-45deg);
|
||||
-moz-transform: rotate(-45deg);
|
||||
-ms-transform: rotate(-45deg);
|
||||
-o-transform: rotate(-45deg);
|
||||
transform: rotate(-45deg);
|
||||
-webkit-box-sizing: content-box;
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
/*
|
||||
Clear button
|
||||
*/
|
||||
|
||||
.backgrid-filter .clear {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 8px;
|
||||
z-index: 1000;
|
||||
width: 10px;
|
||||
height: 20px;
|
||||
margin-top: -10px;
|
||||
font-family: sans-serif;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
line-height: 20px;
|
||||
color: gray;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.backgrid-filter input[type="search"] {
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
width: 206px;
|
||||
height: 20px;
|
||||
padding: 4px 6px;
|
||||
font-weight: normal;
|
||||
color: #555;
|
||||
vertical-align: middle;
|
||||
background-color: #fff;
|
||||
border: 1px solid #ccc;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
-webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
|
||||
-moz-transition: border linear 0.2s, box-shadow linear 0.2s;
|
||||
-o-transition: border linear 0.2s, box-shadow linear 0.2s;
|
||||
transition: border linear 0.2s, box-shadow linear 0.2s;
|
||||
}
|
||||
|
||||
/*
|
||||
Normalize the search input box, with code borrowed from normalize.css.
|
||||
|
||||
https://github.com/necolas/normalize.css/
|
||||
|
||||
Copyright (c) Nicolas Gallagher and Jonathan Neal, MIT @license.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 1. Correct font family not being inherited in all browsers.
|
||||
* 2. Correct font size not being inherited in all browsers.
|
||||
* 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.
|
||||
* 4. Address Firefox 4+ setting `line-height` on `input` using `!important` in the UA stylesheet.
|
||||
*/
|
||||
|
||||
.backgrid-filter input {
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
font-size: 100%;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
/*
|
||||
* Re-set default cursor for disabled elements.
|
||||
*/
|
||||
|
||||
.backgrid-filter input[disabled] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
|
||||
* 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
|
||||
* (include `-moz` to future-proof).
|
||||
*/
|
||||
|
||||
.backgrid-filter input[type="search"] {
|
||||
outline: none;
|
||||
-webkit-box-sizing: content-box;
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the default clear button on IE
|
||||
*/
|
||||
|
||||
.backgrid-filter input[type="search"]::-ms-clear {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the default clear button on WebKit browsers
|
||||
*/
|
||||
|
||||
.backgrid-filter input[type="search"]::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove inner padding and border in Firefox 4+.
|
||||
*/
|
||||
|
||||
.backgrid-filter input::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.backgrid-filter input[type="search"] {
|
||||
padding-right: 18px;
|
||||
padding-left: 22px;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
.backgrid-filter.form-search{position:relative;width:248px;height:30px;margin:20px}.backgrid-filter .search{position:absolute;top:50%;left:6px;z-index:1000;width:10px;height:20px;margin-top:-10px;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.backgrid-filter .search:before{position:absolute;top:50%;left:0;width:6px;height:6px;margin-top:-6px;background:transparent;border:3px solid gray;-webkit-border-radius:12px;-moz-border-radius:12px;border-radius:12px;content:"";-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.backgrid-filter .search:after{position:absolute;top:50%;left:10px;width:3px;height:7px;margin-top:2px;background-color:gray;content:"";-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.backgrid-filter .clear{position:absolute;top:50%;right:8px;z-index:1000;width:10px;height:20px;margin-top:-10px;font-family:sans-serif;font-size:20px;font-weight:bold;line-height:20px;color:gray;text-decoration:none}.backgrid-filter input[type="search"]{position:absolute;display:inline-block;width:206px;height:20px;padding:4px 6px;font-weight:normal;color:#555;vertical-align:middle;background-color:#fff;border:1px solid #ccc;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s}.backgrid-filter input{margin:0;font-family:inherit;font-size:100%;line-height:normal}.backgrid-filter input[disabled]{cursor:default}.backgrid-filter input[type="search"]{outline:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:none}.backgrid-filter input[type="search"]::-ms-clear{display:none}.backgrid-filter input::-moz-focus-inner{padding:0;border:0}.backgrid-filter input[type="search"]{padding-right:18px;padding-left:22px}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
backgrid-paginator
|
||||
http://github.com/wyuenho/backgrid
|
||||
|
||||
Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
|
||||
Licensed under the MIT license.
|
||||
*/
|
||||
|
||||
.backgrid-paginator {
|
||||
text-align: center;
|
||||
border-top: none;
|
||||
-webkit-border-radius: 0 0 4px 4px;
|
||||
-moz-border-radius: 0 0 4px 4px;
|
||||
border-radius: 0 0 4px 4px;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.backgrid-paginator ul {
|
||||
display: inline-block;
|
||||
*display: inline;
|
||||
margin: 5px 0;
|
||||
*zoom: 1;
|
||||
}
|
||||
|
||||
.backgrid-paginator ul > li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.backgrid-paginator ul > li > a,
|
||||
.backgrid-paginator ul > li > span {
|
||||
float: left;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
padding: 0;
|
||||
line-height: 30px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.backgrid-paginator ul > li > a:hover,
|
||||
.backgrid-paginator ul > .active > a,
|
||||
.backgrid-paginator ul > .active > span {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.backgrid-paginator ul > .active > a,
|
||||
.backgrid-paginator ul > .active > span {
|
||||
color: #999999;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.backgrid-paginator ul > .disabled > span,
|
||||
.backgrid-paginator ul > .disabled > a,
|
||||
.backgrid-paginator ul > .disabled > a:hover {
|
||||
color: #999999;
|
||||
cursor: default;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
.backgrid-paginator{text-align:center;border-top:0;-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.backgrid-paginator ul{display:inline-block;*display:inline;margin:5px 0;*zoom:1}.backgrid-paginator ul>li{display:inline}.backgrid-paginator ul>li>a,.backgrid-paginator ul>li>span{float:left;width:30px;height:30px;padding:0;line-height:30px;text-decoration:none}.backgrid-paginator ul>li>a:hover,.backgrid-paginator ul>.active>a,.backgrid-paginator ul>.active>span{background-color:#f5f5f5}.backgrid-paginator ul>.active>a,.backgrid-paginator ul>.active>span{color:#999;cursor:default}.backgrid-paginator ul>.disabled>span,.backgrid-paginator ul>.disabled>a,.backgrid-paginator ul>.disabled>a:hover{color:#999;cursor:default}
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
backgrid-select-all
|
||||
http://github.com/wyuenho/backgrid
|
||||
|
||||
Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
|
||||
Licensed under the MIT @license.
|
||||
*/
|
||||
|
||||
.backgrid .select-row-cell,
|
||||
.backgrid .select-all-header-cell {
|
||||
text-align: center;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
.backgrid .select-row-cell,.backgrid .select-all-header-cell{text-align:center}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,512 @@
|
|||
/*
|
||||
backgrid-filter
|
||||
http://github.com/wyuenho/backgrid
|
||||
|
||||
Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
|
||||
Licensed under the MIT @license.
|
||||
*/
|
||||
(function (root, factory) {
|
||||
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define(["underscore", "backbone", "backgrid"], factory);
|
||||
} else if (typeof exports == "object") {
|
||||
// CommonJS
|
||||
(function () {
|
||||
var lunr;
|
||||
try { lunr = require("lunr"); } catch (e) {}
|
||||
module.exports = factory(require("underscore"),
|
||||
require("backbone"),
|
||||
require("backgrid"),
|
||||
lunr);
|
||||
}());
|
||||
} else {
|
||||
// Browser
|
||||
factory(root._, root.Backbone, root.Backgrid, root.lunr);
|
||||
}
|
||||
|
||||
}(this, function (_, Backbone, Backgrid, lunr) {
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
ServerSideFilter is a search form widget that submits a query to the server
|
||||
for filtering the current collection.
|
||||
|
||||
@class Backgrid.Extension.ServerSideFilter
|
||||
*/
|
||||
var ServerSideFilter = Backgrid.Extension.ServerSideFilter = Backbone.View.extend({
|
||||
|
||||
/** @property */
|
||||
tagName: "form",
|
||||
|
||||
/** @property */
|
||||
className: "backgrid-filter form-search",
|
||||
|
||||
/** @property {function(Object, ?Object=): string} template */
|
||||
template: function (data) {
|
||||
return '<span class="search"> </span><input type="search" ' + (data.placeholder ? 'placeholder="' + data.placeholder + '"' : '') + ' name="' + data.name + '" ' + (data.value ? 'value="' + data.value + '"' : '') + '/><a class="clear" data-backgrid-action="clear" href="#">×</a>';
|
||||
},
|
||||
|
||||
/** @property */
|
||||
events: {
|
||||
"keyup input[type=search]": "showClearButtonMaybe",
|
||||
"click a[data-backgrid-action=clear]": "clear",
|
||||
"submit": "search"
|
||||
},
|
||||
|
||||
/** @property {string} [name='q'] Query key */
|
||||
name: "q",
|
||||
|
||||
/** @property {string} [value] The search box value. */
|
||||
value: null,
|
||||
|
||||
/**
|
||||
@property {string} [placeholder] The HTML5 placeholder to appear beneath
|
||||
the search box.
|
||||
*/
|
||||
placeholder: null,
|
||||
|
||||
/**
|
||||
@param {Object} options
|
||||
@param {Backbone.Collection} options.collection
|
||||
@param {string} [options.name]
|
||||
@param {string} [options.value]
|
||||
@param {string} [options.placeholder]
|
||||
@param {function(Object): string} [options.template]
|
||||
*/
|
||||
initialize: function (options) {
|
||||
ServerSideFilter.__super__.initialize.apply(this, arguments);
|
||||
this.name = options.name || this.name;
|
||||
this.value = options.value || this.value;
|
||||
this.placeholder = options.placeholder || this.placeholder;
|
||||
this.template = options.template || this.template;
|
||||
|
||||
// Persist the query on pagination
|
||||
var collection = this.collection, self = this;
|
||||
if (Backbone.PageableCollection &&
|
||||
collection instanceof Backbone.PageableCollection &&
|
||||
collection.mode == "server") {
|
||||
collection.queryParams[this.name] = function () {
|
||||
return self.searchBox().val() || null;
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
Event handler. Clear the search box and reset the internal search value.
|
||||
*/
|
||||
clearSearchBox: function() {
|
||||
this.value = null;
|
||||
this.searchBox().val(null);
|
||||
this.showClearButtonMaybe();
|
||||
},
|
||||
|
||||
/**
|
||||
Event handler. Show the clear button when the search box has text, hide
|
||||
it otherwise.
|
||||
*/
|
||||
showClearButtonMaybe: function () {
|
||||
var $clearButton = this.clearButton();
|
||||
var searchTerms = this.searchBox().val();
|
||||
if (searchTerms) $clearButton.show();
|
||||
else $clearButton.hide();
|
||||
},
|
||||
|
||||
/**
|
||||
Returns the search input box.
|
||||
*/
|
||||
searchBox: function () {
|
||||
return this.$el.find("input[type=search]");
|
||||
},
|
||||
|
||||
/**
|
||||
Returns the clear button.
|
||||
*/
|
||||
clearButton: function () {
|
||||
return this.$el.find("a[data-backgrid-action=clear]");
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
Returns the current search query.
|
||||
*/
|
||||
query: function() {
|
||||
this.value = this.searchBox().val();
|
||||
return this.value;
|
||||
},
|
||||
|
||||
/**
|
||||
Upon search form submission, this event handler constructs a query
|
||||
parameter object and pass it to Collection#fetch for server-side
|
||||
filtering.
|
||||
|
||||
If the collection is a PageableCollection, searching will go back to the
|
||||
first page.
|
||||
*/
|
||||
search: function (e) {
|
||||
if (e) e.preventDefault();
|
||||
|
||||
var data = {};
|
||||
var query = this.query();
|
||||
if (query) data[this.name] = query;
|
||||
|
||||
var collection = this.collection;
|
||||
|
||||
// go back to the first page on search
|
||||
if (Backbone.PageableCollection &&
|
||||
collection instanceof Backbone.PageableCollection) {
|
||||
collection.getFirstPage({data: data, reset: true, fetch: true});
|
||||
}
|
||||
else collection.fetch({data: data, reset: true});
|
||||
},
|
||||
|
||||
/**
|
||||
Event handler for the clear button. Clears the search box and refetch the
|
||||
collection.
|
||||
|
||||
If the collection is a PageableCollection, clearing will go back to the
|
||||
first page.
|
||||
*/
|
||||
clear: function (e) {
|
||||
if (e) e.preventDefault();
|
||||
this.clearSearchBox();
|
||||
|
||||
var collection = this.collection;
|
||||
|
||||
// go back to the first page on clear
|
||||
if (Backbone.PageableCollection &&
|
||||
collection instanceof Backbone.PageableCollection) {
|
||||
collection.getFirstPage({reset: true, fetch: true});
|
||||
}
|
||||
else collection.fetch({reset: true});
|
||||
},
|
||||
|
||||
/**
|
||||
Renders a search form with a text box, optionally with a placeholder and
|
||||
a preset value if supplied during initialization.
|
||||
*/
|
||||
render: function () {
|
||||
this.$el.empty().append(this.template({
|
||||
name: this.name,
|
||||
placeholder: this.placeholder,
|
||||
value: this.value
|
||||
}));
|
||||
this.showClearButtonMaybe();
|
||||
this.delegateEvents();
|
||||
return this;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
ClientSideFilter is a search form widget that searches a collection for
|
||||
model matches against a query on the client side. The exact matching
|
||||
algorithm can be overriden by subclasses.
|
||||
|
||||
@class Backgrid.Extension.ClientSideFilter
|
||||
@extends Backgrid.Extension.ServerSideFilter
|
||||
*/
|
||||
var ClientSideFilter = Backgrid.Extension.ClientSideFilter = ServerSideFilter.extend({
|
||||
|
||||
/** @property */
|
||||
events: _.extend({}, ServerSideFilter.prototype.events, {
|
||||
"click a[data-backgrid-action=clear]": function (e) {
|
||||
e.preventDefault();
|
||||
this.clear();
|
||||
},
|
||||
"keydown input[type=search]": "search",
|
||||
"submit": function (e) {
|
||||
e.preventDefault();
|
||||
this.search();
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
@property {?Array.<string>} [fields] A list of model field names to
|
||||
search for matches. If null, all of the fields will be searched.
|
||||
*/
|
||||
fields: null,
|
||||
|
||||
/**
|
||||
@property [wait=149] The time in milliseconds to wait since the last
|
||||
change to the search box's value before searching. This value can be
|
||||
adjusted depending on how often the search box is used and how large the
|
||||
search index is.
|
||||
*/
|
||||
wait: 149,
|
||||
|
||||
/**
|
||||
Debounces the #search and #clear methods and makes a copy of the given
|
||||
collection for searching.
|
||||
|
||||
@param {Object} options
|
||||
@param {Backbone.Collection} options.collection
|
||||
@param {string} [options.placeholder]
|
||||
@param {string} [options.fields]
|
||||
@param {string} [options.wait=149]
|
||||
*/
|
||||
initialize: function (options) {
|
||||
ClientSideFilter.__super__.initialize.apply(this, arguments);
|
||||
|
||||
this.fields = options.fields || this.fields;
|
||||
this.wait = options.wait || this.wait;
|
||||
|
||||
this._debounceMethods(["search", "clear"]);
|
||||
|
||||
var collection = this.collection = this.collection.fullCollection || this.collection;
|
||||
var shadowCollection = this.shadowCollection = collection.clone();
|
||||
|
||||
this.listenTo(collection, "add", function (model, collection, options) {
|
||||
shadowCollection.add(model, options);
|
||||
});
|
||||
this.listenTo(collection, "remove", function (model, collection, options) {
|
||||
shadowCollection.remove(model, options);
|
||||
});
|
||||
this.listenTo(collection, "sort", function (col) {
|
||||
if (!this.searchBox().val()) shadowCollection.reset(col.models);
|
||||
});
|
||||
this.listenTo(collection, "reset", function (col, options) {
|
||||
options = _.extend({reindex: true}, options || {});
|
||||
if (options.reindex && options.from == null && options.to == null) {
|
||||
shadowCollection.reset(col.models);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_debounceMethods: function (methodNames) {
|
||||
if (_.isString(methodNames)) methodNames = [methodNames];
|
||||
|
||||
this.undelegateEvents();
|
||||
|
||||
for (var i = 0, l = methodNames.length; i < l; i++) {
|
||||
var methodName = methodNames[i];
|
||||
var method = this[methodName];
|
||||
this[methodName] = _.debounce(method, this.wait);
|
||||
}
|
||||
|
||||
this.delegateEvents();
|
||||
},
|
||||
|
||||
/**
|
||||
Constructs a Javascript regular expression object for #makeMatcher.
|
||||
|
||||
This default implementation takes a query string and returns a Javascript
|
||||
RegExp object that matches any of the words contained in the query string
|
||||
case-insensitively. Override this method to return a different regular
|
||||
expression matcher if this behavior is not desired.
|
||||
|
||||
@param {string} query The search query in the search box.
|
||||
@return {RegExp} A RegExp object to match against model #fields.
|
||||
*/
|
||||
makeRegExp: function (query) {
|
||||
return new RegExp(query.trim().split(/\s+/).join("|"), "i");
|
||||
},
|
||||
|
||||
/**
|
||||
This default implementation takes a query string and returns a matcher
|
||||
function that looks for matches in the model's #fields or all of its
|
||||
fields if #fields is null, for any of the words in the query
|
||||
case-insensitively using the regular expression object returned from
|
||||
#makeRegExp.
|
||||
|
||||
Most of time, you'd want to override the regular expression used for
|
||||
matching. If so, please refer to the #makeRegExp documentation,
|
||||
otherwise, you can override this method to return a custom matching
|
||||
function.
|
||||
|
||||
Subclasses overriding this method must take care to conform to the
|
||||
signature of the matcher function. The matcher function is a function
|
||||
that takes a model as paramter and returns true if the model matches a
|
||||
search, or false otherwise.
|
||||
|
||||
In addition, when the matcher function is called, its context will be
|
||||
bound to this ClientSideFilter object so it has access to the filter's
|
||||
attributes and methods.
|
||||
|
||||
@param {string} query The search query in the search box.
|
||||
@return {function(Backbone.Model):boolean} A matching function.
|
||||
*/
|
||||
makeMatcher: function (query) {
|
||||
var regexp = this.makeRegExp(query);
|
||||
return function (model) {
|
||||
var keys = this.fields || model.keys();
|
||||
for (var i = 0, l = keys.length; i < l; i++) {
|
||||
if (regexp.test(model.get(keys[i]) + "")) return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
Takes the query from the search box, constructs a matcher with it and
|
||||
loops through collection looking for matches. Reset the given collection
|
||||
when all the matches have been found.
|
||||
|
||||
If the collection is a PageableCollection, searching will go back to the
|
||||
first page.
|
||||
*/
|
||||
search: function () {
|
||||
var matcher = _.bind(this.makeMatcher(this.query()), this);
|
||||
var col = this.collection;
|
||||
if (col.pageableCollection) col.pageableCollection.getFirstPage({silent: true});
|
||||
col.reset(this.shadowCollection.filter(matcher), {reindex: false});
|
||||
},
|
||||
|
||||
/**
|
||||
Clears the search box and reset the collection to its original.
|
||||
|
||||
If the collection is a PageableCollection, clearing will go back to the
|
||||
first page.
|
||||
*/
|
||||
clear: function () {
|
||||
this.clearSearchBox();
|
||||
var col = this.collection;
|
||||
if (col.pageableCollection) col.pageableCollection.getFirstPage({silent: true});
|
||||
col.reset(this.shadowCollection.models, {reindex: false});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
LunrFilter is a ClientSideFilter that uses [lunrjs](http://lunrjs.com/) to
|
||||
index the text fields of each model for a collection, and performs
|
||||
full-text searching.
|
||||
|
||||
@class Backgrid.Extension.LunrFilter
|
||||
@extends Backgrid.Extension.ClientSideFilter
|
||||
*/
|
||||
var LunrFilter = Backgrid.Extension.LunrFilter = ClientSideFilter.extend({
|
||||
|
||||
/**
|
||||
@property {string} [ref="id"]`lunrjs` document reference attribute name.
|
||||
*/
|
||||
ref: "id",
|
||||
|
||||
/**
|
||||
@property {Object} fields A hash of `lunrjs` index field names and boost
|
||||
value. Unlike ClientSideFilter#fields, LunrFilter#fields is _required_ to
|
||||
initialize the index.
|
||||
*/
|
||||
fields: null,
|
||||
|
||||
/**
|
||||
Indexes the underlying collection on construction. The index will refresh
|
||||
when the underlying collection is reset. If any model is added, removed
|
||||
or if any indexed fields of any models has changed, the index will be
|
||||
updated.
|
||||
|
||||
@param {Object} options
|
||||
@param {Backbone.Collection} options.collection
|
||||
@param {string} [options.placeholder]
|
||||
@param {string} [options.ref] `lunrjs` document reference attribute name.
|
||||
@param {Object} [options.fields] A hash of `lunrjs` index field names and
|
||||
boost value.
|
||||
@param {number} [options.wait]
|
||||
*/
|
||||
initialize: function (options) {
|
||||
LunrFilter.__super__.initialize.apply(this, arguments);
|
||||
|
||||
this.ref = options.ref || this.ref;
|
||||
|
||||
var collection = this.collection = this.collection.fullCollection || this.collection;
|
||||
this.listenTo(collection, "add", this.addToIndex);
|
||||
this.listenTo(collection, "remove", this.removeFromIndex);
|
||||
this.listenTo(collection, "reset", this.resetIndex);
|
||||
this.listenTo(collection, "change", this.updateIndex);
|
||||
|
||||
this.resetIndex(collection);
|
||||
},
|
||||
|
||||
/**
|
||||
Reindex the collection. If `options.reindex` is `false`, this method is a
|
||||
no-op.
|
||||
|
||||
@param {Backbone.Collection} collection
|
||||
@param {Object} [options]
|
||||
@param {boolean} [options.reindex=true]
|
||||
*/
|
||||
resetIndex: function (collection, options) {
|
||||
options = _.extend({reindex: true}, options || {});
|
||||
|
||||
if (options.reindex) {
|
||||
var self = this;
|
||||
this.index = lunr(function () {
|
||||
_.each(self.fields, function (boost, fieldName) {
|
||||
this.field(fieldName, boost);
|
||||
this.ref(self.ref);
|
||||
}, this);
|
||||
});
|
||||
|
||||
collection.each(function (model) {
|
||||
this.addToIndex(model);
|
||||
}, this);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
Adds the given model to the index.
|
||||
|
||||
@param {Backbone.Model} model
|
||||
*/
|
||||
addToIndex: function (model) {
|
||||
var index = this.index;
|
||||
var doc = model.toJSON();
|
||||
if (index.documentStore.has(doc[this.ref])) index.update(doc);
|
||||
else index.add(doc);
|
||||
},
|
||||
|
||||
/**
|
||||
Removes the given model from the index.
|
||||
|
||||
@param {Backbone.Model} model
|
||||
*/
|
||||
removeFromIndex: function (model) {
|
||||
var index = this.index;
|
||||
var doc = model.toJSON();
|
||||
if (index.documentStore.has(doc[this.ref])) index.remove(doc);
|
||||
},
|
||||
|
||||
/**
|
||||
Updates the index for the given model.
|
||||
|
||||
@param {Backbone.Model} model
|
||||
*/
|
||||
updateIndex: function (model) {
|
||||
var changed = model.changedAttributes();
|
||||
if (changed && !_.isEmpty(_.intersection(_.keys(this.fields),
|
||||
_.keys(changed)))) {
|
||||
this.index.update(model.toJSON());
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
Takes the query from the search box and performs a full-text search on
|
||||
the client-side. The search result is returned by resetting the
|
||||
underlying collection to the models after interrogating the index for the
|
||||
query answer.
|
||||
|
||||
If the collection is a PageableCollection, searching will go back to the
|
||||
first page.
|
||||
*/
|
||||
search: function () {
|
||||
var col = this.collection;
|
||||
if (!this.query()) {
|
||||
col.reset(this.shadowCollection.models, {reindex: false});
|
||||
return;
|
||||
}
|
||||
|
||||
var searchResults = this.index.search(this.query());
|
||||
var models = [];
|
||||
for (var i = 0; i < searchResults.length; i++) {
|
||||
var result = searchResults[i];
|
||||
models.push(this.shadowCollection.get(result.ref));
|
||||
}
|
||||
|
||||
if (col.pageableCollection) col.pageableCollection.getFirstPage({silent: true});
|
||||
col.reset(models, {reindex: false});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}));
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,433 @@
|
|||
/*
|
||||
backgrid-paginator
|
||||
http://github.com/wyuenho/backgrid
|
||||
|
||||
Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
|
||||
Licensed under the MIT @license.
|
||||
*/
|
||||
(function (root, factory) {
|
||||
|
||||
// CommonJS
|
||||
if (typeof exports == "object") {
|
||||
module.exports = factory(require("underscore"),
|
||||
require("backbone"),
|
||||
require("backgrid"),
|
||||
require("backbone.paginator"));
|
||||
}
|
||||
// AMD. Register as an anonymous module.
|
||||
else if (typeof define === 'function' && define.amd) {
|
||||
define(['underscore', 'backbone', 'backgrid', 'backbone.paginator'], factory);
|
||||
}
|
||||
// Browser
|
||||
else {
|
||||
factory(root._, root.Backbone, root.Backgrid);
|
||||
}
|
||||
|
||||
}(this, function (_, Backbone, Backgrid) {
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
PageHandle is a class that renders the actual page handles and reacts to
|
||||
click events for pagination.
|
||||
|
||||
This class acts in two modes - control or discrete page handle modes. If
|
||||
one of the `is*` flags is `true`, an instance of this class is under
|
||||
control page handle mode. Setting a `pageIndex` to an instance of this
|
||||
class under control mode has no effect and the correct page index will
|
||||
always be inferred from the `is*` flag. Only one of the `is*` flags should
|
||||
be set to `true` at a time. For example, an instance of this class cannot
|
||||
simultaneously be a rewind control and a fast forward control. A `label`
|
||||
and a `title` function or a string are required to be passed to the
|
||||
constuctor under this mode. If a `title` function is provided, it __MUST__
|
||||
accept a hash parameter `data`, which contains a key `label`. Its result
|
||||
will be used to render the generated anchor's title attribute.
|
||||
|
||||
If all of the `is*` flags is set to `false`, which is the default, an
|
||||
instance of this class will be in discrete page handle mode. An instance
|
||||
under this mode requires the `pageIndex` to be passed from the constructor
|
||||
as an option and it __MUST__ be a 0-based index of the list of page numbers
|
||||
to render. The constuctor will normalize the base to the same base the
|
||||
underlying PageableCollection collection instance uses. A `label` is not
|
||||
required under this mode, which will default to the equivalent 1-based page
|
||||
index calculated from `pageIndex` and the underlying PageableCollection
|
||||
instance. A provided `label` will still be honored however. The `title`
|
||||
parameter is also not required under this mode, in which case the default
|
||||
`title` function will be used. You are encouraged to provide your own
|
||||
`title` function however if you wish to localize the title strings.
|
||||
|
||||
If this page handle represents the current page, an `active` class will be
|
||||
placed on the root list element.
|
||||
|
||||
If this page handle is at the border of the list of pages, a `disabled`
|
||||
class will be placed on the root list element.
|
||||
|
||||
Only page handles that are neither `active` nor `disabled` will respond to
|
||||
click events and triggers pagination.
|
||||
|
||||
@class Backgrid.Extension.PageHandle
|
||||
*/
|
||||
var PageHandle = Backgrid.Extension.PageHandle = Backbone.View.extend({
|
||||
|
||||
/** @property */
|
||||
tagName: "li",
|
||||
|
||||
/** @property */
|
||||
events: {
|
||||
"click a": "changePage"
|
||||
},
|
||||
|
||||
/**
|
||||
@property {string|function(Object.<string, string>): string} title
|
||||
The title to use for the `title` attribute of the generated page handle
|
||||
anchor elements. It can be a string or a function that takes a `data`
|
||||
parameter, which contains a mandatory `label` key which provides the
|
||||
label value to be displayed.
|
||||
*/
|
||||
title: function (data) {
|
||||
return 'Page ' + data.label;
|
||||
},
|
||||
|
||||
/**
|
||||
@property {boolean} isRewind Whether this handle represents a rewind
|
||||
control
|
||||
*/
|
||||
isRewind: false,
|
||||
|
||||
/**
|
||||
@property {boolean} isBack Whether this handle represents a back
|
||||
control
|
||||
*/
|
||||
isBack: false,
|
||||
|
||||
/**
|
||||
@property {boolean} isForward Whether this handle represents a forward
|
||||
control
|
||||
*/
|
||||
isForward: false,
|
||||
|
||||
/**
|
||||
@property {boolean} isFastForward Whether this handle represents a fast
|
||||
forward control
|
||||
*/
|
||||
isFastForward: false,
|
||||
|
||||
/**
|
||||
Initializer.
|
||||
|
||||
@param {Object} options
|
||||
@param {Backbone.Collection} options.collection
|
||||
@param {number} pageIndex 0-based index of the page number this handle
|
||||
handles. This parameter will be normalized to the base the underlying
|
||||
PageableCollection uses.
|
||||
@param {string} [options.label] If provided it is used to render the
|
||||
anchor text, otherwise the normalized pageIndex will be used
|
||||
instead. Required if any of the `is*` flags is set to `true`.
|
||||
@param {string} [options.title]
|
||||
@param {boolean} [options.isRewind=false]
|
||||
@param {boolean} [options.isBack=false]
|
||||
@param {boolean} [options.isForward=false]
|
||||
@param {boolean} [options.isFastForward=false]
|
||||
*/
|
||||
initialize: function (options) {
|
||||
var collection = this.collection;
|
||||
var state = collection.state;
|
||||
var currentPage = state.currentPage;
|
||||
var firstPage = state.firstPage;
|
||||
var lastPage = state.lastPage;
|
||||
|
||||
_.extend(this, _.pick(options,
|
||||
["isRewind", "isBack", "isForward", "isFastForward"]));
|
||||
|
||||
var pageIndex;
|
||||
if (this.isRewind) pageIndex = firstPage;
|
||||
else if (this.isBack) pageIndex = Math.max(firstPage, currentPage - 1);
|
||||
else if (this.isForward) pageIndex = Math.min(lastPage, currentPage + 1);
|
||||
else if (this.isFastForward) pageIndex = lastPage;
|
||||
else {
|
||||
pageIndex = +options.pageIndex;
|
||||
pageIndex = (firstPage ? pageIndex + 1 : pageIndex);
|
||||
}
|
||||
this.pageIndex = pageIndex;
|
||||
|
||||
this.label = (options.label || (firstPage ? pageIndex : pageIndex + 1)) + '';
|
||||
var title = options.title || this.title;
|
||||
this.title = _.isFunction(title) ? title({label: this.label}) : title;
|
||||
},
|
||||
|
||||
/**
|
||||
Renders a clickable anchor element under a list item.
|
||||
*/
|
||||
render: function () {
|
||||
this.$el.empty();
|
||||
var anchor = document.createElement("a");
|
||||
anchor.href = '#';
|
||||
if (this.title) anchor.title = this.title;
|
||||
anchor.innerHTML = this.label;
|
||||
this.el.appendChild(anchor);
|
||||
|
||||
var collection = this.collection;
|
||||
var state = collection.state;
|
||||
var currentPage = state.currentPage;
|
||||
var pageIndex = this.pageIndex;
|
||||
|
||||
if (this.isRewind && currentPage == state.firstPage ||
|
||||
this.isBack && !collection.hasPreviousPage() ||
|
||||
this.isForward && !collection.hasNextPage() ||
|
||||
this.isFastForward && (currentPage == state.lastPage || state.totalPages < 1)) {
|
||||
this.$el.addClass("disabled");
|
||||
}
|
||||
else if (!(this.isRewind ||
|
||||
this.isBack ||
|
||||
this.isForward ||
|
||||
this.isFastForward) &&
|
||||
state.currentPage == pageIndex) {
|
||||
this.$el.addClass("active");
|
||||
}
|
||||
|
||||
this.delegateEvents();
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
jQuery click event handler. Goes to the page this PageHandle instance
|
||||
represents. No-op if this page handle is currently active or disabled.
|
||||
*/
|
||||
changePage: function (e) {
|
||||
e.preventDefault();
|
||||
var $el = this.$el, col = this.collection;
|
||||
if (!$el.hasClass("active") && !$el.hasClass("disabled")) {
|
||||
if (this.isRewind) col.getFirstPage();
|
||||
else if (this.isBack) col.getPreviousPage();
|
||||
else if (this.isForward) col.getNextPage();
|
||||
else if (this.isFastForward) col.getLastPage();
|
||||
else col.getPage(this.pageIndex, {reset: true});
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
Paginator is a Backgrid extension that renders a series of configurable
|
||||
pagination handles. This extension is best used for splitting a large data
|
||||
set across multiple pages. If the number of pages is larger then a
|
||||
threshold, which is set to 10 by default, the page handles are rendered
|
||||
within a sliding window, plus the rewind, back, forward and fast forward
|
||||
control handles. The individual control handles can be turned off.
|
||||
|
||||
@class Backgrid.Extension.Paginator
|
||||
*/
|
||||
var Paginator = Backgrid.Extension.Paginator = Backbone.View.extend({
|
||||
|
||||
/** @property */
|
||||
className: "backgrid-paginator",
|
||||
|
||||
/** @property */
|
||||
windowSize: 10,
|
||||
|
||||
/**
|
||||
@property {number} slideScale the number used by #slideHowMuch to scale
|
||||
`windowSize` to yield the number of pages to slide. For example, the
|
||||
default windowSize(10) * slideScale(0.5) yields 5, which means the window
|
||||
will slide forward 5 pages as soon as you've reached page 6. The smaller
|
||||
the scale factor the less pages to slide, and vice versa.
|
||||
|
||||
Also See:
|
||||
|
||||
- #slideMaybe
|
||||
- #slideHowMuch
|
||||
*/
|
||||
slideScale: 0.5,
|
||||
|
||||
/**
|
||||
@property {Object.<string, Object.<string, string>>} controls You can
|
||||
disable specific control handles by setting the keys in question to
|
||||
null. The defaults will be merged with your controls object, with your
|
||||
changes taking precedent.
|
||||
*/
|
||||
controls: {
|
||||
rewind: {
|
||||
label: "《",
|
||||
title: "First"
|
||||
},
|
||||
back: {
|
||||
label: "〈",
|
||||
title: "Previous"
|
||||
},
|
||||
forward: {
|
||||
label: "〉",
|
||||
title: "Next"
|
||||
},
|
||||
fastForward: {
|
||||
label: "》",
|
||||
title: "Last"
|
||||
}
|
||||
},
|
||||
|
||||
/** @property */
|
||||
renderIndexedPageHandles: true,
|
||||
|
||||
/**
|
||||
@property {Backgrid.Extension.PageHandle} pageHandle. The PageHandle
|
||||
class to use for rendering individual handles
|
||||
*/
|
||||
pageHandle: PageHandle,
|
||||
|
||||
/** @property */
|
||||
goBackFirstOnSort: true,
|
||||
|
||||
/**
|
||||
Initializer.
|
||||
|
||||
@param {Object} options
|
||||
@param {Backbone.Collection} options.collection
|
||||
@param {boolean} [options.controls]
|
||||
@param {boolean} [options.pageHandle=Backgrid.Extension.PageHandle]
|
||||
@param {boolean} [options.goBackFirstOnSort=true]
|
||||
*/
|
||||
initialize: function (options) {
|
||||
var self = this;
|
||||
self.controls = _.defaults(options.controls || {}, self.controls,
|
||||
Paginator.prototype.controls);
|
||||
|
||||
_.extend(self, _.pick(options || {}, "windowSize", "pageHandle",
|
||||
"slideScale", "goBackFirstOnSort",
|
||||
"renderIndexedPageHandles"));
|
||||
|
||||
var col = self.collection;
|
||||
self.listenTo(col, "add", self.render);
|
||||
self.listenTo(col, "remove", self.render);
|
||||
self.listenTo(col, "reset", self.render);
|
||||
self.listenTo(col, "backgrid:sorted", function () {
|
||||
if (self.goBackFirstOnSort) col.getFirstPage({reset: true});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
Decides whether the window should slide. This method should return 1 if
|
||||
sliding should occur and 0 otherwise. The default is sliding should occur
|
||||
if half of the pages in a window has been reached.
|
||||
|
||||
__Note__: All the parameters have been normalized to be 0-based.
|
||||
|
||||
@param {number} firstPage
|
||||
@param {number} lastPage
|
||||
@param {number} currentPage
|
||||
@param {number} windowSize
|
||||
@param {number} slideScale
|
||||
|
||||
@return {0|1}
|
||||
*/
|
||||
slideMaybe: function (firstPage, lastPage, currentPage, windowSize, slideScale) {
|
||||
return Math.round(currentPage % windowSize / windowSize);
|
||||
},
|
||||
|
||||
/**
|
||||
Decides how many pages to slide when sliding should occur. The default
|
||||
simply scales the `windowSize` to arrive at a fraction of the `windowSize`
|
||||
to increment.
|
||||
|
||||
__Note__: All the parameters have been normalized to be 0-based.
|
||||
|
||||
@param {number} firstPage
|
||||
@param {number} lastPage
|
||||
@param {number} currentPage
|
||||
@param {number} windowSize
|
||||
@param {number} slideScale
|
||||
|
||||
@return {number}
|
||||
*/
|
||||
slideThisMuch: function (firstPage, lastPage, currentPage, windowSize, slideScale) {
|
||||
return ~~(windowSize * slideScale);
|
||||
},
|
||||
|
||||
_calculateWindow: function () {
|
||||
var collection = this.collection;
|
||||
var state = collection.state;
|
||||
|
||||
// convert all indices to 0-based here
|
||||
var firstPage = state.firstPage;
|
||||
var lastPage = +state.lastPage;
|
||||
lastPage = Math.max(0, firstPage ? lastPage - 1 : lastPage);
|
||||
var currentPage = Math.max(state.currentPage, state.firstPage);
|
||||
currentPage = firstPage ? currentPage - 1 : currentPage;
|
||||
var windowSize = this.windowSize;
|
||||
var slideScale = this.slideScale;
|
||||
var windowStart = Math.floor(currentPage / windowSize) * windowSize;
|
||||
if (currentPage <= lastPage - this.slideThisMuch()) {
|
||||
windowStart += (this.slideMaybe(firstPage, lastPage, currentPage, windowSize, slideScale) *
|
||||
this.slideThisMuch(firstPage, lastPage, currentPage, windowSize, slideScale));
|
||||
}
|
||||
var windowEnd = Math.min(lastPage + 1, windowStart + windowSize);
|
||||
return [windowStart, windowEnd];
|
||||
},
|
||||
|
||||
/**
|
||||
Creates a list of page handle objects for rendering.
|
||||
|
||||
@return {Array.<Object>} an array of page handle objects hashes
|
||||
*/
|
||||
makeHandles: function () {
|
||||
|
||||
var handles = [];
|
||||
var collection = this.collection;
|
||||
|
||||
var window = this._calculateWindow();
|
||||
var winStart = window[0], winEnd = window[1];
|
||||
|
||||
if (this.renderIndexedPageHandles) {
|
||||
for (var i = winStart; i < winEnd; i++) {
|
||||
handles.push(new this.pageHandle({
|
||||
collection: collection,
|
||||
pageIndex: i
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
var controls = this.controls;
|
||||
_.each(["back", "rewind", "forward", "fastForward"], function (key) {
|
||||
var value = controls[key];
|
||||
if (value) {
|
||||
var handleCtorOpts = {
|
||||
collection: collection,
|
||||
title: value.title,
|
||||
label: value.label
|
||||
};
|
||||
handleCtorOpts["is" + key.slice(0, 1).toUpperCase() + key.slice(1)] = true;
|
||||
var handle = new this.pageHandle(handleCtorOpts);
|
||||
if (key == "rewind" || key == "back") handles.unshift(handle);
|
||||
else handles.push(handle);
|
||||
}
|
||||
}, this);
|
||||
|
||||
return handles;
|
||||
},
|
||||
|
||||
/**
|
||||
Render the paginator handles inside an unordered list.
|
||||
*/
|
||||
render: function () {
|
||||
this.$el.empty();
|
||||
|
||||
if (this.handles) {
|
||||
for (var i = 0, l = this.handles.length; i < l; i++) {
|
||||
this.handles[i].remove();
|
||||
}
|
||||
}
|
||||
|
||||
var handles = this.handles = this.makeHandles();
|
||||
|
||||
var ul = document.createElement("ul");
|
||||
for (var i = 0; i < handles.length; i++) {
|
||||
ul.appendChild(handles[i].render().el);
|
||||
}
|
||||
|
||||
this.el.appendChild(ul);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}));
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
backgrid-paginator
|
||||
http://github.com/wyuenho/backgrid
|
||||
|
||||
Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
|
||||
Licensed under the MIT @license.
|
||||
*/
|
||||
!function(a,b){"object"==typeof exports&&(module.exports=b(require("underscore"),require("backbone"),require("backgrid"),require("backbone.paginator"))),"function"==typeof define&&define.amd?define(["underscore","backbone","backgrid","backbone.paginator"],b):b(a._,a.Backbone,a.Backgrid)}(this,function(a,b,c){"use strict";var d=c.Extension.PageHandle=b.View.extend({tagName:"li",events:{"click a":"changePage"},title:function(a){return"Page "+a.label},isRewind:!1,isBack:!1,isForward:!1,isFastForward:!1,initialize:function(b){var c=this.collection,d=c.state,e=d.currentPage,f=d.firstPage,g=d.lastPage;a.extend(this,a.pick(b,["isRewind","isBack","isForward","isFastForward"]));var h;this.isRewind?h=f:this.isBack?h=Math.max(f,e-1):this.isForward?h=Math.min(g,e+1):this.isFastForward?h=g:(h=+b.pageIndex,h=f?h+1:h),this.pageIndex=h,this.label=(b.label||(f?h:h+1))+"";var i=b.title||this.title;this.title=a.isFunction(i)?i({label:this.label}):i},render:function(){this.$el.empty();var a=document.createElement("a");a.href="#",this.title&&(a.title=this.title),a.innerHTML=this.label,this.el.appendChild(a);var b=this.collection,c=b.state,d=c.currentPage,e=this.pageIndex;return this.isRewind&&d==c.firstPage||this.isBack&&!b.hasPreviousPage()||this.isForward&&!b.hasNextPage()||this.isFastForward&&(d==c.lastPage||c.totalPages<1)?this.$el.addClass("disabled"):this.isRewind||this.isBack||this.isForward||this.isFastForward||c.currentPage!=e||this.$el.addClass("active"),this.delegateEvents(),this},changePage:function(a){a.preventDefault();var b=this.$el,c=this.collection;return b.hasClass("active")||b.hasClass("disabled")||(this.isRewind?c.getFirstPage():this.isBack?c.getPreviousPage():this.isForward?c.getNextPage():this.isFastForward?c.getLastPage():c.getPage(this.pageIndex,{reset:!0})),this}}),e=c.Extension.Paginator=b.View.extend({className:"backgrid-paginator",windowSize:10,slideScale:.5,controls:{rewind:{label:"《",title:"First"},back:{label:"〈",title:"Previous"},forward:{label:"〉",title:"Next"},fastForward:{label:"》",title:"Last"}},renderIndexedPageHandles:!0,pageHandle:d,goBackFirstOnSort:!0,initialize:function(b){var c=this;c.controls=a.defaults(b.controls||{},c.controls,e.prototype.controls),a.extend(c,a.pick(b||{},"windowSize","pageHandle","slideScale","goBackFirstOnSort","renderIndexedPageHandles"));var d=c.collection;c.listenTo(d,"add",c.render),c.listenTo(d,"remove",c.render),c.listenTo(d,"reset",c.render),c.listenTo(d,"backgrid:sorted",function(){c.goBackFirstOnSort&&d.getFirstPage({reset:!0})})},slideMaybe:function(a,b,c,d){return Math.round(c%d/d)},slideThisMuch:function(a,b,c,d,e){return~~(d*e)},_calculateWindow:function(){var a=this.collection,b=a.state,c=b.firstPage,d=+b.lastPage;d=Math.max(0,c?d-1:d);var e=Math.max(b.currentPage,b.firstPage);e=c?e-1:e;var f=this.windowSize,g=this.slideScale,h=Math.floor(e/f)*f;e<=d-this.slideThisMuch()&&(h+=this.slideMaybe(c,d,e,f,g)*this.slideThisMuch(c,d,e,f,g));var i=Math.min(d+1,h+f);return[h,i]},makeHandles:function(){var b=[],c=this.collection,d=this._calculateWindow(),e=d[0],f=d[1];if(this.renderIndexedPageHandles)for(var g=e;f>g;g++)b.push(new this.pageHandle({collection:c,pageIndex:g}));var h=this.controls;return a.each(["back","rewind","forward","fastForward"],function(a){var d=h[a];if(d){var e={collection:c,title:d.title,label:d.label};e["is"+a.slice(0,1).toUpperCase()+a.slice(1)]=!0;var f=new this.pageHandle(e);"rewind"==a||"back"==a?b.unshift(f):b.push(f)}},this),b},render:function(){if(this.$el.empty(),this.handles)for(var a=0,b=this.handles.length;b>a;a++)this.handles[a].remove();for(var c=this.handles=this.makeHandles(),d=document.createElement("ul"),a=0;a<c.length;a++)d.appendChild(c[a].render().el);return this.el.appendChild(d),this}})});
|
|
@ -0,0 +1,294 @@
|
|||
/*
|
||||
backgrid-select-all
|
||||
http://github.com/wyuenho/backgrid
|
||||
|
||||
Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
|
||||
Licensed under the MIT @license.
|
||||
*/
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define(["backbone", "backgrid", "underscore"], factory);
|
||||
} else if (typeof exports == "object") {
|
||||
// CommonJS
|
||||
module.exports = factory(require("backbone"), require("backgrid"), require("underscore"));
|
||||
}
|
||||
// Browser
|
||||
else factory(root.Backbone, root.Backgrid, root._);
|
||||
|
||||
}(this, function (Backbone, Backgrid, _) {
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
Renders a checkbox for row selection.
|
||||
|
||||
@class Backgrid.Extension.SelectRowCell
|
||||
@extends Backbone.View
|
||||
*/
|
||||
var SelectRowCell = Backgrid.Extension.SelectRowCell = Backbone.View.extend({
|
||||
|
||||
/** @property */
|
||||
className: "select-row-cell",
|
||||
|
||||
/** @property */
|
||||
tagName: "td",
|
||||
|
||||
/** @property */
|
||||
events: {
|
||||
"keydown input[type=checkbox]": "onKeydown",
|
||||
"change input[type=checkbox]": "onChange",
|
||||
"click input[type=checkbox]": "enterEditMode"
|
||||
},
|
||||
|
||||
/**
|
||||
Initializer. If the underlying model triggers a `select` event, this cell
|
||||
will change its checked value according to the event's `selected` value.
|
||||
|
||||
@param {Object} options
|
||||
@param {Backgrid.Column} options.column
|
||||
@param {Backbone.Model} options.model
|
||||
*/
|
||||
initialize: function (options) {
|
||||
|
||||
this.column = options.column;
|
||||
if (!(this.column instanceof Backgrid.Column)) {
|
||||
this.column = new Backgrid.Column(this.column);
|
||||
}
|
||||
|
||||
var column = this.column, model = this.model, $el = this.$el;
|
||||
this.listenTo(column, "change:renderable", function (column, renderable) {
|
||||
$el.toggleClass("renderable", renderable);
|
||||
});
|
||||
|
||||
if (Backgrid.callByNeed(column.renderable(), column, model)) $el.addClass("renderable");
|
||||
|
||||
this.listenTo(model, "backgrid:select", function (model, selected) {
|
||||
this.checkbox().prop("checked", selected).change();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
Returns the checkbox.
|
||||
*/
|
||||
checkbox: function () {
|
||||
return this.$el.find("input[type=checkbox]");
|
||||
},
|
||||
|
||||
/**
|
||||
Focuses the checkbox.
|
||||
*/
|
||||
enterEditMode: function () {
|
||||
this.checkbox().focus();
|
||||
},
|
||||
|
||||
/**
|
||||
Unfocuses the checkbox.
|
||||
*/
|
||||
exitEditMode: function () {
|
||||
this.checkbox().blur();
|
||||
},
|
||||
|
||||
/**
|
||||
Process keyboard navigation.
|
||||
*/
|
||||
onKeydown: function (e) {
|
||||
var command = new Backgrid.Command(e);
|
||||
if (command.passThru()) return true; // skip ahead to `change`
|
||||
if (command.cancel()) {
|
||||
e.stopPropagation();
|
||||
this.checkbox().blur();
|
||||
}
|
||||
else if (command.save() || command.moveLeft() || command.moveRight() ||
|
||||
command.moveUp() || command.moveDown()) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.model.trigger("backgrid:edited", this.model, this.column, command);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
When the checkbox's value changes, this method will trigger a Backbone
|
||||
`backgrid:selected` event with a reference of the model and the
|
||||
checkbox's `checked` value.
|
||||
*/
|
||||
onChange: function () {
|
||||
var checked = this.checkbox().prop("checked");
|
||||
this.$el.parent().toggleClass("selected", checked);
|
||||
this.model.trigger("backgrid:selected", this.model, checked);
|
||||
},
|
||||
|
||||
/**
|
||||
Renders a checkbox in a table cell.
|
||||
*/
|
||||
render: function () {
|
||||
this.$el.empty().append('<input tabindex="-1" type="checkbox" />');
|
||||
this.delegateEvents();
|
||||
return this;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
Renders a checkbox to select all rows on the current page.
|
||||
|
||||
@class Backgrid.Extension.SelectAllHeaderCell
|
||||
@extends Backgrid.Extension.SelectRowCell
|
||||
*/
|
||||
var SelectAllHeaderCell = Backgrid.Extension.SelectAllHeaderCell = SelectRowCell.extend({
|
||||
|
||||
/** @property */
|
||||
className: "select-all-header-cell",
|
||||
|
||||
/** @property */
|
||||
tagName: "th",
|
||||
|
||||
/**
|
||||
Initializer. When this cell's checkbox is checked, a Backbone
|
||||
`backgrid:select` event will be triggered for each model for the current
|
||||
page in the underlying collection. If a `SelectRowCell` instance exists
|
||||
for the rows representing the models, they will check themselves. If any
|
||||
of the SelectRowCell instances trigger a Backbone `backgrid:selected`
|
||||
event with a `false` value, this cell will uncheck its checkbox. In the
|
||||
event of a Backbone `backgrid:refresh` event, which is triggered when the
|
||||
body refreshes its rows, which can happen under a number of conditions
|
||||
such as paging or the columns were reset, this cell will still remember
|
||||
the previously selected models and trigger a Backbone `backgrid:select`
|
||||
event on them such that the SelectRowCells can recheck themselves upon
|
||||
refreshing.
|
||||
|
||||
@param {Object} options
|
||||
@param {Backgrid.Column} options.column
|
||||
@param {Backbone.Collection} options.collection
|
||||
*/
|
||||
initialize: function (options) {
|
||||
|
||||
this.column = options.column;
|
||||
if (!(this.column instanceof Backgrid.Column)) {
|
||||
this.column = new Backgrid.Column(this.column);
|
||||
}
|
||||
|
||||
var collection = this.collection;
|
||||
var selectedModels = this.selectedModels = {};
|
||||
this.listenTo(collection.fullCollection || collection,
|
||||
"backgrid:selected", function (model, selected) {
|
||||
if (selected) selectedModels[model.id || model.cid] = 1;
|
||||
else {
|
||||
delete selectedModels[model.id || model.cid];
|
||||
this.checkbox().prop("checked", false);
|
||||
}
|
||||
if (_.keys(selectedModels).length === (collection.fullCollection|| collection).length) {
|
||||
this.checkbox().prop("checked", true);
|
||||
}
|
||||
});
|
||||
|
||||
this.listenTo(collection.fullCollection || collection, "remove", function (model) {
|
||||
delete selectedModels[model.id || model.cid];
|
||||
if ((collection.fullCollection || collection).length === 0) {
|
||||
this.checkbox().prop("checked", false);
|
||||
}
|
||||
});
|
||||
|
||||
this.listenTo(collection, "backgrid:refresh", function () {
|
||||
if ((collection.fullCollection || collection).length === 0) {
|
||||
this.checkbox().prop("checked", false);
|
||||
}
|
||||
else {
|
||||
var checked = this.checkbox().prop("checked");
|
||||
for (var i = 0; i < collection.length; i++) {
|
||||
var model = collection.at(i);
|
||||
if (checked || selectedModels[model.id || model.cid]) {
|
||||
model.trigger("backgrid:select", model, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var column = this.column, $el = this.$el;
|
||||
this.listenTo(column, "change:renderable", function (column, renderable) {
|
||||
$el.toggleClass("renderable", renderable);
|
||||
});
|
||||
|
||||
if (Backgrid.callByNeed(column.renderable(), column, collection)) $el.addClass("renderable");
|
||||
},
|
||||
|
||||
/**
|
||||
Propagates the checked value of this checkbox to all the models of the
|
||||
underlying collection by triggering a Backbone `backgrid:select` event on
|
||||
the models on the current page, passing each model and the current
|
||||
`checked` value of the checkbox in each event.
|
||||
|
||||
A `backgrid:selected` event will also be triggered with the current
|
||||
`checked` value on all the models regardless of whether they are on the
|
||||
current page.
|
||||
|
||||
This method triggers a 'backgrid:select-all' event on the collection
|
||||
afterwards.
|
||||
*/
|
||||
onChange: function () {
|
||||
var checked = this.checkbox().prop("checked");
|
||||
|
||||
var collection = this.collection;
|
||||
collection.each(function (model) {
|
||||
model.trigger("backgrid:select", model, checked);
|
||||
});
|
||||
|
||||
if (collection.fullCollection) {
|
||||
collection.fullCollection.each(function (model) {
|
||||
if (!collection.get(model.cid)) {
|
||||
model.trigger("backgrid:selected", model, checked);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.collection.trigger("backgrid:select-all", this.collection, checked);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
Convenient method to retrieve a list of selected models. This method only
|
||||
exists when the `SelectAll` extension has been included. Selected models
|
||||
are retained across pagination.
|
||||
|
||||
@member Backgrid.Grid
|
||||
@return {Array.<Backbone.Model>}
|
||||
*/
|
||||
Backgrid.Grid.prototype.getSelectedModels = function () {
|
||||
var selectAllHeaderCell;
|
||||
var headerCells = this.header.row.cells;
|
||||
for (var i = 0, l = headerCells.length; i < l; i++) {
|
||||
var headerCell = headerCells[i];
|
||||
if (headerCell instanceof SelectAllHeaderCell) {
|
||||
selectAllHeaderCell = headerCell;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var result = [];
|
||||
if (selectAllHeaderCell) {
|
||||
var selectedModels = selectAllHeaderCell.selectedModels;
|
||||
var collection = this.collection.fullCollection || this.collection;
|
||||
for (var modelId in selectedModels) {
|
||||
result.push(collection.get(modelId));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
Convenient method to deselect the selected models. This method is only
|
||||
available when the `SelectAll` extension has been included.
|
||||
|
||||
@member Backgrid.Grid
|
||||
*/
|
||||
Backgrid.Grid.prototype.clearSelectedModels = function () {
|
||||
var selectedModels = this.getSelectedModels();
|
||||
for (var i = 0, l = selectedModels.length; i < l; i++) {
|
||||
var model = selectedModels[i];
|
||||
model.trigger("backgrid:select", model, false);
|
||||
}
|
||||
};
|
||||
|
||||
}));
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
backgrid-select-all
|
||||
http://github.com/wyuenho/backgrid
|
||||
|
||||
Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
|
||||
Licensed under the MIT @license.
|
||||
*/
|
||||
!function(a,b){"object"==typeof exports?module.exports=b(require("backbone"),require("backgrid")):b(a.Backbone,a.Backgrid)}(this,function(a,b){"use strict";var c=b.Extension.SelectRowCell=a.View.extend({className:"select-row-cell",tagName:"td",events:{"keydown input[type=checkbox]":"onKeydown","change input[type=checkbox]":"onChange","click input[type=checkbox]":"enterEditMode"},initialize:function(a){this.column=a.column,this.column instanceof b.Column||(this.column=new b.Column(this.column));var c=this.column,d=this.model,e=this.$el;this.listenTo(c,"change:renderable",function(a,b){e.toggleClass("renderable",b)}),b.callByNeed(c.renderable(),c,d)&&e.addClass("renderable"),this.listenTo(d,"backgrid:select",function(a,b){this.$el.find("input[type=checkbox]").prop("checked",b).change()})},enterEditMode:function(){this.$el.find("input[type=checkbox]").focus()},exitEditMode:function(){this.$el.find("input[type=checkbox]").blur()},onKeydown:function(a){var c=new b.Command(a);return c.passThru()?!0:(c.cancel()?(a.stopPropagation(),this.$el.find("input[type=checkbox]").blur()):(c.save()||c.moveLeft()||c.moveRight()||c.moveUp()||c.moveDown())&&(a.preventDefault(),a.stopPropagation(),this.model.trigger("backgrid:edited",this.model,this.column,c)),void 0)},onChange:function(){var a=this.$el.find("input[type=checkbox]").prop("checked");this.$el.parent().toggleClass("selected",a),this.model.trigger("backgrid:selected",this.model,a)},render:function(){return this.$el.empty().append('<input tabindex="-1" type="checkbox" />'),this.delegateEvents(),this}}),d=b.Extension.SelectAllHeaderCell=c.extend({className:"select-all-header-cell",tagName:"th",initialize:function(a){this.column=a.column,this.column instanceof b.Column||(this.column=new b.Column(this.column));var c=this.collection,d=this.selectedModels={};this.listenTo(c.fullCollection||c,"backgrid:selected",function(a,b){b?d[a.id||a.cid]=1:(delete d[a.id||a.cid],this.$el.find("input[type=checkbox]").prop("checked",!1))}),this.listenTo(c.fullCollection||c,"remove",function(a){delete d[a.id||a.cid]}),this.listenTo(c,"backgrid:refresh",function(){for(var a=this.$el.find("input[type=checkbox]").prop("checked"),b=0;b<c.length;b++){var e=c.at(b);(a||d[e.id||e.cid])&&e.trigger("backgrid:select",e,!0)}});var e=this.column,f=this.$el;this.listenTo(e,"change:renderable",function(a,b){f.toggleClass("renderable",b)}),b.callByNeed(e.renderable(),e,c)&&f.addClass("renderable")},onChange:function(){var a=this.$el.find("input[type=checkbox]").prop("checked"),b=this.collection;b.each(function(b){b.trigger("backgrid:select",b,a)}),b.fullCollection&&b.fullCollection.each(function(c){b.get(c.cid)||c.trigger("backgrid:selected",c,a)}),this.collection.trigger("backgrid:select-all",this.collection,a)}});b.Grid.prototype.getSelectedModels=function(){for(var a,b=this.header.row.cells,c=0,e=b.length;e>c;c++){var f=b[c];if(f instanceof d){a=f;break}}var g=[];if(a){var h=a.selectedModels,i=this.collection.fullCollection||this.collection;for(var j in h)g.push(i.get(j))}return g},b.Grid.prototype.clearSelectedModels=function(){for(var a=this.getSelectedModels(),b=0,c=a.length;c>b;b++){var d=a[b];d.trigger("backgrid:select",d,!1)}}});
|
|
@ -24,6 +24,9 @@
|
|||
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap-datepicker3.css')}}"/>
|
||||
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap-switch.css')}}"/>
|
||||
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/backgrid/backgrid.css')}}"/>
|
||||
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/backgrid/backgrid-select-all.css' if config.DEBUG else 'css/backgrid/backgrid-select-all.min.css')}}"/>
|
||||
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/backgrid/backgrid-paginator.css' if config.DEBUG else 'css/backgrid/backgrid-paginator.min.css')}}"/>
|
||||
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/backgrid/backgrid-filter.css' if config.DEBUG else 'css/backgrid/backgrid-filter.min.css')}}"/>
|
||||
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/select2/select2.css' if config.DEBUG else 'css/select2/select2.min.css')}}"/>
|
||||
|
||||
<!-- View specified stylesheets -->
|
||||
|
@ -32,6 +35,7 @@
|
|||
{% endfor %}
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/overrides.css') }}"/>
|
||||
{% block css_link %}{% endblock %}
|
||||
|
||||
<!-- Base template scripts -->
|
||||
<script type="text/javascript" src="{{ url_for('static', filename='js/require.js' if config.DEBUG else 'js/require.min.js') }}"></script>
|
||||
|
@ -44,6 +48,9 @@
|
|||
"deps": ['underscore', 'jquery'],
|
||||
"exports": 'Backbone'
|
||||
},
|
||||
"backbone.paginator": {
|
||||
"deps": ['underscore', 'jquery', 'backbone']
|
||||
},
|
||||
"bootstrap": {
|
||||
"deps": ['jquery'],
|
||||
},
|
||||
|
@ -51,6 +58,15 @@
|
|||
"deps": ['backform'],
|
||||
"exports": 'Backgrid',
|
||||
},
|
||||
"backgrid.select.all": {
|
||||
"deps": ['backgrid']
|
||||
},
|
||||
"backgrid.paginator": {
|
||||
"deps": ['backgrid', 'backbone.paginator']
|
||||
},
|
||||
"backgrid.filter": {
|
||||
"deps": ['backgrid']
|
||||
},
|
||||
"bootstrap.switch": {
|
||||
"deps": ['jquery', 'bootstrap'],
|
||||
"exports": 'jQuery.fn.bootstrapSwitch'
|
||||
|
@ -85,10 +101,14 @@
|
|||
alertifyjs: "{{ url_for('static', filename='js/alertifyjs/' + ('alertify' if config.DEBUG else 'alertify.min')) }}",
|
||||
'pgadmin.alertifyjs': "{{ url_for('static', filename='js/alertifyjs/pgadmin.defaults') }}",
|
||||
backbone: "{{ url_for('static', filename='js/' + ('backbone' if config.DEBUG else 'backbone-min')) }}",
|
||||
"backbone.paginator": "{{ url_for('static', filename='js/' + ('backbone.paginator' if config.DEBUG else 'backbone.paginator.min')) }}",
|
||||
"bootstrap.datepicker": "{{ url_for('static', filename='js/' + ('bootstrap-datepicker' if config.DEBUG else 'bootstrap-datepicker.min')) }}",
|
||||
"bootstrap.switch": "{{ url_for('static', filename='js/' + ('bootstrap-switch' if config.DEBUG else 'bootstrap-switch.min')) }}",
|
||||
backform: "{{ url_for('static', filename='js/backform') }}",
|
||||
backgrid: "{{ url_for('static', filename='js/backgrid/' + ('backgrid' if config.DEBUG else 'backgrid.min')) }}",
|
||||
"backgrid.select.all": "{{ url_for('static', filename='js/backgrid/' + ('backgrid-select-all' if config.DEBUG else 'backgrid-select-all.min')) }}",
|
||||
"backgrid.paginator": "{{ url_for('static', filename='js/backgrid/' + ('backgrid-paginator' if config.DEBUG else 'backgrid-paginator.min')) }}",
|
||||
"backgrid.filter": "{{ url_for('static', filename='js/backgrid/' + ('backgrid-filter' if config.DEBUG else 'backgrid-filter.min')) }}",
|
||||
"backbone.undo": "{{ url_for('static', filename='js/' + ('backbone.undo' if config.DEBUG else 'backbone.undo.min')) }}",
|
||||
"pgadmin.backgrid": "{{ url_for('static', filename='js/backgrid/backgrid.pgadmin') }}",
|
||||
'pgadmin.backform': "{{ url_for('static', filename='js/backform.pgadmin') }}"{% for script in current_app.javascripts %},
|
||||
|
|
Loading…
Reference in New Issue