// fix for missing document.activeElement in firefox2 and other browsers
if(typeof document.activeElement == 'undefined') {
    function _dom_trackActiveElement(evt) {
      if (evt && evt.target) {
        document.activeElement =
            evt.target == document ? null : evt.target;
      }
    }

    function _dom_trackActiveElementLost(evt) {
      document.activeElement = null;
      }

    if (document.addEventListener) {

      document.addEventListener("focus",_dom_trackActiveElement,true);
      document.addEventListener("blur",_dom_trackActiveElementLost,true);
    }
}

//================================================
// Notespanel
//================================================
function NotesPanel(id) { this.__construct(id); };
    NotesPanel.prototype.visible = true;
    NotesPanel.prototype.element = null;
    NotesPanel.prototype.show = function() {
        this.visible = true;
        this.element.style.left = '0px';
    };
    NotesPanel.prototype.hide = function() {
        this.visible = false;

        this.element.style.left = '-'+(this.element.clientWidth-8)+'px';
    };
    NotesPanel.prototype.__construct = function(id) {

        Notes.visibilityCallback = function() {document.getElementById('notes_visibility').checked = Notes.areVisible()};

        // panel element
        var box = document.createElement('div');
        box.id = id;
        box.style.position = 'fixed';
        box.style.left = '0px';
        box.className = 'notes-panel';

        // title
        var title = document.createElement('div');
        title.innerHTML = '<a href="/service/notizen">Notizen</a>';
        title.className = 'notes-title';
        box.appendChild(title);

        // show/hide checkbox
        var checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        checkbox.id = 'notes_visibility';
        checkbox.checked = Notes.areVisible();
        checkbox.onchange = function() {Notes.toggleVisibility();};
        box.appendChild(checkbox);
        var label = document.createElement('label');
        //label.for = 'notes_visibility';
        label.innerHTML = ' Anzeigen';
        box.appendChild(label);

        // tag filter
        title = document.createElement('div');
        title.innerHTML = 'Tags';
        title.className = 'notes-title';
        box.appendChild(title);

        var input = document.createElement('input');
        input.type = 'text';
        input.className = 'notes-filter';
        input.onkeyup = function() {Notes.applyTagFilter(this.value)};
        box.appendChild(input);

        // autor filter
        title = document.createElement('div');
        title.className = 'notes-title';
        title.innerHTML = 'Autoren';
        box.appendChild(title);

        input = document.createElement('input');
        input.type = 'text';
        input.className = 'notes-filter';
        input.onkeyup = function() {Notes.applyAuthorFilter(this.value)};
        box.appendChild(input);

        // add element to document
        document.getElementById('bgo').appendChild(box);


        this.element = box;
        var me = this;
        this.element.onmouseover = function() { me.show(); };
        this.element.onmouseout  = function() { me.hide(); };

        this.hide();
    };


//================================================
// Notes manager singleton
//================================================
function NotesManager(uri){ this.__construct(uri); };

    NotesManager.prototype.instance = null;

	NotesManager.prototype.visible = true;

	/**
	* filter
	*/
	NotesManager.prototype.activeTagFilter = null;
	NotesManager.prototype.activeAuthorFilter = null;

    /**
    * URI
    */
    NotesManager.prototype.URI    = "";

    /**
    * identity
    */
    NotesManager.prototype.identity = null;

    /**
    * list of all existing notes
    */
    NotesManager.prototype.notes  = [];

    /**
    * active object
    */
	NotesManager.prototype.layerCounter = 1;
	NotesManager.prototype.focusObject = null;

    NotesManager.prototype.activeObject = null;
    /**
    * active object action
    */
    NotesManager.prototype.activeAction = null;

    /**
    * active object offset
    */
    NotesManager.prototype.activeOffset = null;

    /**
    * offset element
    */
    NotesManager.prototype.offset = [0, 0];

    /**
    * mouse coordinates
    */
    NotesManager.prototype.mouseOffset = [0,0];

    /**
    * key timer
    */
    NotesManager.prototype.keyTimer = 0;

    /**
    * author list
    */
    NotesManager.prototype.authors = [];

	/**
	* parse tags into an array
	*/
	NotesManager.prototype.parseTags = function(tags) {
		if(typeof tags == 'undefined') {
			return [];
		}

		if(typeof tags == 'string') {
			tags = tags.split(",");
		}

		for(var i=0;i<tags.length;i++) {
			tags[i] = tags[i].replace (/^\s+/, '').replace (/\s+$/, '');
		}

		return tags;
	};

    /**
    * register a note with the manager
    */
    NotesManager.prototype.register  = function(note) {
		if(note.databaseId > 0) {
            if((this.activeTagFilter && !note.hasTags(this.activeTagFilter)) || (this.activeAuthorFilter && !note.hasAuthor(this.activeAuthorFilter))) {
                note.hide();
            }
        } else {
            if(!this.visible) {
                this.toggleVisibility();
            }
        }

        this.notes[note.id] = note;
    };

    /**
    * unregister a note from the manager
    */
    NotesManager.prototype.unregister = function(note) {
        if(typeof this.notes[note.id] != 'undefined') {
            delete this.notes[note.id];
        }
    };

    /**
    * return the note with the specified id
    */
    NotesManager.prototype.pool = function(id) {
        if(typeof this.notes[id] != 'undefined') {
            return this.notes[id];
        }

        return null;
    };

	/**
	* focus a note
	*/
	NotesManager.prototype.focus = function(note) {
		if(note != this.focusObject) {
			this.focusObject = note;
			this.focusObject.element.style.zIndex = this.layerCounter++;
		}
	};

	/**
	* unfocus note
	*/

    /**
    * start resizing a note
    */
    NotesManager.prototype.resize = function(note, offsetX, offsetY) {
		this.focus(note);
		this.activeObject = note;
        this.activeAction = 'resize';
        this.activeOffset = [offsetX,offsetY];
    };

    /**
    * start dragging a note
    */
    NotesManager.prototype.drag = function(note, offsetX, offsetY) {
       	this.focus(note);
		this.activeObject = note;
        this.activeAction = 'drag';
        this.activeOffset = [offsetX, offsetY];
    };

    /**
    * handles mouse movement and mouse events
    */
    NotesManager.prototype.__handleKeyEvent = function(type, event) {
        if(event.keyCode == 110 || event.which == 110) {
            if(document.activeElement &&
                (document.activeElement.tagName == 'INPUT' || document.activeElement.tagName == 'TEXTAREA')) {
                return true;
            }

            var time = (new Date()).getTime();
            if(time - this.keyTimer < 1000) {
                if(!this.areVisible()) {
                    this.toggleVisibility();
                }

                (new Note(0,0,'')).startDragging();
                this.keyTimer = 0;
            } else {
                this.keyTimer = time;
            }
        }
        return true;
    };

    /**
    * handles mouse movement and mouse events
    */
    NotesManager.prototype.__handleMouseEvent = function(type, event) {
        // get coordinates
        var x = 0;
        var y = 0;
        if(event.pageX) {
            x = event.pageX;
            y = event.pageY;
        } else {
            x = event.clientX + document.body.scrollLeft;
            y = event.clientY + document.body.scrollTop;
        }
        this.mouseOffset = [x,y];

        if(this.activeAction == null || this.activeObject == null || this.activeObject == null) {
            return;
        }

        // handle mouse up
        if(type == 'up') {
            this.activeObject.save();
			this.activeObject = null;
            this.activeAction = null;
        // handle movement
        } else if(type == 'move') {
            if(this.activeAction == 'drag') {
                this.activeObject.setPosition(x-this.activeOffset[0]-this.offset[0],y-this.activeOffset[1]-this.offset[1]);
            } else if(this.activeAction == 'resize') {
                var xo = this.activeObject.element.offsetLeft;
                var yo = this.activeObject.element.offsetTop;

                this.activeObject.setSize(x - xo + this.activeOffset[0], y - yo + this.activeOffset[1]);
            }
        }

        return;
    };

	/**
	* checks if notes are visible
	*/
	NotesManager.prototype.areVisible = function() {
		return this.visible;
	};

	/**
	* shows all notes
	*/
	NotesManager.prototype.show = function() {
		this.visible = true;
		document.getElementById('notes_offset').style.display = 'block';
        document.getElementById('notes_offset').style.height = '0px';

        // update offset
        var offsetElement = document.getElementById('notes_offset');
        this.offset = [offsetElement.offsetLeft, offsetElement.offsetTop];

		bgTools.setCookie('notes_visibility', this.visible, 30 , '/');
        if(this.visibilityCallback) {
            this.visibilityCallback();
        }
	};

	/**
	* hides all notes
	*/
	NotesManager.prototype.hide = function() {
		this.visible = false;
		document.getElementById('notes_offset').style.display = 'none';

		bgTools.setCookie('notes_visibility', this.visible, 30, '/');
        if(this.visibilityCallback) {
            this.visibilityCallback();
        }
	};

	/**
	* toggle visibility of all notes
	*/
	NotesManager.prototype.toggleVisibility = function() {
		if(!this.areVisible()) {
			this.show();
		} else {
			this.hide();
		}
	};

	/**
	* return active tag filter
	*/
	NotesManager.prototype.getTagFilter = function() {
		var tags = this.activeTagFilter;
		if(tags == null || typeof tags == 'undefined') {
			return '';
		}
		var res = '';
		for(var i=0;i<tags.length;i++) {
			res += (res != '' ? ',':'') + tags[i];
		}
		return res;
	};

    /**
    * return active tag filter
    */
    NotesManager.prototype.getAuthorFilter = function() {
        var authors = this.activeAuthorFilter;
        if(authors == null || typeof authors == 'undefined') {
            return '';
        }
        var res = '';
        for(var i=0;i<authors.length;i++) {
            res += (res != '' ? ',':'') + authors[i];
        }
        return res;
    };

    /**
    * apply tag filter
    */
    NotesManager.prototype.applyTagFilter = function(tags) {
        this.applyFilter(tags, this.activeAuthorFilter);
    };

    /**
    * apply author filter
    */
    NotesManager.prototype.applyAuthorFilter = function(authors) {
        this.applyFilter(this.activeTagFilter, authors);
    };

	/**
	* filter notes by tags
	*/
	NotesManager.prototype.applyFilter = function(tags, authors) {
		// set tag filter
		if(typeof tags == 'undefined' || tags == '' || tags == null) {
			this.activeTagFilter = null;
		} else {
            this.activeTagFilter = this.parseTags(tags);
		}
        // set author filter
        if(typeof authors == 'undefined' || authors == '' || authors == null) {
            this.activeAuthorFilter = null;
        } else {
            this.activeAuthorFilter = this.parseTags(authors);
        }

		// apply filter
		for(var i=0;i<this.notes.length;i++) {
            if(typeof this.notes[i] == 'undefined') {continue;};

			if((this.activeTagFilter && !this.notes[i].hasTags(this.activeTagFilter)) ||
            (this.activeAuthorFilter && !this.notes[i].hasAuthor(this.activeAuthorFilter))) {
				this.notes[i].hide();
			} else {
				this.notes[i].show();
			}
		}

		bgTools.setCookie('notes_tag_filter', this.getTagFilter(), 30 , '/');
        bgTools.setCookie('notes_author_filter', this.getAuthorFilter(), 30 , '/');
	};

    /**
    * add an author
    */
    NotesManager.prototype.setIdentity = function(id, name, writable) {
        if(this.getAuthor(id)) {
            return;
        }
        this.identity = {id: id, name: name, writable: writable};
        this.authors.push(this.identity);
    };

    /**
    * add an author
    */
    NotesManager.prototype.addAuthor = function(id, name, writable) {
        if(this.getAuthor(id)) {
            return;
        }
        this.authors.push({id: id, name: name, writable: writable});
    };

    /**
    * returns an author by id
    */
    NotesManager.prototype.getAuthor = function(id) {
        for(var i=0;i<this.authors.length;i++) {
            if(this.authors[i].id == id) {
                return this.authors[i];
            }
        }
        return null;
    };

    /**
    * constructor
    */
    NotesManager.prototype.__construct = function(uri) {
        this.URI = uri;

        moveHandler     = function(event) { Notes.__handleMouseEvent('move',event); return false;   };
        upHandler       = function(event) { Notes.__handleMouseEvent('up',event);   return false;   };
        keyHandler      = function(event) { Notes.__handleKeyEvent('press',event);  return true;    };

        if(window.addEventListener) {
            document.addEventListener('mousemove',  moveHandler,    false);
            document.addEventListener('mouseup',    upHandler,      false);
            document.addEventListener('keypress',   keyHandler,     false);
        } else {
            document.attachEvent('onmousemove',     moveHandler);
            document.attachEvent('onmouseup',       upHandler);
            document.attachEvent('onkeypress',      keyHandler);
        }

        var tags    = bgTools.getCookie('notes_tag_filter');
        var authors = bgTools.getCookie('notes_author_filter');
        if(tags !== null || authors !== null) {
            this.applyFilter(tags, authors);
        }

        var visibility = bgTools.getCookie('notes_visibility');
        if(visibility !== null && visibility == 'false') {
            this.hide();
        } else {
            this.show();
        }
    };

//================================================

//================================================
// Notes object
//================================================
function Note(x, y, text, tags, width, height, databaseId, timestamp, identityId) {
    if (typeof Notes == 'undefined') {
        alert('Sie müssen sich erst einloggen, um Notizen anzulegen!');
        throw {};
    }

    // timestamp
    if(typeof timestamp != 'undefined') {
        this.timestamp = timestamp;
    }

    // owner information
    if(typeof identityId != 'undefined') {
        this.identityId = identityId;
    } else {
        this.identityId = Notes.identity.id;
    }

    this.author     = Notes.getAuthor(this.identityId);
    // check that a valid author was found
    if(this.author === null) {
        return false;
    }

    // object id
    this.id      = Note.prototype.counter++;

    // database id
    if(typeof databaseId != 'undefined') {
        this.databaseId = databaseId;
    }

    // window coordinates
    if(typeof x != 'undefined') {
        this.x = parseInt(x,10);
    }
    if(typeof y != 'undefined') {
        this.y = parseInt(y,10);
    }

    // note size
    if(typeof width != 'undefined') {
        this.width  = parseInt(width, 10);
        this.height = parseInt(height, 10);
    }

    // content
    if(typeof text != 'undefined') {
        this.text = Base64.decode(text);
    }

    // create dom element
    this.element                    = document.createElement('div');
    this.element.id                 = 'note'+this.id;
    this.element.className          = 'note' + (this.identityId == Notes.identity.id ? '' : ' note-shared');
    this.element.style.position     = 'absolute';
    this.element.style.overflow     = 'hidden';
    this.setPosition(this.x,this.y);

    var id = this.id;

    // create title
    this.title = document.createElement('div');
    this.title.className = 'note-title';

    this.menu = document.createElement('div');
    this.menu.className = 'note-menu';

    this.closer = document.createElement('div');
    this.closer.className = 'note-close';

    this.title.appendChild(this.closer);
    this.title.appendChild(this.menu);

    this.element.appendChild(this.title);

	this.infoTags = document.createElement('div');
	this.infoTags.className = 'note-infoTags';
	this.infoTags.innerHTML = '<b>Tags:</b> ';

	this.infoTagsContent = document.createElement('span');
	this.infoTags.appendChild(this.infoTagsContent);

	this.infoTagsInput = document.createElement('input');
	this.infoTagsInput.style.display = 'none';
	this.infoTags.appendChild(this.infoTagsInput);

	this.element.appendChild(this.infoTags);

    // create content
    this.content = document.createElement('div');
    this.content.className = 'note-content';

    this.element.appendChild(this.content);

    // create input
    this.input = document.createElement('textarea');

    this.element.appendChild(this.input);

    // create footer
    this.footer = document.createElement('div');
    this.footer.className = 'note-footer';

    this.resizer = document.createElement('div');
    this.resizer.className = 'note-resize';

    this.element.appendChild(this.footer);
    this.element.appendChild(this.resizer);

    // set timestamp string
    this.footer.innerHTML = this.timestamp;

    // show nickname if this note was created by a different user
    if(this.identityId != Notes.identity.id) {
        this.menu.innerHTML     = '<b>Von:</b> ' + this.author.name;
    }

    this.input.style.display        = 'none';

    this.input.style.overflow       = 'auto';
    this.content.style.overflow     = 'auto';

	focusLostHandler	= function() {var n = Notes.pool(id); if(n) {n.__handleEvent('focuslost');} return false; };
	clickHandler         = function(event) { var n = Notes.pool(id); if(n) {n.__handleEvent('click',event);}      return false; };
	moveHandler         = function(event) { var n = Notes.pool(id); if(n) {n.__handleEvent('move',event);}      return false; };
    closeHandler        = function(event) { var n = Notes.pool(id); if(n) {n.__handleEvent('close',event);}     return false; };
    resizeHandler       = function(event) { var n = Notes.pool(id); if(n) {n.__handleEvent('resize',event);}    return false; };
    dblclickHandler     = function(event) { var n = Notes.pool(id); if(n) {n.__handleEvent('dblclick',event);}  return false; };

	this.input.onblur               = focusLostHandler;
	this.infoTagsInput.onblur       = focusLostHandler;

    if(window.addEventListener) {
		this.element.onmousedown	= clickHandler;
        this.title.onmousedown      = moveHandler;
        this.closer.onmousedown     = closeHandler;
        this.resizer.onmousedown    = resizeHandler;
        this.element.ondblclick     = dblclickHandler;
    } else {
		this.element.attachEvent('onmousedown', clickHandler);
        this.title.attachEvent('onmousedown',   moveHandler);
        this.closer.attachEvent('onmousedown',  closeHandler);
        this.resizer.attachEvent('onmousedown', resizeHandler);
        this.element.attachEvent('ondblclick',  dblclickHandler);
    }

    this.updateText();

	// tags
	if(typeof tags != 'undefined') {
		this.setTags(Base64.decode(tags));
	}

    // add note to document
    document.getElementById('notes_offset').appendChild(this.element);

    this.setSize(this.width,this.height);

    // register note
    Notes.register(this);
};

    /**
    * author of the note
    */
    Note.prototype.author = null;

    Note.prototype.counter = 0;

    /**
	* tags
	*/
	Note.prototype.tags = '';

    /**
    * edit mode flag
    */
    Note.prototype.editMode = '';

    /**
    * timestamp
    */
    Note.prototype.timestamp = "-";

    /**
    * dom element
    */
    Note.prototype.element = null;

    /**
    * owner information
    */
    Note.prototype.identityId = 0;

    /**
    * object id
    */
    Note.prototype.id      = 0;

    /**
    * database id
    */
    Note.prototype.databaseId = 0;

    /**
    * window coordinates
    */
    Note.prototype.x = 0;
    Note.prototype.y = 0;

    /**
    * note size
    */
    Note.prototype.width  = 200;
    Note.prototype.height = 160;

    /**
    * content
    */
    Note.prototype.text = '';

    /**
    * set the notes position
    */
    Note.prototype.setPosition = function(x,y) {
        this.x = x;
        this.y = y;

        this.element.style.left         = (this.x) + 'px';
        this.element.style.top          = (this.y) + 'px';
    };

   	/**
	* updates the tags
	*/
	Note.prototype.setTags = function(tags) {
		// only accept strings
		if(typeof tags != 'string') {
			return;
		}

		this.infoTagsContent.innerHTML = tags;

		this.tags = Notes.parseTags(tags);
	};

    /**
    * sets the notes size
    */
    Note.prototype.setSize = function(width, height) {
        if(width < 100) {
            width = 100;
        }
        if(height < 40) {
            height = 40;
        }

        this.width = width;
        this.height = height;

        this.element.style.width    = width + 'px';
        this.element.style.height   = height + 'px';

        this.resizer.style.left     = (this.element.offsetWidth - 11) + 'px';
        this.resizer.style.top      = (this.element.offsetHeight - 11) + 'px';

        this.footer.style.top       = (this.element.offsetHeight - 15) + 'px';

        this.closer.style.left      = (this.element.offsetWidth - 11) + 'px';

        this.input.style.height     = (this.element.offsetHeight - 53) + 'px';
        this.content.style.height   = (this.element.offsetHeight - 53) + 'px';

		this.infoTagsInput.style.width = (this.element.offsetWidth - 65) + 'px'
    };

    /**
    * destructor
    */
    Note.prototype.__destruct = function() {
        // remove dom element
        document.getElementById('notes_offset').removeChild(this.element);

        // unregister note
        Notes.unregister(this);
    };

    /**
     * close this note
     */
    Note.prototype.close = function() {
        if(confirm('Wollen Sie diese Notiz wirklich schliessen?')) {
            if(this.isWritable()) {
                this.save('delete');
            }
            this.__destruct();
        }
    };

    /**
    * start dragging
    */
    Note.prototype.startDragging = function() {
        this.setPosition(Notes.mouseOffset[0]-Notes.offset[0], Notes.mouseOffset[1]-Notes.offset[1]);
        Notes.drag(this,0,0);
    };

    /**
    * set timestamp
    */
    Note.prototype.setTimestamp = function(timestamp) {
        this.timestamp = timestamp;
        this.footer.innerHTML = timestamp;
    };

    /**
    * save the note
    */
    Note.prototype.save = function(action) {
        if(!this.isWritable()) {
            return;
        }

        if(typeof action == 'undefined') {
            action = 'save';
        }
        var data = this.databaseId + "\n";
        data    += action + "\n";
        if(action == 'save') {
			// serialize tags
			var tags = '';
			for(var i=0;i<this.tags.length;i++) {
				tags += (tags != '' ? ',':'') + this.tags[i];
			}

            data    += Base64.encode(this.text) + "\n";         
            
            data    += this.x       + "," + this.y      + "\n";
            data    += this.width   + "," + this.height + "\n";
			data	+= Base64.encode(tags) + "\n";
            data    += Base64.encode(Notes.URI);
        }

        var xrequest = null;
        if (typeof XMLHttpRequest != 'undefined') {
            xrequest = new XMLHttpRequest();
        }
        if (window.ActiveXObject) {
            if (navigator.userAgent.toLowerCase().indexOf("msie 5") != -1) {
                xrequest = new ActiveXObject("Microsoft.XMLHTTP");
            } else {
                xrequest = new ActiveXObject("Msxml2.XMLHTTP");
            }
        }

        var c = this.id;
        xrequest.onreadystatechange = function() {
            if(xrequest.readyState == 4) {
                if(action == 'delete') {
                    return;
                }

                var lines = xrequest.responseText.split("\n");
                var id = parseInt(lines[0]);
                var note = Notes.pool(c);

                if(!isNaN(id)) {
                    note.databaseId = id;
                    note.setTimestamp(lines[1]);
                } else {
                    //note.__destruct();
                }
            }
        };
        xrequest.open("POST",'/notes/',true);
        xrequest.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
        xrequest.send(data);
    };

    /**
    * update the displayed text
    */
    Note.prototype.updateText = function() {
        var text = this.text;
        text = text.replace(/</g,'&lt;');
        text = text.replace(/>/g,'&gt;');             
        text = text.replace(/\n/g,'<br />');
        
        text = text.replace(/\[(.*?)\s+(.*?)\]/g,'<a href="$1">$2</a>'); 
        
        
        this.content.innerHTML = text;
    };

    /**
    * checks if this note is owned by one of the specified authors
    */
    Note.prototype.hasAuthor = function(authors) {
        if(!this.author) {
            return false;
        }

        var j = 0;
        for(var i = 0; i<authors.length; i++) {
            // ignore empty authors
            if(authors[i] == '') {
                continue;
            }
            // match using lowercase and first characters
            if(this.author.name.toLowerCase().indexOf(authors[i].toLowerCase()) === 0) {
                return true;
            }
        }

        return false;
    };

	/**
	* checks if this note has one or of the specified tags
	*/
	Note.prototype.hasTags = function(tags) {
		var j = 0;
		for(var i = 0; i<tags.length; i++) {
			for(j = 0; j<this.tags.length; j++) {
                // ignore empty tags
                if(tags[i] == '') {
                    continue;
                }
                // match using lowercase and first characters
				if(this.tags[j].toLowerCase().indexOf(tags[i].toLowerCase()) === 0) {
					return true;
				}
			}
		}

		return false;
	};

	/**
	* toggle visibility
	*/
	Note.prototype.toggleVisiblity = function() {
		if(this.isVisible()) {
			this.hide();
		} else {
			this.show();
		}
	};

	/**
	* hide note
	*/
	Note.prototype.hide = function() {
		this.element.style.display = 'none';
	};

	/**
	* show note
	*/
	Note.prototype.show = function() {
		this.element.style.display = 'block';
	};

	/**
	* check if note is visible
	*/
	Note.prototype.isVisible = function() {
		if(this.element.style.display == 'none') {
			return false;
		}
		return true;
	};

    /**
    * check if this note is writable
    */
    Note.prototype.isWritable = function() {
        if(this.author !== null && !this.author.writable) {
            return false;
        }
        return true;
    };

    /**
    * switch edit mode
    */
    Note.prototype.toggleEditMode = function(data) {
        if(!this.isWritable()) {
            return;
        }

		if(this.editMode != '') {
			if(this.editMode == 'text') {
                
				this.text                   = this.input.value;                
            	this.input.style.display    = 'none';
            	this.content.style.display  = 'block';

            	this.updateText();
			} else if(this.editMode == 'tags') {
				this.setTags(this.infoTagsInput.value);
				this.infoTagsInput.style.display = 'none';
				this.infoTagsContent.style.display = '';
			}
			this.editMode = '';
			this.save();
		}

		if(data != '') {
			if(data == 'text') {
	    		this.content.style.display  = 'none';
	        	this.input.value            = this.text;
	        	this.input.style.display    = 'block';
	        	this.input.focus();
	    	} else if(data == 'tags') {
				this.infoTagsInput.value 	= this.infoTagsContent.innerHTML;
				this.infoTagsInput.style.display = '';
				this.infoTagsContent.style.display = 'none';
				this.infoTagsInput.focus();
			}
			this.editMode = data;
		}
    };

    /**
    * event handler
    */
    Note.prototype.__handleEvent = function(type, event) {
        var target = (typeof event == 'undefined' ? null : ((typeof event.target != 'undefined') ? event.target : event.srcElement));

		if(type == 'focuslost') {
			this.toggleEditMode();
		} else if(type == 'dblclick') {
            var data = (target == this.infoTagsContent || target == this.infoTags ? 'tags' : 'text');
			this.toggleEditMode(data);
		} else if(type == 'click') {
			Notes.focus(this);
        } else if(type == 'move' || type == 'resize' || type== 'close') {
            var x = 0;
            var y = 0;
            if(event.pageX) {
                x = event.pageX;
                y = event.pageY;
            } else {
                x = event.clientX + document.body.scrollLeft;
                y = event.clientY + document.body.scrollTop;
            }
            x -= this.element.offsetLeft;
            y -= this.element.offsetTop;

            var xr = this.element.offsetWidth - x;
            var yr = this.element.offsetHeight - y;

            if(type == 'move' && target == this.menu) {
                Notes.drag(this,x - Notes.offset[0],y - Notes.offset[1]);
            } else if (type == 'close' && target == this.closer) {
                this.close();
            } else if (type == 'resize' && target == this.resizer) {
                Notes.resize(this, xr, yr);
            }

        }
    };
//================================================