add/update/delete requests debug testing

/*=================================================================================================
 domready
 =================================================================================================*/
window.addEvent('load', function() {
     var setup = {
          url: "localhost:9000",
          get: [
               "/json/logicalactions"
               //"/json/xtypes",
               //"/json/xobjects"
          ]
     };
     new simGui(setup);
});
/*=================================================================================================
 mainlayer
 =================================================================================================*/
var simGui = new Class({
     initialize: function(guisetup) {
          this._setup = guisetup;
          this._panels = {};
          this._render();
          this._events();
          this._init();
     },
     _init: function() {
          //@todo render buttons instead
          for(var a=0;a<this.setup.get.length;a++){               
                this._panels[this.setup.get[a]] = new simPanel(this.setup.get[a], 0);
          }         
     },
     _render: function() {
          this._gui = document.body;
          this._guiHead = render(this._gui, 'div', 'gui_head', 'gui_head');
          this._guiBody = render(this._gui, 'div', 'gui_body', 'gui_body');
          this._guiFoot = render(this._gui, 'div', 'gui_foot', 'gui_foot');
          this._gui.getFirst().inject(this._guiHead);//htmlversion menue
          this._gui.getFirst().inject(this._guiHead);//htmlversion section#main
     },
     _events: function() {
          var self = this;
          var panel = null;
          document.body.addEvents({
               'mouseup:relay(select)': function(e) {
                    self._onInputClick(this);
               },
               'mouseup:relay(input)': function(e) {
                    self._onInputClick(this);
               },
               'click:relay(div)': function(e) {
                    var paneldiv = this.getParent('.gui_panel');
                    if (paneldiv) {
                         panel = self._panels[paneldiv.get('pid')];
                         switch (this.get('class')) {
                              case "item":
                                   self._onItemClick(this, panel);
                                   break;
                              case 'button item_add':
                                   self._onEditClick("Add", panel);
                                   break;
                              case 'button item_undo':
                                   panel._inspectItem();
                                   break;
                              case 'button item_delete':
                                   self._onEditClick("Delete", panel);
                                   break;
                              case 'button item_save':
                                   self._onEditClick("Save", panel);
                                   break;
                         }
                    }
               }
          });
     },
     _refresh: function(level) {
          for (var key in this._panels) {
               if (this._panels[key]._level > level) {
                    delete this._panels[key]._destroy();
               }
          }
     },
     _onInputClick: function(element) {
          var container = element.getParent('.item_input');
          var input;
          switch (element.get('tag')) {
               case 'select':
                    input = element.getSelected();
                    break;
               case 'input':
                    input = element;
                    break;
          }
          if (container && input.get('value') != container.get('val')) {
               this._panels[element.getParent('.gui_panel').get('pid')]._buttons(["save", "undo"]);
               element.getParent('.panel_body').setStyle('background', '#bbb');
               container.set({
                    val: input.get('value'),
                    txt: input.get('html')
               });
          }
     },
     _onItemClick: function(element, panel) {
          this._refresh(panel._level);
          var item = panel._inspectItem(element.get('id'));          
          for (var a = 0; a < item.children.length; a++) {
               var child = item.children[a];
               if (this._panels[child]) {
                    delete this._panels[child]._destroy();
               }
               this._panels[child] = new simPanel(child, panel._level + 1, item.model);
          }
     },
     _onEditClick: function(order, panel) {
          var self = this;
          var dummy;
          new maskBox({
               _confirm: order,
               onBuild: function(box) {
                    dummy = panel._editWin.clone();
                    dummy.getLast().destroy();
                    dummy.getElements('.item_input').each(function(e) {
                         e.set('html', e.get('key') + "<span>" + e.get('txt') + "</span>");
                    });
                    if (order == "Add") {
                         var head = dummy.getFirst().set('html', 'Add Item');
                         var body = head.getNext().empty();
                         panel._renderEdit(body, panel._addModel);
                    }
                    dummy.inject(box).fade(1);
               },
               onConfirm: function() {
                    switch (order) {
                         case "Delete":
                              panel._deleteItem();
                              self._refresh(panel._level);
                              break;
                         case "Save":
                              panel._saveItem();
                              break;
                         case "Add":
                              var model = {};
                              dummy.getElements('.item_input').each(function(e) {
                                   model[e.get('key')] = e.get('val');
                              });
                              panel._addItem(model);
                              break;
                    }
               }
          });
     }
});
/*=================================================================================================
 panels
 =================================================================================================*/
