Skip to content

Instantly share code, notes, and snippets.

@svetlyak40wt
Created September 24, 2020 20:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save svetlyak40wt/72e49d6699e0b18f8575a13559a3ae72 to your computer and use it in GitHub Desktop.
Save svetlyak40wt/72e49d6699e0b18f8575a13559a3ae72 to your computer and use it in GitHub Desktop.
Example of autocompletion box using Weblocks
;; This example illustrates how to call actions from JS and update the widget in response.
;; It is incomplete but could be refactored into reusable library.
;; Hope, somebody will do this some day.
(defpackage #:weblocks-autocomplete
(:use #:cl))
(in-package weblocks-autocomplete)
(ql:quickload '(weblocks log4cl))
(defparameter *data-to-complete*
(list
"Ahmedabad"
"Alexandria"
"Atlanta"
"Baghdad"
"Bangalore"
"Bangkok"
"Barcelona"
"Beijing"
"Belo Horizonte"
"Bogot√°"
"Buenos"
"Cairo"
"Chengdu"
"Chennai"
"Chicago"
"Chongqing"
"Dalian"
"Dallas"
"Dar es Salaam"
"Delhi"
"Dhaka"
"Dongguan"
"Foshan"
"Fukuoka"
"Guadalajara"
"Guangzhou"
"Hangzhou"
"Harbin"
"Ho Chi Minh City"
"Hong Kong"
"Houston"
"Hyderabad"
"Istanbul"
"Jakarta"
"Jinan"
"Johannesburg"
"Karachi"
"Khartoum"
"Kinshasa"
"Kolkata"
"Kuala Lumpur"
"Lagos"
"Lahore"
"Lima"
"London"
"Los"
"Luanda"
"Madrid"
"Manila"
"Mexico"
"Miami"
"Moscow"
"Mumbai"
"Nagoya"
"Nanjing"
"New"
"Osaka"
"Paris"
"Philadelphia"
"Pune"
"Qingdao"
"Rio"
"Riyadh"
"Saint Petersburg"
"Santiago"
"Seoul"
"Shanghai"
"Shenyang"
"Shenzhen"
"Singapore"
"Surat"
"Suzhou"
"S√£o"
"Tehran"
"Tianjin"
"Tokyo"
"Toronto"
"Washington, D.C."
"Wuhan"
"Xi'an"
"Yangon"))
(weblocks/widget:defwidget completions ()
((visible :initform nil
:reader completions-visible)
(items :initform nil
:reader completions-list)))
(weblocks/widget:defwidget autocomplete-box ()
((action-code :initarg :action-code
:reader action-code)
(completions :initform (make-instance 'completions)
:reader completions)))
(defmethod autocomplete ((widget autocomplete-box) &rest args)
(log:info "Autocompleting" args)
(let* ((completions (completions widget))
(text (getf args :value)))
(setf (slot-value completions 'items)
(remove-if-not (lambda (item)
(str:starts-with-p text item :ignore-case t))
*data-to-complete*))
(setf (slot-value completions 'visible)
t)
(weblocks/widget:update completions)))
(defmethod initialize-instance :after ((obj autocomplete-box) &rest args)
(declare (ignorable args))
(setf (slot-value obj 'action-code)
(weblocks/actions::function-or-action->action
(lambda (&rest args)
(apply #'autocomplete obj args)))))
(defmethod weblocks/widget:render ((box autocomplete-box))
(let ((js-code
(format nil "initiateActionWithArgs(\"~A\", \"\", {\"value\": this.value})"
(action-code box))))
(weblocks/html:with-html
(:input :type "text"
:placeholder "Autocomplete"
:oninput js-code)
(weblocks/widget:render (completions box)))))
(defmethod weblocks/widget:render ((widget completions))
(let ((style (if (completions-visible widget)
(format nil "position:absolute;z-index:1000;background:#F1F1F1;list-style:none;padding:5px;")
(format nil "display:hidden"))))
(weblocks/html:with-html
(:ul :style style
(loop for item in (completions-list widget)
do (:li item))))))
(weblocks/app:defapp test-app
:prefix "/")
(weblocks/widget:defwidget index-page ()
((input :initform (make-instance 'autocomplete-box)
:reader input)))
(defmethod weblocks/widget:render ((widget index-page))
(weblocks/html:with-html
(:p "This is a demo of the autocompletion widget:")
(weblocks/widget:render (input widget))
(:p "A text to check that completion results will float above.")))
(defmethod weblocks/session:init ((app test-app))
(declare (ignorable app))
(make-instance 'index-page))
;; This should be used to add JS and CSS to the widget
;; Examples can be found in the Ultralisp's code:
;; https://github.com/ultralisp/ultralisp/blob/f46cbaf6e8626e52ba0ca632bc50ae9261060f18/src/github/widgets/repositories.lisp#L448-L475
;; (defmethod weblocks/dependencies:get-dependencies ((box autocomplete-box))
;; (append (call-next-method)
;; (weblocks/dependencies:make-dependency)))
@svetlyak40wt
Copy link
Author

Here is a Gif with a demo:

2020-09-24 23 08 21

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment