// Copyright (C) 2009 3banana Inc.
// 3banana is hiring! email us at aschobel+kthx@3banana.com

if(!this.JSON){JSON={};}
(function(){function f(n){return n<10?'0'+n:n;}
if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return this.getUTCFullYear()+'-'+
f(this.getUTCMonth()+1)+'-'+
f(this.getUTCDate())+'T'+
f(this.getUTCHours())+':'+
f(this.getUTCMinutes())+':'+
f(this.getUTCSeconds())+'Z';};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf();};}
var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4);})+'"':'"'+string+'"';}
function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key);}
if(typeof rep==='function'){value=rep.call(holder,key,value);}
switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null';}
gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||'null';}
v=partial.length===0?'[]':gap?'[\n'+gap+
partial.join(',\n'+gap)+'\n'+
mind+']':'['+partial.join(',')+']';gap=mind;return v;}
if(rep&&typeof rep==='object'){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==='string'){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}
v=partial.length===0?'{}':gap?'{\n'+gap+partial.join(',\n'+gap)+'\n'+
mind+'}':'{'+partial.join(',')+'}';gap=mind;return v;}}
if(typeof JSON.stringify!=='function'){JSON.stringify=function(value,replacer,space){var i;gap='';indent='';if(typeof space==='number'){for(i=0;i<space;i+=1){indent+=' ';}}else if(typeof space==='string'){indent=space;}
rep=replacer;if(replacer&&typeof replacer!=='function'&&(typeof replacer!=='object'||typeof replacer.length!=='number')){throw new Error('JSON.stringify');}
return str('',{'':value});};}
if(typeof JSON.parse!=='function'){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==='object'){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v;}else{delete value[k];}}}}
return reviver.call(holder,key,value);}
cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return'\\u'+
('0000'+a.charCodeAt(0).toString(16)).slice(-4);});}
if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){j=eval('('+text+')');return typeof reviver==='function'?walk({'':j},''):j;}
throw new SyntaxError('JSON.parse');};}})();


    function populateElement(selector, defvalue) {
      if($.trim($(selector).val()) == "") {
        $(selector).val(defvalue);
      }

      $(selector).focus(function() {
        if($(selector).val() == defvalue) {
          $(selector).val("");
        }
      });

      $(selector).blur(function() {
        if($.trim($(selector).val()) == "") {
          $(selector).val(defvalue);
        }
      });
    }



    function bindNewNoteActions(selector) {


      var defaultTextEn = 'Click Here to Enter A Private Note, Share It Later\nUse # to mark any word as a #label';

      quickReplyNote(selector.find(".comment_link"), "Add New Comment");
      quickShareNote(selector.find(".share_link"));
      quickEditNote(selector.find(".edit_link"));
      quickPhotoNote(selector.find(".photo_link"));
      ajaxSubmit(selector.find('.submit_comment'), defaultTextEn);
      //$(e.target).find("#noteInput").val()
      hoverClick(selector);//.find('.replyClass'));
    }


    function ajaxSubmitTopNote(selector, defaultText) {
      selector.bind("submit", function(e) {
        //if ($(e.target).find("#noteInput").val() != defaultText || confirm('Save this empty note?')) {
        if ($(e.target).find(".noteInput").val() != defaultText || confirm('Save this empty note?')) {
          // allow submit to go on, make this ajax
          /*
           var url = "/APINoteJson.action";
           var data = { viewNodeId: "<s:property value="account.id"/>", note: $(e.target).find(".noteInput").val() }
         var callback = function(e){

         // new note get passed to this
         //bindNewNoteActions();

         };
         $.post(url, data, callback, "json");*/
        } else {
          e.preventDefault();
          e.stopPropagation();
        }
      });
    };


    function getBubbleInput() {
      return '<div>'
          +'<form method="post" onsubmit="return true;" action="APINoteJson.action" name="addNote" id="addNote">'
          +'<div class="create_note_AJAX">'
          +'   <div><textarea type="text" name="noteInput" id="noteInput" wrap="virtual" class="noteInput" tabindex="1"></textarea></div>'
          +'</div>'
          +'<div class="save">'
          +'<a href="#" class="replyInputCancel">cancel</a>'
          +'<input type="submit" name="saveNowButton" class="saveButton round" id="addNote_0" value="Comment" tabindex="2"> '
          +'</div>'
          +' </form>'
          +'</div>';
    }
    function getBubbleInputSandbox() {
      return '<div>'
          +'<form method="post" onsubmit="return true;" action="APINoteJson.action" name="addNote" id="addNote">'
          +'<div class="create_note_AJAX">'
          +'   <div><textarea type="text" name="noteInput" id="noteInput" wrap="virtual" class="noteInput" tabindex="1"></textarea></div>'
          +'</div>'
          +'<div class="save">'
          +'<b>You are in demo mode, no changes will be saved.</b><br><a href="#" class="replyInputCancel">cancel</a>'
          +'<input type="submit" name="saveNowButton" class="saveButton round" id="addNote_0" value="Comment" tabindex="2"> '
          +'</div>'
          +' </form>'
          +'</div>';
    }


    function getBubbleNoteSandbox(nodeId, owner, text) {
      return '<li id="'+nodeId+'" class="noteRoot">'
          + '<div class="noteBubble">'
          + '<p class=" noteContent">'+text+'</p><p class="notePhoto"></p>'
          + '</div>'
          + '<div class="note_header">'
          +'<div class="note_links">'
          + '<ul  class="simple_list_inline">'
          + '<li><a href="#" class="newShare">share</a></li>'
          + '<li><a href="#" class="newMore">options</a></li>'
          +    '<li><a style="font-weight: bold;" href="#" class="newComment">comment</a></li>'
          + '<li><a href="#" class="newAttach"><img src="http://cdn.3banana.com/attach_icon.png" alt="attach photo" border="0"></a></li>'
          +      '</ul>'
          +'</div>'
          + '<div class="noteHeaderWrap">'
          +   '<img class="quoteCorner" src="http://cdn.3banana.com/quote_corner_up_big.png">'
          +   '<div class="note_header_text">'+owner+'</div>'
          +   '<div class="note_header_time">Just now</div>'
          + '</div>'
          + ' </div>'
          +'<ul class="replyHide reply"></ul>'
          + '</li>';

    }

    function getBubbleNote(nodeId, owner, text) {
      return '<li id="'+nodeId+'" class="noteRoot">'
          + '<div class="noteBubble">'
          + '<p class="noteContent">'+text+'</p><p class="notePhoto"></p>'
          + '</div>'
          + '<div class="note_header">'
          +'<div class="note_links">'
          + '<ul  class="simple_list_inline">'
          + '<li><a href="#" class="newShare">share</a></li>'
          + '<li><a href="#" class="newMore">options</a></li>'
          +    '<li><a style="font-weight: bold;" href="#" class="newComment">comment</a></li>'
          + '<li><a href="#" class="newAttach"><img src="http://cdn.3banana.com/attach_icon.png" alt="attach photo" border="0"></a></li>'
          + '  <li><a href="/NonShareablePrivateURL.action?viewNodeId='+nodeId+'" target="_blank"><img src="http://cdn.3banana.com/pop_out_icon.png" alt="open note in new window" border="0"></a></li>'
          +      '</ul>'
          +'</div>'
          + '<div class="noteHeaderWrap">'
          +   '<img class="quoteCorner" src="http://cdn.3banana.com/quote_corner_up_big.png">'
          +   '<div class="note_header_text">'+owner+'</div>'
          +   '<div class="note_header_time">Just now</div>'
          + '</div>'
          + ' </div>'
          +'<ul class="replyHide reply"></ul>'
          + '</li>';
    }

    function feedToggle(selector) {
      selector.bind("click", function (e) {
        var target = $(e.target);
        if (!target.hasClass('feed_single_item_header')) {
          target = target.parents('.feed_single_item_header');
        }
        e.preventDefault();
        e.stopPropagation();
        /*if (target.next().css('display') == 'none') {
         target.children("img").attr('src', 'http://static.3banana.com/pics/downsm.png');
         } else {
         target.children("img").attr('src', 'http://static.3banana.com/pics/rightsm.png');
         } */
        target.next().toggle();
      });
    }

    function doEdit(target, noteRoot) {
        var noteContent = noteRoot.children(".noteBubble").find('.noteContent:first');
        //var textOriginal = noteContent.html();
        var textOriginal = noteContent.html();
        var text = unescape(noteContent.attr("raw"));
        var textareaHeight = noteContent.height()+50;
        var result = noteContent.html('<textarea style="height:'+textareaHeight+'px;" class="noteInput" type="text" name="noteInput">'+text+'</textarea>');
        var oldNoteHeaderWrap = noteRoot.children('.note_header').children('.noteHeaderWrap').html();
        noteRoot.children('.note_header').children('.note_links').hide();
        var newNoteHeaderWrap = noteRoot.children('.note_header').children('.noteHeaderWrap').html('<div class="save"><a href="#" class="editCancel">cancel</a> <input type="submit" value="Save Note" id="quickSave" class="bigButton"/></div>');
        result.find(".noteInput").focus();
        var nodeId = noteRoot.attr('id');
        newNoteHeaderWrap.find('#quickSave').bind('click', function (e) {
          var url = "/APIEditNoteJson.action";
          var text = result.find(".noteInput").val();
          if (text.length != 0 || confirm('Save this empty note?')) {
            result.find('#quickSave').attr('disabled', 'yep');
            result.find('#quickSave').attr('value', 'Please Wait');
            noteRoot.children('.note_header').children('.note_links').show();
            var data = { viewNodeId: nodeId, note: text};
            if (isSanboxMode) {
              noteContent.html(text);
              newNoteHeaderWrap.html(oldNoteHeaderWrap);
            } else {
              var callback = function(data){
		noteContent.attr("raw", escape(text));
                noteContent.html(data['entries'][0]['text']);
                newNoteHeaderWrap.html(oldNoteHeaderWrap);
              }
              $.post(url, data, callback, "json");
            }
          }
        });
        newNoteHeaderWrap.find('.editCancel').bind('click', function (e) {
          e.preventDefault();
          e.stopPropagation();
          noteRoot.children('.note_header').children('.note_links').show();
          noteContent.html(textOriginal);
          newNoteHeaderWrap.html(oldNoteHeaderWrap);
        });
        hideOptionsMenu();
}

    function newQuickEdit(selector) {
      selector.bind('click', function(e) {
        e.preventDefault();
        e.stopPropagation();
        var target = $(e.target);
	var noteRoot = target.closest(".noteRoot");
	doEdit(target, noteRoot);
      });
    }
    function newEdit(selector, noteRoot) {
      selector.bind('click', function(e) {
        e.preventDefault();
        e.stopPropagation();
        var target = $(e.target);
	doEdit(target, noteRoot);
      });
    }

    function uploadForm(nodeId) {
      return '<form enctype="multipart/form-data" method="post" action="/APIUploadImage.action" onsubmit="return true;" name="uploadForm" id="uploadForm" target="uploadIFrame_'+nodeId+'">'
          +'<input type=hidden name="viewNodeId" value="'+nodeId+'">'
          + '<input style="position: absolute; opacity: 0; width:220px; height:10px;" onmouseover="style.cursor=\'pointer\'" type="file" id="uploadImage" name="uploadImage"/>'
          + '</form>'
    }
    function uploadIFrame(nodeId) {
      return '<iframe style="display:none;" id="uploadIFrame_' + nodeId + '" name="uploadIFrame_' + nodeId + '"></iframe>';
    }

    function asyncLoadImageInDiv(photoDiv, imageId) {
      photoDiv.html("Loading image...")
      $.get("/APIPhotoViewIsReady.action", { imageId: imageId},
          function(data){
            var timeCacheExpire = new Date().getTime();
            photoDiv.html('<img style="max-width: 100%;" src="http://photos.3banana.com/viewImage.action?imageId='+imageId+'&'+timeCacheExpire+'">');
          });
    }

    function newPhoto(selector, noteRoot) {
      var target = selector;

      var nodeId = noteRoot.attr('id');
      var wrap = target.parent();

      var uploadStatus = wrap.find('.uploadStatus:first');
      wrap.append(uploadForm(nodeId));
      var iframe = $(uploadIFrame(nodeId));
      wrap.append(iframe);

      var container = wrap.css({
        position: 'relative',
        height: target.outerHeight()+uploadStatus.outerHeight()+'px',
        width: target.outerWidth()+'px',
        overflow: 'hidden',
        cursor: 'pointer',
        margin: 0,
        padding: 0
      });

      var uploadImage = wrap.find("#uploadImage:first");

      wrap.mousemove(function(e){
        uploadImage.css({
          top: e.pageY-wrap.offset().top - 5 +'px',
          left: e.pageX-wrap.offset().left - 175 +'px'
        });
      });

      uploadImage.change(function(e) {
        uploadStatus.text('Uploading...')
        if (isSanboxMode) {
          var photoDiv = noteRoot.children('.noteBubble').find('.notePhoto:first');
          setTimeout(function(){
            noteRoot.addClass('hasPhoto');
            hideOptionsMenu();
            photoDiv.html('<img style="max-width: 100%;" src="http://cdn.3banana.com/WelcomeBanana.jpg">');
          }, 150);
        } else {
          iframe.load(function() {
            var myFrame = document.getElementById(iframe.attr('name'));
            var response = $(myFrame.contentWindow.document.body).text();
            var data = JSON.parse(response);
            var imageId = data["entries"][0]["imageId"];
            var photoDiv = noteRoot.children('.noteBubble').find('.notePhoto:first');
            uploadStatus.text('Done!');
            noteRoot.addClass('hasPhoto');
            setTimeout(function(){hideOptionsMenu();}, 150);
            asyncLoadImageInDiv(photoDiv, imageId);
          });
          $(e.target).closest('#uploadForm').submit();
        }
      });
    }


    function newPhotoDelete(selector, noteRoot) {
      //var photoDiv = selector.closest('.noteRoot').children('.noteBubble').find('.notePhoto:first');
      selector.bind('click', function (e) {
        e.preventDefault();
        e.stopPropagation();
        var nodeId = noteRoot.attr('id');
        if (isSanboxMode) {
          noteRoot.removeClass('hasPhoto');
          var photoDiv = noteRoot.children('.noteBubble').find('.notePhoto:first');
          photoDiv.html('');
          hideOptionsMenu();
        } else {
        $.get("/APIPhotoViewDelete.action", { viewNodeId: nodeId },
            function(data){
              noteRoot.removeClass('hasPhoto');
              var photoDiv = noteRoot.children('.noteBubble').find('.notePhoto:first');
              photoDiv.html('');
              hideOptionsMenu();
            });
        }
      });
    }

    function addReply(replyUL, nodeId, owner, text) {
      if (isSanboxMode) {
        replyUL.prepend(getBubbleNoteSandbox(nodeId, owner, text));
      } else {
        replyUL.prepend(getBubbleNote(nodeId, owner, text));
      }
      replyUL.find('.replyInput:first').remove();
      var newNote = replyUL.find('#'+nodeId);

      newShare(newNote.find('.newShare:first'));
      newAttach(newNote.find('.newAttach:first'));
      newComment(newNote.find('.newComment:first'));
      newMore(newNote.find('.newMore:first'));
    }

    function newCommentSubmit(submitButton) {
      submitButton.bind('submit', function (e) {
        e.preventDefault();
        e.stopPropagation();
        var target = $(e.target);
        var replyUL = target.closest('.reply');
        var noteRoot = replyUL.parent();
        var nodeId = noteRoot.attr('id');
        var topShareURL =  noteRoot.attr('topShareURL');
        var text = target.find("#noteInput").val();
        if (text.length != 0 || confirm('Save this empty note?')) {
          target.find('#addNote_0').attr('disabled', 'yep');
          target.find('#addNote_0').attr('value', 'Please Wait');
          var url = "/APINoteJson.action";
          var data;
          if (topShareURL) {
            data = { viewNodeId: nodeId, note: text, topShareURL: topShareURL};
          } else {
            data = { viewNodeId: nodeId, note: text};
          }
          var callback = function(data){
            var nodeId = data['entries'][0]['nodeId'];
            var owner = data['entries'][0]['owner'];
            var text = data['entries'][0]['text'];
            addReply(replyUL, nodeId, owner, text);
          }

          $.post(url, data, callback, "json");
        }

      });
    }

    function newCommentSandbox(submitButton) {
      submitButton.bind('submit', function (e) {
        e.preventDefault();
        e.stopPropagation();
        var target = $(e.target);
        var replyUL = target.closest('.reply');
        var noteRoot = replyUL.parent();
        var nodeId = noteRoot.attr('id');
        var topShareURL =  noteRoot.attr('topShareURL');
        var text = target.find("#noteInput").val();
        var owner = "Me"
        if (text.length != 0 || confirm('Save this empty note?')) {
          addReply(replyUL, nodeId, owner, text);
        }
      });

    }
    function newCommentNeedsSignInClick(submitButton) {
      submitButton.bind('click', function (e) {
        var target = $(e.target);
        var replyUL = target.closest('.reply');
        var noteRoot = replyUL.parent();
        var shareurl = noteRoot.attr('shareurl');
	document.cookie = "commentCookie=nom|"+escape(shareurl) + "; path=/;";
      });
    }

    function addShare(shareURL) {
      return $(
          '<div class="more"><div class="noteMore simple_list">'
          + '<ul style=\"padding-bottom:20px\">'
          + '<li><a href="/shareBounce.action?share=FACEBOOK&shareURL='+shareURL+'" target="_blank"><img src="http://cdn.3banana.com/icon_fb.gif" border=0>Facebook</a></li>'
          + '<li><a href="/shareBounce.action?share=TWITTER&shareURL='+shareURL+'" target="_blank"><img src="http://cdn.3banana.com/icon_twitter.gif" border=0>Twitter</a></li>'
          + '<li><a href="/shareBounce.action?share=QR_CODE&shareURL='+shareURL+'" target="_blank"><img src="http://cdn.3banana.com/icon_qrcode.png" border=0>QR Code</a></li>'
          + '<li><span class="social_url">URL </span></li>'
          +'<li><input type="text" readonly="sa" onclick="javascript:this.focus();this.select();" value="'+shareURL+'" class="social_url_input" name="social_url"/></li>'
          + '</ul>'
          + '</div></div>');
    }

    function hasReplyUL(target) {
      return target.closest('.noteRoot').children('.reply').length==1;
    }

    function addReplyUL(target) {
      target.closest('.noteRoot').append('<ul class="reply"></ul>');
    }

    function removeReply(target) {
      var reply = target.closest('.noteRoot').children('.reply').children('.replyInput');
      var text = reply.find("#noteInput:first").val();
      if (text == null || text.length == 0 || confirm('Cancel note?')) {
        reply.remove();
        return true;
      }
      return false;
    }

    function hasReplyInput(target) {
      return target.closest('.noteRoot').children('.reply').children('.replyInput').length==1
    }

    function bindReplyInputCancel(target) {
      target.bind("click", function (e) {
        e.preventDefault();
        e.stopPropagation();
        var reply = $(e.target).closest('.replyInput');
        var text = reply.find("#noteInput:first").val();
        if (text.length == 0 || confirm('Cancel note?')) {
          reply.remove();
        }
      });
    }

    function addMoreAddPhoto(target, viewNodeId) {
      return $(
          '<div class="more" style=""><div class="noteMore simple_list">'
              +'<ul>'
              +'<li><a href="/NonShareablePrivateURL.action?viewNodeId='+viewNodeId+'&view=pt">print note</a></li>'
              +'<li><div class="newPhotoWrap"><a class="morePhoto" href="#">attach photo</a><div class="uploadStatus">2MB limit</div></div></li>'
              +'<li><hr></li>'
              +'<li><a class="moreDelete" href="/removeNote.action?viewNodeId='+viewNodeId+'">delete note</a></li>'
              +'</ul>'
              +'</div></div>');
    }

    function addMoreRemovePhoto(target, viewNodeId) {
      return $(
          '<div class="more" style=""><div class="noteMore simple_list">'
              +'<ul>'
              +'<li><a href="/NonShareablePrivateURL.action?viewNodeId='+viewNodeId+'&view=pt">print note</a></li>'
              +'<li><a class="morePhotoDelete" href="#">remove photo</a></li>'
              +'<li><hr></li>'
              +'<li><a class="moreDelete" href="/removeNote.action?viewNodeId='+viewNodeId+'">delete note</a></li>'
              +'</ul>'
              +'</div></div>');
    }

    function addMoreRemoveOnly(target, viewNodeId) {
      return $(
          '<div class="more" style=""><div class="noteMore simple_list">'
              +'<ul>'
              +'<li><a href="/NonShareablePrivateURL.action?viewNodeId='+viewNodeId+'&view=pt">print note</a></li>'
              +'<li></li>'
              +'<li><hr></li>'
              +'<li><a class="moreDelete" href="/removeNote.action?viewNodeId='+viewNodeId+'">remove note</a></li>'
              +'</ul>'
              +'</div></div>');
    }

    function addAttach(target, viewNodeId) {
      return $(
          '<div class="more"><div class="noteMore simple_list" style="width:90px;min-width:90px;">'
              +'<ul>'
              +'<li><div class="newPhotoWrap"><a class="morePhoto" href="#">attach photo</a><div class="uploadStatus">2MB limit</div></div></li>'
              +'</ul>'
              +'</div></div>');
    }

    function getShareURL(noteRoot) {
      if (isSanboxMode) {
        return "http://3banana.com/"
      }
      return noteRoot.attr('shareURL');;
    }

    function newShare(selector) {
      selector.bind("click", function (e) {
        var target = $(e.target);
        e.preventDefault();
        e.stopPropagation();
        toggleBigHeader(target);
        var noteRoot = target.parents('.noteRoot:first');
        var viewNodeId = noteRoot.attr('id');
        var optionsMenuId = viewNodeId+"_share";
        if (!hasOptionsMenu(optionsMenuId)) {
          hideOptionsMenu();
          var moreToAdd;


          var shareURL = getShareURL(noteRoot);
          if (shareURL) {
            moreToAdd = addShare(shareURL);
            showOptionsMenu(noteRoot, target.position(), moreToAdd, optionsMenuId);
          } else {
            moreToAdd = addShare('Loading...');
            showOptionsMenu(noteRoot, target.position(), moreToAdd, optionsMenuId);
            $.get("/APIGetShareURL.action", { viewNodeId: viewNodeId},
            function(data){
              data = JSON.parse(data);
              var shareURL = data['entries'][0]['shareURL'];
              noteRoot.attr('shareURL', shareURL);
              moreToAdd = addShare(shareURL);
              hideOptionsMenu();
              showOptionsMenu(noteRoot, target.position(), moreToAdd, optionsMenuId);
            })
          }

        } else {
          hideOptionsMenu();
        }
      });
    }

    function showReplies(selector) {
      selector.bind("click", function (e) {
        var target = $(e.target);
        var reply = target.closest('.noteRoot').children('.reply');
        e.preventDefault();
        e.stopPropagation();
        hideOptionsMenu()
        reply.toggle();
      });
    }

    function newComment(selector, hasSignIn) {
      selector.bind("click", function (e) {
        var target = $(e.target);
        e.preventDefault();
        e.stopPropagation();
        if (!hasReplyUL(target)) {
          addReplyUL(target);
        }

        var replyUL = target.closest('.noteRoot').children('.reply');
        hideOptionsMenu();
        if (!hasReplyInput(target)) {
          replyUL.show();
          if (isSanboxMode) {
            replyUL.prepend(
                "<li class='replyInput'>"
                    + getBubbleInputSandbox()
                    +"</li>");
            newCommentSandbox(replyUL.find('form:first'));

          } else if (!hasSignIn) {
            replyUL.prepend(
                "<li class='replyInput'>"
                    + getBubbleInput()
                    +"</li>");
            newCommentSubmit(replyUL.find('form:first'));
          } else {
            replyUL.prepend(
                "<li class='replyInput'>"
                    + getBubbleInputSignIn()
                    +"</li>");
            replyUL.find(".saveLocation").each(function () {newCommentNeedsSignInClick($(this))})
          }
            replyUL.find('#noteInput:first').focus();
          bindReplyInputCancel(replyUL.find('.replyInputCancel'));
        } else {
          replyUL.hide();
          removeReply(target);
        }
      });
    }

    var optionsMenuDiv;
    function hasOptionsMenu(optionsMenuId) {
      if (!optionsMenuDiv) {
        return false;
      }
      return optionsMenuDiv.attr('optionsMenuId') == optionsMenuId ;
    }

    function showOptionsMenu(anywhere, myPosition, content, optionsMenuId) {
      if (!hasOptionsMenu(optionsMenuId)) {
        optionsMenuDiv = $('<div id="optionsMenuDiv"></div>').css({
          position: 'absolute',
          zIndex: '1',
          left:myPosition.left-20 + 'px',
          top: myPosition.top + 'px'
        });
        optionsMenuDiv.appendTo(anywhere);
      }

      optionsMenuDiv.css({left:myPosition.left-20 + 'px',
        top: myPosition.top + 'px'});

      optionsMenuDiv.attr('optionsMenuId', optionsMenuId);
      optionsMenuDiv.html(content);

    }

    function hideOptionsMenu() {
      if (optionsMenuDiv) {
        optionsMenuDiv.remove();
        optionsMenuDiv = undefined;
        lastBigHeader.removeClass('noteMoreHeader');
      }
    }

    var lastBigHeader;
    function toggleBigHeader(target) {
      var hadNoteMoreHeader = target.parent().hasClass('noteMoreHeader');
      if (lastBigHeader) {
        lastBigHeader.removeClass('noteMoreHeader');
      }

      if (!hadNoteMoreHeader) {
        lastBigHeader = target.parent().addClass('noteMoreHeader');
      }
    }

    function newMore(selector) {
      selector.bind("click", function (e) {
        var target = $(e.target);
        e.preventDefault();
        e.stopPropagation();
        toggleBigHeader(target);
        var noteRoot = target.parents('.noteRoot:first');
        var viewNodeId = noteRoot.attr('id');
        var optionsMenuId = viewNodeId+"_more";
        if (!hasOptionsMenu(optionsMenuId)) {
          hideOptionsMenu();
          var moreToAdd;
          if (noteRoot.hasClass('removeOnly')) {
            moreToAdd = addMoreRemoveOnly(target, viewNodeId);
            showOptionsMenu(noteRoot, target.position(), moreToAdd, optionsMenuId);
          } else if (noteRoot.hasClass('hasPhoto')) {
            moreToAdd = addMoreRemovePhoto(target, viewNodeId);
            showOptionsMenu(noteRoot, target.position(), moreToAdd, optionsMenuId);
            newPhotoDelete(moreToAdd.find('.morePhotoDelete:first'), noteRoot);
            newEdit(moreToAdd.find('.moreEdit:first'), noteRoot);
          } else {
            moreToAdd = addMoreAddPhoto(target, viewNodeId);
            showOptionsMenu(noteRoot, target.position(), moreToAdd, optionsMenuId);
            newPhoto(moreToAdd.find('.morePhoto:first'), noteRoot);
            newEdit(moreToAdd.find('.moreEdit:first'), noteRoot);
          }
        } else {
          hideOptionsMenu();
        }
      });
    }
    function newAttach(selector) {
      selector.bind("click", function (e) {
        var target = $(e.target);
        e.preventDefault();
        e.stopPropagation();
        toggleBigHeader(target);
        var noteRoot = target.parents('.noteRoot:first');
        var viewNodeId = noteRoot.attr('id');
        var optionsMenuId = viewNodeId+"_attach";
        if (!hasOptionsMenu(optionsMenuId)) {
          hideOptionsMenu();
          var moreToAdd;
            moreToAdd = addAttach(target, viewNodeId);
            showOptionsMenu(noteRoot, target.position(), moreToAdd, optionsMenuId);
            newPhoto(moreToAdd.find('.morePhoto:first'), noteRoot);
         // }
        } else {
          hideOptionsMenu();
        }
      });
    }

    function bindFeedback(selector) {
      selector.bind("click", function () {
        var feedback = $('#feedback');
        if (feedback.css('left') == '0px') {
          feedback.animate({left:'-280px'},100);
          $('#feedbackInput').blur();
        } else {
          feedback.animate({left:'0px'},100);
          $('#feedbackInput').focus();
        }
      });
      $('#feedback_cancel').bind("click", function (e) {
        e.preventDefault();
        e.stopPropagation();
        var feedback = $('#feedback');
        feedback.animate({left:'-280px'},100);
        $('#feedbackInput').blur();
        $('#feedbackInput').val('');
      });
      $('#feedbackForm').bind("submit", function (e) {
        e.preventDefault();
        e.stopPropagation();
        var feedbackInput = $('#feedbackInput');
        var feedbackSubmit = $('#feedbackSubmit');
        feedbackSubmit.attr('disabled', 'yep');
        feedbackSubmit.attr('value', 'Thank you!');
        var url = "/feedback.action"
        var data = { feedback: feedbackInput.val()};
        var callback = function(data){
          //noteContent.html(data['entries'][0]['text']);
          //newNoteHeaderWrap.html(oldNoteHeaderWrap);
        }
        $.post(url, data, callback, "json");
        setTimeout(function () {
          var feedback = $('#feedback');
          feedback.animate({left:'-280px'},100);
          $('#feedbackInput').blur();
          $('#feedbackInput').val('');
          feedbackSubmit.removeAttr('disabled');
          feedbackSubmit.attr('value', 'Submit'); }, 1500);
      });
    }

 function showLabelHint(labelsToShow) {
      var result = $("#result");
      result.html("");
      result.attr("active", "yes");
      result.attr("selectPosition", "-1");
      result.attr("hintSize", labelsToShow.length-1);
      result.show();
      for (var i=0; i < labelsToShow.length; i++) {
        result.append("<li style='z-index:220;' id='select_"+i+"'>" + labelsToShow[i] + "</li>");
      }
    }
    function hideLabelHint() {
      //console.log("hideLabelHint");
      var result = $("#result");
      result.hide();
      result.removeAttr("active");
    }

    function isHashcodeStart(text, cursorPosition) {

      // # at start of text
      if (cursorPosition == 0 && text.charAt(cursorPosition) == '#') {
        return true;
      }

      // # with a space or LF before it
      if (cursorPosition > 0 && text.charAt(cursorPosition) == '#'
          && (text.charAt(cursorPosition-1).charCodeAt() == 32 ||
              text.charAt(cursorPosition-1).charCodeAt() == 10)) {
        return true;
      }

      return false;
    }

    // thanks Alex Brem http://laboratorium.0xab.cd/jquery/fieldselection/0.1.0/jquery-fieldselection.js
    function getCaretPosition(textarea) {
      if (document.selection) { // ieeeeeeeeee
        var selectionRange = document.selection.createRange();
        var selectionRangeEnd  = textarea[0].createTextRange();
        var selectionRangeEndDupe = selectionRangeEnd.duplicate();
        selectionRangeEnd.moveToBookmark(selectionRange.getBookmark());
        selectionRangeEndDupe.setEndPoint('EndToStart', selectionRangeEnd);
        return selectionRangeEndDupe.text.length + selectionRange.text.length;
      } else {
        return textarea[0].selectionStart;
      }
    }

    function handleText(textarea) {
      // 32 space
      // 35 #
      var cursorPosition = getCaretPosition(textarea);
      var text = textarea.val();
      var hashcodePosition = -1;
      for (var i = cursorPosition-1; i >= 0; i--) {

        // space or LF
        if (text.charAt(i).charCodeAt() == 32 ||
            text.charAt(i).charCodeAt() == 10) {
          break;
        }

        if (isHashcodeStart(text, i)) {
          hashcodePosition = i;
          break;
        }

        // after testing for #, we find one. know it is a dupe
        if (text.charAt(i) == '#') {
          hashcodePosition = -1;
          break;
        }
      }

      var label;
      filteredLabels = [];
      if (hashcodePosition != -1) {
        label = text.substring(hashcodePosition+1, cursorPosition).toLowerCase();
        for (var labelSingle in labels) {
          if (labelSingle.indexOf(label) == 0) {
            filteredLabels.push(labels[labelSingle]);
          }
        }
      }
      var result = $("#result");
      if (filteredLabels.length != 0) {
        showLabelHint(filteredLabels);
        result.attr("hashcodePosition", hashcodePosition);
        result.attr("originalText", escape(text));
        result.attr("hashcodePosition", hashcodePosition);
        result.attr("cursorPosition", cursorPosition);
      } else {
        hideLabelHint();
      }
    }

    function isLabelHintActive() {
      var result = $("#result");
      return result.attr("active") != undefined;
    }

    function labelHintHighlight(previousSelection, newSelection) {
      if (previousSelection != undefined) {
        previousSelection.removeClass("labelHintSelect");
      }
      newSelection.addClass("labelHintSelect");
    }

    function replaceLabelInTextarea(result, position, padWithSpace) {
      var textarea = $("#addNote_noteInputNew");
      var text = unescape(result.attr("originalText"));
      var cursorPosition = parseInt(result.attr('cursorPosition'));
      var hashcodePosition = parseInt(result.attr('hashcodePosition'));
      var replacementLabel = filteredLabels[position];
      if (position == -1) {
        replacementLabel = text.slice(hashcodePosition+1, cursorPosition);
      }

      if (padWithSpace != undefined) {
        replacementLabel = replacementLabel + " ";
      }

      textarea.val(text.slice(0, hashcodePosition+1) + replacementLabel
          + text.slice(cursorPosition));
    }

    function labelHintMoveUp() {
      var result = $("#result");
      var position = parseInt(result.attr("selectPosition"));
      var hintSize = parseInt($("#result").attr("hintSize"));
      if (position < 0) {
        position = hintSize+1;
      }

      var previousSelection = result.children("#select_" + position);
      position = position - 1;
      replaceLabelInTextarea(result, position);
      result.attr("selectPosition", position);

      var newSelection = result.children("#select_" + position);
      labelHintHighlight(previousSelection, newSelection);
    }

    function labelHintMoveDown() {
      var result = $("#result");
      var position = parseInt(result.attr("selectPosition"));
      var hintSize = parseInt($("#result").attr("hintSize"));
      if (position == hintSize) {
        result.children("#select_"+position).removeClass("labelHintSelect");
        position = -1;
        result.attr("selectPosition", position);
        replaceLabelInTextarea(result, position);
        return;
      }

      var previousSelection = result.children("#select_" + position);
      position = position + 1;
      replaceLabelInTextarea(result, position);
      result.attr("selectPosition", position);

      var newSelection = result.children("#select_" + position);
      labelHintHighlight(previousSelection, newSelection);
    }

    function labelHintSelect() {
      var result = $("#result");
      var position = parseInt(result.attr("selectPosition"));
      replaceLabelInTextarea(result, position, true);
      hideLabelHint();
    }
