/*

ZNotes (Zooomr Notes)
Copyright (C) 2006-08 Kristopher Tate / Zooomr Inc. / BlueBridge Technologies Group / BlueBridge K.K.

(Some DOM and Prototype code Copyright (c) 2006 Dusty Davidson - http://www.dustyd.net)
(portions Copyright (c) 2005 Angus Turnbull http://www.twinhelix.come)

*/

/*********************************************************/
/*** Notes Wrapper ***************************************/
/*********************************************************/


znotes = {

  AddJSONNotes: function(container,JSON) {

    for (var i = 0;i<JSON.length;i++) {
      var currentNote = JSON[i];
      
      //console.log(currentNote);
      
      var relatdeg = (global_nsid == currentNote.oid || global_nsid == _ZGLOBAL[_ZGLOBAL['_CTX'].photo].owner.nsid || global_nsid == '' ? 1 : 0) //(global_nsid > 0 && currentNote.oid in _ZGLOBAL['social_circle'] ? 2 : 3))

      var html_data = znotes.GenerateBody(currentNote);

      var note = new PhotoNote(page_photo_id,currentNote.typ,currentNote.text, html_data ,currentNote.id,currentNote.oid,currentNote.pun,currentNote.portalpic,relatdeg,new PhotoNoteRect(currentNote.rectdata[0],currentNote.rectdata[1],currentNote.rectdata[2],currentNote.rectdata[3]));
          note.onsave = znotes.SaveNote;
          note.ondelete = znotes.DeleteNote;
      
      container.AddNote(note);
      
    }
  
  },
  
  GenerateBody : function(note) {  //Generates HTML Body data for Notes
    if (note.text != '') {
      var note_text = (note.oid == global_nsid ? '' : '<a href="/people/' + note.owner.url + '/" class="iconlink" style="font-weight:bold;"><img src="' + _icon_root + note.oid + '.jpg" style="vertical-align: top;" alt="" width="12" height="12" /> ' + note.owner.name + '</a>: ') + note.text;
    } else {
      var note_text = '';
    }
    if ( note.typ == 1) {
      if (note.pun.nsid == '00@Z01') {
        var out = '<h1><a href="/search/photos/?q=%22people:' + note.pun.emailhash + '=' + note.pun.fname + '%20' + note.pun.lname + '%22" class="iconlink"><img src="/images/avatarmaker/default.png" style="vertical-align:middle;" alt="" /> ' + note.pun.fname + ' ' + note.pun.lname + '</a></h1>';
      } else {
        var out = '<h1><a href="/people/' + note.pun.url + '/" class="iconlink"><img src="' + _icon_root + note.pun.nsid + '.jpg" style="vertical-align:middle;" alt="' + note.pun.name + '" /> ' + note.pun.name + '</a></h1>';
      }
      return out + (note_text ? '<br />' + note_text : '');
    } else {
      return note_text;
    }
  },
  
  AddNote : function(photoid,container,typ,person_un) {
//    var relatdeg = (global_nsid == container.ownerid ? 1 : (global_nsid > 0 && currentNote.oid in _ZGLOBAL['social_circle'] ? 2 : 3))
    var newNote = new PhotoNote(photoid,typ,gettext("Add note text here..."),'',-1,global_nsid,null,null,1,new PhotoNoteRect(10,10,50,50));
    newNote.onsave = znotes.SaveNote;
    newNote.ondelete = znotes.DeleteNote;

    if (typ == 1 && person_un) newNote.gui.PeopleInput.value = person_un.name + ' <' + person_un.url + '>';

    container.AddNote(newNote);

    newNote.Select();
  },
  
  SaveNote : function(note) {  
    var props = {
            photo_id: note.photoid,
            note_type: (note.typ == 2 && !note.portalpic ? 0 : note.typ),
            note_text: note.text == gettext("Add note text here...") ? '' : note.text,
            note_x: note.rect.left,
            note_y: note.rect.top,
            note_w: note.rect.width,
            note_h: note.rect.height
            };

    if (props.note_text == '' && note.typ == 0) { 
      alert( gettext("Please enter your note before saving!") );
      return [-1, ''];
    }

    zloader.enable(note.container.zloader,gettext("Saving..."));
    
    if (note.typ == 1) infotags.saving_prep( 'people' );
    
    var success	= function(t) {
        znotes.RefreshNotes( note.container );
//        if (note.typ == 1) photo_people.rerender(note.photoid,note.person_un,'added_people_console');

      zloader.disable(note.container.zloader);
    };

    
    if (note.id > 0) {
      props['note_id'] = note.id;
      ZAPI.callMethodJSON( 'zooomr.photos.notes.edit', props, {'onSuccess':success});
    } else {
      if (note.portalpic) { props['portal'] = note.portalpic; }
      if (note.person_un) { props['person'] = note.person_un; }
      ZAPI.callMethodJSON( 'zooomr.photos.notes.add', props, {'onSuccess':success});
    }

    return [-1, ''];
  },

  ConvertNote : function( data ) {
    var base_dict = {id: data.id, photoid: page_photo_id, owner: {name: data.authorname, url: data.authorurlname}, typ:data.type, text: data._content, oid: data.author, portalpic: null, rectdata: [ data.x, data.y, data.w, data.h ] };
    
    if (data.type == 1) { //PeopleNote
      if (data.person == "00@Z01") {
        base_dict['pun'] = {nsid: data.person, fname: data.personfname, lname: data.personlname, emailhash: data.personemailhash };
      } else {
        base_dict['pun'] = {nsid: data.person, url: data.personurlname, name: data.personname };
      }
    } else if (data.type == 2) {
      base_dict['portalpic'] = data.portal;
    }
    
    return base_dict;
  },

  RefreshNotes : function(note_container) {  
    note_container.DeleteAllNotes();

    sExec = function( data ) {
      var new_notes = data.photo.notes.note;
      for (var k = 0;k<new_notes.length;k++) {
        var currentNote = znotes.ConvertNote( new_notes[k] );

        var relatdeg = (currentNote.oid == global_nsid || global_nsid == '' ? 1 : 0) //(global_nsid > 0 && currentNote.oid in _ZGLOBAL['social_circle'] ? 2 : 3))

        var html_data = znotes.GenerateBody(currentNote);
  
        var note = new PhotoNote(currentNote.photoid,currentNote.typ,currentNote.text, html_data ,currentNote.id,currentNote.oid,currentNote.pun,currentNote.portalpic,relatdeg,new PhotoNoteRect(currentNote.rectdata[0],currentNote.rectdata[1],currentNote.rectdata[2],currentNote.rectdata[3]));
            note.onsave = znotes.SaveNote;
            note.ondelete = znotes.DeleteNote;
        
        note_container.AddNote(note);
        
      }

      infotags.refresh_node( 'people' );
      
    };
  
    ptools.refresh_data(page_photo_id, sExec);

  },


  DeleteNote : function(note) {    
    zloader.enable(note.container.zloader, gettext("Deleting Note...") );

    var success	= function(t) {
//        znotes.RefreshNotes( note.container );
      zloader.disable(note.container.zloader);
      if (note.typ == 1) infotags.refresh_node( 'people' );
    };

    ZAPI.callMethodJSON( 'zooomr.photos.notes.delete', {note_id: note.id}, {'onSuccess':success});

//    if (note.typ == 1) photo_people.delete_user(note.photoid,note.person_un);

    return true;
  },
  
  BuildMBrowser : function(container_element,note) { //photo_id,note
      container_element.innerHTML = '';

      // create PixChooser
      var pixChooser = newNode("div");
          pixChooser.setAttribute('class','pixchooser');
          pixChooser.style.margin = 'auto';
          pixChooser.style.marginTop = '50px';
          pixChooser.style.width = '700px';
          pixChooser.style.height = '345px';


      var self = this;
    
      var cancelImg = newNode("img");
          cancelImg.src = "http://assets2.zooomr.com/images/tidbits/window_closer_black.gif";
          cancelImg.setAttribute('style','float:right;margin:4px;cursor:pointer;z-index:9000;');
          cancelImg.alt = gettext("Cancel");
          cancelImg.title = gettext("Cancel");
          cancelImg.border = '0';
          cancelImg.onclick = function() { new Effect.BlindUp(container_element); container_element.innerHTML = '';};
    
      pixChooser.appendChild(cancelImg);
    
    
      var streamChooserDiv = newNode("div");
          streamChooserDiv.setAttribute('class','innerPixchooser');
          streamChooserDiv.style.width = '230px';
          streamChooserDiv.style.height = '275px';
          streamChooserDiv.style.position = 'absolute';
          streamChooserDiv.style.padding = '10px';
    
      //The actual input
      var ainput = newNode("input");
    
    // <input style="color: #333; font-size: 10px; padding: 0" type="text" name="q" value="" size="30">
    
      ainput.style.color = '#000';
      ainput.style.fontSize = '13px';
      ainput.style.fontWeight = 'bold';
      ainput.style.width = '220px';
    
      ainput.style.padding = '2px';
      
      ainput.style.borderTop = '1px solid #000';
      ainput.style.borderLeft = '1px solid #000';
      ainput.style.borderRight = '1px solid #ccc';
      ainput.style.borderBottom = '1px solid #ccc';
      
      ainput.setAttribute('type','text');
      ainput.setAttribute('value',gettext("Refine by Tags"));
      
      streamChooserDiv.appendChild(ainput);
    
    
      var photosDiv = newNode("div");
    
      streamChooserDiv.appendChild(photosDiv);
    
    
      Event.observe(ainput, 'focus', function(){if (ainput.value == gettext("Refine by Tags")) {
                                                  ainput.value = '';
                                                }}, false);
    
      Event.observe(ainput, 'blur', function(){if (ainput.value == '') {ainput.value = gettext("Refine by Tags");}}, false);
      
      pixChooser.appendChild(streamChooserDiv);
    
      var streamSelectedDiv = newNode("div");
          streamSelectedDiv.setAttribute('class','innerPixchooser');
          streamSelectedDiv.innerHTML = '<h1 style="margin:0;">Destination Photo</h1>';
          streamSelectedDiv.style.width = '393px';
          streamSelectedDiv.style.height = '285px';
          streamSelectedDiv.style.marginLeft = '275px';
          streamSelectedDiv.style.padding = '5px 10px';
    
      var innerStreamSelectedDiv = newNode("div");
    //      innerStreamSelectedDiv.style.overflow = 'auto';
    
      streamSelectedDiv.appendChild(innerStreamSelectedDiv);
    
      pixChooser.appendChild(streamSelectedDiv);    
    
      Event.observe(ainput, 'keyup', function(oEvent){znotes.getdataForPixChooser(1,ainput,photosDiv,innerStreamSelectedDiv,note);}, false);

      znotes.getdataForPixChooser(1,ainput,photosDiv,innerStreamSelectedDiv,note);
    
    //<input type="submit" onclick="contacts.savecontact('1148782764_5315','add','addcontactform')" class="reg_button" value="OK!"/>
    //<input type="submit" onclick="new Effect.BlindUp('addcontactform');" value="CANCEL"/>
    
      var buttonDiv = newNode("div");
          buttonDiv.style.width = '690px';
          buttonDiv.style.margin = '5px 0';
          buttonDiv.style.textAlign = 'right';
    
      var cancelInput = newNode("input");
          cancelInput.setAttribute('class','cancel_button');
          cancelInput.setAttribute('type','button');
          cancelInput.setAttribute('value',gettext("Cancel"));
          cancelInput.onclick = function() { new Effect.BlindUp(container_element); container_element.innerHTML = '';};
    
      buttonDiv.appendChild(cancelInput);
    
      buttonDiv.appendChild(document.createTextNode(' '));
    
      buttonDiv.appendChild(document.createTextNode(' '));
    
      greenInput = newNode("input");
      greenInput.setAttribute('class','reg_button');
      greenInput.setAttribute('type','button');
      greenInput.setAttribute('value','CONTINUE');
//      greenInput.setAttribute('disabled','true');

      greenInput.onclick = function () {
                                          if (note.portalpic) {
                                            note.container.RedrawNote(note);
                                            new Effect.BlindUp(container_element);
                                            container_element.innerHTML = '';
                                          } else {
                                            alert( gettext("Please select a Destination Photo first.") );
                                          }
                                          
                                        }
    
      buttonDiv.appendChild(greenInput);
    
      pixChooser.appendChild(buttonDiv);

      container_element.appendChild(pixChooser);

  },
  
  getdataForPixChooser : function(page_num,ainput,photoContainer,streamSelectedDiv,note) {
        //Get Object Data:    
        var success	= function(t) {
          photoContainer.innerHTML = '';
          //Parse Data
          var this_page = json_parse(t.responseText)['photos'];
          //Load Page Nav
      
          var navDiv = newNode("div");
              navDiv.setAttribute('class','pcPageNav');
      
          if (this_page.pages == 0) {
            navDiv.appendChild(document.createTextNode( gettext("No photos were found.") ));
          } else {
      
            var prevNav = newNode("a");
                prevNav.href = "javascript:void(0);";
                prevNav.onclick = function() {if (page_num-1 > 0) { znotes.getdataForPixChooser(page_num-1,ainput,photoContainer,streamSelectedDiv,note);} else { znotes.getdataForPixChooser(this_page.pages,ainput,photoContainer,streamSelectedDiv,note); }}
                prevNav.innerHTML = '&laquo;';
        
            navDiv.appendChild(prevNav);
        
            var placeNav = newNode("span");
                placeNav.innerHTML = this_page.page+'/'+this_page.pages+' ('+this_page.total+')';
        
            navDiv.appendChild(placeNav);
        
        
            var nextNav = newNode("a");
                nextNav.href = "javascript:void(0);";
                nextNav.onclick = function() {if (this_page.pages-this_page.page > 0) {znotes.getdataForPixChooser(page_num+1,ainput,photoContainer,streamSelectedDiv,note);} else { znotes.getdataForPixChooser(1,ainput,photoContainer,streamSelectedDiv,note); }}
                nextNav.innerHTML = '&raquo;';
        
            navDiv.appendChild(nextNav);
      
          }
      
          photoContainer.appendChild(navDiv);
      
          for (k=0;k<this_page['photo'].length;k++) {
            photoContainer.appendChild(znotes.drawimgForPixChooser(this_page['photo'][k],'highlight',ainput,photoContainer,streamSelectedDiv,note));
          }
          
          zloader.disable();
      
        }
      
        var tag_data = ainput.value;
        if (tag_data == gettext("Refine by Tags")) {
          tag_data = '';
        }
      
//X          var url = '/objnfo.awe';
//X          var pars = 'data='+JSON.stringify({"action":"ps","limit_list":[],"uid":global_nsid,"tags":tag_data,"page":page_num,"perpage":16});
//X        //	alert(pars);
//X          new Ajax.Request(url, {method:'post', postBody:pars, onSuccess:success});
        

        ZAPI.callMethodJSON( 'zooomr.photos.search', {query: tag_data + " query:owner=" + global_nsid, per_page: 16, page: page_num}, {onSuccess:success})
        zloader.enable();
        
    },
    
    drawimgForPixChooser : function(photo_data,h_mode,ainput,photoContainer,streamSelectedDiv,note) {
      var testImg = newNode("img");
          testImg.setAttribute('class',h_mode);
          testImg.src = _photo_root + photo_data.id + '_' + photo_data.secret + '_s.jpg'; //photo_data.src;
          testImg.style.padding = '2px';
          testImg.style.margin = '1px';
          testImg.style.height = '50px';
          testImg.style.width = '50px';
          testImg.onclick = function() {note.portalpic = photo_data.id; streamSelectedDiv.innerHTML = '';
                                        var newPortalThumbnail = document.createElement('img');
                                            newPortalThumbnail.border = 0;
                                            newPortalThumbnail.src = _photo_root + photo_data.id + '_' + photo_data.secret + '_m.jpg';
                                        streamSelectedDiv.appendChild(newPortalThumbnail);
                                        };
    
      return testImg
    
    }

}


/*********************************************************/
/*** Photo Notes Container *******************************/
/*********************************************************/
function PhotoNoteContainer(element, config)
{
    var props = {
        element: element,
        dragresize: null,
        notes: new Array(),
        editing: false,
        zloader: zloader.build('zloader_'+element.id,element,'Loading...',(element.clientWidth / 2.5 > 99 ? element.clientWidth / 2.5 : 100),true),
        ownerid: -1,
        enabled: true,
        
        inUse: 0
        
    };

    for (var p in props)
    {
        this[p] = (!config || typeof config[p] == 'undefined') ? props[p] : config[p];
    }
};

PhotoNoteContainer.prototype.RedrawNote = function(note)
{

    var note_data = {
                     photoid: note.photoid,
                     typ: note.typ,
                     text: note.text,
                     id: note.id,
                     oid: note.oid,
                     person_un: note.person_un,
                     portalpic: note.portalpic,
                     relatdeg: note.relatdeg,
                     rect: [note.rect.left,note.rect.top,note.rect.width,note.rect.height],
                     onsave: note.onsave,
                     ondelete: note.ondelete
                     };

    this.DeleteNote(note); // Bye, Pal.

    var newNote = new PhotoNote(note_data.photoid,note_data.typ,note_data.text,'',note_data.id,note_data.oid,note_data.person_un,note_data.portalpic,note_data.relatdeg,new PhotoNoteRect(note_data.rect[0],note_data.rect[1],note_data.rect[2],note_data.rect[3]));

    newNote.onsave = note_data.onsave;
    newNote.ondelete = note_data.ondelete;

    this.AddNote(newNote);

    newNote.Select();

}

