Bug 379745, add some additional template sort hint options to sort case-insensitive, sort by integers, and skip natural sort order, r=neil,sr=sicking

This commit is contained in:
Neil Deakin 2010-06-16 13:09:51 -04:00
Родитель ce7169288e
Коммит 2a82f1fe95
16 изменённых файлов: 331 добавлений и 75 удалений

Просмотреть файл

@ -845,6 +845,7 @@ GK_ATOM(sort, "sort")
GK_ATOM(sortActive, "sortActive")
GK_ATOM(sortDirection, "sortDirection")
GK_ATOM(sorted, "sorted")
GK_ATOM(sorthints, "sorthints")
GK_ATOM(sortLocked, "sortLocked")
GK_ATOM(sortResource, "sortResource")
GK_ATOM(sortResource2, "sortResource2")

Просмотреть файл

@ -45,6 +45,9 @@ interface nsIDOMNode;
[scriptable, uuid(F29270C8-3BE5-4046-9B57-945A84DFF132)]
interface nsIXULSortService : nsISupports
{
const unsigned long SORT_COMPARECASE = 0x0001;
const unsigned long SORT_INTEGER = 0x0100;
/**
* Sort the contents of the widget containing <code>aNode</code>
* using <code>aSortKey</code> as the comparison key, and
@ -52,14 +55,17 @@ interface nsIXULSortService : nsISupports
*
* @param aNode A node in the XUL widget whose children are to be sorted.
* @param aSortKey The value to be used as the comparison key.
* @param aSortDirection May be either <b>natural</b> to return
* the contents to their natural (unsorted) order,
* <b>ascending</b> to sort the contents in ascending order, or
* <b>descending</b> to sort the contents in descending order.
* @param aSortHints One or more hints as to how to sort:
*
* ascending: to sort the contents in ascending order
* descending: to sort the contents in descending order
* comparecase: perform case sensitive comparisons
* integer: treat values as integers, non-integers are compared as strings
* twostate: don't allow the natural (unordered state)
*/
void sort(in nsIDOMNode aNode,
in AString aSortKey,
in AString aSortDirection);
in AString aSortHints);
};
%{C++

Просмотреть файл

@ -107,7 +107,7 @@ interface nsIXULTemplateBuilder;
* nsIRDFDataSource or a DOM node, and will always be the same one in between
* calls to initializeForBuilding and done.
*/
[scriptable, uuid(970f1c36-5d2e-4cbc-a1cf-e3327b50df71)]
[scriptable, uuid(C257573F-444F-468A-BA27-DE979DC55FE4)]
interface nsIXULTemplateQueryProcessor : nsISupports
{
/**
@ -291,6 +291,8 @@ interface nsIXULTemplateQueryProcessor : nsISupports
* sorted in a natural order, for instance, based on the order the data in
* stored in the datasource.
*
* The sort hints are the flags in nsIXULSortService.
*
* This method must only be called with results that were created by this
* query processor.
*
@ -302,5 +304,6 @@ interface nsIXULTemplateQueryProcessor : nsISupports
*/
PRInt32 compareResults(in nsIXULTemplateResult aLeft,
in nsIXULTemplateResult aRight,
in nsIAtom aVar);
in nsIAtom aVar,
in unsigned long aSortHints);
};

Просмотреть файл

