diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index b8ccb13c1b..0cbdab8bb3 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -433,6 +433,14 @@ EditMacro.aspx ASPXCodeBehind + + sort.aspx + ASPXCodeBehind + + + sort.aspx + ASPXCodeBehind + EditMacro.aspx @@ -793,6 +801,8 @@ + + @@ -817,6 +827,9 @@ + + + diff --git a/src/Umbraco.Web.UI/umbraco/dialogs/Sort.aspx.cs b/src/Umbraco.Web.UI/umbraco/dialogs/Sort.aspx.cs new file mode 100644 index 0000000000..2d3c846be3 --- /dev/null +++ b/src/Umbraco.Web.UI/umbraco/dialogs/Sort.aspx.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace Umbraco.Web.UI.Umbraco.Dialogs +{ + public partial class Sort : global::umbraco.cms.presentation.sort + { + } +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI/umbraco/dialogs/Sort.aspx.designer.cs b/src/Umbraco.Web.UI/umbraco/dialogs/Sort.aspx.designer.cs new file mode 100644 index 0000000000..ecfbc638bd --- /dev/null +++ b/src/Umbraco.Web.UI/umbraco/dialogs/Sort.aspx.designer.cs @@ -0,0 +1,33 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Umbraco.Web.UI.Umbraco.Dialogs { + + + public partial class Sort { + + /// + /// CssInclude1 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::ClientDependency.Core.Controls.CssInclude CssInclude1; + + /// + /// JsInclude3 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::ClientDependency.Core.Controls.JsInclude JsInclude3; + } +} diff --git a/src/Umbraco.Web.UI/umbraco/dialogs/sort.aspx b/src/Umbraco.Web.UI/umbraco/dialogs/sort.aspx index 824634ee67..430b1578fd 100644 --- a/src/Umbraco.Web.UI/umbraco/dialogs/sort.aspx +++ b/src/Umbraco.Web.UI/umbraco/dialogs/sort.aspx @@ -1,135 +1,81 @@ -<%@ Page Language="c#" MasterPageFile="../masterpages/umbracoDialog.Master"Codebehind="sort.aspx.cs" AutoEventWireup="True" Inherits="umbraco.cms.presentation.sort" %> +<%@ Page Language="c#" MasterPageFile="../masterpages/umbracoDialog.Master" CodeBehind="sort.aspx.cs" AutoEventWireup="True" Inherits="Umbraco.Web.UI.Umbraco.Dialogs.Sort" %> + +<%@ Import Namespace="System.Globalization" %> +<%@ Import Namespace="Umbraco.Core.IO" %> <%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %> <%@ Register TagPrefix="umb" Namespace="ClientDependency.Core.Controls" Assembly="ClientDependency.Core" %> - - - - - - + + + + + - - + - + - +
+ + +

+ <%= umbraco.ui.Text("sort", "sortHelp") %> +

-
- -

- <%= umbraco.ui.Text("sort", "sortHelp") %> -

- -
- - - - - - - - - - - - - - - - -
NameCreation dateSort order
-
-
+
+ + + + + + + + + + + +
NameCreation dateSort order
+
+ -
-

- " /> - or <%=umbraco.ui.Text("general", "cancel", this.getUser())%> -

-
- - - + sortDialog.init(); + }); + + + - \ No newline at end of file diff --git a/src/Umbraco.Web.UI/umbraco_client/Dialogs/SortDialog.css b/src/Umbraco.Web.UI/umbraco_client/Dialogs/SortDialog.css new file mode 100644 index 0000000000..99345dc472 --- /dev/null +++ b/src/Umbraco.Web.UI/umbraco_client/Dialogs/SortDialog.css @@ -0,0 +1,59 @@ +#sortableFrame +{ + height: 270px; + overflow: auto; + border: 1px solid #ccc; +} + +#sortableNodes +{ + padding: 4px; + display: block; + border-spacing:0; + border-collapse:collapse; +} + + #sortableNodes thead tr th + { + border-bottom: 1px solid #ccc; + padding: 4px; + padding-right: 25px; + background-image: url(../tableSorting/img/bg.gif); + cursor: pointer; + font-weight: bold; + background-repeat: no-repeat; + background-position: center right; + } + + #sortableNodes thead tr th.headerSortDown + { + background-image: url(../tableSorting/img/desc.gif); + } + + #sortableNodes thead tr th.headerSortUp + { + background-image: url(../tableSorting/img/asc.gif); + } + + #sortableNodes tbody tr td + { + border-bottom: 1px solid #efefef; + } + + #sortableNodes td + { + padding: 4px; + cursor: move; + } + +tr.tDnD_whileDrag, tr.tDnD_whileDrag td +{ + background: #dcecf3; + border-color: #a8d8eb !Important; + margin-top: 20px; +} + +#sortableNodes .nowrap +{ + white-space: nowrap; +} diff --git a/src/Umbraco.Web.UI/umbraco_client/Dialogs/SortDialog.js b/src/Umbraco.Web.UI/umbraco_client/Dialogs/SortDialog.js new file mode 100644 index 0000000000..75a84292c3 --- /dev/null +++ b/src/Umbraco.Web.UI/umbraco_client/Dialogs/SortDialog.js @@ -0,0 +1,121 @@ +Umbraco.Sys.registerNamespace("Umbraco.Dialogs"); + +(function ($) { + + + Umbraco.Dialogs.SortDialog = base2.Base.extend({ + //private methods/variables + _opts: null, + + _setupTableSorter: function () { + //adds a custom sorter to the tablesorter based on the current cultures date/time format + $.tablesorter.addParser({ + // use a unique id + id: 'cultureDateParser', + is: function(s, table, cell) { + //don't auto-detect this parser + return false; + }, + format: function(s, table, cell, cellIndex) { + var c = table.config; + + s = s.replace(/\-/g, "/"); + //all of these basically transform the string into year-month-day since that + //is what JS understands when creating a Date object + if (c.dateFormat.indexOf("dd/MM/yyyy") == 0 || c.dateFormat.indexOf("dd-MM-yyyy") == 0) { + s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3-$2-$1"); + } + else if (c.dateFormat.indexOf("dd/MM/yy") == 0 || c.dateFormat.indexOf("dd-MM-yy") == 0) { + s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/, "$3-$2-$1"); + } + else if (c.dateFormat.indexOf("MM/dd/yyyy") == 0 || c.dateFormat.indexOf("MM-dd-yyyy") == 0) { + s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3-$1-$2"); + } + else if (c.dateFormat.indexOf("MM/dd/yy") == 0 || c.dateFormat.indexOf("MM-dd-yy") == 0) { + s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/, "$3-$1-$2"); + } + return $.tablesorter.formatFloat(new Date(s).getTime()); + }, + // set the type to either numeric or text (text uses a natural sort function + // so it will work for everything, but numeric is faster for numbers + type: 'numeric' + }); + }, + + _saveSort: function() { + var rows = jQuery('#sortableNodes tbody tr'); + var sortOrder = ""; + + $.each(rows, function () { + sortOrder += $(this).attr("id").replace("node_", "") + ","; + }); + + document.getElementById("sortingDone").style.display = 'none'; + document.getElementById("sortArea").style.display = 'none'; + + document.getElementById("loading").style.display = 'block'; + + var self = this; + + $.ajax({ + type: "POST", + url: self._opts.serviceUrl, + data: '{ "ParentId": ' + parseInt(self._opts.currentId) + ', "SortOrder": "' + sortOrder + '"}', + contentType: "application/json; charset=utf-8", + dataType: "json", + success: function(msg) { + self._showConfirm(); + } + }); + }, + + _showConfirm: function() { + document.getElementById("loading").style.display = 'none'; + document.getElementById("sortingDone").style.display = 'block'; + UmbClientMgr.mainTree().reloadActionNode(); + }, + + // Constructor + constructor: function (opts) { + // Merge options with default + this._opts = $.extend({ + // Default options go here + }, opts); + + this._setupTableSorter(); + }, + + //public methods/variables + + init: function () { + var self = this; + + //create the sorter + $("#sortableNodes").tablesorter({ + dateFormat: self._opts.dateTimeFormat, + headers: { + 0: { sorter: "text" }, + 1: { sorter: "cultureDateParser" }, //ensure to set our custom parser here + 2: { sorter: "numeric" } + } + }); + + //setup the drag/drop sorting + $("#sortableNodes").tableDnD({ containment: jQuery("#sortableFrame") }); + + //wire up the submit button + self._opts.submitButton.click(function() { + self._saveSort(); + }); + + //wire up the close button + self._opts.closeWindowButton.click(function () { + UmbClientMgr.closeModalWindow(); + }); + }, + + }); + + + +})(jQuery); \ No newline at end of file diff --git a/src/Umbraco.Web.UI/umbraco_client/tablesorting/jquery.tablesorter.min.js b/src/Umbraco.Web.UI/umbraco_client/tablesorting/jquery.tablesorter.min.js new file mode 100644 index 0000000000..b8605df1e7 --- /dev/null +++ b/src/Umbraco.Web.UI/umbraco_client/tablesorting/jquery.tablesorter.min.js @@ -0,0 +1,4 @@ + +(function($){$.extend({tablesorter:new +function(){var parsers=[],widgets=[];this.defaults={cssHeader:"header",cssAsc:"headerSortUp",cssDesc:"headerSortDown",cssChildRow:"expand-child",sortInitialOrder:"asc",sortMultiSortKey:"shiftKey",sortForce:null,sortAppend:null,sortLocaleCompare:true,textExtraction:"simple",parsers:{},widgets:[],widgetZebra:{css:["even","odd"]},headers:{},widthFixed:false,cancelSelection:true,sortList:[],headerList:[],dateFormat:"us",decimal:'/\.|\,/g',onRenderHeader:null,selectorHeaders:'thead th',debug:false};function benchmark(s,d){log(s+","+(new Date().getTime()-d.getTime())+"ms");}this.benchmark=benchmark;function log(s){if(typeof console!="undefined"&&typeof console.debug!="undefined"){console.log(s);}else{alert(s);}}function buildParserCache(table,$headers){if(table.config.debug){var parsersDebug="";}if(table.tBodies.length==0)return;var rows=table.tBodies[0].rows;if(rows[0]){var list=[],cells=rows[0].cells,l=cells.length;for(var i=0;i1){arr=arr.concat(checkCellColSpan(table,headerArr,row++));}else{if(table.tHead.length==1||(cell.rowSpan>1||!r[row+1])){arr.push(cell);}}}return arr;};function checkHeaderMetadata(cell){if(($.metadata)&&($(cell).metadata().sorter===false)){return true;};return false;}function checkHeaderOptions(table,i){if((table.config.headers[i])&&(table.config.headers[i].sorter===false)){return true;};return false;}function checkHeaderOptionsSortingLocked(table,i){if((table.config.headers[i])&&(table.config.headers[i].lockedOrder))return table.config.headers[i].lockedOrder;return false;}function applyWidget(table){var c=table.config.widgets;var l=c.length;for(var i=0;i');$("tr:first td",table.tBodies[0]).each(function(){colgroup.append($('').css('width',$(this).width()));});$(table).prepend(colgroup);};}function updateHeaderSortCount(table,sortList){var c=table.config,l=sortList.length;for(var i=0;i b["+i+"]) ? 1 : 0));";};function makeSortTextDesc(i){return"((b["+i+"] < a["+i+"]) ? -1 : ((b["+i+"] > a["+i+"]) ? 1 : 0));";};function makeSortNumeric(i){return"a["+i+"]-b["+i+"];";};function makeSortNumericDesc(i){return"b["+i+"]-a["+i+"];";};function sortText(a,b){if(table.config.sortLocaleCompare)return a.localeCompare(b);return((ab)?1:0));};function sortTextDesc(a,b){if(table.config.sortLocaleCompare)return b.localeCompare(a);return((ba)?1:0));};function sortNumeric(a,b){return a-b;};function sortNumericDesc(a,b){return b-a;};function getCachedSortType(parsers,i){return parsers[i].type;};this.construct=function(settings){return this.each(function(){if(!this.tHead||!this.tBodies)return;var $this,$document,$headers,cache,config,shiftDown=0,sortOrder;this.config={};config=$.extend(this.config,$.tablesorter.defaults,settings);$this=$(this);$.data(this,"tablesorter",config);$headers=buildHeaders(this);this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);var sortCSS=[config.cssDesc,config.cssAsc];fixColumnWidth(this);$headers.click(function(e){var totalRows=($this[0].tBodies[0]&&$this[0].tBodies[0].rows.length)||0;if(!this.sortDisabled&&totalRows>0){$this.trigger("sortStart");var $cell=$(this);var i=this.column;this.order=this.count++%2;if(this.lockedOrder)this.order=this.lockedOrder;if(!e[config.sortMultiSortKey]){config.sortList=[];if(config.sortForce!=null){var a=config.sortForce;for(var j=0;j0){$this.trigger("sorton",[config.sortList]);}applyWidget(this);});};this.addParser=function(parser){var l=parsers.length,a=true;for(var i=0;i 1) { arr = arr.concat(checkCellColSpan(table, headerArr, row++)); } else { if (table.tHead.length == 1 || (cell.rowSpan > 1 || !r[row + 1])) { arr.push(cell); } } } return arr; }; function checkHeaderMetadata(cell) { if (($.metadata) && ($(cell).metadata().sorter === false)) { return true; }; return false; } function checkHeaderOptions(table, i) { if ((table.config.headers[i]) && (table.config.headers[i].sorter === false)) { return true; }; return false; } function applyWidget(table) { var c = table.config.widgets; var l = c.length; for (var i = 0; i < l; i++) { getWidgetById(c[i]).format(table); } } function getWidgetById(name) { var l = widgets.length; for (var i = 0; i < l; i++) { if (widgets[i].id.toLowerCase() == name.toLowerCase()) { return widgets[i]; } } }; function formatSortingOrder(v) { if (typeof (v) != "Number") { i = (v.toLowerCase() == "desc") ? 1 : 0; } else { i = (v == (0 || 1)) ? v : 0; } return i; } function isValueInArray(v, a) { var l = a.length; for (var i = 0; i < l; i++) { if (a[i][0] == v) { return true; } } return false; } function setHeadersCss(table, $headers, list, css) { $headers.removeClass(css[0]).removeClass(css[1]); var h = []; $headers.each(function(offset) { if (!this.sortDisabled) { h[this.column] = $(this); } }); var l = list.length; for (var i = 0; i < l; i++) { h[list[i][0]].addClass(css[list[i][1]]); } } function fixColumnWidth(table, $headers) { var c = table.config; if (c.widthFixed) { var colgroup = $(''); $("tr:first td", table.tBodies[0]).each(function() { colgroup.append($('').css('width', $(this).width())); }); $(table).prepend(colgroup); }; } function updateHeaderSortCount(table, sortList) { var c = table.config, l = sortList.length; for (var i = 0; i < l; i++) { var s = sortList[i], o = c.headerList[s[0]]; o.count = s[1]; o.count++; } } function multisort(table, sortList, cache) { if (table.config.debug) { var sortTime = new Date(); } var dynamicExp = "var sortWrapper = function(a,b) {", l = sortList.length; for (var i = 0; i < l; i++) { var c = sortList[i][0]; var order = sortList[i][1]; var s = (getCachedSortType(table.config.parsers, c) == "text") ? ((order == 0) ? "sortText" : "sortTextDesc") : ((order == 0) ? "sortNumeric" : "sortNumericDesc"); var e = "e" + i; dynamicExp += "var " + e + " = " + s + "(a[" + c + "],b[" + c + "]); "; dynamicExp += "if(" + e + ") { return " + e + "; } "; dynamicExp += "else { "; } var orgOrderCol = cache.normalized[0].length - 1; dynamicExp += "return a[" + orgOrderCol + "]-b[" + orgOrderCol + "];"; for (var i = 0; i < l; i++) { dynamicExp += "}; "; } dynamicExp += "return 0; "; dynamicExp += "}; "; eval(dynamicExp); cache.normalized.sort(sortWrapper); if (table.config.debug) { benchmark("Sorting on " + sortList.toString() + " and dir " + order + " time:", sortTime); } return cache; }; function sortText(a, b) { return ((a < b) ? -1 : ((a > b) ? 1 : 0)); }; function sortTextDesc(a, b) { return ((b < a) ? -1 : ((b > a) ? 1 : 0)); }; function sortNumeric(a, b) { return a - b; }; function sortNumericDesc(a, b) { return b - a; }; function getCachedSortType(parsers, i) { return parsers[i].type; }; this.construct = function(settings) { return this.each(function() { if (!this.tHead || !this.tBodies) return; var $this, $document, $headers, cache, config, shiftDown = 0, sortOrder; this.config = {}; config = $.extend(this.config, $.tablesorter.defaults, settings); $this = $(this); $headers = buildHeaders(this); this.config.parsers = buildParserCache(this, $headers); cache = buildCache(this); var sortCSS = [config.cssDesc, config.cssAsc]; fixColumnWidth(this); $headers.click(function(e) { $this.trigger("sortStart"); var totalRows = ($this[0].tBodies[0] && $this[0].tBodies[0].rows.length) || 0; if (!this.sortDisabled && totalRows > 0) { var $cell = $(this); var i = this.column; this.order = this.count++ % 2; if (!e[config.sortMultiSortKey]) { config.sortList = []; if (config.sortForce != null) { var a = config.sortForce; for (var j = 0; j < a.length; j++) { if (a[j][0] != i) { config.sortList.push(a[j]); } } } config.sortList.push([i, this.order]); } else { if (isValueInArray(i, config.sortList)) { for (var j = 0; j < config.sortList.length; j++) { var s = config.sortList[j], o = config.headerList[s[0]]; if (s[0] == i) { o.count = s[1]; o.count++; s[1] = o.count % 2; } } } else { config.sortList.push([i, this.order]); } }; setTimeout(function() { setHeadersCss($this[0], $headers, config.sortList, sortCSS); appendToTable($this[0], multisort($this[0], config.sortList, cache)); }, 1); return false; } }).mousedown(function() { if (config.cancelSelection) { this.onselectstart = function() { return false }; return false; } }); $this.bind("update", function() { this.config.parsers = buildParserCache(this, $headers); cache = buildCache(this); }).bind("sorton", function(e, list) { $(this).trigger("sortStart"); config.sortList = list; var sortList = config.sortList; updateHeaderSortCount(this, sortList); setHeadersCss(this, $headers, sortList, sortCSS); appendToTable(this, multisort(this, sortList, cache)); }).bind("appendCache", function() { appendToTable(this, cache); }).bind("applyWidgetId", function(e, id) { getWidgetById(id).format(this); }).bind("applyWidgets", function() { applyWidget(this); }); if ($.metadata && ($(this).metadata() && $(this).metadata().sortlist)) { config.sortList = $(this).metadata().sortlist; } if (config.sortList.length > 0) { $this.trigger("sorton", [config.sortList]); } applyWidget(this); }); }; this.addParser = function(parser) { var l = parsers.length, a = true; for (var i = 0; i < l; i++) { if (parsers[i].id.toLowerCase() == parser.id.toLowerCase()) { a = false; } } if (a) { parsers.push(parser); }; }; this.addWidget = function(widget) { widgets.push(widget); }; this.formatFloat = function(s) { var i = parseFloat(s); return (isNaN(i)) ? 0 : i; }; this.formatInt = function(s) { var i = parseInt(s); return (isNaN(i)) ? 0 : i; }; this.isDigit = function(s, config) { var DECIMAL = '\\' + config.decimal; var exp = '/(^[+]?0(' + DECIMAL + '0+)?$)|(^([-+]?[1-9][0-9]*)$)|(^([-+]?((0?|[1-9][0-9]*)' + DECIMAL + '(0*[1-9][0-9]*)))$)|(^[-+]?[1-9]+[0-9]*' + DECIMAL + '0+$)/'; return RegExp(exp).test($.trim(s)); }; this.clearTableBody = function(table) { if ($.browser.msie) { function empty() { while (this.firstChild) this.removeChild(this.firstChild); } empty.apply(table.tBodies[0]); } else { table.tBodies[0].innerHTML = ""; } }; } }); $.fn.extend({ tablesorter: $.tablesorter.construct }); var ts = $.tablesorter; ts.addParser({ id: "text", is: function(s) { return true; }, format: function(s) { return $.trim(s.toLowerCase()); }, type: "text" }); ts.addParser({ id: "digit", is: function(s, table) { var c = table.config; return $.tablesorter.isDigit(s, c); }, format: function(s) { return $.tablesorter.formatFloat(s); }, type: "numeric" }); ts.addParser({ id: "currency", is: function(s) { return /^[£$€?.]/.test(s); }, format: function(s) { return $.tablesorter.formatFloat(s.replace(new RegExp(/[^0-9.]/g), "")); }, type: "numeric" }); ts.addParser({ id: "ipAddress", is: function(s) { return /^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s); }, format: function(s) { var a = s.split("."), r = "", l = a.length; for (var i = 0; i < l; i++) { var item = a[i]; if (item.length == 2) { r += "0" + item; } else { r += item; } } return $.tablesorter.formatFloat(r); }, type: "numeric" }); ts.addParser({ id: "url", is: function(s) { return /^(https?|ftp|file):\/\/$/.test(s); }, format: function(s) { return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//), '')); }, type: "text" }); ts.addParser({ id: "isoDate", is: function(s) { return /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s); }, format: function(s) { return $.tablesorter.formatFloat((s != "") ? new Date(s.replace(new RegExp(/-/g), "/")).getTime() : "0"); }, type: "numeric" }); ts.addParser({ id: "percent", is: function(s) { return /\%$/.test($.trim(s)); }, format: function(s) { return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g), "")); }, type: "numeric" }); ts.addParser({ id: "usLongDate", is: function(s) { return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/)); }, format: function(s) { return $.tablesorter.formatFloat(new Date(s).getTime()); }, type: "numeric" }); ts.addParser({ id: "shortDate", is: function(s) { return /\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s); }, format: function(s, table) { var c = table.config; s = s.replace(/\-/g, "/"); if (c.dateFormat == "us") { s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3/$1/$2"); } else if (c.dateFormat == "uk") { s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3/$2/$1"); } else if (c.dateFormat == "dd/mm/yy" || c.dateFormat == "dd-mm-yy") { s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/, "$1/$2/$3"); } return $.tablesorter.formatFloat(new Date(s).getTime()); }, type: "numeric" }); ts.addParser({ id: "time", is: function(s) { return /^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s); }, format: function(s) { return $.tablesorter.formatFloat(new Date("2000/01/01 " + s).getTime()); }, type: "numeric" }); ts.addParser({ id: "metadata", is: function(s) { return false; }, format: function(s, table, cell) { var c = table.config, p = (!c.parserMetadataName) ? 'sortValue' : c.parserMetadataName; return $(cell).metadata()[p]; }, type: "numeric" }); ts.addWidget({ id: "zebra", format: function(table) { if (table.config.debug) { var time = new Date(); } $("tr:visible", table.tBodies[0]).filter(':even').removeClass(table.config.widgetZebra.css[1]).addClass(table.config.widgetZebra.css[0]).end().filter(':odd').removeClass(table.config.widgetZebra.css[0]).addClass(table.config.widgetZebra.css[1]); if (table.config.debug) { $.tablesorter.benchmark("Applying Zebra widget", time); } } }); })(jQuery); \ No newline at end of file +(function($) { + $.extend({ + tablesorter: new function() { + var parsers = [], widgets = []; + this.defaults = { cssHeader: "header", cssAsc: "headerSortUp", cssDesc: "headerSortDown", sortInitialOrder: "asc", sortMultiSortKey: "shiftKey", sortForce: null, sortAppend: null, textExtraction: "simple", parsers: {}, widgets: [], widgetZebra: { css: ["even", "odd"] }, headers: {}, widthFixed: false, cancelSelection: true, sortList: [], headerList: [], dateFormat: "us", decimal: '.', debug: false }; + + function benchmark(s, d) { log(s + "," + (new Date().getTime() - d.getTime()) + "ms"); } + + this.benchmark = benchmark; + + function log(s) { + if (typeof console != "undefined" && typeof console.debug != "undefined") { + console.log(s); + } + else { + alert(s); + } + } + + function buildParserCache(table, $headers) { + if (table.config.debug) { + var parsersDebug = ""; + } + var rows = table.tBodies[0].rows; + if (table.tBodies[0].rows[0]) { + var list = [], cells = rows[0].cells, l = cells.length; + for (var i = 0; i < l; i++) { + var p = false; + if ($.metadata && ($($headers[i]).metadata() && $($headers[i]).metadata().sorter)) { + p = getParserById($($headers[i]).metadata().sorter); + } + else if ((table.config.headers[i] && table.config.headers[i].sorter)) { + p = getParserById(table.config.headers[i].sorter); + } + if (!p) { + p = detectParserForColumn(table, cells[i]); + } + if (table.config.debug) { + parsersDebug += "column:" + i + " parser:" + p.id + "\n"; + } + list.push(p); + } + } + if (table.config.debug) { + log(parsersDebug); + } + return list; + } + + ; + + function detectParserForColumn(table, node) { + var l = parsers.length; + for (var i = 1; i < l; i++) { + if (parsers[i].is($.trim(getElementText(table.config, node)), table, node)) { + return parsers[i]; + } + } + return parsers[0]; + } + + function getParserById(name) { + var l = parsers.length; + for (var i = 0; i < l; i++) { + if (parsers[i].id.toLowerCase() == name.toLowerCase()) { + return parsers[i]; + } + } + return false; + } + + function buildCache(table) { + if (table.config.debug) { + var cacheTime = new Date(); + } + var totalRows = (table.tBodies[0] && table.tBodies[0].rows.length) || 0, totalCells = (table.tBodies[0].rows[0] && table.tBodies[0].rows[0].cells.length) || 0, parsers = table.config.parsers, cache = { row: [], normalized: [] }; + for (var i = 0; i < totalRows; ++i) { + var c = table.tBodies[0].rows[i], cols = []; + cache.row.push($(c)); + for (var j = 0; j < totalCells; ++j) { + cols.push(parsers[j].format(getElementText(table.config, c.cells[j]), table, c.cells[j])); + } + cols.push(i); + cache.normalized.push(cols); + cols = null; + } + ; + if (table.config.debug) { + benchmark("Building cache for " + totalRows + " rows:", cacheTime); + } + return cache; + } + + ; + + function getElementText(config, node) { + if (!node) return ""; + var t = ""; + if (config.textExtraction == "simple") { + if (node.childNodes[0] && node.childNodes[0].hasChildNodes()) { + t = node.childNodes[0].innerHTML; + } + else { + t = node.innerHTML; + } + } + else { + if (typeof(config.textExtraction) == "function") { + t = config.textExtraction(node); + } + else { + t = $(node).text(); + } + } + return t; + } + + function appendToTable(table, cache) { + if (table.config.debug) { + var appendTime = new Date(); + } + var c = cache, r = c.row, n = c.normalized, totalRows = n.length, checkCell = (n[0].length - 1), tableBody = $(table.tBodies[0]), rows = []; + for (var i = 0; i < totalRows; i++) { + rows.push(r[n[i][checkCell]]); + if (!table.config.appender) { + var o = r[n[i][checkCell]]; + var l = o.length; + for (var j = 0; j < l; j++) { + tableBody[0].appendChild(o[j]); + } + } + } + if (table.config.appender) { + table.config.appender(table, rows); + } + rows = null; + if (table.config.debug) { + benchmark("Rebuilt table:", appendTime); + } + applyWidget(table); + setTimeout(function() { $(table).trigger("sortEnd"); }, 0); + } + + ; + + function buildHeaders(table) { + if (table.config.debug) { + var time = new Date(); + } + var meta = ($.metadata) ? true : false, tableHeadersRows = []; + for (var i = 0; i < table.tHead.rows.length; i++) { + tableHeadersRows[i] = 0; + } + ; + $tableHeaders = $("thead th", table); + $tableHeaders.each(function(index) { + this.count = 0; + this.column = index; + this.order = formatSortingOrder(table.config.sortInitialOrder); + if (checkHeaderMetadata(this) || checkHeaderOptions(table, index)) this.sortDisabled = true; + if (!this.sortDisabled) { + $(this).addClass(table.config.cssHeader); + } + table.config.headerList[index] = this; + }); + if (table.config.debug) { + benchmark("Built headers:", time); + log($tableHeaders); + } + return $tableHeaders; + } + + ; + + function checkCellColSpan(table, rows, row) { + var arr = [], r = table.tHead.rows, c = r[row].cells; + for (var i = 0; i < c.length; i++) { + var cell = c[i]; + if (cell.colSpan > 1) { + arr = arr.concat(checkCellColSpan(table, headerArr, row++)); + } + else { + if (table.tHead.length == 1 || (cell.rowSpan > 1 || !r[row + 1])) { + arr.push(cell); + } + } + } + return arr; + } + + ; + + function checkHeaderMetadata(cell) { + if (($.metadata) && ($(cell).metadata().sorter === false)) { + return true; + } + ; + return false; + } + + function checkHeaderOptions(table, i) { + if ((table.config.headers[i]) && (table.config.headers[i].sorter === false)) { + return true; + } + ; + return false; + } + + function applyWidget(table) { + var c = table.config.widgets; + var l = c.length; + for (var i = 0; i < l; i++) { + getWidgetById(c[i]).format(table); + } + } + + function getWidgetById(name) { + var l = widgets.length; + for (var i = 0; i < l; i++) { + if (widgets[i].id.toLowerCase() == name.toLowerCase()) { + return widgets[i]; + } + } + } + + ; + + function formatSortingOrder(v) { + var i; + if (typeof v != "number") { + i = (v.toLowerCase() == "desc") ? 1 : 0; + } + else { + i = (v == (0 || 1)) ? v : 0; + } + return i; + } + + function isValueInArray(v, a) { + var l = a.length; + for (var i = 0; i < l; i++) { + if (a[i][0] == v) { + return true; + } + } + return false; + } + + function setHeadersCss(table, $headers, list, css) { + $headers.removeClass(css[0]).removeClass(css[1]); + var h = []; + $headers.each(function(offset) { + if (!this.sortDisabled) { + h[this.column] = $(this); + } + }); + var l = list.length; + for (var i = 0; i < l; i++) { + h[list[i][0]].addClass(css[list[i][1]]); + } + } + + function fixColumnWidth(table, $headers) { + var c = table.config; + if (c.widthFixed) { + var colgroup = $(''); + $("tr:first td", table.tBodies[0]).each(function() { colgroup.append($('').css('width', $(this).width())); }); + $(table).prepend(colgroup); + } + ; + } + + function updateHeaderSortCount(table, sortList) { + var c = table.config, l = sortList.length; + for (var i = 0; i < l; i++) { + var s = sortList[i], o = c.headerList[s[0]]; + o.count = s[1]; + o.count++; + } + } + + function multisort(table, sortList, cache) { + if (table.config.debug) { + var sortTime = new Date(); + } + var dynamicExp = "var sortWrapper = function(a,b) {", l = sortList.length; + for (var i = 0; i < l; i++) { + var c = sortList[i][0]; + var order = sortList[i][1]; + var s = (getCachedSortType(table.config.parsers, c) == "text") ? ((order == 0) ? "sortText" : "sortTextDesc") : ((order == 0) ? "sortNumeric" : "sortNumericDesc"); + var e = "e" + i; + dynamicExp += "var " + e + " = " + s + "(a[" + c + "],b[" + c + "]); "; + dynamicExp += "if(" + e + ") { return " + e + "; } "; + dynamicExp += "else { "; + } + var orgOrderCol = cache.normalized[0].length - 1; + dynamicExp += "return a[" + orgOrderCol + "]-b[" + orgOrderCol + "];"; + for (var i = 0; i < l; i++) { + dynamicExp += "}; "; + } + dynamicExp += "return 0; "; + dynamicExp += "}; "; + eval(dynamicExp); + cache.normalized.sort(sortWrapper); + if (table.config.debug) { + benchmark("Sorting on " + sortList.toString() + " and dir " + order + " time:", sortTime); + } + return cache; + } + + ; + + function sortText(a, b) { return ((a < b) ? -1 : ((a > b) ? 1 : 0)); } + + ; + + function sortTextDesc(a, b) { return ((b < a) ? -1 : ((b > a) ? 1 : 0)); } + + ; + + function sortNumeric(a, b) { return a - b; } + + ; + + function sortNumericDesc(a, b) { return b - a; } + + ; + + function getCachedSortType(parsers, i) { return parsers[i].type; } + + ; + this.construct = function(settings) { + return this.each(function() { + if (!this.tHead || !this.tBodies) return; + var $this, $document, $headers, cache, config, shiftDown = 0, sortOrder; + this.config = {}; + config = $.extend(this.config, $.tablesorter.defaults, settings); + $this = $(this); + $headers = buildHeaders(this); + this.config.parsers = buildParserCache(this, $headers); + cache = buildCache(this); + var sortCSS = [config.cssDesc, config.cssAsc]; + fixColumnWidth(this); + $headers.click(function(e) { + $this.trigger("sortStart"); + var totalRows = ($this[0].tBodies[0] && $this[0].tBodies[0].rows.length) || 0; + if (!this.sortDisabled && totalRows > 0) { + var $cell = $(this); + var i = this.column; + this.order = this.count++ % 2; + if (!e[config.sortMultiSortKey]) { + config.sortList = []; + if (config.sortForce != null) { + var a = config.sortForce; + for (var j = 0; j < a.length; j++) { + if (a[j][0] != i) { + config.sortList.push(a[j]); + } + } + } + config.sortList.push([i, this.order]); + } + else { + if (isValueInArray(i, config.sortList)) { + for (var j = 0; j < config.sortList.length; j++) { + var s = config.sortList[j], o = config.headerList[s[0]]; + if (s[0] == i) { + o.count = s[1]; + o.count++; + s[1] = o.count % 2; + } + } + } + else { + config.sortList.push([i, this.order]); + } + } + ; + setTimeout(function() { + setHeadersCss($this[0], $headers, config.sortList, sortCSS); + appendToTable($this[0], multisort($this[0], config.sortList, cache)); + }, 1); + return false; + } + }).mousedown(function() { + if (config.cancelSelection) { + this.onselectstart = function() { return false }; + return false; + } + }); + $this.bind("update", function() { + this.config.parsers = buildParserCache(this, $headers); + cache = buildCache(this); + }).bind("sorton", function(e, list) { + $(this).trigger("sortStart"); + config.sortList = list; + var sortList = config.sortList; + updateHeaderSortCount(this, sortList); + setHeadersCss(this, $headers, sortList, sortCSS); + appendToTable(this, multisort(this, sortList, cache)); + }).bind("appendCache", function() { appendToTable(this, cache); }).bind("applyWidgetId", function(e, id) { getWidgetById(id).format(this); }).bind("applyWidgets", function() { applyWidget(this); }); + if ($.metadata && ($(this).metadata() && $(this).metadata().sortlist)) { + config.sortList = $(this).metadata().sortlist; + } + if (config.sortList.length > 0) { + $this.trigger("sorton", [config.sortList]); + } + applyWidget(this); + }); + }; + this.addParser = function(parser) { + var l = parsers.length, a = true; + for (var i = 0; i < l; i++) { + if (parsers[i].id.toLowerCase() == parser.id.toLowerCase()) { + a = false; + } + } + if (a) { + parsers.push(parser); + } + ; + }; + this.addWidget = function(widget) { widgets.push(widget); }; + this.formatFloat = function(s) { + var i = parseFloat(s); + return (isNaN(i)) ? 0 : i; + }; + this.formatInt = function(s) { + var i = parseInt(s); + return (isNaN(i)) ? 0 : i; + }; + this.isDigit = function(s, config) { + var DECIMAL = '\\' + config.decimal; + var exp = '/(^[+]?0(' + DECIMAL + '0+)?$)|(^([-+]?[1-9][0-9]*)$)|(^([-+]?((0?|[1-9][0-9]*)' + DECIMAL + '(0*[1-9][0-9]*)))$)|(^[-+]?[1-9]+[0-9]*' + DECIMAL + '0+$)/'; + return RegExp(exp).test($.trim(s)); + }; + this.clearTableBody = function(table) { + if ($.browser.msie) { + + function empty() { while (this.firstChild) this.removeChild(this.firstChild); } + + empty.apply(table.tBodies[0]); + } + else { + table.tBodies[0].innerHTML = ""; + } + }; + } + }); + $.fn.extend({ tablesorter: $.tablesorter.construct }); + var ts = $.tablesorter; + ts.addParser({ id: "text", is: function(s) { return true; }, format: function(s) { return $.trim(s.toLowerCase()); }, type: "text" }); + ts.addParser({ + id: "digit", + is: function(s, table) { + var c = table.config; + return $.tablesorter.isDigit(s, c); + }, + format: function(s) { return $.tablesorter.formatFloat(s); }, + type: "numeric" + }); + ts.addParser({ id: "currency", is: function(s) { return /^[£$€?.]/.test(s); }, format: function(s) { return $.tablesorter.formatFloat(s.replace(new RegExp(/[^0-9.]/g), "")); }, type: "numeric" }); + ts.addParser({ + id: "ipAddress", is: function(s) { return /^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s); }, + format: function(s) { + var a = s.split("."), r = "", l = a.length; + for (var i = 0; i < l; i++) { + var item = a[i]; + if (item.length == 2) { + r += "0" + item; + } + else { + r += item; + } + } + return $.tablesorter.formatFloat(r); + }, + type: "numeric" + }); + ts.addParser({ id: "url", is: function(s) { return /^(https?|ftp|file):\/\/$/.test(s); }, format: function(s) { return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//), '')); }, type: "text" }); + ts.addParser({ id: "isoDate", is: function(s) { return /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s); }, format: function(s) { return $.tablesorter.formatFloat((s != "") ? new Date(s.replace(new RegExp(/-/g), "/")).getTime() : "0"); }, type: "numeric" }); + ts.addParser({ id: "percent", is: function(s) { return /\%$/.test($.trim(s)); }, format: function(s) { return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g), "")); }, type: "numeric" }); + ts.addParser({ id: "usLongDate", is: function(s) { return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/)); }, format: function(s) { return $.tablesorter.formatFloat(new Date(s).getTime()); }, type: "numeric" }); + ts.addParser({ + id: "shortDate", is: function(s) { return /\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s); }, + format: function(s, table) { + var c = table.config; + s = s.replace(/\-/g, "/"); + if (c.dateFormat == "us") { + s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3/$1/$2"); + } + else if (c.dateFormat == "uk") { + s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3/$2/$1"); + } + else if (c.dateFormat == "dd/mm/yy" || c.dateFormat == "dd-mm-yy") { + s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/, "$1/$2/$3"); + } + return $.tablesorter.formatFloat(new Date(s).getTime()); + }, + type: "numeric" + }); + ts.addParser({ id: "time", is: function(s) { return /^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s); }, format: function(s) { return $.tablesorter.formatFloat(new Date("2000/01/01 " + s).getTime()); }, type: "numeric" }); + ts.addParser({ + id: "metadata", is: function(s) { return false; }, + format: function(s, table, cell) { + var c = table.config, p = (!c.parserMetadataName) ? 'sortValue' : c.parserMetadataName; + return $(cell).metadata()[p]; + }, + type: "numeric" + }); + ts.addWidget({ + id: "zebra", + format: function(table) { + if (table.config.debug) { + var time = new Date(); + } + $("tr:visible", table.tBodies[0]).filter(':even').removeClass(table.config.widgetZebra.css[1]).addClass(table.config.widgetZebra.css[0]).end().filter(':odd').removeClass(table.config.widgetZebra.css[0]).addClass(table.config.widgetZebra.css[1]); + if (table.config.debug) { + $.tablesorter.benchmark("Applying Zebra widget", time); + } + } + }); +})(jQuery); \ No newline at end of file diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 119b0b0f25..0e32c19aec 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -485,6 +485,9 @@ ASPXCodeBehind + + ASPXCodeBehind + ASPXCodeBehind @@ -1500,13 +1503,6 @@ EditStyleSheetProperty.aspx - - sort.aspx - ASPXCodeBehind - - - sort.aspx - @@ -1976,9 +1972,6 @@ ASPXCodeBehind - - ASPXCodeBehind - diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sort.aspx b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sort.aspx deleted file mode 100644 index 824634ee67..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sort.aspx +++ /dev/null @@ -1,135 +0,0 @@ -<%@ Page Language="c#" MasterPageFile="../masterpages/umbracoDialog.Master"Codebehind="sort.aspx.cs" AutoEventWireup="True" Inherits="umbraco.cms.presentation.sort" %> -<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %> -<%@ Register TagPrefix="umb" Namespace="ClientDependency.Core.Controls" Assembly="ClientDependency.Core" %> - - - - - - - - - - - - - - - - - - - -
- -

- <%= umbraco.ui.Text("sort", "sortHelp") %> -

- -
- - - - - - - - - - - - - - - - -
NameCreation dateSort order
-
-
- -
-

- " /> - or <%=umbraco.ui.Text("general", "cancel", this.getUser())%> -

-
- - - -
- \ No newline at end of file diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sort.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sort.aspx.cs index a3915c3696..9534a7446e 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sort.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sort.aspx.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Globalization; using System.Linq; @@ -42,6 +42,7 @@ namespace umbraco.cms.presentation ScriptManager.GetCurrent(Page).Services.Add(new ServiceReference("../webservices/legacyAjaxCalls.asmx")); var app = Request.GetItemAsString("app"); + var icon = "../images/umbraco/doc.gif"; int parentId; @@ -137,6 +138,60 @@ namespace umbraco.cms.presentation public DateTime createDate; } + /// + /// JsInclude1 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::ClientDependency.Core.Controls.JsInclude JsInclude1; + + /// + /// JsInclude2 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::ClientDependency.Core.Controls.JsInclude JsInclude2; + + /// + /// prog1 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::umbraco.uicontrols.ProgressBar prog1; + + /// + /// sortDone control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Literal sortDone; + + /// + /// sortPane control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::umbraco.uicontrols.Pane sortPane; + + /// + /// lt_nodes control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Literal lt_nodes; + } public class nodeNameCompare : IComparer diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sort.aspx.designer.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sort.aspx.designer.cs deleted file mode 100644 index 9ed16cebc8..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sort.aspx.designer.cs +++ /dev/null @@ -1,69 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace umbraco.cms.presentation { - - - public partial class sort { - - /// - /// JsInclude1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::ClientDependency.Core.Controls.JsInclude JsInclude1; - - /// - /// JsInclude2 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::ClientDependency.Core.Controls.JsInclude JsInclude2; - - /// - /// prog1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.ProgressBar prog1; - - /// - /// sortDone control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal sortDone; - - /// - /// sortPane control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.Pane sortPane; - - /// - /// lt_nodes control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal lt_nodes; - } -}