Page Menu
Home
Code
Search
Configure Global Search
Log In
Files
F885564
OpmlStore.js
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
15 KB
Subscribers
None
OpmlStore.js
View Options
if
(
!
dojo
.
_hasResource
[
"dojox.data.OpmlStore"
]){
//_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo
.
_hasResource
[
"dojox.data.OpmlStore"
]
=
true
;
dojo
.
provide
(
"dojox.data.OpmlStore"
);
dojo
.
require
(
"dojo.data.util.filter"
);
dojo
.
require
(
"dojo.data.util.simpleFetch"
);
dojo
.
declare
(
"dojox.data.OpmlStore"
,
null
,
{
/* summary:
* The OpmlStore implements the dojo.data.api.Read API.
*/
/* examples:
* var opmlStore = new dojo.data.OpmlStore({url:"geography.xml"});
* var opmlStore = new dojo.data.OpmlStore({url:"http://example.com/geography.xml"});
*/
constructor
:
function
(
/* Object */
keywordParameters
){
// summary: constructor
// keywordParameters: {url: String, label: String} Where label is optional and configures what should be used as the return from getLabel()
this
.
_xmlData
=
null
;
this
.
_arrayOfTopLevelItems
=
[];
this
.
_arrayOfAllItems
=
[];
this
.
_metadataNodes
=
null
;
this
.
_loadFinished
=
false
;
this
.
url
=
keywordParameters
.
url
;
this
.
_opmlData
=
keywordParameters
.
data
;
// XML DOM Document
if
(
keywordParameters
.
label
){
this
.
label
=
keywordParameters
.
label
;
}
this
.
_loadInProgress
=
false
;
//Got to track the initial load to prevent duelling loads of the dataset.
this
.
_queuedFetches
=
[];
this
.
_identityMap
=
{};
this
.
_identCount
=
0
;
this
.
_idProp
=
"_I"
;
},
label
:
"text"
,
url
:
""
,
_assertIsItem
:
function
(
/* item */
item
){
if
(
!
this
.
isItem
(
item
)){
throw
new
Error
(
"dojo.data.OpmlStore: a function was passed an item argument that was not an item"
);
}
},
_assertIsAttribute
:
function
(
/* item || String */
attribute
){
// summary:
// This function tests whether the item passed in is indeed a valid 'attribute' like type for the store.
// attribute:
// The attribute to test for being contained by the store.
if
(
!
dojo
.
isString
(
attribute
)){
throw
new
Error
(
"dojox.data.OpmlStore: a function was passed an attribute argument that was not an attribute object nor an attribute name string"
);
}
},
_removeChildNodesThatAreNotElementNodes
:
function
(
/* node */
node
,
/* boolean */
recursive
){
var
childNodes
=
node
.
childNodes
;
if
(
childNodes
.
length
===
0
){
return
;
}
var
nodesToRemove
=
[];
var
i
,
childNode
;
for
(
i
=
0
;
i
<
childNodes
.
length
;
++
i
){
childNode
=
childNodes
[
i
];
if
(
childNode
.
nodeType
!=
1
){
nodesToRemove
.
push
(
childNode
);
}
}
for
(
i
=
0
;
i
<
nodesToRemove
.
length
;
++
i
){
childNode
=
nodesToRemove
[
i
];
node
.
removeChild
(
childNode
);
}
if
(
recursive
){
for
(
i
=
0
;
i
<
childNodes
.
length
;
++
i
){
childNode
=
childNodes
[
i
];
this
.
_removeChildNodesThatAreNotElementNodes
(
childNode
,
recursive
);
}
}
},
_processRawXmlTree
:
function
(
/* xmlDoc */
rawXmlTree
){
this
.
_loadFinished
=
true
;
this
.
_xmlData
=
rawXmlTree
;
var
headNodes
=
rawXmlTree
.
getElementsByTagName
(
'head'
);
var
headNode
=
headNodes
[
0
];
if
(
headNode
){
this
.
_removeChildNodesThatAreNotElementNodes
(
headNode
);
this
.
_metadataNodes
=
headNode
.
childNodes
;
}
var
bodyNodes
=
rawXmlTree
.
getElementsByTagName
(
'body'
);
var
bodyNode
=
bodyNodes
[
0
];
if
(
bodyNode
){
this
.
_removeChildNodesThatAreNotElementNodes
(
bodyNode
,
true
);
var
bodyChildNodes
=
bodyNodes
[
0
].
childNodes
;
for
(
var
i
=
0
;
i
<
bodyChildNodes
.
length
;
++
i
){
var
node
=
bodyChildNodes
[
i
];
if
(
node
.
tagName
==
'outline'
){
this
.
_identityMap
[
this
.
_identCount
]
=
node
;
this
.
_identCount
++
;
this
.
_arrayOfTopLevelItems
.
push
(
node
);
this
.
_arrayOfAllItems
.
push
(
node
);
this
.
_checkChildNodes
(
node
);
}
}
}
},
_checkChildNodes
:
function
(
node
/*Node*/
){
// summary:
// Internal function to recurse over all child nodes from the store and add them
// As non-toplevel items
// description:
// Internal function to recurse over all child nodes from the store and add them
// As non-toplevel items
//
// node:
// The child node to walk.
if
(
node
.
firstChild
){
for
(
var
i
=
0
;
i
<
node
.
childNodes
.
length
;
i
++
){
var
child
=
node
.
childNodes
[
i
];
if
(
child
.
tagName
==
'outline'
){
this
.
_identityMap
[
this
.
_identCount
]
=
child
;
this
.
_identCount
++
;
this
.
_arrayOfAllItems
.
push
(
child
);
this
.
_checkChildNodes
(
child
);
}
}
}
},
_getItemsArray
:
function
(
/*object?*/
queryOptions
){
// summary:
// Internal function to determine which list of items to search over.
// queryOptions: The query options parameter, if any.
if
(
queryOptions
&&
queryOptions
.
deep
)
{
return
this
.
_arrayOfAllItems
;
}
return
this
.
_arrayOfTopLevelItems
;
},
/***************************************
dojo.data.api.Read API
***************************************/
getValue
:
function
(
/* item */
item
,
/* attribute || attribute-name-string */
attribute
,
/* value? */
defaultValue
){
// summary:
// See dojo.data.api.Read.getValue()
this
.
_assertIsItem
(
item
);
this
.
_assertIsAttribute
(
attribute
);
if
(
attribute
==
'children'
){
return
(
item
.
firstChild
||
defaultValue
);
//Object
}
else
{
var
value
=
item
.
getAttribute
(
attribute
);
return
(
value
!==
undefined
)
?
value
:
defaultValue
;
//Object
}
},
getValues
:
function
(
/* item */
item
,
/* attribute || attribute-name-string */
attribute
){
// summary:
// See dojo.data.api.Read.getValues()
this
.
_assertIsItem
(
item
);
this
.
_assertIsAttribute
(
attribute
);
var
array
=
[];
if
(
attribute
==
'children'
){
for
(
var
i
=
0
;
i
<
item
.
childNodes
.
length
;
++
i
){
array
.
push
(
item
.
childNodes
[
i
]);
}
}
else
if
(
item
.
getAttribute
(
attribute
)
!==
null
){
array
.
push
(
item
.
getAttribute
(
attribute
));
}
return
array
;
// Array
},
getAttributes
:
function
(
/* item */
item
){
// summary:
// See dojo.data.api.Read.getAttributes()
this
.
_assertIsItem
(
item
);
var
attributes
=
[];
var
xmlNode
=
item
;
var
xmlAttributes
=
xmlNode
.
attributes
;
for
(
var
i
=
0
;
i
<
xmlAttributes
.
length
;
++
i
){
var
xmlAttribute
=
xmlAttributes
.
item
(
i
);
attributes
.
push
(
xmlAttribute
.
nodeName
);
}
if
(
xmlNode
.
childNodes
.
length
>
0
){
attributes
.
push
(
'children'
);
}
return
attributes
;
//Array
},
hasAttribute
:
function
(
/* item */
item
,
/* attribute || attribute-name-string */
attribute
){
// summary:
// See dojo.data.api.Read.hasAttribute()
return
(
this
.
getValues
(
item
,
attribute
).
length
>
0
);
//Boolean
},
containsValue
:
function
(
/* item */
item
,
/* attribute || attribute-name-string */
attribute
,
/* anything */
value
){
// summary:
// See dojo.data.api.Read.containsValue()
var
regexp
=
undefined
;
if
(
typeof
value
===
"string"
){
regexp
=
dojo
.
data
.
util
.
filter
.
patternToRegExp
(
value
,
false
);
}
return
this
.
_containsValue
(
item
,
attribute
,
value
,
regexp
);
//boolean.
},
_containsValue
:
function
(
/* item */
item
,
/* attribute || attribute-name-string */
attribute
,
/* anything */
value
,
/* RegExp?*/
regexp
){
// summary:
// Internal function for looking at the values contained by the item.
// description:
// Internal function for looking at the values contained by the item. This
// function allows for denoting if the comparison should be case sensitive for
// strings or not (for handling filtering cases where string case should not matter)
//
// item:
// The data item to examine for attribute values.
// attribute:
// The attribute to inspect.
// value:
// The value to match.
// regexp:
// Optional regular expression generated off value if value was of string type to handle wildcarding.
// If present and attribute values are string, then it can be used for comparison instead of 'value'
var
values
=
this
.
getValues
(
item
,
attribute
);
for
(
var
i
=
0
;
i
<
values
.
length
;
++
i
){
var
possibleValue
=
values
[
i
];
if
(
typeof
possibleValue
===
"string"
&&
regexp
){
return
(
possibleValue
.
match
(
regexp
)
!==
null
);
}
else
{
//Non-string matching.
if
(
value
===
possibleValue
){
return
true
;
// Boolean
}
}
}
return
false
;
// Boolean
},
isItem
:
function
(
/* anything */
something
){
// summary:
// See dojo.data.api.Read.isItem()
// description:
// Four things are verified to ensure that "something" is an item:
// something can not be null, the nodeType must be an XML Element,
// the tagName must be "outline", and the node must be a member of
// XML document for this datastore.
return
(
something
&&
something
.
nodeType
==
1
&&
something
.
tagName
==
'outline'
&&
something
.
ownerDocument
===
this
.
_xmlData
);
//Boolean
},
isItemLoaded
:
function
(
/* anything */
something
){
// summary:
// See dojo.data.api.Read.isItemLoaded()
// OpmlStore loads every item, so if it's an item, then it's loaded.
return
this
.
isItem
(
something
);
//Boolean
},
loadItem
:
function
(
/* item */
item
){
// summary:
// See dojo.data.api.Read.loadItem()
// description:
// The OpmlStore always loads all items, so if it's an item, then it's loaded.
// From the dojo.data.api.Read.loadItem docs:
// If a call to isItemLoaded() returns true before loadItem() is even called,
// then loadItem() need not do any work at all and will not even invoke the callback handlers.
},
getLabel
:
function
(
/* item */
item
){
// summary:
// See dojo.data.api.Read.getLabel()
if
(
this
.
isItem
(
item
)){
return
this
.
getValue
(
item
,
this
.
label
);
//String
}
return
undefined
;
//undefined
},
getLabelAttributes
:
function
(
/* item */
item
){
// summary:
// See dojo.data.api.Read.getLabelAttributes()
return
[
this
.
label
];
//array
},
// The dojo.data.api.Read.fetch() function is implemented as
// a mixin from dojo.data.util.simpleFetch.
// That mixin requires us to define _fetchItems().
_fetchItems
:
function
(
/* Object */
keywordArgs
,
/* Function */
findCallback
,
/* Function */
errorCallback
){
// summary:
// See dojo.data.util.simpleFetch.fetch()
var
self
=
this
;
var
filter
=
function
(
requestArgs
,
arrayOfItems
){
var
items
=
null
;
if
(
requestArgs
.
query
){
items
=
[];
var
ignoreCase
=
requestArgs
.
queryOptions
?
requestArgs
.
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
requestArgs
.
query
){
var
value
=
requestArgs
.
query
[
key
];
if
(
typeof
value
===
"string"
){
regexpList
[
key
]
=
dojo
.
data
.
util
.
filter
.
patternToRegExp
(
value
,
ignoreCase
);
}
}
for
(
var
i
=
0
;
i
<
arrayOfItems
.
length
;
++
i
){
var
match
=
true
;
var
candidateItem
=
arrayOfItems
[
i
];
for
(
var
key
in
requestArgs
.
query
){
var
value
=
requestArgs
.
query
[
key
];
if
(
!
self
.
_containsValue
(
candidateItem
,
key
,
value
,
regexpList
[
key
])){
match
=
false
;
}
}
if
(
match
){
items
.
push
(
candidateItem
);
}
}
}
else
{
// We want a copy to pass back in case the parent wishes to sort the array. We shouldn't allow resort
// of the internal list so that multiple callers can get lists and sort without affecting each other.
if
(
arrayOfItems
.
length
>
0
){
items
=
arrayOfItems
.
slice
(
0
,
arrayOfItems
.
length
);
}
}
findCallback
(
items
,
requestArgs
);
};
if
(
this
.
_loadFinished
){
filter
(
keywordArgs
,
this
.
_getItemsArray
(
keywordArgs
.
queryOptions
));
}
else
{
//If fetches come in before the loading has finished, but while
//a load is in progress, we have to defer the fetching to be
//invoked in the callback.
if
(
this
.
_loadInProgress
){
this
.
_queuedFetches
.
push
({
args
:
keywordArgs
,
filter
:
filter
});
}
else
{
if
(
this
.
url
!==
""
){
this
.
_loadInProgress
=
true
;
var
getArgs
=
{
url
:
self
.
url
,
handleAs
:
"xml"
};
var
getHandler
=
dojo
.
xhrGet
(
getArgs
);
getHandler
.
addCallback
(
function
(
data
){
self
.
_processRawXmlTree
(
data
);
filter
(
keywordArgs
,
self
.
_getItemsArray
(
keywordArgs
.
queryOptions
));
self
.
_handleQueuedFetches
();
});
getHandler
.
addErrback
(
function
(
error
){
throw
error
;
});
}
else
if
(
this
.
_opmlData
){
this
.
_processRawXmlTree
(
this
.
_opmlData
);
this
.
_opmlData
=
null
;
filter
(
keywordArgs
,
this
.
_getItemsArray
(
keywordArgs
.
queryOptions
));
}
else
{
throw
new
Error
(
"dojox.data.OpmlStore: No OPML source data was provided as either URL or XML data input."
);
}
}
}
},
getFeatures
:
function
(){
// summary: See dojo.data.api.Read.getFeatures()
var
features
=
{
'dojo.data.api.Read'
:
true
,
'dojo.data.api.Identity'
:
true
};
return
features
;
//Object
},
/***************************************
dojo.data.api.Identity API
***************************************/
getIdentity
:
function
(
/* item */
item
){
// summary:
// See dojo.data.api.Identity.getIdentity()
if
(
this
.
isItem
(
item
)){
//No ther way to do this other than O(n) without
//complete rework of how the tree stores nodes.
for
(
var
i
in
this
.
_identityMap
){
if
(
this
.
_identityMap
[
i
]
===
item
){
return
i
;
}
}
}
return
null
;
//null
},
fetchItemByIdentity
:
function
(
/* Object */
keywordArgs
){
// summary:
// See dojo.data.api.Identity.fetchItemByIdentity()
//Hasn't loaded yet, we have to trigger the load.
if
(
!
this
.
_loadFinished
){
var
self
=
this
;
if
(
this
.
url
!==
""
){
//If fetches come in before the loading has finished, but while
//a load is in progress, we have to defer the fetching to be
//invoked in the callback.
if
(
this
.
_loadInProgress
){
this
.
_queuedFetches
.
push
({
args
:
keywordArgs
});
}
else
{
this
.
_loadInProgress
=
true
;
var
getArgs
=
{
url
:
self
.
url
,
handleAs
:
"xml"
};
var
getHandler
=
dojo
.
xhrGet
(
getArgs
);
getHandler
.
addCallback
(
function
(
data
){
var
scope
=
keywordArgs
.
scope
?
keywordArgs
.
scope
:
dojo
.
global
;
try
{
self
.
_processRawXmlTree
(
data
);
var
item
=
self
.
_identityMap
[
keywordArgs
.
identity
];
if
(
!
self
.
isItem
(
item
)){
item
=
null
;
}
if
(
keywordArgs
.
onItem
){
keywordArgs
.
onItem
.
call
(
scope
,
item
);
}
self
.
_handleQueuedFetches
();
}
catch
(
error
){
if
(
keywordArgs
.
onError
){
keywordArgs
.
onError
.
call
(
scope
,
error
);
}
}
});
getHandler
.
addErrback
(
function
(
error
){
this
.
_loadInProgress
=
false
;
if
(
keywordArgs
.
onError
){
var
scope
=
keywordArgs
.
scope
?
keywordArgs
.
scope
:
dojo
.
global
;
keywordArgs
.
onError
.
call
(
scope
,
error
);
}
});
}
}
else
if
(
this
.
_opmlData
){
this
.
_processRawXmlTree
(
this
.
_opmlData
);
this
.
_opmlData
=
null
;
var
item
=
this
.
_identityMap
[
keywordArgs
.
identity
];
if
(
!
self
.
isItem
(
item
)){
item
=
null
;
}
if
(
keywordArgs
.
onItem
){
var
scope
=
keywordArgs
.
scope
?
keywordArgs
.
scope
:
dojo
.
global
;
keywordArgs
.
onItem
.
call
(
scope
,
item
);
}
}
}
else
{
//Already loaded. We can just look it up and call back.
var
item
=
this
.
_identityMap
[
keywordArgs
.
identity
];
if
(
!
this
.
isItem
(
item
)){
item
=
null
;
}
if
(
keywordArgs
.
onItem
){
var
scope
=
keywordArgs
.
scope
?
keywordArgs
.
scope
:
dojo
.
global
;
keywordArgs
.
onItem
.
call
(
scope
,
item
);
}
}
},
getIdentityAttributes
:
function
(
/* item */
item
){
// summary:
// See dojo.data.api.Identity.getIdentifierAttributes()
//Identity isn't a public attribute in the item, it's the node count.
//So, return null.
return
null
;
},
_handleQueuedFetches
:
function
(){
// summary:
// Internal function to execute delayed request in the store.
//Execute any deferred fetches now.
if
(
this
.
_queuedFetches
.
length
>
0
)
{
for
(
var
i
=
0
;
i
<
this
.
_queuedFetches
.
length
;
i
++
){
var
fData
=
this
.
_queuedFetches
[
i
];
var
delayedQuery
=
fData
.
args
;
var
delayedFilter
=
fData
.
filter
;
if
(
delayedFilter
){
delayedFilter
(
delayedQuery
,
this
.
_getItemsArray
(
delayedQuery
.
queryOptions
));
}
else
{
this
.
fetchItemByIdentity
(
delayedQuery
);
}
}
this
.
_queuedFetches
=
[];
}
},
close
:
function
(
/*dojo.data.api.Request || keywordArgs || null */
request
){
// summary:
// See dojo.data.api.Read.close()
}
});
//Mix in the simple fetch implementation to this class.
dojo
.
extend
(
dojox
.
data
.
OpmlStore
,
dojo
.
data
.
util
.
simpleFetch
);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Apr 6, 17:06 (2 w, 1 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24306
Default Alt Text
OpmlStore.js (15 KB)
Attached To
rZEDHG ZedLegacy
Event Timeline
Log In to Comment