PhotoNoteContainer.prototype.DeleteNote = function(note)
{
    try {
      note.UnSelect();
    } catch (e) {
    //
    }

    /* remove from the DOM */
    this.element.removeChild(note.gui.ElementRect);
    this.element.removeChild(note.gui.ElementNote);
    
    /* remove from the array... */
    this.notes.splice(this.notes.indexOf(note),1);

}

PhotoNoteContainer.prototype.AddNote = function(note)
{
    if(!this.editing)
    {
        this.ShowAllNotes();
        /* add the note to the array of notes, and set its container */
        this.notes[this.notes.length] = note;
        note.container = this;

        /* add the note to the DOM */
        this.element.appendChild(note.gui.ElementRect);
        this.element.appendChild(note.gui.ElementNote);    
    }
};

/* hide all of the "text" parts of the notes. Primarily called when hovering a note, at which
    point we want to hide all of the other note texts */
PhotoNoteContainer.prototype.HideAllNoteTexts = function()
{
    for (var i = 0;i<this.notes.length;i++)
        this.notes[i].HideNoteText();
};


PhotoNoteContainer.prototype.DisableAllNotes = function()
{
    for (var i = 0;i<this.notes.length;i++)
        this.notes[i].DisableNote();
};

PhotoNoteContainer.prototype.HideAllNotes = function()
{
    this.enabled = false;
    for (var i = 0;i<this.notes.length;i++)
        this.notes[i].HideNote();
};

PhotoNoteContainer.prototype.ShowAllNotes = function()
{
    this.enabled = true;
    for (var i = 0;i<this.notes.length;i++)
        this.notes[i].ShowNote();
};

PhotoNoteContainer.prototype.EnableAllNotes = function()
{
    for (var i = 0;i<this.notes.length;i++)
        this.notes[i].EnableNote();
};

PhotoNoteContainer.prototype.DeleteAllNotes = function()
{
    for (var k = this.notes.length-1;k>-1;k--) {
        try {
          this.notes[k].UnSelect();
        } catch (e) {
        //
        }
    
        /* remove from the DOM */
        this.element.removeChild(this.notes[k].gui.ElementRect);
        this.element.removeChild(this.notes[k].gui.ElementNote);
        
        /* remove from the array... */
        this.notes.splice(k,1);
    }
};

/*********************************************************/
/*** Photo Note ******************************************/
/*********************************************************/
function PhotoNote(photoid,typ,text,html,id,oid,person_un,portalpic,relatdeg,rect)
{
    var props = {
        photoid: photoid,
        typ: typ,
        text: text,
        html: html,                   
        id: id,
        oid: oid,
        person_un: person_un,
        portalpic: portalpic,
        relatdeg: relatdeg,
        rect: rect,                    
        selected: false,
        container: null,
        dragresize: null,
        oldRect: null,
        YOffset: -5,
        XOffset: -5,
        YOffsetFlight: 6,
        XOffsetFlight: -5,
        onsave: null,
        ondelete: null,
        gui: null,
        timer: null
        
    };

    for (var p in props)
    {
        this[p] = props[p];
    }
    
    this.CreateElements();
}


PhotoNote.prototype.Select = function(disable_t2)
{
    //window.status = 'container: ' + this.container;
    if(this.container && !this.container.editing)
    {

        if (!disable_t2 && this.typ == 2 && this.portal_url) {
          this.gui.ElementRect.firstChild.firstChild.firstChild.style.background = 'none';
          new Effect.Puff(this.gui.PortalImg);
          window.location = this.portal_url;
          return;
        }
        
        if (this.container.ownerid == global_nsid || this.oid == global_nsid) {
          this.ShowNoteText();
          this.dragresize.select(this.gui.ElementRect);
          this.selected = true;
          this.SetEditable(true);
        }
    }    
}


PhotoNote.prototype.UnSelect = function()
{
    this.dragresize.deselect(false);
    this.selected = false;
    this.SetEditable(false);
    this.HideNoteText();
}

PhotoNote.prototype.Save = function(newhtml)
{

    this.oldRect = null;
    this.gui.TextTitle.innerHTML = newhtml;//this.gui.TextBox.value;
    this.text = this.gui.TextBox.value;
    if (this.typ == 1 && this.id < 0) {
      if (this.gui.PeopleInput.value != '') {
        this.person_un = this.gui.PeopleInput.value;
      } else {
        this.person_un = this.gui.ForiegnPeopleInput.fname.value + '||' + this.gui.ForiegnPeopleInput.lname.value + ' <' + this.gui.ForiegnPeopleInput.email.value + '>';
      }
    }
    this.html = newhtml;
    this.UnSelect();
}

PhotoNote.prototype.Cancel = function()
{

    //if the note is still new, then we actually want to delete it, not cancel it..
    if (this.id < 0) {
        this.container.DeleteNote(this)
    } else {
       //reset the node to it's old position 
        if(this.oldRect != null)
        {
            this.rect = this.oldRect;                
        }
        
        this.oldRect = null;               
        this.gui.TextBox.value = this.text;
        this.UnSelect();
        this.PositionNote();
    }
    
    if (this.typ == 1) infotags.refresh_node( 'people' );
    
}


