/*global AZCAT,YAHOO,waitStatus,
         doIEPNGFixImgFrom,setNodeValue,recursivePurgeAndRemove,
         isFCKEditorBrowse,browseSelect,Shadowbox,doFileProperties,
         prefsClick,escape,
         createAutoComplete, portal_url,
         editOpensInNewWindow, show_action_buttons,
         doIEPNGFix,clipboard */

/*jslint white: true, onevar: true, browser: true, on: true, undef: true,
         eqeqeq: true, plusplus: true, bitwise: true, regexp: true,
         newcap: true, immed: true, indent: 2, nomen: false */

var object = function () {
  function F() {}
  return function (o) {
    F.prototype = o;
    return new F();
  };
}(), $hasOwnProperty = function (o, p) {
  return !o.constructor().constructor.prototype.hasOwnProperty(p);
};

AZCAT.siteman.Data = function () {
  // Shared resources, ALL instances
  // Cached singletons
  var $l = YAHOO.lang,
      _callback,
      _callback_scope,
      _allDirty;

  // Shared private functions

  function _addItem(obj) { // Also, replace
    var parentObj, alreadySubitem, i, ilen;
    this._items[obj.cmf_uid] = obj;
    // Add the item to the tree if appropriate
    if (this._tree.length) {
      parentObj = this._getParent(obj.cmf_uid);
      if (parentObj) {
        alreadySubitem = false;
        for (i = 0, ilen = parentObj.subitems.length; i < ilen; i += 1) {
          if (parentObj.subitems[i].cmf_uid === obj.cmf_uid) {
            alreadySubitem = true;
            break;
          }
        }
        if (!alreadySubitem) {
          parentObj.subitems.push(obj);
        }
      }
    }
    this.itemAdded.fire(obj);
  }

  function _updateItem(id, obj) {
    if ($l.isUndefined(this._items[id])) {
      this._items[id] = {};
    }
    if ($l.isObject(obj)) {
      for (var i in obj) {
        if ($hasOwnProperty(obj, i)) {
          this._items[id][i] = obj[i];
          // This should be replaced by a custom event that dataView can
          // subscribe to.
          this._parent.dataView.addDirtyData(id, [i]);
        }
      }
    }
  }

  function _deleteItem(cmf_uid) {
    if (!$l.isUndefined(this._items[cmf_uid])) {
      this._parent.dataView.addWasRemoved(cmf_uid, this._getParent(cmf_uid));
      return delete this._items[cmf_uid];
    }
    return false;
  }

  function _buildList() {
    this._list = [];
    var items = [], i, iLen;
    for (i = 0, iLen = this._display_order.length; i < iLen; i += 1) {
      if (!YAHOO.lang.isUndefined(this._items[this._display_order[i]])) {
        items.push(object(this._items[this._display_order[i]]));
      }
    }
    this._list = items;
    this._listDirty = false;
  }

  function _buildTree() {
    var i, ilen, currentItem = null, items, parentItem;
    this._tree = [];
    items = [];
    for (i = 0, ilen = this._display_order.length; i < ilen; i += 1) {
      if (!YAHOO.lang.isUndefined(this._items[this._display_order[i]])) {
        if (
          $l.isNull(currentItem) ||
          currentItem.length > this._items[this._display_order[i]].path.length
        ) {
          currentItem = this._items[this._display_order[i]].path;
        }
        items.push(object(this._items[this._display_order[i]]));
      }
    }
    parentItem = this._tree;
    for (i = 0, ilen = items.length; i < ilen; i += 1) {
      if (items[i].path === currentItem) {
        parentItem.push(items[i]);
      }
      else {
        currentItem = items[i].path;
        parentItem = this._getParent(items[i].cmf_uid);
        // Customized here to allow sitemap to work if a folder is set to
        // exclude from sitemap but it's children aren't.
        if (parentItem === null) {
          parentItem = [];
          continue;
        } else {
          parentItem = parentItem.subitems;
        }
        parentItem.push(items[i]);
      }
    }
    this._treeDirty = false;
  }

  function _getItemsForUpdate() {
    var items = {}, i;
    for (i in this._items) {
      if ($hasOwnProperty(this._items, i)) {
        items[i] = this._items[i].last_catalogued;
      }
    }
    return items;
  }

  function _invalidateDataLackingColumns(columns) {
    /* This is used if a column is added. We need to get a new version of items
       lacking that column */
    var i, iLen, thisColumn, j;
    for (i = 0, iLen = columns.length; i < iLen; i += 1) {
      thisColumn = columns[i];
      for (j in this._items) {
        if (this._items.hasOwnProperty(j)) {
          if (YAHOO.util.Lang.isUndefined(this._items[j][thisColumn])) {
            this._items[j].last_catalogued = -1;
          }
        }
      }
    }
  }

  function _getDataColumns() {
    var visible_columns = this._parent.prefs.getPreference(
      "columns",
      this._parent.data.prefs_id
    ), visible_columns_obj = {}, i, iLen, j, jLen,
        data_columns = [], data_column_obj = {},
        mand_columns = ['actions', 'cmf_uid', 'last_catalogued', 'path', 'id',
                        'is_folderish', 'sort_order'];

    for (i = 0, iLen = visible_columns.length; i < iLen; i += 1) {
      visible_columns_obj[visible_columns[i]] = true;
    }

    for (i in this._parent.dataToColumns) {
      if (this._parent.dataToColumns.hasOwnProperty(i)) {
        for (j = 0, jLen = this._parent.dataToColumns[i].length;
             j < jLen; j += 1) {
          if (!YAHOO.util.Lang.isUndefined(
            visible_columns_obj[this._parent.dataToColumns[i][j]]
          )) {
            data_column_obj[i] = true;
            break;
          }
        }
      }
    }
    // We always need these columns, no matter which columns are displayed
    for (i = 0, iLen = mand_columns.length; i < iLen; i += 1) {
      if (YAHOO.util.Lang.isUndefined(data_column_obj[mand_columns[i]])) {
        data_column_obj[mand_columns[i]] = true;
      }
    }

    for (i in data_column_obj) {
      if (data_column_obj.hasOwnProperty(i)) {
        data_columns.push(i);
      }
    }

    return data_columns;
  }

  function _updateFromServerCallback(o) {
    var items, temp_callback, temp_callback_scope, temp_allDirty,
        searchByString, searchBy;
    items = JSON.parse(o.responseText);
    this.updateItems(items.created,
                     items.updated,
                     items.deleted,
                     items.displayed_uids,
                     items.full_size);
    if (!$l.isUndefined(items.view_root_actions)) {
      this._root_actions = items.view_root_actions;
      this.rootActionsSet.fire(items.view_root_actions);
    }
    if (_callback) {
      temp_callback = _callback;
      temp_callback_scope = _callback_scope;
      temp_allDirty = _allDirty;
      _callback = null;
      _callback_scope = null;
      _allDirty = null;
      temp_callback.call(temp_callback_scope, temp_allDirty);
    }
    searchByString = YAHOO.util.Cookie.get("prefilter");
    if (searchByString) {
      searchBy = document.getElementById("search_by");
      searchBy.value = searchByString;
      YAHOO.util.Cookie.remove("prefilter");
      this._parent.dataView._doSearch();
    }
  }

  function _getSearchResultsFromServerCallback(o) {
    var items = JSON.parse(o.responseText),
        temp_callback, temp_callback_scope, temp_allDirty;
    this.updateItems(items.created,
                     items.updated,
                     items.deleted,
                     items.displayed_uids,
                     items.full_size);
    if (_callback) {
      temp_callback = _callback;
      temp_callback_scope = _callback_scope;
      temp_allDirty = _allDirty;
      _callback = null;
      _callback_scope = null;
      _allDirty = null;
      temp_callback.call(temp_callback_scope, temp_allDirty);
    }
    waitStatus(false);
  }

  function _setInPowerFilterMode(inPowerFilterMode) {
    this._inPowerFilterMode = inPowerFilterMode;
  }

  function _getPowerFilterSearchResultsFromServerCallback(o) {
    var items = JSON.parse(o.responseText),
        temp_callback, temp_callback_scope, temp_allDirty;
    this.updateItems(items.created,
                     items.updated,
                     items.deleted,
                     items.displayed_uids,
                     items.full_size);
    if (_callback) {
      temp_callback = _callback;
      temp_callback_scope = _callback_scope;
      temp_allDirty = _allDirty;
      _callback = null;
      _callback_scope = null;
      _allDirty = null;
      temp_callback.call(temp_callback_scope, temp_allDirty);
    }
    waitStatus(false);
  }

  function _getPowerFilterFormCallback(o) {
    var formData, scripts, myDialog, that;
    waitStatus(false);
    formData = JSON.parse(o.responseText);
    myDialog = new AZCAT.Dialog();
    myDialog.setHeader([myDialog.headerleft, "Power Filter",
                        myDialog.headerright].join(""));
    myDialog.setBody(formData.html);
    myDialog.setFooter([myDialog.footerleft, myDialog.footerright].join(""));
    that = this;
    myDialog.hideEvent.subscribe(cancelPowerFilter, myDialog, that);
    myDialog.render(document.body);

    scripts = document.getElementById("power_filter_form");
    scripts = scripts.getElementsByTagName("script");

    // Load any scripts that are returned with the widgets
    AZCAT.scripts.add("powerFilter", scripts);

    // Initialize any widgets
    for (x = 0, xLen = formData.initScripts.length; x < xLen; x += 1) {
      funcName = formData.initScripts[x].fn;
      if (window[funcName]) {
        window[funcName]();
      }
    }

    this._setInPowerFilterMode(true);
    myDialog.show();
    YAHOO.util.Event.on("power_filter_submit", "click", getPowerFilterFromServer, myDialog, that);
    YAHOO.util.Event.on("power_filter_cancel", "click", cancelPowerFilter, myDialog, that);
    myDialog.changeBodyEvent.fire();
    myDialog.center();
  }

  function _climbTree(c, from) {
    var nextC, i, ilen;
    for (i = 0, ilen = from.length; i < ilen; i += 1) {
      // Mild Hack: We assume that the root of this._tree has been set
      if (from[i].id === c[0] || from[i].cmf_uid === this._tree[0].cmf_uid) {
        if ($l.isUndefined(from[i].subitems)) {
          from[i].subitems = [];
        }
        nextC = c.slice(from[i].cmf_uid === this._tree[0].cmf_uid ?
                        this._tree[0].path.split('/').length : 1);
        if (nextC.length) {
          return this._climbTree(nextC, from[i].subitems);
        }
        else {
          return from[i];
        }
      }
    }
    // Customized here to allow sitemap to work if a folder is set to
    // exclude from sitemap but it's children aren't.
    return null;
  }

  function _getParent(cmf_uid) {
    var path;
    if (this._tree.length && cmf_uid !== this._tree[0].cmf_uid) {
      path = this._items[cmf_uid].path.split('/').slice(0, -1);
      if (path.length) {
        return this._climbTree(path, this._tree);
      }
    }
    return null;
  }

  function _getAllActions() {
    var allActions = {},
        i, thisItem, x, xLen, thisAction;

    // If the view root is not in the items, we need to add its actions in
    // manually
    if ($l.isUndefined(this._items[this.root_cmf_uid]) &&
        !$l.isUndefined(this._root_actions)) {
      for (x = 0, xLen = this._root_actions.length; x < xLen; x += 1) {
        thisAction = this._root_actions[x];
        if ($l.isUndefined(allActions[thisAction.id])) {
          allActions[thisAction.id] = {title: thisAction.title,
                                       icon: thisAction.icon};
        }
      }
    }

    for (i in this._items) {
      if ($hasOwnProperty(this._items, i)) {
        thisItem = this._items[i];
        if (thisItem.actions) {
          for (x = 0, xLen = thisItem.actions.length; x < xLen; x += 1) {
            thisAction = thisItem.actions[x];
            if ($l.isUndefined(allActions[thisAction.id])) {
              allActions[thisAction.id] = {title: thisAction.title,
                                           icon: thisAction.icon};
            }
          }
        }
      }
    }
    return allActions;
  }

  function _getActionIdsByCmfUid(cmf_uids, callback, callback_scope) {
    YAHOO.util.Connect.asyncRequest('POST',
                                    [this.portal_url,
                                     '/getEnabledActionsForSelected'].join(""),
                                    {scope: callback_scope,
                                     success: callback,
                                     failure: AZCAT.utils.connFail},
                                    'cmf_uids=' + JSON.stringify(cmf_uids));
  }

  function updateItems(created, updated, deleted, display_order, full_size) {
    var i, ilen;
    this._full_size = full_size;
    if (updated) {
      for (i = 0, ilen = updated.length; i < ilen; i += 1) {
        this._updateItem(updated[i].cmf_uid, updated[i]);
      }
    }
    if (deleted) {
      for (i = 0, ilen = deleted.length; i < ilen; i += 1) {
        this._deleteItem(deleted[i]);
      }
    }
    if (created) {
      for (i = 0, ilen = created.length; i < ilen; i += 1) {
        this._addItem(created[i]);
      }
    }
    if (display_order) {
      this._display_order = display_order;
    }
    if (deleted || created) {
      this._listDirty = true;
      this._treeDirty = true;
      this._searchResultsDirty = true;
    }
  }

  function getLast(data, myparent) {
    var p = myparent || this._getParent(data.cmf_uid);
    if (p === null) {
      return true;
    }
    return p.subitems[p.subitems.length - 1].cmf_uid === data.cmf_uid;
  }

  function sortList(sortOn, isDescending) {
    if (!$l.isUndefined(this._parent.sortCols[sortOn])) {
      if ($l.isBoolean(isDescending)) {
        this._isListSortDescending = isDescending;
      }
      this._listSortOn = sortOn;
      this._listDirty = true;
      // This should be replaced by a custom event that dataView can subscribe
      // to.
      this._parent.prefs.setPreferences({
          "lastSortedOn" : sortOn,
          "lastSortedOrder" : $l.isBoolean(isDescending) ?
                              isDescending :
                              this._isListSortDescending
        },
        this.prefs_id
      );
      return true;
    }
    else {
      YAHOO.log('Tried to sort on unsortable column.');
      return false;
    }
  }

  function getList() {
    if (this._listDirty) {
      this._buildList();
    }
    return this._list;
  }

  function getTree() {
    if (this._treeDirty) {
      this._buildTree();
    }
    return this._tree;
  }

  function getTreeNode(id) {
    var path;
    if (this._treeDirty) {
      this._buildTree();
    }
    if (this._items[id]) {
      path = (this._items[id].path + this._items[id].id);
      if (path.charAt(path.length - 1) === '/') {
        path = path.slice(0, -1);
      }
      return object(this._climbTree(path.split('/'), this._tree));
    }
    else if (this._items[id.toString()]) {
      path = (this._items[id.toString()].path + this._items[id.toString()].id);
      if (path.charAt(path.length - 1) === '/') {
        path = path.slice(0, -1);
      }
      return object(this._climbTree(path.split('/'), this._tree));
    }
    else if ($l.isString(id) && this._items[id.slice(8)]) {
      path = this._items[id.slice(8)].path + this._items[id.slice(8)].id;
      if (path.charAt(path.length - 1) === '/') {
        path = path.slice(0, -1);
      }
      return object(this._climbTree(path.split('/'), this._tree));
    }
  }

  function getData(id) {
    if (this._items[id]) {
      return object(this._items[id]);
    }
    else if (this._items[id.toString()]) {
      return object(this._items[id.toString()]);
    }
    else if ($l.isString(id) && this._items[id.slice(8)]) {
      return object(this._items[id.slice(8)]);
    }
  }

  function updateFromServer(callback, callback_scope, allDirty) {
    if (_callback) {
      throw {name: 'BusyError',
             message: 'An asynchronous transaction is already in progress.'};
    }
    _callback = callback;
    _callback_scope = callback_scope;
    _allDirty = allDirty;
    waitStatus(true);
    var queryString = [], searchBy, searchByTemp, that;
    if (this._parent.dataView.isSearch()) {
      searchBy = this._parent.prefs.getPreference("lastSearchedBy",
                                                  this.prefs_id);
      if (searchBy) {
        try{
          searchByTemp = JSON.parse(searchBy);
        } catch(err) {
          searchBy = JSON.stringify({"SearchableText" : searchBy});
        }
        queryString.push("searchBy=" + escape(searchBy));
        this._parent.dataView.setIsSearch(true);
      }
    }
    if (!allDirty) {
      queryString.push("itemsForUpdate=" +
                       JSON.stringify(this._getItemsForUpdate()));
    }
    if (this._parent.dataView._isTree) {
      queryString.push("sort_on=" + escape(JSON.stringify(["tree"])));
    } else if (this._listSortOn) {
      queryString.push(
        "sort_on=" +
        escape(JSON.stringify([this._parent.sortCols[this._listSortOn]]))
      );
      queryString.push("sort_ascending%3aboolean=" +
                       (this._isListSortDescending ? 'False' : 'True'));
      queryString.push(
        "batch_data=" +
        escape(
          JSON.stringify(
            {batch_start: this._batching.start,
             batch_size: this._batching.perPageSelect *
                         this._batching.perRowSelect}
          )
        )
      );
    }

    queryString.push("columns=" +
                     escape(JSON.stringify(this._getDataColumns())));

    that = this;
    filterType = this._parent.prefs.getPreference("lastSearchedByType",
                                                  this.prefs_id);
    if (this._parent.dataView.isSearch() && filterType === "powerFilter") {
      YAHOO.util.Connect.asyncRequest('POST',
                                      [this.context_url, '/getPowerFilterForm'].join(""),
                                      {scope: that,
                                       success: that._getPowerFilterSearchResultsFromServerCallback,
                                       failure: AZCAT.utils.connFail},
                                      queryString.join('&'));
    } else {
      YAHOO.util.Connect.asyncRequest('POST',
                                      [this.context_url, '/updateJson'].join(""),
                                      {scope: that,
                                       success: that._updateFromServerCallback,
                                       failure: AZCAT.utils.connFail},
                                      queryString.join("&"));
    }
  }

  function updateItemsFromServer(callback, callback_scope, items_for_update) {
    if (_callback) {
      throw {name: 'BusyError',
             message: 'An asynchronous transaction is already in progress.'};
    }
    _callback = callback;
    _callback_scope = callback_scope;
    _allDirty = true;
    waitStatus(true);
    var queryString = [], searchBy, that, filterType;
    if (this._parent.dataView.isSearch()) {
      searchBy = this._parent.prefs.getPreference("lastSearchedBy",
                                                  this.prefs_id);
      if (searchBy) {
        queryString.push("searchBy=" + escape(searchBy));
      }
    }
    if (items_for_update) {
      queryString.push("itemsForUpdate=" + JSON.stringify(items_for_update));
    }
    if (this._parent.dataView._isTree) {
      queryString.push("sort_on=" + escape(JSON.stringify(["tree"])));
    } else if (this._listSortOn) {
      queryString.push(
        "sort_on=" +
        escape(JSON.stringify([this._parent.sortCols[this._listSortOn]]))
      );
      queryString.push("sort_ascending%3aboolean=" +
                       (this._isListSortDescending ? 'False' : 'True'));
      queryString.push(
        "batch_data=" +
        escape(JSON.stringify({batch_start: this._batching.start,
                               batch_size: this._batching.perPageSelect *
                                           this._batching.perRowSelect}))
      );
    }

    queryString.push("columns=" +
                     escape(JSON.stringify(this._getDataColumns())));

    that = this;
    filterType = this._parent.prefs.getPreference("lastSearchedByType",
                                                  this.prefs_id);
    if (this._parent.dataView.isSearch() && filterType === "powerFilter") {
      YAHOO.util.Connect.asyncRequest('POST',
                                      [this.context_url, '/getPowerFilterForm'].join(""),
                                      {scope: that,
                                       success: that._getPowerFilterSearchResultsFromServerCallback,
                                       failure: AZCAT.utils.connFail},
                                      queryString.join('&'));
    } else {
      YAHOO.util.Connect.asyncRequest('POST',
                                      [this.context_url, '/updateJson'].join(""),
                                      {scope: that,
                                       success: that._updateFromServerCallback,
                                       failure: AZCAT.utils.connFail},
                                      queryString.join("&"));
    }
  }

  function getSearchResultsFromServer(callback, callback_scope) {
    if (_callback) {
      throw {name: 'BusyError',
             message: 'An asynchronous transaction is already in progress.'};
    }
    _callback = callback;
    _callback_scope = callback_scope;
    _allDirty = true;
    waitStatus(true);
    this._searchResultsDirty = true;
    this._parent.dataView.setIsSearch(true);
    var queryString = ["searchBy=" +
                       escape(this._parent.prefs.getPreference("lastSearchedBy",
                                                               this.prefs_id))],
        that;
    if (this._parent.dataView._isTree) {
      queryString.push("sort_on=" + escape(JSON.stringify(["tree"])));
    } else if (this._listSortOn) {
      queryString.push(
        "sort_on=" +
        escape(JSON.stringify([this._parent.sortCols[this._listSortOn]]))
      );
      queryString.push("sort_ascending%3aboolean=" +
                       (this._isListSortDescending ? 'False' : 'True'));
      queryString.push(
        "batch_data=" +
        escape(JSON.stringify({batch_start: this._batching.start,
                               batch_size: this._batching.perPageSelect *
                                           this._batching.perRowSelect}))
      );
    }

    queryString.push("columns=" +
                     escape(JSON.stringify(this._getDataColumns())));

    that = this;
    YAHOO.util.Connect.asyncRequest(
      'POST',
      [this.context_url, '/updateJson'].join(""),
      {scope: that,
       success: that._getSearchResultsFromServerCallback,
       failure: AZCAT.utils.connFail},
      queryString.join('&')
    );
  }

  function getPowerFilterFromServer(e, myDialog) {
    var searchBy, queryString, that;
    YAHOO.util.Event.stopEvent(e);
    YAHOO.util.Connect.setForm("power_filter_form");
    searchBy = JSON.stringify(YAHOO.util.Connect._sFormData);
    YAHOO.util.Connect.resetFormState();
    queryString = ["searchBy=" + escape(searchBy),
                   "_submit_=" + escape(JSON.stringify(1))],
    this.cancelPowerFilter(e, myDialog);
    _callback = this._parent.dataView.updateDisplay;
    _callback_scope = this._parent.dataView;
    _allDirty = true;
    waitStatus(true);
    this._searchResultsDirty = true;
    this._parent.dataView.setIsSearch(true);
    if (this._parent.dataView._isTree) {
      queryString.push("sort_on=" + escape(JSON.stringify(["tree"])));
    } else if (this._listSortOn) {
      queryString.push(
        "sort_on=" +
        escape(JSON.stringify([this._parent.sortCols[this._listSortOn]]))
      );
      queryString.push("sort_ascending%3aboolean=" +
                       (this._isListSortDescending ? 'False' : 'True'));
      queryString.push(
        "batch_data=" +
        escape(JSON.stringify({batch_start: this._batching.start,
                               batch_size: this._batching.perPageSelect *
                                           this._batching.perRowSelect}))
      );
    }

    queryString.push("columns=" +
                     escape(JSON.stringify(this._getDataColumns())));

    if (this._searchedFromViewType === "") {
      this._searchedFromViewType = this.getViewType();
    }

    // Disable the current tab
    this._parent.dataView._changeActiveTab(false);

    // Change the state to List for the search
    this._parent.dataView.setViewType("List");
    this._parent.prefs.setPreferences({"lastSearchedBy": searchBy},
                                       this._parent.data.prefs_id);

    // Enable the new tab
    this._parent.dataView._changeActiveTab(true);

    that = this;
    YAHOO.util.Connect.asyncRequest(
      'POST',
      [this.context_url, '/getPowerFilterForm'].join(""),
      {scope: that,
       success: that._getPowerFilterSearchResultsFromServerCallback,
       failure: AZCAT.utils.connFail},
      queryString.join('&')
    );
    this._parent.dataView._displayClearButton();
  }

  function getInPowerFilterMode() {
    return this._inPowerFilterMode;
  }

  function getPowerFilterForm() {
    var that, queryString;
    waitStatus(true);
    that = this;
    queryString = [];
    if (this._parent.dataView.isSearch()) {
      // We need to load the power filter form with the
      // search terms from the previous power filter.
      queryString.push("powerFilterLastSearchedBy=" +
                       escape(AZCAT.siteman.prefs.getPreference("lastSearchedBy",
                                                                this.prefs_id)));
    }
    YAHOO.util.Connect.asyncRequest("POST",
                                    this.context_url + "/getPowerFilterForm",
                                    {scope: that,
                                     success: that._getPowerFilterFormCallback,
                                     failure: AZCAT.utils.connFail},
                                    queryString.join('&'));
  }

  function cancelPowerFilter(e, myDialog) {
    AZCAT.editForm.main.clearEnabledFields();
    AZCAT.scripts.remove("powerFilter");
    this._setInPowerFilterMode(false);
    if (myDialog.hide) {
      myDialog.hide();
    }
    myDialog = null;
  }

  function batchPrevious() {
    var batchStart = this._batching.start -
                     (this._batching.perPageSelect *
                      this._batching.perRowSelect);
    if (batchStart < 0) {
      batchStart = 0;
    }
    this._batching.start = batchStart;
  }

  function batchNext() {
    var batchStart = this._batching.start +
                     (this._batching.perPageSelect *
                      this._batching.perRowSelect),
        results_length = this.getListLength();
    if (batchStart > results_length) {
      batchStart = results_length;
    }
    this._batching.start = batchStart;
  }

  function resetBatchSize() {
    this._batching.perPageSelect = this._parent.prefs.getPreference(
      "perPage",
      this.prefs_id
    );
    this._batching.perRowSelect = this._parent.prefs.getPreference(
      "perRow",
      this.prefs_id
    );
  }

  function resetBatchStart() {
    this._batching.start = 0;
    this._parent.dataView.resetBatchStart();
  }

  function getListLength() {
    return this._full_size;
  }

  function getLastArray(data, myparent) {
    data = myparent || this._getParent(data.cmf_uid);
    if (data === null) {
      return [];
    }
    return this.getLastArray(data).concat(this.getLast(data));
  }

  function doSort(e) {
    var img = YAHOO.util.Event.getTarget(e),
        newSortOn = img.parentNode.parentNode.id;
    if (this._listSortOn === newSortOn) {
      this.sortList(this._listSortOn, !this._isListSortDescending);
    }
    else {
      this.sortList(newSortOn, false);
    }
    if (this._parent.dataView.isSearch()) {
      this._searchResultsDirty = true;
    }
    this.getBatchDataAndUpdateItemsFromServer(this._isSearch);
  }

  function getInfo(row, override) {
    var myparent = this._getParent(row.cmf_uid),
        i,
        isLast = !myparent && true || getLast(row, myparent),
    // need to add one to the start to fix an assumption in getLastArray
        last = myparent && this.getLastArray(row, myparent) || [],
        isOpen = row.cmf_uid in this._parent.prefs.getPreference(
          "openTo",
          this.prefs_id
        ),
        hasSubitems = row.subitems && row.subitems.length !== 0,
        info = {row: row, isLast: isLast, isOpen: isOpen,
                hasSubitems: hasSubitems, last: last, root_id: this.root_id,
                root_cmf_uid: this._tree && this._tree.length &&
                              this._tree[0].cmf_uid,
                root_path: this._tree && this._tree.length &&
                           this._tree[0].path};
    for (i in override) {
      if (override.hasOwnProperty(i)) {
        info[i] = override[i];
      }
    }
    return info;
  }

  function getBatchDataAndUpdateItemsFromServer(isSearch) {
    var items_for_update = {},
        x;
    for (x in this._items) {
      if (this._items.hasOwnProperty(x)) {
        items_for_update[x] = this._items[x].last_catalogued;
      }
    }
    this.updateItemsFromServer(this._parent.dataView.updateDisplay,
                               this._parent.dataView,
                               items_for_update);
  }

  return function (parent, root_data) {
    // My resources, this instance
    // Private varables, actual

    return {//Private varables, by convention not actually hidden
      _parent : parent,
      _items : {},
      _list : [],
      _display_order: [],
      _full_size: 0,
      _listDirty : true,
      _listSortOn : '',
      _isListSortDescending : false,
      _tree : [],
      _treeDirty : true,
      _searchResults : [],
      _searchResultsDirty : true,
      _batching : {start : 0,
                   perPageSelect : 10,
                   perRowSelect : 3},
      _root_actions : [],
      _allow_power_filter: root_data.allow_power_filter,
      _inPowerFilterMode: false,
      // Should this be in dataView instead?
      _click_action : root_data.click_action,
      //Private Methods
      _addItem : _addItem,
      _updateItem : _updateItem,
      _deleteItem : _deleteItem,
      _buildList : _buildList,
      _buildTree : _buildTree,
      _getItemsForUpdate : _getItemsForUpdate,
      _invalidateDataLackingColumns : _invalidateDataLackingColumns,
      _getDataColumns : _getDataColumns,
      _updateFromServerCallback : _updateFromServerCallback,
      _getSearchResultsFromServerCallback :
        _getSearchResultsFromServerCallback,
      _setInPowerFilterMode: _setInPowerFilterMode,
      _getPowerFilterSearchResultsFromServerCallback : _getPowerFilterSearchResultsFromServerCallback,
      _getPowerFilterFormCallback : _getPowerFilterFormCallback,
      _climbTree : _climbTree,
      _getParent : _getParent,
      _getAllActions : _getAllActions,
      _getActionIdsByCmfUid : _getActionIdsByCmfUid,
      // Public methods
      updateItems : updateItems,
      getLast : getLast,
      sortList : sortList,
      getList : getList,
      getTree : getTree,
      getTreeNode : getTreeNode,
      getData : getData,
      updateFromServer : updateFromServer,
      updateItemsFromServer : updateItemsFromServer,
      getSearchResultsFromServer : getSearchResultsFromServer,
      getInPowerFilterMode: getInPowerFilterMode,
      getPowerFilterForm : getPowerFilterForm,
      cancelPowerFilter : cancelPowerFilter,
      getPowerFilterFromServer : getPowerFilterFromServer,
      batchPrevious : batchPrevious,
      batchNext : batchNext,
      resetBatchSize : resetBatchSize,
      resetBatchStart : resetBatchStart,
      getListLength : getListLength,
      getLastArray : getLastArray,
      doSort : doSort,
      getInfo : getInfo,
      getBatchDataAndUpdateItemsFromServer :
        getBatchDataAndUpdateItemsFromServer,
      // Public Variables
      root_cmf_uid : root_data.cmf_uid,
      root_path : root_data.path,
      root_id : root_data.id,
      prefs_id : root_data.prefs_id,
      context_url : portal_url + root_data.path + root_data.id,
      // Public Events
      rootActionsSet : new YAHOO.util.CustomEvent("rootActionsSet", this),
      itemAdded : new YAHOO.util.CustomEvent("itemAdded", this)
    };
  };
}();




