From 1ef2735aba27502f1d8f25e8e88183af80a4a427 Mon Sep 17 00:00:00 2001 From: David Botton Date: Sun, 31 Jan 2021 23:16:10 -0500 Subject: [PATCH] Tutorial 19 --- README.md | 3 +- clog-base.lisp | 41 +++-- clog-element-common.lisp | 4 +- clog.lisp | 5 + doc/clog-manual.html | 52 +++++- static-files/tutorial/jslists/LICENSE | 21 +++ static-files/tutorial/jslists/README.md | 18 ++ static-files/tutorial/jslists/example.html | 173 ++++++++++++++++++++ static-files/tutorial/jslists/jsLists.css | 24 +++ static-files/tutorial/jslists/jsLists.js | 181 +++++++++++++++++++++ tutorial/19-tutorial.lisp | 36 ++++ tutorial/README.md | 1 + 12 files changed, 543 insertions(+), 16 deletions(-) create mode 100644 static-files/tutorial/jslists/LICENSE create mode 100644 static-files/tutorial/jslists/README.md create mode 100644 static-files/tutorial/jslists/example.html create mode 100644 static-files/tutorial/jslists/jsLists.css create mode 100644 static-files/tutorial/jslists/jsLists.js create mode 100644 tutorial/19-tutorial.lisp diff --git a/README.md b/README.md index 3244496..1b21bc5 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ To load this package and work through tutorials (assuming you have Quicklisp configured): 1. Start emacs then M-x slime -2. In the REPL, run (tutorials currently 1 - 18): +2. In the REPL, run (tutorials currently 1 - 19): ``` CL-USER> (ql:quickload :clog) @@ -163,6 +163,7 @@ Tutorial Summary - 16-tutorial.lisp - Bootstrap 4, Loading css files and javascript - 17-tutorial.lisp - W3.CSS layout example and Form submit methods - 18-tutorial.lisp - Drag and Drop +- 19-tutorial.lisp - Using JavaScript componets Demo Summary diff --git a/clog-base.lisp b/clog-base.lisp index ba54e18..fefe51b 100644 --- a/clog-base.lisp +++ b/clog-base.lisp @@ -38,7 +38,7 @@ lisp and the HTML DOM element.")) ;;;;;;;;;;;;; (defgeneric html-id (clog-obj) - (:documentation "Reader for html-id slot. (Private)")) + (:documentation "Internal html-id of CLOG-Obj. (Internal)")) ;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; connection-data-mutex ;; @@ -68,6 +68,26 @@ during attachment. (Private)")) "'body'" (format nil "clog['~A']" (html-id obj)))) +;;;;;;;;;;;;;;;; +;; js-execute ;; +;;;;;;;;;;;;;;;; + +(defgeneric js-execute (clog-obj script) + (:documentation "Execure SCRIPT on browser. (Internal)")) + +(defmethod js-execute ((obj clog-obj) script) + (cc:execute (connection-id obj) script)) + +;;;;;;;;;;;;;; +;; js-query ;; +;;;;;;;;;;;;;; + +(defgeneric js-query (clog-obj script &key default-answer) + (:documentation "Execure SCRIPT on browser and return result. (Internal)")) + +(defmethod js-query ((obj clog-obj) script &key (default-answer nil)) + (cc:query (connection-id obj) script :default-answer default-answer)) + ;;;;;;;;;;;; ;; jquery ;; ;;;;;;;;;;;; @@ -87,8 +107,7 @@ during attachment. (Private)")) dicarded. (Private)")) (defmethod jquery-execute ((obj clog-obj) method) - (cc:execute (connection-id obj) - (format nil "~A.~A" (jquery obj) method))) + (js-execute obj (format nil "~A.~A" (jquery obj) method))) ;;;;;;;;;;;;;;;;;; ;; jquery-query ;; @@ -99,8 +118,7 @@ dicarded. (Private)")) result or DEFAULT-ANSWER on time out. (Private)")) (defmethod jquery-query ((obj clog-obj) method &key (default-answer nil)) - (cc:query (connection-id obj) - (format nil "~A.~A" (jquery obj) method) + (js-query obj (format nil "~A.~A" (jquery obj) method) :default-answer default-answer)) ;;;;;;;;;;;;; @@ -112,8 +130,7 @@ result or DEFAULT-ANSWER on time out. (Private)")) dicarded. (Private)")) (defmethod execute ((obj clog-obj) method) - (cc:execute (connection-id obj) - (format nil "~A.~A" (script-id obj) method))) + (js-execute obj (format nil "~A.~A" (script-id obj) method))) ;;;;;;;;;;; ;; query ;; @@ -124,8 +141,7 @@ dicarded. (Private)")) result or if time out DEFAULT-ANSWER (Private)")) (defmethod query ((obj clog-obj) method &key (default-answer nil)) - (cc:query (connection-id obj) - (format nil "~A.~A" (script-id obj) method) + (js-query obj (format nil "~A.~A" (script-id obj) method) :default-answer default-answer)) ;;;;;;;;;;;;;;;;;;;;;;; @@ -133,11 +149,12 @@ result or if time out DEFAULT-ANSWER (Private)")) ;;;;;;;;;;;;;;;;;;;;;;; (defgeneric bind-event-script (clog-obj event call-back) - (:documentation "Create the code client side for EVENT CALL-BACK. (Private)")) + (:documentation "Create the code client side for EVENT CALL-BACK. +(Private)")) (defmethod bind-event-script ((obj clog-obj) event call-back) - (jquery-execute - obj (format nil "on('~A',function (e, data){~A})" event call-back))) + (jquery-execute obj (format nil "on('~A',function (e, data){~A})" + event call-back))) ;;;;;;;;;;;;;;;;;;;;;;;;; ;; unbind-event-script ;; diff --git a/clog-element-common.lisp b/clog-element-common.lisp index e6eec69..c657e02 100644 --- a/clog-element-common.lisp +++ b/clog-element-common.lisp @@ -694,11 +694,11 @@ and if :AUTO-PLACE (default t) place-inside-bottom-of CLOG-OBJ")) (class nil) (auto-place t)) (create-child obj (format nil "~A" - (escape-string content) (if class (format nil " class='~A'" (escape-string class)) - "")) + "") + (escape-string content)) :clog-type 'clog-list-item :auto-place auto-place)) ;;;;;;;;;;;;;;;; diff --git a/clog.lisp b/clog.lisp index b368241..708dbb8 100644 --- a/clog.lisp +++ b/clog.lisp @@ -85,6 +85,11 @@ embedded in a native template application.)" (remove-connection-data-item generic-function) (validp generic-function) + "CLOG-Obj - Internals for Extension Plugins" + (html-id generic-function) + (js-execute generic-function) + (js-query generic-function) + "CLOG-Obj - Event Handling" (set-on-resize generic-function) (set-on-focus generic-function) diff --git a/doc/clog-manual.html b/doc/clog-manual.html index 8e1e417..a51ea06 100644 --- a/doc/clog-manual.html +++ b/doc/clog-manual.html @@ -536,6 +536,32 @@ are stored in this string based hash in the format of:

Returns true if connection is valid on this CLOG-OBJ.

+

CLOG-Obj - Internals for Extension Plugins

+ +

+ + + +

+ + + +

+ + +

CLOG-Obj - Event Handling

@@ -5052,6 +5078,30 @@ on-storage event is fired for changes to :local storage keys.

Run tutorial NUM

+

+ + + +

+ + + +

+ + +

Functions for Compilation and Documentation

@@ -5096,7 +5146,7 @@ representation, at least at the time of their creation. The server side representation is a CLOG-obj or one of its descendants that is returned by one of the many create-* functions. The client side representation is the DOM element (or other JavaScript object) itself -stored in the clog array keyed by the html-id clog[html-id][].

+stored in the clog array keyed by the html-id cloghtml-id.

* Client Side Scripting *

diff --git a/static-files/tutorial/jslists/LICENSE b/static-files/tutorial/jslists/LICENSE new file mode 100644 index 0000000..0a08f68 --- /dev/null +++ b/static-files/tutorial/jslists/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 TheTechy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/static-files/tutorial/jslists/README.md b/static-files/tutorial/jslists/README.md new file mode 100644 index 0000000..6e119ed --- /dev/null +++ b/static-files/tutorial/jslists/README.md @@ -0,0 +1,18 @@ +# jslists +A library for creating and managing dynamic collapsible lists. + +When a recent project required a tree view for displaying MI data, I wanted to use a basic HTML list setup. After a quick trawl, there are either heavy weight libraries like jsTree which have a dependency on jQuery or very light weight libraries that didn't really give me what I needed. + +So, I sat down and penned the following little library! It's lightweight enough right now. If I find time I will try and add the features I currently have in dev such as find, expand/close all, drag drop of list nodes. + +Load using a normal script tag +```html + +``` + +Calling JSLists is simple. In the example below, we simply pass the ID of the list we want to collapse: +```html + +``` +There are two parameters in JSLists.applyToList. The first is the ID of the list list you want to collapse. +The second is the list type, so UL [Unordered list], OL [Ordered list], or ALL. diff --git a/static-files/tutorial/jslists/example.html b/static-files/tutorial/jslists/example.html new file mode 100644 index 0000000..f6bfdf2 --- /dev/null +++ b/static-files/tutorial/jslists/example.html @@ -0,0 +1,173 @@ + + + + JSLists - Very simple nested list [Example 1] + + + + +
JSLists
+
+
+
Example 1:
+
    +
  • Formula One Teams (2018) +
      +
    • ○ Scuderia Ferrari
    • +
    • ○ Sahara Force India F1 Team
    • +
    • ○ Haas F1 Team
    • +
    • ○ McLaren F1 Team
    • +
    • ○ Mercedes AMG Petronas Motorsport
    • +
    • ○ Aston Martin Red Bull Racing
    • +
    • ○ Renault Sport Formula One Team
    • +
    • ○ Alfa Romeo Sauber F1 Team
    • +
    • ○ Red Bull Toro Rosso Honda
    • +
    • ○ Williams Martini Racing
    • +
    +
  • +

+
Example 2:
+
    +
  • Formula One Drivers (2018) +
      +
    • ● Lewis Hamilton
    • +
    • ● Sebastian Vettel
    • +
    • ● Kimi Räikkönen
    • +
    • ● Valtteri Bottas
    • +
    • ● Daniel Ricciardo
    • +
    • ● Max Verstappen
    • +
    • ● Nico Hülkenberg
    • +
    • ● Kevin Magnussen
    • +
    • ● Fernando Alonso
    • +
    • ● Sergio Pérez
    • +
    • ● Carlos Sainz Jr.
    • +
    • ● Esteban Ocon
    • +
    • ● Pierre Gasly
    • +
    • ● Romain Grosjean
    • +
    • ● Charles Leclerc
    • +
    • ● Stoffel Vandoorne
    • +
    • ● Marcus Ericsson
    • +
    • ● Lance Stroll
    • +
    • ● Brendon Hartley
    • +
    • ● Sergey Sirotkin
    • +
    +
  • +

+
Example 3:
+
    +
  • Formula One combined (2018) +
      +
    • Scuderia Ferrari +
        +
      • ● Sebastian Vettel
      • +
      • ● Kimi Räikkönen
      • +
      +
    • +
    • Mercedes AMG +
        +
      • ● Lewis Hamilton
      • +
      • ● Valtteri Bottas
      • +
      +
    • +
    • Haas F1 Team +
        +
      • ● Romain Grosjean
      • +
      • ● Kevin Magnussen
      • +
      +
    • +
    • McLaren F1 Team +
        +
      • ● Fernando Alonso
      • +
      • ● Stoffel Vandoorne
      • +
      +
    • +
    • Red Bull Racing +
        +
      • ● Max Verstappen
      • +
      • ● Daniel Ricciardo
      • +
      +
    • +
    • Renault +
        +
      • ● Max Verstappen
      • +
      • ● Daniel Ricciardo
      • +
      +
    • +
    +
  • +
+
+
+ jslists is a small JavaScript library that can turn those pesky unordered & ordered list into a funky tree. + There is an example to the left which demostrates the basic functionality

+ Because JSLists doesn't effect any element of the HTML list you are passing is, you can use all of the functionality of standard HTML list. + So ALL list items can contain any valid HTML elements, such as anchors <a>, <img>, <div> etc. + It's pretty easy to use. To create a tree element, give the UL/OL an id, then simply add another unordered or ordered list as a list item. The text within the list item becomes the heading for that list.

+ The markup for the Formula One Teams list to the left is:
+ <ul id='f1teams' class='jslists'>
+  <li>Formula One Teams (2018)
+   <ul>
+    <li>&#9675; Scuderia Ferrari</li>
+    <li>&#9675; Sahara Force India F1 Team</li>
+    <li>&#9675; Haas F1 Team</li>
+    <li>&#9675; McLaren F1 Team</li>
+    <li>&#9675; Mercedes AMG Petronas Motorsport</li>
+    <li>&#9675; Aston Martin Red Bull Racing</li>
+    <li>&#9675; Renault Sport Formula One Team</li>
+    <li>&#9675; Alfa Romeo Sauber F1 Team</li>
+    <li>&#9675; Red Bull Toro Rosso Honda</li>
+    <li>&#9675; Williams Martini Racing</li>
+   </ul>
+  </li>
+ </ul>

+ You can also create nested lists using jsLists. Check out the source code for Example 3 and you will see the pattern is the same as the standard list. +
+
+ + + + \ No newline at end of file diff --git a/static-files/tutorial/jslists/jsLists.css b/static-files/tutorial/jslists/jsLists.css new file mode 100644 index 0000000..3c63481 --- /dev/null +++ b/static-files/tutorial/jslists/jsLists.css @@ -0,0 +1,24 @@ +*, *:before, *:after {box-sizing: border-box;} +ul, ol {margin: 0; padding: 0;} +li {list-style: none; line-height: 1.6rem;} + +/* List styling */ +.jslists{ + font-size: 1.3rem; + font-family: Arial, Helvetica, sans-serif; +} +.jslist-ul, .jslist-ol, .jslist-li {margin-left: 12px;} /* Unordered lists */ +.jsl-collapsed {display: none;} +.jsl-list-closed { + float: left; + clear: both; + margin: 2px 4px 2px 0px; + width: 18px; + height: 18px; + cursor: pointer; + background-image: url('data:image/svg+xml;utf8,'); + background-repeat: no-repeat; + background-position: center; +} +.jsl-open {display: block;} +.jsl-list-open {background-image: url('data:image/svg+xml;utf8,');} \ No newline at end of file diff --git a/static-files/tutorial/jslists/jsLists.js b/static-files/tutorial/jslists/jsLists.js new file mode 100644 index 0000000..c23cc42 --- /dev/null +++ b/static-files/tutorial/jslists/jsLists.js @@ -0,0 +1,181 @@ +/* + * JSLists v0.4.5 + * © 2016 George Duff + * + * Release date: 01/06/2016 + * The MIT License (MIT) + * Copyright (c) 2016 George Duff + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +// TO DO LIST - Will get round to most of them at some point! +// Add folder & file icons dynamically from param +// Collapse All & Open All are ropey at best! +// Add a search function +// Make the margins user definable +// Add support for UL & OL + +var blackCircle = '● '; +var openCircle = '◎ '; + +(function() { + "use strict"; + function define_JSLists() { + var JSLists = {}; + + var JSLists_Error = function(error, alertType) { + console.log(error); + } + var getUl = function(){ + return document.getElementsByTagName("UL"); + }; + + var getOl = function(){ + return document.getElementsByTagName("OL"); + }; + + var getAllLists = function(){ + var olLists = Array.prototype.slice.call(document.getElementsByTagName("UL")), + ulLists = Array.prototype.slice.call(document.getElementsByTagName("OL")) + var gLists = olLists.concat(ulLists); + return gLists; + } + + JSLists.searchList = function(listId, searchTerm) { + var i, j, lilNodes, liItems = document.getElementsByTagName("LI"); + for(i=0; i 0) { + curElem = document.getElementById(listItems[i].id); + ulCount = document.getElementById(listItems[i].id).getElementsByTagName("UL"); + if(ulCount.length > 0){ + for(j=0; j 0) { //There is a nested UL in this LI element, now find the position of the UL + for(j=0; j