;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-USER; Base: 10 -*- ;;; $Header: dojo/src/djform.lisp $ ;;; Copyright (c) 2008, Andrea Chiumenti. All rights reserved. ;;; Redistribution and use in source and binary forms, with or without ;;; modification, are permitted provided that the following conditions ;;; are met: ;;; * Redistributions of source code must retain the above copyright ;;; notice, this list of conditions and the following disclaimer. ;;; * Redistributions in binary form must reproduce the above ;;; copyright notice, this list of conditions and the following ;;; disclaimer in the documentation and/or other materials ;;; provided with the distribution. ;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED ;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (in-package :dojo) (defclass djform (cform djwidget) ((update-id :initarg :update-id :reader update-id :documentation "A list of the component id to update") (ajax-form-p :initarg :ajax-form-p :reader djform-ajax-form-p :documentation "When not nil, requests are sent via XHR call.")) (:metaclass metacomponent) (:documentation "Class to generate a
element that is capable of XHR requests. More info at http://api.dojotoolkit.org/") (:default-initargs :dojo-type "claw.Form" :update-id () :ajax-form-p t)) (defmethod wcomponent-template((obj djform)) (let ((id (htcomponent-client-id obj)) (method (form-method obj)) (dojo-type (djwidget-dojo-type obj)) (update-id (update-id obj))) (form> :static-id id :xhr (djform-ajax-form-p obj) :method method :dojotype dojo-type :update-id (when update-id (let ((js-array (ps* `(array ,update-id)))) (subseq js-array 0 (1- (length js-array))))) (wcomponent-informal-parameters obj) (input> :name *rewind-parameter* :type "hidden" :value id) (htcomponent-body obj)))) (defmethod htcomponent-instance-initscript ((obj djform)) nil) (defclass djtext-box (cinput djwidget) () (:metaclass metacomponent) (:documentation "This class inherits from a CINPUT, but is used to render a dojo dijit.form.TextBox") (:default-initargs :dojo-type "dijit.form.TextBox" :type "text")) (defmethod wcomponent-template ((obj djtext-box)) (let ((client-id (htcomponent-client-id obj)) (type (claw::input-type obj)) (dojo-type (djwidget-dojo-type obj)) (translator (translator obj)) (value "") (class (claw::css-class obj))) (when (component-validation-errors obj) (if (or (null class) (string= class "")) (setf class "dijitError") (setf class (format nil "~a dijitError" class)))) (setf value (translator-encode translator obj)) (input> :static-id client-id :type type :dojoType dojo-type :name client-id :class class :value value (wcomponent-informal-parameters obj)))) (defclass djtextarea (ctextarea djwidget) () (:metaclass metacomponent) (:documentation "This class inherits from a CINPUT, but is used to render a dojo dijit.form.Textarea") (:default-initargs :dojo-type "dijit.form.Textarea" :tag-name "textarea")) (defmethod wcomponent-template ((obj djtextarea)) (let ((client-id (htcomponent-client-id obj)) (tag-name (djwidget-tag-name obj)) (dojo-type (djwidget-dojo-type obj)) (translator (translator obj)) (value "") (class (claw::css-class obj))) (when (component-validation-errors obj) (if (or (null class) (string= class "")) (setf class "dijitError") (setf class (format nil "~a dijitError" class)))) (setf value (translator-encode translator obj)) (if (string-equal tag-name "textarea") (textarea> :static-id client-id :dojoType dojo-type :name (name-attr obj) :class class (wcomponent-informal-parameters obj) (or (when value ($raw> value)) (htcomponent-body obj))) (let ((tag-name (djwidget-tag-name obj)) (parameters (nconc (list :static-id (htcomponent-client-id obj) :dojo-type (djwidget-dojo-type obj) :name (name-attr obj)) (djwidget-formal-parameters obj)))) (build-tagf tag-name 'tag (not (null (find tag-name *empty-tags*))) (list parameters (wcomponent-informal-parameters obj) (or (when value ($raw> value)) (htcomponent-body obj)))))))) (defclass djsimple-textarea (djtextarea) () (:metaclass metacomponent) (:documentation "This class inherits from a CINPUT, but is used to render a dojo dijit.form.SimpleTextarea") (:default-initargs :dojo-type "dijit.form.SimpleTextarea" :type "text")) (defclass djvalidation-text-box (djtext-box) () (:metaclass metacomponent) (:documentation "This class inherits from a CINPUT, but is used to render a dojo dijit.form.ValidationTextBox") (:default-initargs :dojo-type "dijit.form.ValidationTextBox" :type "text" :dojo-require (list "dijit.form.ValidationTextBox"))) (defclass djmapped-text-box (djvalidation-text-box) () (:metaclass metacomponent) (:documentation "This class inherits from a DJVALIDATION-TEXT-BOX, but is used to render a dojo dijit.form.MappedTextBox") (:default-initargs :dojo-type "dijit.form.MappedTextBox")) (defclass djrange-bound-text-box (djvalidation-text-box) () (:metaclass metacomponent) (:documentation "This class inherits from a DJVALIDATION-TEXT-BOX, but is used to render a dojo dijit.form.RangeBoundTextBox") (:default-initargs :dojo-type "dijit.form.RangeBoundTextBox")) (defclass djnumber-text-box (djtext-box) () (:metaclass metacomponent) (:documentation "This class inherits from a CINPUT, but is used to render a dojo dijit.form.NumberTextBox") (:default-initargs :dojo-type "dijit.form.NumberTextBox" :type "text")) (defclass djnumber-spinner (djtext-box) () (:metaclass metacomponent) (:documentation "This class inherits from a CINPUT, but is used to render a dojo dijit.form.NumberSpinner") (:default-initargs :dojo-type "dijit.form.NumberSpinner" :type "text")) (defclass djcheck-box (ccheckbox djwidget) () (:metaclass metacomponent) (:documentation "This class inherits from a CCHECKBOX, but is used to render a dojo dijit.form.CheckBox") (:default-initargs :dojo-type "dijit.form.CheckBox")) (defmethod wcomponent-template ((cinput djcheck-box)) (let* ((client-id (htcomponent-client-id cinput)) (dojo-type (djwidget-dojo-type cinput)) (translator (translator cinput)) (type (input-type cinput)) (value (translator-value-type-to-string translator (ccheckbox-value cinput))) (current-value (translator-type-to-string translator cinput)) (class (css-class cinput))) (when (component-validation-errors cinput) (if (or (null class) (string= class "")) (setf class "error") (setf class (format nil "~a error" class)))) (input> :static-id client-id :type type :dojoType dojo-type :name (name-attr cinput) :class class :value value :checked (when (and current-value (equal value current-value)) "checked") (wcomponent-informal-parameters cinput)))) (defclass djradio-button (cradio djwidget) () (:metaclass metacomponent) (:documentation "This class inherits from a CRADIO, but is used to render a dojo dijit.form.CheckBox") (:default-initargs :dojo-type "dijit.form.RadioButton" :dojo-require (list "dijit.form.CheckBox"))) (defmethod wcomponent-template ((cinput djradio-button)) (let* ((client-id (htcomponent-client-id cinput)) (translator (translator cinput)) (type (input-type cinput)) (dojo-type (djwidget-dojo-type cinput)) (value (translator-value-type-to-string translator (ccheckbox-value cinput))) (current-value (translator-type-to-string translator cinput)) (class (css-class cinput))) (when (component-validation-errors cinput) (if (or (null class) (string= class "")) (setf class "error") (setf class (format nil "~a error" class)))) (input> :static-id client-id :type type :dojoType dojo-type :name (name-attr cinput) :class class :value value :checked (when (and current-value (equal value current-value)) "checked") (wcomponent-informal-parameters cinput)))) (defclass djcombo-box (cinput djwidget) () (:metaclass metacomponent) (:documentation "This class inherits from a CSELECT, but is used to render a dojo dijit.form.ComboBox") (:default-initargs :dojo-type "dijit.form.ComboBox" :multiple nil)) (defmethod wcomponent-template ((obj djcombo-box)) (let ((client-id (htcomponent-client-id obj)) (dojo-type (djwidget-dojo-type obj)) (translator (translator obj)) (value "") (class (claw::css-class obj))) (when (component-validation-errors obj) (if (or (null class) (string= class "")) (setf class "dijitError") (setf class (format nil "~a dijitError" class)))) (setf value (translator-encode translator obj)) (select> :static-id client-id :dojoType dojo-type :name client-id :class class :value value :multiple (cinput-result-as-list-p obj) (wcomponent-informal-parameters obj) (htcomponent-body obj)))) (defclass djmulti-select (djcombo-box) () (:metaclass metacomponent) (:documentation "This class inherits from a DJVALIDATION-TEXT-BOX, but is used to render a dojo dijit.form.MultiSelect") (:default-initargs :dojo-type "dijit.form.MultiSelect" :multiple t)) (defclass djfiltering-select (djcombo-box) ((onchange :initarg :onchange)) (:metaclass metacomponent) (:documentation "This class inherits from a CSELECT, but is used to render a dojo dijit.form.FilteringSelect") (:default-initargs :dojo-type "dijit.form.FilteringSelect")) (defclass djinline-edit-box (cinput djwidget) ((autosavep :initarg :autosavep :reader djinline-edit-box-autosavep :documentation "Changing the value automatically saves it; don't have to push save button \(and save button isn't even displayed)") (button-save :initarg :button-save :reader djinline-edit-box-button-save :documentation "Save button label") (button-cancel :initarg :button-cancel :reader djinline-edit-box-button-cancel :documentation "Cancel button label") (render-as-html :initarg :render-as-html :accessor djinline-edit-box-render-as-html :documentation "Set this to true if the specified Editor's value should be interpreted as HTML rather than plain text \(ie, dijit.Editor)") (editor :initarg :editor :reader djinline-edit-box-editor :documentation "The widget used to edit the value")) (:metaclass metacomponent) (:documentation "Class for dojo dijit.InLineEditBox. More info at http://api.dojotoolkit.org/") (:default-initargs :empty t :dojo-type "dijit.InlineEditBox" :tag-name "span" :autosavep t :button-save nil :button-cancel nil :render-as-html nil :editor "dijit.form.TextBox")) (defmethod wcomponent-template ((obj djinline-edit-box)) (let ((id (htcomponent-client-id obj)) (tag-name (djwidget-tag-name obj)) (auto-save (if (djinline-edit-box-autosavep obj) "true" "false")) (button-save (djinline-edit-box-button-save obj)) (button-cancel (djinline-edit-box-button-cancel obj)) (render-as-html (if (djinline-edit-box-render-as-html obj) "true" "false")) (editor (djinline-edit-box-editor obj)) (value "")) (build-tagf tag-name 'tag nil :static-id id :value value :autosave auto-save :buttonsave button-save :buttoncancel button-cancel :renderashtml render-as-html :editor editor (wcomponent-informal-parameters obj)))) (defmethod htcomponent-instance-initscript((obj djinline-edit-box)) (let ((id (htcomponent-client-id obj)) (page-url (page-url (htcomponent-page obj)))) (ps* `(dojo.connect (dijit.by-id ,id) "onChange" (lambda (e) (dojo.xhrPost (create :url ,page-url :error (lambda (data) (console.error data)) :timeout 2000 :handle-as "json" :content (create :json (array) ,*rewind-parameter* ,id)))))))) (defclass djdate-text-box (djtext-box) () (:metaclass metacomponent) (:documentation "This class inherits from a CINPUT, but is used to render a dojo dijit.form.DateTextBox") (:default-initargs :dojo-type "dijit.form.DateTextBox" :type "text" :translator *date-translator-ymd*)) (defclass djtime-text-box (djtext-box) () (:metaclass metacomponent) (:documentation "This class inherits from a CINPUT, but is used to render a dojo dijit.form.DateTextBox") (:default-initargs :dojo-type "dijit.form.TimeTextBox" :type "text" :translator *date-translator-time*)) (defclass djcalendar (djtext-box) () (:metaclass metacomponent) (:documentation "This class inherits from a CINPUT, but is used to render a dojo dijit._Calendar") (:default-initargs :dojo-type "dijit._Calendar" :dojo-require (list "dijit._Calendar" "dojo.date.locale") :type "text" :translator *date-translator-ymd*)) (defclass djcurrency-text-box (djtext-box) () (:metaclass metacomponent) (:documentation "This class inherits from a CINPUT, but is used to render a dojo dijit.form.CurrencyTextBox") (:default-initargs :dojo-type "dijit.form.CurrencyTextBox" :type "text")) (defclass _djslider (djwidget) () (:metaclass metacomponent) (:documentation "Base class to map dojo dijit.form.Slider. More info at http://api.dojotoolkit.org/") (:default-initargs :dojo-require (list "dijit.form.Slider"))) (defclass _djslider-slider (cinput _djslider) () (:metaclass metacomponent) (:default-initargs :reserved-parameters (list :value :name) :translator *number-translator*) (:documentation "Base class to map dojo dijit.form.HorizontalSlider and dijit.form.VerticalSlider. More info at http://api.dojotoolkit.org/")) (defmethod wcomponent-template ((_djslider-slider _djslider-slider)) (let ((client-id (htcomponent-client-id _djslider-slider)) (translator (translator _djslider-slider)) (value "") (class (css-class _djslider-slider))) (when (component-validation-errors _djslider-slider) (if (or (null class) (string= class "")) (setf class "dijitError") (setf class (format nil "~a dijitError" class)))) (setf value (translator-encode translator _djslider-slider)) (div> :static-id client-id :dojoType (djwidget-dojo-type _djslider-slider) :value value :class class :name (name-attr _djslider-slider) (wcomponent-informal-parameters _djslider-slider) (htcomponent-body _djslider-slider)))) (defclass djhorizontal-slider (_djslider-slider) () (:metaclass metacomponent) (:documentation "Class for dojo dijit.form.HorizontalSlider. More info at http://api.dojotoolkit.org/") (:default-initargs :dojo-type "dijit.form.HorizontalSlider")) (defclass djhorizontal-rule (_djslider) () (:metaclass metacomponent) (:documentation "Class for dojo dijit.form.HorizontalRule. More info at http://api.dojotoolkit.org/") (:default-initargs :dojo-type "dijit.form.HorizontalRule")) (defclass djhorizontal-rule-labels (_djslider) () (:metaclass metacomponent) (:documentation "Class for dojo dijit.form.HorizontalRuleLabels. Renders like an
    tag element, so put
  1. tag elements inside. More info at http://api.dojotoolkit.org/") (:default-initargs :dojo-type "dijit.form.HorizontalRuleLabels" :tag-name "ol")) (defclass djvertical-slider (_djslider-slider) () (:metaclass metacomponent) (:documentation "Class for dojo dijit.form.VerticalSlider. More info at http://api.dojotoolkit.org/") (:default-initargs :dojo-type "dijit.form.VerticalSlider")) (defclass djvertical-rule (_djslider) () (:metaclass metacomponent) (:documentation "Class for dojo dijit.form.VerticalRule. More info at http://api.dojotoolkit.org/") (:default-initargs :dojo-type "dijit.form.VerticalRule")) (defclass djvertical-rule-labels (_djslider) () (:metaclass metacomponent) (:documentation "Class for dojo dijit.form.VerticalRuleLabels. Renders like an
      tag element, so put
    1. tag elements inside. More info at http://api.dojotoolkit.org/") (:default-initargs :dojo-type "dijit.form.VerticalRuleLabels" :tag-name "ol")) (defclass djtext-box-file (djtext-box) () (:metaclass metacomponent) (:documentation "This class inherits from a CINPUT of type \"file\", but is used to render a dojo dijit.form.DateTextBox") (:default-initargs :dojo-type "dojox.widget.FileInput" :type nil :translator *file-translator*)) (defmethod htcomponent-stylesheet-files((djtext-box-file djtext-box-file)) (list (format nil "~a/dojotoolkit/dojox/widget/FileInput/FileInput.css" (clawserver-base-path (current-server))))) (defclass djeditor (djtextarea) ((form :initform nil :accessor djeditor-form)) (:metaclass metacomponent) (:documentation "Class for dojo dijit.Editor. More info at http://api.dojotoolkit.org/") (:default-initargs :dojo-type "claw.Editor" :tag-name "div")) (defclass djeditor-plugins-always-show-toolbar (djwidget) () (:metaclass metacomponent) (:documentation "Class for dojo dijit.Editor. More info at http://api.dojotoolkit.org/") (:default-initargs :dojo-type "dijit._editor.plugins.AlwaysShowToolbar" :tag-name nil)) (defclass djeditor-plugins-enter-key-handling (djwidget) () (:metaclass metacomponent) (:documentation "Class for dojo dijit.Editor. More info at http://api.dojotoolkit.org/") (:default-initargs :dojo-type "dijit._editor.plugins.EnterKeyHandling" :tag-name nil)) (defclass djeditor-plugins-font-choice (djwidget) () (:metaclass metacomponent) (:documentation "Class for dojo dijit.Editor. More info at http://api.dojotoolkit.org/") (:default-initargs :dojo-type "dijit._editor.plugins.FontChoice" :tag-name nil)) (defclass djeditor-plugins-link-dialog (djwidget) () (:metaclass metacomponent) (:documentation "Class for dojo dijit.Editor. More info at http://api.dojotoolkit.org/") (:default-initargs :dojo-type "dijit._editor.plugins.LinkDialog" :tag-name nil)) (defclass djeditor-plugins-text-color (djwidget) () (:metaclass metacomponent) (:documentation "Class for dojo dijit.Editor. More info at http://api.dojotoolkit.org/") (:default-initargs :dojo-type "dijit._editor.plugins.TextColor" :tag-name nil)) (defclass djeditor-plugins-toggle-dir (djwidget) () (:metaclass metacomponent) (:documentation "Class for dojo dijit.Editor. More info at http://api.dojotoolkit.org/") (:default-initargs :dojo-type "dijit._editor.plugins.ToggleDir" :tag-name nil))