@ -1839,7 +1839,8 @@ nsXULContentBuilder::CompareResultToNode(nsIXULTemplateResult* aResult,
if (mSortState.direction == nsSortState_natural) {
// sort in natural order
nsresult rv = mQueryProcessor->CompareResults(aResult, match->mResult,
nsnull, aSortOrder);
nsnull, mSortState.sortHints,
aSortOrder);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
@ -1848,7 +1849,8 @@ nsXULContentBuilder::CompareResultToNode(nsIXULTemplateResult* aResult,
PRInt32 length = mSortState.sortKeys.Count();
for (PRInt32 t = 0; t < length; t++) {
nsresult rv = mQueryProcessor->CompareResults(aResult, match->mResult,
mSortState.sortKeys[t], aSortOrder);
mSortState.sortKeys[t],
mSortState.sortHints, aSortOrder);
NS_ENSURE_SUCCESS(rv, rv);
if (*aSortOrder)
@ -1872,9 +1874,12 @@ nsXULContentBuilder::InsertSortedNode(nsIContent* aContainer,
nsresult rv;
if (!mSortState.initialized) {
nsAutoString sort, sortDirection;
nsAutoString sort, sortDirection, sortHints;
mRoot->GetAttr(kNameSpaceID_None, nsGkAtoms::sort, sort);
mRoot->GetAttr(kNameSpaceID_None, nsGkAtoms::sortDirection, sortDirection);
mRoot->GetAttr(kNameSpaceID_None, nsGkAtoms::sorthints, sortHints);
sortDirection.AppendLiteral(" ");
sortDirection += sortHints;
rv = XULSortServiceImpl::InitializeSortState(mRoot, aContainer,
sort, sortDirection, &mSortState);
NS_ENSURE_SUCCESS(rv, rv);

Просмотреть файл

@ -72,6 +72,8 @@
#include "nsIDOMXULElement.h"
#include "nsIXULTemplateBuilder.h"
#include "nsTemplateMatch.h"
#include "nsICollation.h"
#include "nsUnicharUtils.h"
NS_IMPL_ISUPPORTS1(XULSortServiceImpl, nsIXULSortService)
@ -156,7 +158,7 @@ XULSortServiceImpl::GetItemsToSort(nsIContent *aContainer,
if (builder) {
nsresult rv = builder->GetQueryProcessor(getter_AddRefs(aSortState->processor));
if (NS_FAILED(rv) || !aSortState->processor)
return rv;
return rv;
return GetTemplateItemsToSort(aContainer, builder, aSortState, aSortItems);
}
@ -174,7 +176,7 @@ XULSortServiceImpl::GetItemsToSort(nsIContent *aContainer,
return NS_OK;
aContainer = treechildren;
}
}
PRUint32 count = aContainer->GetChildCount();
for (PRUint32 c = 0; c < count; c++) {
@ -185,9 +187,9 @@ XULSortServiceImpl::GetItemsToSort(nsIContent *aContainer,
return NS_ERROR_OUT_OF_MEMORY;
cinfo->content = child;
}
}
return NS_OK;
return NS_OK;
}
@ -214,7 +216,7 @@ XULSortServiceImpl::GetTemplateItemsToSort(nsIContent* aContainer,
cinfo->content = child;
cinfo->result = result;
}
}
else if (aContainer->Tag() != nsGkAtoms::_template) {
rv = GetTemplateItemsToSort(child, aBuilder, aSortState, aSortItems);
NS_ENSURE_SUCCESS(rv, rv);
@ -237,7 +239,7 @@ testSortCallback(const void *data1, const void *data2, void *privateData)
if (sortState->direction == nsSortState_natural && sortState->processor) {
// sort in natural order
sortState->processor->CompareResults(left->result, right->result,
nsnull, &sortOrder);
nsnull, sortState->sortHints, &sortOrder);
}
else {
PRInt32 length = sortState->sortKeys.Count();
@ -245,21 +247,19 @@ testSortCallback(const void *data1, const void *data2, void *privateData)
// for templates, use the query processor to do sorting
if (sortState->processor) {
sortState->processor->CompareResults(left->result, right->result,
sortState->sortKeys[t], &sortOrder);
sortState->sortKeys[t],
sortState->sortHints, &sortOrder);
if (sortOrder)
break;
}
}
else {
// no template, so just compare attributes. Ignore namespaces for now.
nsAutoString leftstr, rightstr;
left->content->GetAttr(kNameSpaceID_None, sortState->sortKeys[t], leftstr);
right->content->GetAttr(kNameSpaceID_None, sortState->sortKeys[t], rightstr);
if (!leftstr.Equals(rightstr)) {
sortOrder = (leftstr > rightstr) ? 1 : -1;
break;
}
}
sortOrder = XULSortServiceImpl::CompareValues(leftstr, rightstr, sortState->sortHints);
}
}
}
@ -297,18 +297,18 @@ XULSortServiceImpl::SortContainer(nsIContent *aContainer, nsSortState* aSortStat
sizeof(contentSortInfo), testSortCallback, (void*)aSortState);
startIndex = i + 1;
}
}
}
}
if (i > startIndex + 1) {
if (aSortState->invertSort)
InvertSortInfo(items, startIndex, i - startIndex);
else
else
NS_QuickSort((void *)(items.Elements() + startIndex), i - startIndex,
sizeof(contentSortInfo), testSortCallback, (void*)aSortState);
}
} else {
}
} else {
// if the items are just being inverted, that is, just switching between
// ascending and descending, just reverse the list.
if (aSortState->invertSort)
@ -330,8 +330,8 @@ XULSortServiceImpl::SortContainer(nsIContent *aContainer, nsSortState* aSortStat
items[i].parent = parent;
PRInt32 index = parent->IndexOf(child);
parent->RemoveChildAt(index, PR_TRUE);
}
}
}
// now add the items back in sorted order
for (i = 0; i < numResults; i++)
@ -384,7 +384,7 @@ nsresult
XULSortServiceImpl::InitializeSortState(nsIContent* aRootElement,
nsIContent* aContainer,
const nsAString& aSortKey,
const nsAString& aSortDirection,
const nsAString& aSortHints,
nsSortState* aSortState)
{
// used as an optimization for the content builder
@ -428,17 +428,33 @@ XULSortServiceImpl::InitializeSortState(nsIContent* aRootElement,
}
aSortState->sort.Assign(sort);
aSortState->direction = nsSortState_natural;
PRBool noNaturalState = PR_FALSE;
nsWhitespaceTokenizer tokenizer(aSortHints);
while (tokenizer.hasMoreTokens()) {
const nsDependentSubstring& token(tokenizer.nextToken());
if (token.EqualsLiteral("comparecase"))
aSortState->sortHints |= nsIXULSortService::SORT_COMPARECASE;
else if (token.EqualsLiteral("integer"))
aSortState->sortHints |= nsIXULSortService::SORT_INTEGER;
else if (token.EqualsLiteral("descending"))
aSortState->direction = nsSortState_descending;
else if (token.EqualsLiteral("ascending"))
aSortState->direction = nsSortState_ascending;
else if (token.EqualsLiteral("twostate"))
noNaturalState = PR_TRUE;
}
// if the twostate flag was set, the natural order is skipped and only
// ascending and descending are allowed
if (aSortState->direction == nsSortState_natural && noNaturalState) {
aSortState->direction = nsSortState_ascending;
}
// set up sort order info
if (aSortDirection.EqualsLiteral("descending"))
aSortState->direction = nsSortState_descending;
else if (aSortDirection.EqualsLiteral("ascending"))
aSortState->direction = nsSortState_ascending;
else
aSortState->direction = nsSortState_natural;
aSortState->invertSort = PR_FALSE;
nsAutoString existingsort;
aRootElement->GetAttr(kNameSpaceID_None, nsGkAtoms::sort, existingsort);
nsAutoString existingsortDirection;
@ -449,14 +465,14 @@ XULSortServiceImpl::InitializeSortState(nsIContent* aRootElement,
if (aSortState->direction == nsSortState_descending) {
if (existingsortDirection.EqualsLiteral("ascending"))
aSortState->invertSort = PR_TRUE;
}
}
else if (aSortState->direction == nsSortState_ascending &&
existingsortDirection.EqualsLiteral("descending")) {
existingsortDirection.EqualsLiteral("descending")) {
aSortState->invertSort = PR_TRUE;
}
}
// sort items between separatore independently
// sort items between separators independently
aSortState->inbetweenSeparatorSort =
aRootElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::sortSeparators,
nsGkAtoms::_true, eCaseMatters);
@ -471,10 +487,42 @@ XULSortServiceImpl::InitializeSortState(nsIContent* aRootElement,
return NS_OK;
}
PRInt32
XULSortServiceImpl::CompareValues(const nsAString& aLeft,
const nsAString& aRight,
PRUint32 aSortHints)
{
if (aSortHints & SORT_INTEGER) {
PRInt32 err;
PRInt32 leftint = nsDependentString(aLeft).ToInteger(&err);
if (NS_SUCCEEDED(err)) {
PRInt32 rightint = nsDependentString(aRight).ToInteger(&err);
if (NS_SUCCEEDED(err)) {
return leftint - rightint;
}
}
// if they aren't integers, just fall through and compare strings
}
if (aSortHints & SORT_COMPARECASE) {
return ::Compare(aLeft, aRight);
}
nsICollation* collation = nsXULContentUtils::GetCollation();
if (collation) {
PRInt32 result;
collation->CompareString(nsICollation::kCollationCaseInSensitive,
aLeft, aRight, &result);
return result;
}
return ::Compare(aLeft, aRight, nsCaseInsensitiveStringComparator());
}
NS_IMETHODIMP
XULSortServiceImpl::Sort(nsIDOMNode* aNode,
const nsAString& aSortKey,
const nsAString& aSortDirection)
const nsAString& aSortHints)
{
// get root content node
nsCOMPtr<nsIContent> sortNode = do_QueryInterface(aNode);
@ -483,7 +531,7 @@ XULSortServiceImpl::Sort(nsIDOMNode* aNode,
nsSortState sortState;
nsresult rv = InitializeSortState(sortNode, sortNode,
aSortKey, aSortDirection, &sortState);
aSortKey, aSortHints, &sortState);
NS_ENSURE_SUCCESS(rv, rv);
// store sort info in attributes on content

Просмотреть файл

@ -80,6 +80,8 @@ struct nsSortState
PRBool sortStaticsLast;
PRBool isContainerRDFSeq;
PRUint32 sortHints;
nsSortState_direction direction;
nsAutoString sort;
nsCOMArray<nsIAtom> sortKeys;
@ -89,7 +91,8 @@ struct nsSortState
PRBool lastWasFirst, lastWasLast;
nsSortState()
: initialized(PR_FALSE)
: initialized(PR_FALSE),
sortHints(0)
{
}
void Traverse(nsCycleCollectionTraversalCallback &cb) const
@ -203,4 +206,12 @@ public:
const nsAString& aSortKey,
const nsAString& aSortDirection,
nsSortState* aSortState);
/**
* Compares aLeft and aRight and returns < 0, 0, or > 0. The sort
* hints are checked for case matching and integer sorting.
*/
static PRInt32 CompareValues(const nsAString& aLeft,
const nsAString& aRight,
PRUint32 aSortHints);
};

