Last active
December 31, 2020 13:14
-
-
Save bamboospirit/a10164fe425d90809ea23f2d32747a0e to your computer and use it in GitHub Desktop.
weblocks simple toast effect (common lisp web framework ui frontend)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;; 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