:Class WidgetDoc : MiPageTemplate

    ∇ Compose;ns;widget;doc;t;opts;og
      :Access public
      Add _.StyleSheet'/Styles/widgetDoc.css'
      (ns widget)←Get'namespace widget'
      :If 0∊⍴widget
          Add _.h3'Select widget'
          opts←'onchange="window.open(this.value,''this'');this.selectedIndex=0"'Add _.select
          'disabled=' 'value='opts.Add _.option'[Select widget]'
          :For ns :In '_DC' '_SF' '_JQ' '_html'
              og←('label'ns)opts.Add _.optgroup
              :For widget :In (⍎ns).⎕NL ¯9
                  ('value=?namespace=',ns,'&widget=',widget)og.Add _.option widget
              :EndFor
          :EndFor
      :Else
          doc←ns Document widget
          doc[;2]←{New _.pre ⍵}¨doc[;2]
          Add _.h3 ns,'.',widget
          (Add #._.Table doc).CellAttr←'class="widgetDoc"' 'class="widgetDocContent"'
      :EndIf
    ∇

    ∇ r←ns Document widget;ref;wref;src;mask;chunk;pv;c;c1;c2;samples;files
      :Access public shared
      r←''
      :If 9.1=#.⎕NC⊂ns
          ref←#.⍎ns
          :If 9=ref.⎕NC widget
              wref←ref⍎widget
              src←1↓⎕SRC wref
              src↓⍨←+/∧\''∘≡¨src
              src←#.Strings.dlb¨src
              src←src/⍨∧\'⍝'=⊃¨src
              src←HtmlSafeText¨#.Strings.dlb¨1↓¨src
              pv←∨/¨'::'∘⍷¨src
              r←0 2⍴⊂''
              :For chunk :In pv⊂src
                  c←⊃chunk
                  (c1 c2)←{⍵{(1,1↓<\⍵)⊂⍺}'::'⍷⍵}c
                  c2←#.Strings.deb 2↓c2
                  c2←c2{0∊⍴⍺:⍵ ⋄ 0∊⍴⍵:⊂⍺ ⋄ (⊂⍺),⍵}1↓chunk
                  c2←¯2↓∊c2,¨⊂⎕UCS 13 10
                  r⍪←c1 c2
              :EndFor
              :If 0≠wref.⎕NC⊂'DocBase'
                  r⍪←'Documentation'('target=_blank'New _.A(2⍴⊂wref.DocBase))
              :EndIf
              samples←'/Examples/',(ns~'_'),'/'
              :If ~0∊⍴files←1⌷[2]#.Files.List #.Boot.ms.Config.AppRoot,samples
              :AndIf ~0∊⍴files/⍨←∨/files∘.#.Strings.(beginsWith nocase)widget∘,¨'Simp' 'Adv'
                  r⍪←'Sample Pages'({'target=_blank'New _.A(2⍴⊂⍵)}¨samples∘,¨files)
              :EndIf
          :EndIf
      :EndIf
    ∇

:EndClass

:Class WidgetDoc : MiPageTemplate

    ∇ Compose;ns;widget;doc
      :Access public
      (ns widget)←Get'namespace widget'
      Add _.StyleSheet'/Styles/widgetDoc.css'
      doc←ns Document widget
      :Select doc
      :Case ¯1
          (Add _.h3('Namespace "',ns,'" not found.')).Style'color' 'red'
      :Case ¯2
          (Add _.h3('Widget "',widget,'" not found in namespace ',ns)).Style'color' 'red'
      :Else
          Add _.h3 ns,'.',widget
          :If 0∊⍴doc
              Add _.h4'No documentation found.'
          :Else
              doc[;2]←{New _.pre ⍵}¨doc[;2]
              (Add #._.Table doc).CellAttr←'class="widgetDoc"' 'class="widgetDocContent"'
          :EndIf
      :EndSelect
    ∇

    ∇ r←ns Document widget;ref;wref;src;mask;chunk;pv;c;c1;c2;samples;files
      :Access public shared
      r←¯1
      :If 9.1=#.⎕NC⊂ns
          ref←#.⍎ns
          r←¯2
          :If 9=ref.⎕NC widget
              wref←ref⍎widget
              src←1↓⎕SRC wref
              src↓⍨←+/∧\''∘≡¨src
              src←#.Strings.dlb¨src
              src←src/⍨∧\'⍝'=⊃¨src
              src←HtmlSafeText¨#.Strings.dlb¨1↓¨src
              pv←∨/¨'::'∘⍷¨src
              r←0 2⍴⊂''
              :For chunk :In pv⊂src
                  c←⊃chunk
                  (c1 c2)←{⍵{(1,1↓<\⍵)⊂⍺}'::'⍷⍵}c
                  c2←#.Strings.deb 2↓c2
                  c2←c2{0∊⍴⍺:⍵ ⋄ 0∊⍴⍵:⊂⍺ ⋄ (⊂⍺),⍵}1↓chunk
                  c2←¯2↓∊c2,¨⊂⎕UCS 13 10
                  r⍪←c1 c2
              :EndFor
              :If 0≠wref.⎕NC⊂'DocBase'
                  r⍪←'Documentation'('target=_blank'New _.A(2⍴⊂wref.DocBase))
              :EndIf
              samples←'/Examples/',(ns~'_'),'/'
              :If ~0∊⍴files←1⌷[2]#.Files.List #.Boot.ms.Config.AppRoot,samples
                  files/⍨←∨/files∘.#.Strings.(beginsWith nocase)widget∘,¨'Simp' 'Adv'
              :AndIf ~0∊⍴files
                  r⍪←'Sample Pages'({'target=_blank'New _.A(2⍴⊂⍵)}¨samples∘,¨files)
              :EndIf
          :EndIf
      :EndIf
    ∇

:EndClass

Revert "Resolve conflict"

Revert "Resolve conflict"

This reverts commit 58740171f4b5f40819b69972297295e7cf9330d4.


:class ejDigitalGauge : #._SF._ejWidget

⍝ Description:: Syncfusion Digital Gauge widget
⍝ Constructor:: [text [typeface]]
⍝ text       - text to render in the digital gauge
⍝ typeface   - typeface to use - choices are:
⍝        '7' - 7-segment
⍝       '14' - 14-segment
⍝       '16' - 16-segment
⍝    '88dot' - 8×8 dot matrix with round dots
⍝ '88square' - 8×8 dot matrix with square dots
⍝ seglength  - numeric segment length (default based on typeface)
⍝ segwidth   - numeric segment width (default based on typeface)
⍝
⍝ Public Fields::
⍝ Text - text to render in the digital gauge
⍝ Typeface   - typeface to use - choices are:
⍝        '7' - 7-segment
⍝       '14' - 14-segment
⍝       '16' - 16-segment (default)
⍝    '88dot' - 8×8 dot matrix with round dots
⍝ '88square' - 8×8 dot matrix with square dots
⍝ SegLength  - numeric segment length (default based on typeface)
⍝ SegWidth   - numeric segment width (default based on typeface)

    :field public shared readonly DocBase←'http://help.syncfusion.com/js/api/ejDigitalGauge.html'
    :field public shared readonly ApiLevel←3
    :field public shared readonly DocDyalog←'/Documentation/DyalogAPIs/Syncfusion/ejDigitalGauge.html'
    :field public shared readonly IntEvt←'init' 'itemRendering' 'load' 'renderComplete'
    :field public Text←''
    :field public Typeface←'16'
    :field public SegLength←⍬
    :field public SegWidth←⍬

    ∇ make
      :Access public
      JQueryFn←Uses←'ejDigitalGauge'
      :Implements constructor
      InternalEvents←IntEvt
    ∇

    ∇ make1 args
      :Access public
      JQueryFn←Uses←'ejDigitalGauge'
      :Implements constructor
      InternalEvents←IntEvt
      Text Typeface SegLength SegWidth←args defaultArgs Text Typeface SegLength SegWidth
    ∇

    ∇ r←Render;typeface;ind;text
      :Access public
      :If ~0∊⍴Text ⍝ if the user doesn't specify Text, then we assume he's setting everything himself manually
          'items[1].value'Set text←⍕,Text
          ind←((,'7')'14' '16' '88dot' '88square')⍳⊂,Typeface
          :If 0∊⍴SegLength
              SegLength←ind⊃10 10 10 3 3 10
          :EndIf
          :If 0∊⍴SegWidth
              SegWidth←ind⊃1 1 1 3 3 1
          :EndIf
          'items[1].characterSettings.type'SetIfNotSet ind⊃'sevensegment' 'fourteensegment' 'sixteensegment' 'eightcrosseightdotmatrix' 'eightcrosseightsquarematrix' 'sixteensegment'
          'items[1].segmentSettings.count'SetIfNotSet⊃⍴,text
          'items[1].segmentSettings.length'SetIfNotSet SegLength
          'items[1].segmentSettings.width'SetIfNotSet SegWidth
      :EndIf
      r←⎕BASE.Render
    ∇
:EndClass

:class ejDigitalGauge : #._SF._ejWidget

⍝ Description:: Syncfusion Digital Gauge widget
⍝ Constructor:: [text [typeface [spacing [seglength [segwidth]]]]]
⍝ text       - text to render in the digital gauge
⍝ typeface   - typeface to use - choices are:
⍝             '7' - 7-segment
⍝             '14' - 14-segment
⍝             '16' - 16-segment
⍝             '88dot' - 8×8 dot matrix with round dots
⍝             '88square' - 8×8 dot matrix with square dots
⍝ spacing    - spacing between characters
⍝ seglength  - numeric segment length (default based on typeface)
⍝ segwidth   - numeric segment width (default based on typeface)
⍝
⍝ Public Fields::
⍝ Text - text to render in the digital gauge
⍝ Typeface   - typeface to use - choices are:
⍝             '7' - 7-segment
⍝             '14' - 14-segment
⍝             '16' - 16-segment
⍝             '88dot' - 8×8 dot matrix with round dots
⍝             '88square' - 8×8 dot matrix with square dots
⍝ Spacing    - spacing between characters (default 4)
⍝ SegLength  - numeric segment length (default based on typeface)
⍝ SegWidth   - numeric segment width (default based on typeface)

    :field public shared readonly DocBase←'http://help.syncfusion.com/js/api/ejDigitalGauge.html'
    :field public shared readonly ApiLevel←3
    :field public shared readonly DocDyalog←'/Documentation/DyalogAPIs/Syncfusion/ejDigitalGauge.html'
    :field public shared readonly IntEvt←'init' 'itemRendering' 'load' 'renderComplete'
    :field public Text←''
    :field public Typeface←'16'
    :field public Spacing←4
    :field public SegLength←⍬
    :field public SegWidth←⍬

    ∇ make
      :Access public
      JQueryFn←Uses←'ejDigitalGauge'
      :Implements constructor
      InternalEvents←IntEvt
    ∇

    ∇ make1 args
      :Access public
      JQueryFn←Uses←'ejDigitalGauge'
      :Implements constructor
      InternalEvents←IntEvt
      Text Typeface Spacing SegLength SegWidth←args defaultArgs Text Typeface Spacing SegLength SegWidth
    ∇

    ∇ r←Render;typeface;ind;text
      :Access public
      :If ~0∊⍴Text ⍝ if the user doesn't specify Text, then we assume he's setting everything himself manually
          'items[1].value'Set text←⍕,Text
          ind←((,'7')'14' '16' '88dot' '88square')⍳⊂,Typeface
          :If 0∊⍴SegLength
              SegLength←ind⊃10 10 10 3 3 10
          :EndIf
          :If 0∊⍴SegWidth
              SegWidth←ind⊃1 1 1 3 3 1
          :EndIf
          'items[1].characterSettings.type'SetIfNotSet ind⊃'sevensegment' 'fourteensegment' 'sixteensegment' 'eightcrosseightdotmatrix' 'eightcrosseightsquarematrix' 'sixteensegment'
          'items[1].characterSettings.spacing'SetIfNotSet Spacing
          'items[1].segmentSettings.count'SetIfNotSet⊃⍴,text
          'items[1].segmentSettings.length'SetIfNotSet SegLength
          'items[1].segmentSettings.width'SetIfNotSet SegWidth
      :EndIf
      r←⎕BASE.Render
    ∇
:EndClass

update ejDigitalGauge - add character spacing


:class Select : #._html.select
⍝ Description:: Dyalog Enhanced HTML select
⍝ Constructor:: [options [[selected] [[disabled] [prompt]]]]
⍝ options   - vector of options or 2 column matrix of displayed[;1] and returned[;2] values
⍝ selected  - Boolean or integer array indicating pre-selected options(s)
⍝ disabled  - Boolean or integer array indicating disabled options(s)
⍝ prompt    - first item to display (has no value) (default '[Select]')
⍝
⍝ Public Fields::
⍝ Options   - vector of options or 2 column matrix of displayed[;1] and returned[;2] values
⍝ Selected  - Boolean or integer array indicating pre-selected options(s)
⍝ Disabled  - Boolean or integer array indicating disabled options(s)
⍝ Prompt      - first item to display (has no value) (default '[Select]')
⍝
⍝ Examples::
⍝ Select  ('Choice 1' 'Choice 2' 'Choice 3')
⍝ Select  (3 2⍴'One' 'c1' 'Two' 'c2' 'Three' 'c3')
⍝ Select ((3 2⍴'One' 'c1' 'Two' 'c2' 'Three' 'c3') 2) ⍝ second item is selected
⍝ Select ((3 2⍴'One' 'c1' 'Two' 'c2' 'Three' 'c3') (0 1 0)) ⍝ second item is selected
⍝ Select ((3 2⍴'One' 'c1' 'Two' 'c2' 'Three' 'c3') 2 3 'Pick One') ⍝ second item is selected, third item is disabled
⍝ Select ((3 2⍴'One' 'c1' 'Two' 'c2' 'Three' 'c3') (2 3) 1) ⍝ second and third items are selected, first item is disabled

    :field public Options←0 2⍴⊂''     ⍝ vector or matrix [;1] display, [;2] value
    :field public Selected←⍬          ⍝ either Boolean integer vector indicating
    :field public Prompt←'[Select]'   ⍝ character vector "Prompt" choice - the first choice on the list and does not have a value
    :field public Disabled←⍬          ⍝ either Boolean integer vector indicating

    ∇ make
      :Access public
      :Implements constructor
    ∇

    ∇ make1 args;attr
      :Access public
      :Implements constructor
      args←eis args
      :If (|≡args)∊0 1 2
      :AndIf ~0∊⍴⊃args
          args←,⊂args
      :EndIf
      (Options Selected Disabled Prompt)←args defaultArgs Options Selected Disabled Prompt
    ∇

    ∇ r←Render;opts;sel
      :Access public

      Content←opts←''
      SetInputName
      Add BuildOptions(Options Selected Disabled)

      r←⎕BASE.Render
    ∇

    ∇ r←BuildOptions(opts sel dis);v
      r←''
      :If ~0∊⍴opts
          opts←eis opts
          :If 1=⍴⍴opts
              opts←opts,⍪opts
          :EndIf
      :EndIf

      v←⍳⍬⍴⍴opts
      (sel dis)←v∘∊¨sel dis

      :If 1<+/sel                         ⍝ if we have multiple items selected
      :AndIf 0∊⍴⊃Attrs[⊂'multiple']       ⍝ and the multiple attribute is not set
          Attrs[⊂'multiple']←⊂'multiple'  ⍝ then set it
      :EndIf

      :If ~0∊⍴Prompt
      :AndIf 0∊⍴⊃Attrs[⊂'multiple']  ⍝ prompt makes no sense if multiple selections are allowed
          r,←('disabled="disabled" selected="selected"'New #._html.option Prompt).Render
      :EndIf

      r,←FormatOptions(opts sel dis)
    ∇

    ∇ r←FormatOptions(opts sel dis);o;s;d
      :Access Public Shared
      r←''
      :If 1=⍴⍴opts ⋄ opts←opts,⍪opts ⋄ :EndIf
      :For o s d :InEach (↓opts)sel dis
          r,←'<option',({⍵ ine' value="',(HtmlSafeText ⍵),'"'}2⊃o),(s/' selected="selected"'),(d/' disabled="disabled"'),'>',(1⊃o),'</option>'
      :EndFor
    ∇

    ∇ r←{selector}ReplaceOptions args;sel;opts;dis
⍝     Replaces select elements options - used by callback functions
⍝ Ex: r←Execute ReplaceOptions ('New Option 1' 'New Option 2') 1
⍝     arg = options [[selected] [disabled]]
      :Access public
      :If 0=⎕NC'selector' ⋄ selector←'#',id ⋄ :EndIf
      args←eis args
      :If (|≡args)∊0 1 2
      :AndIf ~0∊⍴⊃args
          args←,⊂args
      :EndIf
      (opts sel dis)←args defaultArgs Options ⍬ ⍬
      r←selector #.JQ.Replace BuildOptions(opts sel dis)
    ∇
:endclass

:class Select : #._html.select
⍝ Description:: Dyalog Enhanced HTML select
⍝ Constructor:: [options [[selected] [[disabled] [prompt]]]]
⍝ options   - vector of options or 2 column matrix of displayed[;1] and returned[;2] values
⍝ selected  - Boolean or integer array indicating pre-selected options(s)
⍝ disabled  - Boolean or integer array indicating disabled options(s)
⍝ prompt    - first item to display (has no value) (default '[Select]')
⍝
⍝ Public Fields::
⍝ Options   - vector of options or 2 column matrix of displayed[;1] and returned[;2] values
⍝ Selected  - Boolean or integer array indicating pre-selected options(s)
⍝ Disabled  - Boolean or integer array indicating disabled options(s)
⍝ Prompt      - first item to display (has no value) (default '[Select]')
⍝
⍝ Examples::
⍝ Select  ('Choice 1' 'Choice 2' 'Choice 3')
⍝ Select  (3 2⍴'One' 'c1' 'Two' 'c2' 'Three' 'c3')
⍝ Select ((3 2⍴'One' 'c1' 'Two' 'c2' 'Three' 'c3') 2) ⍝ second item is selected
⍝ Select ((3 2⍴'One' 'c1' 'Two' 'c2' 'Three' 'c3') (0 1 0)) ⍝ second item is selected
⍝ Select ((3 2⍴'One' 'c1' 'Two' 'c2' 'Three' 'c3') 2 3 'Pick One') ⍝ second item is selected, third item is disabled
⍝ Select ((3 2⍴'One' 'c1' 'Two' 'c2' 'Three' 'c3') (2 3) 1) ⍝ second and third items are selected, first item is disabled

    :field public Options←0 2⍴⊂''     ⍝ vector or matrix [;1] display, [;2] value
    :field public Selected←⍬          ⍝ either Boolean integer vector indicating
    :field public Prompt←'[Select]'   ⍝ character vector "Prompt" choice - the first choice on the list and does not have a value
    :field public Disabled←⍬          ⍝ either Boolean integer vector indicating

    ∇ make
      :Access public
      :Implements constructor
    ∇

    ∇ make1 args;attr
      :Access public
      :Implements constructor
      args←eis args
      :If (|≡args)∊0 1 2
      :AndIf ~0∊⍴⊃args
          args←,⊂args
      :EndIf
      (Options Selected Disabled Prompt)←args defaultArgs Options Selected Disabled Prompt
    ∇

    ∇ r←Render;opts;sel
      :Access public

      Content←opts←''
      SetInputName
      Add BuildOptions(Options Selected Disabled)

      r←⎕BASE.Render
    ∇

    ∇ r←BuildOptions(opts sel dis);v
      r←''
      :If ~0∊⍴opts
          opts←eis opts
          :If 1=⍴⍴opts
              opts←opts,⍪opts
          :EndIf
      :EndIf

      v←⍳⍬⍴⍴opts
      (sel dis)←v∘∊∘{∧/⍵∊0 1:⍵/⍳⍴⍵ ⋄ ⍵}∘,¨sel dis

      :If 1<+/sel                         ⍝ if we have multiple items selected
      :AndIf 0∊⍴⊃Attrs[⊂'multiple']       ⍝ and the multiple attribute is not set
          Attrs[⊂'multiple']←⊂'multiple'  ⍝ then set it
      :EndIf

      :If ~0∊⍴Prompt
      :AndIf 0∊⍴⊃Attrs[⊂'multiple']  ⍝ prompt makes no sense if multiple selections are allowed
          r,←('disabled="disabled" selected="selected"'New #._html.option Prompt).Render
      :EndIf

      r,←FormatOptions(opts sel dis)
    ∇

    ∇ r←FormatOptions(opts sel dis);o;s;d
      :Access Public Shared
      r←''
      :If 1=⍴⍴opts ⋄ opts←opts,⍪opts ⋄ :EndIf
      :For o s d :InEach (↓opts)sel dis
          r,←'<option',({⍵ ine' value="',(HtmlSafeText ⍵),'"'}2⊃o),(s/' selected="selected"'),(d/' disabled="disabled"'),'>',(1⊃o),'</option>'
      :EndFor
    ∇

    ∇ r←{selector}ReplaceOptions args;sel;opts;dis
⍝     Replaces select elements options - used by callback functions
⍝ Ex: r←Execute ReplaceOptions ('New Option 1' 'New Option 2') 1
⍝     arg = options [[selected] [disabled]]
      :Access public
      :If 0=⎕NC'selector' ⋄ selector←'#',id ⋄ :EndIf
      args←eis args
      :If (|≡args)∊0 1 2
      :AndIf ~0∊⍴⊃args
          args←,⊂args
      :EndIf
      (opts sel dis)←args defaultArgs Options ⍬ ⍬
      r←selector #.JQ.Replace BuildOptions(opts sel dis)
    ∇
:endclass

Fix Boolean option for _.Select.(Selected Disabled)


:Namespace SupportedHtml5Elements

 ⍝ this namespace is used to build the _html namespace containing definitions for all HTML5 elements
 ⍝ element names followed by '*' have no closing tag

    Elements←' a abbr acronym address area* article aside audio b base* bdi bdo big blockquote'
    Elements,←' body br* button canvas caption circle* cite code col* colgroup command datalist dd del'
    Elements,←' details dfn div dl dt ellipse* em embed* fieldset figcaption figure footer form'
    Elements,←' h1 h2 h3 h4 h5 h6 head header hgroup hr* html i iframe img* input* ins kbd keygen label'
    Elements,←' legend li line* link* map mark menu meta* meter nav noscript object ol optgroup option'
    Elements,←' output p param* path* polygon* polyline* pre progress q rect* rp rt ruby s samp script'
    Elements,←' section select small source* span strong style sub summary sup svg table tbody td'
    Elements,←' textarea tfoot th thead time title tr track tt u ul var video wbr'

    ∇ Build_html_namespace;e;def;noend;class;make;make1;make2;endclass;make1a;doc

      class←,⊂':Class ∆ : #.HtmlElement'
      doc←':field public shared readonly DocBase←''http://www.w3schools.com/tags/tag_∆.asp''' ':field public shared readonly DocDyalog←''/Documentation/DyalogAPIs/html5.html''' ':field public shared readonly APILevel←2'

      make←'∇make' ':Access Public' 'NoEndTag←⍺' ':Implements Constructor :Base ''∆''' '∇'
      make1←'∇make1 arg' ':Access Public' 'NoEndTag←⍺' ':Implements Constructor :Base ''∆'' arg' '∇'
      make1a←'∇make1 arg' ':Access Public' 'NoEndTag←⍺' ':Implements Constructor :Base ''∆'' '''' arg' '∇'
      make2←'∇make2 (content attr);a' ':Access Public' 'NoEndTag←⍺' 'a←(⊂''∆''),⊂⍣(isString a)⊢a←content attr' ':Implements Constructor :Base a' '∇'
      endclass←,⊂':EndClass'

      #._html.(⎕EX ⎕NL ¯9.4)  ⍝ erase all classes

      :For e :In {⎕ML←3 ⋄ ⍵⊂⍨⍵≠' '}Elements
          e↓⍨←-noend←'*'=¯1↑e
          #._html.⎕FIX⊃,/(⍕¨e noend)∘{((,¨'∆⍺')⎕R ⍺),¨⍵}¨(1 1 1,(noend⌽1 0),1 1)/class doc make make1 make1a make2 endclass
      :EndFor
    ∇

:EndNamespace

:Namespace SupportedHtml5Elements

 ⍝ this namespace is used to build the _html namespace containing definitions for all HTML5 elements
 ⍝ element names followed by '*' have no closing tag

    Elements←' a abbr acronym address area* article aside audio b base* bdi bdo big blockquote'
    Elements,←' body br* button canvas caption circle* cite code col* colgroup command datalist dd del'
    Elements,←' details dfn div dl dt ellipse* em embed* fieldset figcaption figure footer form'
    Elements,←' h1 h2 h3 h4 h5 h6 head header hgroup hr* html i iframe img* input* ins kbd keygen label'
    Elements,←' legend li line* link* map mark menu meta* meter nav noscript object ol optgroup option'
    Elements,←' output p param* path* polygon* polyline* pre progress q rect* rp rt ruby s samp script'
    Elements,←' section select small source* span strong style sub summary sup svg table tbody td'
    Elements,←' textarea tfoot th thead time title tr track tt u ul var video wbr'

    ∇ Build_html_namespace;e;def;noend;class;make;make1;make2;endclass;make1a;doc

      class←,⊂':Class ∆ : #.HtmlElement'
      doc←':field public shared readonly DocBase←''http://www.w3schools.com/tags/tag_∆.asp''' ':field public shared readonly DocDyalog←''/Documentation/DyalogAPIs/html5.html''' ':field public shared readonly APILevel←2'

      make←'∇make' ':Access Public' 'NoEndTag←⍺' ':Implements Constructor :Base (,''∆'')' '∇'
      make1←'∇make1 arg' ':Access Public' 'NoEndTag←⍺' ':Implements Constructor :Base (,''∆'') arg' '∇'
      make1a←'∇make1 arg' ':Access Public' 'NoEndTag←⍺' ':Implements Constructor :Base (,''∆'') '''' arg' '∇'
      make2←'∇make2 (content attr);a' ':Access Public' 'NoEndTag←⍺' 'a←(⊂,''∆''),⊂⍣(isString a)⊢a←content attr' ':Implements Constructor :Base a' '∇'
      endclass←,⊂':EndClass'

      #._html.(⎕EX ⎕NL ¯9.4)  ⍝ erase all classes

      :For e :In {⎕ML←3 ⋄ ⍵⊂⍨⍵≠' '}Elements
          e↓⍨←-noend←'*'=¯1↑e
          #._html.⎕FIX⊃,/(⍕¨e noend)∘{((,¨'∆⍺')⎕R ⍺),¨⍵}¨(1 1 1,(noend⌽1 0),1 1)/class doc make make1 make1a make2 endclass
      :EndFor
    ∇

:EndNamespace

make single-character-named HTML5 elements more tolerant of scalar content arguments


revert an accident change to demo.apl

[APL]
revert an accident change to demo.apl

git-svn-id: 6e74a02f85675cec270f5d931b0f6998666294a3@12645 d31e2699-5ff4-0310-a27c-f18f2fbe73fe


:Class ejDatePickerAdvanced : MiPageSample
⍝ Control:: _SF.ejDatePicker
⍝ Description:: Insert mutually interdependant calendars

⍝ Show 2 calendars to select reservation dates.
⍝ The first date cannot be before today and the second cannot be the
⍝ date before tomorrow. Its default is 1 week after check in.

    ∇ Compose;today;fromidn;minto;tbl;tr;td;head;todate;from
      :Access Public
      today←3↑⎕TS
      fromidn←dateToIDN today

      Add _.h1'Drop ↓ Inn'
      Add _.h2'Hotel reservation system'

    ⍝ The table header
      tbl←Add _.table
      head←tbl.Add _.thead
      (head.Add _.tr).{Add _.th ⍵}¨'Check in' 'Check out'

      tr←tbl.Add _.tr
    ⍝ The in date
      td←tr.Add _.td
      from←'in'td.Add _SF.ejDatePicker today'yyyy/MM/dd'
<<<<<<< HEAD
      from.Set⊂'minDate'(newDate today)
      from.On'change' 'setNewDate',⊂('in' 'model' 'value')('out' 'eval' '$("#out").ejDatePicker("model.value")')
=======
      from.Set'minDate'(newDate today)
      from.On'change' 'setNewDate'(('in' 'argument' 'value')('out' 'eval' '$("#out").ejDatePicker("model.value")'))
>>>>>>> 5ab62425095ccf15d890974e9c9cbf78695bbc72

    ⍝ The out date
      td←tr.Add _.td
      todate←IDNToDate fromidn+7
      TO←'out'td.Add _SF.ejDatePicker todate'yyyy/MM/dd'
      minto←newDate IDNToDate fromidn+1
      TO.Set⊂'minDate'minto
    ∇

    newDate←{'⍎new Date("',(⍕⍵),'")'}
    dateToIDN←{2 ⎕NQ'.' 'datetoidn'⍵}
    IDNToDate←{3↑ 2 ⎕NQ'.' 'idntodate'⍵}

    ∇ r←setNewDate;in;out
      :Access public
    ⍝ Reset minimum reservation check out date
      in←dateToIDN stringToDate⍕Get'in'
      r←'minDate'TO.Update newDate IDNToDate in+1

      out←dateToIDN stringToDate⍕Get'out'

    ⍝ If the new IN date is not before the OUT date we reset OUT to 1 week after
      :If in≥out
          r,←'value'TO.Update newDate IDNToDate in+7
      :EndIf
    ∇

    MONTHS←↓12 3⍴'JanFebMarAprMayJunJulAugSepOctNovDec'

    FI←{(b v)←⎕vfi ⍵ ⋄ b/v}

    ∇ ymd←stringToDate str;pos;mon;t
     ⍝ str is of the genre "Wed Aug 05 2015 00:00:00 GMT-0400 (Eastern Daylight Time)"
     ⍝ We need to weed out the day of the week and the time
      str←(+/∧\' '=str)↓str           ⍝ remove the leading spaces
      :If 0∊⍴t←MONTHS ⎕S 0 3⊢str      ⍝ look for the month as a string. If not found
          ymd←3↑FI str                ⍝ grab the 1st 3 numbers found
          ymd←ymd[⍒(2×31<ymd)+ymd<12] ⍝ put in correct order
      :Else                           ⍝ otherwise (if found)
          (pos mon)←0 1+1⊃t
          :If ~0∊⍴t←FI pos↑str        ⍝ any number before the month? (e.g. 2 May 2021)
              ymd←⌽⍣(31<⍬⍴t)⊢(1↑FI pos↓str),mon,t
          :Else
              ymd←¯1⌽mon,2↑FI pos↓str
          :EndIf
      :EndIf
    ∇

:EndClass

:Class ejDatePickerAdvanced : MiPageSample
⍝ Control:: _SF.ejDatePicker
⍝ Description:: Insert mutually interdependant calendars

⍝ Show 2 calendars to select reservation dates.
⍝ The first date cannot be before today and the second cannot be the
⍝ date before tomorrow. Its default is 1 week after check in.

    ∇ Compose;today;fromidn;minto;tbl;tr;td;head;todate;from
      :Access Public
      today←3↑⎕TS
      fromidn←dateToIDN today

      Add _.h1'Drop ↓ Inn'
      Add _.h2'Hotel reservation system'

    ⍝ The table header
      tbl←Add _.table
      head←tbl.Add _.thead
      (head.Add _.tr).{Add _.th ⍵}¨'Check in' 'Check out'

      tr←tbl.Add _.tr
    ⍝ The in date
      td←tr.Add _.td
      from←'in'td.Add _SF.ejDatePicker today'yyyy/MM/dd'

      from.Set⊂'minDate'(newDate today)
      from.On'change' 'setNewDate',⊂('in' 'model' 'value')('out' 'eval' '$("#out").ejDatePicker("model.value")')

    ⍝ The out date
      td←tr.Add _.td
      todate←IDNToDate fromidn+7
      TO←'out'td.Add _SF.ejDatePicker todate'yyyy/MM/dd'
      minto←newDate IDNToDate fromidn+1
      TO.Set⊂'minDate'minto
    ∇

    newDate←{'⍎new Date("',(⍕⍵),'")'}
    dateToIDN←{2 ⎕NQ'.' 'datetoidn'⍵}
    IDNToDate←{3↑ 2 ⎕NQ'.' 'idntodate'⍵}

    ∇ r←setNewDate;in;out
      :Access public
    ⍝ Reset minimum reservation check out date
      in←dateToIDN stringToDate⍕Get'in'
      r←'minDate'TO.Update newDate IDNToDate in+1

      out←dateToIDN stringToDate⍕Get'out'

    ⍝ If the new IN date is not before the OUT date we reset OUT to 1 week after
      :If in≥out
          r,←'value'TO.Update newDate IDNToDate in+7
      :EndIf
    ∇

    MONTHS←↓12 3⍴'JanFebMarAprMayJunJulAugSepOctNovDec'

    FI←{(b v)←⎕vfi ⍵ ⋄ b/v}

    ∇ ymd←stringToDate str;pos;mon;t
     ⍝ str is of the genre "Wed Aug 05 2015 00:00:00 GMT-0400 (Eastern Daylight Time)"
     ⍝ We need to weed out the day of the week and the time
      str←(+/∧\' '=str)↓str           ⍝ remove the leading spaces
      :If 0∊⍴t←MONTHS ⎕S 0 3⊢str      ⍝ look for the month as a string. If not found
          ymd←3↑FI str                ⍝ grab the 1st 3 numbers found
          ymd←ymd[⍒(2×31<ymd)+ymd<12] ⍝ put in correct order
      :Else                           ⍝ otherwise (if found)
          (pos mon)←0 1+1⊃t
          :If ~0∊⍴t←FI pos↑str        ⍝ any number before the month? (e.g. 2 May 2021)
              ymd←⌽⍣(31<⍬⍴t)⊢(1↑FI pos↓str),mon,t
          :Else
              ymd←¯1⌽mon,2↑FI pos↓str
          :EndIf
      :EndIf
    ∇

:EndClass

Fix ejDatePickerAdvanced merge problem

Fix ejDatePickerAdvanced merge problem


 msg←SelectAdvanced;result;output;sel;froot;prev
⍝ Test /Examples/DC/SelectAdvanced

⍝ Ensure 'multi' (the selection list) is there:
 msg←'selection list not there'
 :If 0≢sel←Find'multi'
   ⍝ Grab the 2 elements already chosen:
     Click'PressMe'
     output←Find'output'
     {0≠⍴output.Text}Retry ⍬ ⍝ Wait to see if it gets populated
     msg←'Expected output was not produced.'
 :AndIf 'You picked: Bananas Pears'≡prev←output.Text
   ⍝ Make a single selection:
     froot←'Grapes'
    'multi'SelectByText'-'froot
         Click'PressMe'
     output←Find'output'
     {prev≢output.Text}Retry ⍬ ⍝ Wait to see if it gets populated
:AndIf (prev←output.Text)≡'You picked: ',froot
   ⍝ Make another selection:
    'multi'SelectByText'Pears'
         Click'PressMe'
     output←Find'output'
     {prev≢output.Text}Retry ⍬ ⍝ Wait to see if it gets populated
    :AndIf (prev←output.Text)≡'You picked: ',froot,' Pears'
    msg←''
 :EndIf

 msg←SelectAdvanced;result;output;sel;froot;prev
⍝ Test /Examples/DC/SelectAdvanced

⍝ Ensure 'multi' (the selection list) is there:
 msg←'selection list not there'
 :If 0≢sel←Find'multi'
   ⍝ Grab the 2 elements already chosen:
     Click'PressMe'
     output←Find'output'
     {0≠⍴output.Text}Retry ⍬ ⍝ Wait to see if it gets populated
     msg←'Expected output was not produced.'
 :AndIf 'You picked: Bananas Pears'≡prev←output.Text
   ⍝ Make a single selection:
     froot←'Grapes'
     'multi'SelectItemText'~'froot
     Click'PressMe'
     output←Find'output'
     {prev≢output.Text}Retry ⍬ ⍝ Wait to see if it gets populated
 :AndIf (prev←output.Text)≡'You picked: ',froot
   ⍝ Make another selection:
     'multi'SelectItemText'Pears'
     Click'PressMe'
     output←Find'output'
     {prev≢output.Text}Retry ⍬ ⍝ Wait to see if it gets populated
 :AndIf (prev←output.Text)≡'You picked: ',froot,' Pears'
     msg←''
 :EndIf

Rename of SelectByText to SelectItemText


:Class Page : #.MiPage

⍝ Class to be used with HTMLRenderer (Dyalog v16 and later)

    :field public _Renderer←''
    :field public _Url←''
    :field public _Interactive←0
    :field public _CallbackFn←'Callback'
    :field public _Config
    :field public _Request
    :field public _Args
    :field public Props
    :field public Coord←'ScaledPixel'
    :field public Size←⍬ ⍬
    :field public ReadOnly NL←⎕UCS 10
    :field public shared APLVersion←{⊃(//)⎕VFI ⍵/⍨2>+\'.'=⍵}2⊃#.⎕WG 'APLVersion'

    begins←{⍺≡(⍴⍺)↑⍵}

    ∇ make
      :Access public
      :Implements constructor
      ⎕SIGNAL makeCommon
    ∇

    ∇ make1 arg
        ⍝ args are: [1] HTML content [2] URL
      :Access public
      :Implements constructor
      arg←,⊆arg
      (content _Url)←2↑arg,(⍴arg)↓'' ''
      :If ~0∊⍴content ⋄ Add content ⋄ :EndIf
      ⎕SIGNAL makeCommon
    ∇

    ∇ r←makeCommon
      →0↓⍨0∊⍴r←(17>APLVersion)/⊂('EN' 11)('Message' 'Dyalog v17.0 or later is required to use HTMLRenderer-based features')
      Props←⎕NS''
      _Config←#.Boot.ms.Config
      _PageName←3⊃⎕SI,⊂'WC2Page'
    ∇

    ∇ Close
      :Implements destructor
      :Trap 0
          2 ⎕NQ _Renderer'Close'
      :EndTrap
    ∇

    ∇ Run
      :Access public
      :If 0∊⍴_Renderer
          run&0
      :Else
          Reset
          Render
      :EndIf
    ∇

    ∇ Reset
      :Access public
      Body.Content←''
      Head.Content←''
    ∇

    ∇ run arg
      :Access public
      _Renderer←⎕NEW'HTMLRenderer'(('Coord'Coord)('Size'Size)('Event'('onHTTPRequest' '__CallbackFn'))('URL'_PageName)('InterceptedURLs'(1 2⍴'*' 1)))
      :If ~0∊⍴props←_Renderer.PropList∩Props.⎕NL ¯2
          {_Renderer⍎⍺,'←⍵'}/¨{⍵(Props⍎⍵)}¨props
      :EndIf
      _Renderer.Wait
    ∇

    ∇ Render
      :Access public
      _Renderer.HTML←⎕BASE.Render
    ∇

    ∇ {r}←{args}Add content
      :Access public
      :If 0=⎕NC'args' ⋄ args←⊢ ⋄ :EndIf
      r←args ⎕BASE.Add content
    ∇

    ∇ {r}←{args}New content
      :Access public
      :If 0=⎕NC'args' ⋄ args←⊢ ⋄ :EndIf
      r←args ⎕BASE.New content
    ∇

    ∇ r←__CallbackFn args;ext;mimeType;filename;url;mask;cbdata;request;int;handler;content
      :Access public
      r←args
      →0⍴⍨0∊⍴8⊃args
      request←⎕NEW #.HtmlRenderRequest(args(819⌶_PageName))
      :If 0∊⍴request.Page ⍝ initialization
          r[4 5 6 7]←1 200 'OK' 'text/html'
          r[10]←⊂UnicodeToHtml ⎕BASE.Render
          r[9]←⊂NL,⍨∊NL,⍨¨('Content-Type: ',7⊃r)('Content-Length: ',⍕≢10⊃r)
      :ElseIf ~0∊⍴ext←(819⌶)1↓⊃¯1↑1 ⎕NPARTS request.Page  ⍝ !!!need to handle case where another MiPage is requested
          :If #.Files.Exists filename←∊1 ⎕NPARTS _Config #.MiServer.Virtual request.Page
              :If ' '∨.≠handler←⊃_Config.MappingHandlers.handler/⍨<\_Config.MappingHandlers.ext≡¨⊂'.',ext
                  (mimeType content)←⍎'filename #.MappingHandlers.',handler,' request'
              :Else
                  mimeType←#.Boot.ms.Config.ContentTypes tableLookup ext
                  content←{{(⎕NUNTIE ⍵)⊢⎕NREAD ⍵,(⎕DR' '),¯1}⍵ ⎕NTIE 0}filename
              :EndIf
              r[7]←mimeType
              r[4 5 6]←1 200 'OK'
              r[9]←⊂NL,⍨∊NL,⍨¨'Content-Type: ' 'Content-Length: ',¨⍕¨mimeType(≢content)
              r[10]←⊂content
          :Else
              r[4 5 6 7]←1 404 'NOT FOUND' ''
              r[9 10]←⊂''
          :EndIf
      :ElseIf request.isAPLJax
          _Args←args
          _Request←request
          ⎕THIS #.MiServer.MoveRequestData _Request
          _what←_Request.GetData'_what'
          _event←_Request.GetData'_event'
          _value←_Request.GetData'_value'
          _selector←_Request.GetData'_selector'
          _target←_Request.GetData'_target'
          _currentTarget←_Request.GetData'_currentTarget'
          _callback←_Request.GetData'_callback'

          :If _CallbackFn≢'Callback'
              r←⍎'_Args ',_CallbackFn,' _Request'  ⍝ did you specify your own HTMLRenderer callback function?
          :Else
              cbdata←Callback
              r[10]←⊂UnicodeToHtml #.JSON.toAPLJAX cbdata ⍝ we expect an APLJAX-style response
              r[4 5 6 7]←1 200 'OK' 'application/json'
              r[9]←⊂NL,⍨∊NL,⍨¨'Content-Type: ' 'Content-Length: ',¨⍕¨'application/json'(≢10⊃r)
          :EndIf
      :EndIf
      r[9]←⊂(⎕UCS 32)~⍨9⊃r
    ∇

    ∇ r←Callback;_context;_found;_valence
      :Access public overridable
      r←''
      :If ''≢_callback
          _context←''
          :While ~_found←3=⎕NC _context,_callback
              :If ~0∊⍴_context
                  :If (,'#')≡⍕⍎_context ⍝ popped up to root and still not found?
                      :Leave
                  :EndIf
              :EndIf
              _context,←'##.'
          :EndWhile
          :If _found
              _valence←|1 2⊃⎕AT _context,_callback
              r←⍎('_Args '/⍨_valence=2),_context,_callback,' _Request'/⍨_valence>0
          :Else
              ⎕←'Callback function not found: ',_callback
          :EndIf
      :EndIf
    ∇

    ∇ r←UnicodeToHtml txt;u;ucs
      :Access public shared
    ⍝ converts chars ⎕UCS >127 to HTML safe format
      r←,⍕txt
      u←127<ucs←⎕UCS r
      (u/r)←(~∘' ')¨↓'G<&#ZZZ9;>'⎕FMT u/ucs
      r←∊r
    ∇

    tableLookup←{(⍺[;2],⊂'')[⍺[;1]⍳⊆,⍵]}

:EndClass

:Class Page : #.MiPage

⍝ Class to be used with HTMLRenderer (Dyalog v16 and later)

    :field public _Renderer←''
    :field public _Url←''
    :field public _Interactive←0
    :field public _CallbackFn←'Callback'
    :field public _Config
    :field public _Request
    :field public _Args
    :field public Props
    :field public Coord←'ScaledPixel'
    :field public Size←⍬ ⍬
    :field public ReadOnly NL←⎕UCS 10
    :field public shared APLVersion←{⊃(//)⎕VFI ⍵/⍨2>+\'.'=⍵}2⊃#.⎕WG 'APLVersion'

    begins←{⍺≡(⍴⍺)↑⍵}

    ∇ make
      :Access public
      :Implements constructor
      ⎕SIGNAL makeCommon
    ∇

    ∇ make1 arg
        ⍝ args are: [1] HTML content [2] URL
      :Access public
      :Implements constructor
      arg←,⊆arg
      (content _Url)←2↑arg,(⍴arg)↓'' ''
      :If ~0∊⍴content ⋄ Add content ⋄ :EndIf
      ⎕SIGNAL makeCommon
    ∇

    ∇ r←makeCommon
      →0↓⍨0∊⍴r←(17>APLVersion)/⊂('EN' 11)('Message' 'Dyalog v17.0 or later is required to use HTMLRenderer-based features')
      Props←⎕NS''
      _Config←#.Boot.ms.Config
      _PageName←3⊃⎕SI,⊂'WC2Page'
    ∇

    ∇ Close
      :Implements destructor
      :Trap 0
          2 ⎕NQ _Renderer'Close'
      :EndTrap
    ∇

    ∇ Run
      :Access public
      :If 0∊⍴_Renderer
          run&0
      :Else
          Reset
          Show
      :EndIf
    ∇

    ∇ Reset
      :Access public
      Body.Content←''
      Head.Content←''
    ∇

    ∇ run arg
      :Access public
      _Renderer←⎕NEW'HTMLRenderer'(('Coord'Coord)('Size'Size)('Event'('onHTTPRequest' '__CallbackFn'))('URL'_PageName)('InterceptedURLs'(1 2⍴'*' 1)))
      :If ~0∊⍴props←_Renderer.PropList∩Props.⎕NL ¯2
          {_Renderer⍎⍺,'←⍵'}/¨{⍵(Props⍎⍵)}¨props
      :EndIf
      _Renderer.Wait
    ∇

    ∇ r←Render
      :Access public
      r←⎕BASE.Render
    ∇

    ∇ Show
      :Access public
      _Renderer.HTML←Render
    ∇

    ∇ {r}←{args}Add content
      :Access public
      :If 0=⎕NC'args' ⋄ args←⊢ ⋄ :EndIf
      r←args ⎕BASE.Add content
    ∇

    ∇ {r}←{args}New content
      :Access public
      :If 0=⎕NC'args' ⋄ args←⊢ ⋄ :EndIf
      r←args ⎕BASE.New content
    ∇

    ∇ r←__CallbackFn args;ext;mimeType;filename;url;mask;cbdata;request;int;handler;content
      :Access public
      r←args
      →0⍴⍨0∊⍴8⊃args
      request←⎕NEW #.HtmlRenderRequest(args(819⌶_PageName))
      :If 0∊⍴request.Page ⍝ initialization
          r[4 5 6 7]←1 200 'OK' 'text/html'
          r[10]←⊂UnicodeToHtml Render
          r[9]←⊂NL,⍨∊NL,⍨¨('Content-Type: ',7⊃r)('Content-Length: ',⍕≢10⊃r)
      :ElseIf ~0∊⍴ext←(819⌶)1↓⊃¯1↑1 ⎕NPARTS request.Page  ⍝ !!!need to handle case where another MiPage is requested
          :If #.Files.Exists filename←∊1 ⎕NPARTS _Config #.MiServer.Virtual request.Page
              :If ' '∨.≠handler←⊃_Config.MappingHandlers.handler/⍨<\_Config.MappingHandlers.ext≡¨⊂'.',ext
                  (mimeType content)←⍎'filename #.MappingHandlers.',handler,' request'
              :Else
                  mimeType←#.Boot.ms.Config.ContentTypes tableLookup ext
                  content←{{(⎕NUNTIE ⍵)⊢⎕NREAD ⍵,(⎕DR' '),¯1}⍵ ⎕NTIE 0}filename
              :EndIf
              r[7]←mimeType
              r[4 5 6]←1 200 'OK'
              r[9]←⊂NL,⍨∊NL,⍨¨'Content-Type: ' 'Content-Length: ',¨⍕¨mimeType(≢content)
              r[10]←⊂content
          :Else
              r[4 5 6 7]←1 404 'NOT FOUND' ''
              r[9 10]←⊂''
          :EndIf
      :ElseIf request.isAPLJax
          _Args←args
          _Request←request
          ⎕THIS #.MiServer.MoveRequestData _Request
          _what←_Request.GetData'_what'
          _event←_Request.GetData'_event'
          _value←_Request.GetData'_value'
          _selector←_Request.GetData'_selector'
          _target←_Request.GetData'_target'
          _currentTarget←_Request.GetData'_currentTarget'
          _callback←_Request.GetData'_callback'

          :If _CallbackFn≢'Callback'
              r←⍎'_Args ',_CallbackFn,' _Request'  ⍝ did you specify your own HTMLRenderer callback function?
          :Else
              cbdata←Callback
              r[10]←⊂UnicodeToHtml #.JSON.toAPLJAX cbdata ⍝ we expect an APLJAX-style response
              r[4 5 6 7]←1 200 'OK' 'application/json'
              r[9]←⊂NL,⍨∊NL,⍨¨'Content-Type: ' 'Content-Length: ',¨⍕¨'application/json'(≢10⊃r)
          :EndIf
      :EndIf
      r[9]←⊂(⎕UCS 32)~⍨9⊃r
    ∇

    ∇ r←Callback;_context;_found;_valence
      :Access public overridable
      r←''
      :If ''≢_callback
          _context←''
          :While ~_found←3=⎕NC _context,_callback
              :If ~0∊⍴_context
                  :If (,'#')≡⍕⍎_context ⍝ popped up to root and still not found?
                      :Leave
                  :EndIf
              :EndIf
              _context,←'##.'
          :EndWhile
          :If _found
              _valence←|1 2⊃⎕AT _context,_callback
              r←⍎('_Args '/⍨_valence=2),_context,_callback,' _Request'/⍨_valence>0
          :Else
              ⎕←'Callback function not found: ',_callback
          :EndIf
      :EndIf
    ∇

    ∇ r←UnicodeToHtml txt;u;ucs
      :Access public shared
    ⍝ converts chars ⎕UCS >127 to HTML safe format
      r←,⍕txt
      u←127<ucs←⎕UCS r
      (u/r)←(~∘' ')¨↓'G<&#ZZZ9;>'⎕FMT u/ucs
      r←∊r
    ∇

    tableLookup←{(⍺[;2],⊂'')[⍺[;1]⍳⊆,⍵]}

:EndClass

Make Page.Render return rendered HTML, add Show method to show rendered HTML in HTMLRenderer


$dot ← {
  WA ← (1↓⍴⍵),⍴⍺
  KA ← (⊃⍴⍴⍺)-1
  VA ← ⍳ ⊃ ⍴WA
  ZA ← (KA⌽¯1↓VA),¯1↑VA
  TA ← ZA⍉WA⍴⍺    ⍝ Replicate, transpose
  WB ← (¯1↓⍴⍺),⍴⍵
  KB ← ⊃ ⍴⍴⍺
  VB ← ⍳ ⊃ ⍴WB
  ZB0 ← (-KB) ↓ KB ⌽ ⍳(⊃⍴VB)
  ZB ← (¯1↓(⍳ KB)),ZB0,KB
  TB ← ZB⍉WB⍴⍵    ⍝ Replicate, transpose
  ⍺⍺ / TA ⍵⍵ TB   ⍝ Compute the result
}

$out ← {
  A ← ⍺
  B ← ⍵
  T ← (⊃(⍴⍴A))⌽⍳⊃⍴(⍴B),⍴A
  x ← T ⍉ ((⍴B),(⍴A)) ⍴ A
  y ← ((⍴A),(⍴B)) ⍴ B
  x ⍺⍺ y
}

$slashbar ← {
  ⍉ ⍺⍺ / ⍉ ⍵
}

$log ← {
  ⍝ Dyadic logarithm
  (⍟⍵)÷⍟⍺
}

ReadCSVDouble ← ⎕ReadDoubleVecFile
ReadCSVInt ← ⎕ReadIntVecFile
xor ← ⎕INT32XOR
and ← ⎕INT32AND
sll ← ⎕INT32SHL
srl ← ⎕INT32SHR
testBit ← { 0≠⍵ and 1 sll (⍺-1) }

Add file reading and bitwise operations to TAIL-prelude


:Namespace _HTML

  :class Form : #._html.form

    :field public Method←'post'
    :field public Action←''
    :field public Serialize←0

    ∇ make;c
      :Access public
      :Implements constructor
      :If {6::0 ⋄ ''≢c∘←##.context ⍵}'_Request'
        Action←c._Request.Page
      :EndIf
    ∇

    ∇ make1 action
      :Access public
      :Implements constructor
      Action←action
    ∇

    ∇ r←Render
      :Access public
      Attr['action' 'method']←Action Method
      r←⎕BASE.Render
    ∇
  :endclass

  :class InputSubmit : #._html.input

    ∇ Make
      :Access public
      :Implements constructor :base
      (name value)←'submit' 'submit'
      SetAttr('type' 'submit')
    ∇

    ∇ Make1 args;n;v
      :Access public
      :Implements constructor :base
      args←eis args
      (n v)←2↑args,(⍴args)↓'submit' 'submit'
      (name value)←n v
      SetAttr('type' 'submit')
    ∇
  :endclass

  :class Input : #._html.input

    :field public Label←''

    ∇ Make1 args;l;n;t;v
      :Access public
      :Implements constructor
      args←eis args
      t n v l←4↑args,(⍴args)↓'text' '' '' ''
      (type value Label)←t v l
      :If ~0∊⍴n ⋄ name←id←n ⋄ :EndIf
    ∇

    ∇ html←Render
      :Access public
      html←''
      :If ~0∊⍴Label
        :If id≡⎕NULL ⋄ id←'gen',⍕?1000 ⋄ :EndIf
        html,←'<label for="',(⍕id),'">',Label,'</label>'
      :EndIf
      html,←⎕BASE.Render
    ∇
  :endclass

  :class InputGrid : #._html.table

    :field public Border←0
    :field public Labels←''
    :field public Inputs←''
    :field public Headings←''

    ∇ html←Render;cells;rows
      :Access public
      cells←{⎕NEW #._html.td(⍵)}¨renderIt¨Labels,[1.1]Inputs
      cells[;1].style←⊂'text-align:right'
      rows←⎕NEW¨(⊃⍴cells)⍴#._html.tr
      rows.Add↓cells
      Content←rows.Render
      SetAttr'border'(⍕Border)
      html←⎕BASE.Render
    ∇
  :endclass

  :class EditField : #._html.input

    ∇ make1 nm
      :Access public
      :Implements constructor
      name←nm
      id←name
      type←'text'
    ∇
    ∇ make2(nm val)
      :Access public
      :Implements constructor
      :If ~1=≡name←nm val    ⍝ handle 2-character names
        (name value)←nm val
      :EndIf
      id←name
      type←'text'
    ∇
    ∇ make3(nm val att)
      :Access public
      :Implements constructor
      :If ~1=≡name←nm val att    ⍝ handle 3-character names
        (name value)←nm val
        SetAttr att
      :EndIf
      id←name
      type←'text'
    ∇
  :endclass

  :class Button : #._html.button

    :field _content←''

    ∇ Make0
      :Access public
      :Implements constructor :base
      SetAttr('type' 'button')
    ∇

    ∇ Make args;n;v
      :Access public
      :Implements constructor :base
          ⍝ arguments are name value {content}
      args←eis args
      (n v _content)←3↑args,(⍴args)↓'button' 'button' ''
      :If 0∊⍴_content ⋄ _content←v ⋄ :EndIf
      (name value)←n v
      id←name
      SetAttr('type' 'button')
    ∇

    ∇ html←Render
      :Access public
      :If 0∊⍴Content
        Content←_content
      :EndIf
      html←⎕BASE.Render
    ∇

  :endclass

  :class Script : #._html.script

    :field public File←''
    :field public Code←''

    ∇ Make0
      :Access public
      :Implements constructor
      SetAttr'type="text/javascript"'
    ∇

    ∇ Make1 params
      :Access public
      :Implements constructor
      params←eis params
      Code File←2↑params,(⍴params)↓'' ''
      SetAttr'type="text/javascript"'
    ∇

    ∇ html←Render
      :Access public
      :If ~0∊⍴File
        SetAttr('src'File)
      :ElseIf ~0∊⍴Code
        Content←Code
      :EndIf
      html←⎕BASE.Render
    ∇

  :endclass

  :class Style : #._html.style

    :field public Selector←''
    :field public Styles←''

    ∇ Make1 params
      :Access public
      :Implements constructor
      params←eis params
      (Selector Styles)←2↑params,(⍴params)↓'' ''
    ∇

    ∇ html←Render
      :Access public
      Content←Selector,#.HTMLUtils.Styles Styles
      html←⎕BASE.Render
    ∇
  :endclass

  :class StyleSheet : #._html.link

    :field public href←''

    ∇ Make1 params
      :Access public
      :Implements constructor
      href←params
    ∇

    ∇ html←Render
      :Access public
      SetAttr(('href'href)('rel' 'stylesheet')('type' 'text/css'))
      html←⎕BASE.Render
    ∇
  :endclass

  :class Table : #._html.table
    :field public Data←0 0⍴⊂''
    :field public CellAttr←''
    :field public HeaderRows←0
    :field public HeaderAttr←''
    :field public MakeCellIds←0
    :field public MakeRowIds←0

    ∇ Make0
      :Access public
      :Implements constructor
    ∇

    ∇ Make1 data
      :Access public
      :Implements constructor
      data←eis data
      (Data CellAttr HeaderRows HeaderAttr MakeCellIds MakeRowIds)←6↑data,(⍴data)↓Data CellAttr HeaderRows HeaderAttr MakeCellIds MakeRowIds
    ∇

    ∇ html←Render;data;atts;tda;tha;hdrrows;cellids;rowids;rows;x;head;body;table;thead;tbody
      :Access public
      data tda tha hdrrows cellids rowids←Data CellAttr HeaderAttr HeaderRows MakeCellIds MakeRowIds
      hdrrows←⍬⍴hdrrows
      data←((rows←×/¯1↓⍴data),¯1↑⍴data)⍴data
      head←body←(0 1×⍴data)⍴⊂''
      :If 0≠hdrrows
        head←{⎕NEW #._html.th ⍵}¨hdrrows↑data
        :If cellids
          head.id←{∊'rc',¨⍕¨⍵}¨⍳⍴head
        :EndIf
        :If ~0∊⍴tha
          head.SetAttr¨(⍴head)⍴⊂¨eis tha
        :EndIf
      :EndIf
      :If 0<(⊃⍴data)-hdrrows
        body←{⎕NEW #._html.td ⍵}¨hdrrows↓data
        :If cellids
          body.id←{∊'rc',¨⍕¨⍵}¨hdrrows↓⍳⍴data
        :EndIf
        :If ~0∊⍴tda
          body.SetAttr¨(⍴body)⍴⊂¨eis tda
        :EndIf
      :EndIf
      (table←⎕NEW¨rows⍴#._html.tr).Add↓head⍪body
      :If rowids
        table.id←{'row',⍕⍵}⍳rows
      :EndIf
      thead←tbody←''
      :If 0≠hdrrows
        (thead←⎕NEW #._html.thead).Add hdrrows↑table
      :EndIf
      :If 0<(⊃⍴data)-hdrrows
        (tbody←⎕NEW #._html.tbody).Add hdrrows↓table
      :EndIf
      Content←thead,tbody
      html←⎕BASE.Render
    ∇
  :endclass

:EndNamespace

:Namespace _HTML

  :class Form : #._html.form

    :field public Method←'post'
    :field public Action←''
    :field public Serialize←0

    ∇ make;c
      :Access public
      :Implements constructor
      :If {6::0 ⋄ ''≢c∘←##.context ⍵}'_Request'
        Action←c._Request.Page
      :EndIf
    ∇

    ∇ make1 action
      :Access public
      :Implements constructor
      Action←action
    ∇

    ∇ r←Render
      :Access public
      Attr['action' 'method']←Action Method
      r←⎕BASE.Render
    ∇
  :endclass

  :class InputSubmit : #._html.input

    ∇ Make
      :Access public
      :Implements constructor :base
      (name value)←'submit' 'submit'
      SetAttr('type' 'submit')
    ∇

    ∇ Make1 args;n;v
      :Access public
      :Implements constructor :base
      args←eis args
      (n v)←2↑args,(⍴args)↓'submit' 'submit'
      (name value)←n v
      SetAttr('type' 'submit')
    ∇
  :endclass

  :class Input : #._html.input

    :field public Label←''

    ∇ Make1 args;l;n;t;v
      :Access public
      :Implements constructor
      args←eis args
      t n v l←4↑args,(⍴args)↓'text' '' '' ''
      (type value Label)←t v l
      :If ~0∊⍴n ⋄ name←id←n ⋄ :EndIf
    ∇

    ∇ html←Render
      :Access public
      html←''
      :If ~0∊⍴Label
        :If id≡⎕NULL ⋄ id←'gen',⍕?1000 ⋄ :EndIf
        html,←'<label for="',(⍕id),'">',Label,'</label>'
      :EndIf
      html,←⎕BASE.Render
    ∇
  :endclass

  :class InputGrid : #._html.table

    :field public Border←0
    :field public Labels←''
    :field public Inputs←''
    :field public Headings←''

    ∇ html←Render;cells;rows
      :Access public
      cells←{⎕NEW #._html.td(⍵)}¨renderIt¨Labels,[1.1]Inputs
      cells[;1].style←⊂'text-align:right'
      rows←⎕NEW¨(⊃⍴cells)⍴#._html.tr
      rows.Add↓cells
      Content←rows.Render
      SetAttr'border'(⍕Border)
      html←⎕BASE.Render
    ∇
  :endclass

  :class EditField : #._html.input

    ∇ make1 nm
      :Access public
      :Implements constructor
      name←nm
      id←name
      type←'text'
    ∇
    ∇ make2(nm val)
      :Access public
      :Implements constructor
      :If ~1=≡name←nm val    ⍝ handle 2-character names
        (name value)←nm val
      :EndIf
      id←name
      type←'text'
    ∇
    ∇ make3(nm val att)
      :Access public
      :Implements constructor
      :If ~1=≡name←nm val att    ⍝ handle 3-character names
        (name value)←nm val
        SetAttr att
      :EndIf
      id←name
      type←'text'
    ∇
  :endclass

  :class Button : #._html.button

    :field _content←''

    ∇ Make0
      :Access public
      :Implements constructor :base
      SetAttr('type' 'button')
    ∇

    ∇ Make args;n;v
      :Access public
      :Implements constructor :base
          ⍝ arguments are name value {content}
      args←eis args
      (n v _content)←3↑args,(⍴args)↓'button' 'button' ''
      :If 0∊⍴_content ⋄ _content←v ⋄ :EndIf
      (name value)←n v
      id←name
      SetAttr('type' 'button')
    ∇

    ∇ html←Render
      :Access public
      :If 0∊⍴Content
        Content←_content
      :EndIf
      html←⎕BASE.Render
    ∇

  :endclass

  :class Script : #._html.script

    :field public File←''
    :field public Code←''

    ∇ Make0
      :Access public
      :Implements constructor
      SetAttr'type="text/javascript"'
    ∇

    ∇ Make1 params
      :Access public
      :Implements constructor
      params←eis params
      Code File←2↑params,(⍴params)↓'' ''
      SetAttr'type="text/javascript"'
    ∇

    ∇ html←Render
      :Access public
      :If ~0∊⍴File
        SetAttr('src'File)
      :ElseIf ~0∊⍴Code
        Content←Code
      :EndIf
      html←⎕BASE.Render
    ∇

  :endclass

  :class Style : #._html.style

    :field public Selector←''
    :field public Styles←''

    ∇ Make1 params
      :Access public
      :Implements constructor
      params←eis params
      (Selector Styles)←2↑params,(⍴params)↓'' ''
    ∇

    ∇ html←Render
      :Access public
      Content←Selector,#.HTMLUtils.Styles Styles
      html←⎕BASE.Render
    ∇
  :endclass

  :class StyleSheet : #._html.link

    :field public href←''

    ∇ Make1 params
      :Access public
      :Implements constructor
      href←params
    ∇

    ∇ html←Render
      :Access public
      SetAttr(('href'href)('rel' 'stylesheet')('type' 'text/css'))
      html←⎕BASE.Render
    ∇
  :endclass

  :class Table : #._html.table
    :field public Data←0 0⍴⊂''
    :field public CellAttr←''
    :field public HeaderRows←0
    :field public HeaderAttr←''
    :field public MakeCellIds←0
    :field public MakeRowIds←0

    ∇ Make0
      :Access public
      :Implements constructor
    ∇

    ∇ Make1 data
      :Access public
      :Implements constructor
      Data←data
    ∇

    ∇ html←Render;data;atts;tda;tha;hdrrows;cellids;rowids;rows;x;head;body;table;thead;tbody
      :Access public
      data tda tha hdrrows cellids rowids←Data CellAttr HeaderAttr HeaderRows MakeCellIds MakeRowIds
      hdrrows←⍬⍴hdrrows
      data←((rows←×/¯1↓⍴data),¯1↑⍴data)⍴data
      head←body←(0 1×⍴data)⍴⊂''
      :If 0≠hdrrows
        head←{⎕NEW #._html.th ⍵}¨hdrrows↑data
        :If cellids
          head.id←{∊'rc',¨⍕¨⍵}¨⍳⍴head
        :EndIf
        :If ~0∊⍴tha
          head.SetAttr¨(⍴head)⍴⊂¨eis tha
        :EndIf
      :EndIf
      :If 0<(⊃⍴data)-hdrrows
        body←{⎕NEW #._html.td ⍵}¨hdrrows↓data
        :If cellids
          body.id←{∊'rc',¨⍕¨⍵}¨hdrrows↓⍳⍴data
        :EndIf
        :If ~0∊⍴tda
          body.SetAttr¨(⍴body)⍴⊂¨eis tda
        :EndIf
      :EndIf
      (table←⎕NEW¨rows⍴#._html.tr).Add↓head⍪body
      :If rowids
        table.id←{'row',⍕⍵}⍳rows
      :EndIf
      thead←tbody←''
      :If 0≠hdrrows
        (thead←⎕NEW #._html.thead).Add hdrrows↑table
      :EndIf
      :If 0<(⊃⍴data)-hdrrows
        (tbody←⎕NEW #._html.tbody).Add hdrrows↓table
      :EndIf
      Content←thead,tbody
      html←⎕BASE.Render
    ∇
  :endclass

:EndNamespace

Revert "Extend _HTML.Table"

Revert "Extend _HTML.Table"

This reverts commit 74fc0567c21704cfa8a0a0bdc253e7ef64a9df8f.


: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 OnLoad←''       ⍝ page equivalent to ⎕LX
    :field Public Charset←'UTF-8' ⍝ default charset

    _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
      Head.Insert #._html.meta''('charset=',⍕Charset)
      :If ''≢OnLoad
          Use'JQuery'
      :EndIf
      b←RenderBody
      styles←∪_Styles
      styles←styles,⍨{0∊⍴⍵:⍵ ⋄ ⊂⍵}_CssReset
      styles←styles,{0∊⍴⍵:⍵ ⋄ ⊂⍵}_CssOverride
      :If ~0∊⍴styles
          {Insert #._DC.StyleSheet ⍵}¨⌽∪styles
      :EndIf
      :If ~0∊⍴_Scripts
          {(Insert _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;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←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.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
      :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
      :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

: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 OnLoad←''       ⍝ page equivalent to ⎕LX
    :field Public Charset←'UTF-8' ⍝ default charset

    _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
      Head.Insert #._html.meta''('charset=',⍕Charset)
      :If ''≢OnLoad
          Use'JQuery'
      :EndIf
      b←RenderBody
      styles←∪_Styles
      styles←styles,⍨{0∊⍴⍵:⍵ ⋄ ⊂⍵}_CssReset
      styles←styles,{0∊⍴⍵:⍵ ⋄ ⊂⍵}_CssOverride
      :If ~0∊⍴styles
          {Insert #._DC.StyleSheet ⍵}¨⌽∪styles
      :EndIf
      :If ~0∊⍴_Scripts
          {(Insert _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;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←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.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
      :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
      :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

:EndClass

Fix to make sure scripts/css files that the user adds to his page load after any framework scripts


:Class ejTabAdvanced : MiPageSample
⍝ Control:: _SF.ejTab
⍝ Description:: Add an advanced tabbed interface

    ∇ Compose;captions;contents;intro;tab
      :Access public

      intro←'Frequently used features include the ability to switch between four orientations '
      intro,←'and load content asynchronously from another page.'

      Add title'_SF.ejTab - Simple Example '
      Add h2'_SF.ejTab - Syncfusion Tab Control'
      Add _html.p intro

      Add h2'Tabs on the left'
      captions←'Tab One' 'Another' 'Third Tab'
      contents←⊂'/Examples/Data/SampleText1.txt' ⍝ First one
      contents,←'These
are
the
contents
of
the
tab
labelled

'∘,¨1↓captions
      tab←Add #._SF.ejTab(captions contents)
      'headerPosition'tab.Set'left'
      tab.IsURL←1 0 0 ⍝ Let it know which are URLs
    ∇

:EndClass

:Class ejTabAdvanced : MiPageSample
⍝ Control:: _SF.ejTab
⍝ Description:: Add an advanced tabbed interface

    ∇ Compose;captions;contents;intro;tab
      :Access public

      intro←'Frequently used features include the ability to switch between four orientations '
      intro,←'and load content asynchronously from another page.'

      Add _.title'_SF.ejTab - Simple Example '
      Add _.h2'_SF.ejTab - Syncfusion Tab Control'
      Add _html.p intro

      Add _.h2'Tabs on the left'
      captions←'Tab One' 'Another' 'Third Tab'
      contents←⊂'/Examples/Data/SampleText1.txt' ⍝ First one
      contents,←'These
are
the
contents
of
the
tab
labelled

'∘,¨1↓captions
      tab←Add _.ejTab(captions contents)
      'headerPosition'tab.Set'left'
      tab.IsURL←1 0 0 ⍝ Let it know which are URLs
    ∇

:EndClass

Update ejTabAdvanced.dyalog

Update ejTabAdvanced.dyalog

_ was missing in some Add-statements


: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
          {Insert #._DC.StyleSheet ⍵}¨⌽∪styles
      :EndIf
      :If ~0∊⍴_Scripts
          {(Insert _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 ~(_PageData.⎕NC names)∊2 9
          r←,proto
      :Else
          r←_PageData⍎names
          :If 2≤≡r
              :If 1=⍴,r
                  r←⊃r
              :EndIf
          :EndIf
          :If isString r
              r←#.JSON.toAPL r
          :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 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
    ∇

    ∇ 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

: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
          {Insert #._DC.StyleSheet ⍵}¨⌽∪styles
      :EndIf
      :If ~0∊⍴_Scripts
          {(Insert _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 ~(_PageData.⎕NC names)∊2 9
          r←,proto
      :Else
          r←_PageData⍎names
          :If 2≤≡r
              :If 1=⍴,r
                  r←⊃r
              :EndIf
          :EndIf
          :If isString r
              r←#.JSON.toAPL r
          :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 2≠_Request.Session.⎕NC names
⍝ MB: edited with Brian in Italy to also return objects (actually: anything)
      :ElseIf 0=_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
    ∇

    ∇ 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

:EndClass

Update MiPage.dyalog

Update MiPage.dyalog

Edited SessionGet to return any valid object stored in the Session.