var simPanel = new Class({
     initialize: function(url, level, model) {
          this._url = url;
          this._data = {};
          this._level = level;
          this._selected = null;
          this._request(url, model);
          this._addModel = {};
     },
     _render: function() {
          for (var key in this._data.settings.edit) {
               this._addModel[key] = "";
          }
          var panelsetup = {
               class: 'gui_panel',
               pid: this._url
          };         
          this._itemWin = render($('gui_body'), 'div').set(panelsetup);
          this._itemHead = render(this._itemWin, 'div', 'panel_head').set('html', this._data.settings.name + '<div class="button item_add">+</div>');
          this._itemBody = render(this._itemWin, 'div', 'panel_body');
          for (var a = 0; a < this._data.entities.length; a++) {
               render(this._itemBody, "div", "item", a, this._data.entities[a].view.displayname);
          }         
          this._editWin = render($('gui_foot'), 'div').set(panelsetup);
          this._editHead = render(this._editWin, 'div', 'panel_head');
          this._editBody = render(this._editWin, 'div', 'panel_body');
          this._editFoot = render(this._editWin, 'div', 'panel_foot');
          this._inspectItem(-1);
     },
     _renderEdit: function(element, model) {
          for (var key in model) {
               var value = model[key];
               var e = new Element("div", {
                    html: key + ' : ',
                    key: key,
                    val: value,
                    txt: value,
                    class: 'item_input'
               }).inject(element);
               if (this._data.settings.edit[key]) {
                    switch (this._data.settings.edit[key].editmode) {
                         case "select":
                              new requestSelect(e, this._data.settings.edit[key].lookupurl);
                              break;
                         case "input":
                              new Element('input', {
                                   type: 'text',
                                   value: value
                              }).inject(e);
                              break;
                         default:
                              e.set('html', key + ' : <span>' + value + '</span>');
                              break;
                    }
               }
               else {
                    e.set('html', key + ' : <span>' + value + '</span>');
               }
          }
     },
     _buttons: function(buttons) {
          this._editFoot.getElements('.button').destroy();
          for (var a = 0; a < buttons.length; a++) {
               render(this._editFoot, 'div', "button item_" + buttons[a], undefined, buttons[a]);
          }
     },
     _addItem: function(model) {
          this._request(this._data.settings.refs.addurl, model);
     },
     _saveItem: function() {
          var self = this;
          var inputs = this._editWin.getElements('.item_input');
          inputs.each(function(e) {
               self._data.entities[self._selected].model[e.get('key')] = e.get('val');
          });
          this._request(self._data.settings.refs.updateurl, self._data.entities[self._selected].model);
          this._inspectItem(this._selected);
     },
     _deleteItem: function() {
          var self = this;
          this._itemWin.getElements('div([id="' + self._selected + '"])').destroy();
          this._request(self._data.settings.refs.deleteurl, self._data.entities[self._selected].model);
          delete self._data.entities[self._selected];
          this._inspectItem(-1);
     },
     _inspectItem: function(index) {
          this._itemBody.getElements('div').set('class', 'item');
          this._itemBody.getChildren('#' + index).addClass('selected');
          this._editWin.fade('hide');
          this._editHead.empty();
          this._editBody.empty().setStyle('background', '');
          if (index == -1)
               return null;
          if (!index)
               index = this._selected;
          var obj = this._data.entities[index];
          this._editWin.fade('show');
          this._selected = index;
          this._editHead.set('html', obj.view.displayname);
          this._renderEdit(this._editBody, obj.model);
          this._buttons(["delete"]);
          return this._data.entities[this._selected];
     },
     _destroy: function(keep) {
          if (this._editWin) {
               this._editWin.destroy();
               this._itemWin.destroy();
          }
          if (!keep)
               delete this;
     },
     _request: function(url, model, update) {
          var self = this;
          if (!url) {
               url = this._url;
          }
          var r = new Request.JSON({
               url: url,
               urlEncoded: false,
               onSuccess: function(j) {
                    self._data = j.super;
                    self._destroy(true);
                    self._render();
               },
               onFailure: function(xhr) {
                    new maskBox({
                         onBuild: function(box) {
                              box.set({
                                   class: "overlaybox somepanel debugpanel",
                                   html: xhr.response.replace(/font-/g, "")
                              });
                              var h = new Element('div').inject(box, 'top');
                              h.set('html', "Request URL : " + url + "</br>" + r.options.method + " : <pre>" + JSON.stringify(model, null, "\t") + "</pre>");
                         }
                    });
               }
          });
          if (model) {
               r.options.data = JSON.encode(model);
               r.post();
          } else {
               r.get();
          }
     }
});
/*=================================================================================================
 utility
 =================================================================================================*/