PhotoNote.prototype.ShowNoteText = function()
{
    if(this.container && !this.container.editing && this.gui.ElementNote.style.display != 'block')
    {
        this.container.HideAllNoteTexts();
        this.container.DisableAllNotes();
        this.EnableNote();

        this.gui.ElementRect.style.border='1px solid #D4D82D';
        this.gui.ElementRect.style.margin='0';
        if (this.typ != 2 || (this.typ == 2 && (this.relatdeg == 1 || this.text != ''))) {
          this.gui.ElementNote.style.display='block';
        }

        this.container.inUse = this.id;

    }

    if (this.typ == 2 && this.portalpic) {
      if (this.id > -1) this.gui.ElementRect.firstChild.firstChild.firstChild.style.background = '#000 url(/images/tidbits/portal_bg.gif)';
//      this.gui.PortalImg.style.left = '0px';
//      this.gui.PortalImg.style.top = '0px';
      this.gui.PortalImg.style.display = 'block';
    }
}

PhotoNote.prototype.DisableNote = function ()
{
    this.dragresize.enabled=false;
}

PhotoNote.prototype.EnableNote = function ()
{
    
    if ((this.typ != 2 || this.id == -1) && (this.container.ownerid == global_nsid || this.oid == global_nsid)) {
      this.dragresize.enabled=true;
    }
}

PhotoNote.prototype.HideNoteText = function ()
{
    if (this.container.inUse == this.id) {
      this.container.inUse = 0;
    }
    this.gui.ElementRect.style.border='0px solid #D4D82D';
    this.gui.ElementRect.style.margin='1px';
    this.gui.ElementNote.style.display='none';
    
    if (this.typ == 2 && this.portalpic) {
      this.gui.ElementRect.firstChild.firstChild.firstChild.style.background = 'none';
      this.gui.PortalImg.style.left = '0px';
      this.gui.PortalImg.style.top = '0px';
      this.gui.PortalImg.style.display = 'none';
    }    
}


PhotoNote.prototype.HideNote = function ()
{
    this.gui.ElementRect.style.display='none';
    this.gui.ElementNote.style.display='none';
}


PhotoNote.prototype.ShowNote = function ()
{
    this.gui.ElementRect.style.display='block';
    this.gui.ElementNote.style.display='none';
}



PhotoNote.prototype.SetEditable = function(editable)
{
    this.container.editing = editable;
    
    if(editable)
    {
        this.gui.ElementNote.style.minWidth = '250px';
        //the first child of the note is the text
        this.gui.TextTitle.style.display = 'none';
        
        //the second child is the edit area...
        this.gui.EditArea.style.display = 'block';
        
        //if this is a "new" note, then hide the delete button
        if(this.id <= 0)
            this.gui.DeleteButton.style.display = 'none';
        else
            this.gui.DeleteButton.style.display = 'inline';
        
        // get the textarea and select the text...
        this.HighlightTextbox();
   }
    else
    {
        this.gui.ElementNote.style.minWidth = '125px';
        
        //the first child of the note is the text
        this.gui.TextTitle.style.display = 'block';
        
        //the second child is the edit area...
        this.gui.EditArea.style.display = 'none';
    }
}

PhotoNote.prototype.HighlightTextbox = function ()
{
    // get the textarea and select the text...
    if(this.gui.EditArea.style.display=='block')
    {
        var textfield = this.gui.TextBox;
        setTimeout(function() {
                try
                {
                    textfield.focus();
                    textfield.select();
                }
                catch(e) {}
            }, 200);
    }

}

