kbrsh / moon Goto Github PK
View Code? Open in Web Editor NEWπ The minimal & fast library for functional user interfaces
Home Page: https://moonjs.org
License: MIT License
π The minimal & fast library for functional user interfaces
Home Page: https://moonjs.org
License: MIT License
The example on the website has one little bug that you might want to fix. When there is no text in the msg area, the input box moves upward. This is kind of annoying. Could you please fix this, thanks.
Boolean value passed via props to component and then used as value for m-if
directive appears as string, so m-if
never receive false
.
Here's the pen that reproduces issue.
Hello,
when I open http://moonjs.ga/, it tries to get minified version of the script but on gh-pages branch, there's no minified script in ./dist folder.
https://github.com/KingPixil/moon/blob/gh-pages/index.html#L100
As a result, it ends up with 404 and scripts.js also gets broken because of missing Moon dependency.
Can someone point me to the documentation on how to code plugins?
Thanks
Having multiple directives on the same element that have the same type, for example:
<div m-on="click:action" m-on="click:otherAction"></div>
The only prop will be m-on:"click:otherAction"
, because the other property is overwritten.
A solution would be to store props as an array inside, only for directives, and execute for all of them.
Supporting computed properties defined in the computed
options in which you can add custom getters and setters to the property. It should also have access to this
as a reference to the instance as well.
Example usage:
new Moon({
data: {
msg: "Hello Moon!"
},
computed: {
reversed: {
get: function() {
return this.get('msg').split('').reverse().join('')
}
}
}
})
This should be updated every time 'msg' is updated, and trigger view updates.
I'm very intrigued by Moon, given the size/functionality ratio. Unfortunately, the documentation right now is in serious need of some search, either Algolia or even Lunr.
I read in the docs that Moon supports computed properties as well, but to find how to use it, I resorted to Github search and found the example in tests.
After removing an item from a list. An error occurs when I try to update other items on the list. For example:
<ul>
<li m-for="dino in {{dinos}}">
<button m-on:click="log({{dino}})">Log</button>
{{dino.name}}
<button m-on:click="removeDino({{dino}})">Make Extinct</button>
</li>
</ul>
Here is the JS:
data : {
dinos : [
{name : "Velociraptor", quantity : 5},
{name : "Triceratops", quantity : 15},
{name : "Stegosaurus", quantity : 10}
]
},
methods : {
log : function (dino) {
var dinos = this.get("dinos");
console.log(dino, dinos.indexOf(dino));
},
removeDino : function (dino) {
let dinos = this.get("dinos");
dinos.splice(dinos.indexOf(dino), 1);
console.log(dinos);
this.set("dinos", dinos);
}
}
When I click removeDino() on the Triceratops, the DOM is updated. However, after removing it, I can't access Stegosaurus from the Data anymore. The DOM will show Stegosaurus but when I click the log button, I get Object {name: "Triceratops", quantity: 15} -1
. Please can you help me fix this? Thanks
Are there code repositories for the "Todo MVC" and "Markdown Editor" examples? They would be nice to study to see how to structure moon.js applications
Hi,
I was just reading though the docs, and noticed a small mistake:
"Type app1.set('signedIn', false)
in the console, and watch the DOM being updated!"
but this should be app2.set('signedIn', false)
The moustache delimiters can conflict with other framework like for example Hugo. Although I can change the delimiters in template.js, I suggest that moon makes the delimiters configurable as a setting.
When diffing a functional component, the children that come after are mismatched with the DOM, and a duplicate element is created.
Is there some example code on how to dynamically mount a component to a certain element during run-time? For example, using a button?
Thanks
I was curious if moon works with multiple checkboxes with the same name. It seems to bind it all together if I use the same model. Also I can't seem to get radiobuttons to work. I was expecting similar to
https://vuejs.org/v2/guide/forms.html#Checkbox -- the 'Multiple checkboxes, bound to the same Array' bit and https://vuejs.org/v2/guide/forms.html#Radio.
My stab at seeing if it would work. Am I just doing something silly? https://jsfiddle.net/fw8spum7/
I see that the checkboxes with different names work fine. Just hoping you might want to cater to this use-case.
Thanks for a great slim front-end, just what I was looking for!
Setting properties using instance.set() is easy enough for integers, strings and the like, but how might one use the set() method for arrays. From a Laracasts tutorial on Vuejs, suppose you had the following:
var app = new Vue({
el: "#app",
data: {
newName: '',
names: [
'Joe',
'Mary',
'Jane',
'Jack'
],
},
methods: {
addName() {
this.names.push(newName)
this.newName = ''
}
}
})
and the following in your HTML:
<div id="app">
<ul>
<li v-for="name in names" v-text="name"></li>
</ul>
<input type="text" placeholder="Add a name" v-model="newName">
<button @click="addName">Add Name</button>
</div>
Every time you add a name via the <input>
and click the <button>
, a new name will be pushed to the names
array. How would this be done via instance.set()
?
What I have so far:
var app = new Moon({
el: "#app",
data: {
newName: '',
names: [
'Joe',
'Mary',
'Jane',
'Jack'
],
},
methods: {
addName() {
this.set('names', /*?????*/)
this.set('newName', '')
}
}
})
I haven't added the Moon version of the HTML, as that's pretty much the same.
When the normalizer is given an array of vnodes, (by m-for
, for example), it ignores or misplaces everything after the array.
Example:
<div id="app">
<span m-for="item in {{items}}">{{item}}</span>
<h1>This will be misplaced</h1>
</div>
It will show the h1
element 2 spans down, and render the rest of the spans under.
With no whitespace, such as:
<div id="app"><span m-for="item in {{items}}">{{item}}</span><h1>This will be ignored</h1></div>
It will ignore the h1
I am trying to conditionally trying to set the disabled
attribute on a button, but this doesn't seem to be working. I should be able to do this by using m-literal:disabled
and set that equal to a Boolean data property.
var app = new Moon({
el: "#app",
data: {
isDisabled: false
},
methods: {
setDisabled () {
this.set('isDisabled', ! this.get('isDisabled'))
}
}
})
<div id="app">
<button
class="button"
m-literal:disabled="{{isDisabled}}"
m-on:click="setDisabled"
>Click to disable</button>
</div>
Before I even click the button to trigger the event, the above HTML should render to:
<button class="button">Click to disable</button>
As isDisabled
is initially set to false, the disabled attribute should not appear at all.
On click, we should get the following:
<button class="button" disabled>Click to disable</button>
Before I even click the button to trigger the event, the above HTML actually renders to:
<button class="button" disabled="false">Click to disable</button>
and the button appears as disabled.
This is probably not a bug. The bug may actually be the human (i.e. me). Suggestions?
The browser support table reset, is that a problem, just wondering.
First of all, congrats for sticking to your idea and launching it! I'm a Vue.js fan and really like the idea of a lightweight alternative, specially for embedded apps.
I tried out Moon this afternoon and had a problem with props. I want to send data from the main Moon instance to a child component via props. Later this data will be loaded from an API.
// app.js
const Moon = require('moonjs')
const ContactsIndex = require('./contacts/index.moon')(Moon)
new Moon({
el: "#app",
data: {
contacts: [{name:"Pedro"},{name:"Augusto"},{name:"Borges"}]
}
})
// contacts/index.moon
<template>
<h1>Contacts</h1>
<ul>
<li m-for="person in {{contacts}}">{{person}}</li>
</ul>
</template>
<script>
exports = {
props: ['contacts']
}
</script>
<!-- /index.html -->
<div id="app" m-mask>
<Index contacts="{{contacts}}"/>
</div>
Moon passes the object as a string and renders each character on a li
element. Am I doing something wrong? I want to avoid converting and parsing JSON.
Another question⦠Is the component name tied to its file name? I want to organize components in folders and name them like so, ContactsIndex
. Moon only accepts the Index
name since the file is located at contacts/index.moon
.
Uncaught TypeError: Cannot set property 'moon' of null
at t.mount (unpkg.com/[email protected]:7)
at t.init (unpkg.com/[email protected]:7)
at new t (unpkg.com/[email protected]:7)
at main (main.js:31)
at index.html:22
const app1 = new Moon(
{
el : "#app1",
data : {
msg : "There is a Moon"
}
}
);
In the Getting Started section for "Loops", the part where it tells you...
Go ahead, try entering app5.set('list', ['New Item', 'Another Item']) in the console!
...generates the following error but still makes the changes to the HTML page.
Uncaught TypeError: Cannot read property 'type' of null
at E (unpkg.com/[email protected]:7)
at D (unpkg.com/[email protected]:7)
at D (unpkg.com/[email protected]:7)
at D (unpkg.com/[email protected]:7)
at t.patch (unpkg.com/[email protected]:7)
at t.build (unpkg.com/[email protected]:7)
at unpkg.com/[email protected]:7
Here's a JSBIN
http://jsbin.com/xavozefeti/2/edit?html,js,output
I wanted to write a small tutorial for the team here, and added some HTML comments.
<!DOCTYPE html>
<html>
<head>
<title>T-Shirt</title>
<meta charset="UTF-8">
<meta name="description" content="">
<meta name="keywords" content="">
<link rel="stylesheet" href="./t-shirt.css">
</head>
<body>
<div class="content">
All the narrow columns have editable content; simply click on an item to edit it.
<p>The T-shirt columns accept either upper- or lower-case input, limited to s, m, l, xl, and xxl.</p>
<p>The story points column accepts any number, but rounds up to the next value that would be appropriate for planning poker. Anything larger than 100 becomes 100.</p>
</div>
<div class="present" id="app"><!-- Moon will be told that this is the div that requires rendering -->
<table>
<tr>
<th>Story</th><th>Effort</th><th>Value</th><th>Points</th>
</tr>
<tr m-for="item in {{stories}}"><!-- See tshirt.js -->
<td class="story" m-html="{{item.story}}"></td>
<td class="work"><input data-type="work" size="4" value="{{item.work}}"></td>
<td class="value"><input data-type="value" size="4" value="{{item.value}}"></td>
<td class="points"><input data-type="points" size="4" value="{{item.points}}"></td>
</tr><!-- Moon will stop the rendering loop here -->
<tr>
<td class="story">Scores</td>
<td class="work result" id="work"></td>
<td class="value result" id="value"></td>
<td class="points result" id="points"></td>
</tr>
</table>
</div>
<script src="./Loader.js"></script>
<script src="./tshirt.js"></script>
</body>
</html>
Then I tried it with a space separating the angle brackets for the "see tshirt.js" comment:
<!DOCTYPE html>
<html>
<head>
<title>T-Shirt</title>
<meta charset="UTF-8">
<meta name="description" content="">
<meta name="keywords" content="">
<link rel="stylesheet" href="./t-shirt.css">
</head>
<body>
<div class="content">
All the narrow columns have editable content; simply click on an item to edit it.
<p>The T-shirt columns accept either upper- or lower-case input, limited to s, m, l, xl, and xxl.</p>
<p>The story points column accepts any number, but rounds up to the next value that would be appropriate for planning poker. Anything larger than 100 becomes 100.</p>
</div>
<div class="present" id="app"><!-- Moon will be told that this is the div that requires rendering -->
<table>
<tr>
<th>Story</th><th>Effort</th><th>Value</th><th>Points</th>
</tr>
<tr m-for="item in {{stories}}"> <!-- See tshirt.js -->
<td class="story" m-html="{{item.story}}"></td>
<td class="work"><input data-type="work" size="4" value="{{item.work}}"></td>
<td class="value"><input data-type="value" size="4" value="{{item.value}}"></td>
<td class="points"><input data-type="points" size="4" value="{{item.points}}"></td>
</tr><!-- Moon will stop the rendering loop here -->
<tr>
<td class="story">Scores</td>
<td class="work result" id="work"></td>
<td class="value result" id="value"></td>
<td class="points result" id="points"></td>
</tr>
</table>
</div>
<script src="./Loader.js"></script>
<script src="./tshirt.js"></script>
</body>
</html>
The results were unexpected:
I don't recall any explicit advice in the docs about being careful with HTML comments, but I certainly could have missed something.
First, add two forms of adding the class
attribute.
Single class:
<h1 class="className"></h1>
Array of Classes:
<h1 class="['className', 'otherClass']"></h1>
Next, add support for a class being a conditional statement in an object:
<h1 class="{className: {{condition}}, otherClass: {{condition}} === false}"></h1>
These objects can also be used in the array of classes.
Looking into your library and I like what I am seeing ... keep up the good work
There is no info in the docs on how to implement a component..
I tried implementing it but it takes in data as string and prints list with "," any reason why this happens?
<script src="https://unpkg.com/moonjs"></script>
<div id="app1">
<list data={{listdata}}></list>
</div>
<script>
var list = Moon.component("list", {
props:['data'],
template:"<ul><li m-for='item in {{data}}'>{{item}}</li></ul>"
})
var app = new Moon({
el:"#app1",
data: {
listdata:[0,1,2,3,4,5,6,7,8,9]
}
})
</script>
When compiling something like this:
<div id="app">
<h1>App</h1>
<ul>
<li m-for='item in items'>
<span>{{item}}</span>
<input />
</li>
</ul>
<button>Some Button</button>
</div>
It will create duplicate buttons, one inside the ul
element.
Edit: It's a problem with how the compiler encounters unclosed elements. It pushes all nodes into the unclosed element, it should actually create an empty one.
Features:
Item 2 brings me to a question: if my application has (for example) flight segments to be rendered
const trip = {
segments : [
{ origin:"MIA",dest:"MCO",date:"09SEP17",departs:"0800",arrives:"0852"},
{ origin:"MCO",dest:"ATL",date:"09SEP17",departs:"1020",arrives:"1115"},
// etc.
]
};
then what does the HTML look like to render that in Moon? (I couldn't make it work the way I wanted to in Vue, and mustaches don't seem to lend themselves to it.) Overall these frameworks seem oriented toward single-field renders or (at best) single-column data amenable to UL rendering. Can't quite get my head around complex data rendering for these things.
Placing same components side-by-side without wrapping at least one of them into plain HTML tag will result in TypeError: Cannot read property 'replaceChild' of null.
https://jsbin.com/qajelaw/edit?html,console,output
Is this an expected behavior and components should be wrapped into tags?
Making a new function call just to evaluate parameters is a very expensive operation, along with getting them inside the opening/closing parenthesis.
A better solution would be to just put the function call in the render method.
Hello @kingpixil π !
Great UI library! I've been looking for the LICENSE
file of the repo but it seems you only added it on the package.json
. It would be great to have it on the repo.
What are the advantages of MoonJS vs RiotJS(http://riotjs.com/)?
Are there more examples coming in order to illustrate what can be done with Moonjs?
I'm trying to fetch data from external json and can't figure out how, I'm using a kind of fechData fro VueJS (as both looks similar) and returning nothing. Any clues?
Nice framework. How should one access data attributes for use in methods?
An example tag.
<article
id="electriccars"
data-columns="3"
data-index-number="12314"
data-parent="cars">
</article>
Passing a template parameter to an event using m-on
doesn't render correctly.
For example:
<button m-on="click:someMethod({{val}})">Button</button>
Moon will throw an error or pass a random string instead of the expected value.
To fix this, maybe Moon should compile the template of the parameters.
If an unclosed tag is given to the compiler, there is now an infinite loop after an error is thrown, for example:
<h1>this will cause an infinite loop
See https://jsperf.com/object-keys-vs-for-in-with-closure/3.
If the for...in loops enumerate lots of properties, using Object.keys gives a huge performance boost in most cases (at the expense of some extra memory). If you're walking 4 items, perhaps no need to bother. Wouldn't be job #1 until Moon is long-term feature complete anyway.
For codecov, do I use my .travis.yml or codecov.yml or create a webhook in the repo? Sorry about this.
<script src="https://unpkg.com/moonjs"></script>
<div id="app1">
<simple-counter></simple-counter>
<simple-counter></simple-counter>
<simple-counter></simple-counter>
</div>
<script>
Moon.component('simple-counter', {
template: '<button m-on:click="add">{{ counter }}</button>',
data: {
counter: 0
},
methods: {
add: function () {
var v = this.get('counter');
this.set('counter', v + 1);
}
}
})
var app = new Moon({
el: "#app1"
})
</script>
the result is strange.
Here are a few lines of code that describes what I am trying to achieve:
test.html
<body>
<div id="app">
<p>{{msg}}</p>
<my-component></my-component>
<div id="dynamic"></div>
</div>
<button id="daBtn">Add</button>
<script src="js/vendor/jquery-1.12.0.min.js"></script>
<script src="node_modules/moonjs/dist/moon.min.js"></script>
<script src="js/main.js"></script>
</body>
main.js
Moon.component('my-component', {
template: "<h1>Custom Component</h1>"
});
var app = new Moon({
el: "#app",
data: {
msg: "Hello Moon!"
}
});
$('#daBtn').on('click', function(e) {
e.preventDefault();
$('#dynamic').append('<my-component></my-component>');
});
What would be the best way to notify the DOM to re-render and thus showing the newly injected component?
Thanks
Love the ideas presented by this library. Can we get a listing of what browsers will work with moon?
if your html is like this:
<section class="todoapp">
"<ccdacasd"
<header class="header">
<h1>todos</h1>
<input class="new-todo" autofocus="autofocus" autocomplete="off" placeholder="What needs to be done?">
</header>
</section>
it will be wrong
This is about the Moon JS framework
I'm using Moon 0.8.0
My browser is: Chrome 57.0.2987.133 (64-bit)
I am sure this issue is not (well sort of not) a duplicate
I am trying to use computed properties, which I saw had been added in early March 2017 (Issue #13). Since computed properties haven't been added to the docs, I decided to give it a kick at the can anyway, based on what I know about Vue. Sadly, I can't get it to work :-( .
My issue may also extend to method calls as well.
var app = new Moon({
el: "#app",
data: {
message: 'Hello World!'
},
computed: {
reversedMessage () {
return this.get('message').split('').reverse().join('')
}
}
})
<div id="app">
<h4 m-text="reversedMessage"></h4>
</div>
The reversedMessage
computed property method should fire, producing the following HTML:
<div id="app">
<h4>!dlroW olleH</h4>
</div>
The way things are now, reversedMessage
did not fire. Instead, it just rendered:
<div id="app">
<h4>reversedMessage</h4>
</div>
I tried to use pipe filters and there was an error. Are there any pipe filters functionalities? Thanks
Hi, I found svg tags are not working: https://jsfiddle.net/b2jky92x/
If there is any whitespace between the moustache braces, the information within the braces will not render. Some (like myself) like to incorporate a space between {{}}
and the data to make the code more readable.
Create a new Moon instance and within the data object, add a message:
var app1 = new Moon({
el: "#app1",
data: {
message: "Hello Moon!"
}
});
and within your HTML:
<p>{{ message }}</p>
{{ message }}
should be replaced by "Hello Moon!"
All you see in your HTML is "{{ message }}".
Currently, I cannot pass DOM instances as the el
option, which is expecting an identifier.
I think something like this could work:
this.$el = typeof el === 'string' ? document.querySelector(el) : el;
Implement a component system that can take props, and each has their own scope, etc.
when I set:
Moon.config.keyCodes({
esc: 27
});
but in a component, m-on:keyup.esc
is not work
Is it there a way to call functions inside of the delimited expressions for example:
...
computed : {
add : {
get : function (a, b) {
return a + b;
}
}
...
and in the html
<p>{{add(1, 3)}}</p>
Moon has trouble when there are different nodes of the same node name, such as two checkboxes. It assumes they are the same and goes on to diff the text nodes, but if the state has changed, no changes are shown.
EDIT:
It turns out this issue was with Moon updating the current node (patch in place). The issue should be fixed if it can rearrange, this can be implemented by having "key" system. The key will be a unique prop that lets Moon know which vnode belongs to what node, allowing it to rearrange the node accordingly.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.