@@ -59,6 +59,11 @@ define([
5959select :null , // callback after selection from suggestInput (value, dtype)
6060allowDataType :null , // list of allowed data types
6161dataCategory :null , // list of data category (use it for ml categories)
62+ columnSelection :'multiple' , // single/multi : allowed column selection
63+ returnFrameType :'' , // DataFrame/Series : required data type for DataFrame -> Series/DataFrame operation
64+ // if Series, only one column selection is allowed and returns Series
65+ // if DataFrame, always returns DataFrame
66+ // if Empty(=== ''), if one column selected, returns Series / others, returns DataFrame
6267// additional options
6368boxClasses :'' ,
6469classes :'' ,
@@ -87,6 +92,9 @@ define([
8792this . prop . dataCategory = this . prop . allowDataType ;
8893}
8994}
95+ if ( this . prop . returnFrameType === 'Series' ) {
96+ this . prop . columnSelection = 'single' ; // only single selection allowed
97+ }
9098
9199this . state = {
92100filterType :'All' ,
@@ -98,6 +106,7 @@ define([
98106slicingEnd1 :'' ,
99107slicingStart2 :'' ,
100108slicingEnd2 :'' ,
109+ singleColumn :'' ,
101110ndRowType :'slicing' ,
102111ndColType :'slicing' ,
103112useIndex :false ,
@@ -409,6 +418,19 @@ define([
409418}
410419}
411420
421+ templateForSingleSelector ( ) {
422+ return `
423+ <div>
424+ <label><input type="checkbox" id="useIndex" class="vp-state"${ this . state . useIndex === true ?'checked' :'' } /> <span>Use Index</span></label>
425+ <div class="vp-ds-df-singleselector"${ this . state . useIndex === true ?'style="display:none;"' :'' } >
426+ <label class="w50">Column</label>
427+ <select id="singleColumn" class="vp-select vp-state w150">
428+ </select>
429+ </div>
430+ </div>
431+ `
432+ }
433+
412434templateForMultiSelector ( ) {
413435return `
414436 <div class="vp-ds-df-option-box">
@@ -599,22 +621,93 @@ define([
599621
600622switch ( dataType ) {
601623case 'DataFrame' :
602- // render option page
603- $ ( this . wrapSelector ( '.vp-ds-option-inner-box' ) ) . html ( this . templateForMultiSelector ( ) ) ;
604624// column selecting
605- this . _columnSelector = new MultiSelector ( this . wrapSelector ( '.vp-ds-df-multiselector' ) ,
606- { mode :'columns' , parent :[ data ] , selectedList :this . state . indexing , allowAdd :true }
607- ) ;
608-
625+ if ( this . prop . columnSelection === 'single' ) {
626+ // render option page
627+ $ ( this . wrapSelector ( '.vp-ds-option-inner-box' ) ) . html ( this . templateForSingleSelector ( ) ) ;
628+ // bind column source
629+ // com_generator.vp_bindColumnSource(this, 'data', ['singleColumn'], 'select', false, false);
630+ // vp_bindColumnSource(pageThis, targetId, columnInputIdList, tagType="input", columnWithEmpty=false, columnWithIndex=false)
631+ const columnInputIdList = [ 'singleColumn' ] ;
632+ if ( data === '' ) {
633+ // reset with no source
634+ columnInputIdList && columnInputIdList . forEach ( columnInputId => {
635+ let defaultValue = that . state [ columnInputId ] ;
636+ if ( defaultValue === null || defaultValue === undefined ) {
637+ defaultValue = '' ;
638+ }
639+ // option tags
640+ var tag = $ ( '<select></select>' ) . attr ( {
641+ 'id' :columnInputId ,
642+ 'class' :'vp-select vp-state'
643+ } ) ;
644+ $ ( that . wrapSelector ( '#' + columnInputId ) ) . replaceWith ( function ( ) {
645+ return $ ( tag ) ;
646+ } ) ;
647+ } ) ;
648+ return ;
649+ }
650+ // get result and show on detail box
651+ vpKernel . getColumnList ( data ) . then ( function ( resultObj ) {
652+ try {
653+ let { result, type, msg} = resultObj ;
654+ var { list} = JSON . parse ( result ) ;
655+
656+ // columns using suggestInput
657+ columnInputIdList && columnInputIdList . forEach ( ( columnInputId , idx ) => {
658+ let defaultValue = that . state [ columnInputId ] ;
659+ if ( defaultValue === null || defaultValue === undefined ) {
660+ defaultValue = '' ;
661+ }
662+ // create tag
663+ var tag = $ ( '<select></select>' ) . attr ( {
664+ 'id' :columnInputId ,
665+ 'class' :'vp-select vp-state w150'
666+ } ) ;
667+ // make tag
668+ list . forEach ( ( listVar , idx ) => {
669+ var option = document . createElement ( 'option' ) ;
670+ $ ( option ) . attr ( {
671+ 'value' :listVar . value ,
672+ 'text' :listVar . label ,
673+ 'data-type' :listVar . dtype
674+ } ) ;
675+ // cell metadata test : defaultValue as selected
676+ if ( listVar . value === defaultValue ) {
677+ $ ( option ) . prop ( 'selected' , true ) ;
678+ }
679+ option . append ( document . createTextNode ( listVar . label ) ) ;
680+ $ ( tag ) . append ( option ) ;
681+ } ) ;
682+ $ ( that . wrapSelector ( '#' + columnInputId ) ) . replaceWith ( function ( ) {
683+ return $ ( tag ) ;
684+ } ) ;
685+ $ ( that . wrapSelector ( '#' + columnInputId ) ) . trigger ( 'change' ) ;
686+ } ) . catch ( function ( err ) {
687+ vpLog . display ( VP_LOG_TYPE . ERROR , 'com_generator - bindColumnSource error ' , err )
688+ } ) ;
689+ } catch ( e ) {
690+ vpLog . display ( VP_LOG_TYPE . ERROR , 'com_generator - bindColumnSource: not supported data type. ' , e ) ;
691+ }
692+ } ) ;
693+ } else {
694+ // render option page
695+ $ ( this . wrapSelector ( '.vp-ds-option-inner-box' ) ) . html ( this . templateForMultiSelector ( ) ) ;
696+ this . _columnSelector = new MultiSelector ( this . wrapSelector ( '.vp-ds-df-multiselector' ) ,
697+ { mode :'columns' , parent :[ data ] , selectedList :this . state . indexing , allowAdd :true }
698+ ) ;
699+ }
609700// bind event
610701$ ( this . wrapSelector ( '#useIndex' ) ) . on ( 'change' , function ( ) {
611702let checked = $ ( this ) . prop ( 'checked' ) ;
612703that . state . useIndex = checked ;
613704if ( checked === true ) {
614705$ ( that . wrapSelector ( '.vp-ds-df-multiselector' ) ) . hide ( ) ;
706+ $ ( that . wrapSelector ( '.vp-ds-df-singleselector' ) ) . hide ( ) ;
615707$ ( that . wrapSelector ( '.vp-ds-df-index-box' ) ) . show ( ) ;
616708} else {
617709$ ( that . wrapSelector ( '.vp-ds-df-multiselector' ) ) . show ( ) ;
710+ $ ( that . wrapSelector ( '.vp-ds-df-singleselector' ) ) . show ( ) ;
618711$ ( that . wrapSelector ( '.vp-ds-df-index-box' ) ) . hide ( ) ;
619712}
620713} ) ;
@@ -728,6 +821,7 @@ define([
728821let {
729822 data, dataType,
730823 useIndex,
824+ singleColumn,
731825 slicingStart1, slicingEnd1,
732826 slicingStart2, slicingEnd2,
733827 ndRowType, ndColType
@@ -742,21 +836,39 @@ define([
742836code . append ( '.index' ) ;
743837} else {
744838// use column selector
745- if ( this . _columnSelector != null ) {
746- let result = this . _columnSelector . getDataList ( ) ;
747- this . state . indexing = result . map ( obj => obj . code ) ; // save state
748- let columnList = [ ] ;
749- result && result . forEach ( obj => {
750- columnList . push ( obj . code ) ;
751- } ) ;
752- if ( columnList . length > 0 ) {
753- if ( columnList . length == 1 ) {
754- // return as Series
755- code . appendFormat ( '[{0}]' , columnList . join ( ', ' ) ) ;
756- // change datatype to Series
757- this . state . returnDataType = 'Series' ;
758- } else {
759- code . appendFormat ( '[[{0}]]' , columnList . join ( ', ' ) ) ;
839+ if ( this . prop . columnSelection === 'single' ) {
840+ // single selector
841+ if ( this . prop . returnFrameType === 'DataFrame' ) {
842+ // return as DataFrame
843+ code . appendFormat ( '[[{0}]]' , singleColumn ) ;
844+ } else {
845+ // return as Series
846+ code . appendFormat ( '[{0}]' , singleColumn ) ;
847+ this . state . returnDataType = 'Series' ;
848+ }
849+ } else {
850+ // multiple selector
851+ if ( this . _columnSelector != null ) {
852+ let result = this . _columnSelector . getDataList ( ) ;
853+ this . state . indexing = result . map ( obj => obj . code ) ; // save state
854+ let columnList = [ ] ;
855+ result && result . forEach ( obj => {
856+ columnList . push ( obj . code ) ;
857+ } ) ;
858+ if ( columnList . length > 0 ) {
859+ if ( columnList . length == 1 ) {
860+ if ( this . prop . returnFrameType === 'DataFrame' ) {
861+ // return as DataFrame
862+ code . appendFormat ( '[[{0}]]' , columnList . join ( ', ' ) ) ;
863+ } else {
864+ // return as Series
865+ code . appendFormat ( '[{0}]' , columnList . join ( ', ' ) ) ;
866+ // change datatype to Series
867+ this . state . returnDataType = 'Series' ;
868+ }
869+ } else {
870+ code . appendFormat ( '[[{0}]]' , columnList . join ( ', ' ) ) ;
871+ }
760872}
761873}
762874}