PhotoNote.prototype.CreateElements = function()
{
    
    this.gui = new PhotoNoteGUI();

    var newArea = document.createElement('div');
        newArea.className = 'zn-area';
        newArea.id = 'zn-area-new';
        
    this.dragresize = new DragResize('dragresize', { allowBlur: false });        

    var newAreaBlack = document.createElement('div');
        newAreaBlack.className = 'zn-area-blackborder';
    var newAreaWhite = document.createElement('div');
        newAreaWhite.className = 'zn-area-whiteborder';
    
    
    var currentNote = this;


    var newAreaInner = document.createElement('div');
        newAreaInner.className = 'zn-area-inner';

    if (this.typ == 2 && this.portalpic) { //Heh, awesome -- a Portal Note

      var newPortalPhoto = document.createElement('img');
          newPortalPhoto.border = 0;
          newPortalPhoto.style.display = 'none';
          newPortalPhoto.className = 'zn-portal-img';
      
      var success	= function(t){
        var res_data = json_parse(t.responseText)['sizes']['size'][0];
        newPortalPhoto.src = res_data['source'];
        currentNote.portal_url = res_data['home'];
      }
      
      this.PortalZSize = (this.rect.width < 240 && this.rect.height < 180 ? (this.rect.width < 60 && this.rect.height < 60 ? 2 : 4) : 8)

      ZAPI.callMethodJSON( 'zooomr.photos.getsizes', {photo_id: this.portalpic, type: this.PortalZSize} , {onSuccess:success})

      var newPortalContainer = document.createElement('div');
          newPortalContainer.className = 'zn-portal-container';

      newPortalContainer.appendChild(newPortalPhoto);
      newAreaInner.appendChild(newPortalContainer);

    } else if ( this.typ == 2 ) {
      newAreaInner.style.background = '#000 url(/images/tidbits/portal_bg.gif)';
      newAreaInner.style.filter = 'alpha(opacity=0.4)';
      newAreaInner.style.opacity = '0.4';
    }

    newAreaWhite.appendChild(newAreaInner);


    //attach mouse events to this element...
    addEvent(newAreaInner, 'mouseover', function() {
            clearTimeout(currentNote.timer);
            currentNote.timer = 0;
            currentNote.ShowNoteText();
        });
    addEvent(newAreaInner, 'mouseout', function() {
            if(!currentNote.selected && !currentNote.timer)
            {
                currentNote.timer = setTimeout(function () {
                                                            currentNote.HideNoteText();
                                                            clearTimeout(currentNote.timer);
                                                            currentNote.timer = 0;
                                                            }, 500);
                                                            
//                console.log("detonator set!: "+currentNote.timer);
                    
            }
        });
        
    addEvent(newAreaInner, 'mousedown', function() {
            if(!currentNote.selected)
            {
                //window.status = 'mouseDown2!';
                currentNote.Select();
            }
        });

    
    newAreaBlack.appendChild(newAreaWhite);
    newArea.appendChild(newAreaBlack);
    
    // add the notes area
    var noteArea = document.createElement('div');
    noteArea.className = 'zn-note';

    var titleArea = document.createElement('div');


    addEvent(titleArea, 'mouseover', function() {
//            console.log("detonator?: "+currentNote.timer);
            clearTimeout(currentNote.timer);
            currentNote.timer = 0;
            currentNote.ShowNoteText();
        });

    addEvent(titleArea, 'mouseout', function() {

            if(!currentNote.selected && !currentNote.timer)
            {
                currentNote.timer = setTimeout(function () {
                                                            currentNote.HideNoteText();
                                                            clearTimeout(currentNote.timer);
                                                            currentNote.timer = 0;
                                                            }, 500);
            }
        });


    if (this.relatdeg == 1) {
      titleArea.className = 'zn-note-text'; //1st deg
    } else if (this.relatdeg == 2) {
      titleArea.className = 'zn-note-text-incircle'; //2nd deg
    } else {
      titleArea.className = 'zn-note-text-incircle'; //outcircle'; //3rd deg
    }


//XXX:OLD    var t = document.createTextNode(this.text);    
    if (this.typ == 2 && this.relatdeg == 1 && global_nsid && this.id > -1) {
      var t = document.createElement('div');
          if (this.text != '') { t.innerHTML = this.html + ' | '; }

      var editLink = document.createElement('a');
          editLink.innerHTML = gettext("Edit or Delete?");
          editLink.href = 'javascript:void(0);';
          editLink.onclick = function () {
                                          currentNote.Select(true);
                                         }
      
      t.appendChild(editLink);

    } else {
      var t = document.createElement('div');
          t.innerHTML = this.html;
    }

    titleArea.appendChild(t);
    noteArea.appendChild(titleArea);
    
    var editArea = document.createElement('div');
    editArea.className = 'zn-note-edit';
    
    var editAreaText = document.createElement('div');
    
    editAreaText.className = 'zn-note-edit-text';

    if (this.typ == 1 && this.id == -1 && global_nsid) { //&& this.relatdeg == 1 && global_nsid > 0) { //People Notes Edit
      var newPeopleTitle = document.createElement('strong');
          newPeopleTitle.innerHTML = gettext("Who is this person?") + ' <a id="znotes_notauser_a" href="javascript:void(0);" onclick="$(\'znotes_notauser_div\').toggle();$(\'znote_contact_names\').toggle();$(\'znote_contact_names\').value=\'\';$(\'znotes_auser_a\').show();this.hide();">Not a Zooomr User?</a>' + ' <a id="znotes_auser_a" href="javascript:void(0);" onclick="$(\'znotes_notauser_div\').toggle();$(\'znote_contact_names\').toggle();$(\'znotes_notauser_a\').show();this.hide()" style="display:none;">A Zooomr User?</a>';

      editAreaText.appendChild(newPeopleTitle);

      editAreaText.appendChild(document.createElement('br'));

      var notAUserDiv = document.createElement('div');
          notAUserDiv.style.textAlign = "right";
          notAUserDiv.style.display = "none";
          notAUserDiv.setAttribute('id', 'znotes_notauser_div');
          

      var newFNameTitle = document.createElement('strong');
          newFNameTitle.innerHTML = gettext("First Name") + ' ';
      notAUserDiv.appendChild(newFNameTitle);

      var newPeopleFNameInput = document.createElement('input');
          newPeopleFNameInput.setAttribute('name','fname');
          newPeopleFNameInput.setAttribute('size','27');
          newPeopleFNameInput.setAttribute('type','text');
          newPeopleFNameInput.style.fontSize = '10px';
          newPeopleFNameInput.value = '';
          
      notAUserDiv.appendChild(newPeopleFNameInput);

      notAUserDiv.appendChild(document.createElement('br'));

      var newLNameTitle = document.createElement('strong');
          newLNameTitle.innerHTML = gettext("Last Name") + ' ';
      notAUserDiv.appendChild(newLNameTitle);

      var newPeopleLNameInput = document.createElement('input');
          newPeopleLNameInput.setAttribute('name','lname');
          newPeopleLNameInput.setAttribute('size','27');
          newPeopleLNameInput.setAttribute('type','text');
          newPeopleLNameInput.style.fontSize = '10px';
          newPeopleLNameInput.value = '';
          
      notAUserDiv.appendChild(newPeopleLNameInput);

      notAUserDiv.appendChild(document.createElement('br'));

      var newEMailTitle = document.createElement('strong');
          newEMailTitle.innerHTML = gettext("Email") + ' ';
      notAUserDiv.appendChild(newEMailTitle);

      var newPeopleEMailInput = document.createElement('input');
          newPeopleEMailInput.setAttribute('name','email');
          newPeopleEMailInput.setAttribute('size','27');
          newPeopleEMailInput.setAttribute('type','text');
          newPeopleEMailInput.style.fontSize = '10px';
          newPeopleEMailInput.value = '';

      notAUserDiv.appendChild(newPeopleEMailInput);


      editAreaText.appendChild(notAUserDiv);


      var newPeopleInput = document.createElement('input');
          newPeopleInput.setAttribute('id','znote_contact_names');
          newPeopleInput.setAttribute('name','contact_names');
          newPeopleInput.setAttribute('size','40');
          newPeopleInput.setAttribute('type','text');
          newPeopleInput.style.fontSize = '10px';
          newPeopleInput.value = '';

      editAreaText.appendChild(newPeopleInput);

    } else if (this.typ == 2 && this.relatdeg == 1 && global_nsid && this.id == -1) {

      var newInstructionTitle = document.createElement('strong');
          newInstructionTitle.innerHTML = gettext("This Portal's Destination Photo:");

      editAreaText.appendChild(newInstructionTitle);

      editAreaText.appendChild(document.createElement('br'));


      var newPortalThumbnail = document.createElement('img');
          newPortalThumbnail.border = 0;
          newPortalThumbnail.style.verticalAlign = 'middle';
          newPortalThumbnail.style.marginRight = '20px';

      
      if (this.portalpic) {      
          var success	= function(t){
            var res_data = json_parse(t.responseText)['sizes']['size'][0];
            newPortalThumbnail.src = res_data['source'];
          }
    
          ZAPI.callMethodJSON( 'zooomr.photos.getsizes', {photo_id: this.portalpic, type: 1} , {onSuccess:success})
          
      } else {
          newPortalThumbnail.src = '/images/tidbits/no_photo_selected.gif';
      }

      var newChooseButton = document.createElement('input');
          newChooseButton.setAttribute('type','button');
          newChooseButton.value = gettext("CHOOSE A PHOTO");
          newChooseButton.className = 'reg_button';
          newChooseButton.onclick = function () {
                                                  znotes.BuildMBrowser($('photosheet_'+currentNote.photoid),currentNote);
                                                  new Effect.BlindDown($('photosheet_'+currentNote.photoid));
                                                };


      var newPortalThumbContainer = document.createElement('div');
          newPortalThumbContainer.appendChild(newPortalThumbnail);
          newPortalThumbContainer.appendChild(newChooseButton);

      editAreaText.appendChild(newPortalThumbContainer);
    }

    var newNoteTitle = document.createElement('div');
        newNoteTitle.style.fontWeight = 'bold';
        newNoteTitle.innerHTML = gettext("Note");

    editAreaText.appendChild(newNoteTitle);

    var newTextbox = document.createElement('textarea');
    newTextbox.value = this.text;
    editAreaText.appendChild(newTextbox);

    editArea.appendChild(editAreaText);
    
    var buttonsDiv = document.createElement('div');
    
    if (this.oid == global_nsid) {
      var newButtonOK = document.createElement('input');
      newButtonOK.type='button';
      newButtonOK.className = 'reg_button';
      newButtonOK.value= gettext("Save").toUpperCase();
      newButtonOK.onclick = function() {
              
              
              if(currentNote.onsave) 
              {
  
                  if ( (currentNote.gui.TextBox.value == gettext("Add note text here...") || currentNote.gui.TextBox.value == '') && currentNote.typ == 0) { 
                    alert( gettext("Please enter your note before saving!") );
                    return;
                  }
                  
                  if (currentNote.typ == 1 && currentNote.id < 0 && ($F(currentNote.gui.ForiegnPeopleInput.fname) != '' || $F(currentNote.gui.ForiegnPeopleInput.lname) != '' || $F(currentNote.gui.ForiegnPeopleInput.email) != '')) {
                    if (($F(currentNote.gui.ForiegnPeopleInput.fname) == '' || $F(currentNote.gui.ForiegnPeopleInput.lname) == '' || $F(currentNote.gui.ForiegnPeopleInput.email) == '') && $F(currentNote.gui.PeopleInput) == '') {
                      alert( gettext("Please complete this person's First Name, Last Name and Email.") );
                      return;
                    } else if (!($F(currentNote.gui.ForiegnPeopleInput.email).indexOf(".") > 2 && $F(currentNote.gui.ForiegnPeopleInput.email).indexOf("@") > 0)) {
                      alert( gettext("Please enter a valid email for this person.") );
                      return;
                    }
                  } else if (currentNote.typ == 1 && currentNote.id < 0 && $F(currentNote.gui.PeopleInput) == '') {
                    alert( gettext("To continue, please enter this person's information.") );
                    return;
                  }

  
                  currentNote.container.HideAllNotes();
                  currentNote.Save('');
                  var res = currentNote.onsave(currentNote);
                  if(res)
                  {
                      //window.status = '';
                      currentNote.id = res[0];
                  }
                  else
                  {
                      alert("error saving note");
                      currentNote.Cancel();                        
                  }
  //                currentNote.container.ShowAllNotes();
              }
              else
              {
                  alert("onsave must be implemented in order to *actually* save");
                  currentNote.Cancel();                        
              }
          
               
          };
      buttonsDiv.appendChild(newButtonOK);
    }
    
    var newButtonCancel = document.createElement('input');
    newButtonCancel.type='button';
    newButtonCancel.className = 'cancel_button';
    newButtonCancel.value= gettext("Cancel").toUpperCase();;
    newButtonCancel.onclick = function() {
            currentNote.Cancel();            
            
        };
    buttonsDiv.appendChild(newButtonCancel);

    var newButtonDelete = document.createElement('input');
    newButtonDelete.type='button';
    newButtonDelete.className = 'cancel_button';
    newButtonDelete.value= gettext("Delete").toUpperCase();
    newButtonDelete.onclick = function() {
            
            if(currentNote.ondelete) 
            {
                var res = currentNote.ondelete(currentNote);
                if(res)
                {
                    currentNote.container.DeleteNote(currentNote);
                }
                else
                {
                    alert("error deleting note");
                }
            }
            else
            {
                alert("ondelete must be implemented in order to *actually* delete");
            }
        };
    buttonsDiv.appendChild(newButtonDelete);

    editArea.appendChild(buttonsDiv);
    noteArea.appendChild(editArea);
    
    

    /********* DRAG & RESIZE EVENTS **********************/
    this.dragresize.isElement = function(elm)
        {
            if(elm.className == 'zn-area')
            {
                try {
                  this.maxRight = currentNote.container.element.offsetWidth;
                  this.maxBottom = currentNote.container.element.offsetHeight;
                } catch (e) { }
                return true;
            }
        };
        
    this.dragresize.isInside = function(x,y)
        {
          if (!currentNote.container) return;
          cN_offset = currentNote.container.element.cumulativeOffset();
          cN_dimensions = currentNote.container.element.getDimensions();
          //console.log([y, cN_offset[1] + cN_dementions.height + 20]);
          var inside = (x > cN_offset[0] &&
                        x < cN_offset[0] + cN_dimensions.width &&
                        y > cN_offset[1] &&
                        y < cN_offset[1] + cN_dimensions.height + 20 ? true : false)

          if (inside && !currentNote.container.enabled && !currentNote.container.editing) {
            currentNote.container.ShowAllNotes();
          } else if (!inside && currentNote.container.enabled && !currentNote.container.editing  && (currentNote.timer || !currentNote.container.inUse)) {
            
            currentNote.container.HideAllNotes();
//            setTimeout(function() {currentNote.container.HideAllNotes(); },200);
          }
        };

    this.dragresize.isPortal = function(elm,x,y)
        {
            if (currentNote.typ != 2) return;
            
            if( elm.className == 'zn-portal-img' && currentNote.gui.PortalImg) {
              var elm_dimensions = elm.getDimensions();
              if (elm_dimensions.width < currentNote.rect.width || elm_dimensions.height < currentNote.rect.height) {
                currentNote.gui.PortalImg.setStyle({left:'0',top:'0'});
              } else {
                cN_dementions = currentNote.container.element.cumulativeOffset();
            
                var mod_w = elm_dimensions.width / currentNote.rect.width;
                var mod_h = elm_dimensions.height / currentNote.rect.height;
  
                if (mod_w == 1 && mod_h == 1) return;
  
                if (mod_w > 1) mod_w--;
                if (mod_h > 1) mod_h--;
                
                x = (x - cN_dementions[0] - currentNote.rect.left);
                y = (y - cN_dementions[1] - currentNote.rect.top);

                var l = Math.floor((x * -mod_w) + ( (x > currentNote.rect.width / 2 ? mod_w / 100 : -0.015 ) * elm_dimensions.width)) + 'px';
                var t = Math.floor((y * -mod_h) + ( (y > currentNote.rect.height / 2 ? mod_h / 100 : -0.015 ) * elm_dimensions.height)) + 'px';
                currentNote.gui.PortalImg.setStyle({left:l,top:t});
              }
            }
        };
    
    this.dragresize.isHandle = function(elm)
        {
            if(elm.className == 'zn-area')
                return true;
        };
    this.dragresize.ondragfocus = function()
        {
            currentNote.gui.ElementRect.style.cursor = 'move';
        };
    this.dragresize.ondragblur = function()
        {
            currentNote.gui.ElementRect.style.cursor = 'pointer';
        };
    this.dragresize.ondragstart = function()
        {
            currentNote.HighlightTextbox();
            currentNote.PositionNote(1);
            if(currentNote.oldRect == null)
            {
                var r = currentNote.rect;
                currentNote.oldRect = new PhotoNoteRect(r.left,r.top,r.width,r.height);
            }
        };

//    this.dragresize.ondragend = function()
//        {
//          
//        };

    this.dragresize.ondragmove = function()
        {

            currentNote.rect.left = parseInt(this.element.style.left);
            currentNote.rect.top = parseInt(this.element.style.top);
            var w = parseInt(this.element.style.width);
            var h = parseInt(this.element.style.height);

            if ((currentNote.rect.height != h || currentNote.rect.width != w) && currentNote.typ == 2 && currentNote.id == -1 && currentNote.PortalZSize) {
              var new_size = (currentNote.rect.width < 240 && currentNote.rect.height < 180 ? (currentNote.rect.width < 60 && currentNote.rect.height < 60 ? 2 : 4) : 8);
              if (currentNote.PortalZSize != new_size) {
                var success	= function(t){
                  var res_data = json_parse(t.responseText)['sizes']['size'][0];
                  currentNote.gui.PortalImg.src = res_data['source'];
                  currentNote.gui.PortalImg.style.left = '0';
                  currentNote.gui.PortalImg.style.top = '0';
                }
                
                currentNote.PortalZSize = new_size;

                ZAPI.callMethodJSON( 'zooomr.photos.getsizes', {photo_id: currentNote.portalpic, type: currentNote.PortalZSize} , {onSuccess:success})


              }

            }

            currentNote.rect.width = parseInt(this.element.style.width);
            currentNote.rect.height = parseInt(this.element.style.height);

            currentNote.PositionNote(1);
        };
        
    this.dragresize.onmouseover = function()
        {
            currentNote.ShowAllNotes()
        };

    this.dragresize.onmouseout = function()
        {
            currentNote.ShowAllNotes()
        };

    this.dragresize.apply(document);
    
    
    
    
    /* setup the GUI object */
    this.gui.ElementRect = newArea;
    this.gui.ElementNote = noteArea;
    this.gui.EditArea = editArea;
    this.gui.TextBox = newTextbox;
    this.gui.TextTitle = titleArea;
    this.gui.DeleteButton = newButtonDelete;
    
    if (this.typ == 2 && this.portalpic) this.gui.PortalImg = newPortalPhoto;
    if (this.typ == 1 && this.id < 0 && global_nsid) {
      this.gui.PeopleInput = newPeopleInput;
      new Ajax.Autocompleter(newPeopleInput, 'auto_complete_area', '/z/contactlist/?addself=1', {frequency:0.7});

      this.gui.ForiegnPeopleInput = {fname: newPeopleFNameInput,
                                     lname: newPeopleLNameInput,
                                     email: newPeopleEMailInput };      
      
      
      
    }
    /* position the note text below the note area */
    this.PositionNote( this.id < 0 );
    
}

