Switching to ng2 side menu (#65)

Closes #63
This commit is contained in:
Nejc Zdovc
2016-07-11 17:14:56 +02:00
committed by József Farkas
parent d20101c981
commit 036c2d0a70
26 changed files with 707 additions and 548 deletions

189
app.js
View File

@@ -1,64 +1,20 @@
$(function() {
// Handlebars template for Sidebar menu.
var sidebarMenuSource = $('#sidebar-menu--source').html();
var sidebarMenuTemplate = Handlebars.compile(sidebarMenuSource);
$('#sidebar-menu').html(sidebarMenuTemplate(menuObject));
_init('.keymap--edit');
// =======================
// Menu-item functionality
// =======================
$('.sidebar__level-2--item').on('click', function() {
var _this = $(this);
var dataContent = _this.data('content');
var dataAbbrev = _this.data('abbrev');
var dataName = _this.data('name');
var _currentView = $('.main-content__inner:visible');
// This can be the same as _currentView.
var _newView = $(dataContent);
// Switch to the corresponding view.
_currentView.hide();
_newView.show();
// Modify name for Factory keymap.
if (dataAbbrev == 'FTY') {
dataName = 'Factory';
_newView.find('.pane-title__name').attr('contenteditable', false);
_newView.find('.pane-title__abbrev').attr('contenteditable', false);
_newView.find('.keymap__remove').hide();
} else {
_newView.find('.pane-title__name').attr('contenteditable', true);
_newView.find('.pane-title__abbrev').attr('contenteditable', true);
_newView.find('.keymap__remove').show();
}
// Hide (undo) notification if any was shown.
$('.notification').on('click', '.notification__dismiss', function(e) {
$('.notification').hide();
}).on('click', '.notification__action--undo', function(e) {
$('.notification').hide();
$('.sidebar__level-2--item:hidden').show().click();
});;
// Fill pane title based on data attributes.
if (dataName != '') {
_newView.find('.pane-title__name').text(dataName);
}
if (dataAbbrev != '') {
_newView.find('.pane-title__abbrev').text(dataAbbrev);
}
// Change .active class in the sidebar.
$('.sidebar__level-2--item.active').removeClass('active');
_this.addClass('active');
_init(dataContent);
});
// ========================
// Keymap related settings.
// ========================
$(function () {
$('[data-toggle="tooltip"]').tooltip()
});
// =======================
// Menu-item functionality LEGACY TODO remove
// =======================
$('.pane-title__name, .pane-title__abbrev').on('mouseover', function() {
$(this).addClass('active');
}).on('mouseout', function() {
@@ -73,11 +29,9 @@ $(function() {
$(this).toggleClass('fa-star-o');
});
$('.sidebar__level-1', '.sidebar__level-1--item').on('click', function() {
$(this).parents('.sidebar__level-1--item').find('ul').slideToggle();
$(this).find('.fa-chevron-down, .fa-chevron-up').toggleClass('fa-chevron-down fa-chevron-up')
});
// ========================
// Keymap related settings.
// ========================
$('button.uhk__layer-switcher').on('click', function(e) {
var button = $(this),
layerOrder = ['base', 'mod', 'fn', 'mouse'],
@@ -131,13 +85,6 @@ $(function() {
$('.notification').show();
});
$('.notification').on('click', '.notification__dismiss', function(e) {
$('.notification').hide();
}).on('click', '.notification__action--undo', function(e) {
$('.notification').hide();
$('.sidebar__level-2--item:hidden').show().click();
});;
// Based on: http://stackoverflow.com/a/24933495
$('img.uhk').each(function(){
var $img = $(this);
@@ -190,7 +137,6 @@ $(function() {
}, 'xml');
});
});
function _init(view) {
@@ -201,116 +147,3 @@ function _init(view) {
break;
}
}
var menuObject = {
menu: [
{
icon: 'keyboard-o',
name: 'Keymaps',
hasDefaults: true,
expandable: true,
dataContent: '.keymap--edit',
children: [
{
icon: '',
name: 'Factory keymap',
abbrev: 'FTY',
isDefault: true
},
{
icon: '',
name: 'QWERTY',
abbrev: 'QTY',
classes: 'active'
},
{
icon: '',
name: 'Dvorak',
abbrev: 'DVR',
},
{
icon: '',
name: 'Colemak',
abbrev: 'COL',
},
{
icon: '',
name: 'VIM',
abbrev: 'VIM',
},
{
icon: '',
name: 'Mortal Kombat X',
abbrev: 'MKX',
}
]
},
{
icon: 'keyboard-o',
name: 'Keymaps-ng2',
hasDefaults: true,
expandable: true,
dataContent: '.keymap--edit-ng2',
children: [
{
icon: '',
name: 'Factory keymap',
abbrev: 'FTY',
isDefault: true
}
]
},
{
icon: 'play',
name: 'Macros',
expandable: true,
dataContent: '.macro--edit',
children: [
{
icon: '',
name: 'Macro1'
},
{
icon: '',
name: 'Macro2'
},
{
icon: '',
name: 'Macro3'
},
{
icon: '',
name: 'Macro4'
}
]
},
{
'icon': 'puzzle-piece',
'name': 'Add-on modules',
'children': [
{
'icon': '',
'name': 'Key cluster'
},
{
'icon': '',
'name': 'Trackball'
},
{
'icon': '',
'name': 'Toucpad'
},
{
'icon': '',
'name': 'Trackpoint'
}
]
}
],
menuBottom: [
{
'icon': 'gear',
'name': 'Settings'
}
]
};

View File

@@ -1,29 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Ultimate Hacking Keyboard Configurator</title>
<link href="node_modules/font-awesome/css/font-awesome.min.css" rel="stylesheet">
<link href="node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="css/app.css" rel="stylesheet">
<link href="css/macro.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
<script>
// This js function is here to make sure it loads before any iframe content on the page.
function resizeIframe(ifr) {
ifr.style.height = (ifr.contentWindow.document.body.scrollHeight + 300) + 'px';
ifr.style.width = ifr.contentWindow.document.body.scrollWidth + 'px';
}
</script>
<script src="node_modules/jquery/dist/jquery.min.js"></script>
<base href="/">
</head>
<body>
<div class="github-fork-ribbon">
<a class="" href="https://github.com/UltimateHackingKeyboard/agent" title="Fork me on GitHub">Fork me on GitHub</a>
</div>
<!-- Google Tag Manager -->
<noscript>
<iframe src="//www.googletagmanager.com/ns.html?id=GTM-PQLCXB" height="0" width="0" style="display:none;visibility:hidden"></iframe>
@@ -37,188 +30,19 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
</script>
<!-- End Google Tag Manager -->
<div id="sidebar-menu" class="split split-horizontal sidebar-menu" style=""></div>
<div id="main-content" class="split split-horizontal container-fluid main-content" style="">
<div class="notification" style="display: none">
<span class="notificatin__text">Keymap removed</span>
<a href="#" class="notification__action notification__action--undo">Undo</a>
<span class="notification__dismiss">&times;</span>
</div>
<div class="keymap--edit keymap--qwerty main-content__inner" style="display: block;">
<div class="row">
<h1 class="col-xs-12 pane-title">
<i class="fa fa-keyboard-o"></i>
<span class="keymap__name pane-title__name" contenteditable="true">QWERTY</span> keymap (<span class="keymap__abbrev pane-title__abbrev" contenteditable="true">QTY</span>)
<i class="fa fa-star-o fa-star keymap__is-default"></i>
<i class="glyphicon glyphicon-trash keymap__remove pull-right" title="Remove keymap" data-toggle="tooltip" data-placement="left"></i>
</h1>
</div>
<div class="row">
</div>
<div class="row uhk--wrapper">
<div class="col-xs-12 text-center" style="margin-bottom: 2rem;">
<span class="uhk__layer-switcher--wrapper" role="" data-title="Layers: ">
<button type="button" data-layer="base" class="uhk__layer-switcher btn btn-primary btn-lg current">Base</button>
<button type="button" data-layer="mod" class="uhk__layer-switcher btn btn-default btn-lg">Mod</button>
<button type="button" data-layer="fn" class="uhk__layer-switcher btn btn-default btn-lg">Fn</button>
<button type="button" data-layer="mouse" class="uhk__layer-switcher btn btn-default btn-lg">Mouse</button>
</span>
</div>
<div class="col-xs-12">
<div class="keyboard-slider">
<div class="item uhk__layer-wrapper uhk__layer-wrapper--base current">
<img src="./images/base-layer.svg" class="uhk uhk--base-layer" alt="">
</div>
<div class="item uhk__layer-wrapper uhk__layer-wrapper--mod">
<img src="./images/base-layer--blank.svg" class="uhk uhk--mod-layer" alt="">
</div>
<div class="item uhk__layer-wrapper uhk__layer-wrapper--fn">
<img src="./images/base-layer--dvorak.svg" class="uhk uhk--fn-layer" alt="">
</div>
<div class="item uhk__layer-wrapper uhk__layer-wrapper--mouse">
<img src="./images/base-layer.svg" class="uhk uhk--mouse-layer" alt="">
</div>
</div>
<iframe src="popup__iframe.html" class="key-editor__popup" frameborder="0" scrolling="no" onload="resizeIframe(this)" style="display: none;"></iframe>
</div>
</div>
</div>
<div class="keymap--edit-ng2 main-content__inner" style="display: none; height: 100%; width: 100%;">
<main-app style="display: flex; height: 100vh; width: 100%;"></main-app>
</div>
<div class="macro--edit main-content__inner" style="display: none;">
<div class="row">
<h1 class="col-xs-12 pane-title">
<i class="fa fa-play"></i>
<span class="macro__name pane-title__name" contenteditable="true">Macro1</span> <i class="fa"></i>
</h1>
</div>
<div class="row">
<div id="listWithHandle" class="list-group col-xs-10 col-xs-offset-1">
<div class="list-group-item action--item">
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
<i class="fa fa-mouse-pointer"></i> Move pointer by 100px leftward
<i class="glyphicon glyphicon-pencil action--edit"></i>
<i class="glyphicon glyphicon-trash action--trash"></i>
</div>
<div class="list-group-item macro-settings" style="display: none;">
<div class="helper"></div>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo
dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor
sit amet.</p>
<div class="row">
<div class="col-sm-12 flex-button-wrapper">
<button class="btn btn-primary btn-sm pull-right flex-button settings-save">Save</button>
<button class="btn btn-default btn-sm pull-right flex-button settings-cancel" style="margin-right: .5em;">Cancel</button>
</div>
</div>
</div>
<div class="list-group-item action--item">
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
<i class="fa fa-square"></i> Press letter A
<i class="glyphicon glyphicon-pencil action--edit"></i>
<i class="glyphicon glyphicon-trash action--trash"></i>
</div>
<div class="list-group-item action--item">
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
<i class="fa fa-square"></i> Press Alt+Tab
<i class="glyphicon glyphicon-pencil action--edit"></i>
<i class="glyphicon glyphicon-trash action--trash"></i>
</div>
<div class="list-group-item action--item">
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
<i class="fa fa-clock-o"></i> Delay of 235ms
<i class="glyphicon glyphicon-pencil action--edit"></i>
<i class="glyphicon glyphicon-trash action--trash"></i>
</div>
<div class="list-group-item action--item">
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
<i class="fa fa-mouse-pointer"></i> Press button 1
<i class="glyphicon glyphicon-pencil action--edit"></i>
<i class="glyphicon glyphicon-trash action--trash"></i>
</div>
<div class="list-group-item action--item">
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
<i class="fa fa-mouse-pointer"></i> Scroll by 150px downward
<i class="glyphicon glyphicon-pencil action--edit"></i>
<i class="glyphicon glyphicon-trash action--trash"></i>
</div>
<div class="list-group-item action--item add-new__action-item no-reorder">
<a href="#" class="add-new__action-item--link"><i class="fa fa-plus"></i> Add new action item</a>
</div>
<div class="list-group-item new-macro-settings">
<div class="helper"></div>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo
dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor
sit amet.</p>
<div class="row">
<div class="col-sm-12 flex-button-wrapper">
<button class="btn btn-primary btn-sm pull-right flex-button settings-save">Save</button>
<button class="btn btn-default btn-sm pull-right flex-button settings-cancel" style="margin-right: .5em;">Cancel</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- TODO move to component -->
<div class="notification" style="display: none">
<span class="notificatin__text">Keymap removed</span>
<a href="#" class="notification__action notification__action--undo">Undo</a>
<span class="notification__dismiss">&times;</span>
</div>
<script src="node_modules/jquery/dist/jquery.min.js"></script>
<script src="node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="node_modules/sortablejs/Sortable.js"></script>
<script src="node_modules/handlebars/dist/handlebars.js"></script>
<script src="node_modules/select2/dist/js/select2.min.js"></script>
<script src="app.js"></script>
<script src="macro.js"></script>
<script src="build/uhk.js"></script>
<main-app></main-app>
<script type="text/x-handlebars-template" id="sidebar-menu--source">
{{#if menu}}
<ul class="menu--top">
{{#each menu as |menuValue menuKey|}}
<li class="sidebar__level-1--item">
<div class="sidebar__level-1">
<i class='fa fa-{{icon}}'></i> {{name}}
<!--<span class="small-text">collapse</span>-->
{{#if expandable}}
<a href="#" class="btn btn-default pull-right btn-sm">
<i class="fa fa-plus"></i>
</a>
{{/if}}
<i class="fa fa-chevron-up pull-right" style=""></i>
</div>
{{#if children}}
<ul>
{{#each children}}
<li class="sidebar__level-2--item {{classes}}" data-name="{{name}}" data-content="{{menuValue.dataContent}}" data-abbrev="{{abbrev}}">
<div class="sidebar__level-2">
{{name}} {{#if menuValue.hasDefaults}} {{#if isDefault}}
<i class="fa fa-star pull-right"></i> {{/if}} {{/if}}
</div>
</li>
{{/each}}
</ul>
{{/if}}
</li>
{{/each}}
</ul>
{{/if}}
{{#if menuBottom}}
<ul class="menu--bottom">
{{#each menuBottom}}
<li class="sidebar__level-1--item">
<div class="sidebar__level-1"><i class='fa fa-{{icon}}'></i> {{name}}</div>
</li>
{{/each}}
</ul>
{{/if}}
</script>
<script src="node_modules/bootstrap/dist/js/bootstrap.min.js"></script> <!-- TODO remove in near future -->
<script src="node_modules/sortablejs/Sortable.js"></script>
<script src="node_modules/select2/dist/js/select2.min.js"></script>
<script src="app.js"></script> <!-- TODO move to typescript and components -->
<script src="build/uhk.js"></script>
</body>
</html>

79
keymapLegacy.html Normal file
View File

@@ -0,0 +1,79 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Ultimate Hacking Keyboard Configurator</title>
<link href="node_modules/font-awesome/css/font-awesome.min.css" rel="stylesheet">
<link href="node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="css/app.css" rel="stylesheet">
<link href="css/macro.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
<script src="node_modules/jquery/dist/jquery.min.js"></script>
<script>
// This js function is here to make sure it loads before any iframe content on the page.
function resizeIframe(ifr) {
ifr.style.height = (ifr.contentWindow.document.body.scrollHeight + 300) + 'px';
ifr.style.width = ifr.contentWindow.document.body.scrollWidth + 'px';
}
</script>
</head>
<body>
<!-- Google Tag Manager -->
<noscript>
<iframe src="//www.googletagmanager.com/ns.html?id=GTM-PQLCXB"
height="0" width="0" style="display:none;visibility:hidden"></iframe>
</noscript>
<script>
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-PQLCXB');
</script>
<div class="keymap--edit keymap--qwerty main-content__inner">
<div class="row">
<h1 class="col-xs-12 pane-title">
<i class="fa fa-keyboard-o"></i>
<span class="keymap__name pane-title__name" contenteditable="true">QWERTY</span> keymap (<span class="keymap__abbrev pane-title__abbrev" contenteditable="true">QTY</span>)
<i class="fa fa-star-o fa-star keymap__is-default"></i>
<i class="glyphicon glyphicon-trash keymap__remove pull-right" title="Remove keymap" data-toggle="tooltip" data-placement="left"></i>
</h1>
</div>
<div class="row">
</div>
<div class="row uhk--wrapper">
<div class="col-xs-12 text-center" style="margin-bottom: 2rem;">
<span class="uhk__layer-switcher--wrapper" role="" data-title="Layers: ">
<button type="button" data-layer="base" class="uhk__layer-switcher btn btn-primary btn-lg current">Base</button>
<button type="button" data-layer="mod" class="uhk__layer-switcher btn btn-default btn-lg">Mod</button>
<button type="button" data-layer="fn" class="uhk__layer-switcher btn btn-default btn-lg">Fn</button>
<button type="button" data-layer="mouse" class="uhk__layer-switcher btn btn-default btn-lg">Mouse</button>
</span>
</div>
<div class="col-xs-12">
<div class="keyboard-slider">
<div class="item uhk__layer-wrapper uhk__layer-wrapper--base current">
<img src="./images/base-layer.svg" class="uhk uhk--base-layer" alt="">
</div>
<div class="item uhk__layer-wrapper uhk__layer-wrapper--mod">
<img src="./images/base-layer--blank.svg" class="uhk uhk--mod-layer" alt="">
</div>
<div class="item uhk__layer-wrapper uhk__layer-wrapper--fn">
<img src="./images/base-layer--dvorak.svg" class="uhk uhk--fn-layer" alt="">
</div>
<div class="item uhk__layer-wrapper uhk__layer-wrapper--mouse">
<img src="./images/base-layer.svg" class="uhk uhk--mouse-layer" alt="">
</div>
</div>
<iframe src="popup__iframe.html" class="key-editor__popup" frameborder="0" scrolling="no" onload="resizeIframe(this)" style="display: none;"></iframe>
</div>
</div>
</div>
<script src="node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="node_modules/sortablejs/Sortable.js"></script>
<script src="node_modules/select2/dist/js/select2.min.js"></script>
<script src="app.js"></script>
</body>

View File

@@ -6,7 +6,7 @@ $(function() {
var newMacroHtml = $('.new-macro-settings');
// List with handle
Sortable.create(listWithHandle, {
Sortable.create(document.getElementById('listWithHandle'), {
handle: '.move-handle',
filter: '.no-reorder',
draggable: '.list-group-item',

97
macroLegacy.html Normal file
View File

@@ -0,0 +1,97 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Ultimate Hacking Keyboard Configurator</title>
<link href="node_modules/font-awesome/css/font-awesome.min.css" rel="stylesheet">
<link href="node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="css/app.css" rel="stylesheet">
<link href="css/macro.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
<script src="node_modules/jquery/dist/jquery.min.js"></script>
</head>
<body>
<div class="macro--edit main-content__inner">
<div class="row">
<h1 class="col-xs-12 pane-title">
<i class="fa fa-play"></i>
<span class="macro__name pane-title__name" contenteditable="true">Macro1</span> <i class="fa"></i>
</h1>
</div>
<div class="row">
<div id="listWithHandle" class="list-group col-xs-10 col-xs-offset-1">
<div class="list-group-item action--item">
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
<i class="fa fa-mouse-pointer"></i> Move pointer by 100px leftward
<i class="glyphicon glyphicon-pencil action--edit"></i>
<i class="glyphicon glyphicon-trash action--trash"></i>
</div>
<div class="list-group-item macro-settings" style="display: none;">
<div class="helper"></div>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo
dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor
sit amet.</p>
<div class="row">
<div class="col-sm-12 flex-button-wrapper">
<button class="btn btn-primary btn-sm pull-right flex-button settings-save">Save</button>
<button class="btn btn-default btn-sm pull-right flex-button settings-cancel" style="margin-right: .5em;">Cancel</button>
</div>
</div>
</div>
<div class="list-group-item action--item">
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
<i class="fa fa-square"></i> Press letter A
<i class="glyphicon glyphicon-pencil action--edit"></i>
<i class="glyphicon glyphicon-trash action--trash"></i>
</div>
<div class="list-group-item action--item">
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
<i class="fa fa-square"></i> Press Alt+Tab
<i class="glyphicon glyphicon-pencil action--edit"></i>
<i class="glyphicon glyphicon-trash action--trash"></i>
</div>
<div class="list-group-item action--item">
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
<i class="fa fa-clock-o"></i> Delay of 235ms
<i class="glyphicon glyphicon-pencil action--edit"></i>
<i class="glyphicon glyphicon-trash action--trash"></i>
</div>
<div class="list-group-item action--item">
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
<i class="fa fa-mouse-pointer"></i> Press button 1
<i class="glyphicon glyphicon-pencil action--edit"></i>
<i class="glyphicon glyphicon-trash action--trash"></i>
</div>
<div class="list-group-item action--item">
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
<i class="fa fa-mouse-pointer"></i> Scroll by 150px downward
<i class="glyphicon glyphicon-pencil action--edit"></i>
<i class="glyphicon glyphicon-trash action--trash"></i>
</div>
<div class="list-group-item action--item add-new__action-item no-reorder">
<a href="#" class="add-new__action-item--link"><i class="fa fa-plus"></i> Add new action item</a>
</div>
<div class="list-group-item new-macro-settings">
<div class="helper"></div>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo
dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor
sit amet.</p>
<div class="row">
<div class="col-sm-12 flex-button-wrapper">
<button class="btn btn-primary btn-sm pull-right flex-button settings-save">Save</button>
<button class="btn btn-default btn-sm pull-right flex-button settings-cancel" style="margin-right: .5em;">Cancel</button>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="node_modules/sortablejs/Sortable.js"></script>
<script src="node_modules/select2/dist/js/select2.min.js"></script>
<script src="macro.js"></script>
</body>
</html>

View File

@@ -13,6 +13,7 @@
"gulp-if": "^2.0.1",
"gulp-sass": "^2.3.2",
"gulp-sourcemaps": "^1.6.0",
"html-loader": "0.4.3",
"npm-run-all": "^2.3.0",
"raw-loader": "^0.5.1",
"sass-loader": "^4.0.0",
@@ -32,6 +33,7 @@
"@angular/core": "2.0.0-rc.4",
"@angular/platform-browser": "2.0.0-rc.4",
"@angular/platform-browser-dynamic": "2.0.0-rc.4",
"@angular/router": "3.0.0-beta.2",
"bootstrap": "^3.3.6",
"browser-stdout": "^1.3.0",
"es6-shim": "^0.35.1",
@@ -44,7 +46,7 @@
"rxjs": "5.0.0-beta.6",
"select2": "^4.0.3",
"sortablejs": "^1.4.2",
"typescript": "^1.8.10",
"typescript": "1.9.0-dev.20160626-1.0",
"xml-loader": "^1.1.0",
"zone.js": "^0.6.12"
},

View File

@@ -2,12 +2,16 @@ import { bootstrap } from '@angular/platform-browser-dynamic';
import { MainAppComponent } from './main-app.component';
import {DataProviderService} from './services/data-provider.service';
import {MapperService} from './services/mapper.service';
import { DataProviderService } from './services/data-provider.service';
import { MapperService } from './services/mapper.service';
import { APP_ROUTER_PROVIDERS } from './main-app.routes';
import { LocationStrategy, HashLocationStrategy } from '@angular/common';
process.stdout = require('browser-stdout')();
bootstrap(MainAppComponent, [
DataProviderService,
MapperService
MapperService,
APP_ROUTER_PROVIDERS,
{ provide: LocationStrategy, useClass: HashLocationStrategy }
]).catch(err => console.error(err));

View File

@@ -0,0 +1,37 @@
<template [ngIf]="keymap">
<div class="row">
<h1 class="col-xs-12 pane-title">
<i class="fa fa-keyboard-o"></i>
<span class="keymap__name pane-title__name" contenteditable="true">{{keymap.name}}</span> keymap
(<span class="keymap__abbrev pane-title__abbrev" contenteditable="true">{{keymap.abbreviation}}</span>)
<i class="fa fa-star-o fa-star keymap__is-default"></i>
<i class="glyphicon glyphicon-trash keymap__remove pull-right" title=""
data-toggle="tooltip" data-placement="left" data-original-title="Remove keymap"></i>
</h1>
</div>
<div class="row uhk--wrapper">
<div class="col-xs-12 text-center">
<span class="uhk__layer-switcher--wrapper" data-title="Layers: ">
<button #baseButton type="button" class="btn btn-default btn-lg btn-primary" (click)="selectLayer(0)">
Base
</button>
<button #modButton type="button" class="btn btn-default btn-lg" (click)="selectLayer(1)">
Mod
</button>
<button #fnButton type="button" class="btn btn-default btn-lg" (click)="selectLayer(2)">
Fn
</button>
<button #mouseButton type="button" class="btn btn-default btn-lg" (click)="selectLayer(3)">
Mouse
</button>
</span>
</div>
<div class="keyboard-slider" *ngIf="layers">
<svg-keyboard-popover *ngFor="let layer of layers.elements"
[moduleConfig]="layer.modules.elements"
(animationend)="onKeyboardAnimationEnd($event)"
hidden>
</svg-keyboard-popover>
</div>
</div>
</template>

View File

@@ -0,0 +1,57 @@
:host {
width: 100%;
height: 100%;
display: block;
}
.uhk--wrapper {
height: calc(100% - 95px);
}
button {
margin: 2px;
}
svg-keyboard-popover {
width: 95%;
max-width: 1400px;
position: absolute;
left: 50%;
transform: translateX(-50%);
animation-duration: 400ms;
animation-timing-function: ease-in-out;
}
.keyboard-slider {
height: calc(100% - 45px);
}
.uhk__layer-switcher--wrapper {
margin-bottom: 2rem;
}
@keyframes animate-center-left {
0% {
transform: translateX(-50%);
left: 50%;
}
100% {
transform: translateX(-100%);
left: 0;
}
}
@keyframes animate-center-right {
0% {
transform: translateX(-50%);
left: 50%;
}
100% {
transform: translateX(0%);
left: 100%;
}
}
[hidden] {
display: none;
}

View File

@@ -0,0 +1,138 @@
import { Component, ViewChildren, QueryList, ElementRef, OnInit, AfterViewInit, Renderer } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { SvgKeyboardPopoverComponent } from '../svg-keyboard-popover.component';
import { Layers } from '../../../config-serializer/config-items/Layers';
import { UhkConfigurationService } from '../../services/uhk-configuration.service';
import { Keymap } from '../../../config-serializer/config-items/Keymap';
import { Subscription } from 'rxjs/Subscription';
@Component({
selector: 'keymap',
template: require('./keymap.component.html'),
styles: [require('./keymap.component.scss')],
directives: [SvgKeyboardPopoverComponent],
providers: [UhkConfigurationService]
})
export class KeymapComponent implements OnInit, AfterViewInit {
@ViewChildren('baseButton,modButton,fnButton,mouseButton')
buttonsQueryList: QueryList<ElementRef>;
@ViewChildren(SvgKeyboardPopoverComponent, { read: ElementRef })
keyboardsQueryList: QueryList<ElementRef>;
private buttons: ElementRef[];
private keyboards: ElementRef[];
private selectedLayerIndex: number;
private keymapId: number = 0;
private layers: Layers;
private keymap: Keymap;
private numAnimationInProgress: number;
private subParams: Subscription;
private subQuery: Subscription;
constructor(
private renderer: Renderer,
private uhkConfigurationService: UhkConfigurationService,
private route: ActivatedRoute
) {
this.buttons = [];
this.keyboards = [];
this.selectedLayerIndex = 0;
this.numAnimationInProgress = 0;
}
ngOnInit() {
this.subParams = this.route.params.subscribe(params => {
let id: number = +params['id'];
if (!isNaN(id)) {
this.keymapId = id;
}
this.keymap = this.uhkConfigurationService.getUhkConfiguration().keymaps.elements[this.keymapId];
this.layers = this.keymap.layers;
});
}
ngAfterViewInit() {
this.buttons = this.buttonsQueryList.toArray();
this.afterView();
this.subQuery = this.keyboardsQueryList.changes.subscribe(() => {
this.afterView();
});
}
ngOnDestroy() {
this.subParams.unsubscribe();
this.subQuery.unsubscribe();
}
private afterView() {
this.keyboards = this.keyboardsQueryList.toArray();
this.renderer.setElementAttribute(this.keyboards[0].nativeElement, 'hidden', undefined);
this.renderer.setElementClass(this.buttons[this.selectedLayerIndex].nativeElement, 'btn-primary', false);
this.renderer.setElementClass(this.buttons[0].nativeElement, 'btn-primary', true);
this.selectedLayerIndex = 0;
}
/* tslint:disable:no-unused-variable */
/* selectLayer is used in the template string */
private selectLayer(index: number): void {
/* tslint:enable:no-unused-variable */
if (this.selectedLayerIndex === index || index > this.keyboards.length - 1 || this.numAnimationInProgress > 0) {
return;
}
this.renderer.setElementClass(this.buttons[this.selectedLayerIndex].nativeElement, 'btn-primary', false);
this.renderer.setElementClass(this.buttons[index].nativeElement, 'btn-primary', true);
if (index > this.selectedLayerIndex) {
this.renderer.setElementStyle(
this.keyboards[this.selectedLayerIndex].nativeElement,
'animation-name',
'animate-center-left'
);
this.renderer.setElementStyle(
this.keyboards[index].nativeElement,
'animation-name',
'animate-center-right'
);
this.renderer.setElementStyle(this.keyboards[index].nativeElement, 'animation-direction', 'reverse');
} else {
this.renderer.setElementStyle(
this.keyboards[this.selectedLayerIndex].nativeElement,
'animation-name',
'animate-center-right'
);
this.renderer.setElementStyle(this.keyboards[index].nativeElement, 'animation-name', 'animate-center-left');
this.renderer.setElementStyle(this.keyboards[index].nativeElement, 'animation-direction', 'reverse');
}
this.numAnimationInProgress += 2;
this.renderer.setElementAttribute(this.keyboards[index].nativeElement, 'hidden', undefined);
this.selectedLayerIndex = index;
}
/* tslint:disable:no-unused-variable */
/* onKeyboardAnimationEnd is used in the template string */
private onKeyboardAnimationEnd(event: AnimationEvent) {
/* tslint:enable:no-unused-variable */
let animationNameTokens: string[] = event.animationName.split('-');
let animationFrom: string = animationNameTokens[1];
let animationTo: string = animationNameTokens[2];
if ((<HTMLElement> event.target).style.animationDirection === 'reverse') {
animationFrom = animationNameTokens[2];
animationTo = animationNameTokens[1];
this.renderer.setElementStyle(event.target, 'animation-direction', undefined);
}
--this.numAnimationInProgress;
this.renderer.setElementStyle(event.target, 'animation-name', undefined);
this.renderer.setElementAttribute(event.target, 'hidden', (animationTo === 'center') ? undefined : '');
}
}

View File

@@ -0,0 +1,18 @@
import { RouterConfig } from '@angular/router';
import { KeymapComponent } from './keymap.component';
export const keymapRoutes: RouterConfig = [
{
path: '',
redirectTo: '/keymap',
pathMatch: 'full'
},
{
path: 'keymap',
component: KeymapComponent
},
{
path: 'keymap/:id',
component: KeymapComponent
}
];

View File

@@ -0,0 +1,9 @@
:host {
height: 100%;
width: 100%;
}
iframe {
height: 100vh;
width: 100%;
}

View File

@@ -0,0 +1,26 @@
import { Component } from '@angular/core';
import { DomSanitizationService, SafeResourceUrl } from '@angular/platform-browser';
import {ActivatedRoute} from '@angular/router';
@Component({
selector: 'legacy',
template:
`
<iframe [src]="safeLink" frameborder="0" scrolling="no"></iframe>
`,
styles: [require('./legacy-loader.component.scss')]
})
export class LegacyLoaderComponent {
private safeLink: SafeResourceUrl;
constructor(private sanitationService: DomSanitizationService, private route: ActivatedRoute) {
}
ngOnInit() {
this.route.params.subscribe(params => {
if (params['id']) {
this.safeLink = this.sanitationService.bypassSecurityTrustResourceUrl(params['id'] + 'Legacy.html');
}
});
}
}

View File

@@ -0,0 +1,9 @@
import { RouterConfig } from '@angular/router';
import {LegacyLoaderComponent} from './legacy-loader.component';
export const legacyRoutes: RouterConfig = [
{
path: 'legacy/:id',
component: LegacyLoaderComponent
}
];

View File

@@ -0,0 +1 @@
Macro

View File

@@ -0,0 +1,12 @@
import { Component } from '@angular/core';
@Component({
selector: 'macro',
template: require('./macro.component.html'),
styles: [require('./macro.component.scss')]
})
export class MacroComponent {
constructor() {
}
}

View File

@@ -0,0 +1,13 @@
import { RouterConfig } from '@angular/router';
import { MacroComponent } from './macro.component';
export const macroRoutes: RouterConfig = [
{
path: 'macro',
component: MacroComponent
},
{
path: 'macro/:id',
component: MacroComponent
}
];

View File

@@ -0,0 +1,87 @@
<ul class="menu--top">
<li class="sidebar__level-1--item">
<div class="sidebar__level-1">
<i class="fa fa-keyboard-o"></i> Keymaps
<a href="#" class="btn btn-default pull-right btn-sm">
<i class="fa fa-plus"></i>
</a>
<i class="fa fa-chevron-up pull-right" (click)="toggleHide($event, keymapElement)"></i>
</div>
<ul #keymapElement>
<li *ngFor="let keymap of keymaps" class="sidebar__level-2--item">
<div class="sidebar__level-2">
<a [routerLink]="['/keymap', keymap.id]">{{keymap.name}}</a>
<i class="fa fa-star pull-right"></i>
</div>
</li>
</ul>
</li>
<li class="sidebar__level-1--item">
<div class="sidebar__level-1">
<i class="fa fa-play"></i> Macros
<a href="#" class="btn btn-default pull-right btn-sm">
<i class="fa fa-plus"></i>
</a>
<i class="fa fa-chevron-up pull-right" (click)="toggleHide($event, macroElement)"></i>
</div>
<ul #macroElement>
<li *ngFor="let macro of macros" class="sidebar__level-2--item">
<div class="sidebar__level-2">
<a [routerLink]="['/macro', macro.id]">{{macro.name}}</a>
<i class="fa fa-star pull-right"></i>
</div>
</li>
</ul>
</li>
<li class="sidebar__level-1--item">
<div class="sidebar__level-1">
<i class="fa fa-puzzle-piece"></i> Add-on modules
<i class="fa fa-chevron-up pull-right" (click)="toggleHide($event, addonElement)"></i>
</div>
<ul #addonElement>
<li class="sidebar__level-2--item" data-name="Key cluster" data-abbrev="">
<div class="sidebar__level-2">
Key cluster
</div>
</li>
<li class="sidebar__level-2--item" data-name="Trackball" data-abbrev="">
<div class="sidebar__level-2">
Trackball
</div>
</li>
<li class="sidebar__level-2--item" data-name="Toucpad" data-abbrev="">
<div class="sidebar__level-2">
Toucpad
</div>
</li>
<li class="sidebar__level-2--item" data-name="Trackpoint" data-abbrev="">
<div class="sidebar__level-2">
Trackpoint
</div>
</li>
</ul>
</li>
<li class="sidebar__level-1--item">
<div class="sidebar__level-1">
<i class="fa fa-exclamation-triangle "></i> Legacy
<i class="fa fa-chevron-up pull-right" (click)="toggleHide($event, legacyElement)"></i>
</div>
<ul #legacyElement>
<li class="sidebar__level-2--item" data-name="Keymap legacy" data-abbrev="QTY">
<div class="sidebar__level-2">
<a [routerLink]="['/legacy', 'keymap']">Keymap HTML</a>
</div>
</li>
<li class="sidebar__level-2--item " data-name="Macro legacy" data-abbrev="DVR">
<div class="sidebar__level-2">
<a [routerLink]="['/legacy', 'macro']">Macro</a>
</div>
</li>
</ul>
</li>
</ul>
<ul class="menu--bottom">
<li class="sidebar__level-1--item">
<div class="sidebar__level-1"><i class="fa fa-gear"></i> Settings</div>
</li>
</ul>

View File

@@ -0,0 +1,23 @@
:host {
background-color: #f5f5f5;
border-right: 1px solid #ccc;
position: fixed;
overflow-y: auto;
width: 250px;
height: 100%;
}
a {
color: #333;
}
ul ul {
max-height: 200px;
transition: max-height 0.5s ease-in;
overflow: hidden;
}
ul ul.slide-up {
max-height: 0;
transition: max-height 0.5s ease-out;
}

View File

@@ -0,0 +1,34 @@
import { Component, OnInit } from '@angular/core';
import { Keymap } from '../../../config-serializer/config-items/Keymap';
import { UhkConfigurationService } from '../../services/uhk-configuration.service';
import { Macro } from '../../../config-serializer/config-items/Macro';
import { ROUTER_DIRECTIVES } from '@angular/router';
@Component({
selector: 'side-menu',
template: require('./side-menu.component.html'),
styles: [require('./side-menu.component.scss')],
providers: [UhkConfigurationService],
directives: [ROUTER_DIRECTIVES]
})
export class SideMenuComponent implements OnInit {
private keymaps: Keymap[];
private macros: Macro[];
constructor(private uhkConfigurationService: UhkConfigurationService) {
}
ngOnInit() {
this.keymaps = this.uhkConfigurationService.getUhkConfiguration().keymaps.elements;
this.macros = this.uhkConfigurationService.getUhkConfiguration().macros.elements;
}
private toggleHide(event: Event, view: Element) {
let header: DOMTokenList = (<Element> event.target).classList;
view.classList.toggle('slide-up');
header.toggle('fa-chevron-up');
header.toggle('fa-chevron-down');
}
}

View File

@@ -0,0 +1,4 @@
<side-menu></side-menu>
<div id="main-content" class="split split-horizontal container-fluid main-content">
<router-outlet></router-outlet>
</div>

View File

@@ -1,58 +1,10 @@
:host {
display: flex;
flex-direction: column;
display: block;
height: 100vh;
width: 100%;
overflow: hidden;
> div:first-child {
display: flex;
flex: 1;
align-items: center;
justify-content: center;
}
}
button {
margin: 2px;
.main-content {
height: 100%;
}
:host > div:last-child {
display: flex;
flex: 5;
position: relative;
}
:host > div:last-child > svg-keyboard-popover {
width: 80%;
position: absolute;
left: 50%;
transform: translateX(-50%);
animation-duration: 400ms;
animation-timing-function: ease-in-out;
}
@keyframes animate-center-left {
0% {
transform: translateX(-50%);
left: 50%;
}
100% {
transform: translateX(-100%);
left: 0%;
}
}
@keyframes animate-center-right {
0% {
transform: translateX(-50%);
left: 50%;
}
100% {
transform: translateX(0%);
left: 100%;
}
}
[hidden] {
display: none;
}

View File

@@ -1,131 +1,16 @@
import { Component, OnInit, AfterViewInit, Renderer, ViewChildren, QueryList, ElementRef} from '@angular/core';
import { Component } from '@angular/core';
import { ROUTER_DIRECTIVES } from '@angular/router';
import {Layers} from '../config-serializer/config-items/Layers';
import {SvgKeyboardPopoverComponent} from './components/svg-keyboard-popover.component';
import {UhkConfigurationService} from './services/uhk-configuration.service';
import { SideMenuComponent } from './components/sidemenu/side-menu.component';
@Component({
moduleId: module.id,
selector: 'main-app',
template:
` <div>
<button #baseButton type="button" class="btn btn-default btn-lg btn-primary" (click)="selectLayer(0)">
Base
</button>
<button #modButton type="button" class="btn btn-default btn-lg" (click)="selectLayer(1)">
Mod
</button>
<button #fnButton type="button" class="btn btn-default btn-lg" (click)="selectLayer(2)">
Fn
</button>
<button #mouseButton type="button" class="btn btn-default btn-lg" (click)="selectLayer(3)">
Mouse
</button>
</div>
<div>
<svg-keyboard-popover *ngFor="let layer of layers.elements"
[moduleConfig]="layer.modules.elements"
(animationend)="onKeyboardAnimationEnd($event)"
hidden>
</svg-keyboard-popover>
</div>
`,
template: require('./main-app.component.html'),
styles: [require('./main-app.component.scss')],
directives: [SvgKeyboardPopoverComponent],
providers: [UhkConfigurationService]
directives: [SideMenuComponent, ROUTER_DIRECTIVES]
})
export class MainAppComponent implements OnInit, AfterViewInit {
@ViewChildren('baseButton,modButton,fnButton,mouseButton')
buttonsQueryList: QueryList<ElementRef>;
@ViewChildren(SvgKeyboardPopoverComponent, { read: ElementRef })
keyboardsQueryList: QueryList<ElementRef>;
private buttons: ElementRef[];
private keyboards: ElementRef[];
private selectedLayerIndex: number;
private layers: Layers;
private numAnimationInProgress: number;
constructor(
private renderer: Renderer,
private uhkConfigurationService: UhkConfigurationService
) {
this.buttons = [];
this.keyboards = [];
this.selectedLayerIndex = -1;
this.numAnimationInProgress = 0;
export class MainAppComponent {
constructor() {
}
ngOnInit() {
this.layers = this.uhkConfigurationService.getUhkConfiguration().keymaps.elements[0].layers;
}
ngAfterViewInit() {
this.buttons = this.buttonsQueryList.toArray();
this.keyboards = this.keyboardsQueryList.toArray();
this.selectedLayerIndex = 0;
this.renderer.setElementAttribute(this.keyboards[0].nativeElement, 'hidden', undefined);
}
/* tslint:disable:no-unused-variable */
/* selectLayer is used in the template string */
private selectLayer(index: number): void {
/* tslint:enable:no-unused-variable */
if (this.selectedLayerIndex === index || index > this.keyboards.length - 1 || this.numAnimationInProgress > 0) {
return;
}
this.renderer.setElementClass(this.buttons[this.selectedLayerIndex].nativeElement, 'btn-primary', false);
this.renderer.setElementClass(this.buttons[index].nativeElement, 'btn-primary', true);
if (index > this.selectedLayerIndex) {
this.renderer.setElementStyle(
this.keyboards[this.selectedLayerIndex].nativeElement,
'animation-name',
'animate-center-left'
);
this.renderer.setElementStyle(
this.keyboards[index].nativeElement,
'animation-name',
'animate-center-right'
);
this.renderer.setElementStyle(this.keyboards[index].nativeElement, 'animation-direction', 'reverse');
} else {
this.renderer.setElementStyle(
this.keyboards[this.selectedLayerIndex].nativeElement,
'animation-name',
'animate-center-right'
);
this.renderer.setElementStyle(this.keyboards[index].nativeElement, 'animation-name', 'animate-center-left');
this.renderer.setElementStyle(this.keyboards[index].nativeElement, 'animation-direction', 'reverse');
}
this.numAnimationInProgress += 2;
this.renderer.setElementAttribute(this.keyboards[index].nativeElement, 'hidden', undefined);
this.selectedLayerIndex = index;
}
/* tslint:disable:no-unused-variable */
/* onKeyboardAnimationEnd is used in the template string */
private onKeyboardAnimationEnd(event: AnimationEvent) {
/* tslint:enable:no-unused-variable */
let animationNameTokens: string[] = event.animationName.split('-');
let animationFrom: string = animationNameTokens[1];
let animationTo: string = animationNameTokens[2];
if ((<HTMLElement> event.target).style.animationDirection === 'reverse') {
animationFrom = animationNameTokens[2];
animationTo = animationNameTokens[1];
this.renderer.setElementStyle(event.target, 'animation-direction', undefined);
}
--this.numAnimationInProgress;
this.renderer.setElementStyle(event.target, 'animation-name', undefined);
this.renderer.setElementAttribute(event.target, 'hidden', (animationTo === 'center') ? undefined : '');
}
}

14
src/main-app.routes.ts Normal file
View File

@@ -0,0 +1,14 @@
import { provideRouter, RouterConfig } from '@angular/router';
import { keymapRoutes } from './components/keymap/keymap.routes';
import { macroRoutes } from './components/macro/macro.routes';
import {legacyRoutes} from './components/legacy/legacy-loader.routes';
export const routes: RouterConfig = [
...keymapRoutes,
...macroRoutes,
...legacyRoutes
];
export const APP_ROUTER_PROVIDERS = [
provideRouter(routes)
];

View File

@@ -21,6 +21,7 @@ module.exports = {
module: {
loaders: [
{ test: /\.ts$/, loader: 'ts-loader', exclude: /node_modules/ },
{ test: /\.html$/, loader: 'html-loader' },
{
test: /\.scss$/,
exclude: /node_modules/,