You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

labelingSelfDefine.js 82 kB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209
  1. ///增加
  2. var VIA_VERSION = '1.0.0';
  3. var VIA_NAME = 'Image Annotator';
  4. var VIA_SHORT_NAME = 'pcl';
  5. var VIA_REGION_SHAPE = { RECT:'rect',
  6. CIRCLE:'circle',
  7. ELLIPSE:'ellipse',
  8. POLYGON:'polygon',
  9. POINT:'point',
  10. POLYLINE:'polyline'
  11. };
  12. var VIA_ATTRIBUTE_TYPE = { TEXT:'text',
  13. CHECKBOX:'checkbox',
  14. RADIO:'radio',
  15. DROPDOWN:'dropdown'
  16. };
  17. var VIA_DISPLAY_AREA_CONTENT_NAME = {IMAGE:'image_panel',
  18. IMAGE_GRID:'image_grid_panel',
  19. SETTINGS:'settings_panel',
  20. PAGE_404:'page_404',
  21. PAGE_GETTING_STARTED:'page_getting_started',
  22. PAGE_ABOUT:'page_about',
  23. PAGE_START_INFO:'page_start_info',
  24. PAGE_LICENSE:'page_license'
  25. };
  26. var VIA_ANNOTATION_EDITOR_MODE = {SINGLE_REGION:'single_region',
  27. ALL_REGIONS:'all_regions'};
  28. var VIA_ANNOTATION_EDITOR_PLACEMENT = {NEAR_REGION:'NEAR_REGION',
  29. IMAGE_BOTTOM:'IMAGE_BOTTOM',
  30. DISABLE:'DISABLE'};
  31. // var VIA_POLYGON_RESIZE_VERTEX_OFFSET = 100;
  32. var VIA_CANVAS_DEFAULT_ZOOM_LEVEL_INDEX = 3;
  33. var VIA_THEME_SEL_REGION_OPACITY = 0.5;
  34. var VIA_THEME_MESSAGE_TIMEOUT_MS = 6000;
  35. // var VIA_THEME_CONTROL_POINT_COLOR = '#ff0000';
  36. var VIA_CSV_SEP = ',';
  37. var VIA_CSV_QUOTE_CHAR = '"';
  38. var VIA_CSV_KEYVAL_SEP = ':';
  39. var _via_img_metadata = {}; // data structure to store loaded images metadata
  40. // var regions=new Array(500);
  41. var _via_img_src = {}; // image content {abs. path, url, base64 data, etc}
  42. var _via_img_fileref = {}; // reference to local images selected by using browser file selector
  43. var _via_img_count = 0; // count of the loaded images
  44. var _via_canvas_regions = []; // image regions spec. in canvas space
  45. var _via_canvas_scale = 1.0;// current scale of canvas image
  46. var _via_image_id = ''; // id={filename+length} of current image
  47. var _via_image_index = -1; // index
  48. var _via_current_image_filename;
  49. var _via_current_image;
  50. var _via_current_image_width;
  51. var _via_current_image_height;
  52. // a record of image statistics (e.g. width, height)
  53. var _via_img_stat = {};
  54. var _via_is_all_img_stat_read_ongoing = false;
  55. var _via_img_stat_current_img_index = false;
  56. // image canvas
  57. // var _via_display_area = document.getElementById('labelwin');
  58. var _via_display_area = document.getElementById('show_region');
  59. var _via_img_panel = document.getElementById('image_panel');
  60. // var _via_reg_canvas = document.getElementById('region_canvas');
  61. var _via_reg_ctx; // initialized in _via_init()
  62. var _via_canvas_width, _via_canvas_height;
  63. // canvas zoom
  64. var _via_canvas_zoom_level_index = VIA_CANVAS_DEFAULT_ZOOM_LEVEL_INDEX; // 1.0
  65. var _via_canvas_scale_without_zoom = 1.0;
  66. // state of the application
  67. var _via_is_user_drawing_region = false;
  68. var _via_current_image_loaded = false;
  69. // var _via_current_image_loaded = true;
  70. var _via_is_window_resized = false;
  71. var _via_is_window_resized = false;
  72. var _via_is_user_resizing_region = false;
  73. var _via_is_user_moving_region = false;
  74. var _via_is_user_drawing_polygon = false;
  75. var _via_is_region_selected = false;
  76. var _via_is_all_region_selected = false;
  77. var _via_is_loaded_img_list_visible = false;
  78. var _via_is_attributes_panel_visible = false;
  79. var _via_is_reg_attr_panel_visible = false;
  80. var _via_is_file_attr_panel_visible = false;
  81. var _via_is_canvas_zoomed = false;
  82. var _via_is_loading_current_image = false;
  83. var _via_is_region_id_visible = true;
  84. var _via_is_region_boundary_visible = true;
  85. var _via_is_region_info_visible = false;
  86. var _via_is_ctrl_pressed = false;
  87. var _via_is_debug_mode = false;
  88. // region
  89. var _via_current_shape = VIA_REGION_SHAPE.RECT;
  90. var _via_current_polygon_region_id = -1;
  91. var _via_user_sel_region_id = -1;
  92. var _via_click_x0 = 0; var _via_click_y0 = 0;
  93. var _via_click_x1 = 0; var _via_click_y1 = 0;
  94. var _via_region_click_x, _via_region_click_y;
  95. var _via_region_edge = [-1, -1];
  96. var _via_current_x = 0; var _via_current_y = 0;
  97. // region copy/paste
  98. var _via_region_selected_flag = []; // region select flag for current image
  99. var _via_copied_image_regions = [];
  100. var _via_paste_to_multiple_images_input;
  101. // message
  102. var _via_message_clear_timer;
  103. // attributes
  104. var _via_attribute_being_updated = 'region'; // {region, file}
  105. // var _via_attributes = { 'region':{}, 'file':{} };
  106. var _via_attributes = { 'region':{}};
  107. var _via_current_attribute_id = '';
  108. // region group color
  109. var _via_canvas_regions_group_color = {}; // color of each region
  110. // invoke a method after receiving user input
  111. var _via_user_input_ok_handler = null;
  112. var _via_user_input_cancel_handler = null;
  113. var _via_user_input_data = {};
  114. // annotation editor
  115. var _via_annotaion_editor_panel = document.getElementById('annotation_editor_panel');
  116. var _via_metadata_being_updated = 'region'; // {region, file}
  117. var _via_annotation_editor_mode = VIA_ANNOTATION_EDITOR_MODE.SINGLE_REGION;
  118. // persistence to local storage
  119. var _via_is_local_storage_available = false;
  120. var _via_is_save_ongoing = false;
  121. // the contents of _via_img_fn_list_img_index_list.
  122. var _via_image_id_list = []; // array of all image id (in order they were added by user)
  123. var _via_image_filename_list = []; // array of all image filename
  124. var _via_image_load_error = []; // {true, false}
  125. var _via_image_filepath_resolved = []; // {true, false}
  126. var _via_image_filepath_id_list = []; // path for each file
  127. var _via_reload_img_fn_list_table = true;
  128. var _via_img_fn_list_img_index_list = []; // image index list of images show in img_fn_list
  129. var _via_img_fn_list_html = []; // html representation of image filename list
  130. // image grid
  131. var image_grid_panel = document.getElementById('image_grid_panel');
  132. var _via_display_area_content_name = ''; // describes what is currently shown in display area
  133. var _via_display_area_content_name_prev = '';
  134. var _via_image_grid_requires_update = false;
  135. var _via_image_grid_content_overflow = false;
  136. var _via_image_grid_load_ongoing = false;
  137. var _via_image_grid_page_first_index = 0; // array index in _via_img_fn_list_img_index_list[]
  138. var _via_image_grid_page_last_index = -1;
  139. var _via_image_grid_selected_img_index_list = [];
  140. var _via_image_grid_page_img_index_list = []; // list of all image index in current page of image grid
  141. var _via_image_grid_visible_img_index_list = []; // list of images currently visible in grid
  142. var _via_image_grid_mousedown_img_index = -1;
  143. var _via_image_grid_mouseup_img_index = -1;
  144. var _via_image_grid_img_index_list = []; // list of all image index in the image grid
  145. var _via_image_grid_region_index_list = []; // list of all image index in the image grid
  146. var _via_image_grid_group = {}; // {'value':[image_index_list]}
  147. var _via_image_grid_group_var = []; // {type, name, value}
  148. var _via_image_grid_group_show_all = false;
  149. var _via_image_grid_stack_prev_page = []; // stack of first img index of every page navigated so far
  150. // image buffer
  151. var VIA_IMG_PRELOAD_INDICES = [1, -1, 2, 3, -2, 4]; // for any image, preload previous 2 and next 4 images
  152. var VIA_IMG_PRELOAD_COUNT = 4;
  153. var _via_buffer_preload_img_index = -1;
  154. var _via_buffer_img_index_list = [];
  155. var _via_buffer_img_shown_timestamp = [];
  156. var _via_preload_img_promise_list = [];
  157. // via settings
  158. var _via_settings = {};
  159. _via_settings.ui = {};
  160. _via_settings.ui.annotation_editor_height = 25; // in percent of the height of browser window
  161. _via_settings.ui.annotation_editor_fontsize = 0.8;// in rem
  162. //_via_settings.ui.leftsidebar_width = 18; // in rem
  163. _via_settings.ui.leftsidebar_width = 43
  164. _via_settings.ui.image_grid = {};
  165. _via_settings.ui.image_grid.img_height = 80; // in pixel
  166. _via_settings.ui.image_grid.rshape_fill = 'none';
  167. _via_settings.ui.image_grid.rshape_fill_opacity = 0.3;
  168. _via_settings.ui.image_grid.rshape_stroke = 'yellow';
  169. _via_settings.ui.image_grid.rshape_stroke_width = 2;
  170. _via_settings.ui.image_grid.show_region_shape = true;
  171. _via_settings.ui.image_grid.show_image_policy = 'all';
  172. _via_settings.ui.image = {};
  173. _via_settings.ui.image.region_label = '__via_region_id__'; // default: region_id
  174. _via_settings.ui.image.region_color = '__via_default_region_color__'; // default color: yellow
  175. _via_settings.ui.image.region_label_font = '10px Sans';
  176. _via_settings.ui.image.on_image_annotation_editor_placement = VIA_ANNOTATION_EDITOR_PLACEMENT.NEAR_REGION;
  177. _via_settings.core = {};
  178. _via_settings.core.buffer_size = 4*VIA_IMG_PRELOAD_COUNT + 2;
  179. _via_settings.core.filepath = {};
  180. _via_settings.core.default_filepath = '';
  181. // UI html elements
  182. var invisible_file_input = document.getElementById("invisible_file_input");
  183. // var display_area = document.getElementById("display_area");
  184. var display_area = document.getElementById("show_region");
  185. var ui_top_panel = document.getElementById("ui_top_panel");
  186. var image_panel = document.getElementById("image_panel");
  187. var img_buffer_now = document.getElementById("img_buffer_now");
  188. var annotation_list_snippet = document.getElementById("annotation_list_snippet");
  189. var annotation_textarea = document.getElementById("annotation_textarea");
  190. var img_fn_list_panel = document.getElementById('img_fn_list_panel');
  191. var img_fn_list = document.getElementById('img_fn_list');
  192. var attributes_panel = document.getElementById('attributes_panel');
  193. var leftsidebar = document.getElementById('leftsidebar');
  194. var BBOX_LINE_WIDTH = 4;
  195. var BBOX_SELECTED_OPACITY = 0.3;
  196. var BBOX_BOUNDARY_FILL_COLOR_ANNOTATED = "#f2f2f2";
  197. var BBOX_BOUNDARY_FILL_COLOR_NEW = "#aaeeff";
  198. var BBOX_BOUNDARY_LINE_COLOR = "#1a1a1a";
  199. var BBOX_SELECTED_FILL_COLOR = "#ffffff";
  200. var VIA_ANNOTATION_EDITOR_HEIGHT_CHANGE = 5; // in percent
  201. var VIA_ANNOTATION_EDITOR_FONTSIZE_CHANGE = 0.1; // in rem
  202. var VIA_IMAGE_GRID_IMG_HEIGHT_CHANGE = 20; // in percent
  203. var VIA_LEFTSIDEBAR_WIDTH_CHANGE = 1; // in rem
  204. var VIA_POLYGON_SEGMENT_SUBTENDED_ANGLE = 5; // in degree (used to approximate shapes using polygon)
  205. var VIA_FLOAT_PRECISION = 3; // number of decimal places to include in float values
  206. function file_region() {
  207. this.shape_attributes = {}; // region shape attributes
  208. this.region_attributes = {}; // region attributes
  209. }
  210. //
  211. // Initialization routine
  212. //
  213. function _via_init() {
  214. console.log(VIA_NAME);
  215. show_message(VIA_NAME + ' (' + VIA_SHORT_NAME + ') version ' + VIA_VERSION +
  216. '. Ready !', 2*VIA_THEME_MESSAGE_TIMEOUT_MS);
  217. if ( _via_is_debug_mode ) {
  218. document.getElementById('ui_top_panel').innerHTML += '<span>DEBUG MODE</span>';
  219. }
  220. // document.getElementById('img_fn_list').style.display = 'block';
  221. document.getElementById('leftsidebar').style.display = 'table-cell';
  222. init_leftsidebar_accordion();
  223. init_message_panel();
  224. // run attached sub-modules (if any)
  225. // e.g. demo modules
  226. if (typeof _via_load_submodules === 'function') {
  227. console.log('Loading VIA submodule');
  228. setTimeout( async function() {
  229. await _via_load_submodules();
  230. }, 100);
  231. }
  232. }
  233. function is_content_name_valid(content_name) {
  234. var e;
  235. for ( e in VIA_DISPLAY_AREA_CONTENT_NAME ) {
  236. if ( VIA_DISPLAY_AREA_CONTENT_NAME[e] === content_name ) {
  237. return true;
  238. }
  239. }
  240. return false;
  241. }
  242. function set_display_area_content(content_name) {
  243. if ( is_content_name_valid(content_name) ) {
  244. _via_display_area_content_name_prev = _via_display_area_content_name;
  245. _via_display_area_content_name = content_name;
  246. }
  247. }
  248. //
  249. // Maintainers of user interface
  250. //
  251. function init_message_panel() {
  252. var p = document.getElementById('message_panel');
  253. p.addEventListener('mousedown', function() {
  254. this.style.display = 'none';
  255. }, false);
  256. p.addEventListener('mouseover', function() {
  257. clearTimeout(_via_message_clear_timer); // stop any previous timeouts
  258. }, false);
  259. }
  260. function show_message(msg, t) {
  261. if ( _via_message_clear_timer ) {
  262. clearTimeout(_via_message_clear_timer); // stop any previous timeouts
  263. }
  264. var timeout = t;
  265. if ( typeof t === 'undefined' ) {
  266. timeout = VIA_THEME_MESSAGE_TIMEOUT_MS;
  267. }
  268. document.getElementById('message_panel_content').innerHTML = msg;
  269. document.getElementById('message_panel').style.display = 'block';
  270. _via_message_clear_timer = setTimeout( function() {
  271. document.getElementById('message_panel').style.display = 'none';
  272. }, timeout);
  273. }
  274. function _via_regions_group_color_init() {
  275. _via_canvas_regions_group_color = {};
  276. var aid = _via_settings.ui.image.region_color;
  277. if ( aid !== '__via_default_region_color__' ) {
  278. var avalue;
  279. for ( var i = 0; i < regions.length; ++i ) {
  280. avalue = regions[i].other.region_attributes[aid];
  281. _via_canvas_regions_group_color[avalue] = 1;
  282. }
  283. var color_index = 0;
  284. for ( avalue in _via_canvas_regions_group_color ) {
  285. _via_canvas_regions_group_color[avalue] = VIA_REGION_COLOR_LIST[ color_index % VIA_REGION_COLOR_LIST.length ];
  286. color_index = color_index + 1;
  287. }
  288. }
  289. }
  290. function toggle_all_regions_selection(is_selected) {
  291. var n = regions.length;
  292. var i;
  293. _via_region_selected_flag = [];
  294. for ( i = 0; i < n; ++i) {
  295. _via_region_selected_flag[i] = is_selected;
  296. }
  297. _via_is_all_region_selected = is_selected;
  298. annotation_editor_hide();
  299. if ( _via_annotation_editor_mode === VIA_ANNOTATION_EDITOR_MODE.ALL_REGIONS ) {
  300. annotation_editor_clear_row_highlight();
  301. }
  302. }
  303. function select_only_region(region_id) {
  304. // toggle_all_regions_selection(false);
  305. // set_region_select_state(region_id, true);
  306. _via_is_region_selected = true;
  307. _via_is_all_region_selected = false;
  308. _via_user_sel_region_id = region_id;
  309. }
  310. function set_region_select_state(region_id, is_selected) {
  311. _via_region_selected_flag[region_id] = is_selected;
  312. }
  313. // source: https://www.w3schools.com/howto/howto_js_accordion.asp
  314. function init_leftsidebar_accordion() {
  315. var leftsidebar = document.getElementById('leftsidebar');
  316. // leftsidebar.style.width = _via_settings.ui.leftsidebar_width + 'rem';
  317. var acc = document.getElementsByClassName('leftsidebar_accordion');
  318. var i;
  319. for ( i = 0; i < acc.length; ++i ) {
  320. acc[i].addEventListener('click', function() {
  321. update_vertical_space();
  322. this.classList.toggle('active');
  323. this.nextElementSibling.classList.toggle('show');
  324. switch( this.innerHTML ) {
  325. case 'Attributes':
  326. update_attributes_update_panel();
  327. break;
  328. // case 'Project':
  329. // update_img_fn_list();
  330. // break;
  331. }
  332. });
  333. }
  334. }
  335. // this vertical spacer is needed to allow scrollbar to show
  336. // items like Keyboard Shortcut hidden under the attributes panel
  337. function update_vertical_space() {
  338. var panel = document.getElementById('vertical_space');
  339. var aepanel = document.getElementById('annotation_editor_panel');
  340. // panel.style.height = (aepanel.offsetHeight + 280) + 'px';
  341. }
  342. //
  343. // region and file attributes update panel
  344. //
  345. function attribute_update_panel_set_active_button() {
  346. var attribute_type;
  347. for ( attribute_type in _via_attributes ) {
  348. var bid = 'button_show_' + attribute_type + '_attributes';
  349. document.getElementById(bid).classList.remove('active');
  350. }
  351. var bid = 'button_show_' + _via_attribute_being_updated + '_attributes';
  352. document.getElementById(bid).classList.add('active');
  353. }
  354. function show_region_attributes_update_panel() {
  355. _via_attribute_being_updated = 'region';
  356. var rattr_list = Object.keys(_via_attributes['region']);
  357. if ( rattr_list.length ) {
  358. _via_current_attribute_id = rattr_list[0];
  359. } else {
  360. _via_current_attribute_id = '';
  361. }
  362. update_attributes_update_panel();
  363. attribute_update_panel_set_active_button();
  364. }
  365. function update_attributes_name_list() {
  366. var p = document.getElementById('attributes_name_list');
  367. p.innerHTML = '';
  368. var attr;
  369. var html=" <tr>\
  370. <th>属性值</th>\
  371. <th>操作</th>\
  372. </tr> ";
  373. for ( attr in _via_attributes[_via_attribute_being_updated] ){
  374. var row = "<tr>\
  375. <td id =\"attr\">"+attr+ "</td>"+
  376. "<td>"+
  377. "<a onclick=\"sessionStorage.setItem(\'attr_id\',\'"+attr+"\'); show_attribute_properties(); show_attribute_options()\" class=\"btn btn-xs btn-success\">" +"显示属性"+ "</a>" + "&nbsp;&nbsp;&nbsp;<a onclick=\"sessionStorage.setItem(\'attr_id\',\'"+attr+"\');delete_existing_attribute_with_confirm()\"; class=\"btn btn-xs btn-success\">删除属性</a>" +
  378. // "<td>" + "<a onclick= \"sessionStorage.setItem(\'attr_id\',\'"+attr+"\'); show_attribute_properties(); show_attribute_options();\">" +attr+ "</a>" +
  379. "</td>"+
  380. "</tr>";
  381. html=html+row;
  382. }
  383. document.getElementById('attributes_name_list').innerHTML=html;
  384. }
  385. function update_attributes_update_panel() {
  386. if ( document.getElementById('attributes_editor_panel').classList.contains('show') ) {
  387. update_attributes_name_list();
  388. // show_attribute_properties();
  389. // show_attribute_options();
  390. }
  391. }
  392. function update_attribute_properties_panel() {
  393. if ( document.getElementById('attributes_editor_panel').classList.contains('show') ) {
  394. show_attribute_properties();
  395. show_attribute_options();
  396. }
  397. }
  398. function show_attribute_properties() {
  399. // var attr_list = document.getElementById('attributes_name_list');
  400. document.getElementById('attribute_properties').innerHTML = '';
  401. var attr_id = sessionStorage.getItem("attr_id");
  402. var attr_type = _via_attribute_being_updated;
  403. if (attr_id == "color"){
  404. document.getElementById("type_color").style.display = "block";
  405. document.getElementById("type_car").style.display = "none";
  406. }
  407. else if (attr_id == "type"){
  408. document.getElementById("type_car").style.display = "block";
  409. document.getElementById("type_color").style.display = "none";
  410. }
  411. else {
  412. document.getElementById("type_color").style.display = "none";
  413. document.getElementById("type_car").style.display = "none";
  414. }
  415. var attr_input_type = _via_attributes[attr_type][attr_id].type;
  416. var attr_desc = _via_attributes[attr_type][attr_id].description;
  417. attribute_property_add_input_property('Name of attribute (appears in exported annotations)',
  418. 'Name',
  419. attr_id,
  420. 'attribute_name');
  421. attribute_property_add_input_property('Description of attribute (shown to user during annotation session)',
  422. 'Desc.',
  423. attr_desc,
  424. 'attribute_description');
  425. if ( attr_input_type === 'text' ) {
  426. var attr_default_value = _via_attributes[attr_type][attr_id].default_value;
  427. attribute_property_add_input_property('Default value of this attribute',
  428. 'Def.',
  429. attr_default_value,
  430. 'attribute_default_value');
  431. }
  432. // add dropdown for type of attribute
  433. var p = document.createElement('div');
  434. p.setAttribute('class', 'property');
  435. var c0 = document.createElement('span');
  436. c0.setAttribute('title', 'Attribute type (e.g. text, checkbox, radio, etc)');
  437. c0.innerHTML = 'Type';
  438. var c1 = document.createElement('span');
  439. var c1b = document.createElement('select');
  440. c1b.setAttribute('onchange', 'attribute_property_on_update(this)');
  441. c1b.setAttribute('id', 'attribute_type');
  442. var type_id;
  443. for ( type_id in VIA_ATTRIBUTE_TYPE ) {
  444. var type = VIA_ATTRIBUTE_TYPE[type_id];
  445. var option = document.createElement('option');
  446. option.setAttribute('value', type);
  447. option.innerHTML = type;
  448. if ( attr_input_type == type ) {
  449. option.setAttribute('selected', 'selected');
  450. }
  451. c1b.appendChild(option);
  452. }
  453. c1.appendChild(c1b);
  454. p.appendChild(c0);
  455. p.appendChild(c1);
  456. document.getElementById('attribute_properties').appendChild(p);
  457. }
  458. function show_attribute_options() {
  459. // var attr_list = document.getElementById('attributes_name_list');
  460. document.getElementById('attribute_options').innerHTML = '';
  461. document.getElementById('attribute_options').innerHTML = '';
  462. // var attr_id = attr_list.value;
  463. var attr_id = sessionStorage.getItem("attr_id");
  464. var attr_type = _via_attributes[_via_attribute_being_updated][attr_id].type;
  465. // populate additional options based on attribute type
  466. switch( attr_type ) {
  467. case VIA_ATTRIBUTE_TYPE.TEXT:
  468. // text does not have any additional properties
  469. break;
  470. case VIA_ATTRIBUTE_TYPE.IMAGE:
  471. var p = document.createElement('div');
  472. p.setAttribute('class', 'property');
  473. p.setAttribute('style', 'text-align:center');
  474. var c0 = document.createElement('span');
  475. c0.setAttribute('style', 'width:25%');
  476. c0.setAttribute('title', 'When selected, this is the value that appears in exported annotations');
  477. c0.innerHTML = 'id';
  478. var c1 = document.createElement('span');
  479. c1.setAttribute('style', 'width:60%');
  480. c1.setAttribute('title', 'URL or base64 (see https://www.base64-image.de/) encoded image data that corresponds to the image shown as an option to the annotator');
  481. c1.innerHTML = 'image url or b64';
  482. var c2 = document.createElement('span');
  483. c2.setAttribute('title', 'The default value of this attribute');
  484. c2.innerHTML = 'def.';
  485. p.appendChild(c0);
  486. p.appendChild(c1);
  487. p.appendChild(c2);
  488. document.getElementById('attribute_options').appendChild(p);
  489. var options = _via_attributes[_via_attribute_being_updated][attr_id].options;
  490. var option_id;
  491. for ( option_id in options ) {
  492. var option_desc = options[option_id];
  493. var option_default = _via_attributes[_via_attribute_being_updated][attr_id].default_options[option_id];
  494. attribute_property_add_option(attr_id, option_id, option_desc, option_default, attr_type);
  495. }
  496. attribute_property_add_new_entry_option(attr_id, attr_type);
  497. break;
  498. case VIA_ATTRIBUTE_TYPE.CHECKBOX: // handled by next case
  499. case VIA_ATTRIBUTE_TYPE.DROPDOWN: // handled by next case
  500. case VIA_ATTRIBUTE_TYPE.RADIO:
  501. var p = document.createElement('div');
  502. p.setAttribute('class', 'property');
  503. p.setAttribute('style', 'text-align:center');
  504. var c0 = document.createElement('span');
  505. c0.setAttribute('style', 'width:25%');
  506. c0.setAttribute('title', 'When selected, this is the value that appears in exported annotations');
  507. c0.innerHTML = 'id';
  508. var c1 = document.createElement('span');
  509. c1.setAttribute('style', 'width:60%');
  510. c1.setAttribute('title', 'This is the text shown as an option to the annotator');
  511. c1.innerHTML = 'description';
  512. var c2 = document.createElement('span');
  513. c2.setAttribute('title', 'The default value of this attribute');
  514. c2.innerHTML = 'def.';
  515. p.appendChild(c0);
  516. p.appendChild(c1);
  517. p.appendChild(c2);
  518. document.getElementById('attribute_options').appendChild(p);
  519. var options = _via_attributes[_via_attribute_being_updated][attr_id].options;
  520. var option_id;
  521. for ( option_id in options ) {
  522. var option_desc = options[option_id];
  523. var option_default = _via_attributes[_via_attribute_being_updated][attr_id].default_options[option_id];
  524. attribute_property_add_option(attr_id, option_id, option_desc, option_default, attr_type);
  525. }
  526. attribute_property_add_new_entry_option(attr_id, attr_type);
  527. break;
  528. default:
  529. console.log('Attribute type ' + attr_type + ' is unavailable');
  530. }
  531. }
  532. function attribute_property_add_input_property(title, name, value, id) {
  533. var p = document.createElement('div');
  534. p.setAttribute('class', 'property');
  535. var c0 = document.createElement('span');
  536. c0.setAttribute('title', title);
  537. c0.innerHTML = name;
  538. var c1 = document.createElement('span');
  539. var c1b = document.createElement('input');
  540. c1b.setAttribute('onchange', 'attribute_property_on_update(this)');
  541. if ( typeof(value) !== 'undefined' ) {
  542. c1b.setAttribute('value', value);
  543. }
  544. c1b.setAttribute('id', id);
  545. c1.appendChild(c1b);
  546. p.appendChild(c0);
  547. p.appendChild(c1);
  548. document.getElementById('attribute_properties').appendChild(p);
  549. }
  550. function attribute_property_add_option(attr_id, option_id, option_desc, option_default, attribute_type) {
  551. var p = document.createElement('div');
  552. p.setAttribute('class', 'property');
  553. var c0 = document.createElement('span');
  554. var c0b = document.createElement('input');
  555. c0b.setAttribute('type', 'text');
  556. c0b.setAttribute('value', option_id);
  557. c0b.setAttribute('title', option_id);
  558. c0b.setAttribute('onchange', 'attribute_property_on_option_update(this)');
  559. c0b.setAttribute('id', '_via_attribute_option_id_' + option_id);
  560. var c1 = document.createElement('span');
  561. var c1b = document.createElement('input');
  562. c1b.setAttribute('type', 'text');
  563. if ( attribute_type === VIA_ATTRIBUTE_TYPE.IMAGE ) {
  564. var option_desc_info = option_desc.length + ' bytes of base64 image data';
  565. c1b.setAttribute('value', option_desc_info);
  566. c1b.setAttribute('title', 'To update, copy and paste base64 image data in this text box');
  567. } else {
  568. c1b.setAttribute('value', option_desc);
  569. c1b.setAttribute('title', option_desc);
  570. }
  571. c1b.setAttribute('onchange', 'attribute_property_on_option_update(this)');
  572. c1b.setAttribute('id', '_via_attribute_option_description_' + option_id);
  573. var c2 = document.createElement('span');
  574. var c2b = document.createElement('input');
  575. c2b.setAttribute('type', attribute_type);
  576. if ( typeof option_default !== 'undefined' ) {
  577. c2b.checked = option_default;
  578. }
  579. if ( attribute_type === 'radio' || attribute_type === 'image' || attribute_type === 'dropdown' ) {
  580. // ensured that user can activate only one radio button
  581. c2b.setAttribute('type', 'radio');
  582. c2b.setAttribute('name', attr_id);
  583. }
  584. c2b.setAttribute('onchange', 'attribute_property_on_option_update(this)');
  585. c2b.setAttribute('id', '_via_attribute_option_default_' + option_id);
  586. c0.appendChild(c0b);
  587. c1.appendChild(c1b);
  588. c2.appendChild(c2b);
  589. p.appendChild(c0);
  590. p.appendChild(c1);
  591. p.appendChild(c2);
  592. document.getElementById('attribute_options').appendChild(p);
  593. }
  594. function attribute_property_add_new_entry_option(attr_id, attribute_type) {
  595. var p = document.createElement('div');
  596. p.setAttribute('class', 'new_option_id_entry');
  597. var c0b = document.createElement('input');
  598. c0b.setAttribute('type', 'text');
  599. c0b.setAttribute('onchange', 'attribute_property_on_option_add(this)');
  600. c0b.setAttribute('id', '_via_attribute_new_option_id');
  601. c0b.setAttribute('placeholder', 'Add new option id');
  602. p.appendChild(c0b);
  603. document.getElementById('attribute_options').appendChild(p);
  604. }
  605. function attribute_property_on_update(p) {
  606. var attr_id = get_current_attribute_id();
  607. var attr_type = _via_attribute_being_updated;
  608. var attr_value = p.value;
  609. switch(p.id) {
  610. case 'attribute_name':
  611. if ( attr_value !== attr_id ) {
  612. Object.defineProperty(_via_attributes[attr_type],
  613. attr_value,
  614. Object.getOwnPropertyDescriptor(_via_attributes[attr_type], attr_id));
  615. delete _via_attributes[attr_type][attr_id];
  616. update_attributes_update_panel();
  617. annotation_editor_update_content(regions);
  618. }
  619. break;
  620. case 'attribute_description':
  621. _via_attributes[attr_type][attr_id].description = attr_value;
  622. update_attributes_update_panel();
  623. annotation_editor_update_content(regions);
  624. break;
  625. case 'attribute_default_value':
  626. _via_attributes[attr_type][attr_id].default_value = attr_value;
  627. update_attributes_update_panel();
  628. annotation_editor_update_content(regions);
  629. break;
  630. case 'attribute_type':
  631. _via_attributes[attr_type][attr_id].type = attr_value;
  632. if( attr_value === VIA_ATTRIBUTE_TYPE.TEXT ) {
  633. _via_attributes[attr_type][attr_id].default_value = '';
  634. delete _via_attributes[attr_type][attr_id].options;
  635. delete _via_attributes[attr_type][attr_id].default_options;
  636. } else {
  637. // preserve existing options
  638. if ( ! _via_attributes[attr_type][attr_id].hasOwnProperty('options') ) {
  639. _via_attributes[attr_type][attr_id].options = {};
  640. _via_attributes[attr_type][attr_id].default_options = {};
  641. }
  642. if ( _via_attributes[attr_type][attr_id].hasOwnProperty('default_value') ) {
  643. delete _via_attributes[attr_type][attr_id].default_value;
  644. }
  645. // collect existing attribute values and add them as options
  646. var attr_values = attribute_get_unique_values(attr_type, attr_id);
  647. var i;
  648. for ( i = 0; i < attr_values.length; ++i ) {
  649. var attr_val = attr_values[i];
  650. if ( attr_val !== '' ) {
  651. _via_attributes[attr_type][attr_id].options[attr_val] = attr_val;
  652. }
  653. }
  654. }
  655. show_attribute_properties();
  656. show_attribute_options();
  657. annotation_editor_update_content(regions);
  658. break;
  659. }
  660. }
  661. function attribute_get_unique_values(attr_type, attr_id) {
  662. var values = [];
  663. switch ( attr_type ) {
  664. case 'region':
  665. var img_id, attr_val, i;
  666. // for ( img_id in _via_img_metadata ) {
  667. if (regions!== undefined){
  668. for ( i = 0; i < regions.length; ++i ) {
  669. // if (_via_img_metadata[img_id].regions[i].hasOwnProperty("region_attributes")){
  670. if (regions[i]!== undefined){
  671. if ( regions[i].other.region_attributes.hasOwnProperty(attr_id) ) {
  672. attr_val = regions[i].other.region_attributes[attr_id];
  673. if ( ! values.includes(attr_val) ) {
  674. values.push(attr_val);
  675. }
  676. }
  677. }
  678. }
  679. }
  680. // }
  681. break;
  682. default:
  683. break;
  684. }
  685. return values;
  686. }
  687. function attribute_property_on_option_update(p) {
  688. var attr_id = get_current_attribute_id();
  689. if ( p.id.startsWith('_via_attribute_option_id_') ) {
  690. var old_key = p.id.substr( '_via_attribute_option_id_'.length );
  691. var new_key = p.value;
  692. if ( old_key !== new_key ) {
  693. var option_id_test = attribute_property_option_id_is_valid(attr_id, new_key);
  694. if ( option_id_test.is_valid ) {
  695. update_attribute_option_id_with_confirm(_via_attribute_being_updated,
  696. attr_id,
  697. old_key,
  698. new_key);
  699. } else {
  700. p.value = old_key; // restore old value
  701. show_message( option_id_test.message );
  702. show_attribute_properties();
  703. }
  704. return;
  705. }
  706. }
  707. if ( p.id.startsWith('_via_attribute_option_description_') ) {
  708. var key = p.id.substr( '_via_attribute_option_description_'.length );
  709. var old_value = _via_attributes[_via_attribute_being_updated][attr_id].options[key];
  710. var new_value = p.value;
  711. if ( new_value !== old_value ) {
  712. _via_attributes[_via_attribute_being_updated][attr_id].options[key] = new_value;
  713. show_attribute_properties();
  714. annotation_editor_update_content(regions);
  715. }
  716. }
  717. if ( p.id.startsWith('_via_attribute_option_default_') ) {
  718. var new_default_option_id = p.id.substr( '_via_attribute_option_default_'.length );
  719. var old_default_option_id_list = Object.keys(_via_attributes[_via_attribute_being_updated][attr_id].default_options);
  720. if ( old_default_option_id_list.length === 0 ) {
  721. // default set for the first time
  722. _via_attributes[_via_attribute_being_updated][attr_id].default_options[new_default_option_id] = p.checked;
  723. } else {
  724. switch ( _via_attributes[_via_attribute_being_updated][attr_id].type ) {
  725. case 'image': // fallback
  726. case 'dropdown': // fallback
  727. case 'radio': // fallback
  728. // to ensure that only one radio button is selected at a time
  729. _via_attributes[_via_attribute_being_updated][attr_id].default_options = {};
  730. _via_attributes[_via_attribute_being_updated][attr_id].default_options[new_default_option_id] = p.checked;
  731. break;
  732. case 'checkbox':
  733. _via_attributes[_via_attribute_being_updated][attr_id].default_options[new_default_option_id] = p.checked;
  734. break;
  735. }
  736. }
  737. // default option updated
  738. attribute_property_on_option_default_update(_via_attribute_being_updated,
  739. attr_id,
  740. new_default_option_id).then( function() {
  741. show_attribute_properties();
  742. annotation_editor_update_content(regons);
  743. });
  744. }
  745. }
  746. function attribute_property_on_option_default_update(attribute_being_updated, attr_id, new_default_option_id) {
  747. return new Promise( function(ok_callback, err_callback) {
  748. // set all metadata to new_value if:
  749. // - metadata[attr_id] is missing
  750. // - metadata[attr_id] is set to option_old_value
  751. var img_id, attr_value, n, i;
  752. var attr_type = _via_attributes[attribute_being_updated][attr_id].type;
  753. switch( attribute_being_updated ) {
  754. case 'region':
  755. // for ( img_id in _via_img_metadata ) {
  756. n = regions.length;
  757. for ( i = 0; i < n; ++i ) {
  758. if ( !regions[i].other.region_attributes.hasOwnProperty(attr_id) ) {
  759. regions[i].other.region_attributes[attr_id] = new_default_option_id;
  760. }
  761. }
  762. // }
  763. break;
  764. }
  765. ok_callback();
  766. });
  767. }
  768. function attribute_property_on_option_add(p) {
  769. if ( p.value === '' || p.value === null ) {
  770. return;
  771. }
  772. if ( p.id === '_via_attribute_new_option_id' ) {
  773. var attr_id = get_current_attribute_id();
  774. var option_id = p.value;
  775. var option_id_test = attribute_property_option_id_is_valid(attr_id, option_id);
  776. if ( option_id_test.is_valid ) {
  777. _via_attributes[_via_attribute_being_updated][attr_id].options[option_id] = '';
  778. show_attribute_options();
  779. annotation_editor_update_content(regions);
  780. } else {
  781. show_message( option_id_test.message );
  782. attribute_property_reset_new_entry_inputs();
  783. }
  784. }
  785. }
  786. function attribute_property_reset_new_entry_inputs() {
  787. var container = document.getElementById('attribute_options');
  788. var p = container.lastChild;
  789. console.log(p.childNodes)
  790. if ( p.childNodes[0] ) {
  791. p.childNodes[0].value = '';
  792. }
  793. if ( p.childNodes[1] ) {
  794. p.childNodes[1].value = '';
  795. }
  796. }
  797. function attribute_property_show_new_entry_inputs(attr_id, attribute_type) {
  798. var n0 = document.createElement('div');
  799. n0.classList.add('property');
  800. var n1a = document.createElement('span');
  801. var n1b = document.createElement('input');
  802. n1b.setAttribute('onchange', 'attribute_property_on_option_add(this)');
  803. n1b.setAttribute('placeholder', 'Add new id');
  804. n1b.setAttribute('value', '');
  805. n1b.setAttribute('id', '_via_attribute_new_option_id');
  806. n1a.appendChild(n1b);
  807. var n2a = document.createElement('span');
  808. var n2b = document.createElement('input');
  809. n2b.setAttribute('onchange', 'attribute_property_on_option_add(this)');
  810. n2b.setAttribute('placeholder', 'Optional description');
  811. n2b.setAttribute('value', '');
  812. n2b.setAttribute('id', '_via_attribute_new_option_description');
  813. n2a.appendChild(n2b);
  814. var n3a = document.createElement('span');
  815. var n3b = document.createElement('input');
  816. n3b.setAttribute('type', attribute_type);
  817. if ( attribute_type === 'radio' ) {
  818. n3b.setAttribute('name', attr_id);
  819. }
  820. n3b.setAttribute('onchange', 'attribute_property_on_option_add(this)');
  821. n3b.setAttribute('id', '_via_attribute_new_option_default');
  822. n3a.appendChild(n3b);
  823. n0.appendChild(n1a);
  824. n0.appendChild(n2a);
  825. n0.appendChild(n3a);
  826. var container = document.getElementById('attribute_options');
  827. container.appendChild(n0);
  828. }
  829. function attribute_property_option_id_is_valid(attr_id, new_option_id) {
  830. var option_id;
  831. for ( option_id in _via_attributes[_via_attribute_being_updated][attr_id].options ) {
  832. if ( option_id === new_option_id ) {
  833. return { 'is_valid':false, 'message':'Option id [' + attr_id + '] already exists' };
  834. }
  835. }
  836. if ( new_option_id.includes('__') ) { // reserved separator for attribute-id, row-id, option-id
  837. return {'is_valid':false, 'message':'Option id cannot contain two consecutive underscores'};
  838. }
  839. return {'is_valid':true};
  840. }
  841. function attribute_property_id_exists(name) {
  842. var attr_name;
  843. for ( attr_name in _via_attributes[_via_attribute_being_updated] ) {
  844. if ( attr_name === name ) {
  845. return true;
  846. }
  847. }
  848. return false;
  849. }
  850. function delete_existing_attribute_with_confirm() {
  851. // var attr_id = document.getElementById('user_input_attribute_id').value;
  852. var attr_id = sessionStorage.getItem("attr_id");
  853. if ( attr_id === '' ) {
  854. show_message('Enter the name of attribute that you wish to delete');
  855. return;
  856. }
  857. if ( attribute_property_id_exists(attr_id) ) {
  858. var config = {'title':'Delete ' + _via_attribute_being_updated + ' attribute [' + attr_id + ']' };
  859. var input = { 'attr_type':{'type':'text', 'name':'Attribute Type', 'value':_via_attribute_being_updated, 'disabled':true},
  860. 'attr_id':{'type':'text', 'name':'Attribute Id', 'value':attr_id, 'disabled':true}
  861. };
  862. if(attr_id === "type" || attr_id ==="id")
  863. {
  864. alert("不能删除属性type或者id,可以修改信息");
  865. // show_message(' does not delete type!');
  866. return;
  867. }
  868. delete_existing_attribute_confirmed(input);
  869. // invoke_with_user_inputs(delete_existing_attribute_confirmed, input, config);
  870. // document.getElementById('attributes_editor_panel').innerHTML = '';
  871. } else {
  872. show_message('Attribute [' + attr_id + '] does not exist!');
  873. return;
  874. }
  875. }
  876. function delete_existing_attribute_confirmed(input) {
  877. var attr_type = input.attr_type.value;
  878. var attr_id = input.attr_id.value;
  879. delete_existing_attribute(attr_type, attr_id);
  880. document.getElementById('user_input_attribute_id').value = '';
  881. show_message('Deleted ' + attr_type + ' attribute [' + attr_id + ']');
  882. user_input_default_cancel_handler();
  883. document.getElementById('attribute_properties').innerHTML = '';
  884. document.getElementById('attribute_options').innerHTML = '';
  885. }
  886. function delete_existing_attribute(attribute_type, attribute_id) {
  887. if ( _via_attributes[attribute_type].hasOwnProperty( attribute_id ) ) {
  888. var attr_id_list = Object.keys(_via_attributes[attribute_type]);
  889. if ( attr_id_list.length === 1 ) {
  890. _via_current_attribute_id = '';
  891. } else {
  892. var current_index = attr_id_list.indexOf(attribute_id);
  893. var next_index = current_index + 1;
  894. if ( next_index === attr_id_list.length ) {
  895. next_index = current_index - 1;
  896. }
  897. _via_current_attribute_id = attr_id_list[next_index];
  898. }
  899. delete _via_attributes[attribute_type][attribute_id];
  900. update_attributes_update_panel();
  901. // annotation_editor_update_content();
  902. }
  903. }
  904. function add_new_attribute_from_user_input() {
  905. var attr_id = document.getElementById('user_input_attribute_id').value;
  906. if ( attr_id === '' ) {
  907. show_message('Enter the name of attribute that you wish to delete');
  908. return;
  909. }
  910. if ( attribute_property_id_exists(attr_id) ) {
  911. show_message('The ' + _via_attribute_being_updated + ' attribute [' + attr_id + '] already exists.');
  912. } else {
  913. _via_current_attribute_id = attr_id;
  914. add_new_attribute(attr_id);
  915. update_attributes_update_panel();
  916. document.getElementById('attribute_properties').innerHTML = '';
  917. document.getElementById('attribute_options').innerHTML = '';
  918. document.getElementById("type_color").style.display = "none";
  919. document.getElementById("type_car").style.display = "none";
  920. annotation_editor_update_content(regions);
  921. show_message('Added ' + _via_attribute_being_updated + ' attribute [' + attr_id + '].');
  922. }
  923. }
  924. function add_new_attribute(attribute_id) {
  925. _via_attributes[_via_attribute_being_updated][attribute_id] = {};
  926. _via_attributes[_via_attribute_being_updated][attribute_id].type = 'text';
  927. _via_attributes[_via_attribute_being_updated][attribute_id].description = '';
  928. _via_attributes[_via_attribute_being_updated][attribute_id].default_value = '';
  929. }
  930. function update_current_attribute_id(p) {
  931. _via_current_attribute_id = p.options[p.selectedIndex].value;
  932. update_attribute_properties_panel();
  933. }
  934. function get_current_attribute_id() {
  935. // return document.getElementById('attributes_name_list').value;
  936. return sessionStorage.getItem("attr_id");
  937. }
  938. function update_attribute_option_id_with_confirm(attr_type, attr_id, option_id, new_option_id) {
  939. var is_delete = false;
  940. var config;
  941. if ( new_option_id === '' || typeof(new_option_id) === 'undefined' ) {
  942. // an empty new_option_id indicates deletion of option_id
  943. config = {'title':'Delete an option for ' + attr_type + ' attribute'};
  944. is_delete = true;
  945. } else {
  946. config = {'title':'Rename an option for ' + attr_type + ' attribute'};
  947. }
  948. var input = { 'attr_type':{'type':'text', 'name':'Attribute Type', 'value':attr_type, 'disabled':true},
  949. 'attr_id':{'type':'text', 'name':'Attribute Id', 'value':attr_id, 'disabled':true}
  950. };
  951. if ( is_delete ) {
  952. input['option_id'] = {'type':'text', 'name':'Attribute Option', 'value':option_id, 'disabled':true};
  953. } else {
  954. input['option_id'] = {'type':'text', 'name':'Attribute Option (old)', 'value':option_id, 'disabled':true},
  955. input['new_option_id'] = {'type':'text', 'name':'Attribute Option (new)', 'value':new_option_id, 'disabled':true};
  956. }
  957. invoke_with_user_inputs(update_attribute_option_id_confirmed, input, config, update_attribute_option_id_cancel);
  958. }
  959. function update_attribute_option_id_cancel(input) {
  960. update_attribute_properties_panel();
  961. }
  962. function update_attribute_option_id_confirmed(input) {
  963. var attr_type = input.attr_type.value;
  964. var attr_id = input.attr_id.value;
  965. var option_id = input.option_id.value;
  966. var is_delete;
  967. var new_option_id;
  968. if ( typeof(input.new_option_id) === 'undefined' || input.new_option_id === '' ) {
  969. is_delete = true;
  970. new_option_id = '';
  971. } else {
  972. is_delete = false;
  973. new_option_id = input.new_option_id.value;
  974. }
  975. update_attribute_option(is_delete, attr_type, attr_id, option_id, new_option_id);
  976. if ( is_delete ) {
  977. show_message('Deleted option [' + option_id + '] for ' + attr_type + ' attribute [' + attr_id + '].');
  978. } else {
  979. show_message('Renamed option [' + option_id + '] to [' + new_option_id + '] for ' + attr_type + ' attribute [' + attr_id + '].');
  980. }
  981. update_attribute_properties_panel();
  982. annotation_editor_update_content();
  983. user_input_default_cancel_handler();
  984. }
  985. function update_attribute_option(is_delete, attr_type, attr_id, option_id, new_option_id) {
  986. switch ( attr_type ) {
  987. case 'region':
  988. update_region_attribute_option_in_all_metadata(is_delete, attr_id, option_id, new_option_id);
  989. if ( ! is_delete ) {
  990. Object.defineProperty(_via_attributes[attr_type][attr_id].options,
  991. new_option_id,
  992. Object.getOwnPropertyDescriptor(_via_attributes[_via_attribute_being_updated][attr_id].options, option_id));
  993. }
  994. delete _via_attributes['region'][attr_id].options[option_id];
  995. break;
  996. }
  997. }
  998. function update_region_attribute_option_in_all_metadata(is_delete, attr_id, option_id, new_option_id) {
  999. // var image_id;
  1000. // for ( image_id in _via_img_metadata ) {
  1001. update_region_attribute_option_from_metadata( is_delete, attr_id, option_id, new_option_id);
  1002. // }
  1003. }
  1004. function update_region_attribute_option_from_metadata(is_delete, attr_id, option_id, new_option_id) {
  1005. var i;
  1006. if (regions!== undefined){
  1007. for ( i = 0; i < regions.length; ++i ) {
  1008. if ( regions[i]!==undefined){
  1009. if ( regions[i].other.region_attributes.hasOwnProperty(attr_id) ) {
  1010. if ( regions[i].other.region_attributes[attr_id].hasOwnProperty(option_id) ) {
  1011. Object.defineProperty(regions[i].other.region_attributes[attr_id],
  1012. new_option_id,
  1013. Object.getOwnPropertyDescriptor(regions[i].other.region_attributes[attr_id], option_id));
  1014. delete regions[i].other.region_attributes[attr_id][option_id];
  1015. }
  1016. }
  1017. }
  1018. }
  1019. }
  1020. }
  1021. //
  1022. // invoke a method after receiving inputs from user
  1023. //
  1024. function invoke_with_user_inputs(ok_handler, input, config, cancel_handler) {
  1025. setup_user_input_panel(ok_handler, input, config, cancel_handler);
  1026. show_user_input_panel();
  1027. }
  1028. function setup_user_input_panel(ok_handler, input, config, cancel_handler) {
  1029. _via_user_input_ok_handler = ok_handler;
  1030. _via_user_input_cancel_handler = cancel_handler;
  1031. _via_user_input_data = input;
  1032. var p = document.getElementById('user_input_panel');
  1033. var c = document.createElement('div');
  1034. c.setAttribute('class', 'content');
  1035. var html = [];
  1036. html.push('<p class="title">' + config.title + '</p>');
  1037. html.push('<div class="user_inputs">');
  1038. var key;
  1039. for ( key in _via_user_input_data ) {
  1040. html.push('<div class="row">');
  1041. html.push('<span class="cell">' + _via_user_input_data[key].name + '</span>');
  1042. var disabled_html = '';
  1043. if ( _via_user_input_data[key].disabled ) {
  1044. disabled_html = 'disabled="disabled"';
  1045. }
  1046. var value_html = '';
  1047. if ( _via_user_input_data[key].value ) {
  1048. value_html = 'value="' + _via_user_input_data[key].value + '"';
  1049. }
  1050. switch(_via_user_input_data[key].type) {
  1051. case 'checkbox':
  1052. if ( _via_user_input_data[key].checked ) {
  1053. value_html = 'checked="checked"';
  1054. } else {
  1055. value_html = '';
  1056. }
  1057. html.push('<span class="cell">' +
  1058. '<input class="_via_user_input_variable" ' +
  1059. value_html + ' ' +
  1060. disabled_html + ' ' +
  1061. 'type="checkbox" id="' + key + '"></span>');
  1062. break;
  1063. case 'text':
  1064. var size = '50';
  1065. if ( _via_user_input_data[key].size ) {
  1066. size = _via_user_input_data[key].size;
  1067. }
  1068. var placeholder = '';
  1069. if ( _via_user_input_data[key].placeholder ) {
  1070. placeholder = _via_user_input_data[key].placeholder;
  1071. }
  1072. html.push('<span class="cell">' +
  1073. '<input class="_via_user_input_variable" ' +
  1074. value_html + ' ' +
  1075. disabled_html + ' ' +
  1076. 'size="' + size + '" ' +
  1077. 'placeholder="' + placeholder + '" ' +
  1078. 'type="text" id="' + key + '"></span>');
  1079. break;
  1080. case 'textarea':
  1081. var rows = '2';
  1082. var cols = '10'
  1083. if ( _via_user_input_data[key].rows ) {
  1084. rows = _via_user_input_data[key].rows;
  1085. }
  1086. if ( _via_user_input_data[key].cols ) {
  1087. cols = _via_user_input_data[key].cols;
  1088. }
  1089. var placeholder = '';
  1090. if ( _via_user_input_data[key].placeholder ) {
  1091. placeholder = _via_user_input_data[key].placeholder;
  1092. }
  1093. html.push('<span class="cell">' +
  1094. '<textarea class="_via_user_input_variable" ' +
  1095. disabled_html + ' ' +
  1096. 'rows="' + rows + '" ' +
  1097. 'cols="' + cols + '" ' +
  1098. 'placeholder="' + placeholder + '" ' +
  1099. 'id="' + key + '">' + value_html + '</textarea></span>');
  1100. break;
  1101. }
  1102. html.push('</div>'); // end of row
  1103. }
  1104. html.push('</div>'); // end of user_input div
  1105. html.push('<div class="user_confirm">' +
  1106. '<span class="ok">' +
  1107. '<button id="user_input_ok_button" onclick="user_input_parse_and_invoke_handler()">&nbsp;OK&nbsp;</button></span>' +
  1108. '<span class="cancel">' +
  1109. '<button id="user_input_cancel_button" onclick="user_input_cancel_handler()">CANCEL</button></span></div>');
  1110. c.innerHTML = html.join('');
  1111. p.innerHTML = '';
  1112. p.appendChild(c);
  1113. }
  1114. function user_input_default_cancel_handler() {
  1115. hide_user_input_panel();
  1116. _via_user_input_data = {};
  1117. _via_user_input_ok_handler = null;
  1118. _via_user_input_cancel_handler = null;
  1119. }
  1120. function user_input_cancel_handler() {
  1121. if ( _via_user_input_cancel_handler ) {
  1122. _via_user_input_cancel_handler();
  1123. }
  1124. user_input_default_cancel_handler();
  1125. }
  1126. function user_input_parse_and_invoke_handler() {
  1127. var elist = document.getElementsByClassName('_via_user_input_variable');
  1128. var i;
  1129. for ( i=0; i < elist.length; ++i ) {
  1130. var eid = elist[i].id;
  1131. if ( _via_user_input_data.hasOwnProperty(eid) ) {
  1132. switch(_via_user_input_data[eid].type) {
  1133. case 'checkbox':
  1134. _via_user_input_data[eid].value = elist[i].checked;
  1135. break;
  1136. default:
  1137. _via_user_input_data[eid].value = elist[i].value;
  1138. break;
  1139. }
  1140. }
  1141. }
  1142. if ( typeof(_via_user_input_data.confirm) !== 'undefined' ) {
  1143. if ( _via_user_input_data.confirm.value ) {
  1144. _via_user_input_ok_handler(_via_user_input_data);
  1145. } else {
  1146. if ( _via_user_input_cancel_handler ) {
  1147. _via_user_input_cancel_handler();
  1148. }
  1149. }
  1150. } else {
  1151. _via_user_input_ok_handler(_via_user_input_data);
  1152. }
  1153. user_input_default_cancel_handler();
  1154. }
  1155. function show_user_input_panel() {
  1156. document.getElementById('user_input_panel').style.display = 'block';
  1157. }
  1158. function hide_user_input_panel() {
  1159. document.getElementById('user_input_panel').style.display = 'none';
  1160. }
  1161. //
  1162. // annotations editor panel
  1163. //
  1164. function annotation_editor_show(topx,lefty,rectIndex,recttype) {
  1165. // remove existing annotation editor (if any)
  1166. annotation_editor_remove();
  1167. // create new container of annotation editor
  1168. var ae = document.createElement('div');
  1169. ae.setAttribute('id', 'annotation_editor');
  1170. if ( _via_annotation_editor_mode === VIA_ANNOTATION_EDITOR_MODE.SINGLE_REGION ) {
  1171. if ( _via_settings.ui.image.on_image_annotation_editor_placement === VIA_ANNOTATION_EDITOR_PLACEMENT.DISABLE ) {
  1172. return;
  1173. }
  1174. // only display on-image annotation editor if
  1175. // - region attribute are defined
  1176. // - region is selected
  1177. if ( _via_is_region_selected &&
  1178. Object.keys(_via_attributes['region']).length &&
  1179. _via_attributes['region'].constructor === Object ) {
  1180. //ae.classList.add('force_small_font');
  1181. //ae.classList.add('display_area_content'); // to enable automatic hiding of this content
  1182. // add annotation editor to image_panel
  1183. if ( _via_settings.ui.image.on_image_annotation_editor_placement === VIA_ANNOTATION_EDITOR_PLACEMENT.NEAR_REGION ) {
  1184. // var html_position = annotation_editor_get_placement(_via_user_sel_region_id);
  1185. console.log("location, topx=" + topx + ", lefty=" + lefty + " dfdfd");
  1186. // ae.setAttribute('style', 'top:' + topx + 'px;left:' + lefty + 'px;position:relative');
  1187. ae.setAttribute('style', 'top:' + topx + 'px;left:' + lefty + 'px;position:relative');
  1188. }
  1189. _via_display_area.appendChild(ae);
  1190. // switch (recttype)
  1191. annotation_editor_update_content(recttype);
  1192. update_vertical_space();
  1193. }
  1194. }
  1195. }
  1196. function annotation_editor_hide() {
  1197. if ( _via_annotation_editor_mode === VIA_ANNOTATION_EDITOR_MODE.SINGLE_REGION ) {
  1198. // remove existing annotation editor (if any)
  1199. annotation_editor_remove();
  1200. } else {
  1201. annotation_editor_clear_row_highlight();
  1202. }
  1203. }
  1204. function annotation_editor_update_content(recttype) {
  1205. return new Promise( function(ok_callback, err_callback) {
  1206. var ae = document.getElementById('annotation_editor');
  1207. if (ae ) {
  1208. ae.innerHTML = '';
  1209. annotation_editor_update_header_html();
  1210. annotation_editor_update_metadata_html(recttype);
  1211. }
  1212. ok_callback();
  1213. });
  1214. }
  1215. function annotation_editor_remove() {
  1216. var p = document.getElementById('annotation_editor');
  1217. if ( p ) {
  1218. p.remove();
  1219. }
  1220. }
  1221. function is_annotation_editor_visible() {
  1222. return document.getElementById('annotation_editor_panel').classList.contains('display_block');
  1223. }
  1224. function annotation_editor_toggle_all_regions_editor() {
  1225. var p = document.getElementById('annotation_editor_panel');
  1226. if ( p.classList.contains('display_block') ) {
  1227. p.classList.remove('display_block');
  1228. _via_annotation_editor_mode = VIA_ANNOTATION_EDITOR_MODE.SINGLE_REGION;
  1229. } else {
  1230. _via_annotation_editor_mode = VIA_ANNOTATION_EDITOR_MODE.ALL_REGIONS;
  1231. p.classList.add('display_block');
  1232. p.style.height = _via_settings.ui.annotation_editor_height + '%';
  1233. p.style.fontSize = _via_settings.ui.annotation_editor_fontsize + 'rem';
  1234. annotation_editor_show();
  1235. }
  1236. }
  1237. function annotation_editor_set_active_button() {
  1238. var attribute_type;
  1239. for ( attribute_type in _via_attributes ) {
  1240. var bid = 'button_edit_' + attribute_type + '_metadata';
  1241. document.getElementById(bid).classList.remove('active');
  1242. }
  1243. var bid = 'button_edit_' + _via_metadata_being_updated + '_metadata';
  1244. document.getElementById(bid).classList.add('active');
  1245. }
  1246. function annotation_editor_update_header_html() {
  1247. var head = document.createElement('div');
  1248. head.setAttribute('class', 'row');
  1249. head.setAttribute('id', 'annotation_editor_header');
  1250. if ( _via_metadata_being_updated === 'region' ) {
  1251. var rid_col = document.createElement('span');
  1252. rid_col.setAttribute('class', 'col header');
  1253. rid_col.innerHTML = '序号';
  1254. head.appendChild(rid_col);
  1255. }
  1256. if ( _via_metadata_being_updated === 'file' ) {
  1257. var rid_col = document.createElement('span');
  1258. rid_col.setAttribute('class', 'col header');
  1259. if ( _via_display_area_content_name === VIA_DISPLAY_AREA_CONTENT_NAME.IMAGE_GRID ) {
  1260. rid_col.innerHTML = 'group';
  1261. } else {
  1262. rid_col.innerHTML = 'filename';
  1263. }
  1264. head.appendChild(rid_col);
  1265. }
  1266. var attr_id;
  1267. for ( attr_id in _via_attributes[_via_metadata_being_updated] ) {
  1268. var col = document.createElement('span');
  1269. col.setAttribute('class', 'col header');
  1270. col.innerHTML = attr_id;
  1271. //console.log("attr_id=" + attr_id + " userType=" + userType);
  1272. if(attr_id =="verify" && userType !=2 ){//标注人员不需要看到审核列
  1273. continue;
  1274. }
  1275. head.appendChild(col);
  1276. }
  1277. var ae = document.getElementById('annotation_editor');
  1278. if ( ae.childNodes.length === 0 ) {
  1279. ae.appendChild(head);
  1280. } else {
  1281. if ( ae.firstChild.id === 'annotation_editor_header') {
  1282. ae.replaceChild(head, ae.firstChild);
  1283. } else {
  1284. // header node is absent
  1285. ae.insertBefore(head, ae.firstChild);
  1286. }
  1287. }
  1288. // var col = document.createElement('span');
  1289. // col.setAttribute('class', 'col header');
  1290. // col.innerHTML = "ReID自动识别";
  1291. // head.appendChild(col);
  1292. }
  1293. function annotation_editor_update_metadata_html(recttype) {
  1294. var ae = document.getElementById('annotation_editor');
  1295. switch ( _via_metadata_being_updated ) {
  1296. case 'region':
  1297. var rindex;
  1298. // ae.appendChild( annotation_editor_get_metadata_row_html(_via_user_sel_region_id) )
  1299. if ( _via_display_area_content_name === VIA_DISPLAY_AREA_CONTENT_NAME.IMAGE_GRID ) {
  1300. ae.appendChild( annotation_editor_get_metadata_row_html(0) );
  1301. } else {
  1302. if ( _via_display_area_content_name === VIA_DISPLAY_AREA_CONTENT_NAME.IMAGE ) {
  1303. if ( _via_annotation_editor_mode === VIA_ANNOTATION_EDITOR_MODE.SINGLE_REGION ) {
  1304. ae.appendChild( annotation_editor_get_metadata_row_html(_via_user_sel_region_id,recttype) );
  1305. } else {
  1306. for ( rindex = 0; rindex < regions.length; ++rindex ) {
  1307. ae.appendChild( annotation_editor_get_metadata_row_html(rindex) );
  1308. }
  1309. }
  1310. }
  1311. }
  1312. break;
  1313. case 'file':
  1314. ae.appendChild( annotation_editor_get_metadata_row_html(0) );
  1315. break;
  1316. }
  1317. }
  1318. function annotation_editor_update_row(row_id,regons) {
  1319. var ae = document.getElementById('annotation_editor');
  1320. var new_row = annotation_editor_get_metadata_row_html(row_id);
  1321. var old_row = document.getElementById(new_row.getAttribute('id'));
  1322. ae.replaceChild(new_row, old_row);
  1323. }
  1324. function annotation_editor_add_row(row_id) {
  1325. if ( is_annotation_editor_visible() ) {
  1326. var ae = document.getElementById('annotation_editor');
  1327. var new_row = annotation_editor_get_metadata_row_html(row_id);
  1328. var penultimate_row_id = parseInt(row_id) - 1;
  1329. if ( penultimate_row_id >= 0 ) {
  1330. var penultimate_row_html_id = 'ae_' + _via_metadata_being_updated + '_' + penultimate_row_id;
  1331. var penultimate_row = document.getElementById(penultimate_row_html_id);
  1332. ae.insertBefore(new_row, penultimate_row.nextSibling);
  1333. } else {
  1334. ae.appendChild(new_row);
  1335. }
  1336. }
  1337. }
  1338. function annotation_editor_get_metadata_row_html(row_id,recttype) {
  1339. var row = document.createElement('div');
  1340. row.setAttribute('class', 'row');
  1341. row.setAttribute('id', 'ae_' + _via_metadata_being_updated + '_' + row_id);
  1342. console.log("row_id=" + row_id);
  1343. if ( _via_metadata_being_updated === 'region' ) {
  1344. var rid = document.createElement('span');
  1345. switch(_via_display_area_content_name) {
  1346. case VIA_DISPLAY_AREA_CONTENT_NAME.IMAGE_GRID:
  1347. rid.setAttribute('class', 'col');
  1348. rid.innerHTML = 'Grouped regions in ' + _via_image_grid_selected_img_index_list.length + ' files';
  1349. break;
  1350. case VIA_DISPLAY_AREA_CONTENT_NAME.IMAGE:
  1351. rid.setAttribute('class', 'col id');
  1352. rid.innerHTML = (row_id );
  1353. break;
  1354. }
  1355. row.appendChild(rid);
  1356. }
  1357. var attr_id;
  1358. for ( attr_id in _via_attributes[_via_metadata_being_updated] ) {
  1359. //console.log("attr_id row=" + attr_id);
  1360. if(attr_id =="verify" && userType !=2 ){//标注人员不需要看到审核列
  1361. continue;
  1362. }
  1363. var col = document.createElement('span');
  1364. col.setAttribute('class', 'col');
  1365. var attr_type = _via_attributes[_via_metadata_being_updated][attr_id].type;
  1366. var attr_desc = _via_attributes[_via_metadata_being_updated][attr_id].desc;
  1367. if ( typeof(attr_desc) === 'undefined' ) {
  1368. attr_desc = '';
  1369. }
  1370. var attr_html_id = attr_id + '__' + row_id;
  1371. var attr_value = '';
  1372. var attr_placeholder = '';
  1373. if ( _via_display_area_content_name === VIA_DISPLAY_AREA_CONTENT_NAME.IMAGE ) {
  1374. console.log("tt=" + _via_display_area_content_name);
  1375. switch(_via_metadata_being_updated) {
  1376. case 'region':
  1377. if (regions[row_id]!==undefined){
  1378. if ( regions[row_id].other.region_attributes.hasOwnProperty(attr_id) ) {
  1379. attr_value = regions[row_id].other.region_attributes[attr_id];
  1380. if (isEmpty(attr_value) && attr_id == "id"){
  1381. attr_value = maxIdNum + 1;
  1382. regions[row_id].other.region_attributes[attr_id]= attr_value;
  1383. maxIdNum = maxIdNum + 1;
  1384. }
  1385. } else {
  1386. attr_placeholder = 'not defined yet!';
  1387. }
  1388. }
  1389. case 'file':
  1390. attr_placeholder = 'not defined yet!';
  1391. // if ( _via_img_metadata[_via_image_id].file_attributes.hasOwnProperty(attr_id) ) {
  1392. // attr_value = _via_img_metadata[_via_image_id].file_attributes[attr_id];
  1393. // } else {
  1394. // attr_placeholder = 'not defined yet!';
  1395. // }
  1396. }
  1397. }
  1398. switch(attr_type) {
  1399. case 'text':
  1400. col.innerHTML = '<textarea ' +
  1401. 'onchange="annotation_editor_on_metadata_update(this)" ' +
  1402. 'onfocus="annotation_editor_on_metadata_focus(this)" ' +
  1403. 'title="' + attr_desc + '" ' +
  1404. 'placeholder="' + attr_placeholder + '" ' +
  1405. 'id="' + attr_html_id + '">' + attr_value + '</textarea>';
  1406. break;
  1407. case 'checkbox':
  1408. var options = _via_attributes[_via_metadata_being_updated][attr_id].options;
  1409. var option_id;
  1410. for ( option_id in options ) {
  1411. var option_html_id = attr_html_id + '__' + option_id;
  1412. var option = document.createElement('input');
  1413. option.setAttribute('type', 'checkbox');
  1414. option.setAttribute('value', option_id);
  1415. option.setAttribute('id', option_html_id);
  1416. option.setAttribute('onfocus', 'annotation_editor_on_metadata_focus(this)');
  1417. option.setAttribute('onchange', 'annotation_editor_on_metadata_update(this)');
  1418. var option_desc = _via_attributes[_via_metadata_being_updated][attr_id].options[option_id];
  1419. if ( option_desc === '' || typeof(option_desc) === 'undefined' ) {
  1420. // option description is optional, use option_id when description is not present
  1421. option_desc = option_id;
  1422. }
  1423. // set the value of options based on the user annotations
  1424. if ( typeof attr_value !== 'undefined') {
  1425. if ( attr_value.hasOwnProperty(option_id) ) {
  1426. option.checked = attr_value[option_id];
  1427. }
  1428. }
  1429. var label = document.createElement('label');
  1430. label.setAttribute('for', option_html_id);
  1431. label.innerHTML = option_desc;
  1432. var container = document.createElement('span');
  1433. container.appendChild(option);
  1434. container.appendChild(label);
  1435. col.appendChild(container);
  1436. }
  1437. break;
  1438. case 'radio':
  1439. var option_id;
  1440. for ( option_id in _via_attributes[_via_metadata_being_updated][attr_id].options ) {
  1441. var option_html_id = attr_html_id + '__' + option_id;
  1442. var option = document.createElement('input');
  1443. option.setAttribute('type', 'radio');
  1444. option.setAttribute('name', attr_html_id);
  1445. option.setAttribute('value', option_id);
  1446. option.setAttribute('id', option_html_id);
  1447. option.setAttribute('onfocus', 'annotation_editor_on_metadata_focus(this)');
  1448. option.setAttribute('onchange', 'annotation_editor_on_metadata_update(this)');
  1449. var option_desc = _via_attributes[_via_metadata_being_updated][attr_id].options[option_id];
  1450. if ( option_desc === '' || typeof(option_desc) === 'undefined' ) {
  1451. // option description is optional, use option_id when description is not present
  1452. option_desc = option_id;
  1453. }
  1454. if ( attr_value === option_id ) {
  1455. option.checked = true;
  1456. }
  1457. var label = document.createElement('label');
  1458. label.setAttribute('for', option_html_id);
  1459. label.innerHTML = option_desc;
  1460. var container = document.createElement('span');
  1461. container.appendChild(option);
  1462. container.appendChild(label);
  1463. col.appendChild(container);
  1464. }
  1465. break;
  1466. case 'image':
  1467. var option_id;
  1468. var option_count = 0;
  1469. for ( option_id in _via_attributes[_via_metadata_being_updated][attr_id].options ) {
  1470. option_count = option_count + 1;
  1471. }
  1472. var img_options = document.createElement('div');
  1473. img_options.setAttribute('class', 'img_options');
  1474. col.appendChild(img_options);
  1475. var option_index = 0;
  1476. for ( option_id in _via_attributes[_via_metadata_being_updated][attr_id].options ) {
  1477. var option_html_id = attr_html_id + '__' + option_id;
  1478. var option = document.createElement('input');
  1479. option.setAttribute('type', 'radio');
  1480. option.setAttribute('name', attr_html_id);
  1481. option.setAttribute('value', option_id);
  1482. option.setAttribute('id', option_html_id);
  1483. option.setAttribute('onfocus', 'annotation_editor_on_metadata_focus(this)');
  1484. option.setAttribute('onchange', 'annotation_editor_on_metadata_update(this)');
  1485. var option_desc = _via_attributes[_via_metadata_being_updated][attr_id].options[option_id];
  1486. if ( option_desc === '' || typeof(option_desc) === 'undefined' ) {
  1487. // option description is optional, use option_id when description is not present
  1488. option_desc = option_id;
  1489. }
  1490. if ( attr_value === option_id ) {
  1491. option.checked = true;
  1492. }
  1493. var label = document.createElement('label');
  1494. label.setAttribute('for', option_html_id);
  1495. label.innerHTML = '<img src="' + option_desc + '"><p>' + option_id + '</p>';
  1496. var container = document.createElement('span');
  1497. container.appendChild(option);
  1498. container.appendChild(label);
  1499. img_options.appendChild(container);
  1500. }
  1501. break;
  1502. case 'dropdown':
  1503. var sel = document.createElement('select');
  1504. sel.setAttribute('id', attr_html_id);
  1505. sel.setAttribute('onfocus', 'annotation_editor_on_metadata_focus(this)');
  1506. sel.setAttribute('onchange', 'annotation_editor_on_metadata_update(this)');
  1507. var option_id;
  1508. var option_selected = false;
  1509. for ( option_id in _via_attributes[_via_metadata_being_updated][attr_id].options ) {
  1510. var option_html_id = attr_html_id + '__' + option_id;
  1511. var option = document.createElement('option');
  1512. option.setAttribute('value', option_id);
  1513. var option_desc = _via_attributes[_via_metadata_being_updated][attr_id].options[option_id];
  1514. if ( option_desc === '' || typeof(option_desc) === 'undefined' ) {
  1515. // option description is optional, use option_id when description is not present
  1516. option_desc = option_id;
  1517. }
  1518. if ( option_id === attr_value ) {
  1519. option.setAttribute('selected', 'selected');
  1520. option_selected = true;
  1521. }
  1522. option.innerHTML = option_desc;
  1523. sel.appendChild(option);
  1524. }
  1525. if ( ! option_selected ) {
  1526. sel.selectedIndex = '-1';
  1527. }
  1528. col.appendChild(sel);
  1529. break;
  1530. }
  1531. row.appendChild(col);
  1532. }
  1533. return row;
  1534. }
  1535. function annotation_editor_scroll_to_row(row_id) {
  1536. if ( is_annotation_editor_visible() ) {
  1537. var row_html_id = 'ae_' + _via_metadata_being_updated + '_' + row_id;
  1538. var row = document.getElementById(row_html_id);
  1539. row.scrollIntoView(false);
  1540. }
  1541. }
  1542. function annotation_editor_highlight_row(row_id) {
  1543. if ( is_annotation_editor_visible() ) {
  1544. var row_html_id = 'ae_' + _via_metadata_being_updated + '_' + row_id;
  1545. var row = document.getElementById(row_html_id);
  1546. row.classList.add('highlight');
  1547. }
  1548. }
  1549. function annotation_editor_clear_row_highlight() {
  1550. if ( is_annotation_editor_visible() ) {
  1551. var ae = document.getElementById('annotation_editor');
  1552. var i;
  1553. for ( i=0; i<ae.childNodes.length; ++i ) {
  1554. ae.childNodes[i].classList.remove('highlight');
  1555. }
  1556. }
  1557. }
  1558. function annotation_editor_extract_html_id_components(html_id) {
  1559. // html_id : attribute_name__row-id__option_id
  1560. var parts = html_id.split('__');
  1561. var parsed_id = {};
  1562. switch( parts.length ) {
  1563. case 3:
  1564. // html_id : attribute-id__row-id__option_id
  1565. parsed_id.attr_id = parts[0];
  1566. parsed_id.row_id = parts[1];
  1567. parsed_id.option_id = parts[2];
  1568. break;
  1569. case 2:
  1570. // html_id : attribute-id__row-id
  1571. parsed_id.attr_id = parts[0];
  1572. parsed_id.row_id = parts[1];
  1573. break;
  1574. default:
  1575. }
  1576. return parsed_id;
  1577. }
  1578. // invoked when the input entry in annotation editor receives focus
  1579. function annotation_editor_on_metadata_focus(p) {
  1580. if ( _via_annotation_editor_mode === VIA_ANNOTATION_EDITOR_MODE.ALL_REGIONS ) {
  1581. var pid = annotation_editor_extract_html_id_components(p.id);
  1582. var region_id = pid.row_id;
  1583. // clear existing highlights (if any)
  1584. toggle_all_regions_selection(false);
  1585. annotation_editor_clear_row_highlight();
  1586. // set new selection highlights
  1587. set_region_select_state(region_id, true);
  1588. annotation_editor_scroll_to_row(region_id);
  1589. annotation_editor_highlight_row(region_id);
  1590. // _via_redraw_reg_canvas();
  1591. }
  1592. }
  1593. // invoked when the user updates annotations using the annotation editor
  1594. function annotation_editor_on_metadata_update(p) {
  1595. var pid = annotation_editor_extract_html_id_components(p.id);
  1596. var img_id = _via_image_id;
  1597. var img_index_list = [ _via_image_index ];
  1598. var region_id = pid.row_id;
  1599. if ( _via_display_area_content_name === VIA_DISPLAY_AREA_CONTENT_NAME.IMAGE_GRID ) {
  1600. img_index_list = _via_image_grid_selected_img_index_list.slice(0);
  1601. region_id = -1; // this flag denotes that we want to update all regions
  1602. }
  1603. if ( _via_metadata_being_updated === 'region' ) {
  1604. if (pid.attr_id == "id"){ //判断id输入是否为数字
  1605. if(!isNumber(p.value)){
  1606. alert('请输入有效的数字');
  1607. return;
  1608. }
  1609. }
  1610. annotation_editor_update_region_metadata( region_id, pid.attr_id, p.value, p.checked).then( function(update_count) {
  1611. if (p.value > maxIdNum && pid.attr_id == "id"){
  1612. maxIdNum = parseInt(p.value);
  1613. }
  1614. // annotation_editor_on_metadata_update_done('region', pid.attr_id, update_count);
  1615. updateLabelHtml();
  1616. drawRect();
  1617. updatelabel(fileindex);
  1618. }, function(err) {
  1619. show_message('Failed to update region attributes! ');
  1620. });
  1621. return;
  1622. }
  1623. }
  1624. function isNumber(value) { //验证是否为数字
  1625. var patrn = /^(-)?\d+(\.\d+)?$/;
  1626. if (patrn.exec(value) == null || value == "") {
  1627. return false
  1628. } else {
  1629. return true
  1630. }
  1631. }
  1632. function annotation_editor_update_region_metadata( region_id, attr_id, new_value, new_checked) {
  1633. return new Promise( function(ok_callback, err_callback) {
  1634. var i, n, img_id, img_index;
  1635. // n = img_index_list.length;
  1636. var update_count = 0;
  1637. var region_list = [];
  1638. var j, m;
  1639. if ( region_id === -1 ) {
  1640. // update all regions on a file (for image grid view)
  1641. // for ( i = 0; i < n; ++i ) {
  1642. // img_index = img_index_list[i];
  1643. // img_id = _via_image_id_list[img_index];
  1644. m = regions.length;
  1645. for ( j = 0; j < m; ++j ) {
  1646. // if ( ! image_grid_is_region_in_current_group(regions[j].region_attributes ) ) {
  1647. // continue;
  1648. // }
  1649. switch( _via_attributes['region'][attr_id].type ) {
  1650. case 'text': // fallback
  1651. case 'dropdown': // fallback
  1652. case 'radio': // fallback
  1653. // case 'image':
  1654. regions[j].other.region_attributes[attr_id] = new_value;
  1655. update_count += 1;
  1656. break;
  1657. case 'checkbox':
  1658. var option_id = new_value;
  1659. if ( regions[j].other.region_attributes.hasOwnProperty(attr_id) ) {
  1660. if ( typeof(regions[j].other.region_attributes[attr_id]) !== 'object' ) {
  1661. var old_value = regions[j].other.region_attributes[attr_id];
  1662. regions[j].other.region_attributes[attr_id] = {}
  1663. if ( Object.keys(_via_attributes['region'][attr_id]['options']).includes(old_value) ) {
  1664. // transform existing value as checkbox option
  1665. regions[j].other.region_attributes[attr_id][old_value] = true;
  1666. }
  1667. }
  1668. } else {
  1669. regions[j].other.region_attributes[attr_id] = {};
  1670. }
  1671. if ( new_checked ) {
  1672. regions[j].other.region_attributes[attr_id][option_id] = true;
  1673. } else {
  1674. // false option values are not stored
  1675. delete regions[j].other.region_attributes[attr_id][option_id];
  1676. }
  1677. update_count += 1;
  1678. break;
  1679. }
  1680. }
  1681. // }
  1682. } else {
  1683. switch( _via_attributes['region'][attr_id].type ) {
  1684. case 'text': // fallback
  1685. case 'dropdown': // fallback
  1686. case 'radio': // fallback
  1687. case 'image':
  1688. regions[region_id].other.region_attributes[attr_id] = new_value;
  1689. update_count += 1;
  1690. break;
  1691. case 'checkbox':
  1692. var option_id = new_value;
  1693. if ( regions[region_id].other.region_attributes.hasOwnProperty(attr_id) ) {
  1694. if ( typeof(regions[region_id].other.region_attributes[attr_id]) !== 'object' ) {
  1695. var old_value = regions[region_id].other.region_attributes[attr_id];
  1696. [region_id].other.region_attributes[attr_id] = {};
  1697. if ( Object.keys(_via_attributes['region'][attr_id]['options']).includes(old_value) ) {
  1698. // transform existing value as checkbox option
  1699. regions[region_id].other.region_attributes[attr_id][old_value] = true;
  1700. }
  1701. }
  1702. } else {
  1703. regions[region_id].other.region_attributes[attr_id] = {};
  1704. }
  1705. if ( new_checked ) {
  1706. regions[region_id].other.region_attributes[attr_id][option_id] = true;
  1707. } else {
  1708. // false option values are not stored
  1709. delete regions[region_id].other.region_attributes[attr_id][option_id];
  1710. }
  1711. update_count += 1;
  1712. break;
  1713. }
  1714. // }
  1715. }
  1716. ok_callback(update_count);
  1717. });
  1718. }
  1719. function set_region_annotations_to_default_value(rid) {
  1720. var attr_id;
  1721. for ( attr_id in _via_attributes['region'] ) {
  1722. var attr_type = _via_attributes['region'][attr_id].type;
  1723. switch( attr_type ) {
  1724. case 'text':
  1725. var default_value = _via_attributes['region'][attr_id].default_value;
  1726. if ( typeof(default_value) !== 'undefined' ) {
  1727. regions[rid].other.region_attributes[attr_id] = default_value;
  1728. }
  1729. break;
  1730. case 'image': // fallback
  1731. case 'dropdown': // fallback
  1732. case 'radio':
  1733. regions[rid].other.region_attributes[attr_id] = '';
  1734. var default_options = _via_attributes['region'][attr_id].default_options;
  1735. if ( typeof(default_options) !== 'undefined' ) {
  1736. regions[rid].other.region_attributes[attr_id] = Object.keys(default_options)[0];
  1737. }
  1738. break;
  1739. case 'checkbox':
  1740. regions[rid].other.region_attributes[attr_id] = {};
  1741. var default_options = _via_attributes['region'][attr_id].default_options;
  1742. if ( typeof(default_options) !== 'underfined' ) {
  1743. var option_id;
  1744. for ( option_id in default_options ) {
  1745. var default_value = default_options[option_id];
  1746. if ( typeof(default_value) !== 'underfined' ) {
  1747. regions[rid].other.region_attributes[attr_id][option_id] = default_value;
  1748. }
  1749. }
  1750. }
  1751. break;
  1752. }
  1753. }
  1754. }
  1755. function show_tpye_attribute(){
  1756. var set_attributes1 = document.getElementById("set_attributes")
  1757. set_attributes1.style.height = '70rem'
  1758. sessionStorage.setItem('attr_id','type');
  1759. // sessionStorage.setItem(\'predict_task_id\',\'"+task_id +"\');
  1760. show_attribute_properties();
  1761. show_tpye_attribute_options();
  1762. }
  1763. function show_color_attribute(){
  1764. var set_attributes2 = document.getElementById("set_attributes")
  1765. set_attributes2.style.height = '70rem'
  1766. sessionStorage.setItem('attr_id','color');
  1767. var isTrue = show_attribute_properties_color();
  1768. if (!isTrue){
  1769. return;
  1770. }
  1771. show_tpye_attribute_options();
  1772. }
  1773. function show_tpye_attribute_options() {
  1774. // var attr_list = document.getElementById('attributes_name_list');
  1775. document.getElementById('attribute_options').innerHTML = '';
  1776. document.getElementById('attribute_options').innerHTML = '';
  1777. // var attr_id = attr_list.value;
  1778. var attr_id = sessionStorage.getItem("attr_id");
  1779. var attr_type = _via_attributes[_via_attribute_being_updated][attr_id].type;
  1780. // populate additional options based on attribute type
  1781. switch( attr_type ) {
  1782. case VIA_ATTRIBUTE_TYPE.TEXT:
  1783. // text does not have any additional properties
  1784. break;
  1785. case VIA_ATTRIBUTE_TYPE.CHECKBOX: // handled by next case
  1786. case VIA_ATTRIBUTE_TYPE.DROPDOWN: // handled by next case
  1787. case VIA_ATTRIBUTE_TYPE.RADIO:
  1788. var p = document.createElement('div');
  1789. p.setAttribute('class', 'property');
  1790. p.setAttribute('style', 'text-align:center');
  1791. var c0 = document.createElement('span');
  1792. c0.setAttribute('style', 'width:25%');
  1793. c0.setAttribute('title', 'When selected, this is the value that appears in exported annotations');
  1794. c0.innerHTML = 'id';
  1795. var c1 = document.createElement('span');
  1796. c1.setAttribute('style', 'width:60%');
  1797. c1.setAttribute('title', 'This is the text shown as an option to the annotator');
  1798. c1.innerHTML = 'description';
  1799. var c2 = document.createElement('span');
  1800. c2.setAttribute('title', 'The default value of this attribute');
  1801. c2.innerHTML = 'def.';
  1802. p.appendChild(c0);
  1803. p.appendChild(c1);
  1804. p.appendChild(c2);
  1805. document.getElementById('attribute_options').appendChild(p);
  1806. input_type_attibutes(attr_id);
  1807. var options = _via_attributes[_via_attribute_being_updated][attr_id].options;
  1808. var option_id;
  1809. for ( option_id in options ) {
  1810. var option_desc = options[option_id];
  1811. var option_default = _via_attributes[_via_attribute_being_updated][attr_id].default_options[option_id];
  1812. attribute_property_add_option(attr_id, option_id, option_desc, option_default, attr_type);
  1813. }
  1814. attribute_property_add_new_entry_option(attr_id, attr_type);
  1815. break;
  1816. default:
  1817. console.log('Attribute type ' + attr_type + ' is unavailable');
  1818. }
  1819. }
  1820. function input_type_attibutes(attr_id){
  1821. _via_attributes[_via_attribute_being_updated][attr_id]["description"] = "";
  1822. _via_attributes[_via_attribute_being_updated][attr_id]["options"] = {};
  1823. if (attr_id=="type"){
  1824. _via_attributes[_via_attribute_being_updated][attr_id]["options"] = {"1":"轿车", "2":"SUV","3":"越野车","4":"出租车","5":"商务车","6":"载人面包车","7":"军警车-轿车","8":"军警车-SUV","9":"军警车-越野车","10":"军警车-商务车","11":"军警车-载人面包车","12":"军警车-客车",13:"中型客车","14":"公交车","15":"大型客车","16":"货用面包车","17":"厢式货车","18":"微型货车","19":"皮卡车","20":"救援车","21":"大型货车","22":"渣土车","23":"挂车","24":"罐车","25":"混凝土搅拌车","26":"随车吊","27":"救护车","28":"三轮车","29":"其他"};
  1825. }
  1826. else if (attr_id=="color"){
  1827. _via_attributes[_via_attribute_being_updated][attr_id]["options"] = {"1":"黑", "2":"白","3":"灰","4":"红","5":"蓝","6":"黄","7":"橙","8":"棕","9":"绿","10":"紫","11":"青","12":"粉",13:"银","14":"金","15":"混色","16":"其他","17":"未知"};
  1828. }
  1829. _via_attributes[_via_attribute_being_updated][attr_id]["default_options"] = {};
  1830. }
  1831. function judge_exit_color(){
  1832. var tableId = document.getElementById('attributes_name_list');
  1833. for(var i=1;i<tableId.rows.length;i++) {
  1834. // alert(tableId.rows[i].cells[1].innerHTML);
  1835. if (tableId.rows[i].cells[0].innerHTML == "color"){
  1836. return true;
  1837. }
  1838. }
  1839. return false;
  1840. }
  1841. function show_attribute_properties_color() {
  1842. if (!judge_exit_color()){
  1843. alert("请输入属性值:color.");
  1844. return false;
  1845. }
  1846. // var attr_list = document.getElementById('attributes_name_list');
  1847. document.getElementById('attribute_properties').innerHTML = '';
  1848. var attr_id = sessionStorage.getItem("attr_id");
  1849. var attr_type = _via_attribute_being_updated;
  1850. _via_attributes[attr_type][attr_id].type = "dropdown"
  1851. var attr_input_type = _via_attributes[attr_type][attr_id].type;
  1852. var attr_desc = _via_attributes[attr_type][attr_id].description;
  1853. attribute_property_add_input_property('Name of attribute (appears in exported annotations)',
  1854. 'Name',
  1855. attr_id,
  1856. 'attribute_name');
  1857. attribute_property_add_input_property('Description of attribute (shown to user during annotation session)',
  1858. 'Desc.',
  1859. attr_desc,
  1860. 'attribute_description');
  1861. if ( attr_input_type === 'text' ) {
  1862. var attr_default_value = _via_attributes[attr_type][attr_id].default_value;
  1863. attribute_property_add_input_property('Default value of this attribute',
  1864. 'Def.',
  1865. attr_default_value,
  1866. 'attribute_default_value');
  1867. }
  1868. // add dropdown for type of attribute
  1869. var p = document.createElement('div');
  1870. p.setAttribute('class', 'property');
  1871. var c0 = document.createElement('span');
  1872. c0.setAttribute('title', 'Attribute type (e.g. text, checkbox, radio, etc)');
  1873. c0.innerHTML = 'Type';
  1874. var c1 = document.createElement('span');
  1875. var c1b = document.createElement('select');
  1876. c1b.setAttribute('onchange', 'attribute_property_on_update(this)');
  1877. c1b.setAttribute('id', 'attribute_type');
  1878. var type_id;
  1879. for ( type_id in VIA_ATTRIBUTE_TYPE ) {
  1880. var type = VIA_ATTRIBUTE_TYPE[type_id];
  1881. var option = document.createElement('option');
  1882. option.setAttribute('value', type);
  1883. option.innerHTML = type;
  1884. if ( attr_input_type == type ) {
  1885. option.setAttribute('selected', 'selected');
  1886. }
  1887. c1b.appendChild(option);
  1888. }
  1889. c1.appendChild(c1b);
  1890. p.appendChild(c0);
  1891. p.appendChild(c1);
  1892. document.getElementById('attribute_properties').appendChild(p);
  1893. return true;
  1894. }