HTML preprocessors can make writing HTML more powerful or convenient. For instance, Markdown is designed to be easier to write and read for text documents and you could write a loop in Pug.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. So you don't have access to higher-up elements like the <html>
tag. If you want to add classes there that can affect the whole document, this is the place to do it.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. If you need things in the <head>
of the document, put that code here.
The resource you are linking to is using the 'http' protocol, which may not work when the browser is using https.
CSS preprocessors help make authoring CSS easier. All of them offer things like variables and mixins to provide convenient abstractions.
It's a common practice to apply CSS to a page that styles elements such that they are consistent across all browsers. We offer two of the most popular choices: normalize.css and a reset. Or, choose Neither and nothing will be applied.
To get the best cross-browser support, it is a common practice to apply vendor prefixes to CSS properties and values that require them to work. For instance -webkit-
or -moz-
.
We offer two popular choices: Autoprefixer (which processes your CSS server-side) and -prefix-free (which applies prefixes via a script, client-side).
Any URLs added here will be added as <link>
s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.
You can apply CSS to your Pen from any stylesheet on the web. Just put a URL to it here and we'll apply it, in the order you have them, before the CSS in the Pen itself.
You can also link to another Pen here (use the .css
URL Extension) and we'll pull the CSS from that Pen and include it. If it's using a matching preprocessor, use the appropriate URL Extension and we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
JavaScript preprocessors can help make authoring JavaScript easier and more convenient.
Babel includes JSX processing.
Any URL's added here will be added as <script>
s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.
You can apply a script from anywhere on the web to your Pen. Just put a URL to it here and we'll add it, in the order you have them, before the JavaScript in the Pen itself.
If the script you link to has the file extension of a preprocessor, we'll attempt to process it before applying.
You can also link to another Pen here, and we'll pull the JavaScript from that Pen and include it. If it's using a matching preprocessor, we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
Search for and use JavaScript packages from npm here. By selecting a package, an import
statement will be added to the top of the JavaScript editor for this package.
Using packages here is powered by esm.sh, which makes packages from npm not only available on a CDN, but prepares them for native JavaScript ESM usage.
All packages are different, so refer to their docs for how they work.
If you're using React / ReactDOM, make sure to turn on Babel for the JSX processing.
If active, Pens will autosave every 30 seconds after being saved once.
If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.
If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.
Visit your global Editor Settings.
import zim from "https://zimjs.org/cdn/016/zim";
// REFERENCES for ZIM at https://zimjs.com
// see https://zimjs.com/intro.html for an intro example
// see https://zimjs.com/learn.html for video and code tutorials
// see https://zimjs.com/docs.html for documentation
// see https://codepen.io/topic/zim/ for ZIM on CodePen
const assets = [
{font: "reuben", src: "Reuben.otf"},
"cathead.png", "catblink.png", "head_smaller.png"
];
const path = "https://assets.codepen.io/2104200/";
const frame = new Frame(FIT, 480, 600, lighter, black, ready, assets, path);
function ready() {
// given F (Frame), S (Stage), W (width), H (height)
// put code here
// CONTEXT
// This quiz was used for the ZIM Cat launch (a few years ago)
// https://zimjs.com/cat.html and press the cat in the top banner.
// For all versions, please see https://zimjs.com/about.html#versions
// Originally, this app handled a set of feature pages going to the left
// MENU PAGE
// ZIM CAT how has a Page class
// that is just a Container with a backing ;-)
// but it will stop people wondering how to make a page in ZIM!
const menu = new Page(W, H, yellow, green).addTo();
// Here is a container that will hold our text and arrows
// we will then animate this in with a sequence
// each child gets animated with a specified delay between
const info = new Container(menu.width, menu.height).addTo(menu);
const cat = new Container(W, H).center(menu).tap(()=>{
pages.go(certPages[0], "right");
});
const cathead = new Pic("cathead.png").sca(.9).pos(30, 0, LEFT, BOTTOM, cat);
const blink = new Pic("catblink.png").sca(.9).center(cat).loc(30, 184).alp(0);
const blinkSeries = series(1, 1, 2, 1, 1, 2, 1, 1, 1, 3, 1, 2, 2, 1);
interval({min: 7, max: 14}, function() {
// running right away so add a small delay here.
interval({min: 1, max: 3}, function() {
blink.alpha = 1;
S.update();
timeout({min: .17, max: .23}, function() {
blink.alpha = 0;
S.update();
});
}, blinkSeries());
}, null, true); // true is run right away
STYLE = {
color: dark,
Label: {
// series will apply these styles in order
lineHeight: series(40, 34),
size: series(38, 32),
align: CENTER,
font: "reuben",
variant: true // small caps
}
};
new Triangle(45, 45, 45).rot(90).loc(399, 422, info);
const labelRight = new Label("ZIM\n\n\nQuiz").hov(grey).loc(391, 341, info);
labelRight.on("mousedown", () => {
pages.go(certPages[0], "right");
});
STYLE = {}; // turn off the previous styles
// For this quiz example on codepen, we are only showing the quiz to right
// it was called a certifiCAT (get it)
const certPages = makeCertPages();
// NAVIGATION
// This looks slightly complex but the system handled
// 20 pages with 80 events and different transitions.
// To put ZIM page management into perspective,
// the code to handle going from a single page to a second page
// in xCode for iOS is probably longer than this code below
// https://www.flickr.com/photos/danzen/4425788955
// Also, since the Cat launch, we have added ZIM Arrow()
// Which works with ZIM Pages to automatically handle page to page
// hold links for all page arrows
const hotSpots = new HotSpots();
// Prepare pages for Page object
// This needs which pages will swipe to which
// The menu page added to start and will push other pages
// The menu swipes to the first certificate page on the right
const pageList = [
// page, then swipes for left, right, up, down
{page:menu, swipe:[null, certPages[0]]}
];
loop(certPages, (page, i) => {
const prev = certPages[i+1]?certPages[i+1]:menu;
const next = certPages[i-1]?certPages[i-1]:menu;
// Pages and swipes
pageList.push({page:page, swipe:[next, prev]});
// HotSpots - arrows
hotSpots.add(page,page.buttonLeft,function(){pages.go(next, LEFT);});
hotSpots.add(page,page.buttonRight,function(){pages.go(prev, RIGHT);});
hotSpots.add(page,page.cat,function(){pages.go(menu, UP, "pixelDark");});
});
const pages = new Pages(pageList, "bubbleZIM", .5, [
// set transition coming back to menu as "pixelDark"
// can specify transition to and from any page like this
[certPages[0], menu, "pixelDark"],
[certPages[certPages.length-1], menu, "pixelDark"]
]).addTo();
pages.puff(.01); // quickly add pages to stage to settle start positions
pages.on("page", function () {
// transform needs to be updated if manually moved - so just hide them
if (pages.lastPage == certPages[3] || pages.page == certPages[3]) {
certPages[3].rect.transformControls.hide();
}
});
pages.on("pagetransitioned", function () {
if (pages.page == certPages[3]) {
certPages[3].rect.transformControls.show();
}
});
function makeCertPages() {
const certPages = [];
// Ten page ZIM CAT Curio test for certifiCAT ;-)
// See header() and footer() functions at the very bottom
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// PAGE 1
// all these could go right on the component
// we are just testing out the styles
STYLE = {
align: CENTER,
sound: true,
Selector: {
borderColor: lighter,
tile: new Tile(new Rectangle(50, 50, series(pink, green, blue)).centerReg(), 3, 1, 10, 10)
},
Slider: {
vertical: false,
useTicks: false,
accentSize: 12,
currentValue: 6
},
Indicator: {
backgroundColor: blue,
foregroundColor: pink,
interactive: true
},
Tabs: {
width: 150,
height: 50,
tabs: {noPick: [1, 2, 3]},
selectedBackgroundColor: blue,
selectedRollBackgroundColor: pink,
currentEnabled: true
},
Toggle: {
backgroundColor: pink.darken(.2),
toggleBackgroundColor: pink.lighten(.1),
startToggled: true
}
};
// ZIM CAT - Style static class
// The Style class holds a number of static methods to help organize STYLE
// STYLE is an object literal and can be manipulated like one at any time
// but just to make some things easier, Style was introduced with the following
// these methods are each just a couple lines of code to work on STYLE
// Style.clear() - clears the STYLE
// same as: STYLE = {};
// Style.clearTypes() - clears the types
// same as: delete STYLE.types;
// Style.clearGroups() - clears the groups
// same as: delete STYLE.groups
// Style.remembered - property for holding remembered styles
// same as: remembered = {};
// Style.remember(id) - stores a copy of the current style in memory at an id or "default"
// same as: remembered[id||"default"] = zim.copy(STYLE); // makes a copy and clones cloneable objects
// Style.clearRemembered(id) - clears all remembered styles
// same as: delete remembered[id||"default"];
// Style.recall(id) - sets the current style to a remembered STYLE
// same as: STYLE = remembered[id];
// Style.add(obj) - adds general styles in form {newStile:val, newStyle2:value}
// same as: STYLE.newStyle = val; STYLE.newStyle2 = val;
// Style.addType(typeName, obj) - adds a type along with its styles - overwrites the same type
// same as: STYLE.type.typeName = obj;
// Style.addGroup(groupName, obj) - adds a group along with its styles - overwrites the same group
// same as: STYLE.group.groupName = obj;
// Style.remove(styleName) - removes a single general style specified as a string - same as delete STYLE.styleName
// same as: delete STYLE.styleName;
// Style.removeType(typeName) - removes a type as string
// same as: delete STYLE.type.typeName
// Style.removeGroup(groupName) - removes a group as a string
// same as: delete STYLE.group.groupName
Style.remember("components"); // store current STYLE as "components"
// ZIM CAT - Tile with new unique parameter (inserted after spacings)
// true below means make the tile unique
// this will make sure items are not cloned which would lose any event
// and it atomatically uses an array in order
// note - if the unique was not set to true, an array would randomize as a ZIM VEE
// we wanted to provide a way for beginners to easily make a tile of unique objects
// and we did not want them to have to remember to use a series()
// So power users can still use ZIM VEE - just don't use unique and remember to set clone false
const page1 = header("Order the Component names", dark);
// ZIM CAT - wire() and wired() let you connect properties of objects
// usually, we are not connecting components
// and the default property happens to be the ZIM DEFAULTWIRE
// which means slider.wire(dial) will make the dial change as the slider changes
// but not the other way around until twoWay is set
const dial = new Dial();
const slider = new Slider().wire(dial, null, true); // true is twoWay
// if you want to wire twoWay but need to change the value in a filter
// for instance - setting the indicator to 3,4,5 sets the tabs to 0,1,2
// and visa versa... we could wire if only one way - but wiring two ways conflicts
// so use event listeners instead which know specifically which component was changed
const selector = new Selector().change(function() {
if (toggle.toggled) indicator.selectedIndex = selector.selectedIndex;
});
const indicator = new Indicator().change(function() {
if (toggle.toggled) {
if (indicator.selectedIndex < 3) selector.selectedIndex = indicator.selectedIndex;
else tabs.selectedIndex = indicator.selectedIndex - 3;
}
});
const tabs = new Tabs().change(function() {
if (toggle.toggled) indicator.selectedIndex = tabs.selectedIndex + 3;
});
const toggle = new Toggle();
new Tile([dial, slider, selector, indicator, toggle, tabs], 1, 6, 0, 40, true)
.sca(.6)
.pos(20, 0, LEFT, CENTER, page1);
Style.clear(); // or STYLE = {}
const tiles = [];
const keys = ["Dial", "Slider", "Selector", "Indicator", "Toggle", "Tabs"];
zim.loop(keys, function(letter, i) {
const tile = new zim.Label({
text: letter,
color: pink.lighten(.8),
font: "reuben",
variant: true,
size: 26,
backing: new zim.Rectangle(160, 40, new RadialColor([purple, pink], [0, 1], 0, 0, 150, 0, 0, 0), null, null, [30, 0, 30, 0]),
align: CENTER,
valign: CENTER,
});
tiles.push(tile);
});
const tile = new Tile({
obj: tiles,
unique: true,
cols: 1,
rows: 6,
spacingV: 16
});
// ZIM CAT - Scrambler Component
// https://zimjs.com/cat/scrambler.html
// scrambles any tile (even with multiple rows and cols)
const scrambler = new Scrambler(tile).pos(50, 5, RIGHT, CENTER, page1);
// Scrambler has a "complete" event for when done
// but here we just want to use the test() method to see if it is correct
// the TEST button is hooked up to call the test function on the page
// it is in the footer and will take care of the results Pane, etc.
page1.test = function() {return scrambler.test();};
footer(page1);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// PAGE 2
const page2 = header("What version of ZIM\ncame just before CAT?", dark);
STYLE = {font: "reuben"};
const list = new List({
width: 300,
height: 300,
selectedIndex: -1,
selectedBackgroundColor: green,
selectedColor: purple,
list: ["ONE", "DUO", "TRI", "4TH", "VEE", "SIX", "HEP", "OCT", "NIO", "TEN", "LEV", "DOZ"]
}).center(page2);
page2.test = function() {
return list.text == "TEN";
};
footer(page2);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// PAGE 3
const page3 = header("Arrange to make\na draggable circle!", dark);
const tiles3 = [];
const keys3 = ["new", "Circle", "()", ".", "drag", "()"];
zim.loop(keys3, function(letter, i) {
const tile = new zim.Label({
text: letter,
color: pink.lighten(.9),
size: 30,
backing: new zim.Rectangle(120, 120, blue),
align: CENTER,
valign: CENTER,
});
tiles3.push(tile);
});
const tile3 = new Tile({
obj: tiles3,
unique: true,
cols: 3,
rows: 2,
spacingH: 5,
spacingV: 5
});
const scrambler3 = new Scrambler(tile3, keys3, "text").center(page3);
page3.test = function() {return scrambler3.test();};
footer(page3);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// PAGE 4
const page4 = header("What method is being used?", dark);
page4.rect = new Rectangle(100, 100, orange).centerReg(page4).mov(-100).transform({
borderColor: white,
borderWidth: 2,
handleSize: 16,
visible: false,
allowToggle: false
});
const buttons4 = new RadioButtons({
buttons: ["gesture()", "transform()", "drag()"],
vertical: true,
inherit: {color: white}
}).sca(.5).center(page4).mov(100);
page4.test = function() {return buttons4.text == "transform()";};
footer(page4);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// PAGE 5
const page5 = header("Identify!", dark);
Style.add({
align: CENTER,
stickColor: white
});
Style.addType("Stepper", {
stepperType: "list",
continuous: true,
width: 400,
scale: .4,
backgroundColor: yellow,
arrowColor: yellow
});
const stepper5_1 = new Stepper(["Wobble", "Doodle", "Squiggle", "Wiggle", "Wave"]);
const stepper5_2 = new Stepper(["Blob", "Bean", "Putty", "Shaper", "Stresso"]);
new Tile([
new Squiggle({length: 230, thickness: 5}),
stepper5_1,
new Blob({color: blue, radius: 50, points: [[13, 30.8, 0, 0, -26.6, -25.4, 26.6, 25.4, "mirror"], [62, 9, 0, 0, -3.1, 27.2, 3.1, -27.2, "mirror"], [-12.1, -39.2, 0, 0, 44.7, -2, -44.7, 2, "mirror"], [-61.2, 28.3, 0, 0, -21.5, -18.2, 21.5, 18.2, "mirror"]]}),
stepper5_2
], 1, 4, 0, 30, true).center(page5); // true for unique
Style.clear();
page5.test = function() {return stepper5_1.currentValue == "Squiggle" && stepper5_2.currentValue == "Blob";};
footer(page5);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// PAGE 6
const page6 = header("What is their name?", dark);
new Pic("pragma.png").sca(.5).center(page6).mov(0, -100);
Style.addType("Label", {
backing: new Rectangle(170, 60, orange),
align: CENTER,
font: "reuben",
color: white,
centerReg: true
});
const tile6 = new Tile([
new Label("Wanda"),
new Label("Pragma"),
new Label("Lula"),
new Label("Tiko")
], 2, 2, 20, 20, true);
Style.clear();
const selector6 = new Selector({tile: tile6, backgroundColor: clear}).center(page6).mov(0, 80);
page6.test = function() {return selector6.selectedIndex == 1;};
footer(page6);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// PAGE 7
const page7 = header("ZIM parameters are like", dark);
STYLE = {color: white};
const buttons7 = new RadioButtons({
buttons: [
"(100, 100, null, null, null, 10)",
"({width:100, height:100, corner:10})",
"either - DUO"
]
}).rot(-30).sca(.5).center(page7).mov(10, -30);
new Rectangle({width: 100, height: 100, corner: 10}).alp(.8).pos(50, 150, RIGHT, BOTTOM, page7);
page7.test = function() {return buttons7.selectedIndex == 2;};
footer(page7);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// PAGE 8
const page8 = header("Which hit test is best?", dark);
const bound = new Rectangle(400, 150, clear, fog, 1, 0, true).center(page8).mov(0, -60);
const rect = new Rectangle(80, 80, pink).center(page8).mov(-70, -60).drag(bound);
const circ = new Circle(40, blue).center(page8).mov(70, -60).drag(bound);
rect.on("pressmove", checkHit);
circ.on("pressmove", checkHit);
function checkHit() {
if (circ.hitTestCircleRect(rect)) {
if (rect.color == pink) {
rect.color = blue;
circ.color = pink;
}
S.update();
} else {
if (rect.color == blue) {
rect.color = pink;
circ.color = blue;
}
S.update();
}
}
STYLE = {
variant: false,
type: {
Stepper: {
stepperType: "list",
color: dark,
width: 700,
scale: .5,
vertical: true,
backgroundColor: yellow,
arrowColor: yellow
}
}
};
const stepper8 = new Stepper([
"hitTestPoint()",
"hitTestReg()",
"hitTestRect()",
"hitTestCircle()",
"hitTestCircleRect()",
"hitTestCircles()",
"hitTestBounds()",
"hitTestPath()",
"hitTestGrid()"
]).center(page8).mov(0, 110);
Style.clear();
new Label({
text: "Drag us!",
color: mist,
font: "reuben",
variant: true,
size: 26
}).loc(184, 125, page8);
page8.test = function() {return stepper8.selectedIndex == 4;};
footer(page8);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// PAGE 9
const page9 = header("ZIM tool to reduce code", dark);
STYLE = {
font: "reuben"
};
const list9 = new List({
height: 300,
width: 320,
selectedIndex: -1,
viewNum: 4.5,
selectedBackgroundColor: green,
selectedColor: purple,
list: [
"ZIMON",
"ZIMIFY",
"WONDER",
"SOCKET",
"MVC",
"NPM",
"SHIM",
"DISTILL",
"TYPESCRIPT",
"ZAP",
"ZOO",
"ASSET LIST",
"CODE ZERO",
"BUBBLING",
"FRAME",
"ACCESSIBILITY",
"BASE",
"PIZZAZZ",
"ZIMPLIFY"
]
}).center(page9);
page9.test = function() {return list9.text == "DISTILL";};
footer(page9);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// PAGE 10
const page10 = header("Who is Dr Abstract?", dark);
// lazy loading images to add dimensions if tiling
const tile10 = new Tile([
new Pic("abstract.png", 177, 177).centerReg(),
new Pic("frank.png", 177, 177).centerReg(),
new Pic("force.png", 177, 177).centerReg(),
new Pic("chris.png", 177, 177).centerReg(),
], 2, 2, 20, 20, true);
const selector10 = new Selector(tile10, pink, 4, clear, (177 + 20) / 2, [50, 10, 5, 10]).sca(.9).center(page10);
Style.addType("Label", {
color: green.darken(.1),
align: CENTER,
lineHeight: 16,
size: 24
});
new Label("d\na\nn\n\nz\ne\nn\n").loc(36, 151, page10);
new Label("f\nr\na\nn\nk\n\nl\no\ns").loc(442, 138, page10);
new Label("c\n\nc\no\ny\ni\ne\nr").loc(442, 329, page10);
new Label("f\nr\na\nn\nk\n\nf\no\nr\nc\ne").loc(36, 304, page10);
page10.test = function() {return selector10.selectedIndex == 0;};
footer(page10);
page10.buttonRight.visible = false;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// GENERAL FUNCTIONS
// overall test results go in here as true or false
const results = [];
function header(instructions, color) {
if (color == null) color = dark;
const page = new Page(W, H, green);
page.cat = new Pic("head_smaller.png").loc(14, -10, page);
F.makeIcon().sca(.3).pos(14, 50, RIGHT, TOP, page);
const backing = new Rectangle(480, 400, color).center(page);
new Label({
text: instructions,
align: CENTER,
valign: BOTTOM,
size: 24,
font: "reuben",
variant: true,
color: dark,
labelWidth: 400
}).loc(W / 2, 80, page).noMouse();
return page;
}
const levels = [
"CATastrophe",
"CATnapper",
"copyCAT",
"CATaloger",
"CATwalker",
"advoCAT",
"CATapulter",
"eduCATer",
"CATalyst",
"CATmando",
"certifiCAT"
];
function footer(page) {
Style.add({variant: true});
Style.addGroup("footer", {font: "reuben", color: purple});
// new Label("bot").pos(0,28,CENTER,BOTTOM,page);
const test = new Button({
width: 150,
height: 50,
backgroundColor: purple.lighten(.8),
rollBackgroundColor: purple,
color: purple,
rollColor: purple.lighten(.8),
corner: 8,
label: "TEST",
group: "footer"
}).pos(0, 20, CENTER, BOTTOM, page).tap(function() {
const result = page.test();
results[certPages.indexOf(page)] = result;
answer.text = result ? "CORRECT!" : "OOPS!";
let correct = 0;
let total = 0;
loop(results, function(r) {
if (zot(r)) return; // this is a ZIM loop continue
correct += r;
total += r == null ? 0 : 1;
});
standing.text = correct + "/" + total;
level.text = "Current Level: " + levels[correct] + "!";
pane.show();
});
page.buttonLeft = new Triangle(35, 35, 35, purple).rot(-90).pos(30, 30, LEFT, BOTTOM, page).expand();
page.buttonRight = page.buttonLeft.clone().rot(90).pos(30, 30, RIGHT, BOTTOM, page).expand();
certPages.push(page);
}
const pane = new Pane({
width: W + 200,
height: 200,
backgroundColor: new GradientColor([purple.lighten(.9), purple.lighten(.6)], [0, 1], 0, 0, 0, 200),
backdropColor: "rgba(0,0,0,.7)"
}).rot(-20);
const answer = new Label({text: "CORRECT!", size: 60, group: "footer"}).center(pane).noMouse().mov(-12, -20);
const level = new Label({text: "Current Level: CATastrophe!", size: 30, group: "footer"}).center(pane).noMouse().mov(-12, 40);
const standing = new Label({text: "0/1", size: 26, group: "footer", color: purple.lighten(.4)}).center(pane).noMouse().mov(200, -60);
return certPages;
}
} // end ready
// Docs for items used:
// https://zimjs.com/docs.html?item=Frame
// https://zimjs.com/docs.html?item=Pic
// https://zimjs.com/docs.html?item=Container
// https://zimjs.com/docs.html?item=Circle
// https://zimjs.com/docs.html?item=Rectangle
// https://zimjs.com/docs.html?item=Triangle
// https://zimjs.com/docs.html?item=Squiggle
// https://zimjs.com/docs.html?item=Blob
// https://zimjs.com/docs.html?item=Label
// https://zimjs.com/docs.html?item=Button
// https://zimjs.com/docs.html?item=RadioButtons
// https://zimjs.com/docs.html?item=Toggle
// https://zimjs.com/docs.html?item=Pane
// https://zimjs.com/docs.html?item=Page
// https://zimjs.com/docs.html?item=Indicator
// https://zimjs.com/docs.html?item=List
// https://zimjs.com/docs.html?item=Stepper
// https://zimjs.com/docs.html?item=Slider
// https://zimjs.com/docs.html?item=Selector
// https://zimjs.com/docs.html?item=Dial
// https://zimjs.com/docs.html?item=Tabs
// https://zimjs.com/docs.html?item=Scrambler
// https://zimjs.com/docs.html?item=tap
// https://zimjs.com/docs.html?item=change
// https://zimjs.com/docs.html?item=drag
// https://zimjs.com/docs.html?item=noMouse
// https://zimjs.com/docs.html?item=wire
// https://zimjs.com/docs.html?item=wired
// https://zimjs.com/docs.html?item=transform
// https://zimjs.com/docs.html?item=hitTestCircleRect
// https://zimjs.com/docs.html?item=loop
// https://zimjs.com/docs.html?item=pos
// https://zimjs.com/docs.html?item=loc
// https://zimjs.com/docs.html?item=mov
// https://zimjs.com/docs.html?item=alp
// https://zimjs.com/docs.html?item=hov
// https://zimjs.com/docs.html?item=rot
// https://zimjs.com/docs.html?item=sca
// https://zimjs.com/docs.html?item=addTo
// https://zimjs.com/docs.html?item=centerReg
// https://zimjs.com/docs.html?item=center
// https://zimjs.com/docs.html?item=expand
// https://zimjs.com/docs.html?item=Pages
// https://zimjs.com/docs.html?item=Arrow
// https://zimjs.com/docs.html?item=HotSpots
// https://zimjs.com/docs.html?item=Tile
// https://zimjs.com/docs.html?item=timeout
// https://zimjs.com/docs.html?item=interval
// https://zimjs.com/docs.html?item=copy
// https://zimjs.com/docs.html?item=GradientColor
// https://zimjs.com/docs.html?item=RadialColor
// https://zimjs.com/docs.html?item=series
// https://zimjs.com/docs.html?item=lighten
// https://zimjs.com/docs.html?item=darken
// https://zimjs.com/docs.html?item=STYLE
Also see: Tab Triggers