/* Ċ Ġ* ĠCopyright Ġ 2 0 2 0 ĠPoly ĠForest , ĠLLC Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ Ċ @ file : Suppress (" Css Replace With Sh orthand S af ely ", Ġ" Css Invalid PropertyValue ", Ġ" Css Un resolved Custom Property ", Ċ ĉ " Css No Generic Font Name ", Ġ" Member Visibility Can Be Private ", Ġ" unused " Ċ ) Ċ Ċ package Ġcom . ac orn ui . component . data grid Ċ Ċ import Ġcom . ac orn ui . Disposable Ċ import Ġcom . ac orn ui . Equality Check Ċ import Ġcom . ac orn ui . component .* Ċ import Ġcom . ac orn ui . component . input . Button Ċ import Ġcom . ac orn ui . component . style . css Class Ċ import Ġcom . ac orn ui . component . style . css Var Ċ import Ġcom . ac orn ui . component . text . TextField Ċ import Ġcom . ac orn ui . component . text . text Ċ import Ġcom . ac orn ui . di . Context Ċ import Ġcom . ac orn ui . dom .* Ċ import Ġcom . ac orn ui . google . Icons Ċ import Ġcom . ac orn ui . input .* Ċ import Ġcom . ac orn ui . observe . ChangeEvent Ċ import Ġcom . ac orn ui . recycle . Clear able Ċ import Ġcom . ac orn ui . recycle . recycle Ċ import Ġcom . ac orn ui . signal . Signal Subscription Ċ import Ġcom . ac orn ui . signal . signal Ċ import Ġcom . ac orn ui . sk ins . Css Props Ċ import Ġcom . ac orn ui . time . next Frame Callback Ċ import Ġkotlinx . browser . document Ċ import Ġkotlinx . collections . immutable . mutate Ċ import Ġkotlinx . collections . immutable . to Persistent List Ċ import Ġorg . w 3 c . dom . HTML Div Element Ċ import Ġorg . w 3 c . dom . HTML InputElement Ċ import Ġorg . w 3 c . dom . Parent Node Ċ import Ġkotlin . contracts . Invocation Kind Ċ import Ġkotlin . contracts . contract Ċ import Ġkotlin . properties . Deleg ates Ċ import Ġcom . ac orn ui . dom . footer Ġas Ġfooter El Ċ Ċ open Ġclass ĠData Grid < E >( owner : ĠContext ) Ġ: ĠDiv ( owner ) Ġ{ ĊĊ ĉ /** Ċĉ Ġ* ĠThis Ġgrid 's Ġ[ data ] Ġhas Ġchanged . Ċĉ Ġ*/ Ċ ĉ val Ġdata Changed Ġ= Ġsignal < ChangeEvent < List < E >> >() ĊĊ ĉ class ĠRow Submitted Event < E >( ĊĊĉ ĉ /** Ċĉĉ Ġ* ĠThe Ġrow Ġindex Ġwithin Ġ[ data ] Ċĉĉ Ġ*/ Ċĉ ĉ val Ġindex : ĠInt , ĊĊĉ ĉ /** Ċĉĉ Ġ* ĠThe Ġrow Ġindex Ġwithin Ġ[ data View ] Ċĉĉ Ġ*/ Ċĉ ĉ val Ġview Index : ĠInt , ĊĊĉ ĉ val Ġold Data : ĠE , Ċĉ ĉ val ĠnewData : ĠE Ċ ĉ ) Ġ: ĠEvent ( c ancellable Ġ= Ġtrue ) ĊĊ ĉ /** Ċĉ Ġ* ĠDis patched Ġwhen Ġthe Ġrow Ġeditor Ġform Ġhas Ġbeen Ġsubmitted Ġand Ġthe Ġform Ġis Ġvalid . Ċĉ Ġ* ĠThis Ġis Ġtypically Ġwhen Ġdata Ġrequests Ġshould Ġbe Ġmade . Ċĉ Ġ* Ġ@ see Ġauto Mutate Ċĉ Ġ*/ Ċ ĉ val Ġrow Submitted Ġ= Ġsignal < Row Submitted Event < E >>() ĊĊ ĉ class ĠRow Edit Event < E >( val Ġitem : ĠE ?) Ġ: ĠEvent ( c ancellable Ġ= Ġtrue ) ĊĊ ĉ /** Ċĉ Ġ* ĠThe Ġcurrently Ġedited Ġrow Ġhas Ġchanged . ĠThis Ġmay Ġbe Ġcancelled . Ċĉ Ġ*/ Ċ ĉ val Ġrow Edited Ġ= Ġsignal < Row Edit Event < E >>() ĊĊ ĉ /** Ċĉ Ġ* ĠIf Ġfalse Ġ( default ) Ġclicking Ġa Ġrow Ġwill Ġnot Ġopen Ġthe Ġrow Ġeditor . Ċĉ Ġ* ĠCalling Ġ[ row Editor ] Ġwill Ġset Ġthis Ġto Ġtrue . Ċĉ Ġ*/ Ċ ĉ var Ġeditable Ġ= Ġfalse ĊĊ ĉ var Ġrow Builder : Ġ( DataGrid Row < E >. () Ġ-> ĠUnit )? Ġ= Ġnull Ċĉ ĉ private Ġset ĊĊ ĉ /** Ċĉ Ġ* ĠSets Ġthe Ġcallback Ġto Ġpopulate Ġa Ġnew Ġrow Ġwith Ġcells . Ċĉ Ġ* ĠRows Ġare Ġre cyc led Ġand Ġshould Ġset Ġtheir Ġvalues Ġwithin Ġ[ DataGrid Row . data ] Ġblocks . Ċĉ Ġ* Ċĉ Ġ* ĠExample : Ċĉ Ġ* Ċĉ Ġ* Ġ``` Ċĉ Ġ* Ġrows Ġ= Ġ{ Ċĉ Ġ* ĠĠ Ġ+ cell Ġ{ Ċĉ Ġ* ĠĠĠĠ Ġdata Ġ{ Ċĉ Ġ* ĠĠĠĠĠĠ Ġlabel Ġ= Ġit . name Ċĉ Ġ* ĠĠĠĠ Ġ} Ċĉ Ġ* ĠĠĠĠ Ġtab Index Ġ= Ġ 0 Ċĉ Ġ* ĠĠ Ġ} Ċĉ Ġ* Ġ} Ċĉ Ġ* Ġ``` Ċĉ Ġ*/ Ċ ĉ fun Ġrows ( builder : ĠData Grid Row < E >. () Ġ-> ĠUnit ) Ġ{ Ċĉ ĉ display Rows . forEach ( Disposable :: dispose ) Ċĉ ĉ display Rows . clear () Ċĉ ĉ row Builder Ġ= Ġbuilder Ċĉ ĉ refresh Rows () Ċ ĉ } ĊĊ ĉ var Ġdata : ĠList < E > Ġ= Ġempty List () Ċĉ ĉ set ( value ) Ġ{ Ċĉĉ ĉ val Ġold Ġ= Ġfield Ċĉĉ ĉ if Ġ( old Ġ== Ġvalue ) Ġreturn Ċĉĉ ĉ field Ġ= Ġvalue Ċĉĉ ĉ data Changed . dispatch ( ChangeEvent ( old , Ġvalue )) Ċĉĉ ĉ refresh Rows () Ċĉ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠIf Ġtrue Ġ( default ), Ġgrid Ġrows Ġwill Ġbe Ġre cyc led Ġeven Ġif Ġa Ġnew Ġdata Ġset Ġhas Ġno Ġmatch Ġusing Ċĉ Ġ* Ġ[ data Matcher ] Ċĉ Ġ*/ Ċ ĉ var Ġalways Re cycle Rows Ġ= Ġfalse ĊĊ ĉ /** Ċĉ Ġ* ĠThe Ġequality Ġcheck Ġis Ġused Ġto Ġselect Ġthe Ġexisting Ġelement Ġto Ġreuse . Ċĉ Ġ* ĠThis Ġis Ġused Ġto Ġassist Ġin Ġrow Ġre cycl ing Ġand Ġreduce Ġthe Ġnumber Ġof Ġbinding Ġchanges . Ċĉ Ġ* ĠBy Ġdefault Ġthis Ġis Ġa Ġgeneral Ġequality Ġ` == `. Ċĉ Ġ* ĠA Ġtypical Ġuse Ġcase Ġwould Ġbe Ġto Ġset Ġthe Ġdata Ġmatcher Ġto Ġmatch Ġby Ġan ĠID . Ċĉ Ġ* ĠĠ Ġe . g . Ċĉ Ġ* ĠĠ Ġ``` data Matcher Ġ= Ġ{ Ġa , Ġb Ġ-> Ġa ?. id Ġ== Ġb ?. id Ġ} ``` Ċĉ Ġ*/ Ċ ĉ var Ġdata Matcher : ĠE quality Check < E ?> Ġ= Ġ{ Ġa , Ġb Ġ-> Ġa Ġ== Ġb Ġ} ĊĊ ĉ var Ġsort : ĠList < Column Sort < E >> Ġ= Ġempty List () Ċĉ ĉ set ( value ) Ġ{ Ċĉĉ ĉ if Ġ( field Ġ== Ġvalue ) Ġreturn Ċĉĉ ĉ field Ġ= Ġvalue Ċĉĉ ĉ refresh Rows () Ċĉ ĉ } ĊĊ ĉ fun Ġsort ( var arg Ġcolumn Sort : ĠColumn Sort < E >) Ġ{ Ċĉ ĉ this . sort Ġ= Ġcolumn Sort . toList () Ċ ĉ } ĊĊ ĉ private Ġfun Ġsort Comparator ( a : ĠE , Ġb : ĠE ): ĠInt Ġ{ Ċĉ ĉ for Ġ( column Sort Ġin Ġsort ) Ġ{ Ċĉĉ ĉ if Ġ( column Sort . direction Ġ== ĠColumn Sort Direction . NONE ) Ġcontinue Ċĉĉ ĉ val Ġv 1 Ġ= Ġcolumn Sort . selector ( a ) Ċĉĉ ĉ val Ġv 2 Ġ= Ġcolumn Sort . selector ( b ) Ċĉĉ ĉ val Ġdiff Ġ= Ġcompare Values ( v 1 , Ġv 2 ) Ċĉĉ ĉ if Ġ( diff Ġ!= Ġ 0 ) Ġreturn Ġif Ġ( column Sort . direction Ġ== ĠColumn Sort Direction . ASC ENDING ) Ġdiff Ġelse Ġ- diff Ċĉ ĉ } Ċĉ ĉ return Ġ 0 Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠThe Ġdata Ġwith Ġany Ġview Ġtransformations Ġsuch Ġas Ġsorting . Ċĉ Ġ*/ Ċ ĉ var Ġdata View : ĠList < E > Ġ= Ġempty List () Ċĉ ĉ private Ġset ĊĊ ĉ /** Ċĉ Ġ* ĠNe cessary Ġonly Ġfor ĠSafari Ċĉ Ġ* Ġhttps :// stackoverflow . com / questions / 5 7 9 3 4 8 0 3 / work around - for - a - s afari - position - sticky - webkit - sticky - bug Ċĉ Ġ*/ Ċ ĉ val Ġmain Container Ġ= Ġadd Child ( div Ġ{ Ċĉ ĉ addClass ( DataGrid Style . main Container Style ) Ċ ĉ }) ĊĊ ĉ val Ġheader Ġ= Ġmain Container . addElement ( div Ġ{ Ċĉ ĉ addClass ( DataGrid Style . header Row Style ) Ċ ĉ }) ĊĊ ĉ /** Ċĉ Ġ* ĠCalls Ġthe Ġspecified Ġfunction Ġ[ block ] Ġwith Ġ[ header ] Ġas Ġits Ġreceiver . Ċĉ Ġ*/ Ċ ĉ fun Ġheader ( block : ĠUi Component . () Ġ-> ĠUnit ) Ġ{ Ċĉ ĉ header . apply ( block ) Ċ ĉ } ĊĊ ĉ val Ġcontents Ġ= Ġmain Container . addElement ( div Ġ{ Ċĉ ĉ addClass ( DataGrid Style . contents Container Style ) Ċ ĉ }) ĊĊ ĉ private Ġval Ġdisplay Rows Ġ= ĠArrayList < DataGrid Row < E >>() ĊĊ ĉ private Ġvar Ġis Second Save Attempt Ġ= Ġfalse ĊĊ ĉ /** Ċĉ Ġ* ĠThe Ġrow Ġeditor . ĠThis Ġmay Ġbe Ġconfigured Ġvia Ġ[ row Editor ] Ċĉ Ġ*/ Ċ ĉ val Ġrow Editor Ġ= Ġdata Grid Row Editor < E > Ġ{ Ċĉ ĉ key Pressed . listen Ġ{ Ċĉĉ ĉ if Ġ( it . keyCode Ġ== ĠAsc ii . ENTER Ġ&& Ġit . shift Key ) Ċĉĉĉ ĉ if Ġ( submit Row ( report Validity Ġ= Ġfalse )) Ċĉĉĉĉ ĉ edit Previous Row () Ċĉ ĉ } Ċĉ ĉ submitted . listen Ġ{ Ċĉĉ ĉ if Ġ( submit Row ( report Validity Ġ= Ġfalse )) Ċĉĉĉ ĉ edit Next Row () Ċĉ ĉ } Ċĉ ĉ input . listen Ġ{ Ċĉĉ ĉ is Second Save Attempt Ġ= Ġfalse Ċĉ ĉ } Ċĉ ĉ focused Out Container . listen Ġ{ Ċĉĉ ĉ if Ġ( submit Row () Ġ|| Ġis Second Save Attempt ) Ċĉĉĉ ĉ edit Row ( null ) Ċĉĉ ĉ else Ċĉĉĉ ĉ is Second Save Attempt Ġ= Ġtrue Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠReturns Ġthe Ġcurrently Ġedited Ġrow . Ċĉ Ġ*/ Ċ ĉ val Ġedited Row : ĠE ? Ċĉ ĉ get () Ġ= Ġrow Editor . data ĊĊ ĉ /** Ċĉ Ġ* ĠReturns Ġthe Ġcurrently Ġfocused Ġcell Ġwithin Ġthe Ġrow , Ġor Ġ- 1 Ġif Ġthe Ġrow Ġisn 't Ġfocused . Ċĉ Ġ*/ Ċ ĉ val Ġedited Cell Index : ĠInt Ċĉ ĉ get () Ġ= Ġrow Editor . active Cell Index ĊĊ ĉ private Ġval ĠUi Component . active Cell Index : ĠInt Ċĉ ĉ get () Ġ{ Ċĉĉ ĉ val Ġactive Element Ġ= Ġdocument . active Element Ġ?: Ġreturn Ġ- 1 Ċĉĉ ĉ return Ġelements . indexOf First Ġ{ Ċĉĉĉ ĉ it . dom . contains ( active Element ) Ċĉĉ ĉ } Ċĉ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠCalls Ġthe Ġspecified Ġfunction Ġ[ block ] Ġwith Ġ[ row Editor ] Ġas Ġits Ġreceiver . Ċĉ Ġ*/ Ċ ĉ fun Ġrow Editor ( block : ĠData Grid Row Editor < E >. () Ġ-> ĠUnit ) Ġ{ Ċĉ ĉ editable Ġ= Ġtrue Ċĉ ĉ row Editor . apply ( block ) Ċ ĉ } ĊĊ ĉ val Ġfooter Ġ= Ġmain Container . addElement ( footer El Ġ{ Ċĉ ĉ addClass ( DataGrid Style . footer Row Style ) Ċ ĉ }) ĊĊ ĉ /** Ċĉ Ġ* ĠCalls Ġthe Ġspecified Ġfunction Ġ[ block ] Ġwith Ġ[ footer ] Ġas Ġits Ġreceiver . Ċĉ Ġ*/ Ċ ĉ fun Ġfooter ( block : ĠUi Component . () Ġ-> ĠUnit ) Ġ{ Ċĉ ĉ footer . apply ( block ) Ċ ĉ } ĊĊ ĉ private Ġval Ġrefresh Rows Ġ= Ġnext Frame Callback Ġ{ Ċĉ ĉ if Ġ( is Disposed ) Ġreturn @ next Frame Callback Ċĉ ĉ data View Ġ= Ġdata . sorted With (:: sort Comparator ) ĊĊĉ ĉ header . elements . forEach Ġ{ Ċĉĉ ĉ if Ġ( it Ġis ĠHeader Cell ) Ġ{ Ċĉĉĉ ĉ it . sort Display Ġ= ĠColumn Sort Direction . NONE Ċĉĉ ĉ } Ċĉ ĉ } Ċĉ ĉ for Ġ( column Sort Ġin Ġsort ) Ġ{ Ċĉĉ ĉ column Sort . header Cell ?. sort Display Ġ= Ġcolumn Sort . direction Ċĉ ĉ } ĊĊĉ ĉ val Ġpreviously Focused Ġ= Ġedited Cell Index Ċĉ ĉ val Ġpreviously Edited Ġ= Ġedited Row Ċĉ ĉ edit Row ( null ) Ċĉ ĉ recycle ( data View , Ġdisplay Rows , Ġfactory Ġ= Ġ{ Ġ_: ĠE , Ġ_: ĠInt Ġ-> Ċĉĉ ĉ create Row () Ċĉ ĉ }, Ġconfigure Ġ= Ġ{ Ġelement : ĠData Grid Row < E >, Ġitem : ĠE , Ġindex : ĠInt Ġ-> Ċĉĉ ĉ element . data Ġ= Ġitem Ċĉĉ ĉ contents . addElement ( index , Ġelement ) Ċĉ ĉ }, Ġdis poser Ġ= Ġ{ Ċĉĉ ĉ it . dispose () Ċĉ ĉ }, Ġretrie ver Ġ= Ġ{ Ġelement Ġ-> Ċĉĉ ĉ element . data Ċĉ ĉ }, Ċĉĉ ĉ matcher Ġ= Ġdata Matcher , Ċĉĉ ĉ always Re cycle Ġ= Ġalways Re cycle Rows Ċĉ ĉ ) Ċĉ ĉ edit Row ( previous ly Edited , Ġpreviously Focused ) Ċ ĉ } ĊĊ ĉ private Ġfun Ġcreate Row () Ġ= Ġdata Grid Row < E > Ġ{ Ċĉ ĉ ( row Builder Ġ?: Ġerror (" rows Ġnot Ġset ")). invoke ( this ) Ċĉ ĉ focused In Container . listen Ġ{ Ċĉĉ ĉ edit Row ( data , Ġactive Cell Index ) Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠIf Ġtrue , Ġthe Ġ[ data ] Ġlist Ġwill Ġautomatically Ġmutate Ġto Ġthe Ġnew Ġvalue Ġproduced Ġby Ġthe Ġrow Ġeditor . Ċĉ Ġ*/ Ċ ĉ var Ġauto Mutate Ġ= Ġtrue ĊĊ ĉ init Ġ{ Ċĉ ĉ addClass ( Panel Style . colors ) Ċĉ ĉ addClass ( DataGrid Style . data Grid ) ĊĊĉ ĉ key Pressed . listen Ġ{ Ċĉĉ ĉ when Ġ( it . keyCode ) Ġ{ Ċĉĉĉ ĉ Ascii . ESCAPE Ġ-> Ġedit Row ( null ) Ċĉĉ ĉ } Ċĉ ĉ } ĊĊĉ ĉ row Submitted . listen Ġ{ Ġe Ġ-> Ċĉĉ ĉ if Ġ( auto Mutate ) Ġ{ Ċĉĉĉ ĉ data Ġ= Ġdata . to Persistent List (). mutate Ġ{ Ċĉĉĉĉ ĉ it [ e . index ] Ġ= Ġe . new Data !! Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠSets Ġthe Ġcurrently Ġedited Ġrow . Ċĉ Ġ* ĠDis patches Ġa Ġ[ row Edited ] Ġsignal , Ġwhich Ġmay Ġbe Ġcancelled . Ċĉ Ġ* Ġ@ param Ġitem ĠThe Ġdata Ġitem Ġto Ġedit . Ċĉ Ġ* Ġ@ param Ġcell Index ĠThe Ġindex Ġof Ġthe Ġcell Ġwithin Ġthe Ġrow Ġto Ġgive Ġfocus . ĠIf Ġthere Ġare Ġno Ġtab b able Ġelements Ġwithin Ċĉ Ġ* Ġthat Ġcell , Ġthe Ġfirst Ġtab b able Ġelement Ġwithin Ġthe Ġrow Ġwill Ġbe Ġfocused . Ċĉ Ġ*/ Ċ ĉ fun Ġedit Row ( item : ĠE ?, Ġcell Index : ĠInt Ġ= Ġ 0 ) Ġ{ Ċĉ ĉ if Ġ(! editable Ġ|| Ġedited Row Ġ== Ġitem ) Ġreturn ĊĊĉ ĉ val Ġe Ġ= ĠRow Edit Event ( item ) Ċĉ ĉ row Edited . dispatch ( e ) Ċĉ ĉ if Ġ( e . default Prevent ed ) Ġreturn ĊĊĉ ĉ val Ġedited Row Old Index Ġ= Ġdisplay Rows . indexOf First Ġ{ Ġit . data Ġ=== Ġedited Row Ġ} Ċĉ ĉ if Ġ( edited Row Old Index Ġ!= Ġ- 1 ) Ġcontents . addElement ( edited Row Old Index , Ġdisplay Rows [ edited Row Old Index ]) Ċĉ ĉ contents . remove Element ( row Editor ) Ċĉ ĉ row Editor . data Ġ= Ġnull Ċĉ ĉ if Ġ( item Ġ== Ġnull ) Ġreturn ĊĊĉ ĉ // ĠSwap Ġthe Ġdisplay Ġrow Ġwith Ġthe Ġrow Ġeditor . Ċĉ ĉ val Ġedited RowIndex Ġ= Ġdisplay Rows . indexOf First Ġ{ Ġit . data Ġ=== Ġitem Ġ} Ċĉ ĉ if Ġ( edited RowIndex Ġ== Ġ- 1 ) Ġreturn Ċĉ ĉ row Editor . data Ġ= Ġitem Ċĉ ĉ val Ġedited Display Row Ġ= Ġdisplay Rows [ edited RowIndex ] Ċĉ ĉ contents . remove Element ( edited Display Row ) Ċĉ ĉ contents . addElement ( edited RowIndex , Ġrow Editor ) ĊĊĉ ĉ // ĠSet Ġfocus Ċĉ ĉ val Ġcell To Focus Ġ= Ġrow Editor . elements . get OrNull ( cell Index )?. dom ?. unsafe Cast < Parent Node >() Ċĉ ĉ var Ġfirst Input Ġ= Ġcell To Focus ?. get Tab b able Elements ()?. first OrNull () ĊĊĉ ĉ if Ġ( first Input Ġ== Ġnull ) Ġ{ Ċĉĉ ĉ // ĠThe Ġrequested Ġcell Ġisn 't Ġfocus able , Ġpick Ġeither Ġthe Ġfirst Ġor Ġlast Ġfocus able Ġelement . Ċĉĉ ĉ val Ġall Tab b able Ġ= Ġrow Editor . dom . get Tab b able Elements () Ċĉĉ ĉ first Input Ġ= Ċĉĉĉ ĉ if Ġ( cell Index Ġ<= Ġrow Editor . elements . size Ġ/ Ġ 2 ) Ġall Tab b able . first OrNull () Ġelse Ġall Tab b able . last OrNull () Ċĉ ĉ } ĊĊĉ ĉ first Input ?. focus () Ċĉ ĉ if Ġ( first Input ?. tagName . equals (" input ", Ġignore Case Ġ= Ġtrue )) Ċĉĉ ĉ first Input . unsafe Cast < HTML InputElement >(). select () Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠOpen s Ġthe Ġnext Ġrow Ġfor Ġediting . Ċĉ Ġ* ĠNote : ĠThis Ġdoes Ġnot Ġsubmit Ġthe Ġcurrent Ġrow . Ċĉ Ġ* Ġ@ see Ġsubmit Row Ċĉ Ġ*/ Ċ ĉ fun Ġedit Next Row () Ġ{ Ċĉ ĉ val Ġi Ġ= Ġdata View . indexOf ( edited Row ) Ċĉ ĉ if Ġ( i Ġ!= Ġ- 1 ) Ġedit Row ( data View . get OrNull ( i Ġ+ Ġ 1 )) Ċĉ ĉ else Ġedit Row ( null ) Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠOpen s Ġthe Ġprevious Ġrow Ġfor Ġediting . Ċĉ Ġ* ĠNote : ĠThis Ġdoes Ġnot Ġsubmit Ġthe Ġcurrent Ġrow . Ċĉ Ġ* Ġ@ see Ġsubmit Row Ċĉ Ġ*/ Ċ ĉ fun Ġedit Previous Row () Ġ{ Ċĉ ĉ val Ġi Ġ= Ġdata View . indexOf ( edited Row ) Ċĉ ĉ edit Row ( data View . get OrNull ( i Ġ- Ġ 1 )) Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠSubmit s Ġthe Ġcurrent Ġrow Ġeditor Ġform . Ċĉ Ġ* ĠThe Ġdefault Ġbehavior Ġafter Ġa Ġrow Ġhas Ġbeen Ġsubmitted Ġis Ġif Ġthe Ġform Ġis Ġvalid Ġand Ġ[ row Submitted ] Ġis Ġnot Ġdefault Ċĉ Ġ* Ġprevent ed , Ġthen Ġthe Ġnext Ġrow Ġwill Ġbe Ġopened . Ċĉ Ġ* Ġ@ return ĠReturns Ġtrue Ġif Ġthe Ġsubmission Ġwas Ġsuccessful . Ċĉ Ġ*/ Ċ ĉ fun Ġsubmit Row ( report Validity : ĠBoolean Ġ= Ġtrue ): ĠBoolean Ġ{ Ċĉ ĉ if Ġ( row Editor . data Ġ== Ġnull ) Ġreturn Ġfalse Ċĉ ĉ val Ġform Ġ= Ġrow Editor . form ĊĊĉ ĉ return Ġif Ġ( form . check Validity ()) Ġ{ Ċĉĉ ĉ val Ġprevious Data Ġ= Ġrow Editor . data !! Ċĉĉ ĉ val Ġsubmitted Event Ġ= ĠRow Submitted Event ( Ċĉĉĉ ĉ data . indexOf ( previous Data ), Ċĉĉĉ ĉ data View . indexOf ( previous Data ), Ċĉĉĉ ĉ previous Data , Ċĉĉĉ ĉ row Editor . data Builder . invoke ( row Editor . data !! ) Ċĉĉ ĉ ) Ċĉĉ ĉ if Ġ( submitted Event . old Data Ġ!= Ġsubmitted Event . new Data ) Ġ{ Ċĉĉĉ ĉ row Submitted . dispatch ( submitted Event ) Ċĉĉ ĉ } Ċĉĉ ĉ ! submitted Event . default Prevent ed Ċĉ ĉ } Ġelse Ġ{ Ċĉĉ ĉ if Ġ( report Validity ) Ċĉĉĉ ĉ form . report Validity () Ċĉĉ ĉ false Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠCloses Ġthe Ġeditor Ġwithout Ġsubmission Ġor Ġvalidation . Ċĉ Ġ*/ Ċ ĉ fun Ġclose Editor () Ġ= Ġedit Row ( null ) Ċ Ċ } ĊĊ Ċ object ĠData Grid Style Ġ{ ĊĊ ĉ val Ġdata Grid Ġby Ġcss Class () Ċ ĉ val Ġmain Container Style Ġby Ġcss Class () Ċ ĉ val Ġheader Row Style Ġby Ġcss Class () Ċ ĉ val Ġfooter Row Style Ġby Ġcss Class () Ċ ĉ val Ġheader CellStyle Ġby Ġcss Class () Ċ ĉ val Ġcontents Container Style Ġby Ġcss Class () Ċ ĉ val Ġrow Style Ġby Ġcss Class () Ċ ĉ val Ġrow Editor Style Ġby Ġcss Class () Ċ ĉ val Ġcell Style Ġby Ġcss Class () Ċ ĉ val Ġeditor CellStyle Ġby Ġcss Class () ĊĊ ĉ val Ġsorted Asc Ġby Ġcss Class () Ċ ĉ val Ġsorted Desc Ġby Ġcss Class () ĊĊ ĉ val Ġborder Thickness Ġby Ġcss Var () ĊĊ ĉ init Ġ{ ĊĊĉ ĉ add Style To Head ( Ċĉĉ ĉ """ Ċ ĉ $ data Grid Ġ{ ĉĊĉ ĉ display : Ġflex ; Ċĉ ĉ flex - direction : Ġcolumn ; Ċĉ ĉ box - sizing : Ġborder - box ; Ċĉ ĉ position : Ġrelative ; Ċĉ ĉ overflow : Ġauto ; Ċĉ ĉ scroll - padding - top : Ġ 4 em ; Ġ/* ĠTo Ġprevent Ġthe Ġsticky Ġheader Ġfrom Ġcover ing Ġup Ġthe Ġfirst Ġrow Ġwhen Ġtab bing Ġ*/ Ċĉ ĉ $ border Thickness : Ġ 1 px ; ĊĉĉĊĉ ĉ row - gap : Ġ${ border Thickness . v }; Ċĉ ĉ column - gap : Ġ${ border Thickness . v }; Ċĉ ĉ background - color : Ġ${ Css Props . border Color . v }; Ċĉ ĉ grid - auto - rows : Ġmin - content ; Ċ ĉ } ĊĉĊ ĉ $ cell Style Ġ{ Ċĉ ĉ padding : Ġcalc (${ Css Props . input Padding . v } Ġ+ Ġ${ Css Props . border Thickness . v }); Ċĉ ĉ display : Ġflex ; Ċĉ ĉ align - items : Ġcenter ; Ċ ĉ } ĊĉĊ ĉ $ main Container Style Ġ{ Ċĉ ĉ min - width : Ġfit - content ; Ċĉ ĉ min - height : Ġfit - content ; Ċĉ ĉ width : Ġinherit ; Ċĉ ĉ height : Ġinherit ; Ċĉ ĉ grid - template - columns : Ġinherit ; Ċĉ ĉ grid - template - rows : Ġinherit ; Ċĉ ĉ align - items : Ġinherit ; Ċĉ ĉ align - content : Ġinherit ; Ċĉ ĉ justify - items : Ġinherit ; ĉĊĉ ĉ justify - content : Ġinherit ; ĊĉĊĉ ĉ display : Ġgrid ; Ċĉ ĉ grid - auto - rows : Ġinherit ; Ċĉ ĉ row - gap : Ġinherit ; Ċĉ ĉ column - gap : Ġinherit ; Ċĉ ĉ background - color : Ġinherit ; Ċ ĉ } ĊĉĊ ĉ $ header Row Style Ġ{ Ċĉ ĉ display : Ġcontents ; Ċ ĉ } ĊĉĊ ĉ $ header Row Style Ġ> Ġdiv : first - child Ġ{ Ċĉ ĉ border - top - left - radius : Ġvar (-- br ); Ċ ĉ } ĊĉĊ ĉ $ header Row Style Ġ> Ġdiv Ġ{ Ċĉ ĉ -- br : Ġcalc (${ Css Props . border Radius . v } Ġ- Ġ${ Css Props . border Thickness . v }); Ċĉ ĉ border - radius : Ġ 0 ; Ċĉ ĉ border : Ġnone ; Ċĉ ĉ position : Ġ- webkit - sticky ; Ċĉ ĉ position : Ġsticky ; Ċĉ ĉ top : Ġ 0 ; Ċĉ ĉ font - weight : Ġb older ; Ċ ĉ } ĊĉĊ ĉ $ footer Row Style Ġ{ Ċĉ ĉ display : Ġcontents ; Ċ ĉ } ĊĉĊ ĉ $ footer Row Style Ġ> Ġdiv Ġ{ Ċĉ ĉ position : Ġ- webkit - sticky ; Ċĉ ĉ position : Ġsticky ; Ċĉ ĉ bottom : Ġ 0 ; Ċĉ ĉ color : Ġinherit ; Ċĉ ĉ background : Ġinherit ; Ċ ĉ } ĊĉĊ ĉ $ data Grid Ġ* : focus Ġ{ Ċĉ ĉ /* ĠTake Ġthe Ġdefault Ġfocus Ġtransition , Ġmake Ġit Ġsn app ier Ġand Ġinset Ġto Ġbe Ġbetter Ġfor Ġdata Ġgrid Ġcells . Ġ*/ Ċĉ ĉ box - shadow : Ġinset Ġ 0 Ġ 0 Ġ 0 Ġ${ Css Props . focus Thickness . v } Ġ${ Css Props . focus . v }; Ċĉ ĉ border - color : Ġ${ Css Props . focus . v }; Ċĉ ĉ transition : Ġbox - shadow Ġ 0 . 0 s Ġease - in - out ; Ċ ĉ } ĊĉĊ ĉ $ contents Container Style Ġ{ Ċĉ ĉ display : Ġcontents ; Ċĉ ĉ border - bottom - left - radius : Ġinherit ; Ċ ĉ } ĊĉĊ ĉ $ row Style Ġ{ Ċĉ ĉ display : Ġcontents ; Ċ ĉ } ĊĉĊ ĉ $ row Editor Style Ġ> Ġform Ġ{ Ċĉ ĉ display : Ġcontents ; Ċ ĉ } ĊĉĊ ĉ $ editor CellStyle Ġ{ Ċĉ ĉ padding : Ġ 0 ; Ċ ĉ } ĊĉĊ ĉ $ contents Container Style Ġ> Ġ$ row Style : nth - child ( 2 n + 0 ) Ġ$ cell Style Ġ{ Ċĉ ĉ background : Ġ${ Css Props . dataRow Even Background . v }; Ċ ĉ } ĊĉĊ ĉ $ contents Container Style Ġ> Ġ$ row Style : nth - child ( 2 n + 1 ) Ġ$ cell Style Ġ{ Ċĉ ĉ background : Ġ${ Css Props . dataRow Odd Background . v }; Ċ ĉ } ĊĉĊ ĉ $ header CellStyle Ġ{ Ċĉ ĉ user - select : Ġnone ; Ċĉ ĉ - moz - user - select : Ġnone ; Ċĉ ĉ - webkit - user - select : Ġnone ; Ċĉ ĉ - webkit - touch - callout : Ġnone ; Ċ ĉ } ĊĉĊ ĉ $ header CellStyle $ sorted Asc :: after , Ġ$ header CellStyle $ sorted Desc :: after Ġ{ Ċĉ ĉ content : Ġ"${ Icons . ARROW _ DOWN WARD . to Char ()} "; Ċĉ ĉ font - family : Ġ" Material ĠIcons "; Ċĉ ĉ display : Ġinline - block ; Ċĉ ĉ white - space : Ġnowrap ; Ċĉ ĉ - webkit - font - smoothing : Ġant iali ased ; Ċĉ ĉ transition : Ġtransform Ġ 0 . 3 s Ġease - in - out ; Ċ ĉ } ĊĉĊ ĉ $ header CellStyle $ sorted Desc :: after Ġ{ Ċĉ ĉ transform : Ġrotate ( 1 8 0 deg ); Ċ ĉ } Ċĉĉĉ ĉ """ Ċĉ ĉ ) Ċ ĉ } Ċ } Ċ Ċ inline Ġfun Ġ< E > ĠContext . data Grid ( init : ĠComponent Init < DataGrid < E >> Ġ= Ġ{} ): ĠData Grid < E > Ġ{ Ċ ĉ contract Ġ{ Ġcalls In Place ( init , ĠInvocation Kind . EX ACT LY _ ON CE ) Ġ} Ċ ĉ return ĠData Grid < E >( this ). apply ( init ) Ċ } Ċ Ċ inline Ġfun Ġ< E > ĠContext . data Grid ( data : ĠList < E >, Ġinit : ĠComponent Init < DataGrid < E >> Ġ= Ġ{} ): ĠData Grid < E > Ġ{ Ċ ĉ contract Ġ{ Ġcalls In Place ( init , ĠInvocation Kind . EX ACT LY _ ON CE ) Ġ} Ċ ĉ return ĠData Grid < E >( this ). apply Ġ{ Ċĉ ĉ this . data Ġ= Ġdata Ċĉ ĉ init () Ċ ĉ } Ċ } Ċ Ċ open Ġclass ĠData Grid Row < E >( owner : ĠContext ) Ġ: ĠDiv ( owner ) Ġ{ ĊĊ ĉ val Ġdata Changed Ġ= Ġsignal < ChangeEvent < E ? >>() ĊĊ ĉ init Ġ{ Ċĉ ĉ addClass ( DataGrid Style . row Style ) Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠSets Ġthe Ġrow 's Ġdata . Ċĉ Ġ*/ Ċ ĉ var Ġdata : ĠE ? Ġ= Ġnull Ċĉ ĉ set ( value ) Ġ{ Ċĉĉ ĉ val Ġold Ġ= Ġfield Ċĉĉ ĉ if Ġ( old Ġ== Ġvalue ) Ġreturn Ċĉĉ ĉ field Ġ= Ġvalue Ċĉĉ ĉ data Changed . dispatch ( ChangeEvent ( old , Ġvalue )) Ċĉ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠInv okes Ġthe Ġcallback Ġwith Ġthe Ġnew Ġdata Ġwhen Ġthis Ġrow 's Ġdata Ġhas Ġchanged . Ċĉ Ġ*/ Ċ ĉ fun Ġdata ( callback : Ġ( E ) Ġ-> ĠUnit ): ĠSignal Subscription Ġ= Ġdata Changed . listen Ġ{ Ċĉ ĉ if Ġ( it . new Data Ġ!= Ġnull ) Ċĉĉ ĉ callback ( it . new Data ) Ċ ĉ } Ċ } Ċ Ċ private Ġinline Ġfun Ġ< E > ĠContext . data Grid Row ( init : ĠComponent Init < DataGrid Row < E >> Ġ= Ġ{} ): ĠData Grid Row < E > Ġ{ Ċ ĉ contract Ġ{ Ġcalls In Place ( init , ĠInvocation Kind . EX ACT LY _ ON CE ) Ġ} Ċ ĉ return ĠData Grid Row < E >( this ). apply ( init ) Ċ } Ċ Ċ open Ġclass ĠData Grid Row Editor < E >( owner : ĠContext ) Ġ: ĠData Grid Row < E >( owner ), ĠClear able Ġ{ ĊĊ ĉ val Ġform Ġ= Ġadd Child ( form Ġ{ Ċĉ ĉ prevent Action () Ċĉ ĉ + hidden Submit () Ċ ĉ }) ĊĊ ĉ /** Ċĉ Ġ* ĠDis patched Ġwhen Ġthe Ġrow Ġeditor Ġform Ġhas Ġbeen Ġsubmitted . Ċĉ Ġ*/ Ċ ĉ val Ġsubmitted Ġ= Ġform . submitted ĊĊ ĉ init Ġ{ Ċĉ ĉ addClass ( DataGrid Style . row Editor Style ) Ċ ĉ } ĊĊ ĉ override Ġfun Ġon Element Added ( old Index : ĠInt , Ġnew Index : ĠInt , Ġelement : ĠWith Node ) Ġ{ Ċĉ ĉ form . addElement ( new Index , Ġelement ) Ċ ĉ } ĊĊ ĉ override Ġfun Ġon Element Removed ( index : ĠInt , Ġelement : ĠWith Node ) Ġ{ Ċĉ ĉ form . remove Element ( element ) Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠWhen Ġthe Ġrow Ġis Ġsubmitted , Ġthis Ġwill Ġconstruct Ġthe Ġnew Ġdata Ġelement . Ċĉ Ġ*/ Ċ ĉ var Ġdata Builder : Ġ(( E ) Ġ-> ĠE ) Ġby ĠDeleg ates . notNull () ĊĊ ĉ override Ġfun Ġclear () Ġ{ Ċĉ ĉ data Ġ= Ġnull Ċĉ ĉ clear Elements ( dispose Ġ= Ġtrue ) Ċ ĉ } Ċ } Ċ Ċ private Ġinline Ġfun Ġ< E > ĠContext . data Grid Row Editor ( init : ĠComponent Init < DataGrid Row Editor < E >> Ġ= Ġ{} ): ĠData Grid Row Editor < E > Ġ{ Ċ ĉ contract Ġ{ Ġcalls In Place ( init , ĠInvocation Kind . EX ACT LY _ ON CE ) Ġ} Ċ ĉ return ĠData Grid Row Editor < E >( this ). apply ( init ) Ċ } Ċ Ċ class ĠHeader Cell ( owner : ĠContext ) Ġ: ĠButton ( owner ) Ġ{ ĊĊ ĉ private Ġvar Ġclick Listener : ĠSignal Subscription ? Ġ= Ġnull ĊĊ ĉ init Ġ{ Ċĉ ĉ addClass ( DataGrid Style . header CellStyle ) Ċ ĉ } ĊĊ ĉ fun Ġ< E , ĠT Ġ: ĠComparable < T >> ĠData Grid < E >. bind Sorting By ( column Sort : Ġ( row : ĠE ) Ġ-> ĠT ) Ġ{ Ċĉ ĉ click Listener ?. dispose () Ċĉ ĉ click Listener Ġ= Ġthis @ Header Cell . clicked . listen Ġ{ Ċĉĉ ĉ if Ġ(! it . is Handled ) Ġ{ Ċĉĉĉ ĉ it . handle () Ċĉĉĉ ĉ if Ġ( it . ctrl Key ) Ġ{ Ċĉĉĉĉ ĉ sort Ġ= Ġempty List () Ċĉĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉĉ ĉ val Ġnew Direction Ġ= Ġif Ġ( sort Display Ġ== ĠColumn Sort Direction . ASC ENDING ) ĠColumn Sort Direction . DESC ENDING Ġelse ĠColumn Sort Direction . ASC ENDING Ċĉĉĉĉ ĉ this . sort ( Column Sort ( new Direction , Ġthis @ Header Cell , Ġcolumn Sort )) Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ } Ċĉ ĉ this @ Header Cell . long Tou ched . listen Ġ{ Ċĉĉ ĉ this . sort () Ċĉ ĉ } ĊĊĉ ĉ this @ Header Cell . long Pressed . listen Ġ{ Ċĉĉ ĉ this . sort () Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠAdjust s Ġthe Ġcss Ġclass Ġlist Ġto Ġrepresent Ġthis Ġcolumn 's Ġsorting . Ċĉ Ġ* ĠThis Ġwill Ġbe Ġmodified Ġby Ġthe ĠData Grid . Ċĉ Ġ*/ Ċ ĉ var Ġsort Display Ġ= ĠColumn Sort Direction . NONE Ċĉ ĉ set ( value ) Ġ{ Ċĉĉ ĉ if Ġ( field Ġ== Ġvalue ) Ġreturn Ċĉĉ ĉ field Ġ= Ġvalue Ċĉĉ ĉ removeClass ( DataGrid Style . sorted Asc ) Ċĉĉ ĉ removeClass ( DataGrid Style . sorted Desc ) Ċĉĉ ĉ if Ġ( value Ġ== ĠColumn Sort Direction . ASC ENDING ) Ġ{ Ċĉĉĉ ĉ addClass ( DataGrid Style . sorted Asc ) Ċĉĉ ĉ } Ġelse Ġif Ġ( value Ġ== ĠColumn Sort Direction . DESC ENDING ) Ġ{ Ċĉĉĉ ĉ addClass ( DataGrid Style . sorted Desc ) Ċĉĉ ĉ } Ċĉ ĉ } Ċ } Ċ Ċ data Ġclass ĠColumn Sort < E >( ĊĊ ĉ /** Ċĉ Ġ* ĠThe Ġdirection Ġof Ġthe Ġsort . Ċĉ Ġ*/ Ċ ĉ val Ġdirection : ĠColumn Sort Direction Ġ= ĠColumn Sort Direction . ASC ENDING , ĊĊ ĉ /** Ċĉ Ġ* ĠIf Ġset , Ġthe Ġheader Ġcell 's Ġ[ Header Cell . sort Display ] Ġwill Ġbe Ġset . Ċĉ Ġ*/ Ċ ĉ val Ġheader Cell : ĠHeader Cell ? Ġ= Ġnull , ĊĊ ĉ /** Ċĉ Ġ* ĠSelect s Ġthe Ġcomp arable Ġvalue Ġon Ġwhich Ġto Ġsort . Ċĉ Ġ*/ Ċ ĉ val Ġselector : Ġ( E ) Ġ-> ĠComparable < *> ? Ċ Ċ ) ĊĊ Ċ enum Ġclass ĠColumn Sort Direction Ġ{ Ċ ĉ NONE , Ċ ĉ ASC ENDING , Ċ ĉ DESC ENDING Ċ } Ċ Ċ inline Ġfun ĠContext . header Cell ( label : ĠString Ġ= Ġ"", Ġinit : ĠComponent Init < Header Cell > Ġ= Ġ{} ): ĠHeader Cell Ġ{ Ċ ĉ contract Ġ{ Ġcalls In Place ( init , ĠInvocation Kind . EX ACT LY _ ON CE ) Ġ} Ċ ĉ return ĠHeader Cell ( this ). apply Ġ{ Ċĉ ĉ this . label Ġ= Ġlabel Ċĉ ĉ init () Ċ ĉ } Ċ } Ċ Ċ inline Ġfun ĠContext . cell ( label : ĠString Ġ= Ġ"", Ġinit : ĠComponent Init < TextField > Ġ= Ġ{} ): ĠTextField Ġ{ Ċ ĉ contract Ġ{ Ġcalls In Place ( init , ĠInvocation Kind . EX ACT LY _ ON CE ) Ġ} Ċ ĉ return Ġtext Ġ{ Ċĉ ĉ tab Index Ġ= Ġ 0 Ċĉ ĉ addClass ( DataGrid Style . cell Style ) Ċĉ ĉ this . label Ġ= Ġlabel Ċĉ ĉ init () Ċ ĉ } Ċ } Ċ Ċ inline Ġfun ĠContext . editor Cell ( init : ĠComponent Init < Ui Component Impl < HTML Div Element >> Ġ= Ġ{} ): ĠUi Component Impl < HTML Div Element > Ġ{ Ċ ĉ contract Ġ{ Ġcalls In Place ( init , ĠInvocation Kind . EX ACT LY _ ON CE ) Ġ} Ċ ĉ return Ġdiv Ġ{ Ċĉ ĉ addClass ( DataGrid Style . cell Style ) Ċĉ ĉ addClass ( DataGrid Style . editor CellStyle ) ĊĊĉ ĉ init () Ċ ĉ } Ċ }