Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sortable Library Swap #439

Merged
merged 2 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/js/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
//

// =require media-background-lazyload.js
// =require sortable.js
236 changes: 236 additions & 0 deletions src/js/sortable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
(function () {
let SELECTOR, addEventListener, clickEvents, numberRegExp, sortable, touchDevice, trimRegExp;

SELECTOR = 'table[data-sortable]';

numberRegExp = /^-?[£$¤]?[\d,.]+%?$/;

trimRegExp = /^\s+|\s+$/g;

clickEvents = ['click'];

touchDevice = 'ontouchstart' in document.documentElement;

if (touchDevice) {
clickEvents.push('touchstart');
}

addEventListener = function (el, event, handler) {
if (el.addEventListener != null) {
return el.addEventListener(event, handler, false);
}
return el.attachEvent(`on${event}`, handler);

};

sortable = {
init: function (options) {
let _i, _len, _results, table, tables;
if (options == null) {
options = {};
}
if (options.selector == null) {
options.selector = SELECTOR;
}
tables = document.querySelectorAll(options.selector);
_results = [];
for (_i = 0, _len = tables.length; _i < _len; _i++) {
table = tables[_i];
_results.push(sortable.initTable(table));
}
return _results;
},
initTable: function (table) {
let _i, _len, _ref, i, th, ths;
if (((_ref = table.tHead) != null ? _ref.rows.length : void 0) !== 1) {
return;
}
if (table.getAttribute('data-sortable-initialized') === 'true') {
return;
}
table.setAttribute('data-sortable-initialized', 'true');
ths = table.querySelectorAll('th');
for (i = _i = 0, _len = ths.length; _i < _len; i = ++_i) {
th = ths[i];
if (th.getAttribute('data-sortable') !== 'false') {
sortable.setupClickableTH(table, th, i);
}
}
return table;
},
setupClickableTH: function (table, th, i) {
let _i, _len, _results, eventName, onClick, type;
type = sortable.getColumnType(table, i);
onClick = function (e) {
let _compare, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _m, _ref, _ref1, compare, item, newSortedDirection, position, row, rowArray, sorted, sortedDirection, tBody, ths, value;
if (e.handled !== true) {
e.handled = true;
} else {
return false;
}
sorted = this.getAttribute('data-sorted') === 'true';
sortedDirection = this.getAttribute('data-sorted-direction');
if (sorted) {
newSortedDirection = sortedDirection === 'ascending' ? 'descending' : 'ascending';
} else {
newSortedDirection = type.defaultSortDirection;
}
ths = this.parentNode.querySelectorAll('th');
for (_i = 0, _len = ths.length; _i < _len; _i++) {
th = ths[_i];
th.setAttribute('data-sorted', 'false');
th.removeAttribute('data-sorted-direction');
}
this.setAttribute('data-sorted', 'true');
this.setAttribute('data-sorted-direction', newSortedDirection);
tBody = table.tBodies[0];
rowArray = [];
if (!sorted) {
if (type.compare != null) {
_compare = type.compare;
} else {
_compare = function (a, b) {
return b - a;
};
}
compare = function (a, b) {
if (a[0] === b[0]) {
return a[2] - b[2];
}
if (type.reverse) {
return _compare(b[0], a[0]);
}
return _compare(a[0], b[0]);

};
_ref = tBody.rows;
for (position = _j = 0, _len1 = _ref.length; _j < _len1; position = ++_j) {
row = _ref[position];
value = sortable.getNodeValue(row.cells[i]);
if (type.comparator != null) {
value = type.comparator(value);
}
rowArray.push([value, row, position]);
}
rowArray.sort(compare);
for (_k = 0, _len2 = rowArray.length; _k < _len2; _k++) {
row = rowArray[_k];
tBody.appendChild(row[1]);
}
} else {
_ref1 = tBody.rows;
for (_l = 0, _len3 = _ref1.length; _l < _len3; _l++) {
item = _ref1[_l];
rowArray.push(item);
}
rowArray.reverse();
for (_m = 0, _len4 = rowArray.length; _m < _len4; _m++) {
row = rowArray[_m];
tBody.appendChild(row);
}
}
if (typeof window.CustomEvent === 'function') {
return typeof table.dispatchEvent === 'function' ? table.dispatchEvent(new CustomEvent('Sortable.sorted', {
bubbles: true
})) : void 0;
}
};
_results = [];
for (_i = 0, _len = clickEvents.length; _i < _len; _i++) {
eventName = clickEvents[_i];
_results.push(addEventListener(th, eventName, onClick));
}
return _results;
},
getColumnType: function (table, i) {
let _i, _j, _len, _len1, _ref, _ref1, _ref2, row, specified, text, type;
specified = (_ref = table.querySelectorAll('th')[i]) != null ? _ref.getAttribute('data-sortable-type') : void 0;
if (specified != null) {
return sortable.typesObject[specified];
}
_ref1 = table.tBodies[0].rows;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
row = _ref1[_i];
text = sortable.getNodeValue(row.cells[i]);
_ref2 = sortable.types;
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
type = _ref2[_j];
if (type.match(text)) {
return type;
}
}
}
return sortable.typesObject.alpha;
},
getNodeValue: function (node) {
let dataValue;
if (!node) {
return '';
}
dataValue = node.getAttribute('data-value');
if (dataValue !== null) {
return dataValue;
}
if (typeof node.innerText !== 'undefined') {
return node.innerText.replace(trimRegExp, '');
}
return node.textContent.replace(trimRegExp, '');
},
setupTypes: function (types) {
let _i, _len, _results, type;
sortable.types = types;
sortable.typesObject = {};
_results = [];
for (_i = 0, _len = types.length; _i < _len; _i++) {
type = types[_i];
_results.push(sortable.typesObject[type.name] = type);
}
return _results;
}
};

sortable.setupTypes([
{
name: 'numeric',
defaultSortDirection: 'descending',
match: function (a) {
return a.match(numberRegExp);
},
comparator: function (a) {
return parseFloat(a.replace(/[^0-9.-]/g, ''), 10) || 0;
}
}, {
name: 'date',
defaultSortDirection: 'ascending',
reverse: true,
match: function (a) {
return !isNaN(Date.parse(a));
},
comparator: function (a) {
return Date.parse(a) || 0;
}
}, {
name: 'alpha',
defaultSortDirection: 'ascending',
match: function () {
return true;
},
compare: function (a, b) {
return a.localeCompare(b);
}
}
]);

setTimeout(sortable.init, 0);

if (typeof define === 'function' && define.amd) {
define(() => {
return sortable;
});
} else if (typeof exports !== 'undefined') {
module.exports = sortable;
} else {
window.Sortable = sortable;
}

}).call(this);
49 changes: 49 additions & 0 deletions src/scss/sortable/_sortable.sass
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
=sortable
table[data-sortable]
border-collapse: collapse
border-spacing: 0

th
vertical-align: bottom
font-weight: bold

th, td
text-align: left
padding: 10px

th:not([data-sortable="false"])
-webkit-user-select: none
-moz-user-select: none
-ms-user-select: none
-o-user-select: none
user-select: none
-webkit-tap-highlight-color: rgba(0, 0, 0, 0)
-webkit-touch-callout: none
cursor: pointer

th

&:after
content: ""
visibility: hidden
display: inline-block
vertical-align: inherit
height: 0
width: 0
border-width: 5px
border-style: solid
border-color: transparent
margin-right: 1px
margin-left: 10px
float: right

&[data-sorted="true"]:after
visibility: visible

&[data-sorted-direction="descending"]:after
border-top-color: inherit
margin-top: 8px

&[data-sorted-direction="ascending"]:after
border-bottom-color: inherit
margin-top: 8px - 5px
32 changes: 32 additions & 0 deletions src/scss/sortable/sortable-theme-bootstrap.sass
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
@import sortable

+sortable

table[data-sortable].sortable-theme-bootstrap
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif
font-size: 14px
line-height: 20px
color: #333
background: #fff

thead th
border-bottom: 2px solid #e0e0e0

tbody td
border-top: 1px solid #e0e0e0

th[data-sorted="true"]
color: #3a87ad
background: #d9edf7
border-bottom-color: #bce8f1

&[data-sorted-direction="descending"]:after
border-top-color: #3a87ad

&[data-sorted-direction="ascending"]:after
border-bottom-color: #3a87ad

&.sortable-theme-bootstrap-striped

tbody > tr:nth-child(odd) > td
background-color: #f9f9f9
13 changes: 13 additions & 0 deletions src/scss/sortable/sortable-theme-dark.sass
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@import sortable

+sortable

table[data-sortable].sortable-theme-dark
color: #b9b9b9
background: #252525

tbody td
border-top: 1px solid #2e2e2e

th[data-sorted="true"]
background: #2e2e2e
51 changes: 51 additions & 0 deletions src/scss/sortable/sortable-theme-finder.sass
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
@import compass/css3
@import sortable

+sortable

table[data-sortable].sortable-theme-finder
font-family: "Lucida Grande", sans-serif
font-size: 12px
line-height: 18px
color: #000
background: #fff
border: 1px solid #cfcfcf

th, td
padding: 2px 8px

thead th
+background-image(linear-gradient(#fff 0%, #f6f6f6 50%, #f0f0f0 50%, #eee 100%))
background-color: #f0f0f0
border-bottom: 1px solid #ccc
font-weight: normal

tbody > tr:nth-child(odd) > td
background-color: #f3f6fa

th

&:after
border-width: 4px
margin-right: 0

&[data-sorted="true"]
+background-image(linear-gradient(#c5e2f6 0%, #80c1f0 50%, #b8e7f5 100%))
+background-size(28px 100%)
+box-shadow(inset 1px 0 #7eb3d3, inset -1px 0 #7eb3d3)
border-bottom-color: #7eb3d3
background-color: #78c0f0

&:first-child
+box-shadow(inset -1px 0 #7eb3d3)

&:last-child
+box-shadow(inset 1px 0 #7eb3d3)

&[data-sorted-direction="descending"]:after
border-top-color: #548ec0
margin-top: 6px

&[data-sorted-direction="ascending"]:after
border-bottom-color: #548ec0
margin-top: 6px - 4px
Loading