/*==================================================
* Exhibit.FacetUtilities
*
* Utilities for facets' code.
*==================================================
*/
Exhibit.FacetUtilities = new Object();
Exhibit.FacetUtilities.constructFacetFrame = function(forFacet, div, facetLabel, onClearAllSelections, uiContext, collapsible, collapsed) {
div.className = "exhibit-facet";
var dom = SimileAjax.DOM.createDOMFromString(
div,
"
" +
"",
{ checkImage: Exhibit.UI.createTranslucentImage("images/black-check.png") }
);
var resizableDivWidget = Exhibit.ResizableDivWidget.create({}, dom.frameDiv, uiContext);
dom.valuesContainer = resizableDivWidget.getContentDiv();
dom.valuesContainer.className = "exhibit-facet-body";
dom.setSelectionCount = function(count) {
this.filterCountSpan.innerHTML = count;
this.clearSelectionsDiv.style.display = count > 0 ? "block" : "none";
};
SimileAjax.WindowManager.registerEvent(dom.clearSelectionsDiv, "click", onClearAllSelections);
if (collapsible) {
SimileAjax.WindowManager.registerEvent(dom.collapseImg, "click", function() {
Exhibit.FacetUtilities.toggleCollapse(dom, forFacet);
});
if (collapsed) {
Exhibit.FacetUtilities.toggleCollapse(dom, forFacet);
}
}
return dom;
};
Exhibit.FacetUtilities.toggleCollapse = function(dom, facet) {
var el = dom.frameDiv;
if (el.style.display != "none") {
el.style.display = "none";
dom.collapseImg.src = Exhibit.urlPrefix + "images/expand.png";
} else {
el.style.display = "block";
dom.collapseImg.src = Exhibit.urlPrefix + "images/collapse.png";
// Try to call onUncollapse but don't sweat it if it isn't there.
if (typeof facet.onUncollapse == 'function') {
facet.onUncollapse();
}
}
};
Exhibit.FacetUtilities.isCollapsed = function(facet) {
var el = facet._dom.frameDiv;
return el.style.display == "none";
};
Exhibit.FacetUtilities.constructFacetItem = function(
label,
count,
color,
selected,
facetHasSelection,
onSelect,
onSelectOnly,
uiContext
) {
if (Exhibit.params.safe) {
label = Exhibit.Formatter.encodeAngleBrackets(label);
}
var dom = SimileAjax.DOM.createDOMFromString(
"div",
"" + count + "
" +
"" +
( "
" +
SimileAjax.Graphics.createTranslucentImageHTML(
Exhibit.urlPrefix +
( facetHasSelection ?
(selected ? "images/black-check.png" : "images/no-check.png") :
"images/no-check-no-border.png"
)) +
"
"
) +
"
" +
"
"
);
dom.elmt.className = selected ? "exhibit-facet-value exhibit-facet-value-selected" : "exhibit-facet-value";
if (typeof label == "string") {
dom.elmt.title = label;
dom.link.innerHTML = label;
if (color != null) {
dom.link.style.color = color;
}
} else {
dom.link.appendChild(label);
if (color != null) {
label.style.color = color;
}
}
SimileAjax.WindowManager.registerEvent(dom.elmt, "click", onSelectOnly, SimileAjax.WindowManager.getBaseLayer());
if (facetHasSelection) {
SimileAjax.WindowManager.registerEvent(dom.inner.firstChild, "click", onSelect, SimileAjax.WindowManager.getBaseLayer());
}
return dom.elmt;
};
Exhibit.FacetUtilities.constructFlowingFacetFrame = function(forFacet, div, facetLabel, onClearAllSelections, uiContext, collapsible, collapsed) {
div.className = "exhibit-flowingFacet";
var dom = SimileAjax.DOM.createDOMFromString(
div,
"" +
""
);
dom.setSelectionCount = function(count) {
// nothing
};
if (collapsible) {
SimileAjax.WindowManager.registerEvent(dom.collapseImg, "click", function() {
Exhibit.FacetUtilities.toggleCollapse(dom, forFacet);
});
if (collapsed) {
Exhibit.FacetUtilities.toggleCollapse(dom, forFacet);
}
}
return dom;
};
Exhibit.FacetUtilities.constructFlowingFacetItem = function(
label,
count,
color,
selected,
facetHasSelection,
onSelect,
onSelectOnly,
uiContext
) {
if (Exhibit.params.safe) {
label = Exhibit.Formatter.encodeAngleBrackets(label);
}
var dom = SimileAjax.DOM.createDOMFromString(
"div",
( "" +
SimileAjax.Graphics.createTranslucentImageHTML(
Exhibit.urlPrefix +
( facetHasSelection ?
(selected ? "images/black-check.png" : "images/no-check.png") :
"images/no-check-no-border.png"
)) +
"
"
) +
"" +
" " +
"(" + count + ")"
);
dom.elmt.className = selected ? "exhibit-flowingFacet-value exhibit-flowingFacet-value-selected" : "exhibit-flowingFacet-value";
if (typeof label == "string") {
dom.elmt.title = label;
dom.inner.innerHTML = label;
if (color != null) {
dom.inner.style.color = color;
}
} else {
dom.inner.appendChild(label);
if (color != null) {
label.style.color = color;
}
}
SimileAjax.WindowManager.registerEvent(dom.elmt, "click", onSelectOnly, SimileAjax.WindowManager.getBaseLayer());
if (facetHasSelection) {
SimileAjax.WindowManager.registerEvent(dom.elmt.firstChild, "click", onSelect, SimileAjax.WindowManager.getBaseLayer());
}
return dom.elmt;
};
Exhibit.FacetUtilities.constructHierarchicalFacetItem = function(
label,
count,
color,
selected,
hasChildren,
expanded,
facetHasSelection,
onSelect,
onSelectOnly,
onToggleChildren,
uiContext
) {
if (Exhibit.params.safe) {
label = Exhibit.Formatter.encodeAngleBrackets(label);
}
var dom = SimileAjax.DOM.createDOMFromString(
"div",
"" + count + "
" +
"" +
(hasChildren ? "" : "")
);
dom.elmt.className = selected ? "exhibit-facet-value exhibit-facet-value-selected" : "exhibit-facet-value";
if (typeof label == "string") {
dom.elmt.title = label;
dom.link.appendChild(document.createTextNode(label));
if (color != null) {
dom.link.style.color = color;
}
} else {
dom.link.appendChild(label);
if (color != null) {
label.style.color = color;
}
}
SimileAjax.WindowManager.registerEvent(dom.elmt, "click", onSelectOnly, SimileAjax.WindowManager.getBaseLayer());
if (facetHasSelection) {
SimileAjax.WindowManager.registerEvent(dom.inner.firstChild, "click", onSelect, SimileAjax.WindowManager.getBaseLayer());
}
if (hasChildren) {
dom.showChildren = function(show) {
dom.childrenContainer.style.display = show ? "block" : "none";
dom.toggle.childNodes[0].style.display = show ? "inline" : "none";
dom.toggle.childNodes[1].style.display = show ? "none" : "inline";
}
SimileAjax.WindowManager.registerEvent(dom.toggle, "click", onToggleChildren, SimileAjax.WindowManager.getBaseLayer());
dom.showChildren(expanded);
}
return dom;
};
Exhibit.FacetUtilities.constructFlowingHierarchicalFacetItem = function(
label,
count,
color,
selected,
hasChildren,
expanded,
facetHasSelection,
onSelect,
onSelectOnly,
onToggleChildren,
uiContext
) {
if (Exhibit.params.safe) {
label = Exhibit.Formatter.encodeAngleBrackets(label);
}
var dom = SimileAjax.DOM.createDOMFromString(
"div",
( "" +
SimileAjax.Graphics.createTranslucentImageHTML(
Exhibit.urlPrefix +
( facetHasSelection ?
(selected ? "images/black-check.png" : "images/no-check.png") :
"images/no-check-no-border.png"
)) +
"
"
) +
"" +
" " +
"(" + count + ")" +
( hasChildren ?
( "" +
SimileAjax.Graphics.createTranslucentImageHTML(
Exhibit.urlPrefix + "images/down-arrow.png") +
SimileAjax.Graphics.createTranslucentImageHTML(
Exhibit.urlPrefix + "images/right-arrow.png") +
""
) :
""
) +
(hasChildren ? "" : "")
);
dom.elmt.className = selected ? "exhibit-flowingFacet-value exhibit-flowingFacet-value-selected" : "exhibit-flowingFacet-value";
if (typeof label == "string") {
dom.elmt.title = label;
dom.inner.appendChild(document.createTextNode(label));
if (color != null) {
dom.inner.style.color = color;
}
} else {
dom.inner.appendChild(label);
if (color != null) {
label.style.color = color;
}
}
SimileAjax.WindowManager.registerEvent(dom.elmt, "click", onSelectOnly, SimileAjax.WindowManager.getBaseLayer());
if (facetHasSelection) {
SimileAjax.WindowManager.registerEvent(dom.elmt.firstChild, "click", onSelect, SimileAjax.WindowManager.getBaseLayer());
}
if (hasChildren) {
dom.showChildren = function(show) {
dom.childrenContainer.style.display = show ? "block" : "none";
dom.toggle.childNodes[0].style.display = show ? "inline" : "none";
dom.toggle.childNodes[1].style.display = show ? "none" : "inline";
}
SimileAjax.WindowManager.registerEvent(dom.toggle, "click", onToggleChildren, SimileAjax.WindowManager.getBaseLayer());
dom.showChildren(expanded);
}
return dom;
};
/*======================================================================
* Cache for item/value mapping
*======================================================================
*/
Exhibit.FacetUtilities.Cache = function(database, collection, expression) {
var self = this;
this._database = database;
this._collection = collection;
this._expression = expression;
this._listener = {
onRootItemsChanged: function() {
if ("_itemToValue" in self) {
delete self._itemToValue;
}
if ("_valueToItem" in self) {
delete self._valueToItem;
}
if ("_missingItems" in self) {
delete self._missingItems;
}
}
};
collection.addListener(this._listener);
}
Exhibit.FacetUtilities.Cache.prototype.dispose = function() {
this._collection.removeListener(this._listener);
this._collection = null;
this._listener = null;
this._itemToValue = null;
this._valueToItem = null;
this._missingItems = null;
}
Exhibit.FacetUtilities.Cache.prototype.getItemsFromValues = function(values, filter) {
var set;
if (this._expression.isPath()) {
set = this._expression.getPath().walkBackward(
values,
"item",
filter,
this._database
).getSet();
} else {
this._buildMaps();
set = new Exhibit.Set();
var valueToItem = this._valueToItem;
values.visit(function(value) {
if (value in valueToItem) {
var itemA = valueToItem[value];
for (var i = 0; i < itemA.length; i++) {
var item = itemA[i];
if (filter.contains(item)) {
set.add(item);
}
}
}
});
}
return set;
}
Exhibit.FacetUtilities.Cache.prototype.getItemsMissingValue = function(filter, results) {
this._buildMaps();
results = results || new Exhibit.Set();
var missingItems = this._missingItems;
filter.visit(function(item) {
if (item in missingItems) {
results.add(item);
}
});
return results;
}
Exhibit.FacetUtilities.Cache.prototype.getValueCountsFromItems = function(items) {
var entries = [];
var database = this._database;
var valueType = "text";
if (this._expression.isPath()) {
var path = this._expression.getPath();
var facetValueResult = path.walkForward(items, "item", database);
valueType = facetValueResult.valueType;
if (facetValueResult.size > 0) {
facetValueResult.forEachValue(function(facetValue) {
var itemSubcollection = path.evaluateBackward(facetValue, valueType, items, database);
entries.push({ value: facetValue, count: itemSubcollection.size });
});
};
} else {
this._buildMaps();
valueType = this._valueType;
for (var value in this._valueToItem) {
var itemA = this._valueToItem[value];
var count = 0;
for (var i = 0; i < itemA.length; i++) {
if (items.contains(itemA[i])) {
count++;
}
}
if (count > 0) {
entries.push({ value: value, count: count });
}
}
}
return { entries: entries, valueType: valueType };
}
Exhibit.FacetUtilities.Cache.prototype.getValuesFromItems = function(items) {
if (this._expression.isPath()) {
return this._expression.getPath().walkForward(items, "item", database).getSet();
} else {
this._buildMaps();
var set = new Exhibit.Set();
var itemToValue = this._itemToValue;
items.visit(function(item) {
if (item in itemToValue) {
var a = itemToValue[item];
for (var i = 0; i < a.length; i++) {
set.add(a[i]);
}
}
});
return set;
}
}
Exhibit.FacetUtilities.Cache.prototype.countItemsMissingValue = function(items) {
this._buildMaps();
var count = 0;
for (var item in this._missingItems) {
if (items.contains(item)) {
count++;
}
}
return count;
}
Exhibit.FacetUtilities.Cache.prototype._buildMaps = function() {
if (!("_itemToValue" in this)) {
var itemToValue = {};
var valueToItem = {};
var missingItems = {};
var valueType = "text";
var insert = function(x, y, map) {
if (x in map) {
map[x].push(y);
} else {
map[x] = [ y ];
}
};
var expression = this._expression;
var database = this._database;
this._collection.getAllItems().visit(function(item) {
var results = expression.evaluateOnItem(item, database);
if (results.values.size() > 0) {
valueType = results.valueType;
results.values.visit(function(value) {
insert(item, value, itemToValue);
insert(value, item, valueToItem);
});
} else {
missingItems[item] = true;
}
});
this._itemToValue = itemToValue;
this._valueToItem = valueToItem;
this._missingItems = missingItems;
this._valueType = valueType;
}
};