# Source: bubble.js

    /** @file This file contains functions that draw the popup bubble during labeling or editing an object. */

    // *******************************************
    // Public methods:
    // *******************************************

    /** This function creates the popup bubble.
     * @param {float} left - xlocation of the bubble
     * @param {float} top - ylocation of the bubble
     * @param {string} innerhtml - extra html content for the bubble
     * @param {string} dom_attach - id of the html element where it should be attached
     * @returns {string} bubble_name - dom element name for the popup bubble
    */
    function CreatePopupBubble(left,top,innerHTML,dom_attach) {
      var html_str;
      var bubble_name = 'myPopup';

      // Adjust location to account for the displacement of the arrow:
      left -= 22;
      if (left < 5) left = 5;

      // Select the vertical position of the bubble decoration arrow
      if (top > 214) {
        html_str  = '<div class= "bubble" id="' + bubble_name + '" style="position:absolute;z-index:5; left:' + left + 'px; top:' + top + 'px;">';
      }
      else {
        html_str  = '<div class= "bubble top" id="' + bubble_name + '" style="position:absolute;z-index:5; left:' + left + 'px; top:' + top + 'px;">';
      }

      // Insert bubble inner contents:
      html_str += innerHTML;

      // Close div tag:
      html_str += '</div>';

      // Insert bubble into the DOM tree:
      $('#'+dom_attach).append(html_str);

      // Place bubble in the right location taking into account the rendered size and the location of the arrow
      if(top > 214) {
        h = $('#'+bubble_name).height();
        document.getElementById(bubble_name).style.top = (top-h-80) + 'px';
      }
      else {
        document.getElementById(bubble_name).style.top = (top) + 'px';
      }

      return bubble_name;
    }

    /** This function creates the close button at the top-right corner of the popup bubble
     * @param {string} dom_bubble - dom_bubble name
     * @param {function} close_button - function to run when the close button is pressed
    */
    function CreatePopupBubbleCloseButton(dom_bubble,close_function) {
      if(arguments.length==1) {
        close_function = function() {return;};
      }
      var html_str = '<img id="' + dom_bubble + '_closebutton" style="border: 0pt none; width:14px; height:14px; z-index:4; -moz-user-select:none; position:absolute; cursor:pointer; right:8px; top: 8px;" src="Icons/close.png" height="14" width="14" />';
      $('#'+dom_bubble).append(html_str);
      $('#'+dom_bubble+'_closebutton').mousedown(function () {
          $('#'+dom_bubble).remove();
          close_function();
          return;
        });
    }

    // *******************************************
    // All functions below here need to be moved to their appropriate module:
    // *******************************************

    // THINGS THAT WILL BE GOOD TO SIMPLIFY:
    //  1- why are there two functions -almost-identical- to close the bubble?
    //  2- why is different the way the data is submitted in edit and query? I think with LM_xml data handling this will be simplified.
    //  3- I want functions
    //        LM_xml.store(obj_index, fieldname, value)
    //        LM_xml.getvalue(obj_index, fieldname)
    //        LM_xml.sendtoserver
    //

    // Query popup bubble:
    function mkPopup(left,top) {
      wait_for_input = 1;
      var innerHTML = GetPopupFormDraw();
      CreatePopupBubble(left,top,innerHTML,'main_section');

      // Focus the cursor inside the box
      setTimeout("$('#objEnter').focus();",1);
    }

    function mkEditPopup(left,top,anno) {
      edit_popup_open = 1;
      var innerHTML = GetPopupFormEdit(anno);
      var dom_bubble = CreatePopupBubble(left,top,innerHTML,'main_section');
      CreatePopupBubbleCloseButton(dom_bubble,StopEditEvent);

      // Focus the cursor inside the box
      $('#objEnter').select();
      $('#objEnter').focus();
    }

    function CloseQueryPopup() {
      wait_for_input = 0;
      $('#myPopup').remove();
    }

    function CloseEditPopup() {
      edit_popup_open = 0;
      $('#myPopup').remove();
    }

    // ****************************
    // Forms:
    // ****************************

    function GetPopupFormDraw() {
      html_str = "<b>Enter object name</b><br />";
      html_str += HTMLobjectBox("");

      if(use_attributes) {
        html_str += HTMLoccludedBox("");
        html_str += "<b>Enter attributes</b><br />";
        html_str += HTMLattributesBox("");
      }
      if(use_parts) {
        html_str += HTMLpartsBox("");
      }
      console.log(html_str);
      html_str += "<br />";

      // Done button:
      html_str += '<input type="button" value="Done" title="Press this button after you have provided all the information you want about the object." onclick="main_handler.SubmitQuery();" tabindex="0" />';

      // Undo close button:
      html_str += '<input type="button" value="Undo close" title="Press this button if you accidentally closed the polygon. You can continue adding control points." onclick="UndoCloseButton();" tabindex="0" />';

      // Delete button:
      html_str += '<input type="button" value="Delete" title="Press this button if you wish to delete the polygon." onclick="main_handler.WhatIsThisObjectDeleteButton();" tabindex="0" />';

      return html_str;
    }

    function GetPopupFormEdit(anno) {
      // get object name and attributes from 'anno'
      var obj_name = LMgetObjectField(LM_xml,anno.anno_id,'name');
      if(obj_name=="") obj_name = "?";
      var attributes = LMgetObjectField(LM_xml,anno.anno_id,'attributes');
      var occluded = LMgetObjectField(LM_xml,anno.anno_id,'occluded');
      var parts = anno.GetParts();

      html_str = "<b>Enter object name</b><br />";
      html_str += HTMLobjectBox(obj_name);

      if(use_attributes) {
        html_str += HTMLoccludedBox(occluded);
        html_str += "<b>Enter attributes</b><br />";
        html_str += HTMLattributesBox(attributes);
      }

      if(use_parts) {
        html_str += HTMLpartsBox(parts);
      }

      html_str += "<br />";

      // Done button:
      if (video_mode) html_str += '<input type="button" value="Done" title="Press this button when you are done editing." onclick="main_media.SubmitEditObject();" tabindex="0" />';

      else html_str += '<input type="button" value="Done" title="Press this button when you are done editing." onclick="main_handler.SubmitEditLabel();" tabindex="0" />';

      /*************************************************************/
      /*************************************************************/
      // Scribble: if anno.GetType() != 0 then scribble mode:

      // Adjust polygon button:
      if (anno.GetType() == 0) {
        html_str += '<input type="button" value="Adjust polygon" title="Press this button if you wish to update the polygon\'s control points." onclick="javascript:AdjustPolygonButton();" />';
      }
      else {
        html_str += '<input type="button" value="Edit Scribbles" title="Press this button if you wish to update the segmentation." onclick="javascript:EditBubbleEditScribble();" />';
      }
      /*************************************************************/
      /*************************************************************/

      // Delete button:
      html_str += '<input type="button" value="Delete" title="Press this button if you wish to delete the polygon." onclick="main_handler.EditBubbleDeleteButton();" tabindex="0" />';

      return html_str;
    }

    // ****************************
    // Simple building blocks:
    // ****************************

    // Shows the box to enter the object name
    function HTMLobjectBox(obj_name) {
      var html_str="";

      html_str += '<input name="objEnter" id="objEnter" type="text" style="width:220px;" tabindex="0" value="'+obj_name+'" title="Enter the object\'s name here. Avoid application specific names, codes, long descriptions. Use a name you think other people would agree in using. "';

      html_str += ' onkeyup="var c;if(event.keyCode)c=event.keyCode;if(event.which)c=event.which;if(c==13)';

      // if obj_name is empty it means that the box is being created
      if (obj_name=='') {
        // If press enter, then submit; if press ESC, then delete:
        if (video_mode) html_str += 'main_media.SubmitObject();if(c==27) main_handler.WhatIsThisObjectDeleteButton();" ';
        else html_str += 'main_handler.SubmitQuery();if(c==27)main_handler.WhatIsThisObjectDeleteButton();" ';
      }
      else {
        // If press enter, then submit:
        if (video_mode) html_str += 'main_media.SubmitEditObject();" ';
        else html_str += 'main_handler.SubmitEditLabel();" ';
      }

      // if there is a list of objects, we need to habilitate the list
      if(object_choices=='...') {
        html_str += '/>'; // close <input
      }
      else {
        html_str += 'list="datalist1" />'; // insert list and close <input
        html_str += '<datalist id="datalist1"><select style="display:none">';
        for(var i = 0; i < object_choices.length; i++) {
          html_str += '<option value="' + object_choices[i] + '">' + object_choices[i] + '</option>';
        }
        html_str += '</select></datalist>';
      }

      html_str += '<br />';

      return html_str;
    }

    // ****************************
    // ATTRIBUTES:
    // ****************************
    // ?attributes=object:car;brand:seat/ford;color:...;comments:...

    // is the object occluded?
    function HTMLoccludedBox(occluded) {
      var html_str="";

      // by default, the value of occluded is "no"
      if (!(occluded=="no" || occluded=="yes")) {
        occluded="no";
      }

      // the value of the selection is inside a hidden field:
      html_str += 'Is occluded? <input type="hidden" name="occluded" id="occluded" value="'+occluded+'"/>';

      // generate radio button
      if (occluded=='yes') {
        html_str += '<input type="radio" name="rboccluded" id="rboccluded" value="yes" checked="yes" onclick="document.getElementById(\'occluded\').value=\'yes\';" />yes';
        html_str += '<input type="radio" name="rboccluded" id="rboccluded" value="no"  onclick="document.getElementById(\'occluded\').value=\'no\';" />no';
      }
      else {
        html_str += '<input type="radio" name="rboccluded" id="rboccluded" value="yes"  onclick="document.getElementById(\'occluded\').value=\'yes\';" />yes';
        html_str += '<input type="radio" name="rboccluded" id="rboccluded" value="no" checked="yes"  onclick="document.getElementById(\'occluded\').value=\'no\';" />no';
      }
      html_str += '<br />';

      return html_str;
    }

    // Boxes to enter attributes
    function HTMLattributesBox(attList) {
      return '<textarea name="attributes" id="attributes" type="text" style="width:220px; height:3em;" tabindex="0" title="Enter a comma separated list of attributes, adjectives or other object properties">'+attList+'</textarea>';
    }

    // ****************************
    // PARTS:
    // ****************************
    function HTMLpartsBox(parts) {
      var html_str="";
      if (parts.length>0) {
        if (parts.length==1) {
          html_str = 'Object has 1 part.';
        }
        else {
          html_str = 'Object has '+parts.length+' parts.';
        }
      }
      else {
        html_str = 'Object has no parts (you can add parts using the right panel).';
      }

      return html_str;
    }