Просмотреть файл

@ -55,7 +55,6 @@
#include "nsGkAtoms.h"
#include "nsIDocument.h"
#include "nsIXULDocument.h"
#include "nsUnicharUtils.h"
#include "nsAttrName.h"
#include "rdf.h"
#include "nsArrayUtils.h"
@ -71,6 +70,7 @@
#include "nsXULTemplateResultRDF.h"
#include "nsXULTemplateResultSetRDF.h"
#include "nsXULTemplateQueryProcessorRDF.h"
#include "nsXULSortService.h"
//----------------------------------------------------------------------
@ -654,6 +654,7 @@ NS_IMETHODIMP
nsXULTemplateQueryProcessorRDF::CompareResults(nsIXULTemplateResult* aLeft,
nsIXULTemplateResult* aRight,
nsIAtom* aVar,
PRUint32 aSortHints,
PRInt32* aResult)
{
NS_ENSURE_ARG_POINTER(aLeft);
@ -704,7 +705,7 @@ nsXULTemplateQueryProcessorRDF::CompareResults(nsIXULTemplateResult* aLeft,
else {
// get the values for the sort key from the results
aLeft->GetBindingObjectFor(aVar, getter_AddRefs(leftNode));
aRight->GetBindingObjectFor(aVar, getter_AddRefs(rightNode));
aRight->GetBindingObjectFor(aVar, getter_AddRefs(rightNode));
}
{
@ -717,18 +718,12 @@ nsXULTemplateQueryProcessorRDF::CompareResults(nsIXULTemplateResult* aLeft,
l->GetValueConst(&lstr);
r->GetValueConst(&rstr);
nsICollation* collation = nsXULContentUtils::GetCollation();
if (collation) {
collation->CompareString(nsICollation::kCollationCaseInSensitive,
nsDependentString(lstr),
nsDependentString(rstr),
aResult);
}
else
*aResult = ::Compare(nsDependentString(lstr),
nsDependentString(rstr),
nsCaseInsensitiveStringComparator());
*aResult = XULSortServiceImpl::CompareValues(
nsDependentString(lstr),
nsDependentString(rstr), aSortHints);
}
return NS_OK;
}
}
@ -752,6 +747,8 @@ nsXULTemplateQueryProcessorRDF::CompareResults(nsIXULTemplateResult* aLeft,
else
*aResult = -1;
}
return NS_OK;
}
}
@ -767,6 +764,8 @@ nsXULTemplateQueryProcessorRDF::CompareResults(nsIXULTemplateResult* aLeft,
*aResult = lval - rval;
}
return NS_OK;
}
}

