Skip to content

Instantly share code, notes, and snippets.

@bamboospirit
Last active December 31, 2020 13:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bamboospirit/a10164fe425d90809ea23f2d32747a0e to your computer and use it in GitHub Desktop.
Save bamboospirit/a10164fe425d90809ea23f2d32747a0e to your computer and use it in GitHub Desktop.
weblocks simple toast effect (common lisp web framework ui frontend)
;;; load the code below then open 127.0.0.1:4002 in the browser and Click on "Click me", the toast should show up.
(ql:quickload '(:weblocks :weblocks-lass :weblocks-navigation-widget :weblocks-ui :find-port))
(defpackage app-package
(:use #:cl
#:weblocks-ui/form
#:weblocks/html)
(:import-from #:parenscript #:ps #:chain)
(:import-from #:weblocks-navigation-widget #:defroutes)
(:import-from #:weblocks/routes #:reset-routes)
(:import-from #:weblocks/session #:*session*)
(:import-from #:weblocks/dependencies #:make-dependency #:get-dependencies #:*cache-remote-dependencies-in*)
(:import-from #:weblocks/widget
#:render
#:update
#:defwidget)
(:import-from #:weblocks/actions
#:make-js-action)
(:import-from #:weblocks/app
#:defapp))
(in-package app-package)
(defwidget toast-widget ()
((text :initarg :text :reader text-of :initform "")))
(defmethod weblocks/dependencies:get-dependencies ((widget toast-widget))
(append
(list
(make-instance 'weblocks-lass:lass-dependency
:type :css
:css "#toast {
visibility: hidden;
min-width: 250px;
-125px;
background-color: #333;
color: #fff;
text-align: center;
border-radius: 2px;
padding: 16px;
position: fixed;
z-index: 1;
left: 50%;
bottom: 30px;
font-size: 17px;
}
#toast.show {
visibility: visible;
-webkit-animation: fadein 0.5s, fadeout 0.5s 2.5s;
animation: fadein 0.5s, fadeout 0.5s 2.5s;
}
@-webkit-keyframes fadein {
from {bottom: 0; opacity: 0;}
to {bottom: 30px; opacity: 1;}
}
@keyframes fadein {
from {bottom: 0; opacity: 0;}
to {bottom: 30px; opacity: 1;}
}
@-webkit-keyframes fadeout {
from {bottom: 30px; opacity: 1;}
to {bottom: 0; opacity: 0;}
}
@keyframes fadeout {
from {bottom: 30px; opacity: 1;}
to {bottom: 0; opacity: 0;}
}")
(weblocks-parenscript:make-dependency
(setf (chain window show-toast)
(lambda ()
(let ((x (chain document (get-element-by-id 'toast))))
(setf (chain x class-name) 'show)
(set-timeout (lambda()
(setf (chain x class-name)
(chain x class-name (replace 'show ""))))
3000))))))
(call-next-method)))
(setf weblocks/js/jquery::*js-dependencies*
(list (make-dependency "https://code.jquery.com/jquery-3.5.1.min.js" ; change to relative path if needed
;; :integrity "sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ="
;:system :your_asdf_system_name ; it can be relative to your asdf system
)
(make-dependency "src/js/jquery/jquery.js"
:system :weblocks)
(make-dependency "src/js/jquery/jquery.ba-bbq.js"
:system :weblocks)
(make-dependency "src/js/jquery/jquery-seq.js"
:system :weblocks)
(make-dependency "src/js/jquery/progress.gif"
:system :weblocks)
#|
|#
))
(defmethod render ((toast toast-widget))
(with-slots (title text) toast
(with-html
(:div :id "toast" text))))
(defwidget js-script-widget () ; a widget which when rendered just executes js code on the page
((code :initarg :code :reader code-of :initform "")))
(defmethod render ((js-script js-script-widget))
(with-slots (code) js-script
(with-html
(:script :type "text/javascript" code))))
(defmethod execute ((js-script js-script-widget) jscode)
(with-slots (code activep) js-script
(setf code jscode)
(update js-script)
(setf code "") ; the widgets get created only when the session is new (for example open new private window in browser and open the page, it will call :initform (make-instance 'js-script widget :code "") , otherwise not
; so to avoid multiple execution of the same code because the user pressed refresh and js-scipt was rendered, we set code back to ""
))
(defwidget abstract-root-widget () ;;; 'global' functionality for the webpage : the ability to execute any js code & the ability to display toasts
((js-script :initarg :js-script :accessor js-script-of :initform (make-instance 'js-script-widget :code ""))
(toast :initarg :toast :accessor toast-of :initform (make-instance 'toast-widget :text ""))))
(defmethod render ((w abstract-root-widget))
(with-slots (js-script toast) w
(with-html
(render toast)
(render js-script))))
(defun toast (text)
"can be called from any lisp code, it will show the toast in the running session"
(with-slots (toast js-script) (weblocks/session:get-value 'page-widget)
(setf (slot-value toast 'text) text)
(update toast)
(execute js-script "showToast();"))) ; the showToast javascript function was defined in toast widget's parenscript dependency
(defwidget mypage-widget (abstract-root-widget)
())
(defun make-mypage-widget ()
(let ((widget (make-instance 'mypage-widget)))
(if *session* ; we need this if so that we can use make-mypage-widget in the repl outside of a browser session
(setf (weblocks/session:get-value 'page-widget) widget)
widget)))
(defmethod render ((page mypage-widget) )
(setf (weblocks/page:get-title) "My page title")
(with-html
(call-next-method) ; abstract-page-widget's render method
(:h1 "Page Title")
(:hr)
;(render other stuff)
(:input :type "button"
:onclick
(when *session* ; condition needed so that we can render page in the repl when *session* is nil
(make-js-action ; compile the lambda function into a js action
(lambda (&key &allow-other-keys)
(log:debug "Preparing to fire the toast")
(toast "It works!"))))
:value "Click me")))
(defapp my-app
:prefix "/"
; :description ""
; :autostart nil
; :debug t
)
(reset-routes) ; delete all routes
(defroutes main-routes
("/" (make-mypage-widget))
;("/tasks/\\d+" (make-task-page))
;(t (page-not-found))
)
(defmethod weblocks/session:init ((app my-app))
(declare (ignorable app))
(make-main-routes))
(weblocks/debug:on)
; (setf weblocks/variables:*invoke-debugger-on-error* t)
(setf *srv* (weblocks/server:start :port 4002 :interface "0.0.0.0"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment