Page Menu
Home
Code
Search
Configure Global Search
Log In
Files
F945895
XmlStore.js
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
33 KB
Subscribers
None
XmlStore.js
View Options
if
(
!
dojo
.
_hasResource
[
"dojox.data.XmlStore"
]){
//_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo
.
_hasResource
[
"dojox.data.XmlStore"
]
=
true
;
dojo
.
provide
(
"dojox.data.XmlStore"
);
dojo
.
provide
(
"dojox.data.XmlItem"
);
dojo
.
require
(
"dojo.data.util.simpleFetch"
);
dojo
.
require
(
"dojo.data.util.filter"
);
dojo
.
require
(
"dojox.data.dom"
);
dojo
.
declare
(
"dojox.data.XmlStore"
,
null
,
{
// summary:
// A data store for XML based services or documents
// description:
// A data store for XML based services or documents
constructor
:
function
(
/* object */
args
)
{
// summary:
// Constructor for the XML store.
// args:
// An anonymous object to initialize properties. It expects the following values:
// url: The url to a service or an XML document that represents the store
// rootItem: A tag name for root items
// keyAttribute: An attribute name for a key or an indentify
// attributeMap: An anonymous object contains properties for attribute mapping,
// {"tag_name.item_attribute_name": "@xml_attribute_name", ...}
// sendQuery: A boolean indicate to add a query string to the service URL
console
.
log
(
"XmlStore()"
);
if
(
args
){
this
.
_url
=
args
.
url
;
this
.
_rootItem
=
(
args
.
rootItem
||
args
.
rootitem
);
this
.
_keyAttribute
=
(
args
.
keyAttribute
||
args
.
keyattribute
);
this
.
_attributeMap
=
(
args
.
attributeMap
||
args
.
attributemap
);
this
.
_labelAttr
=
args
.
label
;
this
.
_sendQuery
=
(
args
.
sendQuery
||
args
.
sendquery
);
}
this
.
_newItems
=
[];
this
.
_deletedItems
=
[];
this
.
_modifiedItems
=
[];
},
/* dojo.data.api.Read */
getValue
:
function
(
/* item */
item
,
/* attribute || attribute-name-string */
attribute
,
/* value? */
defaultValue
){
// summary:
// Return an attribute value
// description:
// 'item' must be an instance of a dojox.data.XmlItem from the store instance.
// If 'attribute' specifies "tagName", the tag name of the element is
// returned.
// If 'attribute' specifies "childNodes", the first element child is
// returned.
// If 'attribute' specifies "text()", the value of the first text
// child is returned.
// For generic attributes, if '_attributeMap' is specified,
// an actual attribute name is looked up with the tag name of
// the element and 'attribute' (concatenated with '.').
// Then, if 'attribute' starts with "@", the value of the XML
// attribute is returned.
// Otherwise, the first child element of the tag name specified with
// 'attribute' is returned.
// item:
// An XML element that holds the attribute
// attribute:
// A tag name of a child element, An XML attribute name or one of
// special names
// defaultValue:
// A default value
// returns:
// An attribute value found, otherwise 'defaultValue'
var
element
=
item
.
element
;
if
(
attribute
===
"tagName"
){
return
element
.
nodeName
;
}
else
if
(
attribute
===
"childNodes"
){
for
(
var
i
=
0
;
i
<
element
.
childNodes
.
length
;
i
++
)
{
var
node
=
element
.
childNodes
[
i
];
if
(
node
.
nodeType
===
1
/*ELEMENT_NODE*/
)
{
return
this
.
_getItem
(
node
);
//object
}
}
return
defaultValue
;
}
else
if
(
attribute
===
"text()"
){
for
(
var
i
=
0
;
i
<
element
.
childNodes
.
length
;
i
++
){
var
node
=
element
.
childNodes
[
i
];
if
(
node
.
nodeType
===
3
/*TEXT_NODE*/
||
node
.
nodeType
===
4
/*CDATA_SECTION_NODE*/
){
return
node
.
nodeValue
;
//string
}
}
return
defaultValue
;
}
else
{
attribute
=
this
.
_getAttribute
(
element
.
nodeName
,
attribute
);
if
(
attribute
.
charAt
(
0
)
===
'@'
){
var
name
=
attribute
.
substring
(
1
);
var
value
=
element
.
getAttribute
(
name
);
return
(
value
!==
undefined
)
?
value
:
defaultValue
;
//object
}
else
{
for
(
var
i
=
0
;
i
<
element
.
childNodes
.
length
;
i
++
){
var
node
=
element
.
childNodes
[
i
];
if
(
node
.
nodeType
===
1
/*ELEMENT_NODE*/
&&
node
.
nodeName
===
attribute
){
return
this
.
_getItem
(
node
);
//object
}
}
return
defaultValue
;
//object
}
}
},
getValues
:
function
(
/* item */
item
,
/* attribute || attribute-name-string */
attribute
){
// summary:
// Return an array of attribute values
// description:
// 'item' must be an instance of a dojox.data.XmlItem from the store instance.
// If 'attribute' specifies "tagName", the tag name of the element is
// returned.
// If 'attribute' specifies "childNodes", child elements are returned.
// If 'attribute' specifies "text()", the values of child text nodes
// are returned.
// For generic attributes, if '_attributeMap' is specified,
// an actual attribute name is looked up with the tag name of
// the element and 'attribute' (concatenated with '.').
// Then, if 'attribute' starts with "@", the value of the XML
// attribute is returned.
// Otherwise, child elements of the tag name specified with
// 'attribute' are returned.
// item:
// An XML element that holds the attribute
// attribute:
// A tag name of child elements, An XML attribute name or one of
// special names
// returns:
// An array of attribute values found, otherwise an empty array
var
element
=
item
.
element
;
if
(
attribute
===
"tagName"
){
return
[
element
.
nodeName
];
}
else
if
(
attribute
===
"childNodes"
){
var
values
=
[];
for
(
var
i
=
0
;
i
<
element
.
childNodes
.
length
;
i
++
){
var
node
=
element
.
childNodes
[
i
];
if
(
node
.
nodeType
===
1
/*ELEMENT_NODE*/
){
values
.
push
(
this
.
_getItem
(
node
));
}
}
return
values
;
//array
}
else
if
(
attribute
===
"text()"
){
var
values
=
[];
for
(
var
i
=
0
;
i
<
element
.
childNodes
.
length
;
i
++
){
var
node
=
childNodes
[
i
];
if
(
node
.
nodeType
===
3
){
values
.
push
(
node
.
nodeValue
);
}
}
return
values
;
//array
}
else
{
attribute
=
this
.
_getAttribute
(
element
.
nodeName
,
attribute
);
if
(
attribute
.
charAt
(
0
)
===
'@'
){
var
name
=
attribute
.
substring
(
1
);
var
value
=
element
.
getAttribute
(
name
);
return
(
value
!==
undefined
)
?
[
value
]
:
[];
//array
}
else
{
var
values
=
[];
for
(
var
i
=
0
;
i
<
element
.
childNodes
.
length
;
i
++
){
var
node
=
element
.
childNodes
[
i
];
if
(
node
.
nodeType
===
1
/*ELEMENT_NODE*/
&&
node
.
nodeName
===
attribute
){
values
.
push
(
this
.
_getItem
(
node
));
}
}
return
values
;
//array
}
}
},
getAttributes
:
function
(
/* item */
item
)
{
// summary:
// Return an array of attribute names
// description:
// 'item' must be an instance of a dojox.data.XmlItem from the store instance.
// tag names of child elements and XML attribute names of attributes
// specified to the element are returned along with special attribute
// names applicable to the element including "tagName", "childNodes"
// if the element has child elements, "text()" if the element has
// child text nodes, and attribute names in '_attributeMap' that match
// the tag name of the element.
// item:
// An XML element
// returns:
// An array of attributes found
var
element
=
item
.
element
;
var
attributes
=
[];
attributes
.
push
(
"tagName"
);
if
(
element
.
childNodes
.
length
>
0
){
var
names
=
{};
var
childNodes
=
true
;
var
text
=
false
;
for
(
var
i
=
0
;
i
<
element
.
childNodes
.
length
;
i
++
){
var
node
=
element
.
childNodes
[
i
];
if
(
node
.
nodeType
===
1
/*ELEMENT_NODE*/
)
{
var
name
=
node
.
nodeName
;
if
(
!
names
[
name
]){
attributes
.
push
(
name
);
names
[
name
]
=
name
;
}
childNodes
=
true
;
}
else
if
(
node
.
nodeType
===
3
){
text
=
true
;
}
}
if
(
childNodes
){
attributes
.
push
(
"childNodes"
);
}
if
(
text
){
attributes
.
push
(
"text()"
);
}
}
for
(
var
i
=
0
;
i
<
element
.
attributes
.
length
;
i
++
){
attributes
.
push
(
"@"
+
element
.
attributes
[
i
].
nodeName
);
}
if
(
this
.
_attributeMap
){
for
(
var
key
in
this
.
_attributeMap
){
var
i
=
key
.
indexOf
(
'.'
);
if
(
i
>
0
){
var
tagName
=
key
.
substring
(
0
,
i
);
if
(
tagName
===
element
.
nodeName
){
attributes
.
push
(
key
.
substring
(
i
+
1
));
}
}
else
{
// global attribute
attributes
.
push
(
key
);
}
}
}
return
attributes
;
//array
},
hasAttribute
:
function
(
/* item */
item
,
/* attribute || attribute-name-string */
attribute
){
// summary:
// Check whether an element has the attribute
// item:
// 'item' must be an instance of a dojox.data.XmlItem from the store instance.
// attribute:
// A tag name of a child element, An XML attribute name or one of
// special names
// returns:
// True if the element has the attribute, otherwise false
return
(
this
.
getValue
(
item
,
attribute
)
!==
undefined
);
//boolean
},
containsValue
:
function
(
/* item */
item
,
/* attribute || attribute-name-string */
attribute
,
/* anything */
value
){
// summary:
// Check whether the attribute values contain the value
// item:
// 'item' must be an instance of a dojox.data.XmlItem from the store instance.
// attribute:
// A tag name of a child element, An XML attribute name or one of
// special names
// returns:
// True if the attribute values contain the value, otherwise false
var
values
=
this
.
getValues
(
item
,
attribute
);
for
(
var
i
=
0
;
i
<
values
.
length
;
i
++
){
if
((
typeof
value
===
"string"
)){
if
(
values
[
i
].
toString
&&
values
[
i
].
toString
()
===
value
){
return
true
;
}
}
else
if
(
values
[
i
]
===
value
){
return
true
;
//boolean
}
}
return
false
;
//boolean
},
isItem
:
function
(
/* anything */
something
){
// summary:
// Check whether the object is an item (XML element)
// item:
// An object to check
// returns:
// True if the object is an XML element, otherwise false
if
(
something
&&
something
.
element
&&
something
.
store
&&
something
.
store
===
this
){
return
true
;
//boolean
}
return
false
;
//boolran
},
isItemLoaded
:
function
(
/* anything */
something
){
// summary:
// Check whether the object is an item (XML element) and loaded
// item:
// An object to check
// returns:
// True if the object is an XML element, otherwise false
return
this
.
isItem
(
something
);
//boolean
},
loadItem
:
function
(
/* object */
keywordArgs
){
// summary:
// Load an item (XML element)
// keywordArgs:
// object containing the args for loadItem. See dojo.data.api.Read.loadItem()
},
getFeatures
:
function
()
{
// summary:
// Return supported data APIs
// returns:
// "dojo.data.api.Read" and "dojo.data.api.Write"
var
features
=
{
"dojo.data.api.Read"
:
true
,
"dojo.data.api.Write"
:
true
};
return
features
;
//array
},
getLabel
:
function
(
/* item */
item
){
// summary:
// See dojo.data.api.Read.getLabel()
if
(
this
.
_labelAttr
&&
this
.
isItem
(
item
)){
var
label
=
this
.
getValue
(
item
,
this
.
_labelAttr
);
if
(
label
){
return
label
.
toString
();
}
}
return
undefined
;
//undefined
},
getLabelAttributes
:
function
(
/* item */
item
){
// summary:
// See dojo.data.api.Read.getLabelAttributes()
if
(
this
.
_labelAttr
){
return
[
this
.
_labelAttr
];
//array
}
return
null
;
//null
},
_fetchItems
:
function
(
request
,
fetchHandler
,
errorHandler
)
{
// summary:
// Fetch items (XML elements) that match to a query
// description:
// If '_sendQuery' is true, an XML document is loaded from
// '_url' with a query string.
// Otherwise, an XML document is loaded and list XML elements that
// match to a query (set of element names and their text attribute
// values that the items to contain).
// A wildcard, "*" can be used to query values to match all
// occurrences.
// If '_rootItem' is specified, it is used to fetch items.
// request:
// A request object
// fetchHandler:
// A function to call for fetched items
// errorHandler:
// A function to call on error
var
url
=
this
.
_getFetchUrl
(
request
);
console
.
log
(
"XmlStore._fetchItems(): url="
+
url
);
if
(
!
url
){
errorHandler
(
new
Error
(
"No URL specified."
));
return
;
}
var
localRequest
=
(
!
this
.
_sendQuery
?
request
:
null
);
// use request for _getItems()
var
self
=
this
;
var
getArgs
=
{
url
:
url
,
handleAs
:
"xml"
,
preventCache
:
true
};
var
getHandler
=
dojo
.
xhrGet
(
getArgs
);
getHandler
.
addCallback
(
function
(
data
){
var
items
=
self
.
_getItems
(
data
,
localRequest
);
console
.
log
(
"XmlStore._fetchItems(): length="
+
(
items
?
items
.
length
:
0
));
if
(
items
&&
items
.
length
>
0
)
{
fetchHandler
(
items
,
request
);
}
else
{
fetchHandler
([],
request
);
}
});
getHandler
.
addErrback
(
function
(
data
){
errorHandler
(
data
,
request
);
});
},
_getFetchUrl
:
function
(
request
){
// summary:
// Generate a URL for fetch
// description:
// This default implementation generates a query string in the form of
// "?name1=value1&name2=value2..." off properties of 'query' object
// specified in 'request' and appends it to '_url', if '_sendQuery'
// is set to false.
// Otherwise, '_url' is returned as is.
// Sub-classes may override this method for the custom URL generation.
// request:
// A request object
// returns:
// A fetch URL
if
(
!
this
.
_sendQuery
){
return
this
.
_url
;
}
var
query
=
request
.
query
;
if
(
!
query
){
return
this
.
_url
;
}
if
(
dojo
.
isString
(
query
)){
return
this
.
_url
+
query
;
}
var
queryString
=
""
;
for
(
var
name
in
query
){
var
value
=
query
[
name
];
if
(
value
){
if
(
queryString
){
queryString
+=
"&"
;
}
queryString
+=
(
name
+
"="
+
value
);
}
}
if
(
!
queryString
){
return
this
.
_url
;
}
//Check to see if the URL already has query params or not.
var
fullUrl
=
this
.
_url
;
if
(
fullUrl
.
indexOf
(
"?"
)
<
0
){
fullUrl
+=
"?"
;
}
else
{
fullUrl
+=
"&"
;
}
return
fullUrl
+
queryString
;
},
_getItems
:
function
(
document
,
request
)
{
// summary:
// Fetch items (XML elements) in an XML document based on a request
// description:
// This default implementation walks through child elements of
// the document element to see if all properties of 'query' object
// match corresponding attributes of the element (item).
// If 'request' is not specified, all child elements are returned.
// Sub-classes may override this method for the custom search in
// an XML document.
// document:
// An XML document
// request:
// A request object
// returns:
// An array of items
var
query
=
null
;
if
(
request
){
query
=
request
.
query
;
}
var
items
=
[];
var
nodes
=
null
;
if
(
this
.
_rootItem
){
nodes
=
document
.
getElementsByTagName
(
this
.
_rootItem
);
}
else
{
nodes
=
document
.
documentElement
.
childNodes
;
}
for
(
var
i
=
0
;
i
<
nodes
.
length
;
i
++
){
var
node
=
nodes
[
i
];
if
(
node
.
nodeType
!=
1
/*ELEMENT_NODE*/
){
continue
;
}
var
item
=
this
.
_getItem
(
node
);
if
(
query
){
var
found
=
true
;
var
ignoreCase
=
request
.
queryOptions
?
request
.
queryOptions
.
ignoreCase
:
false
;
//See if there are any string values that can be regexp parsed first to avoid multiple regexp gens on the
//same value for each item examined. Much more efficient.
var
regexpList
=
{};
for
(
var
key
in
query
){
var
value
=
query
[
key
];
if
(
typeof
value
===
"string"
){
regexpList
[
key
]
=
dojo
.
data
.
util
.
filter
.
patternToRegExp
(
value
,
ignoreCase
);
}
}
for
(
var
attribute
in
query
){
var
value
=
this
.
getValue
(
item
,
attribute
);
if
(
value
){
var
queryValue
=
query
[
attribute
];
if
((
typeof
value
)
===
"string"
&&
(
regexpList
[
attribute
])){
if
((
value
.
match
(
regexpList
[
attribute
]))
!==
null
){
continue
;
}
}
else
if
((
typeof
value
)
===
"object"
){
if
(
value
.
toString
&&
(
regexpList
[
attribute
])){
var
stringValue
=
value
.
toString
();
if
((
stringValue
.
match
(
regexpList
[
attribute
]))
!==
null
){
continue
;
}
}
else
{
if
(
queryValue
===
"*"
||
queryValue
===
value
){
continue
;
}
}
}
}
found
=
false
;
break
;
}
if
(
!
found
){
continue
;
}
}
items
.
push
(
item
);
}
dojo
.
forEach
(
items
,
function
(
item
){
item
.
element
.
parentNode
.
removeChild
(
item
.
element
);
// make it root
},
this
);
return
items
;
},
close
:
function
(
/*dojo.data.api.Request || keywordArgs || null */
request
){
// summary:
// See dojo.data.api.Read.close()
},
/* dojo.data.api.Write */
newItem
:
function
(
/* object? */
keywordArgs
){
// summary:
// Return a new dojox.data.XmlItem
// description:
// At least, 'keywordArgs' must contain "tagName" to be used for
// the new element.
// Other attributes in 'keywordArgs' are set to the new element,
// including "text()", but excluding "childNodes".
// keywordArgs:
// An object containing initial attributes
// returns:
// An XML element
console
.
log
(
"XmlStore.newItem()"
);
keywordArgs
=
(
keywordArgs
||
{});
var
tagName
=
keywordArgs
.
tagName
;
if
(
!
tagName
){
tagName
=
this
.
_rootItem
;
if
(
!
tagName
){
return
null
;
}
}
var
document
=
this
.
_getDocument
();
var
element
=
document
.
createElement
(
tagName
);
for
(
var
attribute
in
keywordArgs
){
if
(
attribute
===
"tagName"
){
continue
;
}
else
if
(
attribute
===
"text()"
){
var
text
=
document
.
createTextNode
(
keywordArgs
[
attribute
]);
element
.
appendChild
(
text
);
}
else
{
attribute
=
this
.
_getAttribute
(
tagName
,
attribute
);
if
(
attribute
.
charAt
(
0
)
===
'@'
){
var
name
=
attribute
.
substring
(
1
);
element
.
setAttribute
(
name
,
keywordArgs
[
attribute
]);
}
else
{
var
child
=
document
.
createElement
(
attribute
);
var
text
=
document
.
createTextNode
(
keywordArgs
[
attribute
]);
child
.
appendChild
(
text
);
element
.
appendChild
(
child
);
}
}
}
var
item
=
this
.
_getItem
(
element
);
this
.
_newItems
.
push
(
item
);
return
item
;
//object
},
deleteItem
:
function
(
/* item */
item
){
// summary:
// Delete an dojox.data.XmlItem (wrapper to a XML element).
// item:
// An XML element to delete
// returns:
// True
console
.
log
(
"XmlStore.deleteItem()"
);
var
element
=
item
.
element
;
if
(
element
.
parentNode
){
this
.
_backupItem
(
item
);
element
.
parentNode
.
removeChild
(
element
);
return
true
;
}
this
.
_forgetItem
(
item
);
this
.
_deletedItems
.
push
(
item
);
return
true
;
//boolean
},
setValue
:
function
(
/* item */
item
,
/* attribute || string */
attribute
,
/* almost anything */
value
){
// summary:
// Set an attribute value
// description:
// 'item' must be an instance of a dojox.data.XmlItem from the store instance.
// If 'attribute' specifies "tagName", nothing is set and false is
// returned.
// If 'attribute' specifies "childNodes", the value (XML element) is
// added to the element.
// If 'attribute' specifies "text()", a text node is created with
// the value and set it to the element as a child.
// For generic attributes, if '_attributeMap' is specified,
// an actual attribute name is looked up with the tag name of
// the element and 'attribute' (concatenated with '.').
// Then, if 'attribute' starts with "@", the value is set to the XML
// attribute.
// Otherwise, a text node is created with the value and set it to
// the first child element of the tag name specified with 'attribute'.
// If the child element does not exist, it is created.
// item:
// An XML element that holds the attribute
// attribute:
// A tag name of a child element, An XML attribute name or one of
// special names
// value:
// A attribute value to set
// returns:
// False for "tagName", otherwise true
if
(
attribute
===
"tagName"
){
return
false
;
//boolean
}
this
.
_backupItem
(
item
);
var
element
=
item
.
element
;
if
(
attribute
===
"childNodes"
){
var
child
=
value
.
element
;
element
.
appendChild
(
child
);
}
else
if
(
attribute
===
"text()"
){
while
(
element
.
firstChild
){
element
.
removeChild
(
element
.
firstChild
);
}
var
text
=
this
.
_getDocument
(
element
).
createTextNode
(
value
);
element
.
appendChild
(
text
);
}
else
{
attribute
=
this
.
_getAttribute
(
element
.
nodeName
,
attribute
);
if
(
attribute
.
charAt
(
0
)
===
'@'
){
var
name
=
attribute
.
substring
(
1
);
element
.
setAttribute
(
name
,
value
);
}
else
{
var
child
=
null
;
for
(
var
i
=
0
;
i
<
element
.
childNodes
.
length
;
i
++
){
var
node
=
element
.
childNodes
[
i
];
if
(
node
.
nodeType
===
1
/*ELEMENT_NODE*/
&&
node
.
nodeName
===
attribute
){
child
=
node
;
break
;
}
}
var
document
=
this
.
_getDocument
(
element
);
if
(
child
){
while
(
child
.
firstChild
){
child
.
removeChild
(
child
.
firstChild
);
}
}
else
{
child
=
document
.
createElement
(
attribute
);
element
.
appendChild
(
child
);
}
var
text
=
document
.
createTextNode
(
value
);
child
.
appendChild
(
text
);
}
}
return
true
;
//boolean
},
setValues
:
function
(
/* item */
item
,
/* attribute || string */
attribute
,
/* array */
values
){
// summary:
// Set attribute values
// description:
// 'item' must be an instance of a dojox.data.XmlItem from the store instance.
// If 'attribute' specifies "tagName", nothing is set and false is
// returned.
// If 'attribute' specifies "childNodes", the value (array of XML
// elements) is set to the element's childNodes.
// If 'attribute' specifies "text()", a text node is created with
// the values and set it to the element as a child.
// For generic attributes, if '_attributeMap' is specified,
// an actual attribute name is looked up with the tag name of
// the element and 'attribute' (concatenated with '.').
// Then, if 'attribute' starts with "@", the first value is set to
// the XML attribute.
// Otherwise, child elements of the tag name specified with
// 'attribute' are replaced with new child elements and their
// child text nodes of values.
// item:
// An XML element that holds the attribute
// attribute:
// A tag name of child elements, an XML attribute name or one of
// special names
// value:
// A attribute value to set
// returns:
// False for "tagName", otherwise true
if
(
attribute
===
"tagName"
){
return
false
;
//boolean
}
this
.
_backupItem
(
item
);
var
element
=
item
.
element
;
if
(
attribute
===
"childNodes"
){
while
(
element
.
firstChild
){
element
.
removeChild
(
element
.
firstChild
);
}
for
(
var
i
=
0
;
i
<
values
.
length
;
i
++
){
var
child
=
values
[
i
].
element
;
element
.
appendChild
(
child
);
}
}
else
if
(
attribute
===
"text()"
){
while
(
element
.
firstChild
){
element
.
removeChild
(
element
.
firstChild
);
}
var
value
=
""
;
for
(
var
i
=
0
;
i
<
values
.
length
;
i
++
){
value
+=
values
[
i
];
}
var
text
=
this
.
_getDocument
(
element
).
createTextNode
(
value
);
element
.
appendChild
(
text
);
}
else
{
attribute
=
this
.
_getAttribute
(
element
.
nodeName
,
attribute
);
if
(
attribute
.
charAt
(
0
)
===
'@'
){
var
name
=
attribute
.
substring
(
1
);
element
.
setAttribute
(
name
,
values
[
0
]);
}
else
{
for
(
var
i
=
element
.
childNodes
.
length
-
1
;
i
>=
0
;
i
--
){
var
node
=
element
.
childNodes
[
i
];
if
(
node
.
nodeType
===
1
/*ELEMENT_NODE*/
&&
node
.
nodeName
===
attribute
){
element
.
removeChild
(
node
);
}
}
var
document
=
this
.
_getDocument
(
element
);
for
(
var
i
=
0
;
i
<
values
.
length
;
i
++
){
var
child
=
document
.
createElement
(
attribute
);
var
text
=
document
.
createTextNode
(
values
[
i
]);
child
.
appendChild
(
text
);
element
.
appendChild
(
child
);
}
}
}
return
true
;
//boolean
},
unsetAttribute
:
function
(
/* item */
item
,
/* attribute || string */
attribute
){
// summary:
// Remove an attribute
// description:
// 'item' must be an instance of a dojox.data.XmlItem from the store instance.
// 'attribute' can be an XML attribute name of the element or one of
// special names described below.
// If 'attribute' specifies "tagName", nothing is removed and false is
// returned.
// If 'attribute' specifies "childNodes" or "text()", all child nodes
// are removed.
// For generic attributes, if '_attributeMap' is specified,
// an actual attribute name is looked up with the tag name of
// the element and 'attribute' (concatenated with '.').
// Then, if 'attribute' starts with "@", the XML attribute is removed.
// Otherwise, child elements of the tag name specified with
// 'attribute' are removed.
// item:
// An XML element that holds the attribute
// attribute:
// A tag name of child elements, an XML attribute name or one of
// special names
// returns:
// False for "tagName", otherwise true
if
(
attribute
===
"tagName"
){
return
false
;
//boolean
}
this
.
_backupItem
(
item
);
var
element
=
item
.
element
;
if
(
attribute
===
"childNodes"
||
attribute
===
"text()"
){
while
(
element
.
firstChild
){
element
.
removeChild
(
element
.
firstChild
);
}
}
else
{
attribute
=
this
.
_getAttribute
(
element
.
nodeName
,
attribute
);
if
(
attribute
.
charAt
(
0
)
===
'@'
){
var
name
=
attribute
.
substring
(
1
);
element
.
removeAttribute
(
name
);
}
else
{
for
(
var
i
=
element
.
childNodes
.
length
-
1
;
i
>=
0
;
i
--
){
var
node
=
element
.
childNodes
[
i
];
if
(
node
.
nodeType
===
1
/*ELEMENT_NODE*/
&&
node
.
nodeName
===
attribute
){
element
.
removeChild
(
node
);
}
}
}
}
return
true
;
//boolean
},
save
:
function
(
/* object */
keywordArgs
){
// summary:
// Save new and/or modified items (XML elements)
// description:
// '_url' is used to save XML documents for new, modified and/or
// deleted XML elements.
// keywordArgs:
// An object for callbacks
if
(
!
keywordArgs
){
keywordArgs
=
{};
}
for
(
var
i
=
0
;
i
<
this
.
_modifiedItems
.
length
;
i
++
){
this
.
_saveItem
(
this
.
_modifiedItems
[
i
],
keywordArgs
,
"PUT"
);
}
for
(
var
i
=
0
;
i
<
this
.
_newItems
.
length
;
i
++
){
var
item
=
this
.
_newItems
[
i
];
if
(
item
.
element
.
parentNode
){
// reparented
this
.
_newItems
.
splice
(
i
,
1
);
i
--
;
continue
;
}
this
.
_saveItem
(
this
.
_newItems
[
i
],
keywordArgs
,
"POST"
);
}
for
(
var
i
=
0
;
i
<
this
.
_deletedItems
.
length
;
i
++
){
this
.
_saveItem
(
this
.
_deletedItems
[
i
],
keywordArgs
,
"DELETE"
);
}
},
revert
:
function
(){
// summary:
// Invalidate changes (new and/or modified elements)
// returns:
// True
console
.
log
(
"XmlStore.revert() _newItems="
+
this
.
_newItems
.
length
);
console
.
log
(
"XmlStore.revert() _deletedItems="
+
this
.
_deletedItems
.
length
);
console
.
log
(
"XmlStore.revert() _modifiedItems="
+
this
.
_modifiedItems
.
length
);
this
.
_newItems
=
[];
this
.
_restoreItems
(
this
.
_deletedItems
);
this
.
_deletedItems
=
[];
this
.
_restoreItems
(
this
.
_modifiedItems
);
this
.
_modifiedItems
=
[];
return
true
;
//boolean
},
isDirty
:
function
(
/* item? */
item
){
// summary:
// Check whether an item is new, modified or deleted
// description:
// If 'item' is specified, true is returned if the item is new,
// modified or deleted.
// Otherwise, true is returned if there are any new, modified
// or deleted items.
// item:
// An item (XML element) to check
// returns:
// True if an item or items are new, modified or deleted, otherwise
// false
if
(
item
)
{
var
element
=
this
.
_getRootElement
(
item
.
element
);
return
(
this
.
_getItemIndex
(
this
.
_newItems
,
element
)
>=
0
||
this
.
_getItemIndex
(
this
.
_deletedItems
,
element
)
>=
0
||
this
.
_getItemIndex
(
this
.
_modifiedItems
,
element
)
>=
0
);
//boolean
}
else
{
return
(
this
.
_newItems
.
length
>
0
||
this
.
_deletedItems
.
length
>
0
||
this
.
_modifiedItems
.
length
>
0
);
//boolean
}
},
_saveItem
:
function
(
item
,
keywordArgs
,
method
){
if
(
method
===
"PUT"
){
url
=
this
.
_getPutUrl
(
item
);
}
else
if
(
method
===
"DELETE"
){
url
=
this
.
_getDeleteUrl
(
item
);
}
else
{
// POST
url
=
this
.
_getPostUrl
(
item
);
}
if
(
!
url
){
if
(
keywordArgs
.
onError
){
keywordArgs
.
onError
.
call
(
scope
,
new
Error
(
"No URL for saving content: "
+
postContent
));
}
return
;
}
var
saveArgs
=
{
url
:
url
,
method
:
(
method
||
"POST"
),
contentType
:
"text/xml"
,
handleAs
:
"xml"
};
var
saveHander
;
if
(
method
===
"PUT"
){
saveArgs
.
putData
=
this
.
_getPutContent
(
item
);
saveHandler
=
dojo
.
rawXhrPut
(
saveArgs
);
}
else
if
(
method
===
"DELETE"
){
saveHandler
=
dojo
.
xhrDelete
(
saveArgs
);
}
else
{
// POST
saveArgs
.
postData
=
this
.
_getPostContent
(
item
);
saveHandler
=
dojo
.
rawXhrPost
(
saveArgs
);
}
var
scope
=
(
keywordArgs
.
scope
||
dojo
.
global
);
var
self
=
this
;
saveHandler
.
addCallback
(
function
(
data
){
self
.
_forgetItem
(
item
);
if
(
keywordArgs
.
onComplete
){
keywordArgs
.
onComplete
.
call
(
scope
);
}
});
saveHandler
.
addErrback
(
function
(
error
){
if
(
keywordArgs
.
onError
){
keywordArgs
.
onError
.
call
(
scope
,
error
);
}
});
},
_getPostUrl
:
function
(
item
){
// summary:
// Generate a URL for post
// description:
// This default implementation just returns '_url'.
// Sub-classes may override this method for the custom URL.
// item:
// An item to save
// returns:
// A post URL
return
this
.
_url
;
//string
},
_getPutUrl
:
function
(
item
){
// summary:
// Generate a URL for put
// description:
// This default implementation just returns '_url'.
// Sub-classes may override this method for the custom URL.
// item:
// An item to save
// returns:
// A put URL
return
this
.
_url
;
//string
},
_getDeleteUrl
:
function
(
item
){
// summary:
// Generate a URL for delete
// description:
// This default implementation returns '_url' with '_keyAttribute'
// as a query string.
// Sub-classes may override this method for the custom URL based on
// changes (new, deleted, or modified).
// item:
// An item to delete
// returns:
// A delete URL
if
(
!
this
.
_url
)
{
return
this
.
_url
;
//string
}
var
url
=
this
.
_url
;
if
(
item
&&
this
.
_keyAttribute
)
{
var
value
=
this
.
getValue
(
item
,
this
.
_keyAttribute
);
if
(
value
)
{
url
=
url
+
'?'
+
this
.
_keyAttribute
+
'='
+
value
;
}
}
return
url
;
//string
},
_getPostContent
:
function
(
item
){
// summary:
// Generate a content to post
// description:
// This default implementation generates an XML document for one
// (the first only) new or modified element.
// Sub-classes may override this method for the custom post content
// generation.
// item:
// An item to save
// returns:
// A post content
var
element
=
item
.
element
;
var
declaration
=
"<?xml version=\"1.0\"?>"
;
// FIXME: encoding?
return
declaration
+
dojox
.
data
.
dom
.
innerXML
(
element
);
//XML string
},
_getPutContent
:
function
(
item
){
// summary:
// Generate a content to put
// description:
// This default implementation generates an XML document for one
// (the first only) new or modified element.
// Sub-classes may override this method for the custom put content
// generation.
// item:
// An item to save
// returns:
// A post content
var
element
=
item
.
element
;
var
declaration
=
"<?xml version=\"1.0\"?>"
;
// FIXME: encoding?
return
declaration
+
dojox
.
data
.
dom
.
innerXML
(
element
);
//XML string
},
/* internal API */
_getAttribute
:
function
(
tagName
,
attribute
){
if
(
this
.
_attributeMap
){
var
key
=
tagName
+
"."
+
attribute
;
var
value
=
this
.
_attributeMap
[
key
];
if
(
value
){
attribute
=
value
;
}
else
{
// look for global attribute
value
=
this
.
_attributeMap
[
attribute
];
if
(
value
){
attribute
=
value
;
}
}
}
return
attribute
;
//object
},
_getItem
:
function
(
element
){
return
new
dojox
.
data
.
XmlItem
(
element
,
this
);
//object
},
_getItemIndex
:
function
(
items
,
element
){
for
(
var
i
=
0
;
i
<
items
.
length
;
i
++
){
if
(
items
[
i
].
element
===
element
){
return
i
;
//int
}
}
return
-
1
;
//int
},
_backupItem
:
function
(
item
){
var
element
=
this
.
_getRootElement
(
item
.
element
);
if
(
this
.
_getItemIndex
(
this
.
_newItems
,
element
)
>=
0
||
this
.
_getItemIndex
(
this
.
_modifiedItems
,
element
)
>=
0
){
return
;
// new or already modified
}
if
(
element
!=
item
.
element
){
item
=
this
.
_getItem
(
element
);
}
item
.
_backup
=
element
.
cloneNode
(
true
);
this
.
_modifiedItems
.
push
(
item
);
},
_restoreItems
:
function
(
items
){
dojo
.
forEach
(
items
,
function
(
item
){
if
(
item
.
_backup
){
item
.
element
=
item
.
_backup
;
item
.
_backup
=
null
;
}
},
this
);
},
_forgetItem
:
function
(
item
){
var
element
=
item
.
element
;
var
index
=
this
.
_getItemIndex
(
this
.
_newItems
,
element
);
if
(
index
>=
0
){
this
.
_newItems
.
splice
(
index
,
1
);
}
index
=
this
.
_getItemIndex
(
this
.
_deletedItems
,
element
);
if
(
index
>=
0
){
this
.
_deletedItems
.
splice
(
index
,
1
);
}
index
=
this
.
_getItemIndex
(
this
.
_modifiedItems
,
element
);
if
(
index
>=
0
){
this
.
_modifiedItems
.
splice
(
index
,
1
);
}
},
_getDocument
:
function
(
element
){
if
(
element
){
return
element
.
ownerDocument
;
//DOMDocument
}
else
if
(
!
this
.
_document
){
return
dojox
.
data
.
dom
.
createDocument
();
// DOMDocument
}
},
_getRootElement
:
function
(
element
){
while
(
element
.
parentNode
){
element
=
element
.
parentNode
;
}
return
element
;
//DOMElement
}
});
//FIXME: Is a full class here really needed for containment of the item or would
//an anon object work fine?
dojo
.
declare
(
"dojox.data.XmlItem"
,
null
,
{
constructor
:
function
(
element
,
store
)
{
// summary:
// Initialize with an XML element
// element:
// An XML element
// store:
// The containing store, if any.
this
.
element
=
element
;
this
.
store
=
store
;
},
// summary:
// A data item of 'XmlStore'
// description:
// This class represents an item of 'XmlStore' holding an XML element.
// 'element'
// element:
// An XML element
toString
:
function
()
{
// summary:
// Return a value of the first text child of the element
// returns:
// a value of the first text child of the element
var
str
=
""
;
if
(
this
.
element
)
{
for
(
var
i
=
0
;
i
<
this
.
element
.
childNodes
.
length
;
i
++
)
{
var
node
=
this
.
element
.
childNodes
[
i
];
if
(
node
.
nodeType
===
3
)
{
str
=
node
.
nodeValue
;
break
;
}
}
}
return
str
;
//String
}
});
dojo
.
extend
(
dojox
.
data
.
XmlStore
,
dojo
.
data
.
util
.
simpleFetch
);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Apr 26, 04:16 (3 d, 23 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24937
Default Alt Text
XmlStore.js (33 KB)
Attached To
rZEDHG ZedLegacy
Event Timeline
Log In to Comment