diff --git a/clog-base.lisp b/clog-base.lisp index a2df57e..83e48d4 100644 --- a/clog-base.lisp +++ b/clog-base.lisp @@ -84,6 +84,30 @@ result. (Private)")) (cc:query (connection-id obj) (format nil "~A.~A" (jquery obj) method))) +;;;;;;;;;;;;; +;; execute ;; +;;;;;;;;;;;;; + +(defgeneric execute (clog-obj method) + (:documentation "Execute the js METHOD on OBJ. Result is +dicarded. (Private)")) + +(defmethod execute ((obj clog-obj) method) + (cc:execute (connection-id obj) + (format nil "~A.~A" (script-id obj) method))) + +;;;;;;;;;;; +;; query ;; +;;;;;;;;;;; + +(defgeneric query (clog-obj method) + (:documentation "Execute the js query METHOD on OBJ and return +result. (Private)")) + +(defmethod query ((obj clog-obj) method) + (cc:query (connection-id obj) + (format nil "~A.~A" (script-id obj) method))) + ;;;;;;;;;;;;;;;;;;;;;;; ;; bind-event-script ;; ;;;;;;;;;;;;;;;;;;;;;;; @@ -142,8 +166,8 @@ result. (Private)")) ;;;;;;;;;;;;;;;;;;;;;;;;;; (defparameter keyboard-event-script - "+ e.keyCode + ':' + e.charCode + ':' + e.altKey + ':' + e.ctrlKey + ':' - + e.shiftKey + ':' + e.metaKey") + "+ e.keyCode + ':' + e.charCode + ':' + e.altKey + ':' + e.ctrlKey + ':' + + e.shiftKey + ':' + e.metaKey") (defun parse-keyboard-event (data) (let ((f (ppcre:split ":" data))) @@ -187,7 +211,7 @@ result. (Private)")) (:documentation "Set html property.")) (defmethod set-property ((obj clog-obj) property-name value) - (jquery-execute obj (format nil "prop('~A','~A')" property-name value))) + (jquery-execute obj (format nil "prop('~A','~A')" property-name (escape-string value)))) (defsetf property set-property) ;;;;;;;;;;; @@ -204,7 +228,7 @@ result. (Private)")) (:documentation "Set css style.")) (defmethod set-style ((obj clog-obj) style-name value) - (jquery-execute obj (format nil "css('~A','~A')" style-name value))) + (jquery-execute obj (format nil "css('~A','~A')" style-name (escape-string value)))) (defsetf style set-style) ;;;;;;;;;;;;;;; @@ -221,7 +245,7 @@ result. (Private)")) (:documentation "Set html tag attribute.")) (defmethod set-attribute ((obj clog-obj) attribute-name value) - (jquery-execute obj (format nil "attr('~A','~A')" attribute-name value))) + (jquery-execute obj (format nil "attr('~A','~A')" attribute-name (escape-string value)))) (defsetf attribute set-attribute) ;;;;;;;;;;;; diff --git a/clog-body.lisp b/clog-body.lisp index bc266cd..22416df 100644 --- a/clog-body.lisp +++ b/clog-body.lisp @@ -17,9 +17,9 @@ ((window :reader window :initarg :window) - (document + (html-document :reader html-document - :initarg :document) + :initarg :html-document) (location :reader location :initarg :location) @@ -37,10 +37,10 @@ (make-instance 'clog-body :connection-id connection-id :html-id 0 - :window (make-instance 'clog-window :connection-id connection-id) - :window (make-instance 'clog-document :connection-id connection-id) - :window (make-instance 'clog-location :connection-id connection-id) - :window (make-instance 'clog-navigator :connection-id connection-id))) + :window (make-clog-window connection-id) + :html-document (make-clog-document connection-id) + :location (make-clog-location connection-id) + :navigator (make-clog-navigator connection-id))) ;;;;;;;;;;;; ;; window ;; diff --git a/clog-document.lisp b/clog-document.lisp index 2736e76..64481fe 100644 --- a/clog-document.lisp +++ b/clog-document.lisp @@ -23,3 +23,161 @@ (defun make-clog-document (connection-id) "Construct a new clog-document. (Private)" (make-instance 'clog-document :connection-id connection-id :html-id "document")) + +;;;;;;;;;;;; +;; domain ;; +;;;;;;;;;;;; + +(defgeneric domain (clog-document) + (:documentation "Get domain.")) + +(defmethod domain ((obj clog-document)) + (query obj "domain")) + +;;;;;;;;;;;;;;;;;;;; +;; input-encoding ;; +;;;;;;;;;;;;;;;;;;;; + +(defgeneric input-encoding (clog-document) + (:documentation "Get input encoding.")) + +(defmethod input-encoding ((obj clog-document)) + (query obj "inputEncoding")) + +;;;;;;;;;;;;;;;;;;; +;; last-modified ;; +;;;;;;;;;;;;;;;;;;; + +(defgeneric last-modified (clog-document) + (:documentation "Get last modified.")) + +(defmethod last-modified ((obj clog-document)) + (query obj "lastModified")) + +;;;;;;;;;;;;; +;; referer ;; +;;;;;;;;;;;;; + +(defgeneric referer (clog-document) + (:documentation "Get referer.")) + +(defmethod referer ((obj clog-document)) + (query obj "referer")) + +;;;;;;;;;;; +;; title ;; +;;;;;;;;;;; + +(defgeneric title (clog-document) + (:documentation "Get/setf title.")) + +(defmethod title ((obj clog-document)) + (query obj "title")) + +(defgeneric set-title (clog-document value)) + +(defmethod set-title ((obj clog-document) value) + (execute obj (format nil "title='~A'" (cc:escape-string value)))) +(defsetf title set-title) + +;;;;;;;;; +;; url ;; +;;;;;;;;; + +(defgeneric url (clog-document) + (:documentation "Get url.")) + +(defmethod url ((obj clog-document)) + (query obj "url")) + +;;;;;;;;;;;;;;;;;;;;;; +;; document-element ;; +;;;;;;;;;;;;;;;;;;;;;; + +(defgeneric document-element (clog-document) + (:documentation "Get document-element.")) + +(defmethod document-element ((obj clog-document)) + (make-instance 'clog-base :connection-id (connection-id obj) :html-id "documentElement")) + +;;;;;;;;;;;;;;;;;; +;; head-element ;; +;;;;;;;;;;;;;;;;;; + +(defgeneric head-element (clog-document) + (:documentation "Get head-element.")) + +(defmethod head-element ((obj clog-document)) + (make-instance 'clog-base :connection-id (connection-id obj) :html-id "head")) + +;;;;;;;;;; +;; body ;; +;;;;;;;;;; + +(defgeneric body-element (clog-document) + (:documentation "Get body-element.")) + +(defmethod body-element ((obj clog-document)) + (make-instance 'clog-base :connection-id (connection-id obj) :html-id "body")) + +;;;;;;;;;;;;;;;;; +;; ready-state ;; +;;;;;;;;;;;;;;;;; + +(defgeneric ready-state (clog-document) + (:documentation "Get ready-state.")) + +(defmethod ready-state ((obj clog-document)) + (query obj "readyState")) + +;;;;;;;;;;;;;; +;; load-css ;; +;;;;;;;;;;;;;; + +(defgeneric load-css (clog-document css-url) + (:documentation "Load css from CSS-URL.")) + +(defmethod load-css ((obj clog-document) css-url) + (jquery-execute (head-element obj) + (format nil "append('')" (escape-string css-url)))) + +;;;;;;;;; +;; put ;; +;;;;;;;;; + +(defgeneric put (clog-document message) + (:documentation "Write text to browser document object.")) + +(defmethod put ((obj clog-document) message) + (execute obj (format nil "write('~A')" (escape-string message)))) + +;;;;;;;;;;;;;; +;; put-line ;; +;;;;;;;;;;;;;; + +(defgeneric put-line (clog-document message) + (:documentation "Write text to browser document object with new-line.")) + +(defmethod put-line ((obj clog-document) message) + (execute obj (format nil "writeln('~A')" (escape-string message)))) + +;;;;;;;;;;;; +;; put-br ;; +;;;;;;;;;;;; + +(defgeneric put-br (clog-document message) + (:documentation "Write text to browser document object with <\br>new-line.")) + +(defmethod put-br ((obj clog-document) message) + (execute obj (format nil "writeln('~A<\br>')" (escape-string message)))) + +;;;;;;;;;;;;;; +;; new-line ;; +;;;;;;;;;;;;;; + +(defgeneric new-line (clog-document) + (:documentation "Write to browser document <\br>new-line.")) + +(defmethod new-line ((obj clog-document)) + (execute obj (format nil "writeln('<\br>')"))) diff --git a/clog-utilities.lisp b/clog-utilities.lisp index b370385..2a29074 100644 --- a/clog-utilities.lisp +++ b/clog-utilities.lisp @@ -28,3 +28,16 @@ (defun open-browser (&key (url "http://127.0.0.1:8080")) "Open a web browser to URL." (trivial-open-browser:open-browser url)) + +;;;;;;;;;;;;;;;;;;; +;; escape-string ;; +;;;;;;;;;;;;;;;;;;; + +(defun escape-string (str) + "Escape STR for sending to browser script." + (let ((res)) + (setf res (ppcre:regex-replace-all "\\x22" str "\\x22")) + (setf res (ppcre:regex-replace-all "\\x27" res "\\x27")) + (setf res (ppcre:regex-replace-all "\\x0A" res "\\x0A")) + (setf res (ppcre:regex-replace-all "\\x0D" res "\\x0D")) + res)) diff --git a/clog-window.lisp b/clog-window.lisp index b2265e9..7c77251 100644 --- a/clog-window.lisp +++ b/clog-window.lisp @@ -33,12 +33,12 @@ window.")) (defmethod window-name ((obj clog-window)) - (property obj "name")) + (query obj "name")) (defgeneric set-window-name (clog-window value)) (defmethod set-window-name ((obj clog-window) value) - (setf (property obj "name") value)) + (execute obj "name" (escape-string value))) (defsetf window-name set-window-name) ;;;;;;;;;;;;;;;; @@ -49,12 +49,12 @@ window.")) (:documentation "Get/Setf status bar text.")) (defmethod status-bar ((obj clog-window)) - (property obj "status")) + (query obj "status")) (defgeneric set-status-bar (clog-window value)) (defmethod set-status-bar ((obj clog-window) value) - (setf (property obj "status") value)) + (execute obj "status" (escape-string value))) (defsetf status-bar set-status-bar) ;;;;;;;;;;;;;;;;;; @@ -65,12 +65,12 @@ window.")) (:documentation "Get/Setf inner height of browser window.")) (defmethod inner-height ((obj clog-window)) - (property obj "innerHeight")) + (query obj "innerHeight")) (defgeneric set-inner-height (clog-window value)) (defmethod set-inner-height ((obj clog-window) value) - (setf (property obj "innerHeight") value)) + (execute obj "innerHeight" value)) (defsetf inner-height set-inner-height) ;;;;;;;;;;;;;;;;; @@ -81,12 +81,12 @@ window.")) (:documentation "Get/Setf inner width of browser window.")) (defmethod inner-width ((obj clog-window)) - (property obj "innerWidth")) + (query obj "innerWidth")) (defgeneric set-inner-width (clog-window value)) (defmethod set-inner-width ((obj clog-window) value) - (setf (property obj "innerWidth") value)) + (execute obj "innerWidth" value)) (defsetf inner-width set-inner-width) ;;;;;;;;;;;;;;;;;; @@ -97,12 +97,12 @@ window.")) (:documentation "Get/Setf outer height of browser window.")) (defmethod outer-height ((obj clog-window)) - (property obj "outerHeight")) + (query obj "outerHeight")) (defgeneric set-outer-height (clog-window value)) (defmethod set-outer-height ((obj clog-window) value) - (setf (property obj "outerHeight") value)) + (execute obj "outerHeight" value)) (defsetf outer-height set-outer-height) ;;;;;;;;;;;;;;;;; @@ -113,12 +113,12 @@ window.")) (:documentation "Get/Setf outer width of browser window.")) (defmethod outer-width ((obj clog-window)) - (property obj "outerWidth")) + (query obj "outerWidth")) (defgeneric set-outer-width (clog-window value)) (defmethod set-outer-width ((obj clog-window) value) - (setf (property obj "outerWidth") value)) + (execute obj "outerWidth" value)) (defsetf outer-width set-outer-width) ;;;;;;;;;;;;;; @@ -129,12 +129,12 @@ window.")) (:documentation "Get/Setf browser window x offset from left edge.")) (defmethod x-offset ((obj clog-window)) - (property obj "pageXOffset")) + (query obj "pageXOffset")) (defgeneric set-x-offset (clog-window value)) (defmethod set-x-offset ((obj clog-window) value) - (setf (property obj "pageXOffset") value)) + (execute obj "pageXOffset" value)) (defsetf x-offset set-x-offset) ;;;;;;;;;;;;;; @@ -145,13 +145,13 @@ window.")) (:documentation "Get/Setf browser window y offset from top edge.")) (defmethod y-offset ((obj clog-window)) - (property obj "pageYOffset")) + (query obj "pageYOffset")) (defgeneric set-y-offset (clog-window value)) (defmethod set-y-offset ((obj clog-window) value) - (setf (property obj "pageYOffset") value)) + (execute obj "pageYOffset" value)) (defsetf y-offset set-y-offsett) ;;;;;;;;; @@ -162,12 +162,12 @@ window.")) (:documentation "Get/Setf browser y postion.")) (defmethod top ((obj clog-window)) - (property obj "screenY")) + (query obj "screenY")) (defgeneric set-top (clog-window value)) (defmethod set-top ((obj clog-window) value) - (setf (property obj "screenY") value)) + (exectue obj "screenY" value)) (defsetf top set-top) ;;;;;;;;;; @@ -178,12 +178,12 @@ window.")) (:documentation "Get/Setf browser x position.")) (defmethod left ((obj clog-window)) - (property obj "screenX")) + (query obj "screenX")) (defgeneric set-left (clog-window value)) (defmethod set-left ((obj clog-window) value) - (setf (property obj "screenX") value)) + (execute obj "screenX" value)) (defsetf left set-x-offset) ;;;;;;;;;;;;;;;;; @@ -194,7 +194,7 @@ window.")) (:documentation "Get device pixel ratio.")) (defmethod pixel-ratio ((obj clog-window)) - (property obj "devicePixelRatio")) + (query obj "devicePixelRatio")) ;;;;;;;;;;; ;; alert ;; @@ -205,7 +205,7 @@ window.")) events and messages may not be trasmitted on most browsers.")) (defmethod alert ((obj clog-window) message) - (cc:alert-box (connection-id obj) message)) + (execute obj (format nil "alert('~A');" (escape-string message)))) ;;;;;;;;;;;;;;;;; ;; log-console ;; @@ -215,8 +215,8 @@ events and messages may not be trasmitted on most browsers.")) (:documentation "Print message to browser console.")) (defmethod log-console ((obj clog-window) message) - (cc:execute (connection-id obj) (format nil "console.log('~A')" - (cc:escape-string message)))) + (execute obj (format nil "console.log('~A')" + (escape-string message)))) ;;;;;;;;;;;;;;; ;; log-error ;; @@ -226,8 +226,8 @@ events and messages may not be trasmitted on most browsers.")) (:documentation "Print error message to browser console.")) (defmethod log-error ((obj clog-window) message) - (cc:execute (connection-id obj) (format nil "console.error('~A')" - (cc:escape-string message)))) + (execute obj (format nil "console.error('~A')" + (escape-string message)))) ;;;;;;;;;;;;;;;;;; ;; print-window ;; @@ -237,7 +237,7 @@ events and messages may not be trasmitted on most browsers.")) (:documentation "Send browser window to printer.")) (defmethod print-window ((obj clog-window)) - (cc:execute (connection-id obj) "print()")) + (execute obj "print()")) ;;;;;;;;;;;;;;; ;; Scroll-by ;; @@ -247,7 +247,7 @@ events and messages may not be trasmitted on most browsers.")) (:documentation "Scroll browser window by x y.")) (defmethod scroll-by ((obj clog-window) x y) - (jquery-execute obj (format nil "scrollBy(~A,~A)" x y))) + (execute obj (format nil "scrollBy(~A,~A)" x y))) ;;;;;;;;;;;;;;; ;; scroll-to ;; @@ -257,7 +257,7 @@ events and messages may not be trasmitted on most browsers.")) (:documentation "Scroll browser window to x y.")) (defmethod scroll-to ((obj clog-window) x y) - (jquery-execute obj (format nil "scrollTo(~A,~A)" x y))) + (execute obj (format nil "scrollTo(~A,~A)" x y))) ;;;;;;;;;;;;;;;;;; ;; close-window ;; @@ -267,7 +267,7 @@ events and messages may not be trasmitted on most browsers.")) (:documentation "Close browser window.")) (defmethod close-window ((obj clog-window)) - (jquery-execute obj "close()")) + (execute obj "close()")) ;;;;;;;;;;;;;;;;;;;;;; ;; close-connection ;; @@ -360,6 +360,20 @@ If ON-ORIENTATION-CHANGE-HANDLER is nil unbind the event.")) ;; Set-on-storage ;; ;;;;;;;;;;;;;;;;;;;; +;; need to change to use a true on-storage event + +(defparameter storage-event-script + "+ e.originalEvent.key + ':' + + e.originalEvent.oldValue + ':' + + e.originalEvent.newValue + ':'") + +(defun parse-storage-event (data) + (let ((f (ppcre:split ":" data))) + (list + :key-value (nth 0 f) + :old-value (nth 1 f) + :new-value (nth 2 f)))) + (defgeneric set-on-storage (clog-window on-storage-handler) (:documentation "Set the ON-STORAGE-HANDLER for CLOG-OBJ. If ON-STORAGE-HANDLER is nil unbind the event.")) @@ -368,8 +382,8 @@ ON-STORAGE-HANDLER is nil unbind the event.")) (let ((on-storage on-storage-handler)) (set-event obj "storage" (lambda (data) - (declare (ignore data)) - (funcall on-storage))))) + (funcall on-storage (parse-storage-event data))) + :call-back-script storage-event-script))) ;;;;;;;;;;;;;;;;;;; ;; Set-on-resize ;; diff --git a/clog.lisp b/clog.lisp index 69250fe..292f7e6 100644 --- a/clog.lisp +++ b/clog.lisp @@ -43,8 +43,9 @@ application." (defsection @clog-utilities (:title "CLOG Utilities") "CLOG utilities" - (js-true-p function) - (open-browser function)) + (js-true-p function) + (open-browser function) + (escape-string function)) (defsection @clog-obj (:title "CLOG Objects") "CLOG-Obj - Base class for CLOG Objects" @@ -161,7 +162,23 @@ application." (defsection @clog-document (:title "CLOG Document Objects") "CLOG-Document - CLOG Document Objects" - (clog-document class)) + (clog-document class) + + (domain generic-function) + (input-encoding generic-function) + (last-modified generic-function) + (referrer generic-function) + (title generic-function) + (url generic-function) + (head-element generic-function) + (body-element generic-function) + (document-element generic-function) + (ready-state generic-function) + (load-css generic-function) + (put generic-function) + (put-line generic-function) + (put-br generic-function) + (put-newline generic-function)) (defsection @clog-location (:title "CLOG Location Objects") "CLOG-Location - CLOG Location Objects" diff --git a/test/test-clog.lisp b/test/test-clog.lisp index bc4a9b3..ffe6c14 100644 --- a/test/test-clog.lisp +++ b/test/test-clog.lisp @@ -10,6 +10,7 @@ (defun on-new-window (win) (log-console (window win) "Message!") (log-error (window win) "Error Log") + (put-br (html-document win) "test 1 2 3") (setf *last-win* win) (let ((tmp)) (clog-connection:put-line (clog::connection-id win) "") @@ -39,6 +40,8 @@ (set-on-character win (lambda (data) (print data))) + (setf (title (html-document win)) "CLOG Test App") + (print (title (html-document win))) )) (defun test ()