diff options
author | Dave Lawrence <dlawrence@mozilla.com> | 2013-01-03 20:41:44 +0100 |
---|---|---|
committer | Dave Lawrence <dlawrence@mozilla.com> | 2013-01-03 20:41:44 +0100 |
commit | a29bc8846fac5d7bcbe37ed306eb612bfc74acee (patch) | |
tree | 20e0b5e7531797d891a912749d068b34903cd7d7 | |
parent | f3975a11266aad202f31ce6fe8e86f321c68cd3e (diff) | |
download | bugzilla-a29bc8846fac5d7bcbe37ed306eb612bfc74acee.tar.gz bugzilla-a29bc8846fac5d7bcbe37ed306eb612bfc74acee.tar.xz |
More MyDashboard work
15 files changed, 514 insertions, 170 deletions
diff --git a/Bugzilla/WebService/Bug.pm b/Bugzilla/WebService/Bug.pm index 4018cfa6e..c0615b169 100644 --- a/Bugzilla/WebService/Bug.pm +++ b/Bugzilla/WebService/Bug.pm @@ -373,13 +373,13 @@ sub history { $bug_id = $bug->id; $item{id} = $self->type('int', $bug_id); - my ($activity) = Bugzilla::Bug::GetBugActivity($bug_id); + my ($activity) = Bugzilla::Bug::GetBugActivity($bug_id, undef, $params->{start_time}); my @history; foreach my $changeset (@$activity) { my %bug_history; $bug_history{when} = $self->type('dateTime', $changeset->{when}); - $bug_history{who} = $self->type('string', $changeset->{who}); + $bug_history{who} = $self->type('email', $changeset->{who}); $bug_history{changes} = []; foreach my $change (@{ $changeset->{changes} }) { my $api_field = $api_name{$change->{fieldname}} || $change->{fieldname}; @@ -2121,6 +2121,11 @@ Note that it's possible for aliases to be disabled in Bugzilla, in which case you will be told that you have specified an invalid bug_id if you try to specify an alias. (It will be error 100.) +=item C<start_time> + +An optional C<datetime> string that only shows changes at and after a specific +time. + =back =item B<Returns> diff --git a/extensions/MyDashboard/lib/Queries.pm b/extensions/MyDashboard/lib/Queries.pm index 79247bf73..e81e7f73f 100644 --- a/extensions/MyDashboard/lib/Queries.pm +++ b/extensions/MyDashboard/lib/Queries.pm @@ -10,6 +10,7 @@ package Bugzilla::Extension::MyDashboard::Queries; use strict; use Bugzilla; +use Bugzilla::Bug; use Bugzilla::CGI; use Bugzilla::Search; use Bugzilla::Util qw(format_time); @@ -17,6 +18,8 @@ use Bugzilla::Util qw(format_time); use Bugzilla::Extension::MyDashboard::Util qw(open_states quoted_open_states); use Bugzilla::Extension::MyDashboard::TimeAgo qw(time_ago); +use Data::Dumper; + use base qw(Exporter); our @EXPORT = qw( QUERY_ORDER @@ -242,5 +245,4 @@ sub query_flags { return undef; } - 1; diff --git a/extensions/MyDashboard/lib/WebService.pm b/extensions/MyDashboard/lib/WebService.pm index 853ef2baf..07619e705 100644 --- a/extensions/MyDashboard/lib/WebService.pm +++ b/extensions/MyDashboard/lib/WebService.pm @@ -9,7 +9,7 @@ package Bugzilla::Extension::MyDashboard::WebService; use strict; use warnings; -use base qw(Bugzilla::WebService); +use base qw(Bugzilla::WebService Bugzilla::WebService::Bug); use Bugzilla::Constants; use Bugzilla::Error; @@ -92,6 +92,7 @@ sub prod_comp_search { sub run_bug_query { my($self, $params) = @_; + my $dbh = Bugzilla->dbh; my $user = Bugzilla->login(LOGIN_REQUIRED); defined $params->{query} @@ -103,6 +104,30 @@ sub run_bug_query { foreach my $qdef (QUERY_DEFS) { next if $qdef->{name} ne $params->{query}; my ($bugs, $query_string) = query_bugs($qdef); + + # Add last changes to each bug + foreach my $b (@$bugs) { + my $last_changes = {}; + my $activity = $self->history({ ids => [ $b->{bug_id} ], + start_time => $b->{changeddate} }); + if (@{$activity->{bugs}[0]{history}}) { + $last_changes->{activity} = $activity->{bugs}[0]{history}[0]{changes}; + $last_changes->{email} = $activity->{bugs}[0]{history}[0]{who}; + $last_changes->{when} = $activity->{bugs}[0]{history}[0]{when}; + } + my $last_comment_id = $dbh->selectrow_array(" + SELECT comment_id FROM longdescs + WHERE bug_id = ? AND bug_when >= ?", + undef, $b->{bug_id}, $b->{changeddate}); + if ($last_comment_id) { + my $comments = $self->comments({ comment_ids => [ $last_comment_id ] }); + $last_changes->{comment} = $comments->{comments}{$last_comment_id}{text}; + $last_changes->{email} = $comments->{comments}{$last_comment_id}{creator} if !$last_changes->{email}; + $last_changes->{when} = $comments->{comments}{$last_comment_id}{creation_time} if !$last_changes->{when}; + } + $b->{last_changes} = $last_changes; + } + $query_string =~ s/^POSTDATA=&//; $qdef->{bugs} = $bugs; $qdef->{buffer} = $query_string; diff --git a/extensions/MyDashboard/template/en/default/pages/mydashboard.html.tmpl b/extensions/MyDashboard/template/en/default/pages/mydashboard.html.tmpl index dcaad0441..e5cd64399 100644 --- a/extensions/MyDashboard/template/en/default/pages/mydashboard.html.tmpl +++ b/extensions/MyDashboard/template/en/default/pages/mydashboard.html.tmpl @@ -24,6 +24,49 @@ [% saved_queries.push(q) IF q.saved %] [% END %] +<script id="last-changes-template" type="text/x-handlebars-template"> + {{#if email}} + <div id="last_changes"> + <div id="last_changes_header"> + Last Changes :: {{email}} :: {{when}} + </div> + {{#if activity}} + <table id="activity"> + {{#each activity}} + <tr> + <td class="field_label">{{field_name}}:</td> + <td class="field_data"> + {{#if removed}} + {{#unless added}} + Removed: + {{/unless}} + {{removed}} + {{/if}} + {{#if added}} + {{#if removed}} + → + {{/if}} + {{/if}} + {{#if added}} + {{#unless removed}} + Added: + {{/unless}} + {{added}} + {{/if}} + </td> + </tr> + {{/each}} + </table> + {{/if}} + {{#if comment}} + <pre class='bz_comment_text'>{{comment}}</pre> + {{/if}} + {{else}} + This is a new [% terms.bug %] and no changes have been made yet. + {{/if}} + </div> +</script> + <div id="mydashboard"> <div class="yui3-skin-sam"> <div id="left"> diff --git a/extensions/MyDashboard/web/js/mydashboard_yui2.js b/extensions/MyDashboard/web/js/mydashboard_yui2.js deleted file mode 100644 index 25529d8c8..000000000 --- a/extensions/MyDashboard/web/js/mydashboard_yui2.js +++ /dev/null @@ -1,159 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This Source Code Form is "Incompatible With Secondary Licenses", as - * defined by the Mozilla Public License, v. 2.0. - */ - -YAHOO.namespace('MyDashboard'); - -var MD = YAHOO.MyDashboard; - -MD.showQuerySection = function () { - var query_select = YAHOO.util.Dom.get('query'); - var selected_value = ''; - for (var i = 0, l = query_select.options.length; i < l; i++) { - if (query_select.options[i].selected) { - selected_value = query_select.options[i].value; - } - } - for (var i = 0, l = MD.full_query_list.length; i < l; i++) { - var query = MD.full_query_list[i]; - if (selected_value == MD.full_query_list[i]) { - YAHOO.util.Dom.removeClass(query + '_container', 'bz_default_hidden'); - } - else { - YAHOO.util.Dom.addClass(query + '_container', 'bz_default_hidden'); - } - } -} - -MD.query_column_defs = [ - { key:"id", label:"ID", sortable:true, sortOptions:{ sortFunction: MD.sortBugIdLinks } }, - { key:"updated", label:"Updated", sortable:true }, - { key:"bug_status", label:"Status", sortable:true }, - { key:"summary", label:"Summary", sortable:true }, -]; - -MD.query_fields = [ - { key:"id" }, - { key:"updated" }, - { key:"bug_status" }, - { key:"summary" } -]; - -MD.requestee_column_defs = [ - { key:"requester", label:"Requester", sortable:true }, - { key:"flag", label:"Flag", sortable:true }, - { key:"bug", label:"Bug", sortable:true }, - { key:"created", label:"Created", sortable:true } -]; - -MD.requestee_fields = [ - { key:"requester" }, - { key:"flag" }, - { key:"bug" }, - { key:"created" } -]; - -MD.requester_column_defs = [ - { key:"requestee", label:"Requestee", sortable:true }, - { key:"flag", label:"Flag", sortable:true }, - { key:"bug", label:"Bug", sortable:true }, - { key:"created", label:"Created", sortable:true } -]; - -MD.requester_fields = [ - { key:"requestee" }, - { key:"flag" }, - { key:"bug" }, - { key:"created" } -]; - -MD.addStatListener = function (div_name, table_name, column_defs, fields, options) { - YAHOO.util.Event.addListener(window, "load", function() { - YAHOO.example.StatsFromMarkup = new function() { - this.myDataSource = new YAHOO.util.DataSource(YAHOO.util.Dom.get(table_name)); - this.myDataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE; - this.myDataSource.responseSchema = { fields:fields }; - this.myDataTable = new YAHOO.widget.DataTable(div_name, column_defs, this.myDataSource, options); - this.myDataTable.subscribe("rowMouseoverEvent", this.myDataTable.onEventHighlightRow); - this.myDataTable.subscribe("rowMouseoutEvent", this.myDataTable.onEventUnhighlightRow); - }; - }); -} - -// Custom sort handler to sort by bug id inside an anchor tag -MD.sortBugIdLinks = function (a, b, desc) { - // Deal with empty values - if (!YAHOO.lang.isValue(a)) { - return (!YAHOO.lang.isValue(b)) ? 0 : 1; - } - else if(!YAHOO.lang.isValue(b)) { - return -1; - } - // Now we need to pull out the ID text and convert to Numbers - // First we do 'a' - var container = document.createElement("bug_id_link"); - container.innerHTML = a.getData("id"); - var anchors = container.getElementsByTagName("a"); - var text = anchors[0].textContent; - if (text === undefined) text = anchors[0].innerText; - var new_a = new Number(text); - // Then we do 'b' - container.innerHTML = b.getData("id"); - anchors = container.getElementsByTagName("a"); - text = anchors[0].textContent; - if (text == undefined) text = anchors[0].innerText; - var new_b = new Number(text); - - if (!desc) { - return YAHOO.util.Sort.compare(new_a, new_b); - } - else { - return YAHOO.util.Sort.compare(new_b, new_a); - } -} - -// Custom sort handler for bug severities -MD.sortBugSeverity = function (a, b, desc) { - // Deal with empty values - if (!YAHOO.lang.isValue(a)) { - return (!YAHOO.lang.isValue(b)) ? 0 : 1; - } - else if(!YAHOO.lang.isValue(b)) { - return -1; - } - - var new_a = new Number(MD.severities[YAHOO.lang.trim(a.getData('bug_severity'))]); - var new_b = new Number(MD.severities[YAHOO.lang.trim(b.getData('bug_severity'))]); - - if (!desc) { - return YAHOO.util.Sort.compare(new_a, new_b); - } - else { - return YAHOO.util.Sort.compare(new_b, new_a); - } -} - -// Custom sort handler for bug priorities -MD.sortBugPriority = function (a, b, desc) { - // Deal with empty values - if (!YAHOO.lang.isValue(a)) { - return (!YAHOO.lang.isValue(b)) ? 0 : 1; - } - else if(!YAHOO.lang.isValue(b)) { - return -1; - } - - var new_a = new Number(MD.priorities[YAHOO.lang.trim(a.getData('priority'))]); - var new_b = new Number(MD.priorities[YAHOO.lang.trim(b.getData('priority'))]); - - if (!desc) { - return YAHOO.util.Sort.compare(new_a, new_b); - } - else { - return YAHOO.util.Sort.compare(new_b, new_a); - } -} diff --git a/extensions/MyDashboard/web/js/query.js b/extensions/MyDashboard/web/js/query.js index 746717e75..865d255a6 100644 --- a/extensions/MyDashboard/web/js/query.js +++ b/extensions/MyDashboard/web/js/query.js @@ -9,9 +9,17 @@ // Main query code YUI({ base: 'js/yui3/', - combine: false + combine: false, + groups: { + gallery: { + combine: false, + base: 'js/yui3/', + patterns: { 'gallery-': {} } + } + } }).use("node", "datatable", "datatable-sort", "datatable-message", "json-stringify", - "datatable-datasource", "datasource-io", "datasource-jsonschema", "cookie", function (Y) { + "datatable-datasource", "datasource-io", "datasource-jsonschema", "cookie", + "gallery-datatable-row-expansion-bmo", "handlebars", function (Y) { var counter = 0, dataSource = null, dataTable = null, @@ -83,7 +91,8 @@ YUI({ dataSource.plug(Y.Plugin.DataSourceJSONSchema, { schema: { resultListLocator: "result.result.bugs", - resultFields: ["bug_id", "changeddate", "bug_status", "short_desc"], + resultFields: ["bug_id", "changeddate", "bug_status", + "short_desc", "last_changes"], metaFields: { description: "result.result.description", heading: "result.result.heading", @@ -94,14 +103,34 @@ YUI({ dataTable = new Y.DataTable({ columns: [ - { key:"bug_id", label:"Bug", sortable:true, + { key: Y.Plugin.DataTableRowExpansion.column_key, label: ' ' }, + { key: "bug_id", label: "Bug", sortable: true, formatter: '<a href="show_bug.cgi?id={value}" target="_blank">{value}</a>', allowHTML: true }, - { key:"changeddate", label:"Updated", sortable:true }, - { key:"bug_status", label:"Status", sortable:true }, - { key:"short_desc", label:"Summary", sortable:true }, + { key: "changeddate", label: "Updated", sortable: true }, + { key: "bug_status", label: "Status", sortable: true }, + { key: "short_desc", label: "Summary", sortable: true }, ], }); + var last_changes_source = Y.one('#last-changes-template').getHTML(), + last_changes_template = Y.Handlebars.compile(last_changes_source); + + dataTable.plug(Y.Plugin.DataTableRowExpansion, { + uniqueIdKey: 'bug_id', + template: function(data) { + var last_changes = {}; + if (data.last_changes.email) { + last_changes = { + activity: data.last_changes.activity, + email: data.last_changes.email, + when: data.last_changes.when, + comment: data.last_changes.comment, + }; + } + return last_changes_template(last_changes); + } + }); + dataTable.plug(Y.Plugin.DataTableSort); dataTable.plug(Y.Plugin.DataTableDataSource, { diff --git a/extensions/MyDashboard/web/styles/mydashboard.css b/extensions/MyDashboard/web/styles/mydashboard.css index dc253c0d1..253e60d42 100644 --- a/extensions/MyDashboard/web/styles/mydashboard.css +++ b/extensions/MyDashboard/web/styles/mydashboard.css @@ -51,3 +51,14 @@ padding: 20px !important; height: 40px; } + +#last_changes_header { + font-size: 12px; + font-weight: bold; + padding-bottom: 5px; + border-bottom: 1px solid rgb(200, 200, 186); +} + +#last_changes .field_label { + text-align: left; +} diff --git a/js/yui3/gallery-datatable-row-expansion-bmo/assets/skins/sam/closed.png b/js/yui3/gallery-datatable-row-expansion-bmo/assets/skins/sam/closed.png Binary files differnew file mode 100644 index 000000000..019c18e14 --- /dev/null +++ b/js/yui3/gallery-datatable-row-expansion-bmo/assets/skins/sam/closed.png diff --git a/js/yui3/gallery-datatable-row-expansion-bmo/assets/skins/sam/gallery-datatable-row-expansion-bmo.css b/js/yui3/gallery-datatable-row-expansion-bmo/assets/skins/sam/gallery-datatable-row-expansion-bmo.css new file mode 100644 index 000000000..7ea55b74d --- /dev/null +++ b/js/yui3/gallery-datatable-row-expansion-bmo/assets/skins/sam/gallery-datatable-row-expansion-bmo.css @@ -0,0 +1 @@ +.yui3-skin-sam .yui3-datatable tr.row-expansion td.post-row-expansion{border-top:1px solid #cbcbcb}.yui3-skin-sam .yui3-datatable .row-toggle a.row-expand-nub{padding:0 8px;height:14px;margin-left:2px;*display:inline-block}.yui3-skin-sam .yui3-datatable .row-closed a.row-expand-nub{background:url(closed.png) no-repeat}.yui3-skin-sam .yui3-datatable .row-open a.row-expand-nub{background:url(open.png) no-repeat}#yui3-css-stamp.skin-sam-gallery-datatable-row-expansion{display:none} diff --git a/js/yui3/gallery-datatable-row-expansion-bmo/assets/skins/sam/open.png b/js/yui3/gallery-datatable-row-expansion-bmo/assets/skins/sam/open.png Binary files differnew file mode 100644 index 000000000..dc7805017 --- /dev/null +++ b/js/yui3/gallery-datatable-row-expansion-bmo/assets/skins/sam/open.png diff --git a/js/yui3/gallery-datatable-row-expansion-bmo/gallery-datatable-row-expansion-bmo-min.js b/js/yui3/gallery-datatable-row-expansion-bmo/gallery-datatable-row-expansion-bmo-min.js new file mode 100644 index 000000000..e3f87804c --- /dev/null +++ b/js/yui3/gallery-datatable-row-expansion-bmo/gallery-datatable-row-expansion-bmo-min.js @@ -0,0 +1,383 @@ +YUI.add('gallery-datatable-row-expansion-bmo', function (Y, NAME) { + +"use strict"; + +/** + * @module gallery-datatable-row-expansion + */ + +/********************************************************************** + * <p>Plugin for DataTable to show additional information for each row via + * a twistdown. The result of the template is displayed spanning all the + * columns beyond the twistdown column.</p> + * + * <p>This class patches `getCell` and `getRow` to ignore the additional + * rows created by this plugin.</p> + * + * @main gallery-datatable-row-expansion + * @class DataTableRowExpansion + * @namespace Plugin + * @extends Plugin.Base + * @constructor + * @param config {Object} configuration + */ +function RowExpansion( + /* object */ config) +{ + RowExpansion.superclass.constructor.call(this, config); +} + +RowExpansion.NAME = "DataTableRowExpansionPlugin"; +RowExpansion.NS = "rowexpander"; + +RowExpansion.ATTRS = +{ + /** + * String template or function that returns a string. + * + * @attribute template + * @type {String|Function} + * @required + */ + template: + { + value: '', + validator: function(value) + { + return (Y.Lang.isString(value) || Y.Lang.isFunction(value)); + } + }, + + /** + * Id of a column (usually not displayed) that yields a + * unique value for each record. Used to maintain the twistdown state + * when paginating. + * + * @attribute uniqueIdKey + * @type {String} + * @required + */ + uniqueIdKey: + { + value: '', + validator: Y.Lang.isString + } +}; + +/** + * The key used to indicate which column contains the twistdown. + * + * @property Y.RowExpansion.column_key + * @type {String} + * @value "row-expander" + */ +RowExpansion.column_key = 'row-expander'; + +/** + * The class added to rows created by this plugin. + * + * @property Y.RowExpansion.row_class + * @type {String} + * @value "row-expansion" + */ +RowExpansion.row_class = 'row-expansion'; + +function insertRow(o) +{ + var plugin = this.rowexpander; + + var pre_cells = ''; + for (var i=0; i<=plugin.col_count.pre; i++) + { + pre_cells += '<td class="yui3-datatable-cell pre-row-expansion"> </td>'; + } + + var tmpl = plugin.get('template'); + if (Y.Lang.isFunction(tmpl)) + { + var s = tmpl.call(this, o.data); + } + else + { + var s = Y.Lang.sub(tmpl, o.data); + } + + var row = o.cell.ancestor(); + var extra_row = Y.Lang.sub( + '<tr class="{c}">' + + '{pre}' + + '<td colspan="{post}" class="yui3-datatable-cell post-row-expansion">{tmpl}</td>' + + '</tr>', + { + c: row.get('className') + ' ' + RowExpansion.row_class, + pre: pre_cells, + post: plugin.col_count.post, + tmpl: s + }); + + row.insert(extra_row, 'after'); +} + +function formatTwistdown(o) +{ + var plugin = this.rowexpander, + row_id = o.data[ plugin.get('uniqueIdKey') ], + open = plugin.open_rows[ row_id ]; + + o.td.addClass('row-toggle'); + o.td.replaceClass('row-(open|closed)', open ? 'row-open' : 'row-closed'); + + o.td.on('click', function() + { + var open = plugin.open_rows[ row_id ] = ! plugin.open_rows[ row_id ]; + + if (open) + { + insertRow.call(this, o); + o.td.replaceClass('row-(open|closed)', open ? 'row-open' : 'row-closed'); + } + else + { + o.cell.ancestor().next().remove(); + o.td.replaceClass('row-(open|closed)', open ? 'row-open' : 'row-closed'); + } + }, + this); + + o.cell.set('innerHTML', '<a class="row-expand-nub" href="javascript:void(0);"></a>'); + + if (open) + { + insertRow.call(this, o); + } +} + +function analyzeColumns() +{ + function countColumns(result, col) + { + if (col.key == RowExpansion.column_key) + { + col.nodeFormatter = formatTwistdown; + result.found = true; + } + else if (col.children) + { + result = Y.reduce(col.children, result, countColumns); + } + else + { + result[ result.found ? 'post' : 'pre' ]++; + } + return result; + } + + this.col_count = Y.reduce( + this.get('host').get('columns'), + { pre:0, post:0, found:false }, + countColumns); +} + +var shift_map = +{ + above: [-1, 0], + below: [ 1, 0], + next: [ 0, 1], + prev: [ 0, -1], + previous: [ 0, -1] +}; + +/* +Returns the `<td>` Node from the given row and column index. Alternately, +the `seed` can be a Node. If so, the nearest ancestor cell is returned. +If the `seed` is a cell, it is returned. If there is no cell at the given +coordinates, `null` is returned. + +Optionally, include an offset array or string to return a cell near the +cell identified by the `seed`. The offset can be an array containing the +number of rows to shift followed by the number of columns to shift, or one +of "above", "below", "next", or "previous". + +<pre><code>// Previous cell in the previous row +var cell = table.getCell(e.target, [-1, -1]); + +// Next cell +var cell = table.getCell(e.target, 'next'); +var cell = table.getCell(e.taregt, [0, 1];</pre></code> + +@method getCell +@param {Number[]|Node} seed Array of row and column indexes, or a Node that + is either the cell itself or a descendant of one. +@param {Number[]|String} [shift] Offset by which to identify the returned + cell Node +@return {Node} +@since 3.5.0 +*/ +function getCell(seed, shift) +{ + var tbody = this.tbodyNode, + row, cell; + + if (seed && tbody) + { + if (Y.Lang.isString(shift)) + { + if (shift_map[shift]) + { + shift = shift_map[shift]; + } + else + { + throw Error('unknown shift in getCell: ' + shift); + } + } + + if (Y.Lang.isArray(seed)) + { + row = tbody.get('children').item(0); + cell = row && row.get('children').item(seed[1]); + if (shift) + { + shift[0] += seed[0]; + } + else + { + shift = [ seed[0], 0 ]; + } + } + else if (seed._node) + { + cell = seed.ancestor('.' + this.getClassName('cell'), true); + if (cell.ancestor('tr.' + RowExpansion.row_class)) + { + throw Error('getCell cannot be called with an element from an expansion row'); + } + } + + if (cell && shift) + { + var firstRowIndex = tbody.get('firstChild.rowIndex'); + if (Y.Lang.isArray(shift)) + { + row = cell.ancestor(); + var delta = Math.sign(shift[0]); + if (delta !== 0) + { + var rows = tbody.get('children'); + var index = row.get('rowIndex') - firstRowIndex; + var count = Math.abs(shift[0]); + for (var i=0; i<count && row; i++) + { + index += delta; + row = rows.item(index); + if (row && row.hasClass(RowExpansion.row_class)) + { + index += delta; + row = rows.item(index); + } + } + } + + index = cell.get('cellIndex') + shift[1]; + cell = row && row.get('children').item(index); + } + } + } + + return (cell || null); +} + +/* +Returns the `<tr>` Node from the given row index, Model, or Model's +`clientId`. If the rows haven't been rendered yet, or if the row can't be +found by the input, `null` is returned. + +@method getRow +@param {Number|String|Model} id Row index, Model instance, or clientId +@return {Node} +@since 3.5.0 +*/ +function getRow(id) +{ + var tbody = this.tbodyNode, + row = null; + + if (tbody) + { + if (id) + { + id = this._idMap[id.get ? id.get('clientId') : id] || id; + } + + row = Y.one(Y.Lang.isNumber(id) ? this.getCell([id,0]).ancestor() : '#' + id); + } + + return row; +} + +function replaceGetters() +{ + var view = this.get('host').view; + if (view instanceof Y.DataTable.TableView && + view.body instanceof Y.DataTable.BodyView) + { + var body = view.body; + + this.orig_getCell = body.getCell; + this.orig_getRow = body.getRow; + + body.getCell = getCell; + body.getRow = getRow; + } +} + +function restoreGetters() +{ + var view = this.get('host').view; + if (view.body && this.orig_getCell) + { + view.body.getCell = this.orig_getCell; + } + + if (view.body && this.orig_getRow) + { + view.body.getRow = this.orig_getRow; + } +} + +Y.extend(RowExpansion, Y.Plugin.Base, +{ + initializer: function(config) + { + this.open_rows = {}; + this.on('uniqueIdKeyChange', function() + { + this.open_rows = {}; + }); + + analyzeColumns.call(this); + this.afterHostEvent('columnsChange', analyzeColumns); + + this.afterHostEvent('table:renderTable', replaceGetters); + }, + + destructor: function() + { + restoreGetters.call(this); + } +}); + +Y.namespace("Plugin"); +Y.Plugin.DataTableRowExpansion = RowExpansion; + + +}, '@VERSION@', { + "skinnable": "true", + "requires": [ + "datatable", + "plugin", + "gallery-funcprog", + "gallery-node-optimizations", + "gallery-math" + ] +}); diff --git a/js/yui3/gallery-funcprog/gallery-funcprog-min.js b/js/yui3/gallery-funcprog/gallery-funcprog-min.js new file mode 100644 index 000000000..5354b068c --- /dev/null +++ b/js/yui3/gallery-funcprog/gallery-funcprog-min.js @@ -0,0 +1 @@ +YUI.add("gallery-funcprog",function(e,t){"use strict";function n(t,n){var r=e.Array(arguments,1,!0);switch(e.Array.test(n)){case 1:return e.Array[t].apply(null,r);case 2:return r[0]=e.Array(n,0,!0),e.Array[t].apply(null,r);default:return n&&n[t]&&n!==e?(r.shift(),n[t].apply(n,r)):e.Object[t].apply(null,r)}}e.mix(e,{every:function(e,t,r,i){return n("every",e,t,r,i)},filter:function(e,t,r,i){return n("filter",e,t,r,i)},find:function(e,t,r,i){return n("find",e,t,r,i)},map:function(e,t,r,i){return n("map",e,t,r,i)},partition:function(e,t,r,i){return n("partition",e,t,r,i)},reduce:function(e,t,r,i,s){return n("reduce",e,t,r,i,s)},reduceRight:function(e,t,r,i,s){return n("reduceRight",e,t,r,i,s)},reject:function(e,t,r,i){return n("reject",e,t,r,i)}}),e.mix(e.Array,{findIndexOf:function(t,n,r){var i=-1;return e.Array.some(t,function(e,s){if(n.call(r,e,s,t))return i=s,!0}),i}}),e.Array.reduceRight=e.Lang._isNative(Array.prototype.reduceRight)?function(e,t,n,r){return Array.prototype.reduceRight.call(e,function(e,t,i,s){return n.call(r,e,t,i,s)},t)}:function(e,t,n,r){var i=t;for(var s=e.length-1;s>=0;s--)i=n.call(r,i,e[s],s,e);return i}},"@VERSION@",{requires:["oop","array-extras","gallery-object-extras"],optional:["gallery-nodelist-extras2"]}); diff --git a/js/yui3/gallery-math/gallery-math-min.js b/js/yui3/gallery-math/gallery-math-min.js new file mode 100644 index 000000000..1d9348e48 --- /dev/null +++ b/js/yui3/gallery-math/gallery-math-min.js @@ -0,0 +1 @@ +YUI.add("gallery-math",function(e,t){"use strict";e.mix(Math,{sign:function(e){return e<0?-1:e>0?1:0},add:function(){return e.Array.reduce(e.Array(arguments),0,function(t,n){return e.Lang.isArray(n)&&(n=Math.add.apply(this,n)),t+n})},addReciprocals:function(){return e.Array.reduce(e.Array(arguments),0,function(t,n){return e.Lang.isArray(n)?t+Math.addReciprocals.apply(this,n):t+1/n})},parallel:function(){return 1/Math.addReciprocals.apply(this,arguments)},multiply:function(){return e.Array.reduce(e.Array(arguments),1,function(t,n){return e.Lang.isArray(n)&&(n=Math.multiply.apply(this,n)),t*n})},degreesToRadians:function(e){return e*Math.PI/180},radiansToDegrees:function(e){return e*180/Math.PI},acosh:function(e){return Math.log(e+Math.sqrt(e*e-1))},asinh:function(e){return Math.log(e+Math.sqrt(e*e+1))},atanh:function(e){return Math.log((1+e)/(1-e))/2},cosh:function(e){var t=Math.exp(e);return(t+1/t)/2},sinh:function(e){var t=Math.exp(e);return(t-1/t)/2},tanh:function(e){var t=Math.exp(2*e);return(t-1)/(t+1)}})},"@VERSION@",{requires:["array-extras"]}); diff --git a/js/yui3/gallery-node-optimizations/gallery-node-optimizations-min.js b/js/yui3/gallery-node-optimizations/gallery-node-optimizations-min.js new file mode 100644 index 000000000..297b60ac6 --- /dev/null +++ b/js/yui3/gallery-node-optimizations/gallery-node-optimizations-min.js @@ -0,0 +1 @@ +YUI.add("gallery-node-optimizations",function(e,t){"use strict";var n=/^([a-z]*)\.([-_a-z0-9]+)$/i,r=/^\.([-_a-z0-9]+)$/i,i=/^[a-z]+$/i;e.Node.class_re_prefix="(?:^|\\s)(?:",e.Node.class_re_suffix=")(?:\\s|$)";var s=e.Node.prototype.ancestor;e.Node.prototype.ancestor=function(t,n){if(e.Lang.isString(t)){var o=r.exec(t);if(o&&o.length)return this.getAncestorByClassName(o[1],n);if(i.test(t))return this.getAncestorByTagName(t,n)}return s.apply(this,arguments)},e.Node.prototype.getAncestorByClassName=function(t,n){var r=this._node;n||(r=r.parentNode);while(r&&!e.DOM.hasClass(r,t)){r=r.parentNode;if(!r||!r.tagName)return null}return e.one(r)},e.Node.prototype.getAncestorByTagName=function(t,n){var r=this._node;n||(r=r.parentNode),t=t.toLowerCase();while(r&&r.tagName.toLowerCase()!=t){r=r.parentNode;if(!r||!r.tagName)return null}return e.one(r)},e.Node.prototype.getElementsByClassName=function(t,n){var r=e.Node.getDOMNode(this).getElementsByTagName(n||"*"),i=new e.NodeList;for(var s=0;s<r.length;s++){var o=r[s];e.DOM.hasClass(o,t)&&i.push(o)}return i},e.Node.prototype.getFirstElementByClassName=function(t,n){if(!n||n=="*"||n=="div"){var r=[e.Node.getDOMNode(this)],i=[];while(r.length){for(var s=0;s<r.length;s++){var o=r[s],u=o.children||o.childNodes;for(var a=0;a<u.length;a++){var f=u[a];if(e.DOM.hasClass(f,t))return e.one(f);i.push(f)}}r=i,i=[]}}else{var l=e.Node.getDOMNode(this).getElementsByTagName(n||"*");for(var s=0;s<l.length;s++){var f=l[s];if(e.DOM.hasClass(f,t))return e.one(f)}}return null}},"@VERSION@",{requires:["node-base"]}); diff --git a/js/yui3/gallery-object-extras/gallery-object-extras-min.js b/js/yui3/gallery-object-extras/gallery-object-extras-min.js new file mode 100644 index 000000000..608ae8f57 --- /dev/null +++ b/js/yui3/gallery-object-extras/gallery-object-extras-min.js @@ -0,0 +1 @@ +YUI.add("gallery-object-extras",function(e,t){"use strict";e.mix(e.Object,{every:function(e,t,n,r){for(var i in e)if((r||e.hasOwnProperty(i))&&!t.call(n,e[i],i,e))return!1;return!0},filter:function(e,t,n,r){var i={};for(var s in e){var o=e[s];(r||e.hasOwnProperty(s))&&t.call(n,o,s,e)&&(i[s]=o)}return i},find:function(e,t,n,r){for(var i in e){var s=e[i];if((r||e.hasOwnProperty(i))&&t.call(n,s,i,e))return s}return null},keyOf:function(e,t,n){for(var r in e)if((n||e.hasOwnProperty(r))&&e[r]===t)return r;return null},invoke:function(t,n){var r=e.Array(arguments,2,!0),i={};for(var s in t){var o=t[s];t.hasOwnProperty(s)&&e.Lang.isFunction(o[n])&&(i[s]=o[n].apply(o,r))}return i},map:function(e,t,n,r){var i={};for(var s in e)if(r||e.hasOwnProperty(s))i[s]=t.call(n,e[s],s,e);return i},partition:function(e,t,n,r){var i={matches:{},rejects:{}};for(var s in e){var o=e[s];if(r||e.hasOwnProperty(s)){var u=t.call(n,o,s,e)?i.matches:i.rejects;u[s]=o}}return i},reduce:function(e,t,n,r,i){var s=t;for(var o in e)if(i||e.hasOwnProperty(o))s=n.call(r,s,e[o],o,e);return s},reject:function(t,n,r,i){return e.Object.filter(t,function(e,t,i){return!n.call(r,e,t,i)},r,i)},zip:function(t,n){var r={};return e.Array.each(t,function(e,t){r[e.toString()]=n[t]}),r}}),e.Object.reduceRight=e.Object.reduce,e.mix(e.Array,{toObject:function(t,n){var r={};return e.Array.each(t,function(e){r[e[n]]=e}),r}})},"@VERSION@",{requires:[""],optional:["gallery-funcprog"]}); |