Tutorial 19

This commit is contained in:
David Botton 2021-01-31 23:16:10 -05:00
parent 1dc4c72dc3
commit 1ef2735aba
12 changed files with 543 additions and 16 deletions

View file

@ -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

View file

@ -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 ;;

View file

@ -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 "<li~A>~A</li>"
(escape-string content)
(if class
(format nil " class='~A'"
(escape-string class))
""))
"")
(escape-string content))
:clog-type 'clog-list-item :auto-place auto-place))
;;;;;;;;;;;;;;;;

View file

@ -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)

View file

@ -536,6 +536,32 @@ are stored in this string based hash in the format of:
<p>Returns true if connection is valid on this <code>CLOG-OBJ</code>.</p></li>
</ul>
<p>CLOG-Obj - Internals for Extension Plugins</p>
<p><a id='x-28CLOG-3AHTML-ID-20GENERIC-FUNCTION-29'></a></p>
<ul>
<li><p><span class=reference-bullet><span class=reference><span class="locative-type">[generic-function]</span> <span class="reference-object"><a href="#x-28CLOG-3AHTML-ID-20GENERIC-FUNCTION-29" >HTML-ID</a></span></span> <span class="locative-args">CLOG-OBJ</span></span></p>
<p>Internal html-id of CLOG-Obj. (Internal)</p></li>
</ul>
<p><a id='x-28CLOG-3AJS-EXECUTE-20GENERIC-FUNCTION-29'></a></p>
<ul>
<li><p><span class=reference-bullet><span class=reference><span class="locative-type">[generic-function]</span> <span class="reference-object"><a href="#x-28CLOG-3AJS-EXECUTE-20GENERIC-FUNCTION-29" >JS-EXECUTE</a></span></span> <span class="locative-args">CLOG-OBJ SCRIPT</span></span></p>
<p>Execure <code>SCRIPT</code> on browser. (Internal)</p></li>
</ul>
<p><a id='x-28CLOG-3AJS-QUERY-20GENERIC-FUNCTION-29'></a></p>
<ul>
<li><p><span class=reference-bullet><span class=reference><span class="locative-type">[generic-function]</span> <span class="reference-object"><a href="#x-28CLOG-3AJS-QUERY-20GENERIC-FUNCTION-29" >JS-QUERY</a></span></span> <span class="locative-args">CLOG-OBJ SCRIPT &amp;KEY DEFAULT-ANSWER</span></span></p>
<p>Execure <code>SCRIPT</code> on browser and return result. (Internal)</p></li>
</ul>
<p>CLOG-Obj - Event Handling</p>
<p><a id='x-28CLOG-3ASET-ON-RESIZE-20GENERIC-FUNCTION-29'></a></p>
@ -5052,6 +5078,30 @@ on-storage event is fired for changes to :local storage keys.</p></li>
<p>Run tutorial <code>NUM</code></p></li>
</ul>
<p><a id='x-28CLOG-3ALOAD-TUTORIAL-20FUNCTION-29'></a></p>
<ul>
<li><p><span class=reference-bullet><span class=reference><span class="locative-type">[function]</span> <span class="reference-object"><a href="#x-28CLOG-3ALOAD-TUTORIAL-20FUNCTION-29" >LOAD-TUTORIAL</a></span></span> <span class="locative-args">NUM</span></span></p>
<p>Load tutorial <code>NUM</code> - use (clog-user:start-tutorial)</p></li>
</ul>
<p><a id='x-28CLOG-3ARUN-DEMO-20FUNCTION-29'></a></p>
<ul>
<li><p><span class=reference-bullet><span class=reference><span class="locative-type">[function]</span> <span class="reference-object"><a href="#x-28CLOG-3ARUN-DEMO-20FUNCTION-29" >RUN-DEMO</a></span></span> <span class="locative-args">NUM</span></span></p>
<p>Run demo <code>NUM</code></p></li>
</ul>
<p><a id='x-28CLOG-3ALOAD-DEMO-20FUNCTION-29'></a></p>
<ul>
<li><p><span class=reference-bullet><span class=reference><span class="locative-type">[function]</span> <span class="reference-object"><a href="#x-28CLOG-3ALOAD-DEMO-20FUNCTION-29" >LOAD-DEMO</a></span></span> <span class="locative-args">NUM</span></span></p>
<p>Load demo <code>NUM</code> - use (clog-user:start-demo)</p></li>
</ul>
<p>Functions for Compilation and Documentation</p>
<p><a id='x-28CLOG-3ALOAD-WORLD-20FUNCTION-29'></a></p>
@ -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][].</p>
stored in the clog array keyed by the html-id clog<a href="#x-28CLOG-3AHTML-ID-20GENERIC-FUNCTION-29" title="(CLOG:HTML-ID GENERIC-FUNCTION)"><code>html-id</code></a>.</p>
<p><em>* Client Side Scripting *</em></p>

View file

@ -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.

View file

@ -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
<script src="jsLists.min.js"></script>
```
Calling JSLists is simple. In the example below, we simply pass the ID of the list we want to collapse:
```html
<script>JSLists.applyToList('simple_list', 'ALL');</script>
```
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.

View file

@ -0,0 +1,173 @@
<!doctype html>
<html>
<head>
<title>JSLists - Very simple nested list [Example 1]</title>
<link rel="stylesheet" href="jsLists.css"/>
<style>
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
body {
font-family: Arial, Helvetica, sans-serif;
font-size: 16px;
}
header {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 90px;
background-color: rgb(156, 158, 160);
padding-left: 18px;
}
header > div {
position: relative;
display: inline-block;
top: 50%;
transform: translateY(-50%);
font-size: 3.4rem;
font-weight: 900;
}
main {
position: absolute;
top: 90px;
height: calc(100vh - 90px);
}
main > div:nth-child(1) {
padding: 16px;
}
main > div:nth-child(2) {
padding: 18px;
}
</style>
</head>
<body>
<header><div>JSLists</div></header>
<main>
<div style='height: 100%; width: 30%; float: left; overflow-y: scroll;'>
<div style='font-size: 1.4rem; font-weight:700;'>Example 1:</div>
<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><br>
<div style='font-size: 1.4rem; font-weight:700;'>Example 2:</div>
<ul id='f1drivers' class='jslists'>
<li>Formula One Drivers (2018)
<ul>
<li>&#9679; Lewis Hamilton</li>
<li>&#9679; Sebastian Vettel</li>
<li>&#9679; Kimi Räikkönen</li>
<li>&#9679; Valtteri Bottas</li>
<li>&#9679; Daniel Ricciardo</li>
<li>&#9679; Max Verstappen</li>
<li>&#9679; Nico Hülkenberg</li>
<li>&#9679; Kevin Magnussen</li>
<li>&#9679; Fernando Alonso</li>
<li>&#9679; Sergio Pérez</li>
<li>&#9679; Carlos Sainz Jr.</li>
<li>&#9679; Esteban Ocon</li>
<li>&#9679; Pierre Gasly</li>
<li>&#9679; Romain Grosjean</li>
<li>&#9679; Charles Leclerc</li>
<li>&#9679; Stoffel Vandoorne</li>
<li>&#9679; Marcus Ericsson</li>
<li>&#9679; Lance Stroll</li>
<li>&#9679; Brendon Hartley</li>
<li>&#9679; Sergey Sirotkin</li>
</ul>
</li>
</ul><br>
<div style='font-size: 1.4rem; font-weight:700;'>Example 3:</div>
<ul id='f1combined' class='jslists'>
<li>Formula One combined (2018)
<ul>
<li>Scuderia Ferrari
<ul>
<li>&#9679; Sebastian Vettel</li>
<li>&#9679; Kimi Räikkönen</li>
</ul>
</li>
<li>Mercedes AMG
<ul>
<li>&#9679; Lewis Hamilton</li>
<li>&#9679; Valtteri Bottas</li>
</ul>
</li>
<li>Haas F1 Team
<ul>
<li>&#9679; Romain Grosjean</li>
<li>&#9679; Kevin Magnussen</li>
</ul>
</li>
<li>McLaren F1 Team
<ul>
<li>&#9679; Fernando Alonso</li>
<li>&#9679; Stoffel Vandoorne</li>
</ul>
</li>
<li>Red Bull Racing
<ul>
<li>&#9679; Max Verstappen</li>
<li>&#9679; Daniel Ricciardo</li>
</ul>
</li>
<li>Renault
<ul>
<li>&#9679; Max Verstappen</li>
<li>&#9679; Daniel Ricciardo</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<div style='height: 100%; width: 70%; float: left; overflow-y: scroll; font-size: 1.15rem;'>
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<br><br>
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 &lt;a&gt;, &lt;img&gt;, &lt;div&gt; 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. <br><br>
The markup for the Formula One Teams list to the left is:<br>
&lt;ul id='f1teams' class='jslists'&gt;<br>
&emsp;&lt;li&gt;Formula One Teams (2018)<br>
&emsp;&emsp;&lt;ul&gt;<br>
&emsp;&emsp;&emsp;&lt;li&gt;&amp;#9675; Scuderia Ferrari&lt;/li&gt;<br>
&emsp;&emsp;&emsp;&lt;li&gt;&amp;#9675; Sahara Force India F1 Team&lt;/li&gt;<br>
&emsp;&emsp;&emsp;&lt;li&gt;&amp;#9675; Haas F1 Team&lt;/li&gt;<br>
&emsp;&emsp;&emsp;&lt;li&gt;&amp;#9675; McLaren F1 Team&lt;/li&gt;<br>
&emsp;&emsp;&emsp;&lt;li&gt;&amp;#9675; Mercedes AMG Petronas Motorsport&lt;/li&gt;<br>
&emsp;&emsp;&emsp;&lt;li&gt;&amp;#9675; Aston Martin Red Bull Racing&lt;/li&gt;<br>
&emsp;&emsp;&emsp;&lt;li&gt;&amp;#9675; Renault Sport Formula One Team&lt;/li&gt;<br>
&emsp;&emsp;&emsp;&lt;li&gt;&amp;#9675; Alfa Romeo Sauber F1 Team&lt;/li&gt;<br>
&emsp;&emsp;&emsp;&lt;li&gt;&amp;#9675; Red Bull Toro Rosso Honda&lt;/li&gt;<br>
&emsp;&emsp;&emsp;&lt;li&gt;&amp;#9675; Williams Martini Racing&lt;/li&gt;<br>
&emsp;&emsp;&lt;/ul&gt;<br>
&emsp;&lt;/li&gt;<br>
&lt;/ul&gt;<br><br>
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.
</div>
</main>
<script src="jsLists.js"></script>
<script>
// JSLists.createTree("simple_list");
JSLists.createTree("f1teams");
JSLists.createTree("f1drivers");
JSLists.createTree("f1combined");
</script>
</body>
</html>

View file

@ -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,<svg aria-hidden="true" data-prefix="far" data-icon="plus-square" class="svg-inline--fa fa-plus-square fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M352 240v32c0 6.6-5.4 12-12 12h-88v88c0 6.6-5.4 12-12 12h-32c-6.6 0-12-5.4-12-12v-88h-88c-6.6 0-12-5.4-12-12v-32c0-6.6 5.4-12 12-12h88v-88c0-6.6 5.4-12 12-12h32c6.6 0 12 5.4 12 12v88h88c6.6 0 12 5.4 12 12zm96-160v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zm-48 346V86c0-3.3-2.7-6-6-6H54c-3.3 0-6 2.7-6 6v340c0 3.3 2.7 6 6 6h340c3.3 0 6-2.7 6-6z"></path></svg>');
background-repeat: no-repeat;
background-position: center;
}
.jsl-open {display: block;}
.jsl-list-open {background-image: url('data:image/svg+xml;utf8,<svg aria-hidden="true" data-prefix="far" data-icon="minus-square" class="svg-inline--fa fa-minus-square fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M108 284c-6.6 0-12-5.4-12-12v-32c0-6.6 5.4-12 12-12h232c6.6 0 12 5.4 12 12v32c0 6.6-5.4 12-12 12H108zM448 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zm-48 346V86c0-3.3-2.7-6-6-6H54c-3.3 0-6 2.7-6 6v340c0 3.3 2.7 6 6 6h340c3.3 0 6-2.7 6-6z"></path></svg>');}

View file

@ -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 = '&#9679; ';
var openCircle = '&#9678; ';
(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<liItems.length; i++) {
if(liItems[i].hasChildNodes()) {
for(j=0; j<liItems[i].childNodes.length; j++) {
if(liItems[i].childNodes[j].innerHTML == searchTerm) {
//?????
}
}
}
}
}
JSLists.collapseAll = function(listId) {
var i, ulLists = document.getElementsByTagName("UL");
for(i=0; i<ulLists.length; i++) {
if(ulLists[i].className == "jsl-collapsed") {
console.log(ulLists[i].className + '\n' + '@');
}
};
};
JSLists.openAll = function(listId){
var i, olLists = Array.prototype.slice.call(document.getElementsByTagName("UL")),
ulLists = Array.prototype.slice.call(document.getElementsByTagName("OL"))
var gLists = olLists.concat(ulLists);
for(i=1; i<gLists.length; i++) {
gLists[i].setAttribute('class', 'jsl-open');
};
};
JSLists.padUnorderedLists = function(listId) {
var i, listItems = document.getElementById(listId).getElementsByTagName("UL");
for(i=0; i<listItems.length; i++) {
listItems[i].classList.add('jslist-ul');
}
};
JSLists.padOrderedLists = function(listId) {
var i, listItems = document.getElementById(listId).getElementsByTagName("UL");
for(i=0; i<listItems.length; i++) {
listItems[i].classList.add('jslist-ol');
}
};
JSLists.padLists = function(listId) {
var i, listItems = document.getElementById(listId).getElementsByTagName("LI");
for(i=0; i<listItems.length; i++) {
if(listItems[i].childNodes[0].className != "jsl-collapsed-arrow") {
listItems[i].classList.add('jslist-li');
}
}
for(i=1; i<listItems.length; i++) {
// console.log(listItems[i].childNodes.length);
if(listItems[i].classList = "jslist-li" && listItems[i].childNodes.length < 2) {
listItems[i].innerHTML = blackCircle + listItems[i].innerHTML
}
}
this.padUnorderedLists(listId);
this.padOrderedLists(listId);
};
JSLists.createTree = function(listId, bulletPoint) {
document.getElementById(listId).style.display = "none;"
var i, j, curElem, ulCount, olCount, listItems = document.getElementById(listId).getElementsByTagName('LI'); //this should be the main parent
for(i=0; i<listItems.length; i++) {
if(listItems[i].id.length > 0) {
curElem = document.getElementById(listItems[i].id);
ulCount = document.getElementById(listItems[i].id).getElementsByTagName("UL");
if(ulCount.length > 0){
for(j=0; j<ulCount.length; j++) {
if(ulCount[j].nodeName == "UL") {
break;
}
}
ulCount[j].setAttribute('class', 'jsl-collapsed');
var tglDiv = document.createElement("div");
tglDiv.setAttribute('class', 'jsl-list-closed');
tglDiv.setAttribute("id", listItems[i].id + i +'_tgl');
curElem.insertBefore(tglDiv, curElem.childNodes[0]);
document.getElementById(listItems[i].id + i +'_tgl').addEventListener('click', function(e) {
document.getElementById(e.target.id).classList.toggle('jsl-list-open');
document.getElementById(e.target.id).parentElement.lastElementChild.classList.toggle('jsl-open');
e.stopPropagation();
},true);
}
} else {
listItems[i].setAttribute("id", listId+"tmp"+i);
curElem = document.getElementById(listId+"tmp"+i);
ulCount = document.getElementById(listItems[i].id).getElementsByTagName("UL");
if(ulCount.length > 0) { //There is a nested UL in this LI element, now find the position of the UL
for(j=0; j<ulCount.length; j++) {
if(ulCount[j].nodeName == "UL") {
break; //Multiple UL's? //Set class collapseAll here
}
}
ulCount[j].setAttribute('class', 'jsl-collapsed');
var tglDiv = document.createElement("div");
tglDiv.setAttribute('class', 'jsl-list-closed');
tglDiv.setAttribute("id", listItems[i].id + i +'_tgl');
curElem.insertBefore(tglDiv, curElem.childNodes[0]);
document.getElementById(listItems[i].id + i +'_tgl').addEventListener('click', function(e){
document.getElementById(e.target.id).classList.toggle('jsl-list-open');
document.getElementById(e.target.id).parentElement.lastElementChild.classList.toggle('jsl-open');
e.stopPropagation();
},true);
}
listItems[i].removeAttribute("id");
}
}
setTimeout(function() {
document.getElementById(listId).style.display = "block;"
}, 50); // stops FOUC!
this.padLists(listId);
};
// JSLists.applyToList = function(listId, listType, applyIcons, applyTheme, themeNumber){
//Check the params here
// does the id exist?
JSLists.applyToList = function(listId, bulletPoint) {
this.createTree(listId, "UL");
};
return JSLists;
}
//define the JSLists library in the global namespace if it doesn't already exist
if(typeof(JSLists) === 'undefined') {
window.JSLists = define_JSLists();
}else{
console.log("JSLists already defined.");
}
})();

36
tutorial/19-tutorial.lisp Normal file
View file

@ -0,0 +1,36 @@
(defpackage #:clog-user
(:use #:cl #:clog)
(:export start-tutorial))
(in-package :clog-user)
;; In this tutorial we will see how to easily use a JavaScript
;; component. In the static-files directory there is a simple java
;; component (clog/static-files/tutorial/jslists) to create
;; collapsible trees that we will use for this tutorial.
(defun on-new-window (body)
;; First we need to load jslists' JavaScript file and css
(load-css (html-document body) "/tutorial/jslists/jsLists.css")
(load-script (html-document body) "/tutorial/jslists/jsLists.js")
;; Second we need to build an example list. jsLists uses an ordered
;; or unordered list for it's data.
(let* ((list-top (create-unordered-list body))
(item (create-list-item list-top :content "Top of tree"))
(list-b (create-unordered-list item))
(item (create-list-item list-b :content "Item 1"))
(item (create-list-item list-b :content "Item 2"))
(item (create-list-item list-b :content "Item 3"))
(item (create-list-item list-b :content "Item 4")))
(js-execute body (format nil "JSLists.applyToList('~A', 'ALL');"
(html-id list-top)))
(run body)))
(defun start-tutorial ()
"Start turtorial."
(initialize #'on-new-window)
(open-browser))

View file

@ -51,3 +51,4 @@ 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