Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.idea/
.idea/*
64 changes: 64 additions & 0 deletions aimara-es6/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Aimara</title>

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">

<link rel="stylesheet" type="text/css" href="src/css/aimara.es6.css">
</head>
<body>
<div id="target-div"></div>
<script type="text/javascript" src="src/js/aimara.es6.js"></script>
<script type="text/javascript" src="src/js/aimara.es6.model.js"></script>
<script type="text/javascript" src="src/js/aimara.es6.view.js"></script>
<script type="text/javascript" src="src/js/aimara.es6.controller.js"></script>

<script type="text/javascript" src="src/js/aimara.node.es6.js"></script>
<script type="text/javascript" src="src/js/aimara.node.model.es6.js"></script>
<script type="text/javascript" src="src/js/aimara.node.view.es6.js"></script>
<script type="text/javascript" src="src/js/aimara.node.controller.es6.js"></script>


<script type="text/javascript">
let tree = new Aimara('target-div', null);

for (var i=1; i<10; i++) {
node1 = tree.createNode({icon: '', label: `Level 1: ${String(i).padStart(2, '0')}`});
for (var j=1; j<5; j++) {
node2 = tree.createChildNode(node1, {icon: '', label: `Level 2: ${String(j).padStart(2, '0')}`, contextMenu: {
itemName: {
icon: 'fa-wrench',
label: 'Menu de contexto 01',
action: ()=>{ console.log('MENU 1'); },
submenus: {
itemName: {
icon: 'fa-wrench',
label: 'Menu de contexto 01 - 01',
action: ()=>{ console.log('MENU 1 - S01'); },
submenus: null
},
itemName2: {
icon: 'fa-wrench',
label: 'Menu de contexto 01 - 02',
action: ()=>{ console.log('MENU 1 - S02'); },
submenus: null
}
}
},
itemName2: {
icon: 'fa-wrench',
label: 'Menu de contexto 02',
action: ()=>{ console.log('MENU 2'); },
submenus: null
}
}});
for (var k=1; k<5; k++) {
node3 = tree.createChildNode(node2, {icon: 'fa-wrench', label: `Level 3: ${String(i).padStart(2, '0')}`});
}
}
}
</script>
</body>
</html>
135 changes: 135 additions & 0 deletions aimara-es6/src/css/aimara.es6.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
ul.tree * {
transition: all .2s linear;
}
ul.tree,
ul.tree ul {
list-style: none;
position: relative;
}
ul.tree li {
position: relative;
margin-bottom: .7rem;
white-space: nowrap;
text-overflow: ellipsis;
}
ul.tree li > span {
border-radius: .1rem;
padding: .3rem .6rem;
}
ul.tree li.selected > span,
ul.tree li.hover > span:hover {
cursor: pointer;
background-color: green;
}
ul.tree li > ul {
display: none;
margin-top: .6rem;
}
ul.tree li.on > ul {
display: block;
}

ul.tree li > i {
margin-right: .5rem;
z-index: 1;
}

ul.tree li > span > i {
margin-right: .25rem;
}
ul.tree li:before {
content: '';
display: inline-block;
width: 2.5rem;
height: 1.7rem;
border-right: unset;
border-top: unset;
border-left: 1px dashed lightgray;
border-bottom: 1px dashed lightgray;
position: absolute;
left: -2rem;
top: -1.2rem;
z-index: -1;
}
ul.tree > li:first-child:before {
border-left: 1px dashed lightgray;
border-bottom: 1px dashed lightgray;
height: 1rem;
top: -.5rem;
}
ul.tree li:not(:last-child) > ul:before {
content: '';
display: inline-block;
width: 0;
height: calc(100% + .7rem);
border-right: unset;
border-top: unset;
border-left: 1px dashed lightgray;
border-bottom: 1px dashed lightgray;
position: absolute;
left: -2rem;
top: -1.15rem;
z-index: -1;
}
ul.tree li:last-child:before {
border-bottom-left-radius: 5px;
z-index: -1;
}

ul.context-menu,
ul.context-menu ul {
list-style: none;
}
ul.context-menu {
padding: 0;
margin: 0;
position: fixed;
display: block;
max-width: 0;
max-height: 0;
overflow-x: hidden;
overflow-y: hidden;
z-index: 10;

border: 1px solid rgba(0, 0, 0, .1);
border-radius: 2px;
box-shadow: 0 0 5px 0 rgba(0,0,0,0.75);
background-color: white;
}
ul.context-menu.active {
max-width: 50vw;
max-height: 50vh;
overflow-y: auto;
}
ul.context-menu li span {
padding: .5rem .7rem;
display: block;
cursor: pointer;
}
ul.context-menu li > ul > li > span {
padding: 5px;
}
ul.context-menu li span i:first-child {
margin-right: .5rem;
}
ul.context-menu i.chevron {
float: right;
transition: all .4s linear;
}
ul.context-menu li > ul {
max-height: 0;
overflow: hidden;
transition: all .4s ease-in;
}
ul.context-menu li:hover > ul {
max-height: 50vh;
transition: all .4s ease-out;
}
ul.context-menu li:hover > span > i.chevron {
transform: rotate(90deg);
transition: all .4s linear;
}

ul.context-menu li:hover > span {
background-color: lightgrey;
}
91 changes: 91 additions & 0 deletions aimara-es6/src/js/aimara.es6.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
class AimaraController {
/** * @param {Aimara} parent */
constructor(parent) {
/** * @type {Aimara} */
this.parent = parent;
}


