/* * Inspector grouping support. * */ +function ($) { "use strict"; // GROUP MANAGER CLASS // ============================ var GroupManager = function(controlId) { this.controlId = controlId this.rootGroup = null this.cachedGroupStatuses = null } GroupManager.prototype.createGroup = function(groupId, parentGroup) { var group = new Group(groupId) if (parentGroup) { parentGroup.groups.push(group) group.parentGroup = parentGroup // Circular reference, but memory leaks are not noticed } else { this.rootGroup = group } return group } GroupManager.prototype.getGroupIndex = function(group) { return group.getGroupIndex() } GroupManager.prototype.isParentGroupExpanded = function(group) { if (!group.parentGroup) { // The root group is always expanded return true } return this.isGroupExpanded(group.parentGroup) } GroupManager.prototype.isGroupExpanded = function(group) { if (!group.parentGroup) { // The root group is always expanded return true } var groupIndex = this.getGroupIndex(group), statuses = this.readGroupStatuses() if (statuses[groupIndex] !== undefined) { return statuses[groupIndex] } return false } GroupManager.prototype.setGroupStatus = function(groupIndex, expanded) { var statuses = this.readGroupStatuses() statuses[groupIndex] = expanded this.writeGroupStatuses(statuses) } GroupManager.prototype.readGroupStatuses = function() { if (this.cachedGroupStatuses !== null) { return this.cachedGroupStatuses } var statuses = getInspectorGroupStatuses() if (statuses[this.controlId] !== undefined) { this.cachedGroupStatuses = statuses[this.controlId] } else { this.cachedGroupStatuses = {} } return this.cachedGroupStatuses } GroupManager.prototype.writeGroupStatuses = function(updatedStatuses) { var statuses = getInspectorGroupStatuses() statuses[this.controlId] = updatedStatuses setInspectorGroupStatuses(statuses) this.cachedGroupStatuses = updatedStatuses } GroupManager.prototype.findGroupByIndex = function(index) { return this.rootGroup.findGroupByIndex(index) } GroupManager.prototype.findGroupRows = function(table, index, ignoreCollapsedSubgroups) { var group = this.findGroupByIndex(index) if (!group) { throw new Error('Cannot find the requested row group.') } return group.findGroupRows(table, ignoreCollapsedSubgroups, this) } GroupManager.prototype.markGroupRowInvalid = function(group, table) { var currentGroup = group while (currentGroup) { var row = currentGroup.findGroupRow(table) if (row) { $.oc.foundation.element.addClass(row, 'invalid') } currentGroup = currentGroup.parentGroup } } GroupManager.prototype.unmarkInvalidGroups = function(table) { var rows = table.querySelectorAll('tr.invalid') for (var i = rows.length-1; i >= 0; i--) { $.oc.foundation.element.removeClass(rows[i], 'invalid') } } GroupManager.prototype.isRowVisible = function(table, rowGroupIndex) { var group = this.findGroupByIndex(index) if (!group) { throw new Error('Cannot find the requested row group.') } var current = group while (current) { if (!this.isGroupExpanded(current)) { return false } current = current.parentGroup } return true } // // Internal functions // function getInspectorGroupStatuses() { var statuses = document.body.getAttribute('data-inspector-group-statuses') if (statuses !== null) { return JSON.parse(statuses) } return {} } function setInspectorGroupStatuses(statuses) { document.body.setAttribute('data-inspector-group-statuses', JSON.stringify(statuses)) } // GROUP CLASS // ============================ var Group = function(groupId) { this.groupId = groupId this.parentGroup = null this.groupIndex = null this.groups = [] } Group.prototype.getGroupIndex = function() { if (this.groupIndex !== null) { return this.groupIndex } var result = '', current = this while (current) { if (result.length > 0) { result = current.groupId + '-' + result } else { result = String(current.groupId) } current = current.parentGroup } this.groupIndex = result return result } Group.prototype.findGroupByIndex = function(index) { if (this.getGroupIndex() == index) { return this } for (var i = this.groups.length-1; i >= 0; i--) { var groupResult = this.groups[i].findGroupByIndex(index) if (groupResult !== null) { return groupResult } } return null } Group.prototype.getLevel = function() { var current = this, level = -1 while (current) { level++ current = current.parentGroup } return level } Group.prototype.getGroupAndAllParents = function() { var current = this, result = [] while (current) { result.push(current) current = current.parentGroup } return result } Group.prototype.findGroupRows = function(table, ignoreCollapsedSubgroups, groupManager) { var groupIndex = this.getGroupIndex(), rows = table.querySelectorAll('tr[data-parent-group-index="'+groupIndex+'"]'), result = Array.prototype.slice.call(rows) // Convert node list to array for (var i = 0, len = this.groups.length; i < len; i++) { var subgroup = this.groups[i] if (ignoreCollapsedSubgroups && !groupManager.isGroupExpanded(subgroup)) { continue } var subgroupRows = subgroup.findGroupRows(table, ignoreCollapsedSubgroups, groupManager) for (var j = 0, subgroupLen = subgroupRows.length; j < subgroupLen; j++) { result.push(subgroupRows[j]) } } return result } Group.prototype.findGroupRow = function(table) { return table.querySelector('tr[data-group-index="'+this.groupIndex+'"]') } $.oc.inspector.groupManager = GroupManager }(window.jQuery);