-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path_JQ.dyalog
666 lines (577 loc) · 28.1 KB
/
_JQ.dyalog
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
:Namespace _JQ ⍝ jQueryUI
(⎕IO ⎕ML)←1
:section Common Code
eis←{(,∘⊂)⍣((326∊⎕DR ⍵)<2>|≡⍵),⍵} ⍝ Enclose if simple
quote←{0∊⍴⍵: '' ⋄ '⍎"'∊⍨⍬⍴⍵:⍵ ⋄ '"',(('"' ⎕R '\\\0')⍕⍵),'"'}
fmtSelector←{{'this'≡⍵:⍵ ⋄quote ⍵}¯2↓∊{⍵,', '}¨eis ⍵}
fmtValue←{(2=≡⍵)∧0=≢⍴⍵:⊃⍵ ⋄ #.JSON.fromAPL ⍵}
∇ r←opt(sel Update jqfn)val
⍝ update an option for a widget
r←#.JQ.Execute'$(',(fmtSelector sel),').',jqfn,'("option","',opt,'",',(fmtValue val),');'
∇
:endsection
:section Base Classes
:class _jqObject : #.HtmlElement
:field public Selector←'' ⍝ Selector to apply the JQuery function to
:field public JavaScript←'' ⍝ additional JavaScript to run AFTER the jQuery function, can be function chain, separate code or both
:field public PreJavaScript←'' ⍝ additional JavaScript to run BEFORE the jQuery function
:field public Var←'' ⍝ JavaScript variable name for created object
:field public JQueryFn←'' ⍝ JQuery function to apply
:field public JQPars←'' ⍝ JQuery function parameters
:field public Type←'' ⍝ Type specification that may precede JQPars
:field public shared readonly _true←#.JSON.true ⍝ same definition as in #.JSON
:field public shared readonly _false←#.JSON.false ⍝ same definition as in #.JSON
:field public ScriptOptions←⍬ ⍝ determines how script will be rendered [1] wrap with <script>...</script>, [2] wrap with $(function(){...})
∇ Make0
:Access public
:Implements constructor
∇
∇ Make1 pars
:Access public
:Implements constructor
pars←eis pars
JQueryFn Selector JQPars JavaScript Var PreJavaScript Type←7↑pars,(⍴pars)↓'' '' '' '' '' '' ''
∇
∇ r←Render
:Access public
SetUse
r←ScriptOptions #.JQ.JQueryfn JQueryFn Selector JQPars JavaScript Var PreJavaScript Type
∇
∇ r←isSelector str ⍝ checks if str is probably a jQuery selector
:Access public shared
r←∨/str∊'''"*[]:>+~()#.'
∇
:section APLJax
∇ 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'(renderContent content))
∇
∇ r←name Assign data
:Access public
r←⊂('assign'name)('data'data)
∇
:EndSection
:endclass
:class _jqWidget : _jqObject
:field public Options←'' ⍝ options for the object to be created
:field public ContainerTag←'div' ⍝ default container type
:field public Container
:field public InternalEvents←'' ⍝ list of events the widget "knows" about
:field public BuildHTML←1 ⍝ if 0, we build any HTML infrastructure for the widget, otherwise, assume the user built it
:field public WidgetDef←'event,ui' 'event' 'ui' '$(event.currentTarget)' '.val()' ⍝ see _JQ.RenderHandlerCore for details
∇ r←{a}rand w;⎕RL
:Access public
⎕RL←0
:If 0=⎕NC'a' ⋄ r←?w
:Else ⋄ r←a?w ⋄ :EndIf
∇
∇ Make
:Access public
Options←⎕NS''
Container←⎕NEW #.HtmlElement
:Implements constructor
∇
∇ r←Render;build;html;handlers;js;oldJavaScript
:Access public
r←html←js←''
SetUse
BuildHTML∧←0∊⍴Selector ⍝ if the user explicitly specifies a selector, assume he's built the content himself
:If BuildHTML
Container.(id name type style class title)←Container.(id name type style class title){UNDEF≡⍵:⍺ ⋄ UNDEF≢⍺:⍺ ⋄ ⍵}¨⎕THIS.(id name type style class title)
:If Container.id≡UNDEF
:If Container.name≢UNDEF
Container.id←Container.name
:Else
Container.id←SetId
:EndIf
:EndIf
Selector←'#',Container.id
:EndIf
handlers←''
:If ~0∊⍴Handlers
handlers←';',⍨∊¯1↓¨Handlers.Render
:EndIf
oldJavaScript←JavaScript
JavaScript,←handlers
JQPars←Options
js←⎕BASE.Render
JavaScript←oldJavaScript
:If BuildHTML≥0∊⍴Container.Content
:Select ⊃Selector
:Case '#' ⍝ id?
Container.id←1↓Selector
:Case '.' ⍝ class?
Container.class←1↓Selector
:EndSelect
:If ContainerTag{⍵≡(⍴⍵)↑⍺}'input'
:AndIf UNDEF≡Container.name
Container.name←('.#'∊⍨⊃Selector)↓Selector
:EndIf
Container.Tag←ContainerTag
html←Container.Render
:EndIf
r←html,js
∇
∇ {handler}←On args
:Access public
⍝ args - event callback clientData javascript
handler←⎕BASE.On args
handler.InternalEvents←InternalEvents
handler.(WidgetDef←WidgetRef.WidgetDef)
∇
∇ {r}←{name}Set value
:Access public
r←⎕THIS
→(0∊⍴value)⍴0
:If 326≠⎕DR Options ⋄ Options←⎕NS'' ⋄ :EndIf
:If 0=⎕NC'name'
:Trap 11
(name value)←ParseValue value
:Else
⎕SIGNAL/⎕DMX.(EM EN)
:EndTrap
:EndIf
:Trap 0
name(Options SetOption)value
:Else
⎕SIGNAL/⎕DMX.(EM EN)
:EndTrap
∇
∇ {r}←name SetIfNotSet value
:Access public
:If 0∊⍴GetOption name
name Set value
:EndIf
r←⎕THIS
∇
∇ name(ref SetOption)value;set;parent;ind;newref;chunk;n;now;new;chunkroot;array;val;pos;r;v
→(0∊⍴value)⍴0
:If 1<|≡name ⍝ multiple names?
value←(⊂⍣((⎕DR value)∊80 82))value
name(ref SetOption)¨value
:Else
set←{
⍺⍺⍎'(',⍺,')←⍵'
}
:If 0∊⍴parent←(-'.'⍳⍨⌽name)↓name ⍝ if no parent...
:If 1<n←≢ref ⍝ multiple refs?
⎕SIGNAL 5/⍨(0=≢⍴value)=(⍴ref)=⍴value ⍝ LENGTH ERROR if value is not scalar or same length as ref
:For (r v) :InEach ref(n⍴value)
name(r set)v
:EndFor
:ElseIf (1+' '+.=name)=≢value
name(ref set)value
:Else
name(ref set)value ⍝ single name: assign directly (may be more than 1 name)
:EndIf
:Else
ind←name⍳'.'
chunk←¯1↓ind↑name
(chunkroot pos)←2↑'[]'#.Utils.penclose chunk
:If array←'[]'≡¯2↑chunk ⍝ is it an array assignment?
pos←≢val←eis value
:Select ⊃ref.⎕NC chunkroot
:Case 0
new←⎕NS¨(⌈/pos)⍴⊂⍬
chunkroot(ref set)new
:Case 2 ⍝ already exists
('Invalid option specification - length error on "',chunkroot,'".')⎕SIGNAL 5/⍨~(⍴new←ref⍎chunkroot)∊1,pos
:Else
('Invalid option specification - "',chunkroot,'" is not an array.')⎕SIGNAL 11
:EndSelect
new{(ind↓name)(⍺ SetOption)⍵}¨val
:Else
(chunkroot pos)←2↑'[]'#.Utils.penclose chunk
pos←2⊃⎕VFI pos
:Trap 3 6
newref←ref⍎chunk
:Case 3 ⍝ index error
n←⍴now←ref⍎chunkroot
new←⎕NS¨(pos-n)⍴⊂⍬
chunkroot(ref set)now,new
newref←ref⍎chunk
:Case 6 ⍝ value error
:If ~0∊⍴pos
new←⎕NS¨(⌈/pos)⍴⊂⍬
chunkroot(ref set)new
:Else
chunkroot ref.⎕NS''
:EndIf
newref←ref⍎chunk
:EndTrap
(ind↓name)(newref SetOption)value
:EndIf
:EndIf
:EndIf
∇
∇ r←ParseValue value
:Access shared public
:If 2=⍴⍴value
:AndIf 2=¯1↑⍴value
:ElseIf 2<|≡value
:AndIf ∧/(,2)∘≡∘⍴¨value
value←↑value
:ElseIf 0=2|⍴value
value←((0.5×⍴value),2)⍴value
:Else
'Invalid option format'⎕SIGNAL 11
:EndIf
r←↓[1]value
∇
∇ r←GetOption names
:Access public
r←{6::'' ⋄ Options.⍎⍵}¨{⎕ML←3 ⋄ ⍵⊂⍨⍵≠' '}names
:If 1=⍴r ⋄ r←⊃r ⋄ :EndIf ⍝ if single setting requested
∇
∇ r←name Update value;v
:Access public
r←name(Selector #._JQ.Update JQueryFn)value
name Set value
∇
∇ r←ShowOptions
:Access public
r←(⎕JSON⍠'Compact' 0)Options
∘∘∘
∇
:endclass
:class _jqUIWidget : _jqWidget
:field public Force←0
⍝ :field public WidgetSyntax ←⊂'event,ui' 'event' 'ui' '$(event.target)' '.val()' ⍝ see Handler class below
∇ make
:Access public
:If 0=⎕NC⊂'Uses' ⋄ Uses←'' ⋄ :EndIf
:If 0∊⍴Uses ⋄ Uses←'JQueryUI' ⋄ :EndIf
:Implements constructor
∇
∇ make1 pars
:Access public
:If 0=⎕NC⊂'Uses' ⋄ Uses←'' ⋄ :EndIf
:If 0∊⍴Uses ⋄ Uses←'JQueryUI' ⋄ :EndIf
:Implements constructor :base pars
∇
∇ {r}←opts RenderHandler handler
:Access public
r←opts ⎕BASE.RenderHandler(handler WidgetDef Force)
∇
:endclass
:endsection
⍝ --- Events ---
:Section Events
:Class Handler
:Field public Selector←'' ⍝ CSS/jQuery selector to bind handler to
:Field public Delegates←'' ⍝ See jQuery.On for information about delegates
:Field public Events←'' ⍝ events to bind
:Field public ClientData←'' ⍝ any additional client data to send to server
:Field public Callback←1 ⍝ execute AJAX callback to server? or the name of the server-side callback function
:Field public JavaScript←'' ⍝ JavaScript to execute prior to server callback
:Field public Page←'' ⍝ server URL to request for an AJAX callback
:Field public Method←'on' ⍝ by default use jQuery .on(), but can also be set to 'one' for a handler that fires only once
:Field public jQueryWrap←1 ⍝ wrap handler in $(function(){...});
:Field public ScriptWrap←1 ⍝ wrap handler in <script>...</script>
:Field public StatusHandlers ⍝
:Field public WidgetDef←'' ⍝ widget definitions (e.g. jQuery or Syncfusion, others libraries may different)
⍝ jQuery Syncfusion
⍝ [1] event handler syntax: 'event,ui' 'argument'
⍝ [2] syntax to access the event object: 'event' 'argument'
⍝ [3] syntax to access the object's model: 'ui' 'argument.model'
⍝ [4] syntax to access the widget itself: '$(event.target)' 'this.element'
⍝ [5] syntax to access the value of an input widget - this default to '' but may overridden by individual widget
⍝ see ejSlider as an example
⍝
:Field public ForceInternal←¯1 ⍝ indicates whether to "force" the event to be treated as a widget internal event
:Field public WidgetRef←'' ⍝ ref to widget instance if this handler is on
:Field public Hourglass←¯1 ⍝ indicates whether to display hourglass during callback execution
⍝ 1 - yes, 0 - no, ¯1 - only if calling back to APL
:Field public Uses←'JQuery'
:Field public _PageRef_←''
quote←{0∊⍴⍵: '' ⋄ '⍎"'∊⍨⍬⍴⍵:⍵~'⍎' ⋄ '"',(('"' ⎕R '\\\0')⍵),'"'} ⍝ quote unless already quoted or begins with ⍎
ine←{0∊⍴⍺:'' ⋄ ⍵} ⍝ if not empty
eis←{(,∘⊂)⍣((326∊⎕DR ⍵)<2>|≡⍵),⍵} ⍝ Enclose if simple
∇ Make0
:Access public
:Implements constructor
CommonSetup
∇
∇ Make1 params
:Access public
:Implements constructor
params←#.HtmlElement.eis params
(Selector Events Callback ClientData JavaScript Delegates Page)←7↑params,(⍴params)↓7⍴⊂''
:If #.HtmlPage #.HtmlElement.isInstance Page ⋄ Page←Page.Page ⋄ :EndIf ⍝ if request object passed
CommonSetup
∇
∇ CommonSetup;c
:Access public
:Trap 0
c←#.HtmlElement.context'_PageRef'
:If ~0∊⍴c
(c⍎'_PageRef').Use Uses
_PageRef_←c._PageRef
:EndIf
:EndTrap
WidgetDef←'event,ui' 'event' 'ui' '$(event.target)' '.val()'
StatusHandlers←408 500,⍪'alert("Session timed out")' 'alert("Internal Server Error")'
∇
∇ r←code OnStatus javascript;ind
:Access public
ind←StatusHandlers[;1]⍳code
StatusHandlers↑⍨←ind⌈≢StatusHandlers
StatusHandlers[ind;]←code javascript
∇
∇ r←Render;sel;syn_handler;syn_event;syn_model;syn_this;data;useajax;force;cd;selector;arg;verb;name;phrase;datasel;JQfn;jqfn;hg;removehg;dtype;success;status;ajax;widget;syn_value;delegates;v;events;selSelector;statjs;statcode
:Access public
r←''
:If ~0∊⍴Events ⍝ skip if no events specified
:If #.MiPage #.HtmlElement.isInstance Page
Page←Page._PageName
:EndIf
(selector delegates)←2↑(eis Selector),'' ''
:If ~0∊⍴Delegates
delegates←Delegates
:EndIf
:If useajax←(,0)≢,Callback ⍝ callback=0 → don't make callback to server; =1 → use APLJax, =charvec → call ⍎charvec
:AndIf (0∊⍴Page)>0∊⍴_PageRef_
Page←_PageRef_._PageName
:EndIf
force←0
events←Events
:If widget←#.HtmlElement.isWidget WidgetRef ⍝ is this a widget handler?
WidgetDef←WidgetRef.WidgetDef
:If ForceInternal=¯1
:If ∨/', '∊Events ⍝ multiple events?
events←', '#.Utils.penclose Events
:Else
events←,⊂Events
:EndIf
force←∧/events∊WidgetRef.InternalEvents
:Else
force←ForceInternal
:EndIf
:EndIf
:If 0∊⍴selector ⍝ empty selector → use entire page
:If widget
selector←WidgetRef.Selector
:ElseIf #.HtmlElement #.HtmlElement.isInstance ##
:If #.MiPage #.HtmlElement.isInstance ##
selector←'⍎document'
:Else
selector←'#',##.id
:EndIf
:Else
selector←'⍎document'
:EndIf
:EndIf
(syn_handler syn_event syn_model syn_this syn_value)←5↑WidgetDef
data←'_event: ',syn_event,'.type, '
data,←'_what: function(arg){try{return arg.attr("id");}catch(e){return"";}}(',syn_this,'), '
data,←'_value: function(arg){try{return arg',syn_value,';}catch(e){return"";}}(',syn_this,'), '
data,←'_selector: ',(quote selector~'⍎'),', '
data,←'_target: function(arg){try{return arg.target.id;}catch(e){return"";}}(',syn_event,'), '
data,←'_currentTarget: function(arg){try{return arg.currentTarget.id;}catch(e){return"";}}(',syn_event,'), '
:If #.HtmlElement.isString Callback ⍝ numeric Callback 1-call APLJax, 0-no callback to server
:AndIf ~0∊⍴Callback
data,←'_callback: ',(quote Callback),', '
:EndIf
:If 0∊⍴ClientData ⍝ if you don't specify any clientdata, we serialize any forms on the page
data,←'_serialized_: $("form").serialize(), '
:EndIf
data←¯2↓data
:If ~0∊⍴ClientData
:Select ≡⊃ClientData
:CaseList 0 ⍝ ClientData is a simple vector
ClientData←,⊂2⍴⊂,ClientData ⍝ so name and verb are set to the same
:CaseList 1 ⍝ first element is a vector
ClientData←,⊂ClientData ⍝ enclose it
:EndSelect
:For cd :In ClientData
cd←#.HtmlElement.eis cd
(name verb arg sel)←4↑cd,(⍴cd)↓4⍴⊂''
:If (~0∊⍴name)∨verb≡'serialize'
:AndIf ~0∊⍴verb
jqfn←'' ⍝ jQuery function to call if this client data element refers to a widget
:If (⊂verb)∊'html' 'val' ⍝ neither html or val take an argument
:AndIf 0∊⍴sel
sel←arg
:EndIf
⍝ build the selector for the data element
:If sel≡'' ⍝ it's for the current element/widget
:If #.HtmlElement.isWidget WidgetRef
datasel←'$(',(quote WidgetRef.Selector),').'
:If ~0∊⍴jqfn←WidgetRef.JQueryFn
datasel,←WidgetRef.JQueryFn
:EndIf
:Else
datasel←syn_this,'.'
:EndIf
:ElseIf #.HtmlElement #.HtmlElement.isInstance sel ⍝ selector is reference to other element
:If #._JQ._jqObject #.HtmlElement.isInstance sel ⍝ is it a jQuery-based object?
:If 0∊⍴selSelector←sel.Selector ⍝ no Selector?
sel.SetId
selSelector←'#',sel.id
:EndIf
datasel←'$(',(quote selSelector),').'
:If ~0∊⍴jqfn←sel.JQueryFn
datasel,←sel.JQueryFn
:EndIf
:Else ⍝ not a jQuery-based object
sel.SetId
datasel←'$(',(quote'#',sel.id),').'
:EndIf
:Else ⍝ sel is not an HtmlElement
:Select |≡sel
:CaseList 0 1
datasel←'$(',(quote sel),').'
:Case 2
datasel←'$(',(quote(1⊃sel)),').',jqfn←2⊃sel
:EndSelect
:EndIf
⍝ now figure out what data to generate
phrase←''
:Select verb
:CaseList 'attr' 'css' 'is' 'prop'
datasel,←'().'/⍨~0∊⍴jqfn
phrase←datasel,verb,'(',(quote arg),')'
:CaseList 'html' 'val'
datasel,←'().'/⍨~0∊⍴jqfn
phrase←datasel,verb,'()'
:Case 'option' ⍝ jQueryUI and Syncfusion widgets
name,⍨←'_json_'
:If 0∊⍴arg
phrase←'APLstringify(',datasel,'("option"))'
:Else
phrase←'APLstringify(',datasel,'("option",',(quote arg),'))'
:EndIf
:Case 'method' ⍝ jQueryUI and Syncfusion widgets
:If 0∊⍴arg
phrase←'"no method information specified!"'
:Else
phrase←datasel,'(',(quote arg),')'
:EndIf
:CaseList 'event' 'this' 'argument'
v←('event' 'argument' 'this'⍳⊂verb)⊃syn_event syn_event syn_this
name,⍨←'_json_'
:If 0∊⍴arg
phrase←'APLstringify(',v,')'
:Else
phrase←'APLstringify(',v,'.',arg,')'
:EndIf
:CaseList 'model' 'ui' ⍝ widgets only
:If ~0∊⍴jqfn
datasel,←'().'
name,⍨←'_json_'
:If 0∊⍴arg
phrase←'APLstringify(',syn_model,')'
:Else
phrase←'APLstringify(',syn_model,'.',arg,')'
:EndIf
:EndIf
:Case 'eval'
sel←'' ⍝ ignore selector on eval
phrase←'eval(',(quote arg),')'
:Case 'js'
sel←''
phrase←arg
:Case 'string'
phrase←quote arg
:Case 'serialize'
:If 0∊⍴sel
:If 0∊⍴arg
sel←'form'
:Else
sel←arg
:EndIf
:EndIf
phrase←'$(',(quote sel),').serialize()'
name,⍨←'_serialized_'
:Else
:If 1<≡verb
sel←''
phrase←⊃verb
:ElseIf '⍎'=⊃verb
sel←''
phrase←1↓verb
:Else
#.DUI.Log'Unknown event handler verb: "',verb,'"',{0::'' ⋄ ' on page ',##._PageRef._PageName}⍬
phrase←quote phrase
:EndIf
:EndSelect
data,←',',name,': ',phrase
:EndIf
:EndFor
:EndIf
(hg removehg)←((1+Hourglass=¯1)⊃Hourglass useajax)∘{⍺:';document.body.style.cursor="',⍵,'";' ⋄ ''}¨'wait' 'default'
dtype←'"json"'
success←'success: function(obj){APLJaxReturn(obj)',removehg,'}'
status←'statusCode:{ '
:For (statcode statjs) :In ↓StatusHandlers
:If ~0∊⍴statjs
status,←(⍕statcode),': function(p1, p2, p3){',statjs,removehg,'},' ⍝ use generic p1, p2, p3 because jQuery has different parameters for error and success
:EndIf
:EndFor
status←(¯1↓status),'}'
⍝status←'statusCode:{ 408: function(){alert("Session timed out")',removehg,'}}'
ajax←(JavaScript ine JavaScript,(';'=¯1↑JavaScript)↓';'),useajax/hg,'$.ajax({url: ',(quote Page),', cache: false, type: "POST", dataType: ',dtype,', headers:{"isAPLJax": "true"}, data: {',data,'}, ',success,', ',status,'});'
:If widget
:If force
(eis events)(WidgetRef.Options{⍺⍺⍎⍺,'←⍵'})¨⊂⊂'function(',syn_handler,'){',ajax,'}'
:Else
r←'.',Method,'(',(quote Events),', function(event,ui){',ajax,'});'
:EndIf
:Else
r←'$(',(quote selector),').',Method,'(',(quote Events),(delegates ine', ',quote delegates),', function(event,ui){',ajax,'});'
:If jQueryWrap ⋄ r←'$(function(){',r,'});' ⋄ :EndIf
:If ScriptWrap ⋄ r←'<script>',r,'</script>' ⋄ :EndIf
:EndIf
:EndIf
∇
:endclass
:endsection
:EndNamespace