/**
*
* @param {Event} event
* @param {{parent: *, img: HTMLElement, label: {img: HTMLElement, anchor: HTMLElement, span: HTMLElement}, li: HTMLElement, events: {onClickExpandCollapse: {before: Array, after: Array}, onClickNodeHolderImage: {before: Array, after: Array}, onClickNodeHolder: {before: Array, after: Array}, onClickNodeHolderAnchor: {before: Array, after: Array}, onClickNode: {before: Array, after: Array}}, child: null}} node
*/
onClickNode(event, node) {
event.preventDefault();
event.stopPropagation();
node.events.onClickNode.before.map(callback => callback(event, node));

node.events.onClickNode.after.map(callback => callback(event, node));
}

/**
*
* @param {Event} event
* @param {{parent: *, img: HTMLElement, label: {img: HTMLElement, anchor: HTMLElement, span: HTMLElement}, li: HTMLElement, events: {onClickExpandCollapse: {before: Array, after: Array}, onClickNodeHolderImage: {before: Array, after: Array}, onClickNodeHolder: {before: Array, after: Array}, onClickNodeHolderAnchor: {before: Array, after: Array}, onClickNode: {before: Array, after: Array}}, child: null}} node
*/
onClickNodeHolder(event, node) {
event.preventDefault();
event.stopPropagation();

node.events.onClickNodeHolder.before.map(callback => callback(event, node));

node.events.onClickNodeHolder.after.map(callback => callback(event, node));
}

/**
*
* @param {Event} event
* @param {{parent: *, img: HTMLElement, label: {img: HTMLElement, anchor: HTMLElement, span: HTMLElement}, li: HTMLElement, events: {onClickExpandCollapse: {before: Array, after: Array}, onClickNodeHolderImage: {before: Array, after: Array}, onClickNodeHolder: {before: Array, after: Array}, onClickNodeHolderAnchor: {before: Array, after: Array}, onClickNode: {before: Array, after: Array}}, child: null}} node
*/
onClickNodeHolderImage(event, node) {
event.preventDefault();
event.stopPropagation();

node.events.onClickNodeHolderImage.before.map(callback => callback(event, node));

node.events.onClickNodeHolderImage.after.map(callback => callback(event, node));
}

/**
*
* @param {Event} event
* @param {{parent: *, img: HTMLElement, label: {img: HTMLElement, anchor: HTMLElement, span: HTMLElement}, li: HTMLElement, events: {onClickExpandCollapse: {before: Array, after: Array}, onClickNodeHolderImage: {before: Array, after: Array}, onClickNodeHolder: {before: Array, after: Array}, onClickNodeHolderAnchor: {before: Array, after: Array}, onClickNode: {before: Array, after: Array}}, child: null}} node
*/
onClickNodeHolderAnchor(event, node) {
event.preventDefault();
event.stopPropagation();

node.events.onClickNodeHolderAnchor.before.map(callback => callback(event, node));

node.events.onClickNodeHolderAnchor.after.map(callback => callback(event, node));
}

/**
*
* @param {Event} event
* @param {{parent: *, img: HTMLElement, label: {img: HTMLElement, anchor: HTMLElement, span: HTMLElement}, li: HTMLElement, events: {onClickExpandCollapse: {before: Array, after: Array}, onClickNodeHolderImage: {before: Array, after: Array}, onClickNodeHolder: {before: Array, after: Array}, onClickNodeHolderAnchor: {before: Array, after: Array}, onClickNode: {before: Array, after: Array}}, child: null}} node
*/
onClickExpandCollapse(event, node) {
event.preventDefault();
event.stopPropagation();
node.events.onClickExpandCollapse.before.map(callback => callback(event, node));

if (node.li.classList.contains('on')) {
node.li.classList.remove('on');
if (node.child) { node.img.src = 'static/vendors/aimara/images/expand.png'; }
} else {
node.li.classList.add('on');
if (node.child) { node.img.src = 'static/vendors/aimara/images/collapse.png'; }
}

node.events.onClickExpandCollapse.after.map(callback => callback(event, node));
}
}

class AimaraException extends DOMException {
constructor(message) {
super();
console.log(message);
}
}
66 changes: 66 additions & 0 deletions aimara-es6/src/js/aimara.es6.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
class Aimara {
/**
*
* @param {string|HTMLElement} container
* @param {Aimara.defaults.options|null|undefined} options
*/
constructor(container, options) {
options = options || JSON.parse(JSON.stringify(Aimara.defaults.options));
/** * @type {Aimara.defaults.options|{}} */
this.options = options;

/** * @type {HTMLElement|null} */
this.container = null;

if (typeof(container) === "string") { this.container = document.getElementById(container); }
else if (container instanceof HTMLElement) { this.container = container; }
else { throw new AimaraException("Invalid Parent container.\n\nThe Parent container could be type of string or HTMLElement"); }

if (!this.container) { throw new AimaraException("Invalid Parent container.\n\nThe Parent container could be type of string or HTMLElement"); }

/** * @type {AimaraModel} */
this.model = new AimaraModel(this);
/** * @type {AimaraView} */
this.view = new AimaraView(this);
/** * @type {AimaraController} */
this.controller = new AimaraController(this);
}

/**
*
* @param {AimaraNode.defaults.options} options
* @return {AimaraNode}
*/
createNode(options) {
return this.model.createNode(null, options);
}

/**
*
* @param {HTMLElement|null|undefined} parent
* @param {AimaraNode.defaults.options} options
* @return {AimaraNode}
*/
createChildNode(parent, options) {
return this.model.createNode(parent, options);
}

clear() {
this.model.nodeList.map(node => node.remove());
this.model.nodeList = [];
}
expandAll() { this.model.nodeList.map(node => node.controller.expand(null)); }
collapseAll() { this.model.nodeList.map(node => node.controller.collapse(null)); }
}

/**
*
* @type {{options: {hover: boolean|null|undefined, select: boolean|null|undefined, multiSelection: boolean|null|undefined}}}
*/
Aimara.defaults = {
options: {
multiSelection: true,
select: true,
hover: true
}
};
25 changes: 25 additions & 0 deletions aimara-es6/src/js/aimara.es6.model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
class AimaraModel {
/** * @param {Aimara} parent */
constructor(parent) {
/** * @type {Aimara} */
this.parent = parent;

/** * @type {[AimaraNode]} */
this.nodeList = [];
}

/**
*
* @param {HTMLElement|null|undefined} parent
* @param {AimaraNode.defaults.options} options
* @return {AimaraNode}
*/
createNode(parent, options) {
let node = new AimaraNode(this.parent, parent, options);
this.nodeList.push(node);
if (!parent) { this.parent.view.mainHolder.appendChild(this.nodeList[this.nodeList.length - 1].li); }
else { this.nodeList[this.nodeList.length - 1].parent.appendChild(this.nodeList[this.nodeList.length - 1].li); }
return this.nodeList[this.nodeList.length - 1];
}

}
Loading