Skip to content

Commit

Permalink
Merge branch 'master' of git://github.com/SitePen/dgrid
Browse files Browse the repository at this point in the history
Conflicts:
	List.js
	test/JsonRest.html
	test/data/rest.php
  • Loading branch information
kriszyp committed Jan 9, 2014
2 parents 4a40399 + ed0b560 commit 0d3278d
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 43 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Expand Up @@ -7,6 +7,8 @@ This document outlines changes since 0.3.0. For older changelogs, see the

### General/Core

* Added logic to account for `dojo/store/Observable`'s propensity to drop items
at page boundaries, primarily in the `List` module. (#701, #714)
* Fixed a long-standing regression in the `util/has-css3` module's
`css-transforms3d` test due to a modified classname. (#776, thanks amuraco)

Expand Down
107 changes: 66 additions & 41 deletions List.js
Expand Up @@ -473,18 +473,20 @@ function(kernel, declare, listen, has, miscUtil, TouchScroll, hasClass, put){
if(from > -1 && rows[from]){
// remove from old slot
row = rows.splice(from, 1)[0];
// check to make the sure the node is still there before we try to remove it, (in case it was moved to a different place in the DOM)
// check to make sure the node is still there before we try to remove it
// (in case it was moved to a different place in the DOM)
if(row.parentNode == container){
firstRow = row.nextSibling;
if(firstRow){ // it's possible for this to have been already removed if it is in overlapping query results
if(from != to){ // if from and to are identical, it is an in-place update and we don't want to alter the rowIndex at all
firstRow.rowIndex--; // adjust the rowIndex so adjustRowIndices has the right starting point
}
}
self.removeRow(row); // now remove
self.removeRow(row);
}
// Update count to reflect that we lost one row
options.count--;
// the removal of rows could cause us to need to page in more items
// The removal of rows could cause us to need to page in more items
if(self._processScroll){
self._processScroll();
}
Expand All @@ -493,11 +495,13 @@ function(kernel, declare, listen, has, miscUtil, TouchScroll, hasClass, put){
// Add to new slot (either before an existing row, or at the end)
// First determine the DOM node that this should be placed before.
if(rows.length){
nextNode = rows[to];
if(nextNode){
if(to < 2){ // if it is one of the first rows, we can safely get the next item
nextNode = rows[to];
// Re-retrieve the element in case we are referring to an orphan
nextNode = correctElement(nextNode);
nextNode = nextNode && correctElement(nextNode);
}else{
// If we are near the end of the page, we may not be able to retrieve the
// result from our own array, so go from the previous row and advance one
nextNode = rows[to - 1];
if(nextNode){
// Make sure to skip connected nodes, so we don't accidentally
Expand Down Expand Up @@ -538,10 +542,11 @@ function(kernel, declare, listen, has, miscUtil, TouchScroll, hasClass, put){
}

if(from === 0){
overlapRows([1,1]);
}
else if(from === results.length - 1){
overlapRows([0,0]);
overlapRows(1, 1);
}else if(from === results.length - (to === -1 ? 0 : 1)){
// It was (re)moved from the end
// (which was the previous length if it was a removal)
overlapRows(0, 0);
}

from != to && firstRow && self.adjustRowIndices(firstRow);
Expand All @@ -551,38 +556,49 @@ function(kernel, declare, listen, has, miscUtil, TouchScroll, hasClass, put){
var rowsFragment = document.createDocumentFragment(),
lastRow;

function overlapRows(sides){
// This is responsible for setting row overlaps in result
// sets to ensure that observable can always properly determine which page
function overlapRows(){
// This is responsible for setting row overlaps in result sets to
// ensure that observable can always properly determine which page
// an object belongs to.
// This is function uses kind of an esoteric argument optimized for
// performance and size, since it is called quite frequently
// The sides is an array of overlapping operations, with a falsy item indicating
// This function uses kind of an esoteric argument, optimized for
// performance and size, since it is called quite frequently.
// `sides` is an array of overlapping operations, with a falsy item indicating
// to add an overlap to the top, and a truthy item means to add an overlap
// to the bottom (so [0, 1] adds one overlap to the top and the bottom)

var sides = arguments;
// Only perform row overlap in the case of observable results
if(observerIndex > -1){
// Only perform row overlap in the case of observable results
// now iterate through the sides operations
// Iterate through the sides operations
for(var i = 0; i < sides.length; i++){
var top = sides[i];
// make sure we have the correct row element
var lastRow = correctElement(rows[top ? 0 : rows.length-1]);
var row = self[top ? "up" : "down"](self.row(lastRow));
if(row && row.element != lastRow){
var method = top ? "unshift" : "push";
// now take the row and data from the adjacent page and unshift to the
// top or push to the bottom of our array of rows and results
results[method](row.data);
rows[method](row.element);
// and adjust the count
options.count++;
var lastRow = rows[top ? 0 : rows.length-1];
// check to make sure we have a row, we won't if we don't have any rows
if(lastRow){
// Make sure we have the correct row element
// (not one that was previously removed)
lastRow = correctElement(lastRow);
var row = self[top ? "up" : "down"](self.row(lastRow));
if(row && row.element != lastRow){
var method = top ? "unshift" : "push";
// Take the row and data from the adjacent page and unshift to the
// top or push to the bottom of our array of rows and results,
// and adjust the count
results[method](row.data);
rows[method](row.element);
options.count++;
}
}
}
}
}
function correctElement(row){
// if a node has been orphaned, this will retrieve the correct, in-document, element.
return self.row(row.id.slice(self.id.length + 5)).element;
// If a node has been orphaned, try to retrieve the correct, in-document, element
if(!row.offsetParent && byId(row.id)){
return self.row(row.id.slice(self.id.length + 5)).element;
}
// Fall back to the originally-specified element
return row;
}

function mapEach(object){
Expand All @@ -600,7 +616,10 @@ function(kernel, declare, listen, has, miscUtil, TouchScroll, hasClass, put){
throw error;
}
}
var originalRows;
function whenDone(resolvedRows){
// Save the original rows, before the overlapping is performed
originalRows = resolvedRows.slice(0);
container = beforeNode ? beforeNode.parentNode : self.contentNode;
if(container && container.parentNode &&
(container !== self.contentNode || resolvedRows.length)){
Expand All @@ -612,19 +631,24 @@ function(kernel, declare, listen, has, miscUtil, TouchScroll, hasClass, put){
// rows are already out of view or there were none to track
whenError();
}
return (rows = resolvedRows);
rows = resolvedRows;
}

// now render the results
// Now render the results
if(results.map){
rows = results.map(mapEach, console.error);
if(rows.then){
results.then(function(resultsArray){
return results.then(function(resultsArray){
results = resultsArray;
// overlap rows in the results array when using observable so that we can determine page boundary changes
overlapRows([1,1,0,0]);
return rows.then(function(resolvedRows){
whenDone(resolvedRows);
// Overlap rows in the results array when using observable
// so that we can determine page boundary changes
// (but return the original set)
overlapRows(1, 1, 0, 0);
return originalRows;
});
});
return rows.then(whenDone);
}
}else{
rows = [];
Expand All @@ -634,8 +658,9 @@ function(kernel, declare, listen, has, miscUtil, TouchScroll, hasClass, put){
}

whenDone(rows);
overlapRows([1,1,0,0]);
return rows;
overlapRows(1, 1, 0, 0);
// Return the original rows, not the overlapped set
return originalRows;
},

_onNotification: function(rows, object, from, to){
Expand Down Expand Up @@ -767,7 +792,7 @@ function(kernel, declare, listen, has, miscUtil, TouchScroll, hasClass, put){
}while((nextSibling = (!visible || !current.hidden) && current[steps < 0 ? "lastChild" : "firstChild"]));
}else{
current = current.parentNode;
if(current === this.bodyNode || current === this.headerNode){
if(!current || current === this.bodyNode || current === this.headerNode){
// Break out if we step out of the navigation area entirely.
break;
}
Expand Down Expand Up @@ -981,4 +1006,4 @@ function(kernel, declare, listen, has, miscUtil, TouchScroll, hasClass, put){
this.resize(); // to account for (dis)appearance of footer
}
});
});
});
7 changes: 7 additions & 0 deletions OnDemandList.js
Expand Up @@ -558,6 +558,13 @@ return declare([List, _StoreMixin], {

// recalculate the count
below.count = total - below.node.rowIndex;
// check to see if we are on the last page
if(below.count === 0){
// This is a hack to get Observable to recognize that this is the
// last page; if the count doesn't match results.length, Observable
// will think this is the last page and properly handle additions to the bottom
options.count++;
}
// readjust the height
adjustHeight(below);
}
Expand Down
1 change: 1 addition & 0 deletions test/JsonRest.html
Expand Up @@ -43,6 +43,7 @@
var columns = [
tree({label:'Name', field:'name', sortable: false}),
{label:'Id', field:'id', sortable: true},
{label:'Id', field:'id'},
editor({label:'Comment', field:'comment', sortable: false}, "text"),
editor({label:'Boolean', field:'boo', sortable: false, autoSave: true}, "checkbox")
];
Expand Down
4 changes: 2 additions & 2 deletions test/data/rest.php
Expand Up @@ -3,7 +3,7 @@
$total = 500;
$id_prefix = "";
if(isset($_GET["parent"])){
$id_prefix = $_GET["parent"]."-";
$id_prefix = ($_GET["parent"] + 1) * 1000;
}
usleep(rand(0,500000));
$range = "";
Expand All @@ -30,7 +30,7 @@
if($i != $start){
echo ',';
}
echo '{"id":'.$id_prefix.$i.',"name":"Item '.$i.'","comment":"hello"}';
echo '{"id":'.($id_prefix+$i).',"name":"Item '.$i.'","comment":"hello"}';
}
echo ']';
?>

0 comments on commit 0d3278d

Please sign in to comment.