AZCAT.siteman.DataView = function () {
  // Shared resources; ALL instances
  // Cached singletons;
  var $l = YAHOO.lang, dialogEventHandlers;

  // Shared private functions

  function _setViewType(view) {
    if ($l.isString(view) &&
        ['List', 'Tree', 'Gallery'].indexOf(view) !== -1) {
      if (this._viewType) {
        YAHOO.util.Dom.removeClass(['refresh', this._viewType, 'LI'].join(""),
                                   'highlight');
      }
      this._viewType = view;
      this._isTree = (view === 'Tree');
      this._isList = (view === 'List');
      this._isGallery = (view === 'Gallery');
      YAHOO.util.Dom.addClass(['refresh', this._viewType, 'LI'].join(""),
                              'highlight');
    }
  }

  function _drawTree(json_data, tbody) {
    var row, myid, tr, x, xlen, info,
        columns = this._parent.prefs.getPreference("columns",
                                                   this._parent.data.prefs_id),
        i, ilen;
    for (i = 0, ilen = json_data.length; i < ilen; i += 1) {
      row = json_data[i];
      myid = ['cmf_uid_', row.cmf_uid].join("");
      tr = document.createElement('tr');
      tr.id = myid;
      tr.style.display = "none";
      tbody.appendChild(tr);
      info = this._parent.data.getInfo(row, {isTree: this._isTree});
      for (x = 0, xlen = columns.length; x < xlen; x += 1) {
        info.td = document.createElement('td');
        info.td.id = [myid, '|||', columns[x]].join('');
        tr.appendChild(info.td);
        this._parent.displayCode[columns[x]](info);
        info.td = null;
      }
      doIEPNGFixImgFrom(tr);

      if (info.hasSubitems) {
        if (info.isOpen) {
          this._drawTree(row.subitems, tbody);
        }
      }
      info = null;
      tr = null;
    }
    tbody = null;
  }

  function _createBatchFooter() {
    var tfoot = document.createElement("tfoot"),
        tr = document.createElement("tr"),
        td = document.createElement("td"),
        colspan = document.createAttribute("colspan"),
        previous_a = document.createElement("a"),
        previous_href = document.createAttribute("href"),
        previous_text2 = document.createTextNode("<< Previous"),
        previous_span = document.createElement("span"),
        previous_text = document.createTextNode("<< Previous"),
        results_span = document.createElement("span"),
        results_showing_text = document.createTextNode("Showing results "),
        results_min = document.createElement("span"),
        results_min_text = document.createTextNode("0"),
        results_to_text = document.createTextNode(" to "),
        results_max = document.createElement("span"),
        results_max_text = document.createTextNode("0"),
        results_of_text = document.createTextNode(" of "),
        results_total = document.createElement("span"),
        results_total_text = document.createTextNode("0"),
        next_a = document.createElement("a"),
        next_href = document.createAttribute("href"),
        next_text2 = document.createTextNode("Next >>"),
        next_span = document.createElement("span"),
        next_text = document.createTextNode("Next >>");

    YAHOO.util.Dom.setStyle(tfoot, "display", "none");
    tfoot.id = 'batching_container';
    td.id = 'batching_td';
    setNodeValue(colspan, this._getColumnsLength());
    td.setAttributeNode(colspan);
    YAHOO.util.Dom.setStyle(td, "padding", "10px");
    YAHOO.util.Dom.setStyle(td, "text-align", "center");
    previous_a.id = 'previous_a';
    YAHOO.util.Dom.setStyle(previous_a, "display", "none");
    setNodeValue(previous_href, "#");
    previous_a.setAttributeNode(previous_href);
    YAHOO.util.Event.addListener(previous_a, "click",
                                 this.batchPreviousClick, this, true);
    previous_span.id = 'previous_span';
    YAHOO.util.Dom.setStyle(results_span, "paddingLeft", "15px");
    YAHOO.util.Dom.setStyle(results_span, "paddingRight", "15px");
    results_min.id = 'results_min';
    results_max.id = 'results_max';
    results_total.id = 'results_total';
    next_a.id = 'next_a';
    YAHOO.util.Dom.setStyle(next_a, "display", "none");
    setNodeValue(next_href, "#");
    next_a.setAttributeNode(next_href);
    YAHOO.util.Event.addListener(next_a, "click", this.batchNextClick, this,
                                 true);
    next_span.id = 'next_span';

    tfoot.appendChild(tr);
    tr.appendChild(td);
    td.appendChild(previous_a);
    td.appendChild(previous_span);
    td.appendChild(results_span);
    td.appendChild(next_a);
    td.appendChild(next_span);

    previous_span.appendChild(previous_text);
    previous_a.appendChild(previous_text2);
    next_span.appendChild(next_text);
    next_a.appendChild(next_text2);
    results_span.appendChild(results_showing_text);
    results_span.appendChild(results_min);
    results_span.appendChild(results_to_text);
    results_span.appendChild(results_max);
    results_span.appendChild(results_of_text);
    results_span.appendChild(results_total);
    results_min.appendChild(results_min_text);
    results_max.appendChild(results_max_text);
    results_total.appendChild(results_total_text);

    this._batching.Container = tfoot.id;
    this._batching.TD = td.id;
    this._batching.Min = results_min.id;
    this._batching.Max = results_max.id;
    this._batching.Total = results_total.id;
    this._batching.PreviousSpan = previous_span.id;
    this._batching.PreviousA = previous_a.id;
    this._batching.NextSpan = next_span.id;
    this._batching.NextA = next_a.id;

    tr = null;
    td = null;
    colspan = null;
    previous_a = null;
    previous_href = null;
    previous_text2 = null;
    previous_span = null;
    previous_text = null;
    results_span = null;
    results_showing_text = null;
    results_min = null;
    results_min_text = null;
    results_to_text = null;
    results_max = null;
    results_max_text = null;
    results_of_text = null;
    results_total = null;
    results_total_text = null;
    next_a = null;
    next_href = null;
    next_text2 = null;
    next_span = null;
    next_text = null;

    return tfoot;
  }

  function _showPreviousLink() {
    YAHOO.util.Dom.setStyle(this._batching.PreviousSpan, "display", "none");
    YAHOO.util.Dom.setStyle(this._batching.PreviousA, "display", "inline");
  }

  function _hidePreviousLink() {
    YAHOO.util.Dom.setStyle(this._batching.PreviousA, "display", "none");
    YAHOO.util.Dom.setStyle(this._batching.PreviousSpan, "display", "inline");
  }

  function _showNextLink() {
    YAHOO.util.Dom.setStyle(this._batching.NextSpan, "display", "none");
    YAHOO.util.Dom.setStyle(this._batching.NextA, "display", "inline");
  }

  function _hideNextLink() {
    YAHOO.util.Dom.setStyle(this._batching.NextA, "display", "none");
    YAHOO.util.Dom.setStyle(this._batching.NextSpan, "display", "inline");
  }

  function _updatePerPage() {
    var perPageSelect = document.getElementById("perPageSelect"), x, xlen;
    if (!YAHOO.lang.isNull(perPageSelect)) {
      for (x = 0, xlen = perPageSelect.options.length; x < xlen; x += 1) {
        if (parseInt(
              this._parent.prefs.getPreference("perPage",
                                               this._parent.data.prefs_id),
              10
            ) === parseInt(perPageSelect.options[x].value, 10)) {
          perPageSelect.options[x].selected = true;
          break;
        }
      }
    }
    perPageSelect = null;
  }

  function _updatePerRow() {
    var perRowSelect = document.getElementById("perRowSelect"), x;
    if (!YAHOO.lang.isNull(perRowSelect)) {
      for (x = 0; x < perRowSelect.options.length; x += 1) {
        if (parseInt(
              this._parent.prefs.getPreference("perRow",
                                               this._parent.data.prefs_id),
              10
            ) === parseInt(perRowSelect.options[x].value, 10)) {
          perRowSelect.options[x].selected = true;
          break;
        }
      }
    }
    perRowSelect = null;
  }

  function _updateRow(row, dirtyColumns, allColumns, openTo) {
    var rowid = ['cmf_uid_', row.cmf_uid].join(''),
        x, xlen, rowele, i, colid, td, info;
    rowele = document.getElementById(rowid);
    if (rowele) {
      info = this._parent.data.getInfo(row, {isTree: this._isTree});
      for (i in dirtyColumns) {
        if (dirtyColumns.hasOwnProperty(i)) {
          colid = [rowid, '|||', i].join('');
          td = document.getElementById(colid);
          if (td) {
            YAHOO.util.Dom.batch(YAHOO.util.Dom.getChildren(td),
                                 recursivePurgeAndRemove);
            td.innerHTML = '';
            info.td = td;
            this._parent.displayCode[i](info);
            info.td = null;
            td = null;
          }
        }
      }
    }
    else {
      rowele = document.createElement('tr');
      rowele.id = rowid;
      info = this._parent.data.getInfo(row, {isTree: this._isTree});
      for (x = 0, xlen = allColumns.length; x < xlen; x += 1) {
        td = document.createElement('td');
        rowele.appendChild(td);
        td.id = [rowid, '|||', allColumns[x]].join("");
        info.td = td;
        this._parent.displayCode[allColumns[x]](info);
        info.td = null;
        td = null;
      }
    }
    info = null;
    doIEPNGFixImgFrom(rowele);
    return rowele;
  }

  function _recursiveOpenStateUpdate(items, myparent, isInsert, openTo) {
    var item, i, ilen;
    for (i = 0, ilen = items.length; i < ilen; i += 1) {
      item = document.getElementById(['cmf_uid_', items[i].cmf_uid].join(''));
      if (isInsert && !item) {
        this.addWasInserted(items[i].cmf_uid);
      }
      if (!isInsert && item) {
        this.addWasRemoved(items[i].cmf_uid, myparent);
      }
      if (items[i].subitems && items[i].subitems.length) {
        if (items[i].cmf_uid in openTo && isInsert) {
          this._recursiveOpenStateUpdate(items[i].subitems, items[i], true,
                                         openTo);
        }
        else {
          this._recursiveOpenStateUpdate(items[i].subitems, items[i], false,
                                         openTo);
        }
      }
    }
    item = null;
  }

  function _grabLastSubitem(items, openTo) {
    if (items[items.length - 1].subitems &&
        items[items.length - 1].subitems.length > 0 &&
        items[items.length - 1].cmf_uid in openTo) {
      return this._grabLastSubitem(items[items.length - 1].subitems, openTo);
    }
    else {
      return items[items.length - 1];
    }
  }

  function _sortLevel(item) {
    var itemEle = document.getElementById(['cmf_uid_', item.cmf_uid].join('')),
        moveEle, x, xlen;
    if (itemEle) {
      for (x = 0, xlen = item.subitems.length - 1; x <= xlen; xlen -= 1) {
        moveEle = document.getElementById(
          ['cmf_uid_', item.subitems[xlen].cmf_uid].join('')
        );
        if (moveEle) {
          itemEle.parentNode.insertBefore(moveEle, itemEle.nextSibling);
          this.addDirtyData(item.subitems[xlen].cmf_uid, ['title']);
          if (item.subitems[xlen].subitems &&
              item.subitems[xlen].subitems.length) {
            this._sortLevel(item.subitems[xlen]);
          }
        }
      }
    }
    itemEle = null;
    moveEle = null;
  }

  function _updateColumns(row, order, openTo) {
    var i, ilen, colid, td, x, xlen, info, temp = [],
        rowid = ['cmf_uid_', row.cmf_uid].join(''),
        tr = document.getElementById(rowid);
    if (tr) {
      info = this._parent.data.getInfo(row, {isTree: this._isTree});
      for (i = 0, ilen = order.length; i < ilen; i += 1) {
        colid = [rowid, '|||', order[i]].join('');
        td = document.getElementById(colid);
        if (!td) {
          td = document.createElement('td');
          td.id = colid;
          info.td = td;
          if (this._parent.displayCode[order[i]]) {
            this._parent.displayCode[order[i]](info);
          }
          info.td = null;
        }
        temp.push(td.cloneNode(true));
      }
      YAHOO.util.Dom.batch(YAHOO.util.Dom.getChildren(tr),
                           recursivePurgeAndRemove);
      for (i = 0, ilen = temp.length; i < ilen; i += 1) {
        tr.appendChild(temp[i]);
      }
      doIEPNGFixImgFrom(tr);
      temp = null;
      if (row.subitems && row.subitems.length) {
        for (x = 0, xlen = row.subitems.length; x < xlen; x += 1) {
          this._updateColumns(row.subitems[x], order, openTo);
        }
      }
    }
    tr = null;
    td = null;
    info = null;
  }

  function _refreshColumnHeaders(containing_element) {
    var i, ilen, header_list, thisHeader;
    if ($l.isUndefined(containing_element)) {
      containing_element = document.getElementById(
        "site_manager_thead"
      ).firstChild;
    }
    header_list = containing_element.getElementsByTagName('TH');
    for (i = 0, ilen = header_list.length; i < ilen; i += 1) {
      thisHeader = header_list[i];
      if (i % 2 === 1) {
        thisHeader.className = 'odd';
      } else {
        thisHeader.className = 'even';
      }
    }
    header_list = null;
    containing_element = null;
    thisHeader = null;
  }

  function _getPerPageSelect() {
    return document.getElementById(
      "perPageSelect"
    ).options[document.getElementById("perPageSelect").selectedIndex].value;
  }

  function _getPerRowSelect() {
    return document.getElementById(
      "perRowSelect"
    ).options[document.getElementById("perRowSelect").selectedIndex].value;
  }

  function _updateBatchDisplay() {
    var display_to_use = YAHOO.env.supports_inline_block ? "inline-block" :
                                                           "inline",
        getPref = this._parent.prefs.getPreference,
        colspan, results_length, batchStart, batchSize;
    if (this._batching.TD) {
      colspan = document.getElementById(
        this._batching.TD
      ).getAttributeNode("colspan");
      setNodeValue(colspan, this._getColumnsLength());

      results_length = this._parent.data.getListLength();
      batchStart = this._parent.data._batching.start;
      batchSize = this._parent.data._batching.perPageSelect *
                  this._parent.data._batching.perRowSelect;
      if (batchStart) {
        this._showPreviousLink();
      } else {
        this._hidePreviousLink();
      }
      document.getElementById(this._batching.Min).innerHTML = Math.min(
        batchStart + 1,
        results_length
      );

      if ((batchStart + batchSize) >= results_length) {
        this._hideNextLink();
        document.getElementById(this._batching.Max).innerHTML = results_length;
      } else {
        this._showNextLink();
        document.getElementById(this._batching.Max).innerHTML = (
          batchStart + batchSize
        );
      }

      document.getElementById(this._batching.Total).innerHTML = results_length;

      // TODO: Needs to be tested in IE6 to see if Yahoo is handling conversion
      // to block
      YAHOO.util.Dom.setStyle(this._batching.Container,
                              "display",
                              "table-footer-group");
      YAHOO.util.Dom.setStyle("perPage", "display", display_to_use);
      if (this._isGallery) {
        YAHOO.util.Dom.setStyle("perRow", "display", display_to_use);
      } else {
        YAHOO.util.Dom.setStyle("perRow", "display", "none");
      }
      this._parent.data._batching.perPageSelect = getPref(
        "perPage",
        this._parent.data.prefs_id
      );
      this._parent.data._batching.perRowSelect = getPref(
        "perRow",
        this._parent.data.prefs_id
      );
    }
  }

  function _resetBatchSize() {
    this._parent.data.resetBatchSize();
    this._updatePerPage();
    this._updatePerRow();
    this._updateBatchDisplay(true);
  }

  function _getColumnsLength() {
    if (this._isGallery) {
      return this._parent.prefs.getPreference("perRow",
                                              this._parent.data.prefs_id);
    } else {
      return this._parent.prefs.getPreference(
        "columns",
        this._parent.data.prefs_id
      ).length;
    }
  }

  function _isBlock(el) {
    return (YAHOO.util.Dom.getStyle(el, 'display') === 'block');
  }

  function _makeInline(el) {
    YAHOO.util.Dom.setStyle(el, 'display', 'inline');
  }

  function _clearControlButtons() {
    var i, current_button_data_len = this._controlButtons.length,
        divs_to_delete = ["filter", "perPage", "perRow"],
        divs_len = divs_to_delete.length, thisDiv,
        divContainer = document.getElementById("siteman_control_buttons__" +
                                               this._parent.data.prefs_id);
    for (i = 0; i < current_button_data_len; i += 1) {
      this._controlButtons[i].destroy();
    }

    for (i = 0; i < divs_len; i += 1) {
      thisDiv = document.getElementById(divs_to_delete[i]);
      if (thisDiv !== null) {
        divContainer.removeChild(thisDiv);
      }
    }
  }

  function _createControlButtons() {
    var button_data, thisButtonData, i,
        column_list = AZCAT.siteman.columns[isFCKEditorBrowse ?
                                            'FCKEditor' : 'site_manager'
                                           ][this._parent.data.prefs_id],
        new_button_span, new_button_data_len,
        divContainer = document.getElementById("siteman_control_buttons__" +
                                               this._parent.data.prefs_id),
        autoComplete, clear, content, contentDiv, filter,
        searchBy, span, type, searchByValue,
        display_to_use = YAHOO.env.supports_inline_block ? "inline-block" :
                                                           "inline",
        option, selectEl, selectValues, text, z, zLen,
        elsWithDivs = ['filter', 'perPage', 'perRow'],
        newButton,
        setStyle = YAHOO.util.Dom.setStyle, showPerRow, showPerPage,
        filterContainer, filterMenuItemClick, filterType, filterMenu,
        filterButtonCfg, filterButton, clearContainer, clearButton, that = this;

    this._clearControlButtons();

    /* Some pages, such as sitemap, do not allow the user to specify which
       columns and views to use. Therefore, we do not create those buttons */
    if (divContainer && !$l.isUndefined(column_list)) {
      button_data = [
        {label: 'Tree View',
         id:                 'refreshTreeLI',
         column_info_branch: 'Tree',
         fn :                this.treeViewClick,
         icon :              '/application_side_tree_list_view.png',
         selected:           this._isTree},
        {label: 'List View',
         id:                 'refreshListLI',
         column_info_branch: 'List',
         fn :                this.listViewClick,
         icon :              '/application_view_columns.png',
         selected:           this._isList},
        {label: 'Gallery View',
         id:                 'refreshGalleryLI',
         column_info_branch: 'Gallery',
         fn :                this.galleryViewClick,
         icon :              '/application_view_tile.png',
         selected:           this._isGallery}
      ];
      new_button_data_len = button_data.length;
      for (i = 0; i < new_button_data_len; i += 1) {
        thisButtonData = button_data[i];
        if (!$l.isUndefined(column_list[thisButtonData.column_info_branch])) {
          new_button_span = document.createElement('span');
          divContainer.appendChild(new_button_span);
          newButton = new YAHOO.widget.Button({
            id: thisButtonData.id,
            type: "button",
            label: thisButtonData.label,
            srcelement: new_button_span,
            onclick: {
              "fn"    : thisButtonData.fn,
              "scope" : this
            }
          });
          if (thisButtonData.selected) {
            newButton.addClass('default');
          }
          if (!$l.isUndefined(thisButtonData.icon)) {
            setStyle(newButton._button.parentNode, 'background',
                     ['url(', thisButtonData.icon,
                      ') no-repeat 4px 50%'].join(''));
            setStyle(newButton._button, 'paddingLeft', '24px');
          }
          this._controlButtons.push(newButton);
        }
      }
      new_button_span = document.createElement('span');
      divContainer.appendChild(new_button_span);
      newButton = new YAHOO.widget.Button({
        type: "button",
        id: "columnsButton",
        label: "Columns",
        srcelement: new_button_span,
        onclick: {
          "fn" : prefsClick,
          "obj": {prefs_id: this._parent.data.prefs_id}
        }
      });
      this._controlButtons.push(newButton);
      setStyle(newButton._button.parentNode, 'background',
               'url(/table_edit.png) no-repeat 4px 50%');
      setStyle(newButton._button, 'paddingLeft', '24px');
    }

    if (divContainer !== null) {
      showPerPage = this._isList || this._isGallery;
      contentDiv = document.createElement("DIV");
      divContainer.appendChild(contentDiv);
      contentDiv.id = "perPage";
      setStyle(contentDiv, "display", showPerPage ? display_to_use : "none");
      setStyle(contentDiv, "float", "none");
      content = document.createElement("div");
      contentDiv.appendChild(content);
      selectEl = document.createElement("select");
      content.appendChild(selectEl);
      selectEl.id = "perPageSelect";
      YAHOO.util.Event.on(selectEl, "change", this.perPageClick, this, true);
      selectValues = [5, 10, 15, 25, 50];
      for (z = 0, zLen = selectValues.length; z < zLen; z += 1) {
        option = new Option(selectValues[z], selectValues[z], false, false);
        selectEl.options[selectEl.length] = option;
      }
      text = document.createTextNode("Rows Per Page");
      content.appendChild(text);
      if (showPerPage) {
        this._updatePerPage();
      }

      showPerRow = this._isGallery;
      contentDiv = document.createElement("DIV");
      divContainer.appendChild(contentDiv);
      contentDiv.id = "perRow";
      setStyle(contentDiv, "display", showPerRow ? display_to_use : "none");
      setStyle(contentDiv, "float", "none");
      content = document.createElement("div");
      contentDiv.appendChild(content);
      selectEl = document.createElement("select");
      content.appendChild(selectEl);
      selectEl.id = "perRowSelect";
      YAHOO.util.Event.on(selectEl, "change", this.perRowClick, this, true);
      selectValues = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
      for (z = 0, zLen = selectValues.length; z < zLen; z += 1) {
        option = new Option(selectValues[z], selectValues[z], false, false);
        selectEl.options[selectEl.length] = option;
      }
      text = document.createTextNode("Items Per Row");
      content.appendChild(text);
      if (showPerRow) {
        this._updatePerRow();
      }

      contentDiv = document.createElement("DIV");
      divContainer.appendChild(contentDiv);
      setStyle(contentDiv, "display", display_to_use);
      contentDiv.id = "filter";
      content = document.createElement("div");
      contentDiv.appendChild(content);
      searchBy = document.createElement("input");
      type = document.createAttribute("type");
      setNodeValue(type, "text");
      searchBy.setAttributeNode(type);
      value = document.createAttribute("value");
      content.appendChild(searchBy);
      searchBy.id = "search_by";
      filterType = this._parent.prefs.getPreference("lastSearchedByType",
                                                    this._parent.data.prefs_id);
      if (this._isSearch) {
        searchByValue = this._parent.prefs.getPreference(
          "lastSearchedBy",
          this._parent.data.prefs_id
        );
        if (searchByValue) {
          searchByValue = JSON.parse(searchByValue);
          if (searchByValue.SearchableText) {
            searchBy.value = searchByValue.SearchableText;
          }
        }
      }
      filterContainer = document.createElement("SPAN");
      content.appendChild(filterContainer);
      function filterMenuItemClick(p_sType, p_aArgs, p_oItem) {
        var title, doClearFilter, searchBy;
        title = p_oItem.cfg.getProperty("text");
        doClearFilter = filterButton.get("label") !== title;
        filterButton.set("label", title);
        searchBy = document.getElementById("search_by");
        // Does not exist on the inital setup
        if (this._parent) {
          this._parent.prefs.setPreferences({"lastSearchedByType": (title === "Filter") ? "filter" : "powerFilter"},
                                             this._parent.data.prefs_id);
          this._parent.prefs.savePreferences();
        }
        if (doClearFilter) {
          this._clearFilterAndRefreshList();
        }
        if (title === "Power Filter") {
          // Does not exist on the inital setup
          if (this._doSearch) {
            this._doSearch(null, filterButton);
          }
          YAHOO.util.Dom.addClass(searchBy, "disabled");
          searchBy.value = "-disabled-";
          searchBy.disabled = true;
        } else {
          searchBy.disabled = false;
          searchBy.value = "";
          YAHOO.util.Dom.removeClass(searchBy, "disabled");
        }
      };
      filterButtonCfg = {"type"      : "push",
                         "label"     : (filterType === "filter") ? "Filter" : "Power Filter",
                         "id"        : "filterButton",
                         "name"      : "filterButton",
                         "container" : filterContainer}
      if (this._parent.data._allow_power_filter) {
        filterButtonCfg.menu = [{"text"    : "Filter",
                                 "value"   : "filter",
                                 "onclick" : {"fn"    : filterMenuItemClick,
                                              "scope" : that}},
                                {"text"    : "Power Filter",
                                 "value"   : "powerFilter",
                                 "onclick" : {"fn"    : filterMenuItemClick,
                                              "scope" : that}}];
        filterButtonCfg.type = "split";
      }
      filterButton = new YAHOO.widget.Button(filterButtonCfg);
      if (this._parent.data._allow_power_filter) {
        // filterButton.getMenu().getItems() returns undefined if the menu items are not yet created
        filterButton.getMenu().show();
        filterButton.getMenu().hide();
        filterMenuItemClick(null, null, filterButton.getMenu().getItems()[(filterType === "filter") ? 0 : 1]);
      }
      filterButton.on("click", this._doSearch, filterButton, that);
      clearContainer = document.createElement("SPAN");
      content.appendChild(clearContainer);
      clearButton = new YAHOO.widget.Button({"type"      : "push",
                                             "label"     : "Show All",
                                             "id"        : "showAll",
                                             "name"      : "showAll",
                                             "onclick"   : {"fn"    : this._clearFilterAndRefreshList,
                                                            "scope" : that},
                                             "container" : clearContainer});
      setStyle(clearContainer, "display", this._isSearch ? display_to_use : "none");
      autoComplete = document.createElement("div");
      content.appendChild(autoComplete);
      autoComplete.id = "search_by_auto_complete";
      createAutoComplete({"dataURL" : [this._parent.data.context_url,
                                       "/getAutoCompleteText"].join(""),
                          "dataStructure" : {resultsList: "ws",
                                             fields: ["w"]},
                          "searchFieldID" : "search_by",
                          "autoCompleteDivID" : "search_by_auto_complete",
                          "searchFunc" : {fn: this._doSearch,
                                          scope: that}});

      if (!YAHOO.env.supports_inline_block) {
        for (i = 0; i < elsWithDivs.length; i += 1) {
          YAHOO.util.Dom.getElementsBy(_isBlock, 'DIV',
                                       document.getElementById(elsWithDivs[i]),
                                       _makeInline);
        }
      }
    }
  }

  function __sortTitle(x, y) {
    if (x.title > y.title) {
      return 1;
    }
    else if (x.title < y.title) {
      return -1;
    }
    else {
      return 0;
    }
  }


  function _createActionsSidebar() {
    var allActions, allActionIds = [], thisAction, id, i, iLen, action_data,
        that = this;
    if (!this._suppress_sidebar && this._parent.sidebar) {
      this._parent.sidebar.removeAllActions(true);
      allActions = this._parent.data._getAllActions();
      for (id in allActions) {
        if ($hasOwnProperty(allActions, id)) {
          allActionIds.push({id: id, title: allActions[id].title});
        }
      }
      allActionIds.sort(__sortTitle);
      // this._parent.sidebar.render();
      for (i = 0, iLen = allActionIds.length; i < iLen; i += 1) {
        thisAction = allActions[allActionIds[i].id];
        action_data = {
          id: allActionIds[i].id,
          label: thisAction.title,
          icon: thisAction.icon,
          onclick: {
            fn: this._handleSidebarButtonClick,
            obj: allActionIds[i].id,
            scope: that
          }
        };
        this._parent.sidebar.addAction(action_data);
      }
      this._updateActiveSidebarActions();
      this._parent.sidebar.render();
    }
  }

  function _getSelectedCMFUids() {
    var i, thisItem, thisTD, thisCheckbox, checkedIds = [];
    for (i in this._parent.data._items) {
      if ($hasOwnProperty(this._parent.data._items, i)) {
        thisItem = this._parent.data._items[i];
        thisTD = document.getElementById(['cmf_uid_', thisItem.cmf_uid,
                                          '|||getMultiSelectCheckboxes'
                                          ].join(''));
        if (thisTD) {
          thisCheckbox = thisTD.getElementsByTagName('INPUT')[0];
          if (thisCheckbox && thisCheckbox.checked) {
            checkedIds.push(thisItem.cmf_uid);
          }
        }
      }
    }
    return checkedIds;
  }

  function _updateActiveSidebarActions() {
    var selected_cmf_uids = this._getSelectedCMFUids(), thisItemActions,
        action_list, i, iLen;
    if (selected_cmf_uids.length < 2) {
      if (selected_cmf_uids.length === 0) {
        thisItemActions = this._parent.data._root_actions;
      } else {
        thisItemActions = this._parent.data._items[
          selected_cmf_uids[0]
        ].actions;
      }
      action_list = [];
      for (i = 0, iLen = thisItemActions.length; i < iLen; i += 1) {
        action_list.push(thisItemActions[i].id);
      }
      this._setActiveSidebarButtons({responseText: JSON.stringify({
        actions: action_list
      })});
    } else {
      this._parent.data._getActionIdsByCmfUid(selected_cmf_uids,
                                              this._setActiveSidebarButtons,
                                              this);
    }
  }

  function _setActiveSidebarButtons(o) {
    var active_action_ids = JSON.parse(o.responseText),
        all_actions = this._parent.data._getAllActions(),
        thisActionId, thisActionEnabled, x, xLen,
        selected_cmf_uids = this._getSelectedCMFUids(),
        j, jLen = selected_cmf_uids.length, k, kLen,
        thisObjActions, thisObjHasPaste;
    if (active_action_ids && active_action_ids.actions) {
      active_action_ids = active_action_ids.actions;
      xLen = active_action_ids.length;
    }
    else {
      return;
    }
    if (!selected_cmf_uids.length) {
      selected_cmf_uids = [this._parent.data.root_cmf_uid];
      jLen = 1;
    }
    for (thisActionId in all_actions) {
      if ($hasOwnProperty(all_actions, thisActionId)) {
        thisActionEnabled = false;
        if (thisActionId === 'pastehere') {
          // Hard-coded HACK for Paste Here button
          thisActionEnabled = clipboard.items.length > 0 &&
                              selected_cmf_uids.length === 1;
          if (thisActionEnabled) {
            for (j = 0; j < jLen; j += 1) {
              thisObjActions =
                this._parent.data._items[selected_cmf_uids[j]].actions;
              thisObjHasPaste = false;
              for (k = 0, kLen = thisObjActions.length; k < kLen; k += 1) {
                if (thisObjActions[k].id === 'pastehere') {
                  thisObjHasPaste = true;
                  break;
                }
              }
              if (!thisObjHasPaste) {
                thisActionEnabled = false;
                break;
              }
            }
          }
        } else {
          for (x = 0; x < xLen; x += 1) {
            if (thisActionId === active_action_ids[x]) {
              thisActionEnabled = true;
              break;
            }
          }
        }
        if (thisActionEnabled) {
          this._parent.sidebar.enableAction(thisActionId);
        } else {
          this._parent.sidebar.disableAction(thisActionId);
        }
      }
    }
  }

  function _handleSidebarButtonClick(e, action_id) {
    var selected_cmf_uids = this._getSelectedCMFUids(), i, iLen, x, xLen,
        thisAction, this_action_onclick, effective_ids, effective_id,
        hrefs, item_to_use, item_actions, item_url, is_onclick_action;
    if (!selected_cmf_uids.length) {
      selected_cmf_uids = [this._parent.data.root_cmf_uid];
    }
    if (selected_cmf_uids.length !== 1 &&
        AZCAT.powerEdit.actionCode[action_id]) {
      AZCAT.powerEdit.dialog.init(action_id, selected_cmf_uids,
                                  {event_handlers: this.dialogEventHandlers,
                                   callback_scope: this});
    } else {
      effective_ids = [];
      hrefs = [];
      is_onclick_action = false;
      for (x = 0, xLen = selected_cmf_uids.length; x < xLen; x += 1) {
        item_to_use = this._parent.data._items[selected_cmf_uids[x]];
        if ($l.isUndefined(item_to_use) &&
            selected_cmf_uids[x] === this._parent.data.root_cmf_uid) {
          item_actions = this._parent.data._root_actions;
          item_url = this._parent.data.root_path + this._parent.data.root_id;
        } else {
          item_actions = item_to_use.actions;
          item_url = item_to_use.path + item_to_use.id;
        }
        for (i = 0, iLen = item_actions.length; i < iLen; i += 1) {
          thisAction = item_actions[i];
          if (thisAction.id === action_id) {
            YAHOO.util.Event.stopEvent(e);
            if (item_url === '/') {
              effective_id = '';
            } else {
              effective_id = item_url;
            }
            if (thisAction.onclick) {
              is_onclick_action = true;
              effective_ids.push(effective_id);
              this_action_onclick = AZCAT.dialog.actionCode[thisAction.id];
            } else if (thisAction.href.match(/^https?:\/\//)) {
              hrefs.push(thisAction.href);
            } else if (thisAction.href) {
              hrefs.push(portal_url + effective_id + thisAction.href);
            }
            break;
          }
        }
      }
      if (is_onclick_action) {
        this_action_onclick(e, {ids: effective_ids,
                                event_handlers: this.dialogEventHandlers,
                                callback_scope: this,
                                cmf_uids: selected_cmf_uids});
      } else {
        if (hrefs.length > 1) {
          AZCAT.utils.reportError([action_id,
                                   " requested on multiple objects (",
                                   selected_cmf_uids.join(", "),
                                   ").  Hrefs: \"",
                                   hrefs.join("\", \""), "\"."].join(""));
          alert(["You are not able to ", action_id,
                 " multiple items.  Please select only one and try",
                 " again."].join(""));
        } else {
          document.location.href = hrefs[0];
        }
      }
      // Prevent YUI default button handler:
      return false;
    }
  }

  /*
     -*********-
     |CopyPaste|
     -*********-
     + These are methods relating to the copy paste functionality.

  */


  /*
     -+++++++++++++-
     |pasteCallback|
     -+++++++++++++-
     + This is the callback function of pasteHere
  */

  function _pasteCallback(o) {
    AZCAT.nav.updateTabs();
    this._parent.data.updateFromServer(this.updateDisplay, this);
  }

  /*
     -+++++++++++++++++-
     |removePasteAction|
     -+++++++++++++++++-
     + This removes the 'Paste Here' action as the default action into
  */
  function _removePasteAction() {
    var list = this._parent.data.getList(),
        paste_here = "Paste Here",
        row, actions, i, ilen;
    for (i = 0, ilen = list.length; i < ilen; i += 1) {
      row = list[i];
      if (row.is_folderish) {
        actions = row.actions;
        if (actions[0].title === paste_here) {
          actions.shift();
          this._parent.data._updateItem(row.cmf_uid, {actions: actions});
        }
      }
    }
    this.updateDisplay();
  }

  /*
     -+++++++++++++++++-
     |insertPasteAction|
     -+++++++++++++++++-
     + This inserts the 'Paste Here' action as the default action into
  */
  function _insertCallback(o) {
    var list = this._parent.data.getList(), paste_here = "Paste Here", row,
        actions, myDialog, allowed = JSON.parse(o.responseText), i, ilen;
    if (allowed.length) {
      for (i = 0, ilen = list.length; i < ilen; i += 1) {
        row = list[i];
        if (row.is_folderish) {
          if (allowed.indexOf(parseInt(row.cmf_uid, 10)) !== -1) {
            actions = row.actions;
            if (actions[0].title !== paste_here) {
              actions.unshift({
                'id': 'pastehere',
                'icon': '/folder_page.png',
                'href': '',
                'onclick':
                  'javascript:AZCAT.siteman.dataView.pasteHere(event);',
                'title': paste_here
              });
              this._parent.data._updateItem(row.cmf_uid, {actions: actions});
            }
          }
        }
      }
      this.updateDisplay();
    }
    else {
      myDialog = new AZCAT.Dialog();
      myDialog.setHeader([myDialog.headerleft, "Cut / Copy",
                          myDialog.headerright].join(""));
      myDialog.setBody('The item or combination of items you have selected ' +
                       'do not have a valid place to be pasted.  Please ' +
                       'select a different item or combination of items.');
      myDialog.setFooter([myDialog.footerleft, myDialog.footerright].join(""));
      myDialog.render(document.body);
      myDialog.show();
    }
  }

  function _toggleItemSelection(origin, automate_checkbox) {
    var item_container, isUnselecting, isSelectCheckbox, theCheckbox;
    if (this._isGallery) {
      item_container = YAHOO.util.Dom.getAncestorByTagName(origin, 'TD');
    } else {
      item_container = YAHOO.util.Dom.getAncestorByTagName(origin, 'TR');
    }
    /* Unfortunately, origin.checked may or may not have been updated yet,
       depending on timing. Therefore, we have to rely on the class
       instead. */
    isUnselecting = YAHOO.util.Dom.hasClass(item_container, 'selected');
    if (isUnselecting) {
      YAHOO.util.Dom.removeClass(item_container, 'selected');
    } else {
      YAHOO.util.Dom.addClass(item_container, 'selected');
    }

    if (automate_checkbox) {
      isSelectCheckbox = function (el) {
        if (el.name === 'copy_pasta_checkbox') {
          return true;
        }
      };
      theCheckbox = YAHOO.util.Dom.getElementsBy(isSelectCheckbox,
                                                 null, item_container);
      if (theCheckbox.length) {
        theCheckbox = theCheckbox[0];
      } else {
        return;
      }
      theCheckbox.checked = !isUnselecting;
    }

    this._updateActiveSidebarActions();
  }

  function _displayClearButton() {
    var searchByEl = document.getElementById("search_by"),
        searchBy = searchByEl.value,
        showAll = document.getElementById("showAll");
    if (searchBy === "") {
      showAll.style.display = "none";
    } else {
      showAll.style.display = "inline";
    }
  }

  function _clearFilter() {
    var searchByEl = document.getElementById("search_by");
    setNodeValue(searchByEl, "");
    if (!this._searchedFromViewType) {
      this._searchedFromViewType = this.getViewType();
    }
    this.setViewType(this._searchedFromViewType);
    this._parent.prefs.setPreferences({"lastSearchedBy": ""},
                                       this._parent.data.prefs_id);
    this.setIsSearch(false);
    this._searchedFromViewType = "";
    this._displayClearButton();
  }

  function _clearFilterAndRefreshList() {
    this._clearFilter();
    this._parent.data.getBatchDataAndUpdateItemsFromServer(this._isSearch);
  }

  function _changeActiveTab(value) {
    if (!value) {
      value = true;
    }
    var refresh = document.getElementById(["refresh",
                                           this.getViewType(),
                                           "LI"].join(""));
    if (refresh.className !== "") {
      if (value) {
        if (refresh.className !== "on" &&
            refresh.className.indexOf(" on") === -1) {
          refresh.className = refresh.className + " on";
        }
      } else {
        if (refresh.className === "on") {
          refresh.className = "";
        } else if (refresh.className.indexOf(" on") === -1) {
          refresh.className = refresh.className.substring(
            0,
            refresh.className.indexOf(" on")
          );
        }
      }
    } else {
      if (value) {
        refresh.className = "on";
      }
    }
  }

  function _doSearch(e, filterButton) {
    var searchByEl, searchBy;
    if (filterButton && filterButton.get("label") === "Power Filter") {
      this._parent.data.getPowerFilterForm();
    } else {
      searchByEl = document.getElementById('search_by');
      searchBy = searchByEl.value;
      if (searchBy === "") {
        return;
      }

      if (this._searchedFromViewType === "") {
        this._searchedFromViewType = this.getViewType();
      }

      // Disable the current tab
      this._changeActiveTab(false);

      // Change the state to List for the search
      this.setViewType("List");
      this._parent.prefs.setPreferences({"lastSearchedBy":
                                         JSON.stringify({"SearchableText" : searchBy})},
                                         this._parent.data.prefs_id);

      // Enable the new tab
      this._changeActiveTab(true);

      this._parent.data.getSearchResultsFromServer(this.updateDisplay, this);
      this._displayClearButton();
    }
  }

  function _toggleSubItems(e) {
    YAHOO.util.Event.stopEvent(e);
    var img = YAHOO.util.Event.getTarget(e),
        tr = img.parentNode.parentNode,
        cmf_uid = tr.id.split('_'), openTo;
    cmf_uid = cmf_uid[cmf_uid.length - 1];
    openTo = this._parent.prefs.getPreference("openTo",
                                              this._parent.data.prefs_id);
    if (cmf_uid in openTo) {
      delete openTo[cmf_uid];
    }
    else {
      openTo[cmf_uid] = true;
    }
    this._parent.prefs.setPreferences({"openTo": openTo},
                                       this._parent.data.prefs_id);
    this.addDirtyData(cmf_uid, ['title']);
    this.updateDisplay();
  }

  function _processAddedItem(e, obj) {
    var parentObj, openTo;
    if (!obj.length) {
      return;
    }

    obj = obj[0];

    if (this._isTree) {
      parentObj = this._parent.data._getParent(obj.cmf_uid);
      openTo = this._parent.prefs.getPreference("openTo",
                                                this._parent.data.prefs_id);
      if (!parentObj || parentObj.cmf_uid in openTo) {
        this.addWasInserted(obj.cmf_uid);
      }
    } else {
      this.addWasInserted(obj.cmf_uid);
    }
  }

  // Shared public functions

  function setViewType(viewType, settingInitialView) {
    if ($l.isString(viewType)) {
      this._setViewType(viewType);
      if (!settingInitialView) {
        this._parent.prefs.setPreferences({"lastViewMethod": viewType},
                                          this._parent.data.prefs_id);
      }
      this._parent.data.resetBatchStart();
    }
  }

  function getViewType() {
    return this._viewType;
  }

  function isTree() {
    return this._isTree;
  }

  function isList() {
    return this._isList;
  }

  function isGallery() {
    return this._isGallery;
  }

  function isSearch() {
    return this._isSearch;
  }

  function setIsSearch(isSearch) {
    this._isSearch = isSearch;
  }

  function updateGallery() {
    var filling, listeners, items_for_update, list, table, tbody,
        tfoot, x, xlen, columns, div, i, ilen, info, myid, mytd, perRow, row,
        tr, startAt, oddeven;
    filling = document.getElementById('filling__' +
                                      this._parent.data.prefs_id);
    listeners = YAHOO.util.Event.getListeners(filling, "click");
    if (!listeners) {
      YAHOO.util.Event.addListener(filling, 'click', this.displayClick,
                                   this, true);
    }

    // Clear out old elements & create new ones
    YAHOO.util.Dom.batch(YAHOO.util.Dom.getChildren(filling),
                         recursivePurgeAndRemove);
    table = document.createElement('table');
    table.id = 'site_manager_table';
    table.className = 'main';
    tbody = document.createElement('tbody');
    tbody.id = 'site_manager_tbody';

    filling.appendChild(table);
    table.appendChild(tbody);

    tfoot = this._createBatchFooter();
    table.appendChild(tfoot);
    this._resetBatchSize();
    list = this._parent.data.getList();
    items_for_update = {};

    tr = document.createElement('tr');
    tr.style.display = 'none';
    tbody.appendChild(tr);
    columns = this._parent.prefs.getPreference("columns",
                                               this._parent.data.prefs_id);
    perRow = this._parent.prefs.getPreference("perRow",
                                              this._parent.data.prefs_id);
    for (i = 0, ilen = list.length; i < ilen; i += 1) {
      row = list[i];
      myid = ['cmf_uid_', row.cmf_uid].join("");
      mytd = document.createElement('td');
      tr.appendChild(mytd);
      mytd.id = myid;
      info = this._parent.data.getInfo(row, {isTree: this._isTree});
      for (x = 0, xlen = columns.length; x < xlen; x += 1) {
        div = document.createElement('div');
        mytd.appendChild(div);
        div.id = [myid, '|||', columns[x]].join("");
        info.td = div;
        this._parent.displayCode[columns[x]](info);
        info.td = null;
      }
      if ((i + 1) % perRow === 0) {
        tr = document.createElement('tr');
        tr.style.display = 'none';
        tbody.appendChild(tr);
      }
    }
    if (!tr.childNodes) {
      tbody.removeChild(tr);
    }

    startAt = tbody.firstChild;
    oddeven = true;
    while (startAt) {
      if (startAt.nodeType === 1) {
        startAt.className = oddeven ? "lightgrey" : "grey";
        startAt.style.display = "";
        doIEPNGFixImgFrom(startAt);
        oddeven = !oddeven;
      }
      startAt = startAt.nextSibling;
    }

    filling = null;
    tbody = null;
    table = null;
    tfoot = null;
    tr = null;
    mytd = null;
    div = null;


    // Clean out dirtydata, wasremoved and wasinserted.
    this._dirtyData = {};
    this._wasRemoved = {};
    this._wasInserted = [];

    waitStatus(false);
  }

  function createTreeOrList() {
    var div, filling, i, my_data, table, tbody, tfoot, thead, tr, th, x, xlen,
        listeners, items_for_update,
        columns = this._parent.prefs.getPreference("columns",
                                                   this._parent.data.prefs_id),
        listSort, startAt, oddeven;
    filling = document.getElementById('filling__' +
                                      this._parent.data.prefs_id);
    listeners = YAHOO.util.Event.getListeners(filling, "click");
    if (!listeners) {
      YAHOO.util.Event.addListener(filling, 'click', this.displayClick, this,
                                   true);
    }

    // Clear out old elements & create new ones
    table = document.createElement('table');
    table.id = 'site_manager_table';
    table.className = 'main';
    thead = document.createElement('thead');
    thead.id = 'site_manager_thead';
    tbody = document.createElement('tbody');
    tbody.id = 'site_manager_tbody';

    YAHOO.util.Dom.batch(YAHOO.util.Dom.getChildren(filling),
                         recursivePurgeAndRemove);

    filling.appendChild(table);
    table.appendChild(thead);
    table.appendChild(tbody);

    if (this._isList) {
      my_data = this._parent.data.getList();
      tfoot = this._createBatchFooter();
      table.appendChild(tfoot);
      this._resetBatchSize();
      items_for_update = {};
      for (x = 0, xlen = my_data.length; x < xlen; x += 1) {
        items_for_update[my_data[x].cmf_uid] = my_data[x].last_catalogued;
      }
    } else {
      my_data = this._parent.data.getTree();
    }

    // Make the header
    tr = document.createElement('tr');
    thead.appendChild(tr);
    for (x = 0, xlen = columns.length; x < xlen; x += 1) {
      th = document.createElement('th');
      tr.appendChild(th);
      th.id = columns[x];
      if (this._parent.columnInfo[columns[x]]) {
        div = this._parent.nodeTemplates.div_header();
        th.appendChild(div);
        div.appendChild(document.createTextNode(
          this._parent.columnInfo[columns[x]].column_header)
        );
        if (this._isList && this._parent.columnInfo[columns[x]].sortable) {
          i = this._parent.nodeTemplates.img_header();
          i.src = (this._parent.data._listSortOn === columns[x]) ?
                  (!this._parent.data._isListSortDescending ?
                   'bullet_arrow_down.png' :
                   'bullet_arrow_up.png') : 'bullet_white.png';
          div.appendChild(i);
        }
      }
    }
    doIEPNGFixImgFrom(tr);
    this._refreshColumnHeaders(tr);
    // Make the body
    //Recursivly draw the tree. 'Just Works'TM for list
    this._drawTree(my_data, tbody);
    listSort = new AZCAT.widgets.listSort("site_manager_thead",
                                          "site_manager_headers",
                                           "th", {"constrainY" : [0, 0],
                                                  "overriddenMove" : true});
    listSort.endDragEvent.subscribe(function (type, args) {
      var srcEl = args[0];
      this._parent.dataView.moveColumn(srcEl.id, srcEl.cellIndex, 1);
    }, this, true);
    listSort.onDragOverEvent.subscribe(function (type, args) {
      var srcEl = args[0],
          destEl = args[1],
          that = args[2],
          currSwitch = [srcEl.id, "_", destEl.id, "_",
                        that.forwardOnAxis].join("");
      if (that.lastDraggedOverEl !== currSwitch) {
        that.lastDraggedOverEl = currSwitch;
        this._parent.dataView.moveColumn(srcEl.id, destEl.cellIndex, 0, 0, 1);
      }
    }, this, true);
    startAt = tbody.firstChild;
    oddeven = true;
    while (startAt) {
      if (startAt.nodeType === 1) {
        startAt.className = oddeven ? "lightgrey" : "grey";
        startAt.style.display = "";
        oddeven = !oddeven;
      }
      startAt = startAt.nextSibling;
    }

    // Clean out dirtydata, wasremoved and wasinserted.
    this._dirtyData = {};
    this._wasRemoved = {};
    this._wasInserted = [];

    waitStatus(false);

    filling = null;
    table = null;
    thead = null;
    tbody = null;
    tfoot = null;
    tr = null;
    th = null;
    div = null;
    i = null;
  }

  function updateTreeOrList() {
    var aColspan, batching_td, c, clen, col, cols, div, i, ilen, img,
        insertBefore, insertedEle, insertedIndex, insertedItem, insertedParent,
        insertedParentEle, insertedSiblings, lastItem, my_data, order,
        removedEle, row, rowdata, s, siblings, slen, sort_order_parents,
        sortedItem, table, tbody, th, thead, tr, x, xlen, listSort,
        openTo = this._parent.prefs.getPreference("openTo",
                                                  this._parent.data.prefs_id),
        startAt, isSelectCheckbox, theCheckbox,
        oddeven = true;
    // Update whats marked dirty, insert new and delete old.
    // This will never happen for gallery view or batched list view.
    table = document.getElementById('site_manager_table');
    if (!table) {
      table = document.createElement('table');
      table.id = 'site_manager_table';
      table.className = 'main';
    }
    tbody = document.getElementById('site_manager_tbody');
    if (!tbody) {
      tbody = document.createElement('tbody');
      tbody.id = 'site_manager_tbody';
    }
    thead = document.getElementById('site_manager_thead');
    if (!thead) {
      thead = document.createElement('thead');
      thead.id = 'site_manager_thead';
    }

    if (this._isTree) {
      // Make sure all the correct tree nodes are open.
      this._recursiveOpenStateUpdate(this._parent.data.getTree(), null, true,
                                     openTo);
    }

    // Remove WasRemoved elements. Make siblings dirty for getTitleAndView to
    // dirty if in tree view.
    for (i in this._wasRemoved) {
      if ($hasOwnProperty(this._wasRemoved, i)) {
        removedEle = document.getElementById(['cmf_uid_', i].join(''));
        if (removedEle) {
          recursivePurgeAndRemove(removedEle);
          removedEle = null;
          if (this._wasRemoved[i] &&
              this._wasRemoved[i].cmf_uid !== undefined) {
            this.addDirtyData(this._wasRemoved[i].cmf_uid, ['title']);
            if (!this._wasRemoved[i].subitems ||
                this._wasRemoved[i].subitems.length === 0) {
              delete openTo[this._wasRemoved[i].cmf_uid];
            }
            if (this._isTree && this._wasRemoved[i].cmf_uid in openTo) {
              siblings = this._wasRemoved[i].subitems;
              for (s = 0, slen = siblings.length; s < slen; s += 1) {
                this.addDirtyData(siblings[s].cmf_uid, ['title']);
              }
            }
          }
        }
      }
    }

    // Insert WasInserted elements. Make siblings/parent dirty for
    // getTitleAndView to dirty if in tree view.
    for (i = 0, ilen = this._wasInserted.length; i < ilen; i += 1) {
      insertedItem = this._isList ?
                     this._parent.data.getData(this._wasInserted[i]) :
                     this._parent.data.getTreeNode(this._wasInserted[i]);
      insertedEle = this._updateRow(
        insertedItem,
        this._parent.prefs.getPreference("columns",
                                         this._parent.data.prefs_id),
        this._parent.prefs.getPreference("columns",
                                         this._parent.data.prefs_id),
        openTo
      );
      insertedParent = this._isList ?
                       null :
                       this._parent.data._getParent(this._wasInserted[i]);
      insertedSiblings = this._isList ?
                         this._parent.data.getList() :
                         insertedParent.subitems;
      /* find the ids of insertedItem's next sibling. */
      insertedIndex = -1;
      for (x = 0, xlen = insertedSiblings.length; x < xlen; x += 1) {
        if (insertedSiblings[x].cmf_uid === insertedItem.cmf_uid) {
          insertedIndex = x - 1;
        }
      }
      insertBefore = null;
      if (insertedSiblings[insertedIndex]) {
        lastItem =
          insertedSiblings[insertedIndex].cmf_uid in openTo &&
          insertedSiblings[insertedIndex].subitems &&
          insertedSiblings[insertedIndex].subitems.length &&
          this._grabLastSubitem(insertedSiblings[insertedIndex].subitems,
                                openTo) ||
          insertedSiblings[insertedIndex];
        insertBefore = document.getElementById(['cmf_uid_',
                                                lastItem.cmf_uid].join(''));
      }
      if (insertBefore) {
        if (insertBefore.nextSibling) {
          tbody.insertBefore(insertedEle, insertBefore.nextSibling);
        }
        else {
          tbody.appendChild(insertedEle);
        }
      }
      else {
        insertedParentEle = document.getElementById([
          'cmf_uid_',
          insertedParent.cmf_uid
        ].join(''));
        openTo[insertedParent.cmf_uid] = true;
        if (insertedParentEle.nextSibling) {
          tbody.insertBefore(insertedEle, insertedParentEle.nextSibling);
        }
        else {
          tbody.appendChild(insertedEle);
        }
      }
      if (this._isTree) {
        if (insertedParent.cmf_uid !== undefined) {
          this.addDirtyData(insertedParent.cmf_uid, ['title']);
        }
        for (s = 0, slen = insertedSiblings.length; s < slen; s += 1) {
          this.addDirtyData(insertedSiblings[s].cmf_uid, ['title']);
        }
      }
      insertedItem = null;
      insertedEle = null;
      insertedParentEle = null;
      insertBefore = null;
    }

    /* Don't care about updating items that got removed. */
    for (row in this._dirtyData) {
      if ($hasOwnProperty(this._dirtyData, row)) {
        if (!document.getElementById(['cmf_uid_', row].join(''))) {
          delete this._dirtyData[row];
        }
      }
    }
    // Loop through Dirty IDs and look for addition ids to dirty based on...
    // If columns that contain sort_order are dirty, deal with it D:
    sort_order_parents = [];
    for (row in this._dirtyData) {
      if ($hasOwnProperty(this._dirtyData, row)) {
        if (this._dirtyData[row].sort_order && row !== 0) {
          sortedItem = this._parent.data._getParent(parseInt(row, 10));
          if (sortedItem) {
            sort_order_parents.push(sortedItem);
          }
        }
      }
    }
    for (i = 0, ilen = sort_order_parents.length; i < ilen; i += 1) {
      if (i !== 0 &&
          sort_order_parents[i].path.indexOf(
            sort_order_parents[i - 1].path
          ) !== 0 ||
          i === 0) {
        this._sortLevel(sort_order_parents[i]);
      }
    }
    // Loop through Dirty IDs and update columns marked dirty. Else display a
    // clean version of the current view.
    for (row in this._dirtyData) {
      if ($hasOwnProperty(this._dirtyData, row)) {
        rowdata = this._isTree ?
                  this._parent.data.getTreeNode(parseInt(row, 10)) :
                  this._parent.data.getData(parseInt(row, 10));
        if (rowdata.cmf_uid !== undefined) {
          cols = {};
          for (col in this._dirtyData[row]) {
            if ($hasOwnProperty(this._dirtyData[row], col)) {
              if (this._parent.dataToColumns[col]) {
                for (c = 0, clen = this._parent.dataToColumns[col].length;
                     c < clen; c += 1) {
                  cols[this._parent.dataToColumns[col][c]] = true;
                }
              }
            }
          }
          this._updateRow(
            rowdata, cols,
            this._parent.prefs.getPreference("columns",
                                             this._parent.data.prefs_id),
            openTo
          );
        }
      }
    }
    // If the columns changed, reorder, delete and add columns as necessary
    if (this._columnsDirty) {
      order = this._parent.prefs.getPreference('columns',
                                               this._parent.data.prefs_id);

      //Add/Delete/Sort Headers
      thead = document.getElementById('site_manager_thead');
      tr = document.createElement('tr');
      thead.appendChild(tr);
      for (i = 0, ilen = order.length; i < ilen; i += 1) {
        th = document.getElementById(order[i]);
        if (!th) {
          th = document.createElement('th');
          tr.appendChild(th);
          div = this._parent.nodeTemplates.div_header();
          th.appendChild(div);
          th.id = order[i];
          if (this._parent.columnInfo[order[i]] &&
              this._parent.columnInfo[order[i]].column_header) {
            div.appendChild(
              document.createTextNode(
                this._parent.columnInfo[order[i]].column_header
              )
            );
            if (this._isList && this._parent.columnInfo[order[i]].sortable) {
              img = this._parent.nodeTemplates.img_header();
              img.src = (this._parent.data._listSortOn === order[i]) ?
                        (!this._parent.data._isListSortDescending ?
                         'bullet_arrow_down.png' :
                         'bullet_arrow_up.png') :
                        'bullet_white.png';
              div.appendChild(img);
              img = null;
            }
          }
        }
        else {
          tr.appendChild(th);
        }
      }
      this._refreshColumnHeaders(tr);
      tr = null;
      th = null;
      div = null;
      recursivePurgeAndRemove(thead.firstChild);

      //Add/Delete/Sort Columns
      if (this._isList) {
        my_data = this._parent.data.getList();
      } else {
        my_data = this._parent.data.getTree();
      }
      for (x = 0, xlen = my_data.length; x < xlen; x += 1) {
        this._updateColumns(my_data[x], order, openTo);
      }

      // Update the batch footer colspan
      if (this._isList) {
        batching_td = document.getElementById('batching_td');
        aColspan = batching_td.attributes.getNamedItem('colspan');
        aColspan.value = order.length;
        batching_td = null;
      }

      listSort = new AZCAT.widgets.listSort("site_manager_thead",
                                            "site_manager_headers",
                                            "th",
                                            {"constrainY" : [0, 0],
                                             "overriddenMove" : true});
      listSort.endDragEvent.subscribe(function (type, args) {
        var srcEl = args[0],
            that = args[2];
        this._parent.dataView.moveColumn(srcEl.id,
                                         that.forwardOnAxis ?
                                         srcEl.cellIndex :
                                         srcEl.cellIndex + 1, 1);
      }, this, true);
      listSort.onDragOverEvent.subscribe(function (type, args) {
        var srcEl = args[0],
            destEl = args[1],
            that = args[2],
            currSwitch = [srcEl.id, "_", destEl.id].join("");
        if (that.lastDraggedOverEl !== currSwitch) {
          that.lastDraggedOverEl = currSwitch;
          this._parent.dataView.moveColumn(srcEl.id, destEl.cellIndex, 0, 0,
                                           1);
        }
      }, this, true);
      this.setColumnsDirty(false);
    }
    table = null;
    thead = null;

    startAt = tbody.firstChild;

    isSelectCheckbox = function (el) {
      if (el.name === 'copy_pasta_checkbox') {
        return true;
      }
    };
    while (startAt) {
      if (startAt.nodeType === 1) {
        startAt.className = oddeven ? "lightgrey" : "grey";
        theCheckbox = YAHOO.util.Dom.getElementsBy(isSelectCheckbox,
                                                   null, startAt);
        if (theCheckbox.length && theCheckbox[0].checked) {
          YAHOO.util.Dom.addClass(startAt, 'selected');
        }
        startAt.style.display = "";
        oddeven = !oddeven;
      }
      startAt = startAt.nextSibling;
    }
    this._parent.prefs.setPreferences({"openTo": openTo},
                                      this._parent.data.prefs_id);

    // Clean out dirtydata, wasremoved and wasinserted.
    this._dirtyData = {};
    this._wasRemoved = {};
    this._wasInserted = [];

    waitStatus(false);

    tbody = null;
  }

  function updateDisplay(allDirty) {
    if (this._isGallery) {
      this.updateGallery();
      this._createControlButtons();
    }
    else if (allDirty) { // We want a full redraw.
      this._createControlButtons();
      this.createTreeOrList();
    }
    else {
      this.updateTreeOrList();
    }

    this._createActionsSidebar();

    this._parent.prefs.savePreferences();
  }

  function addDirtyData(id, dirt) {
    if ($l.isString(id) && id.indexOf('cmf_uid_') === 0) {
      id = id.split('_');
      id = id[id.length - 1];
    }
    if ($l.isUndefined(this._dirtyData[id])) {
      this._dirtyData[id] = {};
    }
    for (var i = 0, ilen = dirt.length; i < ilen; i += 1) {
      this._dirtyData[id][dirt[i]] = true;
    }
  }

  function addWasRemoved(id, dirt) {
    this._wasRemoved[id] = dirt;
  }

  function addWasInserted(id) {
    this._wasInserted.push(id);
  }

  function resetBatchStart() {
    var el = document.getElementById("perPage");
    if (this._isTree && el) {
      YAHOO.util.Dom.setStyle(el, "display", "none");
    }
    el = null;
  }

  function treeViewClick() {
    AZCAT.nav.updateTabs();
    this._clearFilter();
    this.setViewType('Tree');
    this._parent.data.updateFromServer(this.updateDisplay, this, true);
  }

  function listViewClick() {
    var getPref = this._parent.prefs.getPreference,
        prefs_id = this._parent.data.prefs_id;
    AZCAT.nav.updateTabs();
    this._clearFilter();
    this.setViewType('List');
    this._parent.data._batching.perPageSelect = getPref('perPage', prefs_id);
    this._parent.data._batching.perRowSelect = getPref('perRow', prefs_id);
    this._parent.data.sortList(getPref('lastSortedOn', prefs_id),
                               getPref('lastSortedOrder', prefs_id));
    this._parent.data.getBatchDataAndUpdateItemsFromServer(this.isSearch());
  }

  function galleryViewClick() {
    var getPref = this._parent.prefs.getPreference,
        prefs_id = this._parent.data.prefs_id;
    AZCAT.nav.updateTabs();
    this._clearFilter();
    this.setViewType('Gallery');
    this._parent.data._batching.perPageSelect = getPref('perPage', prefs_id);
    this._parent.data._batching.perRowSelect = getPref('perRow', prefs_id);
    this._parent.data.sortList(getPref('lastSortedOn', prefs_id),
                               getPref('lastSortedOrder', prefs_id));
    this._parent.data.getBatchDataAndUpdateItemsFromServer(this.isSearch());
  }

  function batchPreviousClick(e) {
    YAHOO.util.Event.stopEvent(e);
    this._parent.data.batchPrevious();
    this._parent.data.getBatchDataAndUpdateItemsFromServer(this.isSearch());
  }

  function batchNextClick(e) {
    YAHOO.util.Event.stopEvent(e);
    this._parent.data.batchNext();
    this._parent.data.getBatchDataAndUpdateItemsFromServer(this.isSearch());
  }

  function perPageClick() {
    var perPage = this._getPerPageSelect();
    if (perPage && parseInt(perPage, 10)) {
      perPage = parseInt(perPage, 10);
      this._parent.prefs.setPreferences({"perPage" : perPage},
                                        this._parent.data.prefs_id);
      this._parent.data._batching.perPageSelect = perPage;
      this._parent.data.resetBatchStart();
      this._parent.data.getBatchDataAndUpdateItemsFromServer(this.isSearch());
    }
  }

  function perRowClick() {
    var perRow = parseInt(this._isGallery ? this._getPerRowSelect() : 1, 10);
    if (perRow) {
      this._parent.prefs.setPreferences({"perRow" : perRow},
                                        this._parent.data.prefs_id);
      this._parent.data._batching.perRowSelect = perRow;
      this._parent.data.resetBatchStart();
      this._parent.data.getBatchDataAndUpdateItemsFromServer(this.isSearch());
    }
  }

  function addColumn(colName, newPos, preserve_header, preserve_body,
                     preserve_preference) {
    // TODO: Write function to add a column. His currently just refreshes from
    // the server. Until this change is made, this method won't work properly
    // if preserve_preferences is set
    var oldPrefs, mycolumns;
    this._parent.data._invalidateDataLackingColumns([colName]);
    if (!preserve_preference) {
      oldPrefs = this._parent.prefs.getPreference("columns",
                                                  this._parent.data.prefs_id);
      mycolumns = oldPrefs.slice(0, newPos);
      mycolumns = mycolumns.concat([colName], oldPrefs.slice(newPos,
                                                             oldPrefs.length));
      this._parent.prefs.setPreferences({"columns": mycolumns},
                                        this._parent.data.prefs_id);
      this.setColumnsDirty(true);
    }

    this._parent.data.getBatchDataAndUpdateItemsFromServer(this.isSearch());
  }

  function deleteColumn(colPos, preserve_header, preserve_body,
                        preserve_preference) {
    var table_header, row_list, table_body, mycolumns, i, ilen;
    if (!preserve_header) {
      table_header = document.getElementById('site_manager_thead');
      row_list = table_header.getElementsByTagName('TR');
      for (i = 0, ilen = row_list.length; i < ilen; i += 1) {
        row_list[i].deleteCell(colPos);
      }
      this._refreshColumnHeaders(table_header);
    }

    if (!preserve_body) {
      table_body = document.getElementById('site_manager_tbody');
      row_list = table_body.getElementsByTagName('TR');
      for (i = 0, ilen = row_list.length; i < ilen; i += 1) {
        row_list[i].deleteCell(colPos);
      }
    }

    if (!preserve_preference) {
      mycolumns = this._parent.prefs.getPreference("columns",
                                                   this._parent.data.prefs_id);
      mycolumns.splice(colPos, 1);
      this._parent.prefs.setPreferences({"columns": mycolumns},
                                        this._parent.data.prefs_id);
    }
    this.setColumnsDirty(true);
    table_header = null;
    table_body = null;
    row_list = null;
  }

  function moveColumn(colName, newPos, preserve_header, preserve_body,
                      preserve_preference) {
    var table_header, row_list, table_body, mycolumns, thisRow, i, ilen,
        movedCell, oldIndex, oldPrefs, curPos;
    if (!preserve_header) {
      table_header = document.getElementById('site_manager_thead');

      row_list = table_header.getElementsByTagName('TR');
      for (i = 0, ilen = row_list.length; i < ilen; i += 1) {
        thisRow = row_list[i];
        movedCell = document.getElementById(colName);
        oldIndex = movedCell.cellIndex;
        if (newPos < thisRow.childNodes.length - 1) {
          thisRow.insertBefore(movedCell, thisRow.cells[newPos]);
        } else {
          thisRow.appendChild(movedCell);
        }
      }
      this._refreshColumnHeaders(table_header);
    }
    if (!preserve_body) {
      table_body = document.getElementById('site_manager_tbody');
      row_list = table_body.getElementsByTagName('TR');
      for (i = 0, ilen = row_list.length; i < ilen; i += 1) {
        thisRow = row_list[i];
        movedCell = document.getElementById([thisRow.id, '|||',
                                             colName].join(""));
        oldIndex = movedCell.cellIndex;
        if (newPos < thisRow.childNodes.length - 1) {
          thisRow.insertBefore(movedCell, thisRow.cells[newPos]);
        } else {
          thisRow.appendChild(movedCell);
        }
      }
    }

    if (!preserve_preference) {
      oldPrefs = this._parent.prefs.getPreference("columns",
                                                  this._parent.data.prefs_id);
      // Some sanity checking done here in case the column ends up in the array
      // twice
      curPos = oldPrefs.indexOf(colName);
      while (curPos !== -1) {
        oldPrefs.splice(curPos, 1);
        curPos = oldPrefs.indexOf(colName);
      }
      mycolumns = oldPrefs.slice(0, newPos);
      mycolumns = mycolumns.concat([colName], oldPrefs.slice(newPos,
                                                             oldPrefs.length));
      this._parent.prefs.setPreferences({"columns": mycolumns},
                                        this._parent.data.prefs_id);
      this._parent.prefs.savePreferences();
    }
    this.setColumnsDirty(true);
    table_header = null;
    table_body = null;
    row_list = null;
    movedCell = null;
  }

  dialogEventHandlers = {
    onDeleteConfirm : function (e) {
      this._parent.data.getBatchDataAndUpdateItemsFromServer(this.isSearch());
      waitStatus(false);
    },
    onRenameConfirm : function (e, renameData) {
      var items_for_update = {},
          my_data,
          x, xlen;
      my_data = this._parent.data.getList();
      for (x = 0, xlen = my_data.length; x < xlen; x += 1) {
        items_for_update[my_data[x].cmf_uid] = my_data[x].last_catalogued;
      }
      this._parent.data.updateItemsFromServer(this.updateDisplay, this,
                                              items_for_update);
      waitStatus(false);
    },
    onSortConfirm : function (e, sortData) {
      this._parent.data.updateFromServer(this.updateDisplay, this);
      waitStatus(false);
    },
    onTransitionConfirm : function (e, transitionData) {
      this._parent.data.updateItems([], transitionData[0], []);
      this.updateDisplay();
    }
  };

  function displayClick(e) {
    var origin = YAHOO.util.Event.getTarget(e),
        td, column, firstAction, row, row_name, effective_id,
        first_action_onclick;
    // find out what column we are
    switch (origin.nodeName.toLowerCase()) {
    case 'img':
      td = origin;
      while (td.nodeName.toLowerCase() !== 'td' &&
             td.nodeName.toLowerCase() !== 'th' &&
             td.nodeName.toLowerCase() !== 'div' &&
             td.parentNode ||
             td.nodeName.toLowerCase() === 'div' &&
             td.id && td.id.search('|||') === -1 &&
             td.parentNode ||
             td.nodeName.toLowerCase() === 'div' &&
             !td.id && td.parentNode) {
        td = td.parentNode;
      }
      if (td.nodeName.toLowerCase() === 'th') {
        this._parent.data.doSort(e);
      }
      else {
        column = td.id.split('|||')[1];
        // dispatch event to handler who deals with the event.
        switch (column) {
        case 'getTitleAndView':
        case 'getTitleAndViewSitemap':
        case 'getTitleAndEdit':
          if (origin.className.indexOf('clickme') !== -1) {
            this._toggleSubItems(e);
          } else if (origin.className === 'view_link_image') {
            if (this._parent.data._click_action === 'shadowbox' && Shadowbox) {
              YAHOO.util.Event.stopEvent(e);
              Shadowbox.open(
                YAHOO.util.Dom.getAncestorByTagName(
                  YAHOO.util.Event.getTarget(e),
                  'a'
                )
              );
            } else if (this._parent.data._click_action === 'file_properties') {
              YAHOO.util.Event.stopEvent(e);
              doFileProperties(e);
            }
          } else {
            this._toggleItemSelection(origin, true);
          }
          break;
        case 'getActions':
          row_name = td.id.split('|||')[0];
          row = this._parent.data.getData(row_name);
          firstAction = row.actions[0];
          if (firstAction.onclick) {
            YAHOO.util.Event.stopEvent(e);
            first_action_onclick = AZCAT.dialog.actionCode[firstAction.id];
            effective_id = row.path + row.id;
            if (effective_id === '/') {
              effective_id = '';
            }
            first_action_onclick(e, {
              ids: [effective_id],
              event_handlers: this.dialogEventHandlers,
              callback_scope: this
            });
          }
          break;
        case 'getThumbnail':
          if (isFCKEditorBrowse) {
            browseSelect(e);
          } else if (this._parent.data._click_action === 'shadowbox' &&
                     Shadowbox) {
            YAHOO.util.Event.stopEvent(e);
            Shadowbox.open(
              YAHOO.util.Dom.getAncestorByTagName(
                YAHOO.util.Event.getTarget(e),
                'a'
              )
            );
          } else if (this._parent.data._click_action === 'file_properties') {
            YAHOO.util.Event.stopEvent(e);
            doFileProperties(e);
          }
          break;
        default:
          this._toggleItemSelection(origin, true);
          break;
        }
      }
      td = null;
      break;
    case 'input':
      if (origin.name === 'copy_pasta_checkbox') {
        this._toggleItemSelection(origin, false);
      } else {
        this._toggleItemSelection(origin, true);
      }
      break;
    case 'a':
      td = origin;
      while (td.nodeName.toLowerCase() !== 'td' &&
             td.nodeName.toLowerCase() !== 'div' &&
             td.parentNode ||
             td.nodeName.toLowerCase() === 'div' &&
             td.id && td.id.search('|||') === -1 &&
             td.parentNode ||
             td.nodeName.toLowerCase() === 'div' &&
             !td.id &&
             td.parentNode) {
        td = td.parentNode;
      }
      column = td.id.split('|||')[1];
      switch (column) {
      case 'getActions':
        row_name = td.id.split('|||')[0];
        row = this._parent.data.getData(row_name);
        firstAction = row.actions[0];
        if (firstAction.onclick) {
          YAHOO.util.Event.stopEvent(e);
          first_action_onclick = AZCAT.dialog.actionCode[firstAction.id];
          effective_id = row.path + row.id;
          if (effective_id === '/') {
            effective_id = '';
          }
          first_action_onclick(e, {
            ids: [effective_id],
            event_handlers: this.dialogEventHandlers,
            callback_scope: this
          });
        }
        break;
      case 'getThumbnail':
        if (isFCKEditorBrowse) {
          browseSelect(e);
        } else {
          this._toggleItemSelection(origin, true);
        }
        break;
      case 'getTitleAndView':
        if (isFCKEditorBrowse) {
          browseSelect(e);
        } else if (this._parent.data._click_action === 'shadowbox' &&
                   Shadowbox) {
          YAHOO.util.Event.stopEvent(e);
          Shadowbox.open(YAHOO.util.Event.getTarget(e));
        }
        else if (this._parent.data._click_action === 'file_properties') {
          YAHOO.util.Event.stopEvent(e);
          doFileProperties(e);
        }
        break;
      default:
        break;
      }
      td = null;
      break;
    case 'div':
      // Currently, only clicking the blue area gets you here.
      break;
    default:
      this._toggleItemSelection(origin, true);
      break;
    }
    origin = null;
  }

  function getCMFUIDfromPath(path) {
    var item, items = this._parent.data._items;
    for (item in items) {
      if (items.hasOwnProperty(item)) {
        if (items[item].path + items[item].id === path) {
          return items[item].cmf_uid;
        }
      }
    }
  }

  /*
     -+++++++++-
     |pasteHere|
     -+++++++++-
     + This inserts the 'Paste Here' action as the default action into
  */

  function pasteHere(e, dialogParams) {
    YAHOO.util.Event.stopEvent(e);
    var qstr = "",
        name = "id:list=",
        thisObj, that = this, x, ID;
    for (x = 0; x < clipboard.items.length; x += 1) {
      thisObj = this._parent.data.getData(clipboard.items[x]);
      qstr = [qstr, name, thisObj.path, thisObj.id, "&"].join("");
    }
    qstr = [qstr, "action=", clipboard.action].join("");

    ID = dialogParams.ids[0];
    YAHOO.util.Connect.asyncRequest('POST',
                                    [portal_url, ID, '/doPaste'].join(""),
                                    {scope: that,
                                     success: this._pasteCallback,
                                     failure: AZCAT.utils.connFail},
                                    qstr);

    clipboard.items = '';
    clipboard.action = '';
    this._removePasteAction();
  }

  /*
     -++++++++-
     |cutItems|
     -++++++++-
     + This method will store the selected items into the cut id list
     and enable the paste into here methods.
  */
  function cutItems() {
    clipboard.items = this._getSelectedCMFUids();
    clipboard.action = 'cut';
    this.insertPasteAction();
  }

  /*
     -+++++++++-
     |copyItems|
     -+++++++++-
     + This method will store the selected items into the copy id list
     and enable the paste into here methods.
  */
  function copyItems() {
    clipboard.items = this._getSelectedCMFUids();
    clipboard.action = 'copy';
    this.insertPasteAction();
  }

  function insertPasteAction() {
    var qstr = ['cmf_uids=', JSON.stringify(clipboard.items), '&action=',
                clipboard.action].join(''),
        that = this;
    YAHOO.util.Connect.asyncRequest('POST',
                                    [portal_url,
                                     '/getAllowedPasteFolders'].join(""),
                                    {scope: that,
                                     success: this._insertCallback,
                                     failure: AZCAT.utils.connFail},
                                    qstr);
  }

  function setColumnsDirty(isDirty) {
    this._columnsDirty = isDirty;
  }

  function destroy() {
    var filling_div = document.getElementById('filling__' +
                                              this._parent.data.prefs_id);
    YAHOO.util.Event.removeListener(window, "beforeunload", this.destroy);
    this._clearControlButtons();

    this._parent.data.itemAdded.unsubscribe(this._processAddedItem, this);

    if (filling_div) {
      YAHOO.util.Event.purgeElement(filling_div);
      YAHOO.util.Dom.batch(YAHOO.util.Dom.getChildren(filling_div),
                           recursivePurgeAndRemove);
    }

    if (!this._suppress_sidebar && this._parent.sidebar) {
      this._parent.sidebar.destroy();
    }
  }

  return function (parent, suppress_sidebar) {
    // My resources, this instance
    // Private varables, actual

    var filling, that = {//Private varables, by convention not actually hidden
      _parent : parent,
      _dirtyData : {},
      _wasRemoved : {},
      _wasInserted : [],
      _viewType : '',
      _isTree : false,
      _isList : false,
      _isGallery : false,
      _isSearch : false,
      _batching : {"Container"                : null,
                    "TD"                       : null,
                    "Min"                      : null,
                    "Max"                      : null,
                    "Total"                    : null,
                    "PreviousSpan"             : null,
                    "PreviousA"                : null,
                    "NextSpan"                 : null,
                    "NextA"                    : null,
                    "perPage"                  : null,
                    "perPageSelect"            : null,
                    "perRow"                   : null,
                    "perRowSelect"             : null},
      _controlButtons : [],
      _rootActionButtons : [],
      _supress_sidebar : suppress_sidebar,
      _searchedFromViewType : "",
      _columnsDirty : true,
      //Private Methods
      _setViewType : _setViewType,
      _drawTree : _drawTree,
      _createBatchFooter : _createBatchFooter,
      _showPreviousLink : _showPreviousLink,
      _hidePreviousLink : _hidePreviousLink,
      _showNextLink : _showNextLink,
      _hideNextLink : _hideNextLink,
      _updatePerPage : _updatePerPage,
      _updatePerRow : _updatePerRow,
      _updateRow : _updateRow,
      _recursiveOpenStateUpdate : _recursiveOpenStateUpdate,
      _grabLastSubitem : _grabLastSubitem,
      _sortLevel : _sortLevel,
      _updateColumns : _updateColumns,
      _refreshColumnHeaders : _refreshColumnHeaders,
      _getPerPageSelect : _getPerPageSelect,
      _getPerRowSelect : _getPerRowSelect,
      _updateBatchDisplay : _updateBatchDisplay,
      _resetBatchSize : _resetBatchSize,
      _getColumnsLength : _getColumnsLength,
      _createControlButtons : _createControlButtons,
      _clearControlButtons : _clearControlButtons,
      _createActionsSidebar : _createActionsSidebar,
      _getSelectedCMFUids : _getSelectedCMFUids,
      _updateActiveSidebarActions : _updateActiveSidebarActions,
      _setActiveSidebarButtons : _setActiveSidebarButtons,
      _handleSidebarButtonClick : _handleSidebarButtonClick,
      _pasteCallback : _pasteCallback,
      _removePasteAction : _removePasteAction,
      _insertCallback : _insertCallback,
      _toggleItemSelection : _toggleItemSelection,
      _displayClearButton : _displayClearButton,
      _clearFilter : _clearFilter,
      _clearFilterAndRefreshList : _clearFilterAndRefreshList,
      _changeActiveTab : _changeActiveTab,
      _doSearch : _doSearch,
      _toggleSubItems : _toggleSubItems,
      _processAddedItem : _processAddedItem,

      // Public methods
      setViewType : setViewType,
      getViewType : getViewType,
      isTree : isTree,
      isList : isList,
      isGallery : isGallery,
      isSearch : isSearch,
      setIsSearch : setIsSearch,
      updateGallery : updateGallery,
      createTreeOrList : createTreeOrList,
      updateTreeOrList : updateTreeOrList,
      updateDisplay : updateDisplay,
      addDirtyData : addDirtyData,
      addWasRemoved : addWasRemoved,
      addWasInserted : addWasInserted,
      resetBatchStart : resetBatchStart,
      treeViewClick : treeViewClick,
      listViewClick : listViewClick,
      galleryViewClick : galleryViewClick,
      batchPreviousClick : batchPreviousClick,
      batchNextClick : batchNextClick,
      perPageClick : perPageClick,
      perRowClick : perRowClick,
      addColumn : addColumn,
      deleteColumn : deleteColumn,
      moveColumn : moveColumn,
      dialogEventHandlers : dialogEventHandlers,
      displayClick : displayClick,
      getCMFUIDfromPath : getCMFUIDfromPath,
      pasteHere : pasteHere,
      cutItems : cutItems,
      copyItems : copyItems,
      insertPasteAction : insertPasteAction,
      setColumnsDirty : setColumnsDirty,
      destroy : destroy
    };

    if (!suppress_sidebar &&
        document.getElementById('sidebar_actions_container')) {
      filling = document.getElementById('filling__' + parent.data.prefs_id);

      parent.registerEls({
        top_align: filling,
        stretched: YAHOO.util.Dom.getAncestorByClassName(filling.parentNode,
                                                         'yui-content')
      });
    }

    parent.data.itemAdded.subscribe(_processAddedItem, that, true);

    YAHOO.util.Event.on(window, "beforeunload", destroy, that, true);

    return that;
  };
}();

AZCAT.register("data", AZCAT.siteman.data, {version: "2.0.0", build: "???"});
AZCAT.register("dataView", AZCAT.siteman.dataView, {version: "2.0.0",
                                                    build: "???"});
