我有这个 parenscript 宏:
;;; Parenscript macro for showModal() and close() methods for pop-up dialogs.
;;;Takes the dialog's id, button for opening the dialog's id, and closing button's id.
(defpsmacro open-close-modal-dialog (dialog-id element-id-1 element-id-2 &key open close open-args close-args)
(let ((dialog (ps-gensym)))
`(progn
(setf ,dialog (chain document (get-element-by-id ,dialog-id)))
(setf (chain document (get-element-by-id ,element-id-1) onclick)
(lambda (,@open-args)
(progn
,@open
(funcall (chain ,dialog show-modal)))))
(setf (chain document (get-element-by-id ,element-id-2) onclick)
(lambda (,@close-args)
(progn
,@close
(funcall (chain ,dialog close))))))))
我在 Hunchentoot 处理程序中使用它,如下所示:
(define-easy-handler (student-name :uri "/student-info") (name)
(let ((student (student-from-name name)))
(standard-page (:title "Ashtanga Yoga Osaka | Student Page"
:script (ps
(defun init ()
(open-close-modal-dialog "editPassDialog" "getPass" "submitPass"
;; This is the pop-up dialog
:open (ps(defvar frm (chain document (get-element-by-id "editPass"))))))
(setf (chain window onload) init)))
;; Main form
(:form :action "/edit-student" :method "post" :id "editStudent"
(:p "Name" (:input :type "text" :name "name" :class "txt" :value (format nil "~A" (name student))))
(:P "Email" (:input :type "email" :name "email" :class "txt" :value (format nil "~A" (email student))))
(:p "Passes" (:select :name "passlist"
(dolist (pass (pass student))
(htm
(:option :id "pass" :value (pass->json pass)
(fmt "~A ~A" (print-month (getf pass :date))
(print-year (getf pass :date)))))))
(:button :type "button" :id "getPass" :class "btn" "Get Pass"))
(:input :type "hidden" :name "previous" :value nil) ; previous value of the pass
(:input :type "hidden" :name "old-name" :value name) ; old name of student, used for retrieving the correct instance
(:p (:input :type "submit" :value "Edit Info" :class "btn")))
;; Pop-up dialog for editing passes
(:dialog :id "editPassDialog"
(:h1 "Edit Pass")
(:form :action "#" :method "post" :id "editPass"
(:p "Date bought" (:input :type "text" :name "date" :class "txt"))
(:p "Type" (:input :type "text" :name "type" :class "txt"))
(:p "Amount Paid" (:input :type "text" :name "amt"))
(:p (:button :type "button" :class "btn" :id "submitPass" "Edit Pass")))))))
现在,当我通过 Quicklisp 加载系统时,我收到此错误:
; caught ERROR:
; during macroexpansion of
; (PS
; (DEFUN INIT # ...)
; (SETF #)).
; Use *BREAK-ON-SIGNALS* to intercept.
;
; The Parenscript form (DEFVAR FRM
; (CHAIN DOCUMENT
; (GET-ELEMENT-BY-ID
; editPass))) cannot be compiled into an expression.
这很奇怪,因为我可以在 REPL 中定义这种形式:
SHALA-SYS> (macroexpand-1 '(ps (defvar frm (chain document (GET-ELEMENT-BY-ID "editPass")))))
"var frm = document.getElementById('editPass');"
如果我删除:open
和它的参数,系统加载,然后我添加:open
和 args 并重新编译处理程序,它编译没有问题。
有什么想法吗?