Просмотреть файл

@ -54,6 +54,7 @@
#include "nsXULTemplateBuilder.h"
#include "nsXULTemplateResultStorage.h"
#include "nsXULContentUtils.h"
#include "nsXULSortService.h"
#include "mozIStorageService.h"
@ -468,6 +469,7 @@ NS_IMETHODIMP
nsXULTemplateQueryProcessorStorage::CompareResults(nsIXULTemplateResult* aLeft,
nsIXULTemplateResult* aRight,
nsIAtom* aVar,
PRUint32 aSortHints,
PRInt32* aResult)
{
*aResult = 0;
@ -524,14 +526,12 @@ nsXULTemplateQueryProcessorStorage::CompareResults(nsIXULTemplateResult* aLeft,
// Values are not integers or floats, so we just compare them as simple strings
nsAutoString leftVal;
if (aLeft)
aLeft->GetBindingFor(aVar, leftVal);
aLeft->GetBindingFor(aVar, leftVal);
nsAutoString rightVal;
if (aRight)
aRight->GetBindingFor(aVar, rightVal);
aRight->GetBindingFor(aVar, rightVal);
*aResult = Compare(nsDependentString(leftVal),
nsDependentString(rightVal),
nsCaseInsensitiveStringComparator());
*aResult = XULSortServiceImpl::CompareValues(leftVal, rightVal, aSortHints);
return NS_OK;
}

Просмотреть файл

@ -61,6 +61,7 @@
#include "nsXULTemplateBuilder.h"
#include "nsXULTemplateQueryProcessorXML.h"
#include "nsXULTemplateResultXML.h"
#include "nsXULSortService.h"
NS_IMPL_ISUPPORTS1(nsXMLQuery, nsXMLQuery)
@ -428,27 +429,22 @@ NS_IMETHODIMP
nsXULTemplateQueryProcessorXML::CompareResults(nsIXULTemplateResult* aLeft,
nsIXULTemplateResult* aRight,
nsIAtom* aVar,
PRUint32 aSortHints,
PRInt32* aResult)
{
*aResult = 0;
if (!aVar)
return NS_OK;
// XXXndeakin - bug 379745
// it would be good for this to handle other types such as integers,
// so that sorting can be optimized for different types.
return NS_OK;
nsAutoString leftVal;
if (aLeft)
aLeft->GetBindingFor(aVar, leftVal);
aLeft->GetBindingFor(aVar, leftVal);
nsAutoString rightVal;
if (aRight)
aRight->GetBindingFor(aVar, rightVal);
aRight->GetBindingFor(aVar, rightVal);
// currently templates always sort case-insensitive
*aResult = ::Compare(leftVal, rightVal,
nsCaseInsensitiveStringComparator());
*aResult = XULSortServiceImpl::CompareValues(leftVal, rightVal, aSortHints);
return NS_OK;
}

Просмотреть файл

@ -59,10 +59,12 @@
#include "nsGkAtoms.h"
#include "nsXULContentUtils.h"
#include "nsXULTemplateBuilder.h"
#include "nsIXULSortService.h"
#include "nsTArray.h"
#include "nsUnicharUtils.h"
#include "nsINameSpaceManager.h"
#include "nsIDOMClassInfo.h"
#include "nsWhitespaceTokenizer.h"
// For security check
#include "nsIDocument.h"
@ -262,6 +264,11 @@ protected:
*/
Direction mSortDirection;
/*
* Sort hints (compare case, etc)
*/
PRUint32 mSortHints;
/**
* The builder observers.
*/
@ -308,7 +315,7 @@ NS_INTERFACE_MAP_END_INHERITING(nsXULTemplateBuilder)
nsXULTreeBuilder::nsXULTreeBuilder()
: mSortDirection(eDirection_Natural)
: mSortDirection(eDirection_Natural), mSortHints(0)
{
}
@ -395,6 +402,21 @@ nsXULTreeBuilder::Sort(nsIDOMElement* aElement)
// Grab the new sort variable
mSortVariable = do_GetAtom(sort);
nsAutoString hints;
header->GetAttr(kNameSpaceID_None, nsGkAtoms::sorthints, hints);
PRBool hasNaturalState = PR_TRUE;
nsWhitespaceTokenizer tokenizer(hints);
while (tokenizer.hasMoreTokens()) {
const nsDependentSubstring& token(tokenizer.nextToken());
if (token.EqualsLiteral("comparecase"))
mSortHints |= nsIXULSortService::SORT_COMPARECASE;
else if (token.EqualsLiteral("integer"))
mSortHints |= nsIXULSortService::SORT_INTEGER;
else if (token.EqualsLiteral("twostate"))
hasNaturalState = PR_FALSE;
}
// Cycle the sort direction
nsAutoString dir;
header->GetAttr(kNameSpaceID_None, nsGkAtoms::sortDirection, dir);
@ -403,7 +425,7 @@ nsXULTreeBuilder::Sort(nsIDOMElement* aElement)
dir.AssignLiteral("descending");
mSortDirection = eDirection_Descending;
}
else if (dir.EqualsLiteral("descending")) {
else if (hasNaturalState && dir.EqualsLiteral("descending")) {
dir.AssignLiteral("natural");
mSortDirection = eDirection_Natural;
}
@ -1865,7 +1887,7 @@ nsXULTreeBuilder::CompareResults(nsIXULTemplateResult* aLeft, nsIXULTemplateResu
}
PRInt32 sortorder;
mQueryProcessor->CompareResults(aLeft, aRight, mSortVariable, &sortorder);
mQueryProcessor->CompareResults(aLeft, aRight, mSortVariable, mSortHints, &sortorder);
if (sortorder)
sortorder = sortorder * mSortDirection;

Просмотреть файл

@ -49,6 +49,7 @@ _TEST_FILES = \
test_bug441785.xul \
bug441785-1.rdf \
bug441785-2.rdf \
test_sortservice.xul \
$(NULL)
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -140,6 +140,7 @@ _TEST_FILES = \
test_tmpl_simplesyntaxfilter.xul \
test_tmpl_sortascendingquerysyntax.xul \
test_tmpl_sortdescendingquerysyntax.xul \
test_tmpl_sortascendinginteger.xul \
test_tmpl_sortunknownascendingquerysyntax.xul \
test_tmpl_sortresourceascendingquerysyntax.xul \
test_tmpl_sortresourcedescendingquerysyntax.xul \

Просмотреть файл

@ -0,0 +1,71 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<!--
sort ascending - integers
-->
<window title="XUL Template Tests" width="500" height="600"
onload="test_template();"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
<script src="templates_shared.js"/>
<script>
<![CDATA[
SimpleTest.waitForExplicitFinish();
var testid ="sort ascending - integers";
var queryType = "rdf";
var isTreeBuilder = false;
var needsOpen = false;
var notWorkingYet = false;
var notWorkingYetDynamic = false;
var expectedOutput =
<output>
<label id="http://www.some-fictitious-zoo.com/mammals/ninebandedarmadillo" value="Nine-banded Armadillo"/>
<label id="http://www.some-fictitious-zoo.com/mammals/aardvark" value="aardvark"/>
<label id="http://www.some-fictitious-zoo.com/mammals/hippopotamus" value="HIPPOPOTAMUS"/>
<label id="http://www.some-fictitious-zoo.com/mammals/lion" value="Lion"/>
<label step="-1" id="http://www.some-fictitious-zoo.com/mammals/llama" value="LLAMA"/>
<label id="http://www.some-fictitious-zoo.com/mammals/gorilla" value="Gorilla"/>
<label step="1" id="http://www.some-fictitious-zoo.com/mammals/llama" value="LLAMA"/>
<label id="http://www.some-fictitious-zoo.com/mammals/africanelephant" value="African Elephant"/>
<label id="http://www.some-fictitious-zoo.com/mammals/polarbear" value="Polar Bear"/>
</output>;
var changes = [
// step 1
function(targetds, root) {
var subject = RDF.GetResource(ZOO_NS + 'mammals/llama');
var predicate = RDF.GetResource(ZOO_NS + 'rdf#specimensAsString');
var oldval = targetds.GetTarget(subject, predicate, true);
targetds.Change(subject, predicate, oldval, RDF.GetLiteral('12'), true);
}
];
]]>
</script>
<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" id="root" datasources="animals.rdf"
ref="http://www.some-fictitious-zoo.com/mammals" sort="?specimens ?name" sortDirection="ascending" sorthints="integer">
<template id="template">
<query id="query">
<content uri="?uri"/>
<member container="?uri" child="?animal"/>
<triple subject="?animal" predicate="http://www.some-fictitious-zoo.com/rdf#name" object="?name"/>
<triple subject="?animal" predicate="http://www.some-fictitious-zoo.com/rdf#specimensAsString" object="?specimens"/>
</query>
<action id="action">
<label uri="?animal" value="?name"/>
</action>
</template>
</vbox>
</window>

Просмотреть файл

@ -0,0 +1,73 @@
<?xml version="1.0" ?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<vbox id="box"/>
<body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/x-javascript">
<![CDATA[
var tests = [
[["One", "Two", "Three", "Four"], "", ["Four One Three Two"]],
[["One", "Two", "Three", "Four"], "integer", ["Four One Three Two"]],
[["One", "Two", "Three", "Four"], "descending", ["Two Three One Four"]],
[["One", "Two", "Three", "Four"], "descending integer", ["Two Three One Four"]],
[["One", "Two", "Three", "Four"], "integer cat descending", ["Two Three One Four"]],
[["1", "13", "2", "7", "12", "240", "2", "170", "222", "98"], "", ["1 12 13 170 2 2 222 240 7 98"]],
[["1", "13", "2", "7", "12", "240", "2", "170", "222", "98"], "integer", ["1 2 2 7 12 13 98 170 222 240"]],
[["1", "13", "2", "7", "12", "240", "2", "170", "222", "98"], "ascending integer", ["1 2 2 7 12 13 98 170 222 240"]],
[["1", "13", "2", "7", "12", "240", "2", "170", "222", "98"], "integer descending", ["240 222 170 98 13 12 7 2 2 1"]],
[["Cat", "cat", "Candy", "candy"], "comparecase", ["Candy Cat candy cat"]],
[["1", "102", "22", "One", "40", "Two"], "integer", ["1 22 40 102 One Two"]],
];
SimpleTest.waitForExplicitFinish();
function doTests()
{
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var box = document.getElementById("box");
const sortService = Components.classes["@mozilla.org/xul/xul-sort-service;1"].
getService(Components.interfaces.nsIXULSortService);
for (let t = 0; t < tests.length; t++) {
var test = tests[t];
for (let e = 0; e < test[0].length; e++) {
var label = document.createElement("label");
label.setAttribute("value", test[0][e]);
box.appendChild(label);
}
sortService.sort(box, "value", test[1]);
var actual = "";
for (let e = 0; e < box.childNodes.length; e++) {
if (actual)
actual += " ";
actual += box.childNodes[e].getAttribute("value");
}
is(actual, test[2], "sorted step " + (t + 1));
while(box.hasChildNodes())
box.removeChild(box.firstChild);
box.removeAttribute("sortDirection");
}
SimpleTest.finish();
}
window.addEventListener("load", doTests, false);
]]>
</script>
</window>

Просмотреть файл

@ -635,6 +635,11 @@ nsTreeContentView::CycleHeader(nsITreeColumn* aCol)
default: sortdirection.AssignLiteral("ascending"); break;
}
nsAutoString hints;
column->GetAttr(kNameSpaceID_None, nsGkAtoms::sorthints, hints);
sortdirection.AppendLiteral(" ");
sortdirection += hints;
nsCOMPtr<nsIDOMNode> rootnode = do_QueryInterface(mRoot);
xs->Sort(rootnode, sort, sortdirection);
}

Просмотреть файл

@ -1031,6 +1031,20 @@ function testtag_tree_TreeView_rows_sort(tree, testid, rowInfo)
// Check we have gone back to natural sorting.
is(columnElement.getAttribute("sortDirection"), "",
"cycleHeader column sortDirection");
columnElement.setAttribute("sorthints", "twostate");
view.cycleHeader(column);
is(tree.getAttribute("sortDirection"), "ascending", "cycleHeader sortDirection ascending twostate");
view.cycleHeader(column);
is(tree.getAttribute("sortDirection"), "descending", "cycleHeader sortDirection ascending twostate");
view.cycleHeader(column);
is(tree.getAttribute("sortDirection"), "ascending", "cycleHeader sortDirection ascending twostate again");
columnElement.removeAttribute("sorthints");
view.cycleHeader(column);
view.cycleHeader(column);
is(columnElement.getAttribute("sortDirection"), "",
"cycleHeader column sortDirection reset");
}
// checks if the current and selected rows are correct