var requestSelect = new Class({
     initialize: function(element, url) {
          new Request.JSON({
               url: url,
               onSuccess: function(j) {
                    if (element) {
                         var selected = element.get('val');
                         var s = new Element('select');
                         for (var a = 0; a < j.super.entities.length; a++) {
                              var item = j.super.entities[a];
                              var e = new Element('option', {
                                   html: item.name,
                                   value: item.id
                              }).inject(s);
                              if (item.id == selected) {
                                   e.set('selected', true);
                                   element.set('txt', item.name);
                              }
                         }
                         s.inject(element).fade('hide').fade(1);
                    }
               }
          }).get();
     }
});
var maskBox = new Class({
     Implements: [Options, Events],
     options: {
          _confirm: false
                  //_onBuild : function(box){}
                  //_onConfirm : function(box){}
                  //_onCancel : function(box){}
     },
     initialize: function(options) {
          var self = this;
          self.setOptions(options);
          this._mask = new Element('div', {
               class: 'overlay',
               events: {
                    'click': function() {
                         self.fireEvent('onCancel', []);
                         self._destroy();
                    }
               }
          }).inject(document.body).fade('hide');
          this._box = new Element('div', {
               class: 'overlaybox'
          }).inject(document.body).fade('hide');
          this._show();
     },
     _confirm: function() {
          var self = this;
          this._confirm = new Element('div', {
               class: 'button',
               html: this.options._confirm,
               events: {
                    'click': function() {
                         self.fireEvent('onConfirm', []);
                         self._destroy();
                    }
               }
          });
          this._cancel = new Element('div', {
               class: 'button',
               html: 'Cancel',
               events: {
                    'click': function() {
                         self.fireEvent('onCancel', []);
                         self._destroy();
                    }
               }
          });
          if (this.options._confirm) {
               this._confirm.inject(this._box);
               this._cancel.inject(this._box);
          }
     },
     _show: function() {
          this.fireEvent('onBuild', [this._box]);
          this._confirm();
          this._box.fade(1);
          this._mask.fade(0.5);
     },
     _destroy: function() {
          this._confirm.removeEvent('click');
          this._cancel.removeEvent('click');
          this._mask.removeEvent('click');
          this._mask.fade(0);
          this._box.fade(0);
          var self = this;
          (function() {
               self._mask.destroy();
               self._box.destroy();
               delete self;
          }).delay(500);
     }
});
function render(element, tag, css, id, html) {
     var e = new Element(tag).inject(element);
     if (css)
          e.set('class', css);
     if (id != undefined)
          e.set('id', id);
     if (html)
          e.set('html', html);
     return e;
}


//requires json-tree from luxid with changed super.settings.edit :
//"edit": {
//        "id": {
//          "editmode": "none"
//        },
//        "context": {
//          "editmode": "select",
//          "lookupurl": "/json/xobjects/lookup/context"
//        },
//        "usertype": {
//          "editmode": "select",
//          "lookupurl": "/json/xobjects/lookup/usertype"
//        },
//        "created_at": {
//          "editmode": "none"
//        }
//      }