PhotoNote.prototype.PositionNote = function(inFlight)
{
    /* outer most box */
    this.gui.ElementRect.style.left  = this.rect.left + 'px';
    this.gui.ElementRect.style.top  = this.rect.top + 'px';
    this.gui.ElementRect.style.width  = this.rect.width + 'px';
    this.gui.ElementRect.style.height  = this.rect.height + 'px';
    
    // black border
    this.gui.ElementRect.firstChild.style.width  = parseInt(this.gui.ElementRect.style.width) - 2 + 'px';
    this.gui.ElementRect.firstChild.style.height  = parseInt(this.gui.ElementRect.style.height) - 2 + 'px';        
    
    // white border
    this.gui.ElementRect.firstChild.firstChild.style.width  = parseInt(this.gui.ElementRect.style.width) - 4 + 'px';
    this.gui.ElementRect.firstChild.firstChild.style.height  = parseInt(this.gui.ElementRect.style.height) - 4 + 'px';        

    // inner box
    this.gui.ElementRect.firstChild.firstChild.firstChild.style.width  = parseInt(this.gui.ElementRect.style.width) - 4 + 'px';
    this.gui.ElementRect.firstChild.firstChild.firstChild.style.height  = parseInt(this.gui.ElementRect.style.height) - 4 + 'px';        
 
    if (this.container && this.container.editing && this.gui.ElementNote.offsetHeight > this.container.element.offsetHeight - (this.rect.top + (inFlight ? this.YOffsetFlight : this.YOffset) + this.rect.height)) { 
      this.gui.ElementNote.style.left  = this.rect.left + (inFlight ? this.XOffsetFlight : this.XOffset) + 'px';
      this.gui.ElementNote.style.top  = (this.rect.top - (inFlight ? this.YOffsetFlight : this.YOffset) - this.gui.ElementNote.offsetHeight) + 'px';
    } else {
      this.gui.ElementNote.style.left  = this.rect.left + (inFlight ? this.XOffsetFlight : this.XOffset) + 'px';
      this.gui.ElementNote.style.top  = this.rect.top + (inFlight ? this.YOffsetFlight : this.YOffset) + this.rect.height + 'px';

    }

}




/*********************************************************/
/*** Photo Note GUI Object *******************************/
/*********************************************************/
function PhotoNoteGUI()
{
    this.ElementRect = null;
    
    // the note text area...
    this.ElementNote = null;
    this.TextTitle = null;
    this.EditArea = null;
    this.TextBox = null;
    this.PortalImg = null;
    this.PeopleInput = null;
    
    // buttons
    this.DeleteButton = null;
}



/*********************************************************/
/*** Rectangle *******************************************/
/*********************************************************/
function PhotoNoteRect(left,top,width,height)
{
    this.left = left;
    this.top = top;
    this.width = width;
    this.height = height;
}

/* for debugging purposes */
PhotoNoteRect.prototype.toString = function()
{
    return 'left: ' + this.left + ', top: ' + this.top + ', width: ' + this.width + ', height: ' + this.height;
}









// *** Common API Code ***
// (c) 2005 Angus Turnbull http://www.twinhelix.come

var aeOL = [];
function addEvent(o, n, f, l)
{
 var a = 'addEventListener', h = 'on'+n, b = '', s = '';
 if (o[a] && !l) return o[a](n, f, false);
 o._c |= 0;
 if (o[h])
 {
  b = '_f' + o._c++;
  o[b] = o[h];
 }
 s = '_f' + o._c++;
 o[s] = f;
 o[h] = function(e)
 {
  e = e || window.event;
  var r = true;
  if (b) r = o[b](e) != false && r;
  r = o[s](e) != false && r;
  return r;
 };
 aeOL[aeOL.length] = { o: o, h: h };
};
addEvent(window, 'unload', function() {
 for (var i = 0; i < aeOL.length; i++) with (aeOL[i])
 {
  o[h] = null;
  for (var c = 0; o['_f' + c]; c++) o['_f' + c] = null;
 }
});

function cancelEvent(e, c)
{
 e.returnValue = false;
 if (e.preventDefault) e.preventDefault();
 if (c)
 {
  e.cancelBubble = true;
  if (e.stopPropagation) e.stopPropagation();
 }
};

function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      oldonload();
      func();
    }
  }
}



/* Extend the Array object with some useful features 
   http://www.ditchnet.org/wp/?p=8
*/

Array.prototype.clear = function () {
    this.length = 0;
};

Array.prototype.remove = function (element) {
	var result = false;
	var array = [];
	for (var i = 0; i < this.length; i++) {
		if (this[i] == element) {
			result = true;
		} else {
			array.push(this[i]);
		}
	}
	this.clear();
	for (var i = 0; i < array.length; i++) {
		this.push(array[i]);
	}
	array = null;
	return result;
};






// *** Drag and Resize Library Code ***
// (c) 2005 Angus Turnbull http://www.twinhelix.come


function DragResize(myName, config)
{
    var props = {
        myName: myName,                  // Name of the object.
        enabled: true,                   // Global toggle of drag/resize.
        handles: ['tl', 'tm', 'tr',
        'ml', 'mr', 'bl', 'bm', 'br'], // Array of drag handles: top/mid/.
        isElement: null,                 // Function ref to test for an element.
        isInside: null,                 // Function ref to test if we are inside our target element.
        isPortal: null,                 // Function ref to test if we are inside a portal element.
        isHandle: null,                  // Function ref to test for move handle.
        element: null,                   // The currently selected element.
        dragging: null,                  // Active handle reference of the element.
        minWidth: 10, minHeight: 10,     // Minimum pixel size of elements.
        minLeft: 0, maxRight: 9999,      // Bounding box area.
        minTop: 0, maxBottom: 9999,
        zIndex: 1,                       // The highest Z-Index yet allocated.
        mouseX: 0, mouseY: 0,            // Current mouse position, recorded live.
        lastMouseX: 0, lastMouseY: 0,    // Last processed mouse positions.
        mOffX: 0, mOffY: 0,              // A known offset between position & mouse.
        elmX: 0, elmY: 0,                // Element position.
        elmW: 0, elmH: 0,                // Element size.
        allowBlur: true,                 // Whether to allow automatic blur onclick.
        ondragfocus: null,               // Event handler functions.
        ondragstart: null,
        ondragmove: null,
        ondragend: null,
        ondragblur: null
    };

    for (var p in props)
    {
        this[p] = (typeof config[p] == 'undefined') ? props[p] : config[p];
    }
};


DragResize.prototype.apply = function(node)
{
    // Adds object event handlers to the specified DOM node.

    var obj = this;
    addEvent(node, 'mousedown', function(e) { obj.mouseDown(e) } );
    addEvent(node, 'mousemove', function(e) { obj.mouseMove(e) } );
    addEvent(node, 'mouseup', function(e) { obj.mouseUp(e) } );
};


DragResize.prototype.handleSet = function(elm, show) { with (this)
{
    // Either creates, shows or hides the resize handles within an element.

    // If we're showing them, and no handles have been created, create 4 new ones.
    if (!elm._handle_tr)
    {
        for (var h = 0; h < handles.length; h++)
        {
            // Create 4 news divs, assign each a generic + specific class.
            var hDiv = document.createElement('div');
            hDiv.className = myName + ' ' +  myName + '-' + handles[h];
            elm['_handle_' + handles[h]] = elm.appendChild(hDiv);
        }
    }

    // We now have handles. Find them all and show/hide.
    for (var h = 0; h < handles.length; h++)
    {
        elm['_handle_' + handles[h]].style.visibility = show ? 'inherit' : 'hidden';
    }
}};


DragResize.prototype.select = function(newElement) { with (this)
{
    // Selects an element for dragging.

    if (!document.getElementById || !enabled) return;

    // Activate and record our new dragging element.
    if (newElement && (newElement != element) && enabled)
    {
        element = newElement;
        // Elevate it and give it resize handles.
        element.style.zIndex = ++zIndex;
        handleSet(element, true);
        // Record element attributes for mouseMove().
        elmX = parseInt(element.style.left);
        elmY = parseInt(element.style.top);
        elmW = element.offsetWidth;
        elmH = element.offsetHeight;
        if (ondragfocus) this.ondragfocus();
    //window.status = 'start elmX=' + element.className;
        
    }
}};


DragResize.prototype.deselect = function(keepHandles) { with (this)
{
    // Immediately stops dragging an element. If 'keepHandles' is false, this
    // remove the handles from the element and clears the element flag,
    // completely resetting the .

    if (!document.getElementById || !enabled) return;

    if (!keepHandles)
    {
        if (ondragblur) this.ondragblur();
        handleSet(element, false);
        element = null;
    }

    dragging = null;
    mOffX = 0;
    mOffY = 0;
}};


DragResize.prototype.mouseDown = function(e) { with (this)
{
    //window.status = 'mouseDown!';
    // Suitable elements are selected for drag/resize on mousedown.
    // We also initialise the resize boxes, and drag parameters like mouse position etc.
    if (!document.getElementById || !enabled) return true;

    var elm = e.target || e.srcElement,
    newElement = null,
    newHandle = null,
    hRE = new RegExp(myName + '-([trmbl]{2})', '');

    while (elm)
    {
        // Loop up the DOM looking for matching elements. Remember one if found.
        if (elm.className)
        {
        if (!newHandle && (hRE.test(elm.className) || isHandle(elm))) newHandle = elm;
        if (isElement(elm)) { newElement = elm; break }
        }
        elm = elm.parentNode;
    }

    // If this isn't on the last dragged element, call deselect(false),
    // which will hide its handles and clear element.
    if (element && (element != newElement) && allowBlur) deselect(false);

    // If we have a new matching element, call select().
    if (newElement && (!element || (newElement == element)))
    {
        // Stop mouse selections.
        cancelEvent(e);
        select(newElement, newHandle);
        dragging = newHandle;
        if (dragging && ondragstart) this.ondragstart();
    }
}};


DragResize.prototype.mouseMove = function(e) { with (this)
{
    //console.log(e);

    // This continually offsets the dragged element by the difference between the
    // last recorded mouse position (mouseX/Y) and the current mouse position.
    if (!document.getElementById) return true;

    // We always record the current mouse position.
    mouseX = e.pageX || e.clientX + document.documentElement.scrollLeft;
    mouseY = e.pageY || e.clientY + document.documentElement.scrollTop;
    //console.log([mouseX, mouseY]);
    
    // Record the relative mouse movement, in case we're dragging.
    // Add any previously stored&ignored offset to the calculations.
    var diffX = mouseX - lastMouseX + mOffX;
    var diffY = mouseY - lastMouseY + mOffY;
    mOffX = mOffY = 0;
    // Update last processed mouse positions.
    lastMouseX = mouseX;
    lastMouseY = mouseY;

    //Check if we're inside target...
    isInside(mouseX,mouseY);

    if (isPortal) this.isPortal(e.target || e.srcElement,mouseX,mouseY);

    // That's all we do if we're not dragging anything.
    if (!dragging) return true;

    // Establish which handle is being dragged -- retrieve handle name from className.
    var hClass = dragging && dragging.className &&
    dragging.className.match(new RegExp(myName + '-([tmblr]{2})')) ? RegExp.$1 : '';

    // If the hClass is one of the resize handles, resize one or two dimensions.
    // Bounds checking is the hard bit -- basically for each edge, check that the
    // element doesn't go under minimum size, and doesn't go beyond its boundary.
    var rs = 0, dY = diffY, dX = diffX;
    if (hClass.indexOf('t') >= 0)
    {
        rs = 1;
        if (elmH - dY < minHeight) mOffY = (dY - (diffY = elmH - minHeight));
        else if (elmY + dY < minTop) mOffY = (dY - (diffY = minTop - elmY));
        elmY += diffY;
        elmH -= diffY;
    }
    if (hClass.indexOf('b') >= 0)
    {
        rs = 1;
        if (elmH + dY < minHeight) mOffY = (dY - (diffY = minHeight - elmH));
        else if (elmY + elmH + dY > maxBottom) mOffY = (dY - (diffY = maxBottom - elmY - elmH));
        elmH += diffY;
    }
    if (hClass.indexOf('l') >= 0)
    {
        rs = 1;
        if (elmW - dX < minWidth) mOffX = (dX - (diffX = elmW - minWidth));
        else if (elmX + dX < minLeft) mOffX = (dX - (diffX = minLeft - elmX));
        elmX += diffX;
        elmW -= diffX;
    }
    if (hClass.indexOf('r') >= 0)
    {
        rs = 1;
        if (elmW + dX < minWidth) mOffX = (dX - (diffX = minWidth - elmW));
        else if (elmX + elmW + dX > maxRight) mOffX = (dX - (diffX = maxRight - elmX - elmW));
        elmW += diffX;
        window.status = 'diffX:' + diffX;
    }
    // If 'rs' isn't set, we must be dragging the whole element, so move that.
    if (dragging && !rs)
    {
        // Bounds check left-right...
        if (elmX + dX < minLeft) mOffX = (dX - (diffX = minLeft - elmX));
        else if (elmX + elmW + dX > maxRight) mOffX = (dX - (diffX = maxRight - elmX - elmW));
        // ...and up-down.
        if (elmY + dY < minTop) mOffY = (dY - (diffY = minTop - elmY));
        else if (elmY + elmH + dY > maxBottom) mOffY = (dY - (diffY = maxBottom - elmY - elmH));
        //window.status = 'diffX-' + diffX + ' , elmX-' + elmX;
        elmX += diffX;
        elmY += diffY;
    }
    
    //window.status = 'elmX=' + elmX;
    // Assign new info back to the element, with minimum dimensions.
    with (element.style)
    {
        left =   elmX + 'px';
        width =  elmW + 'px';
        top =    elmY + 'px';
        height = elmH + 'px';
    }

    // Evil, dirty, hackish Opera select-as-you-drag fix.
    if (window.opera && document.documentElement)
    {
        var oDF = document.getElementById('op-drag-fix');
        if (!oDF)
        {
            var oDF = document.createElement('input');
            oDF.id = 'op-drag-fix';
            oDF.style.display = 'none';
            document.body.appendChild(oDF);
        }
        oDF.focus();
    }

    if (ondragmove) this.ondragmove();

    // Stop a normal drag event.
    cancelEvent(e);
}};


DragResize.prototype.mouseUp = function(e) { with (this)
{
    // On mouseup, stop dragging, but don't reset handler visibility.
    if (!document.getElementById || !enabled) return;

    if (ondragend) this.ondragend();
    deselect(true);
}};



