Disabled all broken functionality.

Disabled all broken functionality.

:Class index2 : MiPageSample

    :SECTION GLOBALS ⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝

    :Field TYPES←'Simple' 'Advanced'⍝ Types of samples (if not App)
    :Field GROUPS      ⍝ Names of groups of elements
    :Field REFS        ⍝ ... their refs
    :Field APPS        ⍝ List of all apps
    :Field SAMPLES     ⍝ List of all samples (well, groups and controls really)
    :Field INFOLONG    ⍝ Long desc of each control
    :Field INFOSHORT   ⍝ Short (1-3 words) desc of each control
    :Field NAMESLONG   ⍝ Elements that have long info
    :Field NAMESSHORT  ⍝ Elements that have short info
    :Field SEARCH←''   ⍝ Last-search cache
    :Field CONTROLS←'' ⍝ All control names
    :Field APPDESCS    ⍝ Sample Apps' Description::
    :Field APPCTRLS    ⍝ Sample Apps' Control:: (i.e. the title)
    :Field CORE        ⍝ Core subset of controls
    :Field STR←''      ⍝ String to search for
    :Field ALLFILES    ⍝ List of pathnames for all sample files
    :Field SAMPLE←1    ⍝ The current view is a sample (i.e. has source-code and related samples)

    :ENDSECTION

    :SECTION UTILITIES ⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝

    Q←'"'∘,,∘'"'  ⍝ Surround with quotes, a.k.a. APL dragon

    D←{(×≢⍵)/' – ',⍵} ⍝ Prepend a dash if non-empty

    P←{1⌽(×≢#.HTMLInput.dtlb ⍵)/') (',⍵} ⍝ Surround with parens if non-empty

    Words←{(1↓¨(' '∘=⊂⊢)' ',⍵)~⊂''} ⍝ Split at spaces

    SpaceToDir←{'Examples/',1↓⍵} ⍝ Convert Space name to Folder name

    Frame←{'.iframed' ('src=',Q⍵,'?NoWrapper=1') New _.iframe}

    NewWinA←{'target="_blank"'('href=',Q⊃⌽⍵) 'title="Click to pop out"'New _.a (⊃⍵)} ⍝ New link that opens in a new window/tab

    NewDiv←{⍵ New _.div} ⍝ Make a div

    Horz←{⍺←⊢ ⋄ r⊣(r←⍺ New _.StackPanel ⍵).Horizontal←1} ⍝ Horizontal StackPanel

    Type←{P(1⍳⍨∨/¨TYPES⍷¨⊂⍺)⊃(TYPES,¨⊂' sample for ',⍵),⊂'Sample app'} ⍝ Simple/Advanced/App?

    Dread←{0::,⊂'[file read failed]' ⋄ #.UnicodeFile.ReadNestedText #.Boot.AppRoot,⍵,'.dyalog'} ⍝ Read dyalog file

    Dlist←{0::⍬ ⋄ (Slist #.Boot.AppRoot,⍵,' -raw')[;2]} ⍝ List dyalog files

    Slist←{l←⎕SE.SALT.List ⍵ ⋄ l[;2]←('\\'⎕R'/')(l[;2]) ⋄ l} ⍝ SALT.List with /'s

  ⍝  NodeID←{⍺←⊢ ⋄ ('#node',⊃⍵)∘,¨⍕¨⍺+⍳⍴⊃⌽⍵} ⍝ Generate node ids (⍵='L' items) optional (⍺=offset)

    Split←{{⍵↑⍨+/∨\' '≠⌽⍵}¨('_'⎕R' ')⍵((⍳↑⊣){⍺⍵}(⍳↓⊣))'_'} ⍝ Split at first _ and fix _s

    In←{∨/¨⊃⍷¨/{⎕SE.Dyalog.Utils.lcase¨eis ⍵}¨⍺ ⍵} ⍝ Case-insensitive find

    Names←{1↓¨⍵↑¨⍨¯1+⍵⍳¨':'} ⍝ Extract section names from set of several 'name:: description'

    AddShortInfo←{⍵,¨P¨(4+⍴¨⍵)↓¨(INFOSHORT,⊂'')[NAMESSHORT⍳⍵]} ⍝ ⍵ (ShortDesc)

    ShortInfo←{(4+⍴⍵)↓⊃(INFOSHORT,⊂'')[NAMESSHORT⍳⊂⍵]}

    AddLongInfo←{(New¨_.strong,¨⍵),¨D¨(4+⍴¨⍵)↓¨(INFOLONG,⊂'')[NAMESLONG⍳⍵]} ⍝ ⍵ - LongDesc

    ScoreIn←{(100⊥⌽∨/¨TYPES⍷¨⊂⍵)×(⊂⍺)(∊×⍳⍨)Words'Control'Section Dread ⍵} ⍝ ⍺'s relevance in ⍵ (0=none 1=high 2=lower...)

    Tail←{⍵ ⍺⍺⍨1-(⌽⍵)⍳'/'} ⍝ ↑Tail or ↓Tail

    End←{⍺⍺{⍵↑⍨¯1+⍵⍳'_'}⍺⍺ ⍵} ⍝ ⊢End: until first .   ⌽End: from last .

    NodeToCtrl←{'_',(⊢End 1↓⍵),'.',⌽End ⍵}

    CtrlToNode←{'#',('\.' ⎕R '_')⍵}

    Clean←'[_\-\.]'⎕R' '

    DelEmpty←{((0,⍨2</⍵[;1])∨'/'≠⊃¨⌽¨⍵[;3])⌿⍵}

      DirTree←{
          parent←1(↑Tail ⍵)('/',⍵,'/')
          list←Slist #.Boot.AppRoot,⍵,' -rec -raw'
          0∊⍴list:0 3⍴0 '' ''
          nodir←~list[;1]∊⍨⊂'<DIR>'
          prefix←'/',(↓Tail ⍵),nodir/(↑Tail ⍵),'/' ⍝ Quirk in SALT.List includes path only if has subfolders
          files←prefix∘,¨list[;2]
          levels←2+(+/¨'/'=files)-+/'/'=3⊃parent
          ((list[;1]≡¨⊂'<DIR>')/files),←'/'
          DelEmpty⍣≡parent⍪⍉↑levels(↑Tail¨list[;2])files
      }

      Section←{ ⍝ extract section ⍺:: from code ⍵
          regex←'^\s*⍝\s*',⍺,':(:.*?)$((\R^⍝(?!\s*\w+::).*?$)*)'
          opts←('Mode' 'M')('DotAll' 1)
          res←(regex ⎕S'\1\2'⍠opts)⍵
          (1↓⊃res)~'⍝'
      }

    :ENDSECTION

    :SECTION MAIN ⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝

    ∇ Compose;left;mid;right;sp;list
      :Access public

     ⍝ Initialize globals
      CURRFILES←⊂'/About-MiServer'
      CURRCTRL←''
      SAMPLES←0 3⍴⍬
      GROUPS←'Dyalog Controls' 'SyncFusion' 'JQueryUI' 'Base HTML'
      REFS←_DC _SF _JQ _html
      INFOSHORT←'⍝',¨Dread'Examples/Data/infoShort'
      INFOLONG←'⍝',¨Dread'Examples/Data/infoLong'
      NAMESSHORT←Names INFOSHORT
      NAMESLONG←Names INFOLONG
      list←⊃⍪/{Slist #.Boot.AppRoot,'Examples/',⍵,' -rec -raw -full'}¨'DC' 'SF' 'JQ' 'html'
      ALLFILES←list[;2]/⍨list[;1]≢¨⊂'<DIR>'
      TREE←⎕SE.SALT.Load #.Boot.AppRoot,'Examples/Data/tree -noname'
      CORE←⎕SE.SALT.Load #.Boot.AppRoot,'Examples/Data/core -noname'

      Add _.StyleSheet'/Styles/homepage.css'

      (left mid)←NewDiv¨'#leftBar' '#midBar' ⍝ Create panes
      Add'mainSP'Horz left mid
      PopulateLeft left
      PopulateMid mid
    ∇

    ∇ PopulateLeft thediv;class;depths;group;items;ref;samples;vp;search;menu;i;fs;ac;text;treeall;treecore;names;tree;dirs;levels;core;enames

      :If 0
      ⍝ SEARCH FIELD ⍝⍝⍝
          search←New _.EditField'searchfield'⍝).On'change' 'OnSearch'('str' 'val')
          (search,←'#searchbutton' '.menu'New _.button'Search').On'click' 'OnSearch'('str' '#searchfield' 'val')
          thediv.Add Horz search
          thediv.Add _.hr
      :EndIf

      ⍝ GETTING STARTED ⍝⍝⍝
      '.cat'thediv.Add _.p'Getting Started'
      tree←0 3⍴0 '' ''
      tree⍪←1 'Start here',CURRFILES
      tree⍪←DirTree'Documentation'
      tree⍪←DirTree'Examples/Techniques'
      tree⍪←DirTree'Examples/Applications'
      tree[;2]←Clean¨tree[;2]
      tree←'#treeG'thediv.Add _.ejTreeView tree
      tree.On'nodeSelect' 'OnGS'('node' 'eval' 'argument.id')
      thediv.Add _.hr

      ⍝ CONTROLS ⍝⍝⍝
      '.cat'thediv.Add _.p'Controls'
      tree←0 3⍴0 '' ''
      names←TREE
      dirs←'_'=(⊃⌽)¨names
      ⍝ All
      tree⍪←1 'All' '_'
      levels←1+dirs-⍨+/¨'_'=names
      enames←⌽End¨1↓¨names↓¨⍨-dirs
      tree⍪←⍉↑levels enames names
      ⍝ Core
      core←(2=levels)∨(enames∊CORE) ⍝∧(~dirs) not necessary because no category name appears in core list
      enames/⍨←core
      names/⍨←core
      levels/⍨←core
      levels⌊←3
      core←⍉↑levels enames(names,¨'(')
      tree⍪⍨←⊃⍪/{⍵[1,1+⍋↑1↓⍵[;2];]}¨(2=core[;1])⊂[1]core ⍝ Sort classes
      tree⍪⍨←1 'Core' '_(' ⍝ ( is core suffix
      tree[;2]←Clean¨tree[;2]
      ⍝ Add the whole tree
      tree←'#treeA'thediv.Add _.ejTreeView tree
      tree.On'nodeSelect' 'OnCA'('node' 'eval' 'argument.id')
    ∇

    ∇ PopulateMid mid;url;code;frame;title;navbuts;t;sr;desc

     ⍝ Read framed pages
      url←⊃CURRFILES
      code←Dread url

     ⍝ Create and fill placeholders for title and header
      title←Clean'Control'Section code

     ⍝ _html.code
      '#title'Add _.title('MS3: ',title) ⍝ after the : will be updated later on
      '#SampleTitle'mid.Add _.h2 title

      desc←'#CtlDescs' 'style="display:none"'mid.Add _.div ⍝ All descriptions will go here

     ⍝ Control: Code fragment [View documentation]
      '#ControlDesc'desc.Add _.span
      ('#DocLink'desc.Add _.span).Add'target="_blank'New _.A'View documentation'
      desc.Add _.br

     ⍝ Sample: Embed a code fragment [Pop out]
      '#SampleDesc'desc.Add _.span('Description'Section code)
      ('#PopLink'desc.Add _.span).Add NewWinA'Pop out'url
      desc.Add _.br

     ⍝ [ ] Show related samples
      t←'onchange="$("#rel").toggle()"'desc.Add _.Input'checkbox' '' 'Show related samples' 'right'
      t.style←'margin-left: 0px;'
      '#rel' 'style="display: none;"'desc.Add _.div
      desc.Add _.hr

     ⍝ Create and fill placeholder for embedded page and its source code
      (mid.Add NewDiv'#SampleFrame').Add Frame url
      mid.Add _.hr
      t←'onchange' '$("#SampleSource").toggle()'mid.Add _.Input'checkbox' '' 'Show source code' 'right'
      t.style←'margin-left: 0px;'
      '#SampleSource' '.samplesource' 'style="display: none;"'mid.Add _.div('small;border:none'#.HTMLInput.APLToHTMLColour Dread⊃CURRFILES)

    ∇

    :ENDSECTION

    :SECTION CALLBACKS ⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝

    ∇ r←OnGS;node;list;nodir;prefix;files;out;file;name;item;title;desc;toggle;fromframe
      :Access Public

     ⍝ Callback for Getting Started
      node←(1+'tree'≡4↑_what)⊃_what(Get'node') ⍝ get id of node if tree or id of what if not
      fromframe←'_'=⊃⌽node
      node~←'_' ⍝ _ is frame suffix
      :If '/'=⊃⌽node ⍝ Folder (i.e. Category)
          r←''
          :Return
          CURRCTRL←''
          SAMPLE←0
          node←1↓¯1↓node ⍝ Strip outer slashes
          list←Slist #.Boot.AppRoot,node,' -rec -raw'
          nodir←~list[;1]∊⍨⊂'<DIR>'
          prefix←(↓Tail node),nodir/(Clean↑Tail node),'/' ⍝ Quirk in SALT.List includes path only if has subfolders
          files←prefix∘,¨list[;2]
          files/⍨←list[;1]≢¨⊂'<DIR>'
          CURRFILES←files
          out←NewDiv'.framed'
          :For file :In files
              item←('#/',file,'_')'.listitem' 'title="Click here to open"'out.Add _.p
              item.Add _.strong(Clean↑Tail file)
              item.Add' ',#.HTMLInput.dtlb'Description'Section Dread file
          :EndFor
          out.Add _.Handler'.listitem' 'click' 'OnGS'
          title←Clean node
          desc←'Click on a button below to select a sample.'
          r←title title desc out''
          toggle←';scroll(0,0);$("#CtlDescs").hide()'
      :Else ⍝ File (i.e. Page)
          SAMPLE←1
          toggle←(1+fromframe)⊃'$("#CtlDescs").hide();' '$("#CtlDescs").show();'
          r←Update node
      :EndIf

      r←(Execute toggle),GenJS r
    ∇

    ∇ r←OnCA;node;control;files;list;file;scores;code;desc;score;controls;out;item;title;coreonly;toggle
      :Access Public
     ⍝ Callback for Core/All Controls
      node←(1+'tree'≡4↑_what)⊃_what(Get'node') ⍝ get id of node if tree or id of what if not
      COREONLY←coreonly←'('∊node
      node↓⍨←-coreonly ⍝ drop ( is core suffix
      :If '_'=⊃⌽node ⍝ Category
          r←''
          :Return
          CURRCTRL←''
          SAMPLE←0
          title←('All '/⍨coreonly<1=⍴node),(coreonly/'Core '),(Clean node),' controls'
          r←title title'' '' ''
          toggle←'$("#CtlDescs").hide();'
      :Else ⍝ Control
          SAMPLE←1
          CURRCTRL←node
          control←NodeToCtrl node
          scores←⍬
          :For file :In ALLFILES
              controls←Words'Control'Section Dread'Examples/',file
              score←102-2×(50↑controls)⍳⊂control ⍝ 100=most relevant, 0=not relevant at all
              score-←∨/'Advanced'⍷file           ⍝ subtract 1 if advanced example
              scores,←0⌈score
          :EndFor
          CURRFILES←'/Examples/'∘,¨(ALLFILES/⍨×scores)[⍒scores/⍨×scores] ⍝ sort descending by score
          :If 0=⍴CURRFILES
              r←control control'' '' ''
              toggle←'$("#CtlDescs").hide();'
          :Else
              r←control Update⊃CURRFILES
              toggle←'$("#CtlDescs").show();'
          :EndIf

      :EndIf
      r←(GenJS r),Execute'scroll(0,0);',toggle
    ∇

    ∇ r←OnList;out;file;item;title;node;desc
      :Access Public
     ⍝ Called when user wants the entire list of relevant samples for the current control
      node←¯1↓_what ⍝ Remove desc _ suffix
      out←NewDiv'.framed'
      :If 0=⍴CURRFILES
          '.noitems'out.Add _.p,⊂'[no samples for ',(¯1↓node),' controls]'
              ⍝(2⊃r)←'_',class,'.',AddShortInfo⊂control
              ⍝(3⊃r)←(4↓⊃AddLongInfo,⊂control),' ',('0'=⊃2⊃r)/3⊃r
          r←control(control,' Short Info')'Long info'out''
      :Else
          :For file :In CURRFILES
              item←('#',file,'_')'.listitem' 'title="Click here to open"'out.Add _.p
              item.Add _.strong(↑Tail file)
              item.Add' ',#.HTMLInput.dtlb'Description'Section Dread file
          :EndFor
          out.Add _.Handler'.listitem' 'click' 'OnGS'
          title←NodeToCtrl node
          desc←'Click on a button below to select a sample.'
          r←title title desc out''
      :EndIf
      r←GenJS r
    ∇

    ∇ r←OnSample
      :Access Public
      r←GenJS Update CURRFILES⊃⍨⍎5↓_what ⍝ id="nodeS23"
    ∇

    ∇ r←OnSearch;str;terms;out;i;dir;files;file;url;code;ctrlsec;desc;item;title
      :Access Public

      str←(1+STR≡'')⊃STR(Get'str') ⍝ get search string

      :If ×≢str ⍝ Continue only if there is a search string
      ⍝⍝⍝ Controls
          terms←INFOSHORT/⍨str In INFOSHORT
          terms,←terms~⍨INFOLONG/⍨str In INFOLONG
          terms←'.',¨∪Names terms
      ⍝⍝⍝ Samples
          out←NewDiv'.framed'
          CURRFILES←''
          i←0
          :For dir :In 'Applications' 'html' 'HTMLplus' 'DC' 'JQ' 'SF'
              files←Dlist'Examples/',dir
              :For file :In files~⊂'index'
                  url←'Examples/',dir,'/',file
                  code←Dread url
                  ctrlsec←'Control'Section code
                  desc←⊂'Description'Section code
                  :If ∨/str In desc
                  :OrIf ∨/∊(terms,⊂str)In¨⊂ctrlsec ⍝ always case sensitive
                      i+←1
                      CURRFILES,←⊂url
                      desc←∊desc,file Type⊃Words ctrlsec
                      item←('#nodeS',⍕i)'.listitem'out.Add _.p desc
                      item.On'click' 'OnSample'
                  :EndIf
              :EndFor
          :EndFor
          :If ~×i
              '.noitems'out.Add _.p,⊂'[no results for ',str,']'
          :EndIf
          title←(⍕≢CURRFILES),' sample pages for ',Q str
          desc←'Click on a button below to select a sample.'
          ⍝r←(Q str)title desc out''
          r←'#SampleFrame'Replace out
          r,←'#SampleTitle'Replace(Q str)
          r,←'#title'Replace(Q str)
          :Return
          SEARCH←GenJS⍣(STR≡'')⊢r ⍝ Do not finish up if called by OnTree
          STR←'' ⍝ Reset
      :EndIf
      r←SEARCH
    ∇

    ∇ (page title desc url code)←{spacectrl}Update url;ctrlsec;control;space
     ⍝ Create new placeholder values
      code←Dread url
      :If ×⎕NC'spacectrl'
          page←spacectrl
          title←('All '/⍨2≥⍴page),('Core '/⍨'('=⊃⌽page),⌽End page
      :Else
          page←Clean'Control'Section code
          title←page
      :EndIf
      desc←#.HTMLInput.dtlb'Description'Section code
    ∇

    ∇ r←GenJS(page title desc url code);cd;sd;file;scores;controls;score;out;item;control;coreonly
     ⍝ Generate JavaScript for filling placeholders
      r←'#title'Replace'MS3: ',page
      control←NodeToCtrl CURRCTRL

      :If 'treeG'≡_what
          r,←'#SampleTitle'Replace title
      :Else
          r,←(×≢title)/'#SampleTitle'Replace control
      :EndIf
      (cd←New _.span).Add¨(_.strong'Control: ')(_.em,⊂ShortInfo⌽End CURRCTRL)
      r,←'#ControlDesc'Replace cd
      (sd←New _.span).Add¨(_.strong'Sample: ')(_.em desc)
      r,←'#SampleDesc'Replace sd

      :If 0
          :If ''≡desc
              coreonly←COREONLY
              control←NodeToCtrl¨TREE/⍨∨/¨(⊂node)⍷¨TREE
              control←(CORE∊⍨{⍵↓⍨⌽⍵⍳'.'}¨control)/⍣coreonly⊢control
              scores←⍬
              :For file :In files←ALLFILES[⍋↑ALLFILES]
                  controls←Words'Control'Section Dread'Examples/',file
                  score←2×∨/control∊controls         ⍝ 2=relevant Simple, 0=not relevant
                  score-←∨/'Advanced'⍷file           ⍝ 1=relevant Advanced
                  scores,←0⌈score
              :EndFor
              CURRFILES←'/Examples/'∘,¨(files/⍨×scores)[⍒scores/⍨×scores] ⍝ put Simple before Advanced
              out←NewDiv'.framed'
              :If 0=⍴CURRFILES
                  '.noitems'out.Add _.p,⊂'[no samples for ',(¯1↓node),' controls]'
              ⍝(2⊃r)←'_',class,'.',AddShortInfo⊂control
              ⍝(3⊃r)←(4↓⊃AddLongInfo,⊂control),' ',('0'=⊃2⊃r)/3⊃r
                  r←control(control,' Short Info')'Long info'out''
              :Else
                  :For file :In CURRFILES
                      item←('#',file,'_')'.listitem' 'title="Click here to open"'out.Add _.p
                      item.Add _.strong(↑Tail file)
                      item.Add' ',#.HTMLInput.dtlb'Description'Section Dread file
                  :EndFor
                  out.Add _.Handler'.listitem' 'click' 'OnGS'
                  title←('All '/⍨coreonly<1=⍴node),(coreonly/'Core '),(Clean node),' controls'
              ⍝desc←'Click on a button below to select a sample.'

              :EndIf
          :Else

          :EndIf
      :EndIf

      scores←⍬
      :For file :In ALLFILES
          controls←Words'Control'Section Dread'Examples/',file
          score←102-2×(50↑controls)⍳⊂control ⍝ 100=most relevant, 0=not relevant at all
          score-←∨/'Advanced'⍷file           ⍝ subtract 1 if advanced example
          scores,←0⌈score
      :EndFor
      CURRFILES←'/Examples/'∘,¨(ALLFILES/⍨×scores)[⍒scores/⍨×scores] ⍝ sort descending by score
      out←NewDiv'.framed'
      :If 1<⍴CURRFILES
          :For file :In 1↓CURRFILES
              item←('#',file,'_')'.listitem' 'title="Click here to open"'out.Add _.p
              item.Add _.strong(↑Tail file)
              item.Add' ',#.HTMLInput.dtlb'Description'Section Dread file
          :EndFor
          out.Add _.Handler'.listitem' 'click' 'OnGS'
      :EndIf

      r,←'#rel'Replace out

      r,←(×≢url)/'#SampleFrame'Replace Frame url

      r,←'#PopLink'Replace NewWinA'Pop out'url
      r,←'#SampleSource'Replace'small;border:none'#.HTMLInput.APLToHTMLColour code
      url←∊'/Documentation/DyalogAPIs/WidgetDoc?namespace=_' '&widget=',¨(⊢End{⍺ ⍵}⌽End)1↓CURRCTRL
      r,←'#DocLink'Replace NewWinA'View documentation'url
      :If 0⍝=⍴CURRFILES
          r,←Execute'$("#CtlDescs").show();'
          r,←'#SampleDesc'Replace'.noitems'New _.p,⊂'[no samples using ',control,']'
          r,←'#PopLink'Replace''
          r,←'#SampleSource'Replace''
          r,←'#SampleFrame'Replace''
      :EndIf
    ∇

    ∇ node←GetNode
      node←4↓(1+'tree'≡4↑_what)⊃_what(Get'node')
    ∇
    :ENDSECTION

    :SECTION OBSOLETE ⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝
      JSsafe←{ ⍝ Make text JS safe by escaping problematic chars
          fr←'''' '"' '\\' '\n' '\r',⎕UCS 9 8 12               ⍝ ' " \ NL CR TB BS FF
          to←'\\''' '\\"' '\\\\' '\\n' '\\r' '\\t' '\\b' '\\f' ⍝ problematic in regex too :-)
          Q(fr ⎕R to⍠'Mode' 'D')⍵ ⍝ Replace problematic chars and sourround with quotes
      }

    ∇ r←OnNavBut;file;item;out;title;desc
      :Access Public
      r←''
      :Select 2↓_what
      :Case 'related'
          SAMPLE←0
          out←NewDiv'.framed'
          :For file :In CURRFILES
              item←('#',file,'_')'.listitem' 'title="Click here to open"'out.Add _.p
              item.Add _.strong(Clean↑Tail file)
              item.Add' ',#.HTMLInput.dtlb'Description'Section Dread file
          :EndFor
          out.Add _.Handler'.listitem' 'click' 'OnGS'
          title←''⍝NodeToCtrl node
          desc←'Click on a button below to select a sample.'
          r←GenJS title title desc out''
      :Case 'source'
          :If SAMPLE
              r←'#SampleSource'Replace'small;border:none'#.HTMLInput.APLToHTMLColour Dread⊃CURRFILES
              r,←Execute'location.replace("#source");'
          :EndIf
      :Case 'info'
          :If SAMPLE∧''≢CURRCTRL
              r←Execute'window.open',P Q∊∊'/Documentation/DyalogAPIs/WidgetDoc?namespace=_' '&widget=',¨(⊢End{⍺ ⍵}⌽End)CURRCTRL
          :EndIf
      :Case 'out'
          r←SAMPLE/Execute'window.open',P Q⊃CURRFILES
      :Case 'urce' ⍝ n.b. 2↓
          r←Execute'scroll(0,0);'
      :EndSelect
    ∇

    ∇ js←APLtoJS vtv;act;data
      :Access public shared
     ⍝ Convert vectors of pseudo JS (generated by Replace, Execute, et al.) to proper JS

      js←''
      :For act data :In eis vtv
          data←JSsafe⊃⌽eis data ⍝ the last or only one
          :Select ⊃eis act      ⍝ the first or only one
          :Case 'assign'
              js,←(⊃⌽act),' = ',data,';' ⍝ variable = "data"
          :Case 'execute'
              js,←'eval(',data,');' ⍝ eval("data")
          :Case 'replace'
              js,←'$("',(⊃⌽act),'").html(',data,');' ⍝ $("#myid").html("data")
          :Else
              js,←'$("',(⊃⌽act),'").',(⊃act),'(',data,');' ⍝ $("#myid").append("data")
          :EndSelect
      :EndFor
    ∇

    ∇ r←OnTree;node;descs;out;items;spacectrl;control;spacedir;files;file;i;url;code;ctrlsec;desc;item;title;currctrls;core;names;class;group;cat;score
      :Access Public
      node←GetNode
      :If '0'∊node ⍝ Core or All
          core←'_'=2⊃node
          currctrls←(CORE∘∩⍣core)⊃,/CONTROLS ⍝ Filter if core-only
          out←NewDiv'.framed'
          descs←AddLongInfo currctrls
          items←(currctrls,⍨¨⊂'list',1⌽core↓node)out.Add¨_.p,¨descs ⍝ make IDs like 'DC_Button'
          items.Set⊂'.listitem'
          items.On⊂'click' 'OnTree'
          r←(2↓node)(2↓node,' Controls')((⍕⍴currctrls),(core/' core'),' controls')out''
      :ElseIf '_'=⊃node ⍝ Class or core subset thereof
          core←'_'=2⊃node
          node↓⍨←core ⍝ Remove additional _ from '__html' if core-only
          i←REFS⍳⍎node
          currctrls←(CORE∘∩⍣core)i⊃CONTROLS ⍝ Filter if core-only
          out←NewDiv'.framed'
          descs←AddLongInfo currctrls
          items←(currctrls,⍨¨⊂'list',1⌽core↓node)out.Add¨_.p,¨descs ⍝ make IDs like 'DC_Button'
          items.Set⊂'.listitem'
          items.On⊂'click' 'OnTree'
          r←node((i⊃GROUPS),P node)((⍕⍴currctrls),(core/' core'),' controls')out''
      :ElseIf '_'=⊃⌽node ⍝ Category
          (class cat)←Split node
          names←⍎class
          i←(names[;3]/⍨(⊢=⌊/)names[;1])⍳⊂'node',node
          currctrls←1↓i⊃names[;2]⊂⍨(⊢=⌊/)names[;1]
          group←GROUPS⊃⍨REFS⍳⍎'_',class
          out←NewDiv'.framed'
          descs←AddLongInfo currctrls
          items←(currctrls,⍨¨⊂'list',class)out.Add¨_.p,¨descs ⍝ make IDs like 'DC_Button'
          items.Set⊂'.listitem'
          items.On⊂'click' 'OnTree'
          r←('_',class)(group,(P'_',class),' ',cat)(' controls',⍨⍕⍴currctrls)out''
      :Else ⍝ Control
          spacectrl←'_',('_'⎕R'.')node
          (class control)←Split node
          spacedir←'Examples/',class
          files←Dlist spacedir
          out←NewDiv'.framed'
          CURRFILES←0 2⍴0 'url' ⍝ Score URL
          :For file :In files
              url←spacedir,'/',file
              CURRFILES⍪←(spacectrl ScoreIn url)url
          :EndFor
          CURRFILES⌿⍨←×CURRFILES[;1] ⍝ Weed out 0-score samples
          :If 0∊⍴CURRFILES ⍝ Failed to find a sample, so perform a search instead
              STR←spacectrl ⍝ Pass implicit argument to OnSearch
              r←OnSearch ⍝ Capture and modify result
              (1⊃r)←spacectrl
              (2⊃r)←'_',class,'.',AddShortInfo⊂control
              (3⊃r)←(4↓⊃AddLongInfo,⊂control),' ',('0'=⊃2⊃r)/3⊃r
          :Else
              CURRFILES←CURRFILES[⍋CURRFILES[;1];2] ⍝ Sort by score
              r←control Update⊃CURRFILES
          :EndIf
      :EndIf
      r←GenJS r
    ∇
    :ENDSECTION

:EndClass

:Class index2 : MiPageSample

    :SECTION GLOBALS ⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝

    :Field TYPES←'Simple' 'Advanced'⍝ Types of samples (if not App)
    :Field GROUPS      ⍝ Names of groups of elements
    :Field REFS        ⍝ ... their refs
    :Field APPS        ⍝ List of all apps
    :Field SAMPLES     ⍝ List of all samples (well, groups and controls really)
    :Field INFOLONG    ⍝ Long desc of each control
    :Field INFOSHORT   ⍝ Short (1-3 words) desc of each control
    :Field NAMESLONG   ⍝ Elements that have long info
    :Field NAMESSHORT  ⍝ Elements that have short info
    :Field SEARCH←''   ⍝ Last-search cache
    :Field CONTROLS←'' ⍝ All control names
    :Field APPDESCS    ⍝ Sample Apps' Description::
    :Field APPCTRLS    ⍝ Sample Apps' Control:: (i.e. the title)
    :Field CORE        ⍝ Core subset of controls
    :Field STR←''      ⍝ String to search for
    :Field ALLFILES    ⍝ List of pathnames for all sample files
    :Field SAMPLE←1    ⍝ The current view is a sample (i.e. has source-code and related samples)

    :ENDSECTION

    :SECTION UTILITIES ⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝

    Q←'"'∘,,∘'"'  ⍝ Surround with quotes, a.k.a. APL dragon

    D←{(×≢⍵)/' – ',⍵} ⍝ Prepend a dash if non-empty

    P←{1⌽(×≢#.HTMLInput.dtlb ⍵)/') (',⍵} ⍝ Surround with parens if non-empty

    Words←{(1↓¨(' '∘=⊂⊢)' ',⍵)~⊂''} ⍝ Split at spaces

    SpaceToDir←{'Examples/',1↓⍵} ⍝ Convert Space name to Folder name

    Frame←{'.iframed' ('src=',Q⍵,'?NoWrapper=1') New _.iframe}

    NewWinA←{'target="_blank"'('href=',Q⊃⌽⍵) 'title="Click to pop out"'New _.a (⊃⍵)} ⍝ New link that opens in a new window/tab

    NewDiv←{⍵ New _.div} ⍝ Make a div

    Horz←{⍺←⊢ ⋄ r⊣(r←⍺ New _.StackPanel ⍵).Horizontal←1} ⍝ Horizontal StackPanel

    Type←{P(1⍳⍨∨/¨TYPES⍷¨⊂⍺)⊃(TYPES,¨⊂' sample for ',⍵),⊂'Sample app'} ⍝ Simple/Advanced/App?

    Dread←{0::,⊂'[file read failed]' ⋄ #.UnicodeFile.ReadNestedText #.Boot.AppRoot,⍵,'.dyalog'} ⍝ Read dyalog file

    Dlist←{0::⍬ ⋄ (Slist #.Boot.AppRoot,⍵,' -raw')[;2]} ⍝ List dyalog files

    Slist←{l←⎕SE.SALT.List ⍵ ⋄ l[;2]←('\\'⎕R'/')(l[;2]) ⋄ l} ⍝ SALT.List with /'s

  ⍝  NodeID←{⍺←⊢ ⋄ ('#node',⊃⍵)∘,¨⍕¨⍺+⍳⍴⊃⌽⍵} ⍝ Generate node ids (⍵='L' items) optional (⍺=offset)

    Split←{{⍵↑⍨+/∨\' '≠⌽⍵}¨('_'⎕R' ')⍵((⍳↑⊣){⍺⍵}(⍳↓⊣))'_'} ⍝ Split at first _ and fix _s

    In←{∨/¨⊃⍷¨/{⎕SE.Dyalog.Utils.lcase¨eis ⍵}¨⍺ ⍵} ⍝ Case-insensitive find

    Names←{1↓¨⍵↑¨⍨¯1+⍵⍳¨':'} ⍝ Extract section names from set of several 'name:: description'

    AddShortInfo←{⍵,¨P¨(4+⍴¨⍵)↓¨(INFOSHORT,⊂'')[NAMESSHORT⍳⍵]} ⍝ ⍵ (ShortDesc)

    ShortInfo←{(4+⍴⍵)↓⊃(INFOSHORT,⊂'')[NAMESSHORT⍳⊂⍵]}

    AddLongInfo←{(New¨_.strong,¨⍵),¨D¨(4+⍴¨⍵)↓¨(INFOLONG,⊂'')[NAMESLONG⍳⍵]} ⍝ ⍵ - LongDesc

    ScoreIn←{(100⊥⌽∨/¨TYPES⍷¨⊂⍵)×(⊂⍺)(∊×⍳⍨)Words'Control'Section Dread ⍵} ⍝ ⍺'s relevance in ⍵ (0=none 1=high 2=lower...)

    Tail←{⍵ ⍺⍺⍨1-(⌽⍵)⍳'/'} ⍝ ↑Tail or ↓Tail

    End←{⍺⍺{⍵↑⍨¯1+⍵⍳'_'}⍺⍺ ⍵} ⍝ ⊢End: until first .   ⌽End: from last .

    NodeToCtrl←{'_',(⊢End 1↓⍵),'.',⌽End ⍵}

    CtrlToNode←{'#',('\.' ⎕R '_')⍵}

    Clean←'[_\-\.]'⎕R' '

    DelEmpty←{((0,⍨2</⍵[;1])∨'/'≠⊃¨⌽¨⍵[;3])⌿⍵}

      DirTree←{
          parent←1(↑Tail ⍵)('/',⍵,'/')
          list←Slist #.Boot.AppRoot,⍵,' -rec -raw'
          0∊⍴list:0 3⍴0 '' ''
          nodir←~list[;1]∊⍨⊂'<DIR>'
          prefix←'/',(↓Tail ⍵),nodir/(↑Tail ⍵),'/' ⍝ Quirk in SALT.List includes path only if has subfolders
          files←prefix∘,¨list[;2]
          levels←2+(+/¨'/'=files)-+/'/'=3⊃parent
          ((list[;1]≡¨⊂'<DIR>')/files),←'/'
          DelEmpty⍣≡parent⍪⍉↑levels(↑Tail¨list[;2])files
      }

      Section←{ ⍝ extract section ⍺:: from code ⍵
          regex←'^\s*⍝\s*',⍺,':(:.*?)$((\R^⍝(?!\s*\w+::).*?$)*)'
          opts←('Mode' 'M')('DotAll' 1)
          res←(regex ⎕S'\1\2'⍠opts)⍵
          (1↓⊃res)~'⍝'
      }

    :ENDSECTION

    :SECTION MAIN ⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝

    ∇ Compose;left;mid;right;sp;list
      :Access public

     ⍝ Initialize globals
      CURRFILES←⊂'/About-MiServer'
      CURRCTRL←''
      SAMPLES←0 3⍴⍬
      GROUPS←'Dyalog Controls' 'SyncFusion' 'JQueryUI' 'Base HTML'
      REFS←_DC _SF _JQ _html
      INFOSHORT←'⍝',¨Dread'Examples/Data/infoShort'
      INFOLONG←'⍝',¨Dread'Examples/Data/infoLong'
      NAMESSHORT←Names INFOSHORT
      NAMESLONG←Names INFOLONG
      list←⊃⍪/{Slist #.Boot.AppRoot,'Examples/',⍵,' -rec -raw -full'}¨'DC' 'SF' 'JQ' 'html'
      ALLFILES←list[;2]/⍨list[;1]≢¨⊂'<DIR>'
      TREE←⎕SE.SALT.Load #.Boot.AppRoot,'Examples/Data/tree -noname'
      CORE←⎕SE.SALT.Load #.Boot.AppRoot,'Examples/Data/core -noname'

      Add _.StyleSheet'/Styles/homepage.css'

      (left mid)←NewDiv¨'#leftBar' '#midBar' ⍝ Create panes
      Add'mainSP'Horz left mid
      PopulateLeft left
      PopulateMid mid
    ∇

    ∇ PopulateLeft thediv;class;depths;group;items;ref;samples;vp;search;menu;i;fs;ac;text;treeall;treecore;names;tree;dirs;levels;core;enames

      ⍝ SEARCH FIELD ⍝⍝⍝
      search←New _.EditField'searchfield'⍝).On'change' 'OnSearch'('str' 'val')
      (search,←'#searchbutton' '.menu'New _.button'Search').On'click' 'OnSearch'('str' '#searchfield' 'val')
      thediv.Add Horz search
      thediv.Add _.hr

      ⍝ GETTING STARTED ⍝⍝⍝
      '.cat'thediv.Add _.p'Getting Started'
      tree←0 3⍴0 '' ''
      tree⍪←1 'Start here',CURRFILES
      tree⍪←DirTree'Documentation'
      tree⍪←DirTree'Examples/Techniques'
      tree⍪←DirTree'Examples/Applications'
      tree[;2]←Clean¨tree[;2]
      tree←'#treeG'thediv.Add _.ejTreeView tree
      tree.On'nodeSelect' 'OnGS'('node' 'eval' 'argument.id')
      thediv.Add _.hr

      ⍝ CONTROLS ⍝⍝⍝
      '.cat'thediv.Add _.p'Controls'
      tree←0 3⍴0 '' ''
      names←TREE
      dirs←'_'=(⊃⌽)¨names
      ⍝ All
      tree⍪←1 'All' '_'
      levels←1+dirs-⍨+/¨'_'=names
      enames←⌽End¨1↓¨names↓¨⍨-dirs
      tree⍪←⍉↑levels enames names
      ⍝ Core
      core←(2=levels)∨(enames∊CORE) ⍝∧(~dirs) not necessary because no category name appears in core list
      enames/⍨←core
      names/⍨←core
      levels/⍨←core
      levels⌊←3
      core←⍉↑levels enames(names,¨'(')
      tree⍪⍨←⊃⍪/{⍵[1,1+⍋↑1↓⍵[;2];]}¨(2=core[;1])⊂[1]core ⍝ Sort classes
      tree⍪⍨←1 'Core' '_(' ⍝ ( is core suffix
      tree[;2]←Clean¨tree[;2]
      ⍝ Add the whole tree
      tree←'#treeA'thediv.Add _.ejTreeView tree
      tree.On'nodeSelect' 'OnCA'('node' 'eval' 'argument.id')
    ∇

    ∇ PopulateMid mid;url;code;frame;title;navbuts;t;sr;desc

     ⍝ Read framed pages
      url←⊃CURRFILES
      code←Dread url

     ⍝ Create and fill placeholders for title and header
      title←Clean'Control'Section code

     ⍝ _html.code
      '#title'Add _.title('MS3: ',title) ⍝ after the : will be updated later on
      '#SampleTitle'mid.Add _.h2 title

      desc←'#CtlDescs' 'style="display:none"'mid.Add _.div ⍝ All descriptions will go here

     ⍝ Control: Code fragment [View documentation]
      '#ControlDesc'desc.Add _.span
      ('#DocLink'desc.Add _.span).Add'target="_blank'New _.A'View documentation'
      desc.Add _.br

     ⍝ Sample: Embed a code fragment [Pop out]
      '#SampleDesc'desc.Add _.span('Description'Section code)
      ('#PopLink'desc.Add _.span).Add NewWinA'Pop out'url
      desc.Add _.br

     ⍝ [ ] Show related samples
      t←'onchange="$("#rel").toggle()"'desc.Add _.Input'checkbox' '' 'Show related samples' 'right'
      t.style←'margin-left: 0px;'
      '#rel' 'style="display: none;"'desc.Add _.div
      desc.Add _.hr

     ⍝ Create and fill placeholder for embedded page and its source code
      (mid.Add NewDiv'#SampleFrame').Add Frame url
      mid.Add _.hr
      t←'onchange' '$("#SampleSource").toggle()'mid.Add _.Input'checkbox' '' 'Show source code' 'right'
      t.style←'margin-left: 0px;'
      '#SampleSource' '.samplesource' 'style="display: none;"'mid.Add _.div('small;border:none'#.HTMLInput.APLToHTMLColour Dread⊃CURRFILES)

    ∇

    :ENDSECTION

    :SECTION CALLBACKS ⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝

    ∇ r←OnGS;node;list;nodir;prefix;files;out;file;name;item;title;desc;toggle;fromframe
      :Access Public

     ⍝ Callback for Getting Started
      node←(1+'tree'≡4↑_what)⊃_what(Get'node') ⍝ get id of node if tree or id of what if not
      fromframe←'_'=⊃⌽node
      node~←'_' ⍝ _ is frame suffix
      :If '/'=⊃⌽node ⍝ Folder (i.e. Category)
          r←''
          :Return
          CURRCTRL←''
          SAMPLE←0
          node←1↓¯1↓node ⍝ Strip outer slashes
          list←Slist #.Boot.AppRoot,node,' -rec -raw'
          nodir←~list[;1]∊⍨⊂'<DIR>'
          prefix←(↓Tail node),nodir/(Clean↑Tail node),'/' ⍝ Quirk in SALT.List includes path only if has subfolders
          files←prefix∘,¨list[;2]
          files/⍨←list[;1]≢¨⊂'<DIR>'
          CURRFILES←files
          out←NewDiv'.framed'
          :For file :In files
              item←('#/',file,'_')'.listitem' 'title="Click here to open"'out.Add _.p
              item.Add _.strong(Clean↑Tail file)
              item.Add' ',#.HTMLInput.dtlb'Description'Section Dread file
          :EndFor
          out.Add _.Handler'.listitem' 'click' 'OnGS'
          title←Clean node
          desc←'Click on a button below to select a sample.'
          r←title title desc out''
          toggle←';scroll(0,0);$("#CtlDescs").hide()'
      :Else ⍝ File (i.e. Page)
          SAMPLE←1
          toggle←(1+fromframe)⊃'$("#CtlDescs").hide();' '$("#CtlDescs").show();'
          r←Update node
      :EndIf

      r←(Execute toggle),GenJS r
    ∇

    ∇ r←OnCA;node;control;files;list;file;scores;code;desc;score;controls;out;item;title;coreonly;toggle
      :Access Public
     ⍝ Callback for Core/All Controls
      node←(1+'tree'≡4↑_what)⊃_what(Get'node') ⍝ get id of node if tree or id of what if not
      COREONLY←coreonly←'('∊node
      node↓⍨←-coreonly ⍝ drop ( is core suffix
      :If '_'=⊃⌽node ⍝ Category
          r←''
          :Return
          CURRCTRL←''
          SAMPLE←0
          title←('All '/⍨coreonly<1=⍴node),(coreonly/'Core '),(Clean node),' controls'
          r←title title'' '' ''
          toggle←'$("#CtlDescs").hide();'
      :Else ⍝ Control
          SAMPLE←1
          CURRCTRL←node
          control←NodeToCtrl node
          scores←⍬
          :For file :In ALLFILES
              controls←Words'Control'Section Dread'Examples/',file
              score←102-2×(50↑controls)⍳⊂control ⍝ 100=most relevant, 0=not relevant at all
              score-←∨/'Advanced'⍷file           ⍝ subtract 1 if advanced example
              scores,←0⌈score
          :EndFor
          CURRFILES←'/Examples/'∘,¨(ALLFILES/⍨×scores)[⍒scores/⍨×scores] ⍝ sort descending by score
          :If 0=⍴CURRFILES
              r←control control'' '' ''
              toggle←'$("#CtlDescs").hide();'
          :Else
              r←control Update⊃CURRFILES
              toggle←'$("#CtlDescs").show();'
          :EndIf

      :EndIf
      r←(GenJS r),Execute'scroll(0,0);',toggle
    ∇

    ∇ r←OnList;out;file;item;title;node;desc
      :Access Public
     ⍝ Called when user wants the entire list of relevant samples for the current control
      node←¯1↓_what ⍝ Remove desc _ suffix
      out←NewDiv'.framed'
      :If 0=⍴CURRFILES
          '.noitems'out.Add _.p,⊂'[no samples for ',(¯1↓node),' controls]'
              ⍝(2⊃r)←'_',class,'.',AddShortInfo⊂control
              ⍝(3⊃r)←(4↓⊃AddLongInfo,⊂control),' ',('0'=⊃2⊃r)/3⊃r
          r←control(control,' Short Info')'Long info'out''
      :Else
          :For file :In CURRFILES
              item←('#',file,'_')'.listitem' 'title="Click here to open"'out.Add _.p
              item.Add _.strong(↑Tail file)
              item.Add' ',#.HTMLInput.dtlb'Description'Section Dread file
          :EndFor
          out.Add _.Handler'.listitem' 'click' 'OnGS'
          title←NodeToCtrl node
          desc←'Click on a button below to select a sample.'
          r←title title desc out''
      :EndIf
      r←GenJS r
    ∇

    ∇ r←OnSample
      :Access Public
      r←GenJS Update CURRFILES⊃⍨⍎5↓_what ⍝ id="nodeS23"
    ∇

    ∇ r←OnSearch;str;terms;out;i;dir;files;file;url;code;ctrlsec;desc;item;title
      :Access Public

      str←(1+STR≡'')⊃STR(Get'str') ⍝ get search string

      :If ×≢str ⍝ Continue only if there is a search string
      ⍝⍝⍝ Controls
          terms←INFOSHORT/⍨str In INFOSHORT
          terms,←terms~⍨INFOLONG/⍨str In INFOLONG
          terms←'.',¨∪Names terms
      ⍝⍝⍝ Samples
          out←NewDiv'.framed'
          CURRFILES←''
          i←0
          :For dir :In 'Applications' 'html' 'HTMLplus' 'DC' 'JQ' 'SF'
              files←Dlist'Examples/',dir
              :For file :In files~⊂'index'
                  url←'Examples/',dir,'/',file
                  code←Dread url
                  ctrlsec←'Control'Section code
                  desc←⊂'Description'Section code
                  :If ∨/str In desc
                  :OrIf ∨/∊(terms,⊂str)In¨⊂ctrlsec ⍝ always case sensitive
                      i+←1
                      CURRFILES,←⊂url
                      desc←∊desc,file Type⊃Words ctrlsec
                      item←('#nodeS',⍕i)'.listitem'out.Add _.p desc
                      item.On'click' 'OnSample'
                  :EndIf
              :EndFor
          :EndFor
          :If ~×i
              '.noitems'out.Add _.p,⊂'[no results for ',str,']'
          :EndIf
          title←(⍕≢CURRFILES),' sample pages for ',Q str
          desc←'Click on a button below to select a sample.'
          r←(Q str)title desc out''
          SEARCH←GenJS⍣(STR≡'')⊢r ⍝ Do not finish up if called by OnTree
          STR←'' ⍝ Reset
      :EndIf
      r←SEARCH
    ∇

    ∇ (page title desc url code)←{spacectrl}Update url;ctrlsec;control;space
     ⍝ Create new placeholder values
      code←Dread url
      :If ×⎕NC'spacectrl'
          page←spacectrl
          title←('All '/⍨2≥⍴page),('Core '/⍨'('=⊃⌽page),⌽End page
      :Else
          page←Clean'Control'Section code
          title←page
      :EndIf
      desc←#.HTMLInput.dtlb'Description'Section code
    ∇

    ∇ r←GenJS(page title desc url code);cd;sd;file;scores;controls;score;out;item;control;coreonly
     ⍝ Generate JavaScript for filling placeholders
      r←'#title'Replace'MS3: ',page
      control←NodeToCtrl CURRCTRL

      :If 'treeG'≡_what
          r,←'#SampleTitle'Replace title
      :Else
          r,←(×≢title)/'#SampleTitle'Replace control
      :EndIf
      (cd←New _.span).Add¨(_.strong'Control: ')(_.em,⊂ShortInfo⌽End CURRCTRL)
      r,←'#ControlDesc'Replace cd
      (sd←New _.span).Add¨(_.strong'Sample: ')(_.em desc)
      r,←'#SampleDesc'Replace sd

      :If ''≡desc
          coreonly←COREONLY
          control←NodeToCtrl¨TREE/⍨∨/¨(⊂node)⍷¨TREE
          control←(CORE∊⍨{⍵↓⍨⌽⍵⍳'.'}¨control)/⍣coreonly⊢control
          scores←⍬
          :For file :In files←ALLFILES[⍋↑ALLFILES]
              controls←Words'Control'Section Dread'Examples/',file
              score←2×∨/control∊controls         ⍝ 2=relevant Simple, 0=not relevant
              score-←∨/'Advanced'⍷file           ⍝ 1=relevant Advanced
              scores,←0⌈score
          :EndFor
          CURRFILES←'/Examples/'∘,¨(files/⍨×scores)[⍒scores/⍨×scores] ⍝ put Simple before Advanced
          out←NewDiv'.framed'
          :If 0=⍴CURRFILES
              '.noitems'out.Add _.p,⊂'[no samples for ',(¯1↓node),' controls]'
              ⍝(2⊃r)←'_',class,'.',AddShortInfo⊂control
              ⍝(3⊃r)←(4↓⊃AddLongInfo,⊂control),' ',('0'=⊃2⊃r)/3⊃r
              r←control(control,' Short Info')'Long info'out''
          :Else
              :For file :In CURRFILES
                  item←('#',file,'_')'.listitem' 'title="Click here to open"'out.Add _.p
                  item.Add _.strong(↑Tail file)
                  item.Add' ',#.HTMLInput.dtlb'Description'Section Dread file
              :EndFor
              out.Add _.Handler'.listitem' 'click' 'OnGS'
              title←('All '/⍨coreonly<1=⍴node),(coreonly/'Core '),(Clean node),' controls'
              ⍝desc←'Click on a button below to select a sample.'

          :EndIf
      :Else

          scores←⍬
          :For file :In ALLFILES
              controls←Words'Control'Section Dread'Examples/',file
              score←102-2×(50↑controls)⍳⊂control ⍝ 100=most relevant, 0=not relevant at all
              score-←∨/'Advanced'⍷file           ⍝ subtract 1 if advanced example
              scores,←0⌈score
          :EndFor
          CURRFILES←'/Examples/'∘,¨(ALLFILES/⍨×scores)[⍒scores/⍨×scores] ⍝ sort descending by score
          out←NewDiv'.framed'
          :If 1<⍴CURRFILES
              :For file :In 1↓CURRFILES
                  item←('#',file,'_')'.listitem' 'title="Click here to open"'out.Add _.p
                  item.Add _.strong(↑Tail file)
                  item.Add' ',#.HTMLInput.dtlb'Description'Section Dread file
              :EndFor
              out.Add _.Handler'.listitem' 'click' 'OnGS'
          :EndIf
      :EndIf

      r,←'#rel'Replace out

      r,←(×≢url)/'#SampleFrame'Replace Frame url

      r,←'#PopLink'Replace NewWinA'Pop out'url
      r,←'#SampleSource'Replace'small;border:none'#.HTMLInput.APLToHTMLColour code
      url←∊'/Documentation/DyalogAPIs/WidgetDoc?namespace=_' '&widget=',¨(⊢End{⍺ ⍵}⌽End)1↓CURRCTRL
      r,←'#DocLink'Replace NewWinA'View documentation'url
      :If 0=⍴CURRFILES
          r,←Execute'$("#CtlDescs").show();'
          r,←'#SampleDesc'Replace'.noitems'New _.p,⊂'[no samples using ',control,']'
          r,←'#PopLink'Replace''
          r,←'#SampleSource'Replace''
          r,←'#SampleFrame'Replace''
      :EndIf
    ∇

    ∇ node←GetNode
      node←4↓(1+'tree'≡4↑_what)⊃_what(Get'node')
    ∇
    :ENDSECTION

    :SECTION OBSOLETE ⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝
      JSsafe←{ ⍝ Make text JS safe by escaping problematic chars
          fr←'''' '"' '\\' '\n' '\r',⎕UCS 9 8 12               ⍝ ' " \ NL CR TB BS FF
          to←'\\''' '\\"' '\\\\' '\\n' '\\r' '\\t' '\\b' '\\f' ⍝ problematic in regex too :-)
          Q(fr ⎕R to⍠'Mode' 'D')⍵ ⍝ Replace problematic chars and sourround with quotes
      }

    ∇ r←OnNavBut;file;item;out;title;desc
      :Access Public
      r←''
      :Select 2↓_what
      :Case 'related'
          SAMPLE←0
          out←NewDiv'.framed'
          :For file :In CURRFILES
              item←('#',file,'_')'.listitem' 'title="Click here to open"'out.Add _.p
              item.Add _.strong(Clean↑Tail file)
              item.Add' ',#.HTMLInput.dtlb'Description'Section Dread file
          :EndFor
          out.Add _.Handler'.listitem' 'click' 'OnGS'
          title←''⍝NodeToCtrl node
          desc←'Click on a button below to select a sample.'
          r←GenJS title title desc out''
      :Case 'source'
          :If SAMPLE
              r←'#SampleSource'Replace'small;border:none'#.HTMLInput.APLToHTMLColour Dread⊃CURRFILES
              r,←Execute'location.replace("#source");'
          :EndIf
      :Case 'info'
          :If SAMPLE∧''≢CURRCTRL
              r←Execute'window.open',P Q∊∊'/Documentation/DyalogAPIs/WidgetDoc?namespace=_' '&widget=',¨(⊢End{⍺ ⍵}⌽End)CURRCTRL
          :EndIf
      :Case 'out'
          r←SAMPLE/Execute'window.open',P Q⊃CURRFILES
      :Case 'urce' ⍝ n.b. 2↓
          r←Execute'scroll(0,0);'
      :EndSelect
    ∇

    ∇ js←APLtoJS vtv;act;data
      :Access public shared
     ⍝ Convert vectors of pseudo JS (generated by Replace, Execute, et al.) to proper JS

      js←''
      :For act data :In eis vtv
          data←JSsafe⊃⌽eis data ⍝ the last or only one
          :Select ⊃eis act      ⍝ the first or only one
          :Case 'assign'
              js,←(⊃⌽act),' = ',data,';' ⍝ variable = "data"
          :Case 'execute'
              js,←'eval(',data,');' ⍝ eval("data")
          :Case 'replace'
              js,←'$("',(⊃⌽act),'").html(',data,');' ⍝ $("#myid").html("data")
          :Else
              js,←'$("',(⊃⌽act),'").',(⊃act),'(',data,');' ⍝ $("#myid").append("data")
          :EndSelect
      :EndFor
    ∇

    ∇ r←OnTree;node;descs;out;items;spacectrl;control;spacedir;files;file;i;url;code;ctrlsec;desc;item;title;currctrls;core;names;class;group;cat;score
      :Access Public
      node←GetNode
      :If '0'∊node ⍝ Core or All
          core←'_'=2⊃node
          currctrls←(CORE∘∩⍣core)⊃,/CONTROLS ⍝ Filter if core-only
          out←NewDiv'.framed'
          descs←AddLongInfo currctrls
          items←(currctrls,⍨¨⊂'list',1⌽core↓node)out.Add¨_.p,¨descs ⍝ make IDs like 'DC_Button'
          items.Set⊂'.listitem'
          items.On⊂'click' 'OnTree'
          r←(2↓node)(2↓node,' Controls')((⍕⍴currctrls),(core/' core'),' controls')out''
      :ElseIf '_'=⊃node ⍝ Class or core subset thereof
          core←'_'=2⊃node
          node↓⍨←core ⍝ Remove additional _ from '__html' if core-only
          i←REFS⍳⍎node
          currctrls←(CORE∘∩⍣core)i⊃CONTROLS ⍝ Filter if core-only
          out←NewDiv'.framed'
          descs←AddLongInfo currctrls
          items←(currctrls,⍨¨⊂'list',1⌽core↓node)out.Add¨_.p,¨descs ⍝ make IDs like 'DC_Button'
          items.Set⊂'.listitem'
          items.On⊂'click' 'OnTree'
          r←node((i⊃GROUPS),P node)((⍕⍴currctrls),(core/' core'),' controls')out''
      :ElseIf '_'=⊃⌽node ⍝ Category
          (class cat)←Split node
          names←⍎class
          i←(names[;3]/⍨(⊢=⌊/)names[;1])⍳⊂'node',node
          currctrls←1↓i⊃names[;2]⊂⍨(⊢=⌊/)names[;1]
          group←GROUPS⊃⍨REFS⍳⍎'_',class
          out←NewDiv'.framed'
          descs←AddLongInfo currctrls
          items←(currctrls,⍨¨⊂'list',class)out.Add¨_.p,¨descs ⍝ make IDs like 'DC_Button'
          items.Set⊂'.listitem'
          items.On⊂'click' 'OnTree'
          r←('_',class)(group,(P'_',class),' ',cat)(' controls',⍨⍕⍴currctrls)out''
      :Else ⍝ Control
          spacectrl←'_',('_'⎕R'.')node
          (class control)←Split node
          spacedir←'Examples/',class
          files←Dlist spacedir
          out←NewDiv'.framed'
          CURRFILES←0 2⍴0 'url' ⍝ Score URL
          :For file :In files
              url←spacedir,'/',file
              CURRFILES⍪←(spacectrl ScoreIn url)url
          :EndFor
          CURRFILES⌿⍨←×CURRFILES[;1] ⍝ Weed out 0-score samples
          :If 0∊⍴CURRFILES ⍝ Failed to find a sample, so perform a search instead
              STR←spacectrl ⍝ Pass implicit argument to OnSearch
              r←OnSearch ⍝ Capture and modify result
              (1⊃r)←spacectrl
              (2⊃r)←'_',class,'.',AddShortInfo⊂control
              (3⊃r)←(4↓⊃AddLongInfo,⊂control),' ',('0'=⊃2⊃r)/3⊃r
          :Else
              CURRFILES←CURRFILES[⍋CURRFILES[;1];2] ⍝ Sort by score
              r←control Update⊃CURRFILES
          :EndIf
      :EndIf
      r←GenJS r
    ∇
    :ENDSECTION

:EndClass


remove MiPage stop

remove MiPage stop

:Class MiPage : #.HtmlPage

    ⍝∇:require =\HtmlPage.dyalog
    ⍝∇:require =\JSON.dyalog

    :Field Public _PageName←'' ⍝ Page file name
    :Field Public _PageDate←'' ⍝ Page saved date
    :field Public _Request     ⍝ HTTPRequest
    :field Public _Scripts←''
    :field Public _Styles←''
    :field Public _CssReset←''    ⍝ location of CSS Reset file (if any)
    :field Public _CssOverride←'' ⍝ location of CSS Override file (if any)
    :field public _Serialized←1   ⍝ serialized forms to return in _PageData
    :field Public _event          ⍝ set by APLJAX callback - event that was triggered
    :field Public _what           ⍝ set by APLJAX callback - name or id of the triggering element
    :field Public _value          ⍝ set by APLJAX callback - value of the triggering element
    :field Public _selector       ⍝ set by APLJAX callback - CSS/jQuery selector for the element that triggered the event
    :field Public _callback       ⍝ set by APLJAX callback - name of the callback function
    :field public _PageData
    :field public _AjaxResponse←''
    :field public _DebugCallbacks←0
    :field public OnLoad←''     ⍝ page equivalent to ⎕LX

    _used←'' ⍝ keep track of what's been used

    ∇ Make
      :Access public
      :Implements constructor :Base
      MakeCommon
    ∇

    ∇ Make1 req
      :Access public
      _Request←req
      :Implements constructor :base
      MakeCommon
    ∇

    ∇ MakeCommon
      _PageData←⎕NS''
    ∇

    ∇ {r}←Render;b;styles
      :Access public
⍝      ∘∘∘
      :If ''≢OnLoad
          Use'JQuery'
      :EndIf
      b←RenderBody
      styles←_Styles
      styles←styles,⍨{0∊⍴⍵:⍵ ⋄ ⊂⍵}_CssReset
      styles←styles,{0∊⍴⍵:⍵ ⋄ ⊂⍵}_CssOverride
      :If ~0∊⍴styles
          {(Head.Add _html.link).Set(('href=',⍵)('rel' 'stylesheet')('type' 'text/css'))}¨∪styles
      :EndIf
      :If ~0∊⍴_Scripts
          {(Head.Add _html.script).Set('src=',⍵)}¨∪_Scripts
      :EndIf
      :If ~0∊⍴Handlers
          b,←∊Handlers.Render
      :EndIf
      :If ''≢OnLoad
          b,←(⎕NEW #._html.script('$(function(){',OnLoad,'});')).Render
      :EndIf
      r←RenderPage b
      :If 0≠⎕NC⊂'_Request.Response'
          _Request.Response.HTML←r
      :EndIf
    ∇

    ∇ {r}←Wrap
      :Access public
      r←Render
    ∇

    ∇ Use resources;n;ind;t;x
      :Access public
      resources←eis resources
      :For x :In resources
          :If ~(⊂x)∊_used
              :Select ⊃x
              :Case '⍎' ⍝ script
                  _Scripts,←⊂1↓x
              :Case '⍕' ⍝ style sheet
                  _Styles,←⊂1↓x
              :Else
                  :If 0≠⎕NC⊂'_Request.Server.Config.Resources'
                  :AndIf ~0∊n←1↑⍴_Request.Server.Config.Resources
                      :If n≥ind←_Request.Server.Config.Resources[;1]⍳⊂x
                          :If ~0∊⍴t←{(~0∘∊∘⍴¨⍵)/⍵}(⊂ind 2)⊃_Request.Server.Config.Resources
                              _Scripts,←t
                          :EndIf
                          :If ~0∊⍴t←{(~0∘∊∘⍴¨⍵)/⍵}(⊂ind 3)⊃_Request.Server.Config.Resources
                              _Styles,←t
                          :EndIf
                      :Else
                          1 _Request.Server.Log _PageName,' references unknown resource: ',x
                      :EndIf
                  :EndIf
              :EndSelect
              _used,←⊂x
          :EndIf
      :EndFor
    ∇

    ∇ r←{proto}Get names
      :Access public
      proto←{6::⍵ ⋄ proto}''
      names←eis names
      names←,⍕names
      names←#.Strings.deb names
      :If ' '∊names
          names←{⎕ML←3 ⋄ ⍵⊂⍨⍵≠' '}names
          r←proto∘Get¨names
      :ElseIf 2≠_PageData.⎕NC names
          r←,proto
      :Else
          r←_PageData⍎names
          :If 2=≡r
              :If 1=⍴,r
                  r←⊃r
              :EndIf
          :EndIf
          r←#.JSON.toAPL r
⍝          :If ~isChar proto
⍝              r←{0::⍵ ⋄ 0∊⍴⍵:⍬ ⋄ w←⍵ ⋄ ((w='-')/w)←'¯' ⋄ ⊃(//)⎕VFI w}r
⍝          :EndIf
      :EndIf
    ∇

    ∇ r←{proto}GetRaw names
      :Access public
      proto←{6::⍵ ⋄ proto}''
      names←eis names
      names←,⍕names
      names←#.Strings.deb names
      :If ' '∊names
          names←{⎕ML←3 ⋄ ⍵⊂⍨⍵≠' '}names
          r←proto∘Get¨names
      :ElseIf 2≠_PageData.⎕NC names
          r←,proto
      :Else
          r←_PageData⍎names
          :If 2=≡r
              :If 1=⍴,r
                  r←⊃r
              :EndIf
          :EndIf
          :If ~isChar proto
              r←{0::⍵ ⋄ 0∊⍴⍵:⍬ ⋄ w←⍵ ⋄ ((w='-')/w)←'¯' ⋄ ⊃(//)⎕VFI w}r
          :EndIf
      :EndIf
    ∇

    ∇ r←{proto}SessionGet names
      :Access public
      proto←{6::⍵ ⋄ proto}''
      names←,⍕names
      names←#.Strings.deb names
      :If ' '∊names
          names←{⎕ML←3 ⋄ ⍵⊂⍨⍵≠' '}names
          r←proto∘SessionGet¨names
      :ElseIf 2≠_Request.Session.⎕NC names
          r←proto
      :Else
          r←_Request.Session⍎names
          :If 1<|≡r ⋄ r←∊r ⋄ :EndIf
          :If ~0 2∊⍨10|⎕DR proto
              r←{0∊⍴⍵:⍬ ⋄ w←⍵ ⋄ ((w='-')/w)←'¯' ⋄ ⊃(//)⎕VFI w}r
          :EndIf
      :EndIf
    ∇

    ∇ Close session ⍝ Called when the session ends
      :Access Public Overridable
    ∇

    :section APLJax  ⍝ used for building APLJAX responses
    ∇ _resetAjax
      :Access public
      _AjaxResponse←''
    ∇

    ∇ r←_id
      :Access public
      ⍝ as there seems to be a problem with at least some Syncfusion widgets
      ⍝ being able to provide the id (or name) of the triggering element, we try to obtain it from _what or _selector
      r←''
      :Trap 0
          :If 0∊⍴r←_what
          :AndIf '#'=⊃_selector
              r←1↓_selector
          :EndIf
      :EndTrap
    ∇

    ∇ Respond arg
      :Access public
      ∘∘∘
    ∇

    ∇ r←renderContent content;c
      r←''
      content←eis content
      :While ~0∊⍴content
          :Select ≡c←⊃content
          :Case 0
              :If isClass c
                  :Select ⊃⍴content
                  :Case 1
                      r,←(⎕NEW c).Render
                  :Case 2
                      r,←(⎕NEW c(2⊃content)).Render
                  :Else
                      r,←(⎕NEW c(1↓content)).Render
                  :EndSelect
              :ElseIf isInstance c
                  r,←c.Render
              :Else
                  r,←(⎕NEW #.HtmlElement(''content)).Render
              :EndIf
              content←''
          :Case 1
              :If isClass⊃c
                  r,←(⎕NEW(⊃c)(1↓c)).Render
              :ElseIf isInstance⊃c
                  ∘∘∘ ⍝ should not happen! (I think)
              :Else
                  r,←(⎕NEW #.HtmlElement(''c)).Render
              :EndIf
              content←1↓content
          :Else
              r,←renderContent c
              content←1↓content
          :EndSelect
      :EndWhile
    ∇

    ∇ r←selector Replace content
      :Access public
      r←⊂('replace'selector)('data'(renderContent content))
    ∇
    ∇ r←selector Append content
      :Access public
      r←⊂('append'selector)('data'(renderContent content))
    ∇
    ∇ r←selector Prepend content
      :Access public
      r←⊂('prepend'selector)('data'(renderContent content))
    ∇
    ∇ r←Execute content
      :Access public
      r←⊂('execute'content)
    ∇

    ∇ r←name Assign data
      :Access public
      r←⊂('assign'name)('data'data)
    ∇

    :endsection

    :section Position
    ∇ ref Position args;inds;mask;parameters;my;at;of;collision;within;q
      :Access public shared
      ⍝ ref  - a reference to an instance of anything based on HtmlElement
      ⍝ args - position information per jQueryUI's Position widget http://api.jqueryui.com/position/
      ⍝        can be in any of the following forms
      ⍝      1) positional (my at of collision within)  N.B. we don't use the "using" parameter
      ⍝         example:  myDiv Position 'left top' 'right bottom' '#otherElement'
      ⍝                   positions myDiv's top left corner at the bottom right corner of the element with id "otherElement"
      ⍝      2) paired
      ⍝                   myDiv Position 'my' 'left top' 'at' 'right bottom' 'of' '#otherElement'
      ⍝                   myDiv Position ('my' 'left top') ('at' 'right bottom') ('of' '#otherElement')
      ⍝                   myDiv Position 3 2⍴'my' 'left top' 'at' 'right bottom' 'of' '#otherElement'
      ⍝ Note: positional arguments are in form horizontal (left center right) vertical (top center bottom)

      parameters←'my' 'at' 'of' 'collision' 'within'
      q←{1⌽'''''',{⍵/⍨1+''''=⍵}⍕⍵}
      :If isInstance ref
          :If 2=⍴⍴args ⍝ matrix
              args←,args
          :ElseIf 3=≡args
              args←⊃,/args
          :EndIf
          args←eis args
          inds←parameters⍳args
          :If ∨/mask←inds≤⍴parameters
              :If mask≡(2×+/mask)⍴1 0
                  parameters←mask/args
                  args←(1⌽mask)/args
              :EndIf
          :Else
              parameters←(⍴args)↑parameters
          :EndIf
          parameters(ref{⍺⍺⍎'Position.',⍺,'←',q ⍵})¨args
          ref.Uses,←⊂'JQueryUI'
          ref.Use
      :EndIf
    ∇
    :endsection

    :section Event Handling Support
    ∇ r←isPost
      :Access public
      r←{0::0 ⋄ _Request.isPost}⍬
    ∇

    ∇ r←isAPLJax
      :Access public
      r←{0::0 ⋄ _Request.isAPLJAX}⍬
    ∇

    ∇ r←sel Css args ⍝ JQuery css cover
      :Access public
      r←(sel #._JSS.JQuery'css')args
    ∇

    ∇ r←sel Val args ⍝ JQuery val cover
      :Access public
      r←(sel #._JSS.JQuery'val')args
    ∇

    ∇ r←sel Attr args ⍝ JQuery attr cover
      :Access public
      r←(sel #._JSS.JQuery'attr')args
    ∇

    ∇ r←sel RemoveAttr args ⍝ JQuery removeAttr cover
      :Access public
      r←(sel #._JSS.JQuery'removeAttr')args
    ∇

    ∇ r←sel Html args ⍝ JQuery html cover
      :Access public
      r←(sel #._JSS.JQuery'html')args
    ∇

    :endsection

    ∇ Debug;⎕TRAP
      :Access public
      ⎕TRAP←0⍴⎕TRAP
      ∘∘∘
    ∇

:EndClass

:Class MiPage : #.HtmlPage

    ⍝∇:require =\HtmlPage.dyalog
    ⍝∇:require =\JSON.dyalog

    :Field Public _PageName←'' ⍝ Page file name
    :Field Public _PageDate←'' ⍝ Page saved date
    :field Public _Request     ⍝ HTTPRequest
    :field Public _Scripts←''
    :field Public _Styles←''
    :field Public _CssReset←''    ⍝ location of CSS Reset file (if any)
    :field Public _CssOverride←'' ⍝ location of CSS Override file (if any)
    :field public _Serialized←1   ⍝ serialized forms to return in _PageData
    :field Public _event          ⍝ set by APLJAX callback - event that was triggered
    :field Public _what           ⍝ set by APLJAX callback - name or id of the triggering element
    :field Public _value          ⍝ set by APLJAX callback - value of the triggering element
    :field Public _selector       ⍝ set by APLJAX callback - CSS/jQuery selector for the element that triggered the event
    :field Public _callback       ⍝ set by APLJAX callback - name of the callback function
    :field public _PageData
    :field public _AjaxResponse←''
    :field public _DebugCallbacks←0
    :field public OnLoad←''     ⍝ page equivalent to ⎕LX

    _used←'' ⍝ keep track of what's been used

    ∇ Make
      :Access public
      :Implements constructor :Base
      MakeCommon
    ∇

    ∇ Make1 req
      :Access public
      _Request←req
      :Implements constructor :base
      MakeCommon
    ∇

    ∇ MakeCommon
      _PageData←⎕NS''
    ∇

    ∇ {r}←Render;b;styles
      :Access public
      ∘∘∘
      :If ''≢OnLoad
          Use'JQuery'
      :EndIf
      b←RenderBody
      styles←_Styles
      styles←styles,⍨{0∊⍴⍵:⍵ ⋄ ⊂⍵}_CssReset
      styles←styles,{0∊⍴⍵:⍵ ⋄ ⊂⍵}_CssOverride
      :If ~0∊⍴styles
          {(Head.Add _html.link).Set(('href=',⍵)('rel' 'stylesheet')('type' 'text/css'))}¨∪styles
      :EndIf
      :If ~0∊⍴_Scripts
          {(Head.Add _html.script).Set('src=',⍵)}¨∪_Scripts
      :EndIf
      :If ~0∊⍴Handlers
          b,←∊Handlers.Render
      :EndIf
      :If ''≢OnLoad
          b,←(⎕NEW #._html.script('$(function(){',OnLoad,'});')).Render
      :EndIf
      r←RenderPage b
      :If 0≠⎕NC⊂'_Request.Response'
          _Request.Response.HTML←r
      :EndIf
    ∇

    ∇ {r}←Wrap
      :Access public
      r←Render
    ∇

    ∇ Use resources;n;ind;t;x
      :Access public
      resources←eis resources
      :For x :In resources
          :If ~(⊂x)∊_used
              :Select ⊃x
              :Case '⍎' ⍝ script
                  _Scripts,←⊂1↓x
              :Case '⍕' ⍝ style sheet
                  _Styles,←⊂1↓x
              :Else
                  :If 0≠⎕NC⊂'_Request.Server.Config.Resources'
                  :AndIf ~0∊n←1↑⍴_Request.Server.Config.Resources
                      :If n≥ind←_Request.Server.Config.Resources[;1]⍳⊂x
                          :If ~0∊⍴t←{(~0∘∊∘⍴¨⍵)/⍵}(⊂ind 2)⊃_Request.Server.Config.Resources
                              _Scripts,←t
                          :EndIf
                          :If ~0∊⍴t←{(~0∘∊∘⍴¨⍵)/⍵}(⊂ind 3)⊃_Request.Server.Config.Resources
                              _Styles,←t
                          :EndIf
                      :Else
                          1 _Request.Server.Log _PageName,' references unknown resource: ',x
                      :EndIf
                  :EndIf
              :EndSelect
              _used,←⊂x
          :EndIf
      :EndFor
    ∇

    ∇ r←{proto}Get names
      :Access public
      proto←{6::⍵ ⋄ proto}''
      names←eis names
      names←,⍕names
      names←#.Strings.deb names
      :If ' '∊names
          names←{⎕ML←3 ⋄ ⍵⊂⍨⍵≠' '}names
          r←proto∘Get¨names
      :ElseIf 2≠_PageData.⎕NC names
          r←,proto
      :Else
          r←_PageData⍎names
          :If 2=≡r
              :If 1=⍴,r
                  r←⊃r
              :EndIf
          :EndIf
          r←#.JSON.toAPL r
⍝          :If ~isChar proto
⍝              r←{0::⍵ ⋄ 0∊⍴⍵:⍬ ⋄ w←⍵ ⋄ ((w='-')/w)←'¯' ⋄ ⊃(//)⎕VFI w}r
⍝          :EndIf
      :EndIf
    ∇

    ∇ r←{proto}GetRaw names
      :Access public
      proto←{6::⍵ ⋄ proto}''
      names←eis names
      names←,⍕names
      names←#.Strings.deb names
      :If ' '∊names
          names←{⎕ML←3 ⋄ ⍵⊂⍨⍵≠' '}names
          r←proto∘Get¨names
      :ElseIf 2≠_PageData.⎕NC names
          r←,proto
      :Else
          r←_PageData⍎names
          :If 2=≡r
              :If 1=⍴,r
                  r←⊃r
              :EndIf
          :EndIf
          :If ~isChar proto
              r←{0::⍵ ⋄ 0∊⍴⍵:⍬ ⋄ w←⍵ ⋄ ((w='-')/w)←'¯' ⋄ ⊃(//)⎕VFI w}r
          :EndIf
      :EndIf
    ∇

    ∇ r←{proto}SessionGet names
      :Access public
      proto←{6::⍵ ⋄ proto}''
      names←,⍕names
      names←#.Strings.deb names
      :If ' '∊names
          names←{⎕ML←3 ⋄ ⍵⊂⍨⍵≠' '}names
          r←proto∘SessionGet¨names
      :ElseIf 2≠_Request.Session.⎕NC names
          r←proto
      :Else
          r←_Request.Session⍎names
          :If 1<|≡r ⋄ r←∊r ⋄ :EndIf
          :If ~0 2∊⍨10|⎕DR proto
              r←{0∊⍴⍵:⍬ ⋄ w←⍵ ⋄ ((w='-')/w)←'¯' ⋄ ⊃(//)⎕VFI w}r
          :EndIf
      :EndIf
    ∇

    ∇ Close session ⍝ Called when the session ends
      :Access Public Overridable
    ∇

    :section APLJax  ⍝ used for building APLJAX responses
    ∇ _resetAjax
      :Access public
      _AjaxResponse←''
    ∇

    ∇ r←_id
      :Access public
      ⍝ as there seems to be a problem with at least some Syncfusion widgets
      ⍝ being able to provide the id (or name) of the triggering element, we try to obtain it from _what or _selector
      r←''
      :Trap 0
          :If 0∊⍴r←_what
          :AndIf '#'=⊃_selector
              r←1↓_selector
          :EndIf
      :EndTrap
    ∇

    ∇ Respond arg
      :Access public
      ∘∘∘
    ∇

    ∇ r←renderContent content;c
      r←''
      content←eis content
      :While ~0∊⍴content
          :Select ≡c←⊃content
          :Case 0
              :If isClass c
                  :Select ⊃⍴content
                  :Case 1
                      r,←(⎕NEW c).Render
                  :Case 2
                      r,←(⎕NEW c(2⊃content)).Render
                  :Else
                      r,←(⎕NEW c(1↓content)).Render
                  :EndSelect
              :ElseIf isInstance c
                  r,←c.Render
              :Else
                  r,←(⎕NEW #.HtmlElement(''content)).Render
              :EndIf
              content←''
          :Case 1
              :If isClass⊃c
                  r,←(⎕NEW(⊃c)(1↓c)).Render
              :ElseIf isInstance⊃c
                  ∘∘∘ ⍝ should not happen! (I think)
              :Else
                  r,←(⎕NEW #.HtmlElement(''c)).Render
              :EndIf
              content←1↓content
          :Else
              r,←renderContent c
              content←1↓content
          :EndSelect
      :EndWhile
    ∇

    ∇ r←selector Replace content
      :Access public
      r←⊂('replace'selector)('data'(renderContent content))
    ∇
    ∇ r←selector Append content
      :Access public
      r←⊂('append'selector)('data'(renderContent content))
    ∇
    ∇ r←selector Prepend content
      :Access public
      r←⊂('prepend'selector)('data'(renderContent content))
    ∇
    ∇ r←Execute content
      :Access public
      r←⊂('execute'content)
    ∇

    ∇ r←name Assign data
      :Access public
      r←⊂('assign'name)('data'data)
    ∇

    :endsection

    :section Position
    ∇ ref Position args;inds;mask;parameters;my;at;of;collision;within;q
      :Access public shared
      ⍝ ref  - a reference to an instance of anything based on HtmlElement
      ⍝ args - position information per jQueryUI's Position widget http://api.jqueryui.com/position/
      ⍝        can be in any of the following forms
      ⍝      1) positional (my at of collision within)  N.B. we don't use the "using" parameter
      ⍝         example:  myDiv Position 'left top' 'right bottom' '#otherElement'
      ⍝                   positions myDiv's top left corner at the bottom right corner of the element with id "otherElement"
      ⍝      2) paired
      ⍝                   myDiv Position 'my' 'left top' 'at' 'right bottom' 'of' '#otherElement'
      ⍝                   myDiv Position ('my' 'left top') ('at' 'right bottom') ('of' '#otherElement')
      ⍝                   myDiv Position 3 2⍴'my' 'left top' 'at' 'right bottom' 'of' '#otherElement'
      ⍝ Note: positional arguments are in form horizontal (left center right) vertical (top center bottom)

      parameters←'my' 'at' 'of' 'collision' 'within'
      q←{1⌽'''''',{⍵/⍨1+''''=⍵}⍕⍵}
      :If isInstance ref
          :If 2=⍴⍴args ⍝ matrix
              args←,args
          :ElseIf 3=≡args
              args←⊃,/args
          :EndIf
          args←eis args
          inds←parameters⍳args
          :If ∨/mask←inds≤⍴parameters
              :If mask≡(2×+/mask)⍴1 0
                  parameters←mask/args
                  args←(1⌽mask)/args
              :EndIf
          :Else
              parameters←(⍴args)↑parameters
          :EndIf
          parameters(ref{⍺⍺⍎'Position.',⍺,'←',q ⍵})¨args
          ref.Uses,←⊂'JQueryUI'
          ref.Use
      :EndIf
    ∇
    :endsection

    :section Event Handling Support
    ∇ r←isPost
      :Access public
      r←{0::0 ⋄ _Request.isPost}⍬
    ∇

    ∇ r←isAPLJax
      :Access public
      r←{0::0 ⋄ _Request.isAPLJAX}⍬
    ∇

    ∇ r←sel Css args ⍝ JQuery css cover
      :Access public
      r←(sel #._JSS.JQuery'css')args
    ∇

    ∇ r←sel Val args ⍝ JQuery val cover
      :Access public
      r←(sel #._JSS.JQuery'val')args
    ∇

    ∇ r←sel Attr args ⍝ JQuery attr cover
      :Access public
      r←(sel #._JSS.JQuery'attr')args
    ∇

    ∇ r←sel RemoveAttr args ⍝ JQuery removeAttr cover
      :Access public
      r←(sel #._JSS.JQuery'removeAttr')args
    ∇

    ∇ r←sel Html args ⍝ JQuery html cover
      :Access public
      r←(sel #._JSS.JQuery'html')args
    ∇

    :endsection

    ∇ Debug;⎕TRAP
      :Access public
      ⎕TRAP←0⍴⎕TRAP
      ∘∘∘
    ∇

:EndClass


MiPage.SessionGet fix

MiPage.SessionGet fix

:Class MiPage : #.HtmlPage

    ⍝∇:require =\HtmlPage.dyalog
    ⍝∇:require =\JSON.dyalog

    :Field Public _PageName←'' ⍝ Page file name
    :Field Public _PageDate←'' ⍝ Page saved date
    :field Public _Request     ⍝ HTTPRequest
    :field Public _Scripts←''
    :field Public _Styles←''
    :field Public _CssReset←''    ⍝ location of CSS Reset file (if any)
    :field Public _CssOverride←'' ⍝ location of CSS Override file (if any)
    :field Public _Serialized←1   ⍝ serialized forms to return in _PageData
    :field Public _event          ⍝ set by APLJAX callback - event that was triggered
    :field Public _what           ⍝ set by APLJAX callback - name or id of the triggering element
    :field Public _value          ⍝ set by APLJAX callback - value of the triggering element
    :field Public _selector       ⍝ set by APLJAX callback - CSS/jQuery selector for the element that triggered the event
    :field Public _callback       ⍝ set by APLJAX callback - name of the callback function
    :field Public _target         ⍝ set by APLJAX callback - id of the target element
    :field Public _currentTarget  ⍝ set by APLJAX callback - id of the currentTarget element
    :field Public _PageData       ⍝ namespace containing any data passed via forms or URL
    :field Public _AjaxResponse←''
    :field Public _DebugCallbacks←0
    :field Public _TimedOut←0
    :field Public _Sessioned←1    ⍝ by default save page instance in session
    :field Public _cache←''       ⍝ cached content if page is marked cacheable
    :field Public OnLoad←''       ⍝ page equivalent to ⎕LX
    :field Public Cacheable←0     ⍝ is the page cacheable?
    :field Public Charset←'UTF-8' ⍝ charset for page

    _used←'' ⍝ track what's been Use'd

    ∇ Make
      :Access public
      :Implements constructor :Base
      MakeCommon
    ∇

    ∇ Make1 req
      :Access public
      _Request←req
      :Implements constructor :base
      MakeCommon
    ∇

    ∇ MakeCommon
      _PageData←⎕NS''
    ∇

    ∇ {r}←Render;b;styles;_head;_body;_styles;_scripts;t;i
      :Access public
   ⍝  Capture the current Head and Body content so that we can reset it after rendering
   ⍝  This is so we can re-render and still get the same result

      (_head _body)←(Head Body).Content
      (_styles _scripts)←_Styles _Scripts

      :If ''≢OnLoad
          {0:: ⋄ Use'JQuery'}''
      :EndIf

      b←RenderBody

      :If ~0∊⍴_Scripts
          {(Insert _html.script).Set('src'⍵)}¨⌽∪_Scripts
      :EndIf

      styles←∪_Styles
      styles←styles,⍨{0∊⍴⍵:⍵ ⋄ ⊂⍵}_CssReset
      styles←styles,{0∊⍴⍵:⍵ ⋄ ⊂⍵}_CssOverride

      :If ~0∊⍴styles
          {Insert #._DC.StyleSheet ⍵}¨⌽∪styles
      :EndIf

      t←''
      :If ~0∊⍴Handlers
          t←,∊Handlers.Render
      :EndIf
      :If ~0∊⍴OnLoad
          t,←(⎕NEW #._html.script('$(function(){',OnLoad,'});')).Render
      :EndIf
      :If ~0∊⍴t
          :If '</body>'≡¯7↑b
              i←¯7
          :Else
              i←-6+⊃⍸'>ydob/<'⍷⌽b
          :EndIf
          b←(i↓b),t,i↑b
      :EndIf

      :If ''≢OnLoad

      :EndIf

      :If 0∊⍴⊃Attrs[⊂'lang'] ⍝ set the language for the page if not already set
          {0:: ⋄ {Set'lang="',⍵,'" xml:lang="',⍵,'" xmlns="http://www.w3.org/1999/xhtml"'}_Request.Server.Config.Lang}''
      :EndIf

      :If ~0∊⍴Charset
          Insert _html.meta''('charset="',Charset,'"')
      :EndIf

      r←RenderPage b

      :If 0≠⎕NC⊂'_Request.Response'
          _Request.Response.HTML←r
      :EndIf

      (Head Body).Content←_head _body
      _Styles←_styles
      _Scripts←_scripts
      _used←''
    ∇

    ∇ {r}←Wrap
      :Access public
      r←Render
      :If Cacheable ⋄ _cache←r ⋄ :EndIf
    ∇

    ∇ Use resources;n;ind;t;x;server
      :Access public
      resources←eis resources
      :For x :In resources
          :If ~(⊂x)∊_used
              :Select ⊃x
              :Case '⍎' ⍝ script
                  _Scripts,←⊂1↓x
              :Case '⍕' ⍝ style sheet
                  _Styles,←⊂1↓x
              :Else
                  :If 0≠⎕NC'_Request.Server'
                      server←_Request.Server
                  :ElseIf 0≠⎕NC'#.Boot.ms'
                      server←#.Boot.ms
                  :EndIf
                  :If 0≠server.⎕NC⊂'Config.Resources'
                  :AndIf ~0∊n←1↑⍴server.Config.Resources
                      :If n≥ind←server.Config.Resources[;1]⍳⊂x
                          :If ~0∊⍴t←{(~0∘∊∘⍴¨⍵)/⍵}(⊂ind 2)⊃server.Config.Resources
                              _Scripts,⍨←t
                          :EndIf
                          :If ~0∊⍴t←{(~0∘∊∘⍴¨⍵)/⍵}(⊂ind 3)⊃server.Config.Resources
                              _Styles,⍨←t
                          :EndIf
                      :Else
                          1 server.Log _PageName,' references unknown resource: ',x
                      :EndIf
                  :EndIf
              :EndSelect
              _used,←⊂x
          :EndIf
      :EndFor
    ∇

    ∇ r←{proto}Get names;noproto;char
      :Access public
      :If noproto←0=⎕NC'proto' ⋄ proto←'' ⋄ :EndIf
      names←eis names
      names←,⍕names
      names←#.Strings.deb names
      :If ' '∊names
          names←{⎕ML←3 ⋄ ⍵⊂⍨⍵≠' '}names
          r←({⍬∘⍴⍣(1=≢⍵)⊢⍵}eis proto)Get¨names
      :ElseIf ~(_PageData.⎕NC names)∊2 9
          r←,proto
      :Else
          r←_PageData⍎names
          :If 2≤≡r
              :If 1=⍴,r
                  r←⊃r
              :EndIf
          :EndIf
          :If noproto≥char←0=2|⎕DR proto
          :AndIf isString r
              r←#.JSON.toAPL r
          :EndIf
          :If noproto⍱char
              :If 1≠2|⎕DR r
                  r←,proto
              :EndIf
          :EndIf
      :EndIf
    ∇

    ∇ r←GetNames str
      :Access public
      →0⍴⍨0∊⍴r←_PageData.⎕NL-2 9
      →0⍴⍨0∊⍴str
      r←r/⍨r #.Strings.beginsWith¨⊂str
    ∇

    ∇ r←{proto}GetRaw names
      :Access public
      proto←{6::⍵ ⋄ proto}''
      names←eis names
      names←,⍕names
      names←#.Strings.deb names
      :If ' '∊names
          names←{⎕ML←3 ⋄ ⍵⊂⍨⍵≠' '}names
          r←proto∘Get¨names
      :ElseIf 2≠_PageData.⎕NC names
          r←,proto
      :Else
          r←_PageData⍎names
          :If 2=≡r
              :If 1=⍴,r
                  r←⊃r
              :EndIf
          :EndIf
          :If ~isChar proto
              r←{0::⍵ ⋄ 0∊⍴⍵:⍬ ⋄ w←⍵ ⋄ ((w='-')/w)←'¯' ⋄ ⊃(//)⎕VFI w}r
          :EndIf
      :EndIf
    ∇

    ∇ r←{proto}SessionGet names
      :Access public
      proto←{6::⍵ ⋄ proto}''
      names←,⍕names
      names←#.Strings.deb names
      :If ' '∊names
          names←{⎕ML←3 ⋄ ⍵⊂⍨⍵≠' '}names
          r←proto∘SessionGet¨names
      :ElseIf 0=_Request.⎕NC⊂'Session'
      :OrIf 0=_Request.Session.⎕NC names
          r←proto
      :Else
          r←_Request.Session⍎names
          :If 1<|≡r ⋄ r←∊r ⋄ :EndIf
          :If ~0 2∊⍨10|⎕DR proto  ⍝ if the prototype is numeric
          :AndIf 0 2∊⍨10|⎕DR r    ⍝ and the element is character
              r←{0∊⍴⍵:⍬ ⋄ w←⍵ ⋄ ((w='-')/w)←'¯' ⋄ ⊃(//)⎕VFI w}r
          :EndIf
      :EndIf
    ∇

    ∇ _Close session ⍝ Called when the session ends
    ⍝ this method is specific to #.SimpleSessions and is called when a session is terminated
      :Access Public Overridable
    ∇

    :section APLJax  ⍝ used for building APLJAX responses
    ∇ _resetAjax
      :Access public
      _AjaxResponse←''
    ∇

    ∇ r←_id
      :Access public
      ⍝ as there seems to be a problem with at least some Syncfusion widgets
      ⍝ being able to provide the id (or name) of the triggering element, we try to obtain it from _what or _selector
      r←''
      :Trap 0
          :If 0∊⍴r←_what
          :AndIf '#'=⊃_selector
              r←1↓_selector
          :EndIf
      :EndTrap
    ∇

    ∇ r←renderContent content;c
      :Access public shared
      r←''
      content←eis content
      :Trap 0
          :While ~0∊⍴content
              :Select ≡c←⊃content
              :Case 0
                  :If isClass c
                      :Select ⊃⍴content
                      :Case 1
                          r,←(⎕NEW c).Render
                      :Case 2
                          r,←(⎕NEW c(2⊃content)).Render
                      :Else
                          r,←(⎕NEW c(1↓content)).Render
                      :EndSelect
                  :ElseIf isInstance c
                      r,←c.Render
                  :Else
                      r,←(⎕NEW #.HtmlElement(''content)).Render
                  :EndIf
                  content←''
              :Case 1
                  :If isClass⊃c
                      r,←(⎕NEW(⊃c)(1↓c)).Render
                  :ElseIf isInstance⊃c
                      ∘∘∘ ⍝ should not happen! (I think)
                  :Else
                      r,←(⎕NEW #.HtmlElement(''c)).Render
                  :EndIf
                  content←1↓content
              :Else
                  r,←renderContent c
                  content←1↓content
              :EndSelect
          :EndWhile
      :Else
          :If (⎕EN≥100)∧(⎕EN≤999) ⍝ HTTP status rather than an APL error
          :AndIf 0≠⎕NC⊂'_Request.Response' ⍝ we're actually running a server, not rendering in session
              _Request.Fail ⎕EN
          :Else ⍝ APL errors and in-session errors are not trapped:
              ⎕SIGNAL ⎕DMX.(⊂{⍵(⍎⍵)}¨(⎕NL-⍳9)~'InternalLocation' 'DM' 'OSError') ⍝ re-signal
          :EndIf
      :EndTrap
    ∇

    ∇ r←selector Replace content
      :Access public shared
      r←⊂('replace'selector)('data'(renderContent content))
    ∇
    ∇ r←selector Append content
      :Access public shared
      r←⊂('append'selector)('data'(renderContent content))
    ∇
    ∇ r←selector Prepend content
      :Access public shared
      r←⊂('prepend'selector)('data'(renderContent content))
    ∇
    ∇ r←Execute content
      :Access public shared
      r←⊂('execute'(renderContent content))
    ∇

    ∇ r←name Assign data
      :Access public shared
      r←⊂('assign'name)('data'data)
    ∇

    :endsection

    :section Position

    ∇ ref Position args;inds;mask;parameters;my;at;of;collision;within;q
      :Access public
      ⍝ ref  - a reference to an instance of anything based on HtmlElement
      ⍝ args - position information per jQueryUI's Position widget http://api.jqueryui.com/position/
      ⍝        can be in any of the following forms
      ⍝      1) positional (my at of collision within)  N.B. we don't use the "using" parameter
      ⍝         example:  myDiv Position 'left top' 'right bottom' '#otherElement'
      ⍝                   positions myDiv's top left corner at the bottom right corner of the element with id "otherElement"
      ⍝      2) paired
      ⍝                   myDiv Position 'my' 'left top' 'at' 'right bottom' 'of' '#otherElement'
      ⍝                   myDiv Position ('my' 'left top') ('at' 'right bottom') ('of' '#otherElement')
      ⍝                   myDiv Position 3 2⍴'my' 'left top' 'at' 'right bottom' 'of' '#otherElement'
      ⍝ Note: positional arguments are in form horizontal (left center right) vertical (top center bottom)

      parameters←'my' 'at' 'of' 'collision' 'within'
      q←{1⌽'''''',{⍵/⍨1+''''=⍵}⍕⍵}
      :If isInstance ref
          :If 2=⍴⍴args ⍝ matrix
              args←,args
          :ElseIf 3=≡args
              args←⊃,/args
          :EndIf
          args←eis args
          inds←parameters⍳args
          :If ∨/mask←inds≤⍴parameters
              :If mask≡(2×+/mask)⍴1 0
                  parameters←mask/args
                  args←(1⌽mask)/args
              :EndIf
          :Else
              parameters←(⍴args)↑parameters
          :EndIf
          mask←⍬∘≢¨args
          args←mask/args
          parameters←mask/parameters
          parameters(ref{⍺⍺⍎'Position.',⍺,'←',q ⍵})¨args
          ref.Uses,←⊂'JQueryUI'
          SetUse
      :EndIf
    ∇
    :endsection

    :section Event Handling Support
    ∇ r←isPost
      :Access public
      r←{0::0 ⋄ _Request.isPost}⍬
    ∇

    ∇ r←isAPLJax
      :Access public
      r←{0::0 ⋄ _Request.isAPLJAX}⍬
    ∇

    ∇ r←sel Css args ⍝ JQuery css cover
      :Access public
      r←(sel #._JSS.JQuery'css')args
    ∇

    ∇ r←sel Val args ⍝ JQuery val cover
      :Access public
      r←(sel #._JSS.JQuery'val')args
    ∇

    ∇ r←sel Prop args ⍝ JQuery prop cover
      :Access public
      r←(sel #._JSS.JQuery'prop')args
    ∇

    ∇ r←sel Attr args ⍝ JQuery attr cover
      :Access public
      r←(sel #._JSS.JQuery'attr')args
    ∇

    ∇ r←sel RemoveAttr args ⍝ JQuery removeAttr cover
      :Access public
      r←(sel #._JSS.JQuery'removeAttr')args
    ∇

    ∇ r←sel Html args ⍝ JQuery html cover
      :Access public
      r←(sel #._JSS.JQuery'html')args
    ∇

    ∇ r←sel Show args ⍝ JQuery show cover
      :Access public
      r←(sel #._JSS.JQuery'show')args
    ∇

    ∇ r←sel Hide args ⍝ JQuery hide cover
      :Access public
      r←(sel #._JSS.JQuery'hide')args
    ∇

    ∇ r←sel Toggle args ⍝ JQuery toggle cover
      :Access public
      r←(sel #._JSS.JQuery'toggle')args
    ∇

    ∇ r←Submit sel ⍝ JQuery submit cover
      :Access public
      r←(sel #._JSS.JQuery'submit')''
    ∇

    :endsection

:EndClass

:Class MiPage : #.HtmlPage

    ⍝∇:require =\HtmlPage.dyalog
    ⍝∇:require =\JSON.dyalog

    :Field Public _PageName←'' ⍝ Page file name
    :Field Public _PageDate←'' ⍝ Page saved date
    :field Public _Request     ⍝ HTTPRequest
    :field Public _Scripts←''
    :field Public _Styles←''
    :field Public _CssReset←''    ⍝ location of CSS Reset file (if any)
    :field Public _CssOverride←'' ⍝ location of CSS Override file (if any)
    :field Public _Serialized←1   ⍝ serialized forms to return in _PageData
    :field Public _event          ⍝ set by APLJAX callback - event that was triggered
    :field Public _what           ⍝ set by APLJAX callback - name or id of the triggering element
    :field Public _value          ⍝ set by APLJAX callback - value of the triggering element
    :field Public _selector       ⍝ set by APLJAX callback - CSS/jQuery selector for the element that triggered the event
    :field Public _callback       ⍝ set by APLJAX callback - name of the callback function
    :field Public _target         ⍝ set by APLJAX callback - id of the target element
    :field Public _currentTarget  ⍝ set by APLJAX callback - id of the currentTarget element
    :field Public _PageData       ⍝ namespace containing any data passed via forms or URL
    :field Public _AjaxResponse←''
    :field Public _DebugCallbacks←0
    :field Public _TimedOut←0
    :field Public _Sessioned←1    ⍝ by default save page instance in session
    :field Public _cache←''       ⍝ cached content if page is marked cacheable
    :field Public OnLoad←''       ⍝ page equivalent to ⎕LX
    :field Public Cacheable←0     ⍝ is the page cacheable?
    :field Public Charset←'UTF-8' ⍝ charset for page

    _used←'' ⍝ track what's been Use'd

    ∇ Make
      :Access public
      :Implements constructor :Base
      MakeCommon
    ∇

    ∇ Make1 req
      :Access public
      _Request←req
      :Implements constructor :base
      MakeCommon
    ∇

    ∇ MakeCommon
      _PageData←⎕NS''
    ∇

    ∇ {r}←Render;b;styles;_head;_body;_styles;_scripts;t;i
      :Access public
   ⍝  Capture the current Head and Body content so that we can reset it after rendering
   ⍝  This is so we can re-render and still get the same result

      (_head _body)←(Head Body).Content
      (_styles _scripts)←_Styles _Scripts

      :If ''≢OnLoad
          {0:: ⋄ Use'JQuery'}''
      :EndIf

      b←RenderBody

      :If ~0∊⍴_Scripts
          {(Insert _html.script).Set('src'⍵)}¨⌽∪_Scripts
      :EndIf

      styles←∪_Styles
      styles←styles,⍨{0∊⍴⍵:⍵ ⋄ ⊂⍵}_CssReset
      styles←styles,{0∊⍴⍵:⍵ ⋄ ⊂⍵}_CssOverride

      :If ~0∊⍴styles
          {Insert #._DC.StyleSheet ⍵}¨⌽∪styles
      :EndIf

      t←''
      :If ~0∊⍴Handlers
          t←,∊Handlers.Render
      :EndIf
      :If ~0∊⍴OnLoad
          t,←(⎕NEW #._html.script('$(function(){',OnLoad,'});')).Render
      :EndIf
      :If ~0∊⍴t
          :If '</body>'≡¯7↑b
              i←¯7
          :Else
              i←-6+⊃⍸'>ydob/<'⍷⌽b
          :EndIf
          b←(i↓b),t,i↑b
      :EndIf

      :If ''≢OnLoad

      :EndIf

      :If 0∊⍴⊃Attrs[⊂'lang'] ⍝ set the language for the page if not already set
          {0:: ⋄ {Set'lang="',⍵,'" xml:lang="',⍵,'" xmlns="http://www.w3.org/1999/xhtml"'}_Request.Server.Config.Lang}''
      :EndIf

      :If ~0∊⍴Charset
          Insert _html.meta''('charset="',Charset,'"')
      :EndIf

      r←RenderPage b

      :If 0≠⎕NC⊂'_Request.Response'
          _Request.Response.HTML←r
      :EndIf

      (Head Body).Content←_head _body
      _Styles←_styles
      _Scripts←_scripts
      _used←''
    ∇

    ∇ {r}←Wrap
      :Access public
      r←Render
      :If Cacheable ⋄ _cache←r ⋄ :EndIf
    ∇

    ∇ Use resources;n;ind;t;x;server
      :Access public
      resources←eis resources
      :For x :In resources
          :If ~(⊂x)∊_used
              :Select ⊃x
              :Case '⍎' ⍝ script
                  _Scripts,←⊂1↓x
              :Case '⍕' ⍝ style sheet
                  _Styles,←⊂1↓x
              :Else
                  :If 0≠⎕NC'_Request.Server'
                      server←_Request.Server
                  :ElseIf 0≠⎕NC'#.Boot.ms'
                      server←#.Boot.ms
                  :EndIf
                  :If 0≠server.⎕NC⊂'Config.Resources'
                  :AndIf ~0∊n←1↑⍴server.Config.Resources
                      :If n≥ind←server.Config.Resources[;1]⍳⊂x
                          :If ~0∊⍴t←{(~0∘∊∘⍴¨⍵)/⍵}(⊂ind 2)⊃server.Config.Resources
                              _Scripts,⍨←t
                          :EndIf
                          :If ~0∊⍴t←{(~0∘∊∘⍴¨⍵)/⍵}(⊂ind 3)⊃server.Config.Resources
                              _Styles,⍨←t
                          :EndIf
                      :Else
                          1 server.Log _PageName,' references unknown resource: ',x
                      :EndIf
                  :EndIf
              :EndSelect
              _used,←⊂x
          :EndIf
      :EndFor
    ∇

    ∇ r←{proto}Get names;noproto;char
      :Access public
      :If noproto←0=⎕NC'proto' ⋄ proto←'' ⋄ :EndIf
      names←eis names
      names←,⍕names
      names←#.Strings.deb names
      :If ' '∊names
          names←{⎕ML←3 ⋄ ⍵⊂⍨⍵≠' '}names
          r←({⍬∘⍴⍣(1=≢⍵)⊢⍵}eis proto)Get¨names
      :ElseIf ~(_PageData.⎕NC names)∊2 9
          r←,proto
      :Else
          r←_PageData⍎names
          :If 2≤≡r
              :If 1=⍴,r
                  r←⊃r
              :EndIf
          :EndIf
          :If noproto≥char←0=2|⎕DR proto
          :AndIf isString r
              r←#.JSON.toAPL r
          :EndIf
          :If noproto⍱char
              :If 1≠2|⎕DR r
                  r←,proto
              :EndIf
          :EndIf
      :EndIf
    ∇

    ∇ r←GetNames str
      :Access public
      →0⍴⍨0∊⍴r←_PageData.⎕NL-2 9
      →0⍴⍨0∊⍴str
      r←r/⍨r #.Strings.beginsWith¨⊂str
    ∇

    ∇ r←{proto}GetRaw names
      :Access public
      proto←{6::⍵ ⋄ proto}''
      names←eis names
      names←,⍕names
      names←#.Strings.deb names
      :If ' '∊names
          names←{⎕ML←3 ⋄ ⍵⊂⍨⍵≠' '}names
          r←proto∘Get¨names
      :ElseIf 2≠_PageData.⎕NC names
          r←,proto
      :Else
          r←_PageData⍎names
          :If 2=≡r
              :If 1=⍴,r
                  r←⊃r
              :EndIf
          :EndIf
          :If ~isChar proto
              r←{0::⍵ ⋄ 0∊⍴⍵:⍬ ⋄ w←⍵ ⋄ ((w='-')/w)←'¯' ⋄ ⊃(//)⎕VFI w}r
          :EndIf
      :EndIf
    ∇

    ∇ r←{proto}SessionGet names
      :Access public
      proto←{6::⍵ ⋄ proto}''
      names←,⍕names
      names←#.Strings.deb names
      :If ' '∊names
          names←{⎕ML←3 ⋄ ⍵⊂⍨⍵≠' '}names
          r←proto∘SessionGet¨names
      :ElseIf 0=_Request.⎕NC'Session'
      :OrIf 0=_Request.Session.⎕NC names
          r←proto
      :Else
          r←_Request.Session⍎names
          :If 1<|≡r ⋄ r←∊r ⋄ :EndIf
          :If ~0 2∊⍨10|⎕DR proto  ⍝ if the prototype is numeric
          :AndIf 0 2∊⍨10|⎕DR r    ⍝ and the element is character
              r←{0∊⍴⍵:⍬ ⋄ w←⍵ ⋄ ((w='-')/w)←'¯' ⋄ ⊃(//)⎕VFI w}r
          :EndIf
      :EndIf
    ∇

    ∇ _Close session ⍝ Called when the session ends
    ⍝ this method is specific to #.SimpleSessions and is called when a session is terminated
      :Access Public Overridable
    ∇

    :section APLJax  ⍝ used for building APLJAX responses
    ∇ _resetAjax
      :Access public
      _AjaxResponse←''
    ∇

    ∇ r←_id
      :Access public
      ⍝ as there seems to be a problem with at least some Syncfusion widgets
      ⍝ being able to provide the id (or name) of the triggering element, we try to obtain it from _what or _selector
      r←''
      :Trap 0
          :If 0∊⍴r←_what
          :AndIf '#'=⊃_selector
              r←1↓_selector
          :EndIf
      :EndTrap
    ∇

    ∇ r←renderContent content;c
      :Access public shared
      r←''
      content←eis content
      :Trap 0
          :While ~0∊⍴content
              :Select ≡c←⊃content
              :Case 0
                  :If isClass c
                      :Select ⊃⍴content
                      :Case 1
                          r,←(⎕NEW c).Render
                      :Case 2
                          r,←(⎕NEW c(2⊃content)).Render
                      :Else
                          r,←(⎕NEW c(1↓content)).Render
                      :EndSelect
                  :ElseIf isInstance c
                      r,←c.Render
                  :Else
                      r,←(⎕NEW #.HtmlElement(''content)).Render
                  :EndIf
                  content←''
              :Case 1
                  :If isClass⊃c
                      r,←(⎕NEW(⊃c)(1↓c)).Render
                  :ElseIf isInstance⊃c
                      ∘∘∘ ⍝ should not happen! (I think)
                  :Else
                      r,←(⎕NEW #.HtmlElement(''c)).Render
                  :EndIf
                  content←1↓content
              :Else
                  r,←renderContent c
                  content←1↓content
              :EndSelect
          :EndWhile
      :Else
          :If (⎕EN≥100)∧(⎕EN≤999) ⍝ HTTP status rather than an APL error
          :AndIf 0≠⎕NC⊂'_Request.Response' ⍝ we're actually running a server, not rendering in session
              _Request.Fail ⎕EN
          :Else ⍝ APL errors and in-session errors are not trapped:
              ⎕SIGNAL ⎕DMX.(⊂{⍵(⍎⍵)}¨(⎕NL-⍳9)~'InternalLocation' 'DM' 'OSError') ⍝ re-signal
          :EndIf
      :EndTrap
    ∇

    ∇ r←selector Replace content
      :Access public shared
      r←⊂('replace'selector)('data'(renderContent content))
    ∇
    ∇ r←selector Append content
      :Access public shared
      r←⊂('append'selector)('data'(renderContent content))
    ∇
    ∇ r←selector Prepend content
      :Access public shared
      r←⊂('prepend'selector)('data'(renderContent content))
    ∇
    ∇ r←Execute content
      :Access public shared
      r←⊂('execute'(renderContent content))
    ∇

    ∇ r←name Assign data
      :Access public shared
      r←⊂('assign'name)('data'data)
    ∇

    :endsection

    :section Position

    ∇ ref Position args;inds;mask;parameters;my;at;of;collision;within;q
      :Access public
      ⍝ ref  - a reference to an instance of anything based on HtmlElement
      ⍝ args - position information per jQueryUI's Position widget http://api.jqueryui.com/position/
      ⍝        can be in any of the following forms
      ⍝      1) positional (my at of collision within)  N.B. we don't use the "using" parameter
      ⍝         example:  myDiv Position 'left top' 'right bottom' '#otherElement'
      ⍝                   positions myDiv's top left corner at the bottom right corner of the element with id "otherElement"
      ⍝      2) paired
      ⍝                   myDiv Position 'my' 'left top' 'at' 'right bottom' 'of' '#otherElement'
      ⍝                   myDiv Position ('my' 'left top') ('at' 'right bottom') ('of' '#otherElement')
      ⍝                   myDiv Position 3 2⍴'my' 'left top' 'at' 'right bottom' 'of' '#otherElement'
      ⍝ Note: positional arguments are in form horizontal (left center right) vertical (top center bottom)

      parameters←'my' 'at' 'of' 'collision' 'within'
      q←{1⌽'''''',{⍵/⍨1+''''=⍵}⍕⍵}
      :If isInstance ref
          :If 2=⍴⍴args ⍝ matrix
              args←,args
          :ElseIf 3=≡args
              args←⊃,/args
          :EndIf
          args←eis args
          inds←parameters⍳args
          :If ∨/mask←inds≤⍴parameters
              :If mask≡(2×+/mask)⍴1 0
                  parameters←mask/args
                  args←(1⌽mask)/args
              :EndIf
          :Else
              parameters←(⍴args)↑parameters
          :EndIf
          mask←⍬∘≢¨args
          args←mask/args
          parameters←mask/parameters
          parameters(ref{⍺⍺⍎'Position.',⍺,'←',q ⍵})¨args
          ref.Uses,←⊂'JQueryUI'
          SetUse
      :EndIf
    ∇
    :endsection

    :section Event Handling Support
    ∇ r←isPost
      :Access public
      r←{0::0 ⋄ _Request.isPost}⍬
    ∇

    ∇ r←isAPLJax
      :Access public
      r←{0::0 ⋄ _Request.isAPLJAX}⍬
    ∇

    ∇ r←sel Css args ⍝ JQuery css cover
      :Access public
      r←(sel #._JSS.JQuery'css')args
    ∇

    ∇ r←sel Val args ⍝ JQuery val cover
      :Access public
      r←(sel #._JSS.JQuery'val')args
    ∇

    ∇ r←sel Prop args ⍝ JQuery prop cover
      :Access public
      r←(sel #._JSS.JQuery'prop')args
    ∇

    ∇ r←sel Attr args ⍝ JQuery attr cover
      :Access public
      r←(sel #._JSS.JQuery'attr')args
    ∇

    ∇ r←sel RemoveAttr args ⍝ JQuery removeAttr cover
      :Access public
      r←(sel #._JSS.JQuery'removeAttr')args
    ∇

    ∇ r←sel Html args ⍝ JQuery html cover
      :Access public
      r←(sel #._JSS.JQuery'html')args
    ∇

    ∇ r←sel Show args ⍝ JQuery show cover
      :Access public
      r←(sel #._JSS.JQuery'show')args
    ∇

    ∇ r←sel Hide args ⍝ JQuery hide cover
      :Access public
      r←(sel #._JSS.JQuery'hide')args
    ∇

    ∇ r←sel Toggle args ⍝ JQuery toggle cover
      :Access public
      r←(sel #._JSS.JQuery'toggle')args
    ∇

    ∇ r←Submit sel ⍝ JQuery submit cover
      :Access public
      r←(sel #._JSS.JQuery'submit')''
    ∇

    :endsection

:EndClass