4 ;;;; * Dojo Javascript Components
5 (defcomponent dojo-component
()
6 ((requires :accessor requires
:initarg
:requires
:initform nil
)))
8 (defmethod render-requires ((self dojo-component
))
9 (<ucw
:script
`(progn ,@(loop for r in
(requires self
)
10 collect
`(dojo.require
,r
)))))
12 (defmethod render :wrapping
( (self dojo-component
))
13 (render-requires self
)
16 (defmethod lol::present
:around
((self dojo-component
))
17 (render-requires self
)
20 (defcomponent dojo-ajax-output-component
(window-component)
21 ((component :accessor component
:initarg
:component
:component dojo-component
)))
23 (defmethod render ((self dojo-ajax-output-component
))
26 (defmethod lol::present
((self dojo-ajax-output-component
))
27 (present-output (component self
)))
29 (defcomponent dojo-input-component-mixin
()
32 :initform
(arnesi:random-string
32 arnesi
::+ALPHANUMERIC-ASCII-ALPHABET
+))))
34 (defcomponent dojo-output-component-mixin
()
37 :initform
(arnesi:random-string
32 arnesi
::+ALPHANUMERIC-ASCII-ALPHABET
+))
39 :accessor output-component
40 :component dojo-ajax-output-component
)))
42 (defmethod shared-initialize :after
((self dojo-output-component-mixin
) slots
&rest args
)
43 (declare (ignore slots args
))
44 (setf (component (output-component self
)) self
))
47 (defmacro with-ajax
((component) &body args
)
48 (multiple-value-bind (actions callbacks args output
)
50 if
(eql (car arg
) :action
)
51 nconc
(cdr arg
) into actions
52 else if
(eql (car arg
) :callback
)
53 collect
(cdr arg
) into callbacks
54 else if
(eql (car arg
) :output-to
)
55 nconc
(cdr arg
) into output
58 finally
(return (values actions callbacks args output
)))
59 `(js:with-unique-js-names
(js-callbacks)
61 (setf ,js-callbacks
(array))
62 ,,@(loop for c in callbacks
65 ``(setf (aref ,js-callbacks
,,i
)
66 (lambda () ,,(third c
))))
72 ,(lol::make-action-url
76 (call-component nil
(output-component self
))))))
78 ,(getf args
:post-content
)
79 `(:post-content
(+ ,,@(loop for c in callbacks
81 nconc
`((ucw::make-new-callback
86 `(encode-u-r-i-component ((aref ,js-callbacks
,,n
)))
89 ,(or (getf args
:load
) (not output
) )
92 (setf (slot-value (document.get-element-by-id
,,@output
) inner-h-t-m-l
) data
))))
102 (defcomponent dojo-editor
(dojo-component dojo-input-component-mixin
)
103 ((document :accessor document
:initarg
:document
:initform
"test"))
105 :requires
'("dojo.event.*" "dojo.widget.Editor" "dojo.io.*" "dojo.widget.RichText")))
107 (defmethod save-document ((self dojo-editor
))
110 (defmethod js-on-load ((self dojo-editor
))
112 (setf document.location
113 ,(lol::make-action-url
117 (defmethod render-editor ((self dojo-editor
))
121 (setf div
(document.get-element-by-id
,(input-id self
)))
122 (setf editor
(dojo.widget.from-script
133 ,(ucw::make-new-callback
136 (setf (document self
) x
)))
138 (encode-u-r-i-component (editor.get-html
)))
140 ,(lol::make-action-url
142 (save-document self
))
144 :load
,(js-on-load self
))))))
145 (dojo.event.kw-connect
146 (create :type
"before"
150 :target-func
"saveToServer")))))
151 (<:div
:class
"editor"
154 (<:as-is
(document self
)))))
156 (defmethod render ((self dojo-editor
))
157 (render-editor self
))
159 (defcomponent dojo-editor-presentation
(dojo-editor mewa
::mewa-editor
)
162 (lol::defslot-presentation dojo-editor-slot-presentation
(dojo-editor mewa
::mewa-string-slot-presentation
)
163 ((document :accessor document
:initarg
:document
)
164 (instance :accessor instance
))
165 (:type-name dojo-editor
))
167 (defmethod save-document ((self dojo-editor-slot-presentation
))
168 (setf (lol::presentation-slot-value self
(instance self
)) (document self
)))
170 (defmethod lol::present-slot
((slot dojo-editor-slot-presentation
) instance
)
171 (setf (document slot
) (lol::presentation-slot-value slot instance
))
172 (setf (instance slot
) instance
)
173 (render-requires slot
)
174 (render-editor slot
))
176 (defmethod js-on-load ((self dojo-editor-slot-presentation
))
178 (setf document.location
179 ,(lol::make-action-url
181 (answer-component (ucw::parent self
) self
)))))
184 (defcomponent sortable-list-editor
(lol::mewa-list-presentation
186 dojo-input-component-mixin
187 dojo-output-component-mixin
)
190 :requires
'("dojo.event.*" "dojo.dnd.*" "dojo.io.*")))
192 (defmethod present-output ((self sortable-list-editor
))
193 (loop for li in
(mewa::instances self
)
197 (<:li
:id
(format nil
"~A~A" (input-id self
) n
)
198 (<:as-html
(lol:present-view
(li :one-line
)))
200 (<ucw
:a
:action
(lol:call-view
(li :editor
(call-from self
)))
201 (<:as-html
"(edit)"))
202 (<ucw
:a
:action
(lol:call-view
(li :editor
))
203 (<:as-html
"(remove)"))))))
205 (defmethod lol::present
((self sortable-list-editor
))
206 (<:div
(<:as-html
"Drag and Drop list items to change the order"))
209 (present-output self
))
211 (<ucw
:a
:action
(answer (mewa::instances self
))
212 (<:as-html
"*Save*")))
215 (<ucw
:a
:action
(add-list-item self
)
216 (<:as-html
"*Add Item*")))
218 (<ucw
:a
:action
(answer nil
)
219 (<:as-html
"*Cancel*"))))
222 ;;;; The Dojo example :
223 ;;;; var dl = byId("dragList3");
224 ;;;; new dojo.dnd.HtmlDropTarget(dl, ["li2"]);
225 ;;;; var lis = dl.getElementsByTagName("li");
226 ;;;; for(var x=0; x<lis.length; x++){
227 ;;;; new dojo.dnd.HtmlDragSource(lis[x], "li2");}
229 ;;;; and the parenscript
230 `(dojo.event.connect dojo
"loaded"
234 (setf ulist
(document.get-element-by-id x
))
235 (setf drop
(new (dojo.dnd.
*html-drop-target ulist
(array x
))))
236 (setf list-items
(ulist.get-elements-by-tag-name
"li" ))
237 (dolist (li list-items
)
238 (new (dojo.dnd.
*html-drag-source li x
)))))
239 (make-sortable ,(input-id self
))
244 (dolist (li list-items
)
245 (new (dojo.dnd.
*html-drag-source li
,(input-id self
))))
249 (:callback d
(let ((list-order
250 (mapcar #'(lambda (x)
251 (parse-integer (subseq x
(length (input-id self
)))))
252 (read-from-string d
))))
253 (setf (mewa::instances self
) (reorder-list (mewa::instances self
) list-order
)))
256 (dolist (li list-items
)
257 (setf my-list
(+ my-list
"\"" li.id
"\"" " ")))
258 (setf my-list
(+ my-list
")"))
260 (:load
`(lambda (x data
)
261 (setf (slot-value (document.get-element-by-id
,(input-id self
)) inner-h-t-m-l
) data
)
262 (make-sortable ,(input-id self
)))))))))))
265 ;(defcomponent dojo-combo-box )