(in-package :lisp-on-lines) ;;;; for when there is nothing left to display. (defcomponent empty-page (window-component) ()) (defmethod render-on ((res response) (self empty-page)) "didnt find a thing") (defcomponent auto-complete () ((input-id :accessor input-id :initform (arnesi:random-string 10 arnesi:+ascii-alphabet+)) (output-id :accessor output-id :initform (arnesi:random-string 10 arnesi:+ascii-alphabet+)) (client-value :accessor client-value :initform "" :documentation "The string the user has, so far, insterted.") (index :accessor index :initform nil :documentation "The index (for use with NTH) in list-of-values of the item selected via Ajax") (list-of-values :accessor list-of-values :initform '() :documentation "The list generated by values-generator") (values-generator :accessor values-generator :initarg :values-generator :documentation "Function which, when passed the auto-complete component, returns a list of objects.") (value :accessor value :initform nil :documentation "The lisp value of the object selecting in the drop down") (as-value :accessor as-value :initarg :as-value :documentation "Function which, when passed a value, returns the string to put in the text box.") (render :accessor render :initarg :render :documentation "Function which, when passed the component and one of the values render it (the value).") (input-size :accessor input-size :initarg :input-size :initform 20) (submit-on-select-p :accessor submit-on-select-p :initarg :submit-on-select-p :initform t) (output-component-name :accessor output-component-name :initarg :output-comonent-name :initform 'auto-complete-output))) (defmethod js-on-complete ((l auto-complete)) `(lambda (transport) (setf (slot-value (document.get-element-by-id ,(output-id l)) 'inner-h-t-m-l) transport.response-text))) (defmacro make-action-url (component action) " There has got to be something like this buried in UCW somewhere, but here's what i use." `(ucw::print-uri-to-string (compute-url ,component :action-id (ucw::make-new-action (ucw::context.current-frame *context*) (lambda () (arnesi:with-call/cc ,action)))))) (defun generate-ajax-request (js-url &optional js-options) `(new (*Ajax.*Request ,js-url ,js-options))) (defmacro with-ajax-request (js-url &rest js-options) `(generate-ajax-request-for-url ,js-url ,@js-options)) (defmacro with-ajax-action ((component) &body action) `(generate-ajax-request (make-action-url ,component (progn ,@action)))) (defaction call-auto-complete ((self t) auto-complete-id value index) (let ((auto-complete (get-session-value (intern auto-complete-id)))) (if auto-complete (if index (select-value auto-complete index) (call-auto-complete-from-output auto-complete auto-complete-id value self)) (call 'empty-page :message (error "Cannot find"))))) (defaction call-auto-complete-from-output ((auto-complete auto-complete) auto-complete-id value output) (setf (client-value auto-complete) value) (let ((self output)) (call (output-component-name auto-complete) :auto-complete auto-complete) (call 'empty-page :message (error "ASD")))) (defaction select-value ((self auto-complete) index) (let ((index (when (< 0 (length index)) (parse-integer index)))) (setf (index self) index) (setf (value self) (nth index (list-of-values self))))) (defun make-auto-complete-url (input-id) "creates a url that calls the auto-complete entry-point for INPUT-ID." (format nil "auto-complete.ucw?&auto-complete-id=~A&~A=~A" input-id ucw::+session-parameter-name+ (ucw::session.id (ucw::context.session ucw::*context*)))) (defaction on-submit ((l auto-complete)) ()) (defmethod js-on-select ((l auto-complete)) "the javascript that is called when an item is selected" (when (submit-on-select-p l) `(progn (set-action-parameter ,(register-action (lambda () (arnesi:with-call/cc (on-submit l))))) (submit-form)))) (defmethod render-on ((res response) (l auto-complete)) ;; session-values are stored in an eql hash table. (let ((input-key (intern (input-id l)))) ;; We are storing the input components in the session, ;; keyed on the string that we also use as the id for ;; the input field. (unless (get-session-value input-key) (setf (get-session-value input-key) l)) ;; A hidden field to hold the index number selected via javascript (