},
"getValues": function(/* object */ item, /* string */ attribute) {
- console.log("getValues(" + item + ", " + attribute + ")");
+ //console.log("getValues(" + item + ", " + attribute + ")");
if (!this.isItem(item) || typeof attribute != "string")
throw new FlattenerStoreError("bad arguments");
},
"getAttributes": function(/* object */ item) {
- console.log("getAttributes(" + item + ")");
+ //console.log("getAttributes(" + item + ")");
if (!this.isItem(item))
throw new FlattenerStoreError("getAttributes(): bad args");
else
},
"hasAttribute": function(/* object */ item, /* string */ attribute) {
- console.log("hasAttribute(" + item + ", " + attribute + ")");
+ //console.log("hasAttribute(" + item + ", " + attribute + ")");
if (!this.isItem(item) || typeof attribute != "string") {
throw new FlattenerStoreError("hasAttribute(): bad args");
} else {
/* object */ item,
/* string */ attribute,
/* anything */ value) {
- console.log("containsValue(" + item + ", " + attribute + ", " + value + ")");
+ //console.log("containsValue(" + item + ", " + attribute + ", " + value + ")");
if (!this.isItem(item) || typeof attribute != "string")
throw new FlattenerStoreError("bad data");
else
},
"isItemLoaded": function(/* anything */ something) {
- console.log("isItemLoaded(" + something + ")");
- return this.isItem(something); /* for this store,
- items are always loaded */
+ console.warning("[unfinished] isItemLoaded(" + something + ")");
+
+ /* This is assuming items are always loaded, which is probably not right for this particular store.*/
+ return this.isItem(something);
},
"close": function(/* object */ request) { /* no-op */ return; },
"getLabel": function(/* object */ item) {
- console.log("getLabel(" + item + ")");
+ //console.log("getLabel(" + item + ")");
return "XXX TODO";
},
"getLabelAttributes": function(/* object */ item) {
- console.log("getLabelAttributes(" + item + ")");
+ //console.log("getLabelAttributes(" + item + ")");
return ["XXX TODO"];
},
"loadItem": function(/* object */ keywordArgs) {
- console.log("loadItem(" + dojo.toJson(keywordArgs) + ")");
+ //console.log("loadItem(" + dojo.toJson(keywordArgs) + ")");
if (!this.isItem(keywordArgs.item))
throw new FlattenerStoreError("not an item; can't load it");
// callback to the *req* object for the caller's use, but
// the one we provide does nothing but issue an alert().
- console.log("fetch(" + dojo.toJson(req) + ")");
- /* if-not-ready-then-act-as-if-empty. this is how you do that. */
+ console.info("fetch(" + dojo.toJson(req) + ")");
-// if (!this.cm_cache.is_done) {
-// if (typeof req.onComplete == "function")
-// req.onComplete.call(callback_scope, [], req);
-// return;
-// }
+ /* XXX We're clearing this cache upon every fetch? Do we need/want
+ * to do that? Not sure. */
this._current_items = {};
var callback_scope = req.scope || dojo.global;
return;
if (typeof req.onBegin == "function") {
-
+ /* We lie to onBegin like this because we don't know how
+ * many more rows we might be able to fetch if the
+ * user keeps scrolling. Once we get a number of
+ * results that is less than the limit we asked for,
+ * the grid is smart enough to know we're at the end and
+ * it does the right thing. */
var might_be_a_lie = obj.length;
if (obj.length >= req.count)
might_be_a_lie += req.count;
- console.debug("onBegin(" + might_be_a_lie + ", ...)");
req.onBegin.call(callback_scope, might_be_a_lie, req);
}
dojo.forEach(
obj,
function(item) {
+ /* Cache items internally. */
self._current_items[item[self.fmIdentifier]] = item;
- if (typeof req.onItem == "function") {
+ if (typeof req.onItem == "function")
req.onItem.call(callback_scope, item, req);
- }
}
);
- if (typeof req.onComplete == "function") {
- req.onComplete.call(
- callback_scope,
- openils.Util.objectValues(self._current_items),
- req
- );
- }
+ if (typeof req.onComplete == "function")
+ req.onComplete.call(callback_scope, obj, req);
};
req.abort = function() {
var fetch_time = this._last_fetch = (new Date().getTime());
- console.log(dojo.toJson(post_params));
dojo.xhrPost({
"url": "/opac/extras/flattener",
"content": post_params,
/* *** Begin dojo.data.api.Identity methods *** */
"getIdentity": function(/* object */ item) {
- console.log("getIdentity(" + item + ")");
+ //console.log("getIdentity(" + item + ")");
if (!this.isItem(item))
throw new FlattenerStoreError("not an item");
},
"getIdentityAttributes": function(/* object */ item) {
- console.log("getIdentityAttributes(" + item + ")");
+ // console.log("getIdentityAttributes(" + item + ")");
return [this.fmIdentifier];
},
"fetchItemByIdentity": function(/* object */ keywordArgs) {
- /* XXX This almost certainly needs attention, and/or
- * needs to be able to call fetch() or to talk to the
- * web service directly. */
+ /* XXX This almost certainly needs attention (unless DataGrid
+ * doesn't use it (or loadItem)?), and needs to be able to call
+ * fetch() or to talk to the web service directly. */
- console.log("fetchItemByIdentity(" + dojo.toJson(keywordArgs)+ ")");
+ console.warning(
+ "[unfinished] fetchItemByIdentity(" +
+ dojo.toJson(keywordArgs) + ")"
+ );
if (keywordArgs.identity == undefined)
return null; // Identity API spec unclear whether error callback
// would need to be run, so we won't.
* APIs they're implementing. *** */
"getFeatures": function() {
- console.log("getFeatures()");
return {
"dojo.data.api.Read": true,
"dojo.data.api.Identity": true
"columnReordering": true,
"fmClass": null,
"fmIdentifier": null,
+ "mapExtras": null,
+ /* _generate_map() lives to interpret the attributes of the
+ * FlattenerGrid dijit itself plus those definined in
+ * <table>
+ * <thead>
+ * <tr>
+ * <th field="foo" ...>
+ * to build the map to hand to the FlattenerStore, which in turn
+ * uses it to query the flattener service.
+ */
"_generate_map": function() {
var map = this.mapClause = {};
var fields = this.structure[0].cells[0];
- /* XXX TODO remove column from grid (or hide? or what?)
- * when display is false */
+
+ /* These are the fields defined in thead -> tr -> [th,th,...].
+ * For purposes of building the map, where each field has
+ * three boolean attributes "display", "sort" and "filter",
+ * assume "display" and "sort" are always true for these.
+ * That doesn't mean that at the UI level we can't hide a
+ * column later.
+ *
+ * If you need extra fields in the map for which display
+ * or sort should *not* be true, use mapExtras.
+ */
dojo.forEach(
- fields,
- function(field) {
- if (field.fpath) {
- if ("fdisplay" in field ||
- "fsort" in field ||
- "ffilter" in field) {
- map[field.field] = {
- "display": (field.fdisplay || false),
- "filter": (field.ffilter || false),
- "sort": (field.fsort || false)
- };
- } else {
- map[field.field] = {
- "sort": true,
- "filter": true,
- "display": true
- };
- }
- map[field.field].path = field.fpath;
- }
+ fields, function(field) {
+ map[field.field] = {
+ "display": true,
+ "filter": (field.ffilter || false),
+ "sort": true,
+ "path": field.fpath || field.field
+ };
}
);
};
}
+ if (this.mapExtras) {
+ /* It's not particularly useful to add simple fields, i.e.
+ * circ_lib: "circ_lib.name"
+ * to mapExtras, because by convention used elsewhere in
+ * Flattener, that gives all attributes, including
+ * display, a true value. Still, be consistent to avoid
+ * stumping users.
+ */
+ for (var key in this.mapExtras) {
+ if (typeof this.mapExtras[key] != "object") {
+ this.mapExtras[key] = {
+ "path": this.mapExtras[key],
+ "sort": true,
+ "filter": true,
+ "display": true
+ };
+ }
+ }
+ dojo.mixin(map, this.mapExtras);
+ }
+
return map;
},
orig_mf(node, cellDef);
dojo.forEach(
- ["fpath", "fdisplay", "fsort", "ffilter"],
- function(a) {
+ ["fpath", "ffilter"], function(a) {
var value = dojo.attr(node, a);
if (value)
cellDef[a] = value;