You're Invited: Meet the Socket team at BSidesSF and RSAC - April 27 - May 1.RSVP
Socket
Sign inDemoInstall
Socket

als-component

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

als-component - npm Package Compare versions

Comparing version

to
0.7.0

64

component.js
class Component {
constructor(componentName,fn,data) {
this.start = Component.$genId()
this.$id=0
this.componentName = Component.$firstUpper(componentName)
this.componentName = componentName[0].toUpperCase() + componentName.substring(1)
this.fn = fn
this.data = data
this.actions={}
Component[this.componentName] = this
if(window) {
window['$C'+this.componentName] = this
window['$c'+this.componentName] = this.actions
}
}

@@ -14,13 +17,9 @@

update(data,id,updateElement=true) {
if(id) {
if(this[id] == undefined) this[id] = data
else if(data == undefined) data = this[id]
} else {
if(this.data == undefined) this.data = data
else if(data == undefined) data = this.data
data = this.___getData(data,id)
if(updateElement) {
let element = this.element(id)
if(element !== null) element.outerHTML = this.fn(data,id)
return element
}
let element = this.element(id)
if(element !== null && updateElement) {
element.outerHTML = this.fn(data,id)
} else return this.fn(data,id)
return this.fn(data,id)
}

@@ -31,24 +30,27 @@

if(id) selector += `#${id}`
try {return document.querySelector(selector)
} catch {return null}
let element = document.querySelector(selector)
if(element == null && id) delete this[id]
return element
}
genId(start=this.start) {
let id = start+this.$id
this.$id++
return id
___getData(data,id) {
let self = this
if(id) {
if(this[id] == undefined) this[id] = {
id,
data,
get element() {return self.element(id)},
update:(data) => this.update(data,id,true),
get:(data) => this.update(data,id,false),
}
else if(data !== undefined) this[id].data = data
else if(data == undefined) data = this[id].data
} else {
if(this.data == undefined && data !== undefined) this.data = data
if(data == undefined) data = this.data
}
return data
}
static $genId = (start='id') => `${start}${(Math.random() + 1).toString(36).substring(7)}`
static $firstUpper = (string) => string[0].toUpperCase() + string.substring(1)
static $ = (selector,source=document) => source.querySelector(selector)
static $$ = (selector,source=document) => [...source.querySelectorAll(selector)]
static $next = (element) => element.nextElementSibling
static $prev = (element) => element.previousElementSibling
static $parent = (element) => element.parentNode
static $var(varName,varValue) {
if(varValue == undefined) return getComputedStyle(document.documentElement).getPropertyValue('--'+varName)
else document.documentElement.style.setProperty('--'+varName,varValue)
return varValue
}
}
try {window.$C = (componentName,fn,data) => new Component(componentName,fn,data)} catch {}
try {module.exports = Component} catch{}
function exportComponents(components = res.components,fns=res.fns) {
let Component = require('./component')
let result = '<script>' + Component.toString()
fns.forEach(fn => {
result += `
Component.${fn.name} = ${fn.toString()}`
});
let fnsString = ''
for(let componentName in components) {
let {fn,data,update} = components[componentName]
let varName = componentName.charAt(0).toUpperCase() + componentName.slice(1)
result += `
let ${varName} = new Component('${varName}',${fn.toString()},${JSON.stringify(data)})
${update ? `${varName}.update()` : ''}
new Component('${componentName}',${fn.toString()},${JSON.stringify(data)})
${update ? `.update()` : ''}
`
let curentFns = fns[componentName]
curentFns.forEach(fn => {
let Cn = componentName.charAt(0).toUpperCase() + componentName.slice(1);
fnsString += `Component.${Cn}.actions.${fn.name} = ${fn.toString()}
`
});
}
result += fnsString
result += '</script>'

@@ -22,5 +25,6 @@ return result

res.components = {}
res.fns = []
res.fns = {}
res.component = function(componentName,fn,data,update=false) {
res.components[componentName] = {fn,data,update}
res.fns[componentName] = []
}

@@ -27,0 +31,0 @@ res.exportComponents = function(components = res.components,fns=res.fns) {

{
"name": "als-component",
"version": "0.6.1",
"version": "0.7.0",
"description": "Managing components and states.",
"main": "export.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Alex Sorkin",
"license": "MIT"
}

@@ -11,21 +11,14 @@ # Als-component

*new in 0.5*
* auto capitalize component name on constructor
* ``component.genId(start)`` method - generating id and increasing it automaticly
*new in 0.7*
* all utilities removed (you can use als-dom instead)
* window.$C function = new Component()
* window.$C{ComponentName}
* component.{$id} = {id,update,get,element}
*new in 0.6*
* component(object) methods:
* get method
* element method
* Component (class) methods
* $genId
* $firstUpper
* $
* $$
* $next
* $prev
* $parent
* $var
The version has tested - all should work.
If not, please contact me - Alexsorkin1980@gmail.com
**main**
There are 3 files:

@@ -36,8 +29,13 @@ 1. component.js - for frontend usage

## Component.js
Syntax:
```javascript
new Component(ComponentName,fn,data)
.update(data,id,updateElement=true)
.get(data,id) // => update(data,id,false)
let c = new Component(ComponentName,fn,data)
c.update(data,id,updateElement=true) // return created element
c.get(data,id) // return string html
c.element() // return component's element
c[id] = {update,get,data,element,id}
c.actions // empty object for action functions
```

@@ -47,9 +45,10 @@

* ``new Component(ComponentName,fn,data)``
* **ComponentName** - Name of component, which will be available as Component.componentName
* Has to start with capital (constructor will capitalize first letter anyway)
* **ComponentName** - Name of component
* Available as Component.ComponentName or as $CComponentName
* **fn** - function(data,id) which has to return html code
* html code has to be between ``<tag component="componentName" id="id"></tag>``
* html code has to be between ``<tag component="componentName" id="id"></tag>`` if you want to update the component (not to get it)
* id parameter necessary only then you use more then one component
* **data** - "the state" for component
* available as ``Component.componentName.data`` or ``Component.componentName.id`` if there is id
* available as ``Component.componentName.data`` or ``Component.componentName.id.data`` if there is id
* ``update(data,id,updateElement=true)``

@@ -60,2 +59,4 @@ * **data** - updates the "state".

* **id** - specify which data to use and which element to update
* will create object componet.id= {id,data,element,update,get}
* element is a getter
* **updateElement** - if false, update will return fn result only (without updating html element)

@@ -65,9 +66,17 @@ * true by default - updating data and html element

### Name convention
Component.Upper - Component
Component.lower - fn
Component.$fn - $utility
* ``get(data,id)`` - same as update, but with ``updateElement=false``
### Example
### window shortcuts
Syntax
```javascript
let ComponentName = 'test'
$C(ComponentName,fn,data) // equivalent to new Component(ComponentName,fn,data)
$CTest // equivalent to Component.Test
$cTest // equivalent to Component.Test.actions
```
### Example simple counter
```html

@@ -78,56 +87,117 @@ <!-- Include component.js -->

<!-- Here will appear App component-->
<div component="app"></div>
<div component="counter">0</div>
<button onclick="$CCounter.update(1)">+</button>
<button onclick="$CCounter.update(-1)">-</button>
<script>
// Creating component Test (must be before App)
let Test = new Component('Test',function({testing,some},id) {
return /*html*/`<div component="test">
test component
<div>${testing}</div>
<div>${some}</div>
$C('counter',(add) =>{
let curent = parseInt($CCounter.element().innerHTML)
return /*html*/`<div component="counter">${curent+add}</div>`
})
</script>
```
### Example todos
```html
<div component="todos"></div>
<input type="text" onchange="$cTodos.addNew(this)">
<script>
let todos = [
{title: "delectus aut autem",completed: true},
{title: "quis ut nam facilis et officia qui",completed: false},
{title: "fugiat veniam minus",completed: false}
]
$C('todo',function(todo,id){
let index = id.replace('todo','')
return /*html*/`<div component="todo" id="${id}" >
<span ${todo.completed ? 'style="text-decoration:line-through"' : ''}
onclick="$cTodo.update('${id}')">${todo.title}</span>
<button onclick="$cTodo.remove(${index})">&times;</button>
</div>`
})
// Creating component App with Test component inside
new Component('App',function(data,id) {
let testing = 'testing variable'
return /*html*/`<div component="app">
${Test.get({testing,some:'some variable'},'test-id')}
<input type="text" value="${testing}"
oninput="
Test.data.testing = this.value
Test.update()
">
<div id="test">Hello from main component</div>
$C('todos',function (data){
return /*html*/`<div component="todos">
${data.map((todo,index) => $CTodo.get(
todo,'todo'+index
)).join('')}
</div>`
}).update() // updating component App in html
}).update(todos)
// element method
App.element() // return app html element
Test.element('test-id') // return test html element
$CTodos.actions.addNew = (element) => {
$CTodos.data.unshift({title:element.value,completed:false})
$CTodos.update()
element.value = ''
}
$CTodo.actions.update = (id) => {
$CTodo[id].data.completed = !$CTodo[id].data.completed;
$CTodo[id].update()
}
$CTodo.actions.remove = (index) => {
$CTodos.data.splice(index,1)
$CTodos.update()
}
</script>
```
The example above, creates 2 components(App,Test) and inserting it to ``<div component="app"></div>``.
### utility methods
## router.js
```js
let {$genId,$firstUpper,$qs,$qsa,$next,$prev,$parent,$var} = Component
$genId() // idsxiz5j
$genId('test-') // test-sxiz5j
$firstUpper('some'), // Some
$('#test'), // $(selector,source=document) = document.querySelctor(selector)
$$('.some'), // $$(selector,source=document) = document.querySelctorAll(selector)
$next(dom), // = dom.nextElementSibling
$prev(dom), // = dom.previousElementSibling
$parent(dom), // = dom.parentNode
$var('bg-color'), // getting value for css variable var(--bg-color)
$var('bg-color','blue'), // set new value to var(--bg-color)
router.js has function ``router(routes,defaultRoute)``. The function allows you to use html layout for js files and functions.
**Parameters:**
* routes - object where keys is a keys for ``?route=key`` and value is a src of js file or function.
* defaultRoute - src of js file or function
Here is example:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<script src="/node_modules/als-component/component.js"></script>
<script src="/node_modules/als-component/router.js"></script>
<title>Some</title>
</head>
<body>
<nav>
<a href="?route=test">test</a>
<a href="?route=test1">test1</a>
</nav>
<main component="main"></main>
</body>
<script>
router({
test1:'/test1.js',
test:() => new Componenet('test',/*html*/`
<main component="main">Hello from test fn</main>
`).update()
},'/home.js')
</script>
</html>
```
**test1.js**
```javascript
new Componenet('Test',/*html*/`
<main component="main">Hello from test1.js</main>
`).update()
```
**home.js**
```javascript
Component.$(['component=main']).innerHTML = /*html*/`
Home page - default page if route not found.
`
```
## export.js

@@ -141,3 +211,3 @@ For using export with express you need to add it as middleware:

res.component(componentName,fn,data,update=false) // creating components
res.fns // array for functions which will be available on Component.fnName
res.fns // object for actions
return res.end(`

@@ -150,2 +220,3 @@ <some html>

Let's see how todo application will work with Component. The files we will need:

@@ -155,16 +226,23 @@ 1. todo.js - component for single todo

3. data.js - with todos array
4. addnew.js - action for adding new todo
4. actions.js - action for adding new todo
5. server.js - server using express and running the app
**data.js**
```javascript
module.exports = [
{title: "delectus aut autem",completed: true},
{title: "quis ut nam facilis et officia qui",completed: false},
{title: "fugiat veniam minus",completed: false}
]
```
**todo.js**
```javascript
module.exports = function(todo,id){
return /*html*/`<div component="todo" id="${id}"
${todo.completed ? 'style="text-decoration:line-through"' : ''}
onclick="
Todo['${id}'].completed = !Todo['${id}'].completed;
Todo.update(undefined,'${id}')
">
${todo.title}
module.exports = function(todo,id) {
let index = id.replace('todo','')
return /*html*/`<div component="todo" id="${id}" >
<span ${todo.completed ? 'style="text-decoration:line-through"' : ''}
onclick="$cTodo.update('${id}')">${todo.title}</span>
<button onclick="$cTodo.remove(${index})">&times;</button>
</div>`

@@ -176,7 +254,6 @@ }

```javascript
module.exports = function (data,id){
module.exports = function (data){
return /*html*/`<div component="todos">
${data.map(todo=> Component.Todo.get(
todo,
Component.Todo.genId('todo')
${data.map((todo,index) => $CTodo.get(
todo,'todo'+index
)).join('')}

@@ -187,17 +264,20 @@ </div>`

**data.js**
**actions.js**
```javascript
module.exports = [
{title: "delectus aut autem",completed: true},
{title: "quis ut nam facilis et officia qui",completed: false},
{title: "fugiat veniam minus",completed: false}
]
```
let addNew = (element) => {
$CTodos.data.unshift({title:element.value,completed:false})
$CTodos.update()
element.value = ''
}
**addnew.js**
```javascript
module.exports = function addNew(element) {
Component.Todos.data.unshift({title:element.value,completed:false})
Component.Todos.update()
let update = (id) => {
$CTodo[id].data.completed = !$CTodo[id].data.completed;
$CTodo[id].update()
}
let remove = (index) => {
$CTodos.data.splice(index,1)
$CTodos.update()
}
module.exports = {addNew,update,remove}
```

@@ -211,7 +291,10 @@

app.get('/',(req,res) => {
res.fns.push(require('./addnew')) // Adding function
// Defining components
res.component('Todo',require('./todo'))
res.component('Todos',require('./todos'),require('./data'),true)
// Defining components
res.component('todo',require('./todo'))
res.component('todos',require('./todos'),require('./data'),true)
// Adding actions
let {addNew,update,remove} = require('./actions')
res.fns.todo.push(update)
res.fns.todo.push(remove)
res.fns.todos.push(addNew)
return res.end(/*html*/`<!DOCTYPE html>

@@ -224,3 +307,3 @@ <html lang="en">

<div component="todos"></div>
<input type="text" onchange="Component.addNew(this)">
<input type="text" onchange="$cTodos.addNew(this)">
${res.exportComponents()}

@@ -232,53 +315,1 @@ </body>

```
## router.js
router.js has function ``router(routes,defaultRoute)``. The function allows you to use html layout for js files and functions.
**Parameters:**
* routes - object where keys is a keys for ``?route=key`` and value is a src of js file or function.
* defaultRoute - src of js file or function
Here is example:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<script src="/node_modules/als-component/component.js"></script>
<script src="/node_modules/als-component/router.js"></script>
<title>Some</title>
</head>
<body>
<nav>
<a href="?route=test">test</a>
<a href="?route=test1">test1</a>
</nav>
<main component="main"></main>
</body>
<script>
router({
test1:'/test1.js',
test:() => new Componenet('test',/*html*/`
<main component="main">Hello from test fn</main>
`).update()
},'/home.js')
</script>
</html>
```
**test1.js**
```javascript
new Componenet('Test',/*html*/`
<main component="main">Hello from test1.js</main>
`).update()
```
**home.js**
```javascript
Component.$(['component=main']).innerHTML = /*html*/`
Home page - default page if route not found.
`
```