From 76a986b0dbfdd9b5978c20b89a591ba519ddeee5 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Sun, 9 Jan 2011 14:36:20 -0600 Subject: gjslint recommended javascript cleanups Signed-off-by: Dan McGee --- media/archweb.js | 54 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/media/archweb.js b/media/archweb.js index 1c80ab64..28398c47 100644 --- a/media/archweb.js +++ b/media/archweb.js @@ -1,6 +1,6 @@ /* tablesorter custom parsers for various pages: * devel/index.html, mirrors/status.html, todolists/view.html */ -if(typeof $.tablesorter !== "undefined") { +if (typeof $.tablesorter !== 'undefined') { $.tablesorter.addParser({ id: 'pkgcount', is: function(s) { return false; }, @@ -21,14 +21,14 @@ if(typeof $.tablesorter !== "undefined") { $.tablesorter.addParser({ /* sorts numeric, but put '', 'unknown', and '∞' last. */ id: 'mostlydigit', - is: function(s,table) { + is: function(s, table) { var special = ['', 'unknown', '∞']; var c = table.config; - return ($.inArray(s, special) > -1) || $.tablesorter.isDigit(s,c); + return ($.inArray(s, special) > -1) || $.tablesorter.isDigit(s, c); }, format: function(s) { var special = ['', 'unknown', '∞']; - if($.inArray(s, special) > -1) return Number.MAX_VALUE; + if ($.inArray(s, special) > -1) return Number.MAX_VALUE; return $.tablesorter.formatFloat(s); }, type: 'numeric' @@ -43,7 +43,7 @@ if(typeof $.tablesorter !== "undefined") { }, format: function(s) { var special = ['', 'unknown', '∞']; - if($.inArray(s, special) > -1) return Number.MAX_VALUE; + if ($.inArray(s, special) > -1) return Number.MAX_VALUE; var matches = this.re.exec(s); return matches[1] * 60 + matches[2]; }, @@ -52,17 +52,17 @@ if(typeof $.tablesorter !== "undefined") { $.tablesorter.addParser({ id: 'longDateTime', re: /^(\d{4})-(\d{2})-(\d{2}) ([012]\d):([0-5]\d)(:([0-5]\d))?( (\w+))?$/, - is: function (s) { + is: function(s) { return this.re.test(s); }, - format: function (s) { + format: function(s) { var matches = this.re.exec(s); /* skip group 6, group 7 is optional seconds */ - if(matches[7] == undefined) matches[7] = "0"; + if (matches[7] == undefined) matches[7] = '0'; return $.tablesorter.formatFloat(new Date( matches[1],matches[2],matches[3],matches[4],matches[5],matches[7]).getTime()); }, - type: "numeric" + type: 'numeric' }); } @@ -94,16 +94,16 @@ function ajaxifyFiles() { /* packages/differences.html */ filter_packages = function() { // start with all rows, and then remove ones we shouldn't show - var rows = $("#tbody_differences").children(); + var rows = $('#tbody_differences').children(); var all_rows = rows; - if(!$('#id_multilib').is(':checked')) { - rows = rows.not(".multilib").not(".multilib-testing"); + if (!$('#id_multilib').is(':checked')) { + rows = rows.not('.multilib').not('.multilib-testing'); } - var arch = $("#id_archonly").val(); - if(arch !== "all") { - rows = rows.filter("." + arch); + var arch = $('#id_archonly').val(); + if (arch !== 'all') { + rows = rows.filter('.' + arch); } - if(!$('#id_minor').is(':checked')) { + if (!$('#id_minor').is(':checked')) { // this check is done last because it is the most expensive var pat = /(.*)-(.+)/; rows = rows.filter(function(index) { @@ -111,15 +111,15 @@ filter_packages = function() { // all this just to get the split version out of the table cell var ver_a = cells.eq(2).find('span').text().match(pat); - if(!ver_a) return true; + if (!ver_a) return true; var ver_b = cells.eq(3).find('span').text().match(pat); - if(!ver_b) return true; + if (!ver_b) return true; // first check pkgver - if(ver_a[1] !== ver_b[1]) return true; + if (ver_a[1] !== ver_b[1]) return true; // pkgver matched, so see if rounded pkgrel matches - if(Math.floor(parseFloat(ver_a[2])) == + if (Math.floor(parseFloat(ver_a[2])) == Math.floor(parseFloat(ver_b[2]))) return false; // pkgrel didn't match, so keep the row return true; @@ -129,12 +129,12 @@ filter_packages = function() { all_rows.hide(); rows.show(); // make sure we update the odd/even styling from sorting - $('.results').trigger("applyWidgets"); + $('.results').trigger('applyWidgets'); }; filter_reset = function() { - $('#id_archonly').val("both"); - $('#id_multilib').removeAttr("checked"); - $('#id_minor').removeAttr("checked"); + $('#id_archonly').val('both'); + $('#id_multilib').removeAttr('checked'); + $('#id_minor').removeAttr('checked'); filter_packages(); }; @@ -143,9 +143,11 @@ todolist_flag = function() { var link = this; $.getJSON(link.href, function(data) { if (data.complete) { - $(link).text('Complete').addClass('complete').removeClass('incomplete'); + $(link).text('Complete').addClass( + 'complete').removeClass('incomplete'); } else { - $(link).text('Incomplete').addClass('incomplete').removeClass('complete'); + $(link).text('Incomplete').addClass( + 'incomplete').removeClass('complete'); } }); return false; -- cgit v1.2.3-54-g00ecf From 262f8f3749526a1ec04e208ba3e9945fc12f36ca Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Sun, 9 Jan 2011 14:56:40 -0600 Subject: Convert function expressions to declarations Signed-off-by: Dan McGee --- media/archweb.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/media/archweb.js b/media/archweb.js index 28398c47..bbbc48b2 100644 --- a/media/archweb.js +++ b/media/archweb.js @@ -92,7 +92,7 @@ function ajaxifyFiles() { } /* packages/differences.html */ -filter_packages = function() { +function filter_packages() { // start with all rows, and then remove ones we shouldn't show var rows = $('#tbody_differences').children(); var all_rows = rows; @@ -130,16 +130,16 @@ filter_packages = function() { rows.show(); // make sure we update the odd/even styling from sorting $('.results').trigger('applyWidgets'); -}; -filter_reset = function() { +} +function filter_reset() { $('#id_archonly').val('both'); $('#id_multilib').removeAttr('checked'); $('#id_minor').removeAttr('checked'); filter_packages(); -}; +} /* todolists/view.html */ -todolist_flag = function() { +function todolist_flag() { var link = this; $.getJSON(link.href, function(data) { if (data.complete) { @@ -151,4 +151,4 @@ todolist_flag = function() { } }); return false; -}; +} -- cgit v1.2.3-54-g00ecf From 176d1619023e542cf25a9a52cc61df638df8dd67 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Mon, 10 Jan 2011 14:43:32 -0600 Subject: Fix old news URLs not redirecting properly Signed-off-by: Dan McGee --- news/urls.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/news/urls.py b/news/urls.py index 548d80ea..d938ef58 100644 --- a/news/urls.py +++ b/news/urls.py @@ -4,11 +4,11 @@ (r'^$', 'news_list', {}, 'news-list'), (r'^add/$', 'add'), (r'^preview/$', 'preview'), + # old news URLs, permanent redirect view so we don't break all links + (r'^(?P\d+)/$', 'view_redirect'), (r'^(?P[-\w]+)/$', 'view'), (r'^(?P[-\w]+)/edit/$', 'edit'), (r'^(?P[-\w]+)/delete/$', 'delete'), - # old news URLs, permanent redirect view so we don't break all links - (r'^(?P\d+)/$', 'view_redirect'), ) # vim: set ts=4 sw=4 et: -- cgit v1.2.3-54-g00ecf From 6285c379bac3fa05ecb3ccaccbe981d3573e290a Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Thu, 13 Jan 2011 14:32:57 -0600 Subject: Make userpkgs a simple_tag Cleans up the code a decent amount. Signed-off-by: Dan McGee --- packages/templatetags/package_extras.py | 37 +++++++++++---------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/packages/templatetags/package_extras.py b/packages/templatetags/package_extras.py index 3cd2b91b..d59a5562 100644 --- a/packages/templatetags/package_extras.py +++ b/packages/templatetags/package_extras.py @@ -31,29 +31,16 @@ def do_buildsortqs(parser, token): "%r tag's argument should be in quotes" % tagname) return BuildQueryStringNode(sortfield[1:-1]) -@register.tag -def userpkgs(parser, token): - try: - tagname, user = token.split_contents() - except ValueError: - raise template.TemplateSyntaxError( - "%r tag requires a single argument" % tagname) - return UserPkgsNode(user) - -class UserPkgsNode(template.Node): - def __init__(self, user): - self.user = template.Variable(user) +@register.simple_tag +def userpkgs(user): + if user: + # TODO don't hardcode + title = escape('View packages maintained by ' + user.get_full_name()) + return '%s' % ( + user.username, + title, + user.get_full_name(), + ) + return '' - def render(self, context): - try: - real_user = self.user.resolve(context) - # TODO don't hardcode - title = escape('View packages maintained by ' + real_user.get_full_name()) - return '%s' % ( - real_user.username, - title, - real_user.get_full_name(), - ) - except template.VariableDoesNotExist: - return '' - pass +# vim: set ts=4 sw=4 et: -- cgit v1.2.3-54-g00ecf From 9538d3492eb0efef144b78a50035ce4e4deaf8d1 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Fri, 14 Jan 2011 14:38:23 -0600 Subject: Fix JS null error when parsing non-matching date We didn't escape early with some value, causing an invalid dereference. While fixing this, also touch up the other functions and move a few more thngs to parser dictionary attributes. Signed-off-by: Dan McGee --- media/archweb.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/media/archweb.js b/media/archweb.js index bbbc48b2..cf8acd15 100644 --- a/media/archweb.js +++ b/media/archweb.js @@ -21,14 +21,13 @@ if (typeof $.tablesorter !== 'undefined') { $.tablesorter.addParser({ /* sorts numeric, but put '', 'unknown', and '∞' last. */ id: 'mostlydigit', + special: ['', 'unknown', '∞'], is: function(s, table) { - var special = ['', 'unknown', '∞']; var c = table.config; - return ($.inArray(s, special) > -1) || $.tablesorter.isDigit(s, c); + return ($.inArray(s, this.special) > -1) || $.tablesorter.isDigit(s, c); }, format: function(s) { - var special = ['', 'unknown', '∞']; - if ($.inArray(s, special) > -1) return Number.MAX_VALUE; + if ($.inArray(s, this.special) > -1) return Number.MAX_VALUE; return $.tablesorter.formatFloat(s); }, type: 'numeric' @@ -37,14 +36,14 @@ if (typeof $.tablesorter !== 'undefined') { /* sorts duration; put '', 'unknown', and '∞' last. */ id: 'duration', re: /^([0-9]+):([0-5][0-9])$/, + special: ['', 'unknown', '∞'], is: function(s) { - var special = ['', 'unknown', '∞']; - return ($.inArray(s, special) > -1) || this.re.test(s); + return ($.inArray(s, this.special) > -1) || this.re.test(s); }, format: function(s) { - var special = ['', 'unknown', '∞']; - if ($.inArray(s, special) > -1) return Number.MAX_VALUE; + if ($.inArray(s, this.special) > -1) return Number.MAX_VALUE; var matches = this.re.exec(s); + if (!matches) return Number.MAX_VALUE; return matches[1] * 60 + matches[2]; }, type: 'numeric' @@ -57,6 +56,7 @@ if (typeof $.tablesorter !== 'undefined') { }, format: function(s) { var matches = this.re.exec(s); + if (!matches) return 0; /* skip group 6, group 7 is optional seconds */ if (matches[7] == undefined) matches[7] = '0'; return $.tablesorter.formatFloat(new Date( -- cgit v1.2.3-54-g00ecf From dd72f73edae973c2afdbc8b00fd7f3b1662f3245 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Fri, 14 Jan 2011 14:43:11 -0600 Subject: Add non-minified tablesorter JS file Helpful for places like being on an airplane and needing to look at the source, and just for development purposes. Signed-off-by: Dan McGee --- media/jquery.tablesorter.js | 1031 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1031 insertions(+) create mode 100644 media/jquery.tablesorter.js diff --git a/media/jquery.tablesorter.js b/media/jquery.tablesorter.js new file mode 100644 index 00000000..9b587312 --- /dev/null +++ b/media/jquery.tablesorter.js @@ -0,0 +1,1031 @@ +/* + * + * TableSorter 2.0 - Client-side table sorting with ease! + * Version 2.0.5b + * @requires jQuery v1.2.3 + * + * Copyright (c) 2007 Christian Bach + * Examples and docs at: http://tablesorter.com + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + */ +/** + * + * @description Create a sortable table with multi-column sorting capabilitys + * + * @example $('table').tablesorter(); + * @desc Create a simple tablesorter interface. + * + * @example $('table').tablesorter({ sortList:[[0,0],[1,0]] }); + * @desc Create a tablesorter interface and sort on the first and secound column column headers. + * + * @example $('table').tablesorter({ headers: { 0: { sorter: false}, 1: {sorter: false} } }); + * + * @desc Create a tablesorter interface and disableing the first and second column headers. + * + * + * @example $('table').tablesorter({ headers: { 0: {sorter:"integer"}, 1: {sorter:"currency"} } }); + * + * @desc Create a tablesorter interface and set a column parser for the first + * and second column. + * + * + * @param Object + * settings An object literal containing key/value pairs to provide + * optional settings. + * + * + * @option String cssHeader (optional) A string of the class name to be appended + * to sortable tr elements in the thead of the table. Default value: + * "header" + * + * @option String cssAsc (optional) A string of the class name to be appended to + * sortable tr elements in the thead on a ascending sort. Default value: + * "headerSortUp" + * + * @option String cssDesc (optional) A string of the class name to be appended + * to sortable tr elements in the thead on a descending sort. Default + * value: "headerSortDown" + * + * @option String sortInitialOrder (optional) A string of the inital sorting + * order can be asc or desc. Default value: "asc" + * + * @option String sortMultisortKey (optional) A string of the multi-column sort + * key. Default value: "shiftKey" + * + * @option String textExtraction (optional) A string of the text-extraction + * method to use. For complex html structures inside td cell set this + * option to "complex", on large tables the complex option can be slow. + * Default value: "simple" + * + * @option Object headers (optional) An array containing the forces sorting + * rules. This option let's you specify a default sorting rule. Default + * value: null + * + * @option Array sortList (optional) An array containing the forces sorting + * rules. This option let's you specify a default sorting rule. Default + * value: null + * + * @option Array sortForce (optional) An array containing forced sorting rules. + * This option let's you specify a default sorting rule, which is + * prepended to user-selected rules. Default value: null + * + * @option Boolean sortLocaleCompare (optional) Boolean flag indicating whatever + * to use String.localeCampare method or not. Default set to true. + * + * + * @option Array sortAppend (optional) An array containing forced sorting rules. + * This option let's you specify a default sorting rule, which is + * appended to user-selected rules. Default value: null + * + * @option Boolean widthFixed (optional) Boolean flag indicating if tablesorter + * should apply fixed widths to the table columns. This is usefull when + * using the pager companion plugin. This options requires the dimension + * jquery plugin. Default value: false + * + * @option Boolean cancelSelection (optional) Boolean flag indicating if + * tablesorter should cancel selection of the table headers text. + * Default value: true + * + * @option Boolean debug (optional) Boolean flag indicating if tablesorter + * should display debuging information usefull for development. + * + * @type jQuery + * + * @name tablesorter + * + * @cat Plugins/Tablesorter + * + * @author Christian Bach/christian.bach@polyester.se + */ + +(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 + }; + + /* debuging utils */ + + 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); + } + } + + /* parsers utils */ + + function buildParserCache(table, $headers) { + + if (table.config.debug) { + var parsersDebug = ""; + } + + if (table.tBodies.length == 0) return; // In the case of empty tables + var rows = table.tBodies[0].rows; + + if (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, rows, -1, 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, rows, rowIndex, cellIndex) { + var l = parsers.length, + node = false, + nodeValue = false, + keepLooking = true; + while (nodeValue == '' && keepLooking) { + rowIndex++; + if (rows[rowIndex]) { + node = getNodeFromRowAndCellIndex(rows, rowIndex, cellIndex); + nodeValue = trimAndGetNodeText(table.config, node); + if (table.config.debug) { + log('Checking if value was empty on row:' + rowIndex); + } + } else { + keepLooking = false; + } + } + for (var i = 1; i < l; i++) { + if (parsers[i].is(nodeValue, table, node)) { + return parsers[i]; + } + } + // 0 is always the generic parser (text) + return parsers[0]; + } + + function getNodeFromRowAndCellIndex(rows, rowIndex, cellIndex) { + return rows[rowIndex].cells[cellIndex]; + } + + function trimAndGetNodeText(config, node) { + return $.trim(getElementText(config, node)); + } + + 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; + } + + /* utils */ + + 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) { + + /** Add the table data to main data array */ + var c = $(table.tBodies[0].rows[i]), + cols = []; + + // if this is a child row, add it to the last row's children and + // continue to the next row + if (c.hasClass(table.config.cssChildRow)) { + cache.row[cache.row.length - 1] = cache.row[cache.row.length - 1].add(c); + // go to the next for loop + continue; + } + + cache.row.push(c); + + for (var j = 0; j < totalCells; ++j) { + cols.push(parsers[j].format(getElementText(table.config, c[0].cells[j]), table, c[0].cells[j])); + } + + cols.push(cache.normalized.length); // add position for rowCache + cache.normalized.push(cols); + cols = null; + }; + + if (table.config.debug) { + benchmark("Building cache for " + totalRows + " rows:", cacheTime); + } + + return cache; + }; + + function getElementText(config, node) { + + var text = ""; + + if (!node) return ""; + + if (!config.supportsTextContent) config.supportsTextContent = node.textContent || false; + + if (config.textExtraction == "simple") { + if (config.supportsTextContent) { + text = node.textContent; + } else { + if (node.childNodes[0] && node.childNodes[0].hasChildNodes()) { + text = node.childNodes[0].innerHTML; + } else { + text = node.innerHTML; + } + } + } else { + if (typeof(config.textExtraction) == "function") { + text = config.textExtraction(node); + } else { + text = $(node).text(); + } + } + return text; + } + + 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++) { + var pos = n[i][checkCell]; + + rows.push(r[pos]); + + if (!table.config.appender) { + + //var o = ; + var l = r[pos].length; + for (var j = 0; j < l; j++) { + tableBody[0].appendChild(r[pos][j]); + } + + // + } + } + + + + if (table.config.appender) { + + table.config.appender(table, rows); + } + + rows = null; + + if (table.config.debug) { + benchmark("Rebuilt table:", appendTime); + } + + // apply table widgets + applyWidget(table); + + // trigger sortend + setTimeout(function () { + $(table).trigger("sortEnd"); + }, 0); + + }; + + function buildHeaders(table) { + + if (table.config.debug) { + var time = new Date(); + } + + var meta = ($.metadata) ? true : false; + + var header_index = computeTableHeaderCellIndexes(table); + + $tableHeaders = $(table.config.selectorHeaders, table).each(function (index) { + + this.column = header_index[this.parentNode.rowIndex + "-" + this.cellIndex]; + // this.column = index; + this.order = formatSortingOrder(table.config.sortInitialOrder); + + + this.count = this.order; + + if (checkHeaderMetadata(this) || checkHeaderOptions(table, index)) this.sortDisabled = true; + if (checkHeaderOptionsSortingLocked(table, index)) this.order = this.lockedOrder = checkHeaderOptionsSortingLocked(table, index); + + if (!this.sortDisabled) { + var $th = $(this).addClass(table.config.cssHeader); + if (table.config.onRenderHeader) table.config.onRenderHeader.apply($th); + } + + // add cell to headerList + table.config.headerList[index] = this; + }); + + if (table.config.debug) { + benchmark("Built headers:", time); + log($tableHeaders); + } + + return $tableHeaders; + + }; + + // from: + // http://www.javascripttoolbox.com/lib/table/examples.php + // http://www.javascripttoolbox.com/temp/table_cellindex.html + + + function computeTableHeaderCellIndexes(t) { + var matrix = []; + var lookup = {}; + var thead = t.getElementsByTagName('THEAD')[0]; + var trs = thead.getElementsByTagName('TR'); + + for (var i = 0; i < trs.length; i++) { + var cells = trs[i].cells; + for (var j = 0; j < cells.length; j++) { + var c = cells[j]; + + var rowIndex = c.parentNode.rowIndex; + var cellId = rowIndex + "-" + c.cellIndex; + var rowSpan = c.rowSpan || 1; + var colSpan = c.colSpan || 1 + var firstAvailCol; + if (typeof(matrix[rowIndex]) == "undefined") { + matrix[rowIndex] = []; + } + // Find first available column in the first row + for (var k = 0; k < matrix[rowIndex].length + 1; k++) { + if (typeof(matrix[rowIndex][k]) == "undefined") { + firstAvailCol = k; + break; + } + } + lookup[cellId] = firstAvailCol; + for (var k = rowIndex; k < rowIndex + rowSpan; k++) { + if (typeof(matrix[k]) == "undefined") { + matrix[k] = []; + } + var matrixrow = matrix[k]; + for (var l = firstAvailCol; l < firstAvailCol + colSpan; l++) { + matrixrow[l] = "x"; + } + } + } + } + return lookup; + } + + 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); + } + // headerArr[row] = (i+row); + } + } + 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 < 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") { + return (v.toLowerCase() == "desc") ? 1 : 0; + } else { + return (v == 1) ? 1 : 0; + } + } + + 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) { + // remove all header information + $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++; + } + } + + /* sorting methods */ + + function multisort(table, sortList, cache) { + + if (table.config.debug) { + var sortTime = new Date(); + } + + var dynamicExp = "var sortWrapper = function(a,b) {", + l = sortList.length; + + // TODO: inline functions. + 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 s = (table.config.parsers[c].type == "text") ? ((order == 0) + // ? makeSortText(c) : makeSortTextDesc(c)) : ((order == 0) ? + // makeSortNumeric(c) : makeSortNumericDesc(c)); + var s = (table.config.parsers[c].type == "text") ? ((order == 0) ? makeSortFunction("text", "asc", c) : makeSortFunction("text", "desc", c)) : ((order == 0) ? makeSortFunction("numeric", "asc", c) : makeSortFunction("numeric", "desc", c)); + var e = "e" + i; + + dynamicExp += "var " + e + " = " + s; // + "(a[" + c + "],b[" + c + // + "]); "; + dynamicExp += "if(" + e + ") { return " + e + "; } "; + dynamicExp += "else { "; + + } + + // if value is the same keep orignal order + 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 += "}; "; + + if (table.config.debug) { + benchmark("Evaling expression:" + dynamicExp, new Date()); + } + + eval(dynamicExp); + + cache.normalized.sort(sortWrapper); + + if (table.config.debug) { + benchmark("Sorting on " + sortList.toString() + " and dir " + order + " time:", sortTime); + } + + return cache; + }; + + function makeSortFunction(type, direction, index) { + var a = "a[" + index + "]", + b = "b[" + index + "]"; + if (type == 'text' && direction == 'asc') { + return "(" + a + " == " + b + " ? 0 : (" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : (" + a + " < " + b + ") ? -1 : 1 )));"; + } else if (type == 'text' && direction == 'desc') { + return "(" + a + " == " + b + " ? 0 : (" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : (" + b + " < " + a + ") ? -1 : 1 )));"; + } else if (type == 'numeric' && direction == 'asc') { + return "(" + a + " === null && " + b + " === null) ? 0 :(" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : " + a + " - " + b + "));"; + } else if (type == 'numeric' && direction == 'desc') { + return "(" + a + " === null && " + b + " === null) ? 0 :(" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : " + b + " - " + a + "));"; + } + }; + + function makeSortText(i) { + return "((a[" + i + "] < b[" + i + "]) ? -1 : ((a[" + 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 ((a < b) ? -1 : ((a > b) ? 1 : 0)); + }; + + function sortTextDesc(a, b) { + if (table.config.sortLocaleCompare) return b.localeCompare(a); + 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; + }; /* public methods */ + this.construct = function (settings) { + return this.each(function () { + // if no thead or tbody quit. + if (!this.tHead || !this.tBodies) return; + // declare + var $this, $document, $headers, cache, config, shiftDown = 0, + sortOrder; + // new blank config object + this.config = {}; + // merge and extend. + config = $.extend(this.config, $.tablesorter.defaults, settings); + // store common expression for speed + $this = $(this); + // save the settings where they read + $.data(this, "tablesorter", config); + // build headers + $headers = buildHeaders(this); + // try to auto detect column type, and store in tables config + this.config.parsers = buildParserCache(this, $headers); + // build the cache for the tbody cells + cache = buildCache(this); + // get the css class names, could be done else where. + var sortCSS = [config.cssDesc, config.cssAsc]; + // fixate columns if the users supplies the fixedWidth option + fixColumnWidth(this); + // apply event handling to headers + // this is to big, perhaps break it out? + $headers.click( + + function (e) { + var totalRows = ($this[0].tBodies[0] && $this[0].tBodies[0].rows.length) || 0; + if (!this.sortDisabled && totalRows > 0) { + // Only call sortStart if sorting is + // enabled. + $this.trigger("sortStart"); + // store exp, for speed + var $cell = $(this); + // get current column index + var i = this.column; + // get current column sort order + this.order = this.count++ % 2; + // always sort on the locked order. + if(this.lockedOrder) this.order = this.lockedOrder; + + // user only whants to sort on one + // column + if (!e[config.sortMultiSortKey]) { + // flush the sort list + 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]); + } + } + } + // add column to sort list + config.sortList.push([i, this.order]); + // multi column sorting + } else { + // the user has clicked on an all + // ready sortet column. + if (isValueInArray(i, config.sortList)) { + // revers the sorting direction + // for all tables. + 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 { + // add column to sort list array + config.sortList.push([i, this.order]); + } + }; + setTimeout(function () { + // set css for headers + setHeadersCss($this[0], $headers, config.sortList, sortCSS); + appendToTable( + $this[0], multisort( + $this[0], config.sortList, cache) + ); + }, 1); + // stop normal event by returning false + return false; + } + // cancel selection + }).mousedown(function () { + if (config.cancelSelection) { + this.onselectstart = function () { + return false + }; + return false; + } + }); + // apply easy methods that trigger binded events + $this.bind("update", function () { + var me = this; + setTimeout(function () { + // rebuild parsers. + me.config.parsers = buildParserCache( + me, $headers); + // rebuild the cache map + cache = buildCache(me); + }, 1); + }).bind("updateCell", function (e, cell) { + var config = this.config; + // get position from the dom. + var pos = [(cell.parentNode.rowIndex - 1), cell.cellIndex]; + // update cache + cache.normalized[pos[0]][pos[1]] = config.parsers[pos[1]].format( + getElementText(config, cell), cell); + }).bind("sorton", function (e, list) { + $(this).trigger("sortStart"); + config.sortList = list; + // update and store the sortlist + var sortList = config.sortList; + // update header count index + updateHeaderSortCount(this, sortList); + // set css for headers + setHeadersCss(this, $headers, sortList, sortCSS); + // sort the table and append it to the dom + appendToTable(this, multisort(this, sortList, cache)); + }).bind("appendCache", function () { + appendToTable(this, cache); + }).bind("applyWidgetId", function (e, id) { + getWidgetById(id).format(this); + }).bind("applyWidgets", function () { + // apply widgets + applyWidget(this); + }); + if ($.metadata && ($(this).metadata() && $(this).metadata().sortlist)) { + config.sortList = $(this).metadata().sortlist; + } + // if user has supplied a sort list to constructor. + if (config.sortList.length > 0) { + $this.trigger("sorton", [config.sortList]); + } + // apply widgets + 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) { + // replace all an wanted chars and match. + return /^[-+]?\d*$/.test($.trim(s.replace(/[,.']/g, ''))); + }; + 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 = ""; + } + }; + } + }); + + // extend plugin scope + $.fn.extend({ + tablesorter: $.tablesorter.construct + }); + + // make shortcut + var ts = $.tablesorter; + + // add default parsers + ts.addParser({ + id: "text", + is: function (s) { + return true; + }, format: function (s) { + return $.trim(s.toLocaleLowerCase()); + }, 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(/[£$€]/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") { + // reformat the string in ISO format + s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3/$1/$2"); + } else if (c.dateFormat == "uk") { + // reformat the string in ISO format + 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" + }); + // add default widgets + ts.addWidget({ + id: "zebra", + format: function (table) { + if (table.config.debug) { + var time = new Date(); + } + var $tr, row = -1, + odd; + // loop through the visible rows + $("tr:visible", table.tBodies[0]).each(function (i) { + $tr = $(this); + // style children rows the same way the parent + // row was styled + if (!$tr.hasClass(table.config.cssChildRow)) row++; + odd = (row % 2 == 0); + $tr.removeClass( + table.config.widgetZebra.css[odd ? 0 : 1]).addClass( + table.config.widgetZebra.css[odd ? 1 : 0]) + }); + if (table.config.debug) { + $.tablesorter.benchmark("Applying Zebra widget", time); + } + } + }); +})(jQuery); \ No newline at end of file -- cgit v1.2.3-54-g00ecf From d666cf4aaf5e23ecbc5c61fdd5fe63b9e96657e8 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Fri, 14 Jan 2011 14:45:16 -0600 Subject: Fix short date parsing in stock tablesorter JS This mirrors the change made to the minified file in 09bccb50e7. Signed-off-by: Dan McGee --- media/jquery.tablesorter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/media/jquery.tablesorter.js b/media/jquery.tablesorter.js index 9b587312..331b7617 100644 --- a/media/jquery.tablesorter.js +++ b/media/jquery.tablesorter.js @@ -969,7 +969,7 @@ ts.addParser({ id: "shortDate", is: function (s) { - return /\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(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, "/"); @@ -1028,4 +1028,4 @@ } } }); -})(jQuery); \ No newline at end of file +})(jQuery); -- cgit v1.2.3-54-g00ecf From d3e1b867e4262ad044a683678adf75cd72b79912 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Fri, 14 Jan 2011 15:18:36 -0600 Subject: Update tablesorter cache after clicking todo list status We didn't update this before, so sorting the last after checking off a few todos didn't work right, as it was using the old values. Fix it by adding a call to update; this can eventually be changed to the updateCell call commented out once I upgrade the minified tablesorter.js file. Signed-off-by: Dan McGee --- media/archweb.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/media/archweb.js b/media/archweb.js index cf8acd15..7a0d1dcc 100644 --- a/media/archweb.js +++ b/media/archweb.js @@ -14,7 +14,7 @@ if (typeof $.tablesorter !== 'undefined') { id: 'todostatus', is: function(s) { return false; }, format: function(s) { - return s.match(/incomplete/) ? 1 : 0; + return s.match(/incomplete/i) ? 1 : 0; }, type: 'numeric' }); @@ -149,6 +149,9 @@ function todolist_flag() { $(link).text('Incomplete').addClass( 'incomplete').removeClass('complete'); } + /* let tablesorter know the cell value has changed */ + /* newer version of tablesorter: $('.results').trigger('updateCell', $(link).parent('td')); */ + $('.results').trigger('update'); }); return false; } -- cgit v1.2.3-54-g00ecf From f10688e97664a6f6dab77d57510c9553b947c1e2 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Fri, 14 Jan 2011 23:39:57 -0600 Subject: Simplify JS selector for todo list complete links Signed-off-by: Dan McGee --- templates/todolists/view.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/todolists/view.html b/templates/todolists/view.html index 0792d096..ec8c997a 100644 --- a/templates/todolists/view.html +++ b/templates/todolists/view.html @@ -40,10 +40,10 @@

Todo List: {{ list.name }}

{% if pkg.complete %} Complete + class="status-link complete" title="Toggle completion status">Complete {% else %} Incomplete + class="status-link incomplete" title="Toggle completion status">Incomplete {% endif %} @@ -56,7 +56,7 @@

Todo List: {{ list.name }}

+ {% endif %} -- cgit v1.2.3-54-g00ecf From ecb24ab66a9d0a03ad021d23d4fa543f8163ef3e Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Tue, 18 Jan 2011 14:23:57 -0600 Subject: Small JS clarification for finding table cell Although it happened to be the parent element in this case, we are really just looking for the containing cell. Change the call to closest so we are future-proofed. Signed-off-by: Dan McGee --- media/archweb.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media/archweb.js b/media/archweb.js index b7351878..330eeff9 100644 --- a/media/archweb.js +++ b/media/archweb.js @@ -150,7 +150,7 @@ function todolist_flag() { 'incomplete').removeClass('complete'); } /* let tablesorter know the cell value has changed */ - $('.results').trigger('updateCell', $(link).parent('td')); + $('.results').trigger('updateCell', $(link).closest('td')); }); return false; } -- cgit v1.2.3-54-g00ecf From 9cdc536fffc9e77903892c2b14e9462a6ec94ee5 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Wed, 12 Jan 2011 10:08:29 -0600 Subject: Add arch-specific group overview pages This is easy enough to refactor and support with our current infrastructure and group-fetching functions. Signed-off-by: Dan McGee --- packages/utils.py | 10 ++++++---- packages/views.py | 14 +++++++++++--- templates/packages/group_details.html | 2 +- templates/packages/groups.html | 4 ++-- urls.py | 1 + 5 files changed, 21 insertions(+), 10 deletions(-) diff --git a/packages/utils.py b/packages/utils.py index 93d0de79..aaec0ec4 100644 --- a/packages/utils.py +++ b/packages/utils.py @@ -8,7 +8,7 @@ from .models import PackageGroup @cache_function(300) -def get_group_info(): +def get_group_info(include_arches=None): raw_groups = PackageGroup.objects.values_list( 'name', 'pkg__arch__name').order_by('name').annotate( cnt=Count('pkg'), last_update=Max('pkg__last_update')) @@ -38,10 +38,12 @@ def get_group_info(): new_g['arch'] = arch arch_groups[grp['name']] = new_g - # now transform it back into a sorted list + # now transform it back into a sorted list, including only the specified + # architectures if we got a list groups = [] - for val in group_mapping.itervalues(): - groups.extend(val.itervalues()) + for key, val in group_mapping.iteritems(): + if not include_arches or key in include_arches: + groups.extend(val.itervalues()) return sorted(groups, key=itemgetter('name', 'arch')) class Difference(object): diff --git a/packages/views.py b/packages/views.py index 4e683144..e00e6f94 100644 --- a/packages/views.py +++ b/packages/views.py @@ -88,9 +88,17 @@ def details(request, name='', repo='', arch=''): return redirect("/packages/?arch=%s&repo=%s&q=%s" % ( arch.lower(), repo.title(), name)) -def groups(request): - grps = get_group_info() - return direct_to_template(request, 'packages/groups.html', {'groups': grps}) +def groups(request, arch=None): + arches = [] + if arch: + get_object_or_404(Arch, name=arch, agnostic=False) + arches.append(arch) + grps = get_group_info(arches) + context = { + 'groups': grps, + 'arch': arch, + } + return direct_to_template(request, 'packages/groups.html', context) def group_details(request, arch, name): arch = get_object_or_404(Arch, name=arch) diff --git a/templates/packages/group_details.html b/templates/packages/group_details.html index df9c5e96..9cfa7b73 100644 --- a/templates/packages/group_details.html +++ b/templates/packages/group_details.html @@ -1,5 +1,5 @@ {% extends "base.html" %} -{% block title %}Arch Linux - {{ groupname }} - Group Details{% endblock %} +{% block title %}Arch Linux - {{ groupname }} - {{ arch.name }} - Group Details{% endblock %} {% block navbarclass %}anb-packages{% endblock %} {% block content %} diff --git a/templates/packages/groups.html b/templates/packages/groups.html index 8a96b7e3..87316a34 100644 --- a/templates/packages/groups.html +++ b/templates/packages/groups.html @@ -1,10 +1,10 @@ {% extends "base.html" %} -{% block title %}Arch Linux - Package Groups{% endblock %} +{% block title %}Arch Linux - Package Groups{% if arch %} - {{ arch }}{% endif %}{% endblock %} {% block navbarclass %}anb-packages{% endblock %} {% block content %}
-

Package Groups Overview

+

Package Groups Overview{% if arch %} - {{ arch }}{% endif %}

diff --git a/urls.py b/urls.py index 75f2ae78..b0f58b9f 100644 --- a/urls.py +++ b/urls.py @@ -18,6 +18,7 @@ urlpatterns = patterns('packages.views', (r'^groups/$', 'groups'), + (r'^groups/(?P[A-z0-9]+)/$', 'groups'), (r'^groups/(?P[A-z0-9]+)/(?P[A-z0-9\-+.]+)/$', 'group_details'), -- cgit v1.2.3-54-g00ecf From 523a15f81e819379d1d9ae8412ebd8a7c017a512 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Wed, 12 Jan 2011 13:50:59 -0600 Subject: Link dev names to email on clocks page Signed-off-by: Dan McGee --- templates/devel/clock.html | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/templates/devel/clock.html b/templates/devel/clock.html index 1bc9a849..03d0e9ca 100644 --- a/templates/devel/clock.html +++ b/templates/devel/clock.html @@ -6,13 +6,13 @@

Developer World Clocks

-

This page helps prevent you from waking a sleeping developer. It also - depends on developers keeping the time zone information up to date, so if - you see 'UTC' listed, pester them to update their settings.

-

- Arch Server Time: {{ now|date:"Y-m-d H:i T" }}
- UTC Time: {{ utc_now|date:"Y-m-d H:i T" }} -

+

This page helps prevent you from waking a sleeping developer. It also + depends on developers keeping the time zone information up to date, so if + you see 'UTC' listed, pester them to update their settings.

+

+ Arch Server Time: {{ now|date:"Y-m-d H:i T" }}
+ UTC Time: {{ utc_now|date:"Y-m-d H:i T" }} +

@@ -27,7 +27,7 @@

Developer World Clocks

{% for dev in developers %} - + -- cgit v1.2.3-54-g00ecf
{{ dev.get_full_name }}{{ dev.get_full_name }} {{ dev.username }} {{ dev.userprofile.location }} {{ dev.userprofile.time_zone }}