From f4d9ae2870ded2c5af07fee2cb24af6369df294e Mon Sep 17 00:00:00 2001 From: nanli Date: Tue, 23 Apr 2019 15:16:36 -0400 Subject: [PATCH] Heatmap editor front end page and data model --- apps/heatmap/heatmap.html | 6 + apps/heatmap/init.js | 65 +- apps/heatmap/uicallbacks.js | 555 ++++-------------- common/heatmapeditdatamodels.js | 20 +- components/heatmapcontrol/heatmapcontrol.js | 12 +- .../heatmapediteddatapanel.css | 65 ++ .../heatmapediteddatapanel.js | 113 ++++ iconfont/material-icons.css | 13 +- 8 files changed, 366 insertions(+), 483 deletions(-) create mode 100644 components/heatmapediteddatapanel/heatmapediteddatapanel.css create mode 100644 components/heatmapediteddatapanel/heatmapediteddatapanel.js diff --git a/apps/heatmap/heatmap.html b/apps/heatmap/heatmap.html index 90e015498..6d319365b 100644 --- a/apps/heatmap/heatmap.html +++ b/apps/heatmap/heatmap.html @@ -48,6 +48,8 @@ + + @@ -113,6 +115,7 @@ + @@ -156,6 +159,9 @@
+ +
+ diff --git a/apps/heatmap/init.js b/apps/heatmap/init.js index 7716d8264..9dd6f9be7 100644 --- a/apps/heatmap/init.js +++ b/apps/heatmap/init.js @@ -59,27 +59,7 @@ function initialize(){ function initCore(){ // start initial // TODO zoom info and mmp - const opt = { - draw:{ - // extend context menu btn group - btns:[ - { // annotation - type:'btn', - title:'Annotation', - class:'material-icons', - text:'description', - callback:saveAnnotation - }, - { // analytics - type:'btn', - title:'Analytics', - class:'material-icons', - text:'settings_backup_restore', - callback:saveAnalytics - } - ] - } - } + const opt = {}; // set states if exist if($D.params.states){ opt.states = $D.params.states; @@ -257,6 +237,19 @@ function initCore(){ // Test Data - edited data $D.heatMapData.editedClusters = mergingEditedData(features, $UI.heatmapEditorPanel.getAllOperations()); console.log($D.heatMapData); + + + // create edited data list + $UI.heatmapEditedDataPanel = new HeatmapEditedDataPanel({ + // data:$D.heatMapData.editedClusters, + data:$D.editedDataClusters.data, + // editedDate:$D. + onDBClick: locateEditData, + onDelete: onDeleteEditData + }); + + $UI.editedListSideMenu.addContent($UI.heatmapEditedDataPanel.elt); + Loading.close(); } @@ -281,6 +274,14 @@ function initUIcomponents(){ hasMainTools: false, //mainToolsCallback:mainMenuChange, subTools:[ + { + name:'editeddate', + icon:'view_list',// material icons' name + title:'Edited Data List', + type:'check',// btn/check/dropdown + value:'editeddate', + callback:toggleHeatMapDataList + }, // setting { name:'settings', @@ -430,7 +431,7 @@ function initUIcomponents(){ var checkIsReady = setInterval(function () { if($CAMIC&& $CAMIC.viewer && $CAMIC.viewer.imagingHelper && $CAMIC.viewer.imagingHelper._haveImage && $D.heatMapData) { clearInterval(checkIsReady); - // create side menu + // create editor side menu $UI.editorSideMenu = new SideMenu({ id:'editor_menu', width: 300, @@ -442,12 +443,26 @@ function initUIcomponents(){ title.textContent = 'Heatmap Editor'; $UI.editorSideMenu.addContent(title); + // create edited data list side menu + $UI.editedListSideMenu = new SideMenu({ + id:'edit_list_menu', + width: 300, + //, isOpen:true + callback:toggleHeatMapEditor + }); + const title1 = document.createElement('div'); + title1.classList.add('item_head'); + title1.textContent = 'Edited Data List'; + $UI.editedListSideMenu.addContent(title1); + + $CAMIC.viewer.canvasDrawInstance.drawMode = 'grid'; function getGridSizeInImage(size){ + const correctValue = 0.1; let [w,h] = size; - w = Math.round(w*$CAMIC.viewer.imagingHelper.imgWidth); - h = Math.round(h*$CAMIC.viewer.imagingHelper.imgHeight); - return [w,h]; + w = w*$CAMIC.viewer.imagingHelper.imgWidth; + h = h*$CAMIC.viewer.imagingHelper.imgHeight; + return [w - correctValue, h - correctValue]; } $CAMIC.viewer.canvasDrawInstance.size = getGridSizeInImage($D.heatMapData.provenance.analysis.size); } diff --git a/apps/heatmap/uicallbacks.js b/apps/heatmap/uicallbacks.js index 8c52910c2..8cbbbbdf2 100644 --- a/apps/heatmap/uicallbacks.js +++ b/apps/heatmap/uicallbacks.js @@ -178,62 +178,6 @@ function goHome(data){ redirect($D.pages.home,`GO Home Page`, 0); } -// pen draw callback -function draw(e){ - if(!$CAMIC.viewer.canvasDrawInstance){ - alert('draw doesn\'t initialize'); - return; - } - const state = +e.state; - const canvasDraw = $CAMIC.viewer.canvasDrawInstance; - //$UI.message.add(`Draw: ${state?'ON':'OFF'}`); - - const target = this.srcElement || this.target || this.eventSource.canvas; - switch (state) { - case 0: // off - canvasDraw.clear(); - canvasDraw.drawOff(); - $CAMIC.drawContextmenu.off(); - $UI.appsSideMenu.close(); - break; - case 1: // once - // statements_1 - case 2: // stick - canvasDraw.drawOn(); - $CAMIC.drawContextmenu.on(); - $CAMIC.drawContextmenu.open({x:this.clientX,y:this.clientY,target:target}); - // turn off magnifier - $UI.toolbar._sub_tools[2].querySelector('input[type=checkbox]').checked = false; - $UI.spyglass.close(); - // turn off measurement - $UI.toolbar._sub_tools[3].querySelector('input[type=checkbox]').checked = false; - $CAMIC.viewer.measureInstance.off(); - - //close layers menu - $UI.layersSideMenu.close(); - - // open annotation menu - $UI.appsSideMenu.open(); - $UI.appsList.triggerContent('annotation','open'); - const input = $UI.annotOptPanel._form_.querySelector('#name'); - input.focus(); - input.select(); - break; - default: - // statements_def - break; - } -} - -function toggleOffDrawBtns(){ - const label = $UI.toolbar._sub_tools[1].querySelector('label'); - const state = +label.dataset.state; - label.classList.remove(`s${state}`); - - label.dataset.state = 0; - label.classList.add(`s0`); - -} function heatmapSettingChanged(data){ switch (data.mode) { case 'binal': @@ -256,10 +200,12 @@ function heatmapSettingChanged(data){ } } + function heatmapOpacityChanaged(data){ $CAMIC.viewer.heatmap.setOpacity(data['heat']); $CAMIC.viewer.heatmap.setCoverOpacity(data['cover']); } + function toggleMeasurement(data){ if(!$CAMIC.viewer.measureInstance) { console.warn('No Measurement Tool'); @@ -276,31 +222,35 @@ function toggleMeasurement(data){ measurementOff(); } } + function measurementOn(){ if(!$CAMIC.viewer.measureInstance)return; $CAMIC.viewer.measureInstance.on(); const li = $UI.toolbar.getSubTool('measurement'); li.querySelector('input[type=checkbox]').checked = true; } + function measurementOff(){ if(!$CAMIC.viewer.measureInstance)return; $CAMIC.viewer.measureInstance.off(); const li = $UI.toolbar.getSubTool('measurement'); li.querySelector('input[type=checkbox]').checked = false; } + // toggle magnifier callback function toggleMagnifier(data){ if(data.checked){ magnifierOn(+data.status,this.clientX,this.clientY); // trun off the main menu $UI.settingsSideMenu.close(); - heatMapEditorOff(); + heatmapEditorOff(); // measurement off measurementOff(); }else{ magnifierOff(); } } + function magnifierOn(factor = 1,x=0,y=0){ if(!$UI.spyglass)return; $UI.spyglass.factor = factor; @@ -315,18 +265,6 @@ function magnifierOff(){ const li = $UI.toolbar.getSubTool('magnifier'); li.querySelector('input[type=checkbox]').checked = false; } -// image download -function imageDownload(data){ - // TODO functionality - alert('Download Image'); - console.log(data); -} - -// share url -function shareURL(data){ - const URL = StatesHelper.getCurrentStatesURL(true); - window.prompt('Share this link', URL); -} // main menu changed function toggleHeatMapSettings(e){ @@ -335,6 +273,7 @@ function toggleHeatMapSettings(e){ case true: $UI.settingsSideMenu.open(); heatmapEditorOff(); + heatMapEditedListOff(); setTimeout(function(){ $UI.heatmapcontrol.resize(); },500) @@ -350,14 +289,49 @@ function toggleHeatMapSettings(e){ switch (e.isOpen) { case false: // statements_1 - $UI.toolbar._sub_tools[0].querySelector('input[type="checkbox"]').checked = false; + const li = $UI.toolbar.getSubTool('settings') + li.querySelector('input[type=checkbox]').checked = false; break; + case true: + const li2 = $UI.toolbar.getSubTool('settings') + li2.querySelector('input[type=checkbox]').checked = true; default: // statements_def break; } } +function toggleHeatMapDataList(e){ + switch (e.checked) { + case true: + heatMapEditedListOn(); + break; + case false: + heatMapEditedListOff(); + break; + // default: + // console.warn('Editor error'); + // break; + } +} + +function heatMapEditedListOn(){ + $UI.editedListSideMenu.open(); + const li = $UI.toolbar.getSubTool('editeddate') + li.querySelector('input[type=checkbox]').checked = true; + toggleHeatMapSettings({checked:false,isOpen:false}); + heatmapEditorOff(); + measurementOff(); + magnifierOff(); +} + +function heatMapEditedListOff(){ + $UI.editedListSideMenu.close(); + const li = $UI.toolbar.getSubTool('editeddate') + li.querySelector('input[type=checkbox]').checked = false; + +} + function toggleHeatMapEditor(e){ switch (e.checked) { case true: @@ -371,9 +345,13 @@ function toggleHeatMapEditor(e){ // break; } } + function heatMapEditorOn(){ $UI.editorSideMenu.open(); $UI.settingsSideMenu.close(); + + //$UI.editedListSideMenu.close(); + heatMapEditedListOff(); measurementOff(); magnifierOff(); if(!$CAMIC.viewer.canvasDrawInstance) return; @@ -384,6 +362,7 @@ function heatMapEditorOn(){ } $CAMIC.viewer.canvasDrawInstance.drawOn(); } + function heatmapEditorOff(){ $UI.editorSideMenu.close(); const li = $UI.toolbar.getSubTool('editor'); @@ -392,300 +371,6 @@ function heatmapEditorOff(){ } -function convertHumanAnnotationToPopupBody(notes){ - - const rs = {type:'map',data:[]}; - for(let field in notes){ - const val = notes[field]; - field = field.split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' '); - rs.data.push({key:field,value:val}); - } - return rs; - -} - -function anno_delete(data){ - if(!data.id) return; - if(!confirm(`Are you sure you want to delete this markup {ID:${data.id}}?`)) return; - $CAMIC.store.deleteMark(data.oid,$D.params.data.name) - .then(datas =>{ - // server error - if(datas.error){ - const errorMessage = `${datas.text}: ${datas.url}`; - $UI.message.addError(errorMessage, 5000); - // close - return; - } - - // no data found - if(!datas.rowsAffected || datas.rowsAffected < 1){ - $UI.message.addWarning(`Delete Annotations Failed.`,5000); - return; - } - - const index = $D.overlayers.findIndex(layer => layer.id == data.id); - - if(index==-1) return; - - data.index = index; - const layer = $D.overlayers[data.index]; - // update UI - if(Array.isArray(layer.data)) deleteCallback_old(data) - else deleteCallback(data) - }) - .catch(e=>{ - $UI.message.addError(e); - console.error(e); - }) - .finally(()=>{ - //console.log('delete end'); - }); - -} - - -function deleteCallback(data){ - // remove overlay - $D.overlayers.splice(data.index, 1); - // update layer manager - $CAMIC.viewer.omanager.removeOverlay(data.id); - // update layers Viewer - $UI.layersViewer.update(); - // close popup panel - $UI.annotPopup.close(); - -} - -// for support QUIP2.0 Data model - delete callback -function deleteCallback_old(data){ - const layer = $D.overlayers[data.index]; - // for support QUIP2.0 - const idx = layer.data.findIndex(d=> d._id.$oid === data.oid ); - if(idx ==-1) return; - layer.data.splice(idx, 1); - - // delete entire layer if there is no data. - if(layer.data.length == 0){ - $D.overlayers.splice(data.index, 1); - $CAMIC.viewer.omanager.removeOverlay(data.id); - } - - - $CAMIC.viewer.omanager.updateView(); - // update layers Viewer - $UI.layersViewer.update(); - // close popup panel - $UI.annotPopup.close(); -} - - -function sort_change(sort){ - console.log('sort_change'); - $CAMIC.layersManager.sort(sort); - -} -function anno_callback(data){ - // is form ok? - const noteData = $UI.annotOptPanel._form_.value; - if($UI.annotOptPanel._action_.disabled || noteData.name == ''){ - - // close layer silde - $UI.toolbar._main_tools[1].querySelector('[type=checkbox]').checked = false; - $UI.layersSideMenu.close(); - - // open app silde - $UI.toolbar._main_tools[0].querySelector('[type=checkbox]').checked = true; - $UI.appsSideMenu.open(); - // open annotaion list - $UI.appsList.triggerContent('annotation','open'); - return; - - } - // has Path? - - if($CAMIC.viewer.canvasDrawInstance._path_index===0){ - alert('No Markup on Annotation.'); - return; - } - // save - // provenance - Loading.open($UI.annotOptPanel.elt,'Saving Annotation...'); - const exec_id = randomId(); - - const annotJson = { - provenance:{ - image:{ - slide:$D.params.data.name, - specimen:$D.params.data.specimen, - study:$D.params.data.study - }, - analysis:{ - source:'human', - execution_id:exec_id, - name:noteData.name - } - }, - properties:{ - annotations:noteData - }, - geometries:ImageFeaturesToVieweportFeatures($CAMIC.viewer, $CAMIC.viewer.canvasDrawInstance.getImageFeatureCollection()) - } - //return; - $CAMIC.store.addMark(annotJson) - .then(data=>{ - - // server error - if(data.error){ - $UI.message.addWarning(`${data.text}:${data.url}`); - Loading.close(); - return; - } - - // no data added - if(data.count < 1){ - Loading.close(); - $UI.message.addWarning(`Annotation Save Failed`); - return; - } - loadAnnotationById(null,exec_id); - }) - .catch(e=>{ - Loading.close(); - console.log('save failed'); - console.log(e); - }) - .finally(()=>{ - - }); -} - -function saveAnnotCallback(){ - /* reset as default */ - // clear draw data and UI - $CAMIC.viewer.canvasDrawInstance.drawOff(); - $CAMIC.drawContextmenu.off(); - toggleOffDrawBtns(); - $CAMIC.viewer.canvasDrawInstance.clear(); - // uncheck pen draw icon and checkbox - //$UI.toolbar._sub_tools[1].querySelector('[type=checkbox]').checked = false; - // clear form - $UI.annotOptPanel.clear(); - - // close app side - $UI.toolbar._main_tools[0].querySelector('[type=checkbox]').checked = false; - $UI.appsSideMenu.close(); - $UI.appsList.triggerContent('annotation','close'); - - // open layer side - $UI.toolbar._main_tools[1].querySelector('[type=checkbox]').checked = true; - $UI.layersSideMenu.open(); - $UI.layersViewer.update(); - -} -function algo_callback(data){ - console.log(data); - -} - -// overlayer manager callback function for show or hide -function callback(data){ - data.forEach(item => { - if(!item.layer){ - // load layer data - loadAnnotationById(item,item.id); - - }else{ - item.layer.isShow = item.isShow; - $CAMIC.viewer.omanager.updateView(); - } - }); -} - -function loadAnnotationById(item,id){ - Loading.open(document.body,'loading layers...'); - $CAMIC.store.getMarkByIds([id],$D.params.data.name) - .then(data =>{ - // response error - if(data.error){ - const errorMessage = `${data.text}: ${data.url}`; - $UI.message.addError(errorMessage, 5000); - const layer = $D.overlayers.find(layer => layer.id==id); - if(layer){ - layer.isShow = false; - $UI.layersViewer.update(); - } - return; - } - - // no data found - if(!data[0]){ - console.log(`Annotation:${id} doesn't exist.`); - $UI.message.addError(`Annotation:${id} doesn't exist.`,5000); - // delete item form layview - if(item) removeElement($D.overlayers,id); - $UI.layersViewer.update(); - return; - } - - - - - if(!item){ - console.log(data[0]); - item = covertToLayViewer(data[0].provenance); - item.isShow = true; - // update lay viewer UI - $D.overlayers.push(item); - $UI.layersViewer.update(); - saveAnnotCallback(); - }else{ - data[0].isShow = item.isShow; - } - - // for support quip 2.0 data model - if(data[0].geometry){ - - // twist them - var image = $CAMIC.viewer.world.getItemAt(0); - this.imgWidth = image.source.dimensions.x; - this.imgHeight = image.source.dimensions.y; - item.data = data.map(d => { - d.geometry.coordinates[0] = d.geometry.coordinates[0].map(point => { - return [Math.round(point[0]*imgWidth),Math.round(point[1]*imgHeight)]; - }); - d.properties.style = { - color: "#7CFC00", - lineCap: "round", - lineJoin: "round" - }; - return { - _id:d._id, - provenance:d.provenance, - properties:d.properties, - geometry:d.geometry - } - - - }); - if(item) data[0].isShow = item.isShow; - item.render = old_anno_render; - }else{ - data[0].geometries = VieweportFeaturesToImageFeatures($CAMIC.viewer, data[0].geometries); - item.data = data[0]; - item.render = anno_render; - } - - // create lay and update view - item.layer = $CAMIC.viewer.omanager.addOverlay(item); - $CAMIC.viewer.omanager.updateView(); - }) - .catch(e=>{ - console.error(e); - }) - .finally(()=>{ - Loading.close(); - }); -} /* collapsible list 1. Annotation @@ -694,52 +379,11 @@ function loadAnnotationById(item,id){ function getCurrentItem(data){ console.log(data); } -// some fake events callback for demo - - -function annotationSave(){ - $UI.message.add('Annotation Saved'); - -}; -function algoRun(){ - $UI.message.add('Algo is running...'); -} - -function saveAnnotation(){ - console.log('saveAnnotation'); - - anno_callback.call(null,{id:$UI.annotOptPanel.setting.formSchemas[$UI.annotOptPanel._select_.value].id, data:$UI.annotOptPanel._form_.value}); -} - -function saveAnalytics(){ - console.log('saveAnalytics'); -} -function startDrawing(e){ - $CAMIC.viewer.canvasDrawInstance.stop = !$UI.annotOptPanel._form_.isValid(); - return; -} -function stopDrawing(e){ - let state = +$UI.toolbar._sub_tools[1].querySelector('label').dataset.state; - if(state===1){ - saveAnnotation(); - } -} -/* call back list END */ -/* -- -- */ -/* -- for render anno_data to canavs -- */ -function anno_render(ctx,data){ - DrawHelper.draw(ctx, data.geometries.features); - //DrawHelper.draw(this._canvas_ctx, this.data.canvasData); -} -function old_anno_render(ctx,data){ - DrawHelper.draw(ctx, data); - -} function editorPenChange(data){ - $CAMIC.viewer.canvasDrawInstance.style.color = data[3]; } + function saveEditData(){ console.log('saveEditData'); if(!$CAMIC.viewer.canvasDrawInstance._draws_data_.length){ @@ -764,13 +408,14 @@ function saveEditData(){ }) // update heatmap view $CAMIC.viewer.heatmap.updateView(); - + $UI.heatmapEditedDataPanel.__refresh(); // TODO if success then close $CAMIC.viewer.canvasDrawInstance.clear(); console.log('saved'); } + function mergingEditedData(editedData, cates){ const clusters = new EditDataCluster(); editedData.features.forEach(feature => { @@ -782,46 +427,66 @@ function mergingEditedData(editedData, cates){ }) return clusters; } + +function locateEditData(data){ + const cluster = data.cluster; + const index = data.index; + + const rect = getViewRect( + data.cluster.editDataArray[index], + $D.heatMapData.provenance.analysis.size, + $CAMIC.viewer + ); + + $CAMIC.viewer.viewport.fitBounds(rect); +} + +function onDeleteEditData(data){ + const cluster = data.cluster; + const idx = data.index; + $D.editedDataClusters.data.removeEditDataForCluster(cluster.index, cluster.name, cluster.value, cluster.color, idx); + + // refresh UI + $UI.heatmapEditedDataPanel.__refresh(); + $CAMIC.viewer.heatmap.updateView(); + if($D.editedDataClusters.data.isEmpty()) + alert('NO'); + +} + function findPenInfoByColor(color,info){ return info.find(i=>i[3]==color); } +function getViewRect(points , size, viewer){ // points in normalized, size in normalized, viewer + const point = getBounds(points); + const viewport = viewer.viewport; + const imagingHelper = viewer.imagingHelper; + let min = [point.min[0] - size[0], point.min[1] - size[1]]; + let max = [point.max[0] + size[0]+size[0],point.max[1] +size[1]+size[1]]; + min = [imagingHelper.logicalToDataX(min[0]), imagingHelper.logicalToDataY(min[1])]; + max = [imagingHelper.logicalToDataX(max[0]), imagingHelper.logicalToDataY(max[1])]; + + + return viewport.imageToViewportRectangle(min[0],min[1],max[0]-min[0], max[1]-min[1]); + +} +function getBounds(points){ // return x,y,w,h + let max,min; + points.forEach(point => { + if (!min && !max) { + min = [point[0], point[1]]; + max = [point[0], point[1]]; + } else { + min[0] = Math.min(point[0], min[0]); + max[0] = Math.max(point[0], max[0]); + min[1] = Math.min(point[1], min[1]); + max[1] = Math.max(point[1], max[1]); + } + }); + return { + min:min, + max:max + }; +} -/* -- -- */ -// const fieldsColors = ['#576971','#0A1316','#DFB9C1','#2F1218','#C0A7A3','#271A18','#D07DBE', '#2F0526']; -// function createEeditorPanel(fields,changeFuc,saveFuc){ - -// const container = document.createElement('div'); -// container.classList.add('hmc-container'); -// const name = randomId(); -// let radiosTemplatec =''; -// fields.forEach((field,idx)=>{ -// radiosTemplatec+= `  
`; -// radiosTemplatec+= `  
`; -// }) - - - -// container.innerHTML = radiosTemplatec; -// //container.querySelector -// const radios = container.querySelectorAll(`input[type=radio][name=${name}]`); -// radios[0].checked = true; -// radios.forEach(radio=>{ -// radio.addEventListener('change',function(e){ -// const target = e.srcElement || e.target; -// if(isFunction(changeFuc)) -// changeFuc.call(null,target.value.split('|')); -// }); -// }) -// const saveBtn = document.createElement('button'); -// saveBtn.appendChild(document.createTextNode("SAVE")); -// saveBtn.addEventListener('click',function(){ -// if(isFunction(saveFuc))saveFuc(); -// }); -// container.appendChild(saveBtn); -// return container; -// } -// function getEditor(){ -// const radio = $UI.heatmapEditorPanel.querySelector('input[type=radio]:checked'); -// return radio?radio.value.split('|'):null; -// } diff --git a/common/heatmapeditdatamodels.js b/common/heatmapeditdatamodels.js index 0cedfd354..86b4d6986 100644 --- a/common/heatmapeditdatamodels.js +++ b/common/heatmapeditdatamodels.js @@ -21,10 +21,15 @@ class EditDataCluster{ constructor(clusters=[]){ this.clusters = clusters; } + isEmpty(){ + return !(this.clusters&&this.clusters.length > 0); + } getCluster(index,name,value,color){ return this.clusters.find(cluster => cluster.index==index&&cluster.name==name&&cluster.value==value&&cluster.color==color); } - + getClusterIndex(index,name,value,color){ + return this.clusters.findIndex(cluster => cluster.index==index&&cluster.name==name&&cluster.value==value&&cluster.color==color); + } addEditDateForCluster(index, name, value, color, editData){ if(!Array.isArray(editData)) return; let cluster = this.getCluster(index, name, value, color); @@ -34,5 +39,18 @@ class EditDataCluster{ } cluster.addEditData(editData) } + + removeEditDataForCluster(index,name,value,color, idx = null){ + const clusterIdx = this.getClusterIndex(index,name,value,color); + + if(clusterIdx ==-1) return; + const cluster = this.clusters[clusterIdx]; + if(idx==null){ // remove all + this.clusters.splice(clusterIdx,1); + } else { + cluster.removeEditDataByIndex(idx); + if(cluster.editDataArray.length==0) this.clusters.splice(clusterIdx,1); + } + } } diff --git a/components/heatmapcontrol/heatmapcontrol.js b/components/heatmapcontrol/heatmapcontrol.js index c0369c1f2..68bade4bb 100644 --- a/components/heatmapcontrol/heatmapcontrol.js +++ b/components/heatmapcontrol/heatmapcontrol.js @@ -225,14 +225,4 @@ function createOpacities(container, field, changeFunc){ }); container.appendChild(div); return rs; -} -// function createRadios(mode){ -// const radios = { -// binal:document.createElement('input'), -// gradient:document.createElement('input') -// }; -// = randomId(); -// radios['binal'].value = 'binal'; -// radios['binal'].name = 'binal'; - -// } \ No newline at end of file +} \ No newline at end of file diff --git a/components/heatmapediteddatapanel/heatmapediteddatapanel.css b/components/heatmapediteddatapanel/heatmapediteddatapanel.css new file mode 100644 index 000000000..a0f5155f6 --- /dev/null +++ b/components/heatmapediteddatapanel/heatmapediteddatapanel.css @@ -0,0 +1,65 @@ +/*heatmapediteddatapanel.css*/ + +.hmed-container { + border: 1px solid #ccc; + display: block; + position: relative; + padding: .5rem; + margin: .5rem; + color: #365f9c; + font-size:1.3rem; +} + +.hmed-container .title { + margin-top: .5rem; + padding: 0 1.0rem 0 1.5rem; + display: -webkit-box; + display: -moz-box; + display: -ms-flexbox; + display: -webkit-flex; + display: flex; +} +.hmed-container .title .icon,.hmed-container .list .icon { + border: #cbcbcb 1px solid; + background-color: #f6f6f6; + cursor: pointer; +} +.hmed-container .title label,.hmed-container .list label { + cursor: pointer; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + display: -webkit-flex; + display: flex; + flex: 1; + margin-left: -1px; + border: #cbcbcb 1px solid; + font-weight: bold; +} + +.hmed-container .title label div,.hmed-container .list label div{ + margin: 0 auto; +} +.margin-left-1 { + margin-left:-1px; +} +.color-block { + width:4rem; + height:2rem; +} + + + + + + +.hmed-container .list { + display:flex; + flex-direction:column; +} +.hmed-container .list > div{ + display:flex; + flex:1; + margin-top: .5rem; + padding: 0 2rem 0 3rem; +} \ No newline at end of file diff --git a/components/heatmapediteddatapanel/heatmapediteddatapanel.js b/components/heatmapediteddatapanel/heatmapediteddatapanel.js new file mode 100644 index 000000000..8cf17635e --- /dev/null +++ b/components/heatmapediteddatapanel/heatmapediteddatapanel.js @@ -0,0 +1,113 @@ +// heatmapediteddatapanel.js +function HeatmapEditedDataPanel(options){ + this.name = 'HeatmapEditedDataPanel'; + /* + list:[ + { + id: , + title: , + icon: , + content:string + isExpand:, + + } + ] + */ + this.setting = { + data:null, + onDBClick:null, + onDelete:null + } + + extend(this.setting, options); + + // attach container element + this.elt = document.getElementById(this.setting.id); + if(!this.elt && this.setting.element){ + this.elt = this.setting.element; + } + + if(!this.elt){ + // create main + this.elt = document.createElement('div'); + } + + //create UI + this.__refresh(); + +} +/** + * @private + * __refresh refresh UI part accoding to this.setting + */ +HeatmapEditedDataPanel.prototype.__refresh = function(){ + empty(this.elt); + this.elt.classList.add('hmed-container'); + this._clusters = []; + this.setting.data.clusters.forEach(cluster => { + const name = cluster.name; + const index = cluster.index; + const value = +cluster.value; + const color = cluster.color; + const cate_value = value?'Poistive':'Negative'; + const title = createEditedDataTitle(name,cate_value); + this.elt.appendChild(title); + // add toggle event + title.querySelector('.icon').addEventListener('click', function(e){ + const list = title.nextElementSibling; + if(title.querySelector('.icon').textContent=='keyboard_arrow_up'){ + title.querySelector('.icon').textContent = 'keyboard_arrow_down'; + list.style.display = 'none'; + }else{ + title.querySelector('.icon').textContent = 'keyboard_arrow_up'; + list.style.display = ''; + } + }); + + + + + const listDiv = document.createElement('div'); + listDiv.classList.add('list'); + this.elt.appendChild(listDiv); + cluster.editDataArray.forEach((line,idx) => { + const lineDiv = createEditedDataItem(idx,color); + listDiv.appendChild(lineDiv); + + lineDiv.addEventListener('dblclick', function(e){ + if(isFunction(this.setting.onDBClick)) + this.setting.onDBClick.call(lineDiv, { + cluster:cluster, + index:idx + }); + }.bind(this)); + + lineDiv.querySelector('.icon').addEventListener('click', function(e){ + if(isFunction(this.setting.onDelete)) + this.setting.onDelete.call(lineDiv, { + cluster:cluster, + index:idx + }); + }.bind(this)); + + }); + + }); +} +function createEditedDataTitle(name, cate){ + const div = document.createElement('div'); + div.classList.add('title'); + const clusterTemplate = `
keyboard_arrow_up
`; + div.innerHTML = clusterTemplate; + return div; +} +function createEditedDataItem(idx, color){ + const div = document.createElement('div'); + div.innerHTML = `
clear
`; + return div; +} + + +HeatmapEditedDataPanel.prototype.__dbclick = function(){ + +} \ No newline at end of file diff --git a/iconfont/material-icons.css b/iconfont/material-icons.css index 0ad8660c5..27465692f 100755 --- a/iconfont/material-icons.css +++ b/iconfont/material-icons.css @@ -40,7 +40,18 @@ .material-icons.md-12 { font-size: 1.2rem; } - +.material-icons.md-11 { + font-size: 1.1rem; +} +.material-icons.md-13 { + font-size: 1.3rem; +} +.material-icons.md-15 { + font-size: 1.5rem; +} +.material-icons.md-18 { + font-size: 1.8rem; +} .material-icons.md-24 { font-size: 2.4rem; }