diff --git a/.vscode/configurationCache.log b/.vscode/configurationCache.log new file mode 100644 index 0000000..b1242a3 --- /dev/null +++ b/.vscode/configurationCache.log @@ -0,0 +1 @@ +{"buildTargets":["watch"],"launchTargets":[],"customConfigurationProvider":{"workspaceBrowse":{"browsePath":[],"compilerArgs":[]},"fileIndex":[]}} \ No newline at end of file diff --git a/.vscode/dryrun.log b/.vscode/dryrun.log new file mode 100644 index 0000000..51cece7 --- /dev/null +++ b/.vscode/dryrun.log @@ -0,0 +1,5 @@ +make --dry-run --always-make --keep-going --print-directory +make: Entering directory `/Users/adamgrant/repos/Mozart' +python3 -m http.server 8000 +make: Leaving directory `/Users/adamgrant/repos/Mozart' + diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..65e1ec0 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "makefile.extensionOutputFolder": "./.vscode" +} \ No newline at end of file diff --git a/.vscode/targets.log b/.vscode/targets.log new file mode 100644 index 0000000..ddb75fb --- /dev/null +++ b/.vscode/targets.log @@ -0,0 +1,244 @@ +make all --print-data-base --no-builtin-variables --no-builtin-rules --question +# GNU Make 3.81 +# Copyright (C) 2006 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. +# There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# This program built for i386-apple-darwin11.3.0 + +# Make data base, printed on Tue Aug 9 19:47:23 2022 + +# Variables + +# automatic +/dev/null || echo /Developer)/Makefiles +# environment +VSCODE_CODE_CACHE_PATH = /Users/adamgrant/Library/Application Support/Code/CachedData/da76f93349a72022ca4670c1b84860304616aaa2 +# environment +LOGNAME = adamgrant +# environment +APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL = true +# environment +NVM_CD_FLAGS = -q +# environment +ZSH = /Users/adamgrant/.oh-my-zsh +# environment +VSCODE_HANDLES_UNCAUGHT_ERRORS = true +# automatic +^D = $(patsubst %/,%,$(dir $^)) +# environment +XPC_FLAGS = 0x0 +# default +MAKE = $(MAKE_COMMAND) +# default +MAKECMDGOALS := all +# environment +SHLVL = 1 +# default +MAKE_VERSION := 3.81 +# environment +USER = adamgrant +# makefile +.DEFAULT_GOAL := watch +# environment +LESS = -R +# automatic +%D = $(patsubst %/,%,$(dir $%)) +# default +MAKE_COMMAND := /Library/Developer/CommandLineTools/usr/bin/make +# default +.VARIABLES := +# environment +TMPDIR = /var/folders/w9/r7_p3fh14mdfj9g8wj685tsm0000gn/T/ +# automatic +*F = $(notdir $*) +# environment +VSCODE_IPC_HOOK = /Users/adamgrant/Library/Application Support/Code/1.70.0-main.sock +# environment +MallocNanoZone = 0 +# makefile +MAKEFLAGS = Rrqp +# environment +MFLAGS = -Rrqp +# automatic +*D = $(patsubst %/,%,$(dir $*)) +# environment +NVM_DIR = /Users/adamgrant/.nvm +# environment +XPC_SERVICE_NAME = application.com.microsoft.VSCode.23368604.23368612 +# environment +HOMEBREW_PREFIX = /opt/homebrew +# automatic ++D = $(patsubst %/,%,$(dir $+)) +# automatic ++F = $(notdir $+) +# environment +HOMEBREW_REPOSITORY = /opt/homebrew +# environment +__CF_USER_TEXT_ENCODING = 0x1F5:0x0:0x0 +# environment +COMMAND_MODE = unix2003 +# default +MAKEFILES := +# automatic + { ["html", "js", "css"].forEach(extension => { doc_fetchers.push(new Promise((resolve, reject) => { ((extension, attachee, resolve, reject) => { + const enum_prism_extension = { html: "markup", js: "javascript", css: "css" } + const prism_extension = enum_prism_extension[extension]; + var pre_content = "", request = new XMLHttpRequest(); @@ -31,14 +34,18 @@ attachees.forEach(attachee => { request.onload = function() { if (this.status >= 200 && this.status < 400) { pre_content += this.response; + if (pre_content) { + pre_content = Prism.highlight( + pre_content, Prism.languages[prism_extension], prism_extension + ) + } var code = document.createElement("code"); - code.innerHTML = escapeHTML(pre_content); + code.innerHTML = pre_content; code.removeAttribute("hidden"); - code.classList.add(extension == "js" ? "javascript" : extension); attachee.querySelector("pre").appendChild(code); resolve(); } - else { return resolve(); } + // else { return resolve(); } } request.send(); })(extension, attachee, resolve, reject); @@ -47,11 +54,12 @@ attachees.forEach(attachee => { var script = document.createElement("script"); script.src = `docs/${attachee.dataset.attach}/tests.js` + script.type = "module"; document.body.appendChild(script); }); Promise.all(doc_fetchers).then(() => { - hljs.initHighlighting(); + // TODO?: Allegedly things are ready for syntax highlighting here }); @@ -106,7 +114,12 @@ doc = (config) => { return `

${test.term}

${results}` }).join(""); - body.innerHTML += test_results; + if (body) { + body.innerHTML += test_results; + } + else { + console.error(`could not find attach ID: ${config.attach_id}`) + } } var show_tests = document.getElementById("show-tests"), diff --git a/docs/about/example/index.css b/docs/about/components/index.css similarity index 100% rename from docs/about/example/index.css rename to docs/about/components/index.css diff --git a/docs/about/components/index.html b/docs/about/components/index.html new file mode 100644 index 0000000..41c3584 --- /dev/null +++ b/docs/about/components/index.html @@ -0,0 +1,5 @@ +
+
+
+
+
diff --git a/docs/about/how/index.js b/docs/about/components/index.js similarity index 100% rename from docs/about/how/index.js rename to docs/about/components/index.js diff --git a/docs/about/example/tests.js b/docs/about/components/tests.js similarity index 100% rename from docs/about/example/tests.js rename to docs/about/components/tests.js diff --git a/docs/about/dedicated-files/index.css b/docs/about/dedicated-files/index.css new file mode 100644 index 0000000..f9e0e26 --- /dev/null +++ b/docs/about/dedicated-files/index.css @@ -0,0 +1,4 @@ +/* components/form/form.css */ +[data-component="form"] { + background: white; +} \ No newline at end of file diff --git a/docs/advanced/adding-methods/index.html b/docs/about/dedicated-files/index.html similarity index 100% rename from docs/advanced/adding-methods/index.html rename to docs/about/dedicated-files/index.html diff --git a/docs/about/dedicated-files/index.js b/docs/about/dedicated-files/index.js new file mode 100644 index 0000000..01a3869 --- /dev/null +++ b/docs/about/dedicated-files/index.js @@ -0,0 +1,3 @@ +// components/form/form.js +import Component from "./mozart.js"; +let form = new Component("form"); diff --git a/docs/about/how/tests.js b/docs/about/dedicated-files/tests.js similarity index 100% rename from docs/about/how/tests.js rename to docs/about/dedicated-files/tests.js diff --git a/docs/about/how/index.css b/docs/about/deferred-actions/index.css similarity index 100% rename from docs/about/how/index.css rename to docs/about/deferred-actions/index.css diff --git a/docs/advanced/jquery/index.html b/docs/about/deferred-actions/index.html similarity index 100% rename from docs/advanced/jquery/index.html rename to docs/about/deferred-actions/index.html diff --git a/docs/about/deferred-actions/index.js b/docs/about/deferred-actions/index.js new file mode 100644 index 0000000..ff68c40 --- /dev/null +++ b/docs/about/deferred-actions/index.js @@ -0,0 +1,26 @@ +import Component from "./mozart.js"; +import index from "./components/index/index.js"; +import contact from "./components/contact/contact.js"; + +let form = new Component("form"); + +form.assign({ + submit() { + const [name, email] = this.fields; + // Defer remaining implementation to the components + // "contact" and "index" + const contactIndex = index.createContact({ name, email }); + contact.showContactAtIndex({ index: contactIndex }); + this.clear(); + }, + + get fields() { + return this.q("input").map(input => input.value); + }, + + clear() { + this.q("input").forEach(input => input.value = ""); + } +}) + +form.q(".submit").addEventListener("click", form.submit); \ No newline at end of file diff --git a/docs/basics/using-css/tests.js b/docs/about/deferred-actions/tests.js similarity index 100% rename from docs/basics/using-css/tests.js rename to docs/about/deferred-actions/tests.js diff --git a/docs/about/example/index.html b/docs/about/example/index.html deleted file mode 100644 index 67d60ef..0000000 --- a/docs/about/example/index.html +++ /dev/null @@ -1,28 +0,0 @@ -
-
- - - - - -
- -
- -
-

Name

-

Email

-
-
-
diff --git a/docs/about/example/index.js b/docs/about/example/index.js deleted file mode 100644 index 4df6116..0000000 --- a/docs/about/example/index.js +++ /dev/null @@ -1,24 +0,0 @@ -m.index.events(_$ => { - _$("li").click(_$.act.show_contact); -}); - -// ... - -m.form.events(_$ => { - var name, email; - [name, email] = _$("input").map(input => input.val()); - _$("button").click(m.index.act.add({ name: name, email: email }); -}); - -// ... - -m.index.acts({ - add(_$, args){ - // ... - _$.act.show_contact({ contact: contact }); - }, - - show_contact(_$, args) { - // ... - } -}); diff --git a/docs/about/how/index.html b/docs/about/how/index.html deleted file mode 100644 index 5eda5aa..0000000 --- a/docs/about/how/index.html +++ /dev/null @@ -1,5 +0,0 @@ -
- -
- -
diff --git a/docs/advanced/adding-methods/index.css b/docs/about/scoped-selector/index.css similarity index 100% rename from docs/advanced/adding-methods/index.css rename to docs/about/scoped-selector/index.css diff --git a/docs/advanced/private-methods/index.html b/docs/about/scoped-selector/index.html similarity index 100% rename from docs/advanced/private-methods/index.html rename to docs/about/scoped-selector/index.html diff --git a/docs/about/scoped-selector/index.js b/docs/about/scoped-selector/index.js new file mode 100644 index 0000000..dc5d74c --- /dev/null +++ b/docs/about/scoped-selector/index.js @@ -0,0 +1,9 @@ +import Component from "./mozart.js"; +let form = new Component("form"); + +form.create = function() { /* ... */ } + +// Scoped-selection of the create +// button to call the submit method above. +let create = form.q(".create"); +create.addEventListener("click", form.create); \ No newline at end of file diff --git a/docs/advanced/jquery/index.css b/docs/about/scoped-selector/tests.js similarity index 100% rename from docs/advanced/jquery/index.css rename to docs/about/scoped-selector/tests.js diff --git a/docs/advanced/adding-methods/index.js b/docs/advanced/adding-methods/index.js deleted file mode 100644 index 97ab214..0000000 --- a/docs/advanced/adding-methods/index.js +++ /dev/null @@ -1,24 +0,0 @@ -class Component extends Mozart { - transactions(fn) { - super.add_function_method("transactions", fn); - } - - calculations(obj) { - super.add_object_method("calculations", super.functional_object(obj)); - } -}; - -var m = Component.index; -Component.register("accountant"); - -m.accountant.transactions(_$ => { - // ... -}) - -m.accountant.calculations({ - add: (_$, args) { - // ... - } -}) - -Mozart.init(); diff --git a/docs/advanced/adding-methods/tests.js b/docs/advanced/adding-methods/tests.js deleted file mode 100644 index 9f6fa0f..0000000 --- a/docs/advanced/adding-methods/tests.js +++ /dev/null @@ -1,57 +0,0 @@ -doc({ - attach_id: "advanced/adding-methods", - tests: [ - test("Function and Object Methods can be added", () => { - class Component extends Mozart { - myfunction_method(args) { - super.add_function_method("myfunction_method", args); - } - - myobject_method(obj) { - super.add_object_method( - "myobject_method", - super.parse_object(obj, (args, key) => { - var _$ = this.scoped_selector(); - obj[key](_$, args); - }) - ); - } - }; - - var m = Component.index; - new Component("mycomponent"); - - var scoped = "not scoped", - scoped2 = "not scoped", - args_present = "not present"; - event_decorated_$_acts = undefined; - - m.mycomponent.acts({ - foo() {} - }); - - m.mycomponent.myfunction_method(_$ => { - if (typeof(_$("i")) == "object") { scoped = "scoped" } - event_decorated_$_acts = _$.acts; - }); - - m.mycomponent.myobject_method({ - subfunc(_$, args) { - if (typeof(_$("i")) == "object") { scoped2 = "scoped" } - if (args.foo == "bar") { args_present = "present" } - } - }); - - Mozart.init(); - - m.mycomponent.myobject_method.subfunc({ foo: "bar" }) - - return [ - assert("myfunction_method is defined on instance variable and has scoped _$", scoped, "scoped") - , assert("myobject_method is defined on instance variable and has scoped _$", scoped2, "scoped") - , assert("myobject_method is defined on instance variable and takes arguments", args_present, "present") - , assert("scoped _$ inside function method has components obj methods", typeof(event_decorated_$_acts), "object") - ] - }, `
`) - ] -}); diff --git a/docs/advanced/jquery/index.js b/docs/advanced/jquery/index.js deleted file mode 100644 index 3c74175..0000000 --- a/docs/advanced/jquery/index.js +++ /dev/null @@ -1,15 +0,0 @@ -// card_game/events.js -m.card_game.events(_$ => { - // Because we have jQuery we can do this: - _$("button").click(_$.act.shuffle); - - // Otherwise, we'd need to do this: - _$("button").addEventListener("click", _$.act.shuffle); -}) - -// card_game/actions.js -m.card_game.act({ - shuffle() { - // ... - } -}) diff --git a/docs/advanced/jquery/tests.js b/docs/advanced/jquery/tests.js deleted file mode 100644 index e592cd5..0000000 --- a/docs/advanced/jquery/tests.js +++ /dev/null @@ -1,30 +0,0 @@ -doc({ - attach_id: "advanced/jquery", - tests: [ - test("jQuery is used when included", () => { - function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); - } - var jquery_exists = "not found"; - var jq_fn = "not found"; - - class Component extends Mozart {}; - var m = Component.index; - new Component("jquery_tester"); - - m.jquery_tester.act({ - go(_$, args) { - jquery_exists = typeof(jQuery); - jq_fn = typeof(_$("i").click); - } - }); - - m.jquery_tester.act.go(); - - return [ - assert("jQuery exists", jquery_exists, "function") - , assert("jQuery is defined as _$", jq_fn, "function") - ] - }, `
`) - ] -}); diff --git a/docs/advanced/private-methods/index.js b/docs/advanced/private-methods/index.js deleted file mode 100644 index 41d9096..0000000 --- a/docs/advanced/private-methods/index.js +++ /dev/null @@ -1,29 +0,0 @@ -Component.register(["timer", "controls"]); - -// controls/events.js -m.controls.events(_$ => { - _$(".reset").click(m.timer.act.reset); - - // This would throw an error - m.timer.act.set_clock({ seconds: 0 }); -}); - -// timer/actions.js -m.timer.acts({ - reset(_$, args) { - // We can call the private method - // because it belongs to the component. - _$.set_clock({ seconds: 0 }); - }, - - priv: { - set_clock(_$, args) { - // This method calls to another private method below - _$(".clock").innerHTML = _$.act.format_time(args.seconds); - }, - - format_time(_$, args) { - // ... - } - } -}); diff --git a/docs/advanced/private-methods/tests.js b/docs/advanced/private-methods/tests.js deleted file mode 100644 index 8e14e4e..0000000 --- a/docs/advanced/private-methods/tests.js +++ /dev/null @@ -1,64 +0,0 @@ -doc({ - attach_id: "advanced/private-methods", - tests: [ - test("Private methods can only be accessed by the component", () => { - class Component extends Mozart {}; - var m = Component.index; - new Component("introvert"); - new Component("extrovert"); - - var private_called_from_self = false, - private_called_from_another = false, - public_called_from_self = false, - public_called_from_another = false; - - m.introvert.act({ - public_fn_from_self(_$, args) { - public_called_from_self = true; - }, - - public_fn_from_another(_$, args) { - public_called_from_another = true; - }, - - init(_$, args) { - _$.act.public_fn_from_self(); - try { _$.act.private_fn_from_self(); } - catch(e) { console.error("Could not call own private function") } - }, - - priv: { - private_fn_from_self(_$, args) { - private_called_from_self = true; - }, - private_fn_from_another(_$, args) { - private_called_from_another = true; - } - } - }); - - m.extrovert.act({ - init(_$, args) { - m.introvert.act.public_fn_from_another(); - try { m.introvert.act.private_fn_from_another(); } - catch(e) { - return 0; - // As we'd expect, this should not work. - }; - } - }); - - Mozart.init(); - - m.introvert.act.init(); - m.extrovert.act.init(); - - return [ - assert("Public function called from self is reachable", public_called_from_self, true) - , assert("Public function called from another is reachable", public_called_from_another, true) - , assert("Private function called from self is reachable", private_called_from_self, true) - , assert("Private function called from another is not reachable", private_called_from_another, false) - ] - }) - ] -}); diff --git a/docs/advanced/selection/index.js b/docs/advanced/selection/index.js deleted file mode 100644 index 10e942e..0000000 --- a/docs/advanced/selection/index.js +++ /dev/null @@ -1,64 +0,0 @@ -// OPTION 1 -// ======== - -m.lookup.acts({ - blink_green(_$, args) { - // args.element isn't the component, but if you pass this - // in, Mozart will find it. - var me = _$.me(args.element); - me.classList.add("blink"); - } -}); -m.lookup.acts({ - blink_green(_$, args) { - var me = _$.me(); - me.classList.add("blink"); - // This will work fine as long as there is only one - // "lookup" component. Otherwise, you'll get an array - // of the components back. - } -}); - -// OPTION 2 -// ======== -// But maybe this is a collection of lookup components -// and we're executing this action from some event -// on the specific component we want to blink. - -m.lookup.events(_$ => { - _$(".validate").addEventListener("click", (e) => { - _$.act.blink_green({ element: e.target }); - }); -}); - -m.lookup.acts({ - blink_green(_$, args) { - // args.element isn't the component, but if you pass this - // in, Mozart will find it. - var me = _$.me(args.element); - me.classList.add("blink"); - } -}); - -// OPTION 3 -// ======== -// And here's another way where the component itself is the -// element being clicked. - -m.lookup.events(_$ => { - var lookups = _$.me(), - clickHandler = (e) => _$.act.blink_green({ element: e }); - - // This weird syntax is to prevent variable hoisting. - // If you're using jQuery, you probably don't need to do this. - lookups.forEach(lookup => (clickHandler)(lookup)); -}); - -m.lookup.acts({ - blink_green(_$, args) { - // args.element isn't the component, but if you pass this - // in, Mozart will find it. - var me = _$.me(args.element); - me.classList.add("blink"); - } -}); diff --git a/docs/advanced/selection/tests.js b/docs/advanced/selection/tests.js deleted file mode 100644 index cfb6590..0000000 --- a/docs/advanced/selection/tests.js +++ /dev/null @@ -1,64 +0,0 @@ -doc({ - attach_id: "advanced/selection", - tests: [ - test("_$.me finds the parent component or components", () => { - - class Component extends Mozart {}; - Component.register(["single", "multiple", "multiple_two"]); - var m = Component.index; - - var single_el, - multiple_el, - multiple_two_el, - multiple_el_two, - multiple_two_el_two; - - m.single.acts({ - get_element(_$, args) { single_el = _$.me(); } - }); - - m.multiple.acts({ - get_element(_$, args) { multiple_el = _$.me(); } - }); - - m.multiple_two.acts({ - get_element(_$, args) { multiple_two_el = _$.me(args.child); }, - return_element(_$, args) { return _$.me(args.child); } - }); - - Mozart.init(); - - m.single.act.get_element(); - m.multiple.act.get_element(); - - multiple_el_two = m.multiple.me(); - multiple_two_el_two = m.multiple_two.me(); - - var child = document.querySelectorAll("[data-component='multiple_two']")[1].querySelector("span"); - m.multiple_two.act.get_element({ child: child }); - - var child_parent = { id: undefined }, - child2 = document.querySelectorAll("[data-component='multiple_two']")[2] - child_parent = m.multiple_two.act.return_element({ child: child2 }); - - return [ - assert("_$.me() returns one component when only one exists", typeof(single_el), "object") - , assert("_$.me() returns all components when only multiple exist", multiple_el.length, 3) - , assert("_$.me(element) returns the right component parent", multiple_two_el.id, 2) - , assert("If this child actually is the component, return that", child_parent.id, 3) - , assert("m..me() returns one component when only one exists", typeof(multiple_el_two), "object") - , assert("m..me() returns multiple components when multiple exist", multiple_two_el_two.length, 3) - ] - }, ` -
- -
-
-
- -
-
-
- `) - ] -}); diff --git a/docs/advanced/private-methods/index.css b/docs/advanced/self-selection/index.css similarity index 100% rename from docs/advanced/private-methods/index.css rename to docs/advanced/self-selection/index.css diff --git a/docs/advanced/selection/index.html b/docs/advanced/self-selection/index.html similarity index 100% rename from docs/advanced/selection/index.html rename to docs/advanced/self-selection/index.html diff --git a/docs/advanced/self-selection/index.js b/docs/advanced/self-selection/index.js new file mode 100644 index 0000000..36485be --- /dev/null +++ b/docs/advanced/self-selection/index.js @@ -0,0 +1,14 @@ +import Component from "./mozart.js"; +import notifier from "components/notifier"; +let list = new Component("list"); + +list.assign({ + flash_error(message) { + notifier.error(message) ; + this.highlight(); + }, + + highlight() { + this.me.style.backgroundColor = "red"; + } +}); \ No newline at end of file diff --git a/docs/advanced/self-selection/tests.js b/docs/advanced/self-selection/tests.js new file mode 100644 index 0000000..f160ed5 --- /dev/null +++ b/docs/advanced/self-selection/tests.js @@ -0,0 +1,16 @@ +import Component from "../../../mozart.js"; +doc({ + attach_id: "advanced/self-selection", + tests: [ + test("Mozart basics", () => { + let dropdown_button = new Component("dropdown_button"); + + return [ + assert("dropdown_button element found", dropdown_button.me.dataset.test, "123") + ] + },` + + `) + ] +}); \ No newline at end of file diff --git a/docs/advanced/selection/index.css b/docs/advanced/storing-data/index.css similarity index 100% rename from docs/advanced/selection/index.css rename to docs/advanced/storing-data/index.css diff --git a/docs/basics/using-css/index.html b/docs/advanced/storing-data/index.html similarity index 100% rename from docs/basics/using-css/index.html rename to docs/advanced/storing-data/index.html diff --git a/docs/advanced/storing-data/index.js b/docs/advanced/storing-data/index.js new file mode 100644 index 0000000..a0b2189 --- /dev/null +++ b/docs/advanced/storing-data/index.js @@ -0,0 +1,17 @@ +import Component from "./mozart.js"; +let widget = new Component("widget"); + +widget.store.count = 0; + +widget.assign({ + update_count() { + this.store.count++; + }, + + show_count() { + this.q(".display").innerHTML = this.store.count; + } +}); + +const button = widget.q(".add-to-count"); +button.addEventListener("click", widget.update_count); \ No newline at end of file diff --git a/docs/advanced/storing-data/tests.js b/docs/advanced/storing-data/tests.js new file mode 100644 index 0000000..57b827f --- /dev/null +++ b/docs/advanced/storing-data/tests.js @@ -0,0 +1,37 @@ +import Component from "../../../mozart.js"; +doc({ + attach_id: "advanced/storing-data", + tests: [ + test("Mozart basics", () => { + let dropdown_button = new Component("dropdown_button"); + + dropdown_button.store.marco = "polo"; + dropdown_button.store.marco_from_setter = "wowo"; + + dropdown_button.assign({ + get marco() { + return this.store.marco; + }, + + set set_marco(value) { + this.store.marco_from_setter = value; + }, + + marco_as_function() { + return this.store.marco; + } + }) + + dropdown_button.set_marco = "polo"; + + return [ + assert("dropdown_button has store", !!dropdown_button.store, true), + assert("dropdown_button store readout", dropdown_button.store.marco, "polo"), + assert("dropdown_button store accessible from regular function", dropdown_button.marco_as_function(), "polo"), + assert("dropdown_button store accessible from getter function", dropdown_button.marco, "polo"), + assert("dropdown_button store accessible from setter function", dropdown_button.store.marco_from_setter, "polo"), + ] + },` + `) + ] +}); \ No newline at end of file diff --git a/docs/basics/actions/index.js b/docs/basics/actions/index.js index bb1260b..b15207a 100644 --- a/docs/basics/actions/index.js +++ b/docs/basics/actions/index.js @@ -1,51 +1,10 @@ -// init.js -class Component extends Mozart {}; +import Component from "./mozart.js"; +let dropdown_button = new Component("dropdown_button"); -// For larger projects, you might be better off looping through -// your components to create them like this -components = [ - "timer", - "controls", - "notifier" -] -Component.register(components); -var m = Component.index; +dropdown_button.open = function() { + // ... +} -// notifer/actions.js -m.notifier.acts({ - msg_alert(_$, args) { - // Show the alert with args.msg - } -}); - -// timer/actions.js -m.timer.acts({ - start(_$, args) { - var duration = m.controls.config.duration; - setTimeout(_$.act.complete, duration); - }, - - complete(_$, args) { - m.notifier.act.msg_alert({ - message: "Timer complete" - }); - m.controls.act.reset(); - } -}); - -// controls/actions.js -m.controls.acts({ - start(_$, args) { - m.timer.act.start(); - _$("button.start").disabled(); - } - - reset(_$, args) { - _$("button.start").enabled(); - } -}); - -// controls/events.js -m.controls.events(_$ => { - _$("button.start").click(_$.act.start); -}); +dropdown_button.close = function() { + // ... +} \ No newline at end of file diff --git a/docs/basics/actions/tests.js b/docs/basics/actions/tests.js index 6169ffb..e2b4c74 100644 --- a/docs/basics/actions/tests.js +++ b/docs/basics/actions/tests.js @@ -1,35 +1,18 @@ -doc({ - attach_id: "basics/actions", - tests: [ - test("Actions", () => { - class Component extends Mozart {}; - var m = Component.index; - new Component("actionguy"); - var iexist = false; - var neighbor_response = ""; - - m.actionguy.acts({ - iexist(_$, args) { - iexist = true; - }, +import Component from "../../../mozart.js"; +let dropdown_button = new Component("dropdown_button"); - value_from_neighbor(_$, args) { - neighbor_response = _$.act.neighbor(); - }, +dropdown_button.open = function() { return "open" } +dropdown_button.close = function() { return "close" } - neighbor(_$, args) { - return { "foo": "bar" } - }, - }); +doc({ + attach_id: "basics/actions", + tests: [ + test("Actions", () => { - Mozart.init(); - m.actionguy.act.iexist(); - m.actionguy.act.value_from_neighbor(); - - return [ - assert("Action can be called from the outside", iexist, true) - , assert("A value returned from a neighbor function comes back through the caller", neighbor_response, { "foo": "bar" }) - ] - }) - ] -}); + return [ + assert("Methods can be added one-by-one", [dropdown_button.open(), dropdown_button.close()], ["open", "close"]) + ] + }, ` + `) + ] +}); \ No newline at end of file diff --git a/docs/basics/events/index.css b/docs/basics/actions2/index.css similarity index 100% rename from docs/basics/events/index.css rename to docs/basics/actions2/index.css diff --git a/docs/basics/fragments/index.css b/docs/basics/actions2/index.html similarity index 100% rename from docs/basics/fragments/index.css rename to docs/basics/actions2/index.html diff --git a/docs/basics/actions2/index.js b/docs/basics/actions2/index.js new file mode 100644 index 0000000..35cc2ef --- /dev/null +++ b/docs/basics/actions2/index.js @@ -0,0 +1,12 @@ +import Component from "./mozart.js"; +let dropdown_button = new Component("dropdown_button"); + +dropdown_button.assign({ + open() { + // ... + }, + + close() { + // ... + } +}); \ No newline at end of file diff --git a/docs/basics/actions2/tests.js b/docs/basics/actions2/tests.js new file mode 100644 index 0000000..0c2793f --- /dev/null +++ b/docs/basics/actions2/tests.js @@ -0,0 +1,20 @@ +import Component from "../../../mozart.js"; +let dropdown_button = new Component("dropdown_button"); + +dropdown_button.assign({ + open() { return "open" }, + close() { return "close" } +}) + +doc({ + attach_id: "basics/actions2", + tests: [ + test("Actions", () => { + + return [ + assert("Methods can be added by assignment", [dropdown_button.open(), dropdown_button.close()], ["open", "close"]) + ] + }, ` + `) + ] +}); \ No newline at end of file diff --git a/docs/basics/routes/index.css b/docs/basics/calling/index.css similarity index 100% rename from docs/basics/routes/index.css rename to docs/basics/calling/index.css diff --git a/docs/basics/using-css/index.js b/docs/basics/calling/index.html similarity index 100% rename from docs/basics/using-css/index.js rename to docs/basics/calling/index.html diff --git a/docs/basics/calling/index.js b/docs/basics/calling/index.js new file mode 100644 index 0000000..8d55a9e --- /dev/null +++ b/docs/basics/calling/index.js @@ -0,0 +1,18 @@ +import Component from "./mozart.js"; +let dropdown_button = new Component("dropdown_button"); + +dropdown_button.attach({ + open() { + // ... + this.change_title("Click again to close"); + }, + + close() { + // ... + this.change_title("Open menu") + }, + + change_title(title) { + this.q(".title").innerHTML = title; + } +}); \ No newline at end of file diff --git a/docs/basics/calling/tests.js b/docs/basics/calling/tests.js new file mode 100644 index 0000000..581ffa5 --- /dev/null +++ b/docs/basics/calling/tests.js @@ -0,0 +1,24 @@ +import Component from "../../../mozart.js"; +let timer = new Component("timer"); +let alarm = new Component("alarm"); + +timer.talk_to_alarm = function() { + return alarm.get_status(); +} + +alarm.get_status = function() { + return "all good" +} + +doc({ + attach_id: "basics/calling", + tests: [ + test("Cross component communication", () => { + + return [ + assert("action function responds", timer.talk_to_alarm(), "all good"), + ] + }, ` + `) + ] +}); \ No newline at end of file diff --git a/docs/basics/create-a-component/index.html b/docs/basics/create-a-component/index.html index e69de29..e3321ec 100644 --- a/docs/basics/create-a-component/index.html +++ b/docs/basics/create-a-component/index.html @@ -0,0 +1,14 @@ + \ No newline at end of file diff --git a/docs/basics/create-a-component/index.js b/docs/basics/create-a-component/index.js index ddd40a6..0087341 100644 --- a/docs/basics/create-a-component/index.js +++ b/docs/basics/create-a-component/index.js @@ -1,2 +1,5 @@ -class Component extends Mozart {}; +import Component from "./mozart.js"; +let dropdown_button = new Component("dropdown_button"); + +export default dropdown_button; \ No newline at end of file diff --git a/docs/basics/create-a-component/tests.js b/docs/basics/create-a-component/tests.js index 83fdb47..520cdbb 100644 --- a/docs/basics/create-a-component/tests.js +++ b/docs/basics/create-a-component/tests.js @@ -1,78 +1,30 @@ +import Component from "../../../mozart.js"; doc({ - attach_id: "basics/create-a-component", - tests: [ - test("Mozart function", () => { - class Component extends Mozart {}; - var m = Component.index; - var funcs = { - acts: "not found", - events: "not found", - routes: "not found", - }; - - var funcs2 = { - acts: "not found", - events: "not found", - routes: "not found", - }; - - var dumb_and_dumber = [undefined, undefined]; - - Component.register("check_functions"); - - m.check_functions.routes({ foo: "bar" }); - - m.check_functions.events(_$ => { - funcs.acts = typeof(_$.acts); - funcs.routes = typeof(_$.routes); - }); - - m.check_functions.acts({ - start: (_$, args) => { - funcs2.acts = typeof(_$.acts); - funcs2.routes = typeof(_$.routes); - } - }); - - Component.register(["dumb", "dumber"]); - - Component.register("just_me"); - - var element; - - Component.register("scoper"); - - m.scoper.acts({ - test(_$, args) { - element = [_$(".twin")].flat()[0]; - } - }); - - Mozart.init(); - - m.check_functions.acts.start(); - - dumb_and_dumber[0] = typeof(m.dumb); - dumb_and_dumber[1] = typeof(m.dumber); - - m.scoper.act.test(); - - return [ - assert("Mozart Function exists", typeof(Mozart), "function") - , assert("Subclassed Component function exists", typeof(Component), "function") - , assert("_$ has acts method from events", funcs.acts, "object") - , assert("_$ has routes method from events", funcs.routes, "object") - , assert("_$ has acts method from acts", funcs2.acts, "object") - , assert("_$ has routes method from acts", funcs2.routes, "object") - , assert("Multiple components can be created by passing in an Array", dumb_and_dumber, ["object", "object"]) - , assert("A single component can be created by passing in a String", typeof(m.just_me), "object") - , assert("Subcomponent elements are found only if in the component", element.id, "real") - ] - }, ` - -
- -
- `) - ] -}); + attach_id: "basics/create-a-component", + tests: [ + test("Mozart basics", () => { + let dropdown_button = new Component("dropdown_button"); + + return [ + assert("dropdown_button component exists", typeof(dropdown_button), "object"), + assert("dropdown_button has query_selector", !!dropdown_button.q, true), + assert("dropdown_button has store", !!dropdown_button.store, true), + ] + },` + + `) + ] +}); \ No newline at end of file diff --git a/docs/basics/element-selection/index.css b/docs/basics/element-selection/index.css new file mode 100644 index 0000000..e69de29 diff --git a/docs/basics/element-selection/index.html b/docs/basics/element-selection/index.html new file mode 100644 index 0000000..e69de29 diff --git a/docs/basics/element-selection/index.js b/docs/basics/element-selection/index.js new file mode 100644 index 0000000..e1d34e0 --- /dev/null +++ b/docs/basics/element-selection/index.js @@ -0,0 +1,10 @@ +// From the context of a component +this.q(".title"); +// Equivalent to +document.querySelector("[data-component='dropdown_button'] .title"); + +// You can also select an element from another component's scope. +import timer from "../components/timer.js"; +let start_button = timer.q(".start"); +// Equivalent to +let start_button = document.querySelector("[data-component='timer'] .start"); \ No newline at end of file diff --git a/docs/basics/element-selection/tests.js b/docs/basics/element-selection/tests.js new file mode 100644 index 0000000..819df73 --- /dev/null +++ b/docs/basics/element-selection/tests.js @@ -0,0 +1,29 @@ +import Component from "../../../mozart.js"; +let timer = new Component("timer"); + +timer.get_hello = function() { + return this.q(".hello").innerHTML; +} + +timer.get_element_out_of_scope = function() { + return this.q(".goodbye"); +} + +doc({ + attach_id: "basics/element-selection", + tests: [ + test("Selecting an element", () => { + return [ + assert("Can select scoped element", timer.get_hello(), "hello world"), + assert("Does not select element out of scope", timer.get_element_out_of_scope(), undefined), + ] + }, ` +
+

hello world

+
+
+

You shouldn't see this.

+
+ `) + ] +}); \ No newline at end of file diff --git a/docs/basics/events/index.html b/docs/basics/events/index.html deleted file mode 100644 index 786bcd1..0000000 --- a/docs/basics/events/index.html +++ /dev/null @@ -1,5 +0,0 @@ -
-

Random number generator

-

- -
diff --git a/docs/basics/events/index.js b/docs/basics/events/index.js deleted file mode 100644 index f3527e3..0000000 --- a/docs/basics/events/index.js +++ /dev/null @@ -1,9 +0,0 @@ -// With jQuery -m.generator.events(_$ => { - _$("button").click(_$.act.generate); -}); - -// Plain JavaScript -m.generator.events(_$ => { - _$("button").addEventListener("click", _$.act.generate); -}); diff --git a/docs/basics/events/tests.js b/docs/basics/events/tests.js deleted file mode 100644 index 9618296..0000000 --- a/docs/basics/events/tests.js +++ /dev/null @@ -1,34 +0,0 @@ -doc({ - attach_id: "basics/events", - tests: [ - test("Events are scoped", function() { - var button = [], - number_of_calls = 0; - was_i_called = "not called"; - - class Component extends Mozart {}; - - var m = Component.index; - Component.register("generator"); - - m.generator.events(_$ => { - was_i_called = "called"; - button = _$("button"); - number_of_calls++; - }); - - Mozart.init(); - - return [ - assert("Button can be selected with scoped selector", typeof(button), "object") - , assert("Event function is called on Mozart init", was_i_called, "called") - , assert("Event function is called only once", number_of_calls, 1) - ] - }, ` -
-

- -
- `) - ] -}); diff --git a/docs/basics/fragments/index.html b/docs/basics/fragments/index.html deleted file mode 100644 index 6500a5f..0000000 --- a/docs/basics/fragments/index.html +++ /dev/null @@ -1,9 +0,0 @@ - diff --git a/docs/basics/fragments/index.js b/docs/basics/fragments/index.js deleted file mode 100644 index 321aca6..0000000 --- a/docs/basics/fragments/index.js +++ /dev/null @@ -1,13 +0,0 @@ -class Component extends Mozart {}; -Component.register("registration"); -var m = Component.index; - -m.registration.events(_$ => { - var fragment = _$.template() - document.body.appendChild(fragment); -}); - -// Or elsewhere, outside the component - -var fragment = m.registration.template(); -document.body.appendChild(fragment); diff --git a/docs/basics/fragments/tests.js b/docs/basics/fragments/tests.js deleted file mode 100644 index 47a2eec..0000000 --- a/docs/basics/fragments/tests.js +++ /dev/null @@ -1,24 +0,0 @@ -doc({ - attach_id: "basics/fragments", - tests: [ - test("Document fragments can be spawned", () => { - class Component extends Mozart {}; - Component.register("registration"); - var m = Component.index, - sandbox = document.getElementById("test-sandbox"), - outside_element = m.registration.template(), - inside_element = _$.template(); - - sandbox.appendChild(fragment); - - return [ - assert("Template element could be created outside the scope", outside_element.id, "registration") - , assert("Template element could be created inside the scope", inside_element.id, "registration") - ] - }, ` -