mirror of
https://github.com/ijprest/keyboard-layout-editor
synced 2024-11-13 07:10:41 +00:00
1379 lines
75 KiB
HTML
1379 lines
75 KiB
HTML
<!--***********************************************
|
|
KEYBOARD LAYOUT EDITOR
|
|
Copyright (C) 2013-2015 Ian Prest
|
|
All rights reserved.
|
|
************************************************-->
|
|
<!DOCTYPE html>
|
|
<html ng-app="kbApp">
|
|
<head>
|
|
<title>Keyboard Layout Editor</title>
|
|
<meta charset="utf-8">
|
|
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css" media="screen">
|
|
<link rel="stylesheet" type="text/css" href="css/font-awesome.min.css">
|
|
<link rel="stylesheet" type="text/css" href="css/hint.min.css">
|
|
<link rel="stylesheet" type="text/css" href="css/colorpicker.min.css">
|
|
<link rel="stylesheet" type="text/css" href="css/kb.css">
|
|
<link rel="stylesheet" type="text/css" href="css/kbd-webfont.css">
|
|
<script type="text/javascript" src="js/jquery.min.js"></script>
|
|
<script type="text/javascript" src="js/ace.js"></script>
|
|
<script type="text/javascript" src="js/angular.min.js"></script>
|
|
<script type="text/javascript" src="js/angular-sanitize.min.js"></script>
|
|
<script type="text/javascript" src="js/angular-cookies.min.js"></script>
|
|
<script type="text/javascript" src="js/ui-ace.min.js"></script>
|
|
<script type="text/javascript" src="js/ui-utils.min.js"></script>
|
|
<script type="text/javascript" src="js/ui-bootstrap-tpls-0.12.0.min.js"></script>
|
|
<script type="text/javascript" src="js/crypto-js.js"></script>
|
|
<script type="text/javascript" src="js/marked.min.js"></script>
|
|
<script type="text/javascript" src="js/FileSaver.min.js"></script>
|
|
<script type="text/javascript" src="js/ng-file-upload.min.js"></script>
|
|
<script type="text/javascript" src="js/draganddrop.js"></script>
|
|
<script type="text/javascript" src="js/bootstrap-colorpicker-module.min.js"></script>
|
|
<script type="text/javascript" src="js/doT.min.js"></script>
|
|
<script type="text/javascript" src="js/urlon.js"></script>
|
|
<script type="text/javascript" src="js/cssparser.min.js"></script><script type="text/javascript">$cssParser = parser;</script>
|
|
<script type="text/javascript" src="js/color.js"></script>
|
|
<script type="text/javascript" src="js/jsonl.min.js"></script><script type="text/javascript">jsonl = parser;</script>
|
|
<script type="text/javascript" src="js/html2canvas.min.js"></script>
|
|
<script type="text/javascript" src="extensions.js"></script>
|
|
<script type="text/javascript" src="render.js"></script>
|
|
<script type="text/javascript" src="serial.js"></script>
|
|
<script type="text/javascript" src="kb.js"></script>
|
|
</head>
|
|
<body ng-controller="kbCtrl"
|
|
ng-mouseup="selectRelease($event)"
|
|
ng-mousemove="selectMove($event)"
|
|
ui-keydown="{'shift-191' : 'showHelp($event)',
|
|
112 : 'showHelp($event)',
|
|
118 : 'showOptions($event)',
|
|
'ctrl-83' : 'save($event)' }">
|
|
<style type="text/css" ng-bind-html="customStyles"></style>
|
|
<div id='body_all'><!-- this wrapper is to allow the magic that prints just the summary -->
|
|
<div id="wrap">
|
|
<!--***********************************************
|
|
Nav Bar / Header
|
|
************************************************-->
|
|
<nav class="navbar navbar-inverse navbar-static-top" role="navigation">
|
|
<div class="navbar-header">
|
|
<!-- Hamburger menu, when width is too small -->
|
|
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
|
|
<span class="sr-only">Toggle navigation</span>
|
|
<span class="icon-bar"></span>
|
|
<span class="icon-bar"></span>
|
|
<span class="icon-bar"></span>
|
|
</button>
|
|
|
|
<!-- Main branding icon/title -->
|
|
<a class="navbar-brand" href="#"><i class="fa fa-keyboard-o"></i> keyboard-layout-editor.com</a>
|
|
</div>
|
|
<div class="collapse navbar-collapse navbar-ex1-collapse">
|
|
|
|
<!-- Left-aligned NavBar buttons -->
|
|
<ul class="nav navbar-nav">
|
|
<!-- Presets dropdown -->
|
|
<li class="dropdown" dropdown>
|
|
<a class="dropdown-toggle" dropdown-toggle><i class="fa fa-keyboard-o"></i> Preset <b class="caret"></b></a>
|
|
<ul class="dropdown-menu">
|
|
<li class="dropdown-header">Standard Layouts:</li>
|
|
<li ng-repeat="v in layouts"><a ng-click="loadPreset(v.data)" href="#">{{v.name}}</a></li>
|
|
<li class="divider"></li>
|
|
<li class="dropdown-header">Complex Samples:</li>
|
|
<li ng-repeat="(k,v) in samples"><a ng-click="loadSample(v)" href="#">{{k}}</a></li>
|
|
</ul>
|
|
</li>
|
|
|
|
<!-- Color swatches dropdown -->
|
|
<li class="dropdown" dropdown>
|
|
<a class="dropdown-toggle" dropdown-toggle><i class="fa fa-th"></i> Color Swatches <b class="caret"></b></a>
|
|
<ul class="dropdown-menu">
|
|
<li ng-repeat="pal in palettes"><a ng-click="loadPalette(pal)" href="#">{{pal.name}}</a></li>
|
|
<li class="divider"></li>
|
|
<li><a ng-click="makePaletteFromKeys()" href="#">Current key colors</a></li>
|
|
</ul>
|
|
</li>
|
|
|
|
<!-- Character Picker dropdown -->
|
|
<li class="dropdown" dropdown>
|
|
<a class="dropdown-toggle" dropdown-toggle><i class="fa fa-font"></i> Character Picker <b class="caret"></b></a>
|
|
<ul class="dropdown-menu">
|
|
<li ng-repeat="picker in pickers"><a ng-click="loadCharacterPicker(picker)" href="#">{{picker.name}}</a></li>
|
|
<li class="divider"></li>
|
|
<li><a ng-click="loadCharacterPicker(null)" href="#">User-Defined Glyphs</a></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
|
|
<!-- Right-aligned NavBar buttons -->
|
|
<ul class="nav navbar-nav navbar-right" style="">
|
|
<!-- Options button -->
|
|
<li><a href="#" ng-click="showOptions()"><i class="fa fa-cog"></i> Options</a></li>
|
|
<!-- Tools button -->
|
|
<li><a href="#" ng-click="showTools()"><i class="fa fa-wrench"></i> Tools</a></li>
|
|
<!-- Permalink button -->
|
|
<li><a ng-href="{{getPermalink()}}" target="_blank" ng-click="dirty = false"><i class="fa fa-link"></i> Permalink</a></li>
|
|
<!-- User button -->
|
|
<li ng-hide="user"><a href="#" ng-click="userLogin()"><i class="fa fa-github"></i> Sign in with GitHub</a></li>
|
|
<li ng-hide="!user" class="dropdown" dropdown ng-cloak>
|
|
<a class="dropdown-toggle" dropdown-toggle><span ng-bind-html="user.avatar"></span> {{user.name}} <b class="caret"></b></a>
|
|
<ul class="dropdown-menu">
|
|
<li><a ng-click="showSavedLayouts(false)" href="#"><i class="fa fa-folder-open-o"></i> My Layouts</a></li>
|
|
<li><a ng-click="showSavedLayouts(true)" href="#"><i class="fa fa-star-o"></i> Starred Layouts</a></li>
|
|
<li class="divider"></li>
|
|
<li><a href="https://github.com/settings/connections/applications/{{githubClientId}}" target="_blank"><i class="fa fa-key"></i> Manage GitHub Permissions</a></li>
|
|
<li><a ng-click="userLogout()" href="#"><i class="fa fa-sign-out"></i> Log out</a></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</nav>
|
|
|
|
<div class="body" ng-cloak>
|
|
|
|
<!--***********************************************
|
|
Main Toolbar
|
|
************************************************-->
|
|
<!-- Add Key button w/dropdown -->
|
|
<div class="btn-group" dropdown>
|
|
<button type="button" class="btn btn-primary" ng-click="addKey()"><i class="fa fa-plus-circle"></i> Add Key</button>
|
|
<button type="button" class="btn btn-primary dropdown-toggle" dropdown-toggle>
|
|
<span class="caret"></span>
|
|
</button>
|
|
<ul class="dropdown-menu" role="menu">
|
|
<li><a ng-click="addKeys(1)">Add 1 Key</a></li>
|
|
<li><a ng-click="addKeys(5)">Add 5 Keys</a></li>
|
|
<li><a ng-click="addKeys(10)">Add 10 Keys</a></li>
|
|
<li><a ng-click="addKeys(25)">Add 25 Keys</a></li>
|
|
<li class="divider" ng-class="{hidden: !specialKeys}"></li>
|
|
<li ng-repeat="(k,v) in specialKeys"><a ng-click="addKey(v)">{{k}}</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- Delete Key button -->
|
|
<div class="btn-group">
|
|
<button type="button" class="btn btn-danger" ng-class="{disabled:selectedKeys.length<1}" ng-click="deleteKeys()">
|
|
<i class="fa fa-minus-circle"></i> Delete Keys
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Undo/Redo button group -->
|
|
<div class="btn-group">
|
|
<button type="button" class="btn btn-default" ng-class="{disabled:!canUndo()}" ng-click="undo()"><i class="fa fa-undo"></i> Undo</button>
|
|
<button type="button" class="btn btn-default" ng-class="{disabled:!canRedo()}" ng-click="redo()"><i class="fa fa-repeat"></i> Redo</button>
|
|
</div>
|
|
|
|
<!-- Clipboard button group -->
|
|
<div class="btn-group">
|
|
<button type="button" class="btn btn-default" ng-class="{disabled:!canCopy()}" ng-click="cut()"><i class="fa fa-cut"></i> Cut</button>
|
|
<button type="button" class="btn btn-default" ng-class="{disabled:!canCopy()}" ng-click="copy()"><i class="fa fa-copy"></i> Copy</button>
|
|
<button type="button" class="btn btn-default" ng-class="{disabled:!canPaste()}" ng-click="paste()"><i class="fa fa-paste"></i> Paste</button>
|
|
</div>
|
|
<div class="btn-group" ng-hide="!user || !user.id || !currentGist || isStarred">
|
|
<button type="button" class="btn btn-default" ng-click="setGistStar(currentGist, true)" ><i class="fa fa-star-o"></i> Star</button>
|
|
</div>
|
|
<div class="btn-group" ng-hide="!user || !user.id || !currentGist || !isStarred">
|
|
<button type="button" class="btn btn-default" ng-click="setGistStar(currentGist, false)" ><i class="fa fa-star"></i> Unstar</button>
|
|
</div>
|
|
<!-- Save button (right aligned) -->
|
|
<div class="btn-group pull-right" ng-hide="user && user.id">
|
|
<button type="button" class="btn btn-success hint--bottom hint--no-animate disabled" data-hint="Sign in to save your layouts.">
|
|
<i class="fa fa-save"></i> Save
|
|
</button>
|
|
</div>
|
|
<div class="btn-group pull-right" ng-hide="!user || !user.id">
|
|
<button type="button" class="btn btn-success" ng-class="{disabled:!canSave()}" ng-click="save()">
|
|
<i class="fa fa-save"></i> Save
|
|
</button>
|
|
</div>
|
|
<div class="btn-group pull-right" style="margin-right: 4px;" dropdown>
|
|
<button type="button" class="btn btn-success dropdown-toggle" dropdown-toggle><i class="fa fa-download"></i> Download <span class="caret"></span></button>
|
|
<ul class="dropdown-menu" role="menu">
|
|
<li><a ng-click="downloadSvg()">Download SVG (Experimental)</a></li>
|
|
<li><a ng-click="downloadPng()">Download PNG (Experimental)</a></li>
|
|
<li><a ng-click="downloadJpg()">Download JPG (Experimental)</a></li>
|
|
<li><a ng-click="downloadThumb()">Download Thumbnail (PNG) (Experimental)</a></li>
|
|
<li class="divider"></li>
|
|
<li><a ng-click="downloadJson()">Download JSON</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
|
|
<!--***********************************************
|
|
Main Keyboard Preview/Editor area
|
|
************************************************-->
|
|
<div id="keyboard" ng-cloak tabindex="0"
|
|
ui-keydown="{ left:'moveKeys(-moveStep,0,$event)',
|
|
right:'moveKeys(moveStep,0,$event)',
|
|
up:'moveKeys(0,-moveStep,$event)',
|
|
down:'moveKeys(0,moveStep,$event)',
|
|
'shift-left':'sizeKeys(-sizeStep,0,$event)',
|
|
'shift-right':'sizeKeys(sizeStep,0,$event)',
|
|
'shift-up':'sizeKeys(0,-sizeStep,$event)',
|
|
'shift-down':'sizeKeys(0,sizeStep,$event)',
|
|
'pageup':'rotateKeys(-rotateStep,$event)',
|
|
'pagedown':'rotateKeys(rotateStep,$event)',
|
|
'ctrl-left':'moveCenterKeys(-moveStep,0,$event)',
|
|
'ctrl-right':'moveCenterKeys(moveStep,0,$event)',
|
|
'ctrl-up':'moveCenterKeys(0,-moveStep,$event)',
|
|
'ctrl-down':'moveCenterKeys(0,moveStep,$event)',
|
|
delete:'deleteKeys()',
|
|
insert:'addKey()',
|
|
74: 'prevKey($event)',
|
|
75: 'nextKey($event)',
|
|
'shift-74': 'prevKey($event)',
|
|
'shift-75': 'nextKey($event)',
|
|
113: 'focusEditor()',
|
|
esc: 'unselectAll()',
|
|
'ctrl-65': 'selectAll($event)',
|
|
'ctrl-67 ctrl-45': 'copy($event)',
|
|
'ctrl-88 shift-46': 'cut($event)',
|
|
'ctrl-86 shift-45': 'paste($event)',
|
|
'ctrl-90' : 'undo()',
|
|
'ctrl-shift-90' : 'redo()',
|
|
'ctrl-89' : 'redo()' }"
|
|
ng-mousedown="selectClick($event)"
|
|
ngf-drop="true" ngf-change="uploadJson($files, $event)" ngf-drag-over-class="drag-over">
|
|
|
|
<div id='keyboard-bg'
|
|
ng-attr-style="height:{{kbHeight}}px; width:{{kbWidth}}px; background-color:{{keyboard.meta.backcolor}}; border-radius: {{keyboard.meta.radii || '6px'}}; {{keyboard.meta.background.style}}">
|
|
<div ng-repeat="key in keys()"
|
|
class="key {{key.profile}}"
|
|
ng-mouseover="hoveredKey=key"
|
|
ng-mouseleave="hoveredKey=null"
|
|
ng-class="{hover: hoveredKey==key, selected: selectedKeys.indexOf(key)>=0, HOMING:key.nub}"
|
|
ng-bind-html="key.html">
|
|
</div>
|
|
</div>
|
|
|
|
<div style="line-height:1.2em; padding:3px 5px;" ng-hide="!keyboard.meta.name && !keyboard.meta.author">
|
|
<a href="#" ng-click="previewNotes()">{{keyboard.meta.name}}<br/><i>{{keyboard.meta.author}}</i></a>
|
|
</div>
|
|
<div style='clear:both'></div>
|
|
{{calcKbHeight()}}
|
|
</div>
|
|
<div id="selectionRectangle" ng-style="{display:selRect.display, left:selRect.l+'px', width:selRect.w+'px', top:selRect.t+'px', height:selRect.h+'px'}"></div>
|
|
<div id="rotationCrosshairs" ng-style="{display:multi.crosshairs, left:(keyboardLeft()+multi.crosshairs_x-1)+'px', top:(keyboardTop()+multi.crosshairs_y-3)+'px'}"><i class="fa fa-crosshairs"></i></div>
|
|
|
|
|
|
<!--***********************************************
|
|
Editor controls
|
|
************************************************-->
|
|
|
|
<!-- Tab strip -->
|
|
<ul class="nav nav-tabs" ng-cloak>
|
|
<li ng-class="{active:selTab==0}"><a ng-click="selTab=0" data-toggle="tab"><i class="fa fa-edit"></i> Properties</a></li>
|
|
<li ng-class="{active:selTab==1}"><a ng-click="selTab=1" data-toggle="tab"><i class="fa fa-keyboard-o"></i> Keyboard Properties</a></li>
|
|
<li ng-class="{active:selTab==3}"><a ng-click="selTab=3" data-toggle="tab"><i class="fa fa-file-text-o"></i> Custom Styles</a></li>
|
|
<li ng-class="{active:selTab==2}"><a ng-click="selTab=2" data-toggle="tab"><i class="fa fa-code"></i> Raw data</a></li>
|
|
<li ng-class="{active:selTab==4}"><a ng-click="selTab=4" data-toggle="tab"><i class="fa fa-file-text-o"></i> Summary</a></li>
|
|
</ul>
|
|
<div id="tab-content" class='col-md-12 col-lg-12 row' ui-keydown="{esc:'focusKb()'}" ng-cloak>
|
|
|
|
<!-- PROPERTIES EDITOR -->
|
|
<div id="properties" ng-class="{hidden:selTab!=0}">
|
|
<form class="form-horizontal col-sm-8 col-md-5 col-lg-5">
|
|
|
|
<!-- Top Legend -->
|
|
<div class="form-group form-group-sm">
|
|
<label class="control-label col-md-3 col-lg-3 text-nowrap" for="labeleditor0">Top Legend:</label>
|
|
<div class="col-md-9 col-lg-9">
|
|
<div class="form-inline">
|
|
<kbd-label-editor label-index="0" hint-text="Specify a top-left legend for the keycap."></kbd-label-editor>
|
|
<kbd-label-editor label-index="1" hint-text="Specify a top-center legend for the keycap."></kbd-label-editor>
|
|
<kbd-label-editor label-index="2" hint-text="Specify a top-right legend for the keycap."></kbd-label-editor>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Center Legend -->
|
|
<div class="form-group form-group-sm">
|
|
<label class="control-label col-md-3 col-lg-3 text-nowrap" for="labeleditor3">Center Legend:</label>
|
|
<div class="col-md-9 col-lg-9">
|
|
<div class="form-inline">
|
|
<kbd-label-editor label-index="3" hint-text="Specify a center-left legend for the keycap."></kbd-label-editor>
|
|
<kbd-label-editor label-index="4" hint-text="Specify a center legend for the keycap."></kbd-label-editor>
|
|
<kbd-label-editor label-index="5" hint-text="Specify a center-right legend for the keycap."></kbd-label-editor>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Bottom Legend -->
|
|
<div class="form-group form-group-sm">
|
|
<label class="control-label col-md-3 col-lg-3 text-nowrap" for="labeleditor6">Bottom Legend:</label>
|
|
<div class="col-md-9 col-lg-9">
|
|
<div class="form-inline">
|
|
<kbd-label-editor label-index="6" hint-text="Specify a bottom-left legend for the keycap."></kbd-label-editor>
|
|
<kbd-label-editor label-index="7" hint-text="Specify a bottom-center legend for the keycap."></kbd-label-editor>
|
|
<kbd-label-editor label-index="8" hint-text="Specify a bottom-right legend for the keycap."></kbd-label-editor>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Side-Print Legend -->
|
|
<div class="form-group form-group-sm">
|
|
<label class="control-label col-md-3 col-lg-3 text-nowrap" for="labeleditor9">Front Legend:</label>
|
|
<div class="col-md-9 col-lg-9">
|
|
<div class="form-inline">
|
|
<kbd-label-editor label-index="9" hint-text="Specify a front-left legend for the keycap."></kbd-label-editor>
|
|
<kbd-label-editor label-index="10" hint-text="Specify a front-center legend for the keycap."></kbd-label-editor>
|
|
<kbd-label-editor label-index="11" hint-text="Specify a front-right legend for the keycap."></kbd-label-editor>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Legend Size -->
|
|
<div class="form-group form-group-sm">
|
|
<label class="control-label col-md-3 col-lg-3 text-nowrap" for="textSize-editor">Legend Size:</label>
|
|
<div class="col-md-9 col-lg-9">
|
|
<div class="form-inline hint--top hint--rounded"
|
|
data-hint="Specify the size for the keycap legends. Setting this value will change the size of all legends, and will replace any existing size overrides.">
|
|
<div class="form-group form-group-sm">
|
|
<input id="textSize-editor" class="form-control input-sm" style="max-width:64px" size="6" type='number' min="1" max="9"
|
|
ng-model="multi.default.textSize"
|
|
ng-change="updateMulti('textSize',-1)"
|
|
ng-blur="validateMulti('textSize',-1)"
|
|
ng-disabled="selectedKeys.length<1">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Legend Color -->
|
|
<div class="form-group form-group-sm">
|
|
<label class="control-label col-md-3 col-lg-3 text-nowrap" for="textcoloreditor">Legend Color:</label>
|
|
<div class="col-md-9 col-lg-9">
|
|
<div class="form-inline">
|
|
<kbd-color-picker picker-id="textcoloreditor" picker-position="top"
|
|
ng-model="multi.default.textColor"
|
|
ng-change="updateMulti('textColor',-1)"
|
|
ng-blur="validateMulti('textColor',-1)"
|
|
ng-disabled="selectedKeys.length<1"
|
|
hint-text="Specify the color to use for the legend text on the selected keycaps. Setting this value will change the color of all legends, and will replace any existing color overrides."
|
|
ui-on-Drop="dropSwatch($data,$event,true,-1)" drop-channel="dragColor"></kbd-color-picker>
|
|
<div class="form-group form-group-sm color-name">{{colorName(multi.default.textColor)}}</div>
|
|
</div>
|
|
|
|
<!-- Swap Colors Button -->
|
|
<div>
|
|
<div id="swap-colors"
|
|
class="hint--top hint--rounded"
|
|
data-hint="Swap the text and keycap colors.">
|
|
<button class="btn btn-default"
|
|
ng-click="swapColors()"
|
|
ng-disabled="selectedKeys.length<1 || multi.decal" >
|
|
<i class="fa fa-random"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Key Color -->
|
|
<div class="form-group form-group-sm">
|
|
<label class="control-label col-md-3 col-lg-3 text-nowrap" for="coloreditor">Key Color:</label>
|
|
<div class="col-md-9 col-lg-9">
|
|
<div class="form-inline">
|
|
<kbd-color-picker picker-id="coloreditor" picker-position="top"
|
|
ng-model="multi.color"
|
|
ng-change="updateMulti('color')"
|
|
ng-blur="validateMulti('color')"
|
|
ng-disabled="selectedKeys.length<1 || multi.decal"
|
|
hint-text="Specify the color to use for the background of the selected keycaps."
|
|
ui-on-Drop="dropSwatch($data,$event,false)" drop-channel="dragColor"></kbd-color-picker>
|
|
<div class="form-group form-group-sm color-name">{{colorName(multi.color)}}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Width -->
|
|
<div class="form-group form-group-sm">
|
|
<label class="control-label col-md-3 col-lg-3 text-nowrap" for="width-editor">Width:</label>
|
|
<div class="col-md-9 col-lg-9">
|
|
<div class="form-inline hint--top hint--rounded"
|
|
data-hint="Specify the primary and secondary widths for the keycap. The secondary width is used to specify the size of non-rectangular or stepped keys.">
|
|
<kbd-multi-numbox field="width" size="6" min="0.5" max="18" step='{{sizeStep}}'></kbd-multi-numbox>
|
|
<div class="form-group form-group-sm"> / </div>
|
|
<kbd-multi-numbox field="width2" size="6" min="0.5" max="18" step='{{sizeStep}}' kbd-disable="multi.decal"></kbd-multi-numbox>
|
|
</div>
|
|
|
|
<!-- Swap Sizes Button -->
|
|
<div>
|
|
<div id="swap-sizes"
|
|
class="hint--top hint--rounded"
|
|
data-hint="Swap the primary & secondary sizes (affects legend positioning on oddly shaped keys).">
|
|
<button class="btn btn-default"
|
|
ng-click="swapSizes()"
|
|
ng-disabled="selectedKeys.length<1 || (multi.width == multi.width2 && multi.height == multi.height2) || multi.decal" >
|
|
<i class="fa fa-random"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Height -->
|
|
<div class="form-group form-group-sm">
|
|
<label class="control-label col-md-3 col-lg-3 text-nowrap" for="height-editor">Height:</label>
|
|
<div class="col-md-9 col-lg-9">
|
|
<div class="form-inline hint--top hint--rounded"
|
|
data-hint="Specify the primary and secondary heights for the keycap. The secondary height is used to specify the size of non-rectangular or stepped keys.">
|
|
<kbd-multi-numbox field="height" size="6" min="0.5" max="18" step='{{sizeStep}}'></kbd-multi-numbox>
|
|
<div class="form-group form-group-sm"> / </div>
|
|
<kbd-multi-numbox field="height2" size="6" min="0.5" max="18" step='{{sizeStep}}' kbd-disable="multi.decal"></kbd-multi-numbox>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- X -->
|
|
<div class="form-group form-group-sm">
|
|
<label class="control-label col-md-3 col-lg-3 text-nowrap" for="x-editor">X:</label>
|
|
<div class="col-md-9 col-lg-9">
|
|
<div class="form-inline hint--top hint--rounded"
|
|
data-hint="Specify the X position of the keycap. An X-offset can also be specified to indicate how non-rectangular keys should be displayed.">
|
|
<kbd-multi-numbox field="x" size="6" min="0" max="36" step='{{moveStep}}'></kbd-multi-numbox>
|
|
<div class="form-group form-group-sm"> + </div>
|
|
<kbd-multi-numbox field="x2" size="6" min="-6" max="6" step='{{moveStep}}' kbd-disable="multi.decal"></kbd-multi-numbox>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Y -->
|
|
<div class="form-group form-group-sm">
|
|
<label class="control-label col-md-3 col-lg-3 text-nowrap" for="y-editor">Y:</label>
|
|
<div class="col-md-9 col-lg-9">
|
|
<div class="form-inline hint--top hint--rounded"
|
|
data-hint="Specify the Y position of the keycap. A Y-offset can also be specified to indicate how non-rectangular keys should be displayed.">
|
|
<kbd-multi-numbox field="y" size="6" min="0" max="36" step='{{moveStep}}'></kbd-multi-numbox>
|
|
<div class="form-group form-group-sm"> + </div>
|
|
<kbd-multi-numbox field="y2" size="6" min="-6" max="6" step='{{moveStep}}' kbd-disable="multi.decal"></kbd-multi-numbox>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Rotation -->
|
|
<div class="form-group form-group-sm">
|
|
<label class="control-label col-md-3 col-lg-3 text-nowrap" for="rotation_angle-editor">Rotation:</label>
|
|
<div class="col-md-9 col-lg-9">
|
|
<div class="form-inline hint--top hint--rounded"
|
|
data-hint="Specify the angle (in degrees) by which to rotate the keycaps, and the x & y coordinates of the center of rotation.">
|
|
<kbd-multi-numbox field="rotation_angle" size="3" min="-180" max="180" step='{{rotateStep}}'></kbd-multi-numbox>
|
|
<div class="form-group form-group-sm"> ° </div>
|
|
<kbd-multi-numbox field="rotation_x" size="6" min="0" max="36" step='{{moveStep}}'></kbd-multi-numbox>
|
|
<div class="form-group form-group-sm"> , </div>
|
|
<kbd-multi-numbox field="rotation_y" size="6" min="0" max="36" step='{{moveStep}}'></kbd-multi-numbox>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Profile / Row -->
|
|
<div class="form-group form-group-sm">
|
|
<label class="control-label col-md-3 col-lg-3 text-nowrap" for="profileeditor-search">Profile / Row:</label>
|
|
<div class="col-md-9 col-lg-9">
|
|
<div class="form-inline hint--top hint--rounded"
|
|
data-hint="Specify the profile and (optionally) the row-number of the selected keys, e.g., 'DCS R1', 'DSA', 'DSA SPACE', etc.">
|
|
<div class="form-group form-group-sm">
|
|
<input id="profileeditor-search" class="form-control input-sm" size="24" type='text' autocomplete="off"
|
|
ng-model="multi.profile"
|
|
ng-change="updateMulti('profile')"
|
|
ng-blur="validateMulti('profile')"
|
|
ng-disabled="selectedKeys.length<1 || multi.decal">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Keyswitch options-->
|
|
<div class="form-group form-group-sm">
|
|
<label class="control-label col-md-3 col-lg-3 text-nowrap" for="switcheditor">Switch:</label>
|
|
<div class="form-inline form-outdent col-md-9 col-lg-9">
|
|
|
|
<!-- Keyswitch mount style-->
|
|
<div class="hint--bottom hint--rounded" data-hint="Specify the mount style of switch for this key.">
|
|
<div class="btn-group btn-group-sm-form dropup" dropdown>
|
|
<button id="switcheditor" type="button" class="btn btn-default dropdown-toggle dropdown-fixedwidth" ng-disabled="selectedKeys.length<1 || multi.decal" dropdown-toggle>
|
|
<div>{{(multi.sm || meta.switchMount) ? switches[multi.sm || meta.switchMount].name : 'Mount N/A'}}</div>
|
|
<b class="caret"></b>
|
|
</button>
|
|
<ul class="dropdown-menu dropdown-select" role="menu">
|
|
<li ng-repeat="(k,v) in switches"><a ng-click="setMulti('sm',k)">{{v.name + (meta.switchMount===k ? ' (default)' : '')}}</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Keyswitch brand-->
|
|
<div class="hint--bottom hint--rounded" data-hint="Specify the brand of key switch for this key.">
|
|
<div class="btn-group btn-group-sm-form dropup" dropdown>
|
|
<button type="button" class="btn btn-default dropdown-toggle dropdown-fixedwidth" dropdown-toggle ng-disabled="selectedKeys.length<1 || !(multi.sm || meta.switchMount) || multi.decal">
|
|
<div>{{(multi.sb || meta.switchBrand) ? switches[multi.sm || meta.switchMount].brands[multi.sb || meta.switchBrand].name : 'Brand N/A'}}</div>
|
|
<b class="caret"></b>
|
|
</button>
|
|
<ul class="dropdown-menu dropdown-select" role="menu">
|
|
<li ng-repeat="(k,v) in switches[multi.sm || meta.switchMount].brands"><a ng-click="setMulti('sb',k)">{{v.name + (meta.switchBrand===k ? ' (default)' : '')}}</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Keyswitch type-->
|
|
<div class="hint--bottom hint--rounded" data-hint="Specify the type of key switch for this key.">
|
|
<div class="btn-group btn-group-sm-form dropup" dropdown>
|
|
<button type="button" class="btn btn-default dropdown-toggle dropdown-fixedwidth" dropdown-toggle ng-disabled="selectedKeys.length<1 || !(multi.sm || meta.switchMount) || !(multi.sb || meta.switchBrand) || multi.decal">
|
|
<div>{{(multi.st || meta.switchType) ? switches[multi.sm || meta.switchMount].brands[multi.sb || meta.switchBrand].switches[multi.st || meta.switchType].name : 'Switch N/A'}}</div>
|
|
<b class="caret"></b>
|
|
</button>
|
|
<ul class="dropdown-menu dropdown-select" role="menu">
|
|
<li ng-repeat="(k,v) in switches[multi.sm || meta.switchMount].brands[multi.sb || meta.switchBrand].switches"><a ng-click="setMulti('st',k)">{{v.name + (v.feel ? ', '+v.feel : '') + (v.weight ? ', '+v.weight.toString()+' cN' : '') + (meta.switchType===k ? ' (default)' : '')}}</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Misc -->
|
|
<div class="form-group form-group-sm">
|
|
<label class="control-label col-md-3 col-lg-3 text-nowrap">Misc:</label>
|
|
<div class="col-md-9 col-lg-9">
|
|
<div class="form-inline">
|
|
<kbd-multi-check field="ghost" kbd-disable="multi.decal" hint-text="Specify whether the selected keys should be rendered slightly transparently; this is useful to draw attention to the other, non-ghosted keycaps.">Ghosted</kbd-multi-check>
|
|
<kbd-multi-check field="stepped" kbd-disable="multi.decal" hint-text="Specify whether the selected keys are 'stepped', i.e., part of the key is at a lower height than the rest. The secondary 'width' indicates the width of the stepped part.">Stepped</kbd-multi-check>
|
|
<kbd-multi-check field="nub" kbd-disable="multi.decal" hint-text="Specifies that the selected keys are 'homing' keys, which help the user find the home-row by touch alone.">Homing</kbd-multi-check>
|
|
<kbd-multi-check field="decal" hint-text="Specifies that the selected keys are to be treated as 'decals', i.e., purely decorative additions to the layout.">Decal</kbd-multi-check>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</form>
|
|
|
|
<!-- Color Palette -->
|
|
<div class="col-md-4 col-lg-4" ng-class="{hidden:!palette.name}">
|
|
{{palette.name}} <a ng-href='{{palette.href}}' data-hint="{{palette.description}}" class="hint--top hint--rounded" target="_blank">(more info)</a>
|
|
<ul id="swatches" ng-class="{disabled:selectedKeys.length<1}">
|
|
<li ng-repeat="color in palette.colors"
|
|
ng-style="{'background-color':color.css}"
|
|
ng-click="clickSwatch(color,$event)"
|
|
class="swatch"
|
|
ng-class="{'selected-bg': color.css === multi.color, 'selected-fg': color.css === multi.default.textColor}"
|
|
tooltip="{{color.name}}"
|
|
ui-draggable="true" drag-channel="dragColor" drag="color">
|
|
<div class='highlight fg'></div>
|
|
<div class='highlight bg'></div>
|
|
</li>
|
|
</ul>
|
|
<alert type="warning" style="margin-top:10px;" ng-hide="paletteAlertHidden" close="paletteAlertHidden = true">
|
|
<i class="fa fa-info-circle"></i> Click on a swatch to set the color of the selected key(s), or Ctrl+Click to set the text color. You can also drag color swatches to individual legends to set different colors for each one.
|
|
</alert>
|
|
</div>
|
|
|
|
<!-- Character Picker -->
|
|
<div class="col-md-6 col-lg-6" ng-class="{hidden:!picker.name}">
|
|
{{picker.name}} <a ng-if='picker.href' ng-href='{{picker.href}}' data-hint="{{picker.description}}" class="hint--top hint--rounded" target="_blank">(more info)</a>
|
|
<div class="col-md-12 col-lg-12" style="padding:4px 0px;">
|
|
<input id="picker-filter" class="form-control input-sm" type='text' ng-model="pickerFilter" placeholder="Filter"
|
|
ng-change="pickerSelection = {}">
|
|
</div>
|
|
<div id="glyphScroller">
|
|
<ul id="glyphs" ng-class="{disabled:selectedKeys.length<1}">
|
|
<li ng-repeat="glyph in picker.glyphs | filter:pickerFilter"
|
|
class="glyph"
|
|
tooltip="{{glyph.name}}"
|
|
ng-click="pickerSelect(glyph)"
|
|
ng-bind-html="glyph.html"
|
|
ng-class="{selected:pickerSelection===glyph}"
|
|
ui-draggable="true" drag-channel="dragGlyph" drag="glyph">
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="col-md-12 col-lg-12" style="padding:4px 0px;">
|
|
<input id="picker-html" class="form-control input-sm" type='text'
|
|
ng-model="pickerSelection.html" placeholder="No glyph selected"
|
|
onClick="this.select();" readonly>
|
|
</div>
|
|
<alert type="warning" style="margin-top:40px;" ng-hide="pickerAlertHidden" close="pickerAlertHidden = true">
|
|
<i class="fa fa-info-circle"></i> Click on a glyph to see the HTML code for that glyph. You can also drag glyphs to the legend edit-boxes to assign them to the legend.
|
|
</alert>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- KEYBOARD PROPERTIES EDITOR -->
|
|
<div id="kbdproperties" ng-class="{hidden:selTab!=1}">
|
|
<form class="form-horizontal col-sm-12 col-md-12 col-lg-12">
|
|
|
|
<!-- Keyboard Background -->
|
|
<div class="form-group form-group-sm">
|
|
<label class="control-label col-md-2 col-lg-1 text-nowrap" for="kbdcoloreditor">Case Background:</label>
|
|
<div class="col-md-10 col-lg-11">
|
|
<div class="form-inline">
|
|
<!-- Color -->
|
|
<kbd-color-picker picker-id="kbdcoloreditor"
|
|
ng-model="meta.backcolor"
|
|
ng-change="updateMeta('backcolor')"
|
|
ng-blur="validateMeta('backcolor')"
|
|
hint-text="Specify the background color for the keyboard."></kbd-color-picker>
|
|
|
|
<!-- Background image-->
|
|
<div class="form-group form-group-sm">
|
|
<div class="input-group input-group-sm hint--top hint--rounded" data-hint="Specify the background texture for the keyboard.">
|
|
<div class="btn-group btn-group-sm-form" dropdown>
|
|
<button type="button" class="btn btn-default dropdown-toggle" dropdown-toggle>{{meta.background ? meta.background.name : 'No Texture'}} <b class="caret"></b></button>
|
|
<ul class="dropdown-menu dropdown-select" role="menu">
|
|
<li><a ng-click='setBackground()'>None</a></li>
|
|
<li class="divider"></li>
|
|
<li ng-repeat="category in backgrounds">
|
|
<div class="dropdown-header" ng-attr-style="{{category.style}}">{{category.category}}:</div>
|
|
<ul class="menu">
|
|
<li ng-repeat="bg in category.content"><a ng-click='setBackground(bg)'>{{bg.name}}</a></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Corner radii -->
|
|
<div class="form-group form-group-sm">
|
|
<label class="control-label text-nowrap" style='margin-left: 5px;' for="kbdradiieditor">Radii:</label>
|
|
|
|
<div class="hint--top hint--rounded"
|
|
data-hint="Specify the corner radii for this keyboard, in CSS3 format.
|
|
|
|
Some examples:
|
|
• 20px /*all corners rounded equally*/
|
|
• 10px 10px 10px 10px /*ditto, but less rounding*/
|
|
• 10px 10px 10px 10px / 20px 20px 20px 20px
|
|
• 40% / 20px
|
|
• 30px 30px / 40%">
|
|
<input id="kbdradiieditor" class="form-control input-sm" type='text'
|
|
ng-model="meta.radii"
|
|
ng-change="updateMeta('radii')"
|
|
ng-blur="validateMeta('radii')">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Keyboard Name -->
|
|
<div class="form-group form-group-sm">
|
|
<label class="control-label col-md-2 col-lg-1 text-nowrap" for="kbdnameeditor">Keyboard Name:</label>
|
|
<div class="col-md-10 col-lg-11 form-outdent hint--top hint--rounded"
|
|
data-hint="Specify the name of this keyboard layout.">
|
|
<input id="kbdnameeditor" class="form-control input-sm" type='text'
|
|
ng-model="meta.name"
|
|
ng-change="updateMeta('name')"
|
|
ng-blur="validateMeta('name')">
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Author -->
|
|
<div class="form-group form-group-sm">
|
|
<label class="control-label col-md-2 col-lg-1 text-nowrap" for="authoreditor">Author:</label>
|
|
<div class="col-md-10 col-lg-11 form-outdent hint--top hint--rounded"
|
|
data-hint="Specify the author of this keyboard layout.">
|
|
<input id="authoreditor" class="form-control input-sm" type='text'
|
|
ng-model="meta.author"
|
|
ng-change="updateMeta('author')"
|
|
ng-blur="validateMeta('author')">
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Default keyswitch options-->
|
|
<div class="form-group form-group-sm">
|
|
<label class="control-label col-md-2 col-lg-1 text-nowrap" for="defaultswitcheditor">Default switch:</label>
|
|
|
|
<!-- Default keyswitch mount style-->
|
|
<div class="form-inline form-outdent col-md-10 col-lg-11">
|
|
<div class="hint--top hint--rounded" data-hint="Specify the default mount style of switch for this keyboard layout.">
|
|
<select id="defaultswitcheditor" class="form-control input-sm dropdown"
|
|
ng-model="meta.switchMount"
|
|
ng-change="updateMeta('switchMount')"
|
|
ng-blur="validateMeta('switchMount')">
|
|
<option value="">Mount Style Not Specified</option>
|
|
<option ng-repeat="(k,v) in switches" value="{{k}}" ng-selected="meta.switchMount == k">{{v.name}}</option>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- Default keyswitch brand-->
|
|
<div class="hint--top hint--rounded"
|
|
data-hint="Specify the default brand of key switch for this keyboard layout.">
|
|
<select class="form-control input-sm dropdown"
|
|
ng-model="meta.switchBrand"
|
|
ng-change="updateMeta('switchBrand')"
|
|
ng-blur="validateMeta('switchBrand')"
|
|
ng-disabled="!meta.switchMount">
|
|
<option value="">Brand Not Specified</option>
|
|
<option ng-repeat="(k,v) in switches[meta.switchMount].brands" value="{{k}}" ng-selected="meta.switchBrand == k">{{v.name}}</option>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- Default keyswitch type-->
|
|
<div class=" hint--top hint--rounded"
|
|
data-hint="Specify the default type of key switch for this keyboard layout.">
|
|
<select class="form-control input-sm dropdown"
|
|
ng-model="meta.switchType"
|
|
ng-change="updateMeta('switchType')"
|
|
ng-blur="validateMeta('switchType')"
|
|
ng-disabled="!meta.switchMount || !meta.switchBrand">
|
|
<option value="">Switch Type Not Specified</option>
|
|
<option ng-repeat="v in switches[meta.switchMount].brands[meta.switchBrand].switches" value="{{v.part}}" ng-selected="meta.switchType == v.part">{{v.name + (v.feel ? ', '+v.feel : '') + (v.weight ? ', '+v.weight.toString()+' cN' : '')}}</option>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- Switch mounting -->
|
|
<div class="form-group form-group-sm form-horizontal">
|
|
<label class="control-label text-nowrap" style='margin-left: 5px;' for="pcb">Mounted on:</label>
|
|
<div class="checkbox hint--top hint--rounded" data-hint="Specify if the switches are PCB mounted.">
|
|
<label style='margin-bottom: -3px;'>
|
|
<input type="checkbox" id="pcb" class="checkbox"
|
|
ng-model="meta.pcb"
|
|
ng-change="updateMeta('pcb')"
|
|
ng-blur="validateMeta('pcb')">
|
|
PCB
|
|
</label>
|
|
</div>
|
|
<div class="checkbox hint--top hint--rounded" data-hint="Specify if the switches are plate mounted.">
|
|
<label style='margin-bottom: -3px;'>
|
|
<input type="checkbox" id="plate" class="checkbox"
|
|
ng-model="meta.plate"
|
|
ng-change="updateMeta('plate')"
|
|
ng-blur="validateMeta('plate')">
|
|
Plate
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<!-- Notes -->
|
|
<div class="form-group form-group-sm">
|
|
<label class="control-label col-md-2 col-lg-1 text-nowrap" for="noteseditor">Notes:</label>
|
|
<div class="col-md-10 col-lg-11 form-outdent">
|
|
<div class="hint--top hint--rounded" style="width:100%"
|
|
data-hint="Specify any additional notes about this keyboard layout, e.g., links to manufacturers, colors used, additional credits, etc. GitHub-Flavored Markdown is supported for rich formatting.">
|
|
<div id="noteseditor" class="form-control"
|
|
ui-ace="{mode:'markdown',theme:'textmate',onLoad:aceLoaded,useWrapMode:true,rendererOptions:{animatedScroll:true,showPrintMargin:false}}"
|
|
ng-model="meta.notes"
|
|
ng-change="updateMeta('notes')"
|
|
ng-blur="validateMeta('notes')"></div>
|
|
</div>
|
|
<div class="text-right">
|
|
<div class="btn-group btn-group-xs" role="group">
|
|
<button type="button" class="btn btn-success" ng-click="previewNotes()"><i class="fa fa-eye"></i> Preview</button>
|
|
</div>
|
|
<div class="btn-group btn-group-xs" role="group">
|
|
<a class="btn btn-primary" href="https://help.github.com/articles/markdown-basics/" target='_blank'><i class="fa fa-question-circle"></i> Markdown Syntax</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- CUSTOM STYLES EDITOR -->
|
|
<div id="tab-customstyles" ng-class="{hidden:selTab!=3}">
|
|
<div ngf-drop="true" ngf-change="uploadJson($files, $event)" ngf-drag-over-class="drag-over">
|
|
<div id="customstyles"
|
|
ui-ace="{mode:'css',theme:'textmate',onLoad:aceLoaded,useWrapMode:true,rendererOptions:{animatedScroll:true,showPrintMargin:false}}"
|
|
ng-model="meta.css"
|
|
ng-change="updateCustomStyles()"
|
|
ng-class="{error:customStylesException!==''}"></div>
|
|
</div>
|
|
<div style='text-align:right;margin-top:4px;'>
|
|
<div class="btn-group btn-group-xs" role="group">
|
|
<a class="btn btn-primary" href="https://github.com/ijprest/keyboard-layout-editor/wiki/Custom-Styles" target='_blank'><i class="fa fa-question-circle"></i> Custom Styles Syntax</a>
|
|
</div>
|
|
</div>
|
|
<div id="customstyles-error" class="alert alert-danger" style='margin-top:1em;margin-bottom:0px' ng-class="{hidden:!customStylesException}">{{customStylesException}}</div>
|
|
</div>
|
|
|
|
<!-- RAW DATA EDITOR -->
|
|
<div id="tab-rawdata" ng-class="{hidden:selTab!=2}">
|
|
<div ngf-drop="true" ngf-change="uploadJson($files, $event)" ngf-drag-over-class="drag-over">
|
|
<div id="rawdata"
|
|
ui-ace="{mode:'json',theme:'textmate',onLoad:aceLoaded,useWrapMode:true,rendererOptions:{animatedScroll:true,showPrintMargin:false}}"
|
|
ng-model="serialized"
|
|
ng-change="updateFromSerialized()"
|
|
ng-class="{error:deserializeException!==''}"></div>
|
|
</div>
|
|
<div style='text-align:right;margin-top:4px;'>
|
|
<div class="btn-group btn-group-xs" role="group">
|
|
<button type="button" class="btn btn-success" ng-click="downloadJson()"><i class="fa fa-download"></i> Download JSON</button>
|
|
<button ngf-select="true" class="btn btn-success" ngf-change="uploadJson($files, $event)"><i class="fa fa-upload"></i> Upload JSON</button>
|
|
</div>
|
|
<div class="btn-group btn-group-xs" role="group">
|
|
<a class="btn btn-primary" href="https://github.com/ijprest/keyboard-layout-editor/wiki/Serialized-Data-Format" target='_blank'><i class="fa fa-question-circle"></i> Raw Data Syntax</a>
|
|
</div>
|
|
</div>
|
|
<div id="rawdata-error" class="alert alert-danger" style='margin-top:1em;margin-bottom:0px' ng-class="{hidden:!deserializeException}">{{deserializeException}}</div>
|
|
</div>
|
|
|
|
<!-- SUMMARY -->
|
|
<div id="summary" ng-class="{hidden:selTab!=4}">
|
|
<div class="col-md-12 col-lg-12 row">
|
|
<div id='printSummary'>
|
|
<div>Title: {{meta.name}}</div>
|
|
<div>Author: {{meta.author}}</div>
|
|
<table class='summarytable'>
|
|
<tr><th class='summarytable' colspan='3'>Key sizes summary</th></tr>
|
|
<tr ng-repeat="(k,v) in keyCount()" class='summarytable'>
|
|
<td>{{k}}</td>
|
|
<td><span class="fa fa-square" ng-style="{'color':getTextColor(k)}"> </span></td>
|
|
<td align='right'>{{v}}</td>
|
|
</tr>
|
|
</table>
|
|
<table class='summarytable'>
|
|
<tr><th colspan='3'>Switches summary</th></tr>
|
|
<tr ng-repeat="(k,v) in switchCount()"><td>{{k}}</td><td>{{switchNames[k]}}</td><td>{{v}}</td></tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="btn-group btn-group-xs" role="group">
|
|
<br><button type="button" class="btn btn-success" ng-click="printDiv('printSummary')"><i class="fa fa-print"></i> Print summary</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-12 col-lg-12 row" style="margin-top:1em;margin-left:0px;">
|
|
<alert type="success" ng-hide="!saved" close="saved=false" ng-cloak>
|
|
Saved! Your saved layout can be accessed via <a class="alert-link" ng-href="#/gists/{{saved}}">this link</a>.
|
|
</alert>
|
|
<alert type="danger" ng-hide="!saveError" close="saveError=''" ng-cloak>
|
|
<P>There was an error saving your layout on the server: {{saveError}}</P>
|
|
<P>To ensure you don't lose any data, it is recommended that you <a class="alert-link" ng-click="downloadJson()">download your layout as JSON</a>.</P>
|
|
</alert>
|
|
<alert type="danger" ng-hide="!loadError" close="loadError=false" ng-cloak>
|
|
The requested layout does not exist.
|
|
</alert>
|
|
<alert type="danger" ng-hide="!oauthError" close="oauthError=null" ng-cloak>
|
|
An error occurred during login: {{oauthError}}
|
|
</alert>
|
|
</div>
|
|
|
|
</div>
|
|
</div> <!-- body -->
|
|
</div> <!-- wrap -->
|
|
|
|
<!--***********************************************
|
|
Footer
|
|
************************************************-->
|
|
<div id="footer" ng-cloak>
|
|
<div class="container">
|
|
<p class="text-muted credit" style="float:left">
|
|
Keyboard Layout Editor v{{version}} (<a href='#' ng-click="showMarkdown('CHANGELOG.md', $event)">changelog</a>)<br/>
|
|
Copyright © 2013-2015 — Ian Prest (<a href='#' ng-click="showMarkdown('CONTRIB.md', $event)">and contributors</a>)<br/>
|
|
All rights reserved. (<a href='#' ng-click="showMarkdown('LICENSE.md', $event)">LICENSE</a>)
|
|
</p>
|
|
<div style="float:right;">
|
|
<a href="#" ng-click="showHelp($event)"><i class="fa fa-question-circle"></i> Help & keyboard shortcuts</a><br/>
|
|
<a href="https://github.com/ijprest/keyboard-layout-editor/issues" target="_blank"><i class="fa fa-bug"></i> Found a bug?</a><br/>
|
|
<a href="https://github.com/ijprest/keyboard-layout-editor" target="_blank"><i class="fa fa-github"></i> Code hosted on GitHub</a><br/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!--***********************************************
|
|
Help Dialog
|
|
************************************************-->
|
|
<script type="text/ng-template" id="helpDialog.html">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" ng-click="cancel()">×</button>
|
|
<h4 class="modal-title">How to use keyboard-layout-editor.com</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<h5>Getting Started:</h5>
|
|
<ul>
|
|
<li>Try loading one of the preset layouts from the dropdown at the top of the page.</li>
|
|
<ul>
|
|
<li>The <em>standard layouts</em> are intended to be used as a starting point for customization.</li>
|
|
<li>The <em>complex samples</em> are intended to give you an idea of the editor's capabilities, and to show off some awesome user-creations!</li>
|
|
</ul>
|
|
<li>Select a key in the editor by clicking on it; then try changing the various properties in the property-editor form.</li>
|
|
<li>You can select multiple keys by holding down CTRL and clicking on them, or extend the current selection by SHIFT-clicking on an item. You can also drag a marquee rectangle around the keys you want to select.</li>
|
|
<li>Try the keyboard shortcuts (described below); they make editing various properties much quicker.</li>
|
|
<li>You can save your layout to the server by clicking the 'Save' button on the toolbar.</li>
|
|
<li>You can save your layout locally by bookmarking the 'Permalink' (at the top of the page) in your bookmarks list.</li>
|
|
</ul>
|
|
|
|
<h5>Global Keyboard Shortcuts:</h5>
|
|
<dl class='dl-horizontal'>
|
|
<dt><kbd>F1</kbd> / <kbd>?</kbd></dt><dd>Show this help dialog</dd>
|
|
<dt><kbd>F7</kbd></dt><dd>Show the Options dialog</dd>
|
|
<dt><kbd>Ctrl–S</kbd></dt><dd>Save your layout (on the server)</dd>
|
|
</dl>
|
|
|
|
<h5>Editor Keyboard Shortcuts (these require that the editor has input focus):</h5>
|
|
<dl class='dl-horizontal' style='float:left;width:50%;'>
|
|
<dt><kbd>↑↓←→</kbd></dt><dd>Move the selected keys</dd>
|
|
<dt><kbd>Shift–↑↓←→</kbd></dt><dd>Resize the selected keys</dd>
|
|
<dt><kbd>Ctrl–↑↓←→</kbd></dt><dd>Move the center of rotation for the selected keys</dd>
|
|
<dt><kbd>PgUp</kbd> / <kbd>PgDn</kbd></dt><dd>Change the angle of rotation for the selected keys</dd>
|
|
<dt><kbd>Ins</kbd></dt><dd>Add a new key</dd>
|
|
<dt><kbd>Del</kbd></dt><dd>Delete the selected keys</dd>
|
|
<dt><kbd>F2</kbd></dt><dd>Edit the text of the selected key</dd>
|
|
</dl>
|
|
<dl class='dl-horizontal' style='float:left;width:50%;'>
|
|
<dt><kbd>Ctrl–A</kbd> / <kbd>Esc</kbd></dt><dd>Select / deselect all keys</dd>
|
|
<dt><kbd>J</kbd> / <kbd>K</kbd></dt><dd>Select the previous / next key in the editor.</dd>
|
|
<dt><kbd>Ctrl–Z</kbd></dt><dd>Undo</dd>
|
|
<dt><kbd>Ctrl–Shift–Z</kbd> or <kbd>Ctrl–Y</kbd></dt><dd>Redo</dd>
|
|
<dt><kbd>Ctrl–X</kbd> or <kbd>Shift–Del</kbd></dt><dd>Cut the selected keys</dd>
|
|
<dt><kbd>Ctrl–C</kbd> or <kbd>Ctrl–Ins</kbd></dt><dd>Copy the selected keys</dd>
|
|
<dt><kbd>Ctrl–V</kbd> or <kbd>Shift–Ins</kbd></dt><dd>Paste keys from the clipboard</dd>
|
|
</dl>
|
|
<p> </p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-primary" ng-click="ok()">OK</button>
|
|
</div>
|
|
</script>
|
|
|
|
<!--***********************************************
|
|
Markdown dialog for displaying README, etc.
|
|
************************************************-->
|
|
<script type="text/ng-template" id="markdownDialog.html">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" ng-click="cancel()">×</button>
|
|
<h4 class="modal-title">{{$parent.markdownTitle}}</h4>
|
|
</div>
|
|
<div class="modal-body" ng-bind-html="$parent.markdownContent"> </div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-primary" ng-click="ok()">OK</button>
|
|
</div>
|
|
</script>
|
|
|
|
<!--***********************************************
|
|
Options Dialog
|
|
************************************************-->
|
|
<script type="text/ng-template" id="optionsDialog.html">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" ng-click="cancel()">×</button>
|
|
<h4 class="modal-title">Options</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<h5>Editor Step Sizes:</h5>
|
|
<div class="form-horizontal">
|
|
<div class="form-group form-group-sm">
|
|
<label for="moveStepEditor" class="col-sm-6 col-md-3 col-lg-2 control-label">Move Step:</label>
|
|
<div class="col-sm-6 col-md-9 col-lg-10">
|
|
<div class="form-inline">
|
|
<div class="form-group form-group-sm">
|
|
<div class="input-group input-group-sm hint--top hint--rounded"
|
|
data-hint="Controls the step size when moving keys around the keyboard layout.">
|
|
<input id="moveStepEditor" class="form-control" type="number" min="0.05" max="2.5" step="0.05" size="6" ng-model="params.moveStep">
|
|
<span class="input-group-addon">units</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group form-group-sm">
|
|
<label for="sizeStepEditor" class="col-sm-6 col-md-3 col-lg-2 control-label">Size Step:</label>
|
|
<div class="col-sm-6 col-md-9 col-lg-10">
|
|
<div class="form-inline">
|
|
<div class="form-group form-group-sm">
|
|
<div class="input-group input-group-sm hint--top hint--rounded"
|
|
data-hint="Controls the step size when resizing keys in the keyboard layout.">
|
|
<input id="sizeStepEditor" class="form-control" type="number" min="0.05" max="2.5" step="0.05" size="6" ng-model="params.sizeStep">
|
|
<span class="input-group-addon">units</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group form-group-sm">
|
|
<label for="rotateStepEditor" class="col-sm-6 col-md-3 col-lg-2 control-label">Rotate Step:</label>
|
|
<div class="col-sm-6 col-md-9 col-lg-10">
|
|
<div class="form-inline">
|
|
<div class="form-group form-group-sm">
|
|
<div class="input-group input-group-sm hint--top hint--rounded"
|
|
data-hint="Controls the step size when rotating keys in the keyboard layout.">
|
|
<input id="rotateStepEditor" class="form-control" type="number" min="1" max="90" step="1" size="6" ng-model="params.rotateStep">
|
|
<span class="input-group-addon">degrees</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-danger" ng-click="cancel()">Cancel</button>
|
|
<button type="button" class="btn btn-primary" ng-click="ok()">OK</button>
|
|
</div>
|
|
</script>
|
|
|
|
<!--***********************************************
|
|
Tools Dialog
|
|
************************************************-->
|
|
<script type="text/ng-template" id="toolsDialog.html">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" ng-click="cancel()">×</button>
|
|
<h4 class="modal-title">Tools</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<h5>Remove or Move Legends:</h5>
|
|
<div class="form-group form-group-sm form-horizontal">
|
|
<label class="control-label text-nowrap" style='margin-left: 5px;'>Remove Legends:</label>
|
|
<div class="btn-group btn-group-xs" role="group">
|
|
<button type="button" class="btn btn-success hint--top hint--rounded" data-hint="Remove all the legends from all the keys. Does not remove decals." ng-click="removeLegends('all')"> All</button>
|
|
</div>
|
|
<div class="btn-group btn-group-xs" role="group">
|
|
<button type="button" class="btn btn-success hint--top hint--rounded" data-hint="Remove the legends from all the Alphabetical keys." ng-click="removeLegends('alphas')"> Alphas</button>
|
|
</div>
|
|
<div class="btn-group btn-group-xs" role="group">
|
|
<button type="button" class="btn btn-success hint--top hint--rounded" data-hint="Remove the legends from all the Number keys." ng-click="removeLegends('nums')"> Nums</button>
|
|
</div>
|
|
<div class="btn-group btn-group-xs" role="group">
|
|
<button type="button" class="btn btn-success hint--top hint--rounded" data-hint="Remove the legends from all the Punctuation keys." ng-click="removeLegends('punct')"> Punct</button>
|
|
</div>
|
|
<div class="btn-group btn-group-xs" role="group">
|
|
<button type="button" class="btn btn-success hint--top hint--rounded" data-hint="Remove the legends from all the Function keys." ng-click="removeLegends('fn')"> Fn</button>
|
|
</div>
|
|
<div class="btn-group btn-group-xs" role="group">
|
|
<button type="button" class="btn btn-success hint--top hint--rounded" data-hint="Remove the legends from all the other keys except decals." ng-click="removeLegends('others')"> Others</button>
|
|
</div>
|
|
<div class="btn-group btn-group-xs" role="group">
|
|
<button type="button" class="btn btn-success hint--top hint--rounded" data-hint="Remove the legends from all the Decals." ng-click="removeLegends('decals')"> Decals</button>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-danger" ng-click="cancel()">Cancel</button>
|
|
</div>
|
|
</script>
|
|
|
|
<!--***********************************************
|
|
Markdown dialog for displaying README, etc.
|
|
************************************************-->
|
|
<script type="text/ng-template" id="savedLayouts.html">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" ng-click="cancel()">×</button>
|
|
<h4 class="modal-title">{{params.starred ? 'Starred Layouts' : 'Saved Layouts'}}</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<table class="table table-hover">
|
|
<thead>
|
|
<tr>
|
|
<th>#</th>
|
|
<th>Name</th>
|
|
<th>Date</th>
|
|
<th> </th>
|
|
<th> </th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr ng-if="layouts.length === 0">
|
|
<td colspan='5'>{{params.starred ? 'No starred layouts.' : 'No saved layouts.'}}</td>
|
|
</tr>
|
|
<tr ng-repeat="layout in layouts">
|
|
<td>{{layout.index}}</td>
|
|
<td>{{layout.description}}</td>
|
|
<td>{{layout.updated_at}}</td>
|
|
<td nowrap>
|
|
<a class="btn btn-danger btn-xs" href="#" ng-click="delete(layout.id)" ng-hide="params.starred"><i class="fa fa-trash"></i> Delete</a>
|
|
<a class="btn btn-primary btn-xs" ng-href="{{layout.html_url}}" target='_blank'><i class="fa fa-github"></i> View on GitHub</a>
|
|
</td>
|
|
<td nowrap>
|
|
<a class="btn btn-success btn-xs" href="#" ng-click="load(layout.id)"><i class="fa fa-folder-open"></i> Load</a>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-primary" ng-click="ok()">OK</button>
|
|
</div>
|
|
</script>
|
|
|
|
<!--***********************************************
|
|
Angular Templates
|
|
************************************************-->
|
|
|
|
<!-- Color Picker Template -->
|
|
<script type="text/ng-template" id="colorPicker.html">
|
|
<div class="form-group form-group-sm">
|
|
<div class="input-group input-group-sm hint--top hint--rounded" ng-attr-data-hint="{{hintText}}">
|
|
<input id="{{pickerId}}" class="form-control" size="8" type='text'
|
|
ng-model="color" ng-change="onChange()" ng-blur="onBlur()" ng-disabled="isDisabled && isDisabled()"
|
|
colorpicker="hex" colorpicker-close-on-select="true" colorpicker-position="{{pickerPosition || 'bottom'}}">
|
|
<span class="input-group-btn">
|
|
<button class="btn btn-default" ng-style="{'background-color':color}" ng-model="color" ng-change="onChange()" ng-disabled="isDisabled && isDisabled()"
|
|
colorpicker="hex" colorpicker-close-on-select="true" colorpicker-position="{{pickerPosition || 'bottom'}}"> </button>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</script>
|
|
|
|
<!-- Simple Editor Templates -->
|
|
<script type="text/ng-template" id="multiCheck.html">
|
|
<div class="form-group form-group-sm">
|
|
<div class="checkbox hint--top hint--rounded" ng-attr-data-hint="{{hintText}}">
|
|
<label>
|
|
<input id="{{field}}" type="checkbox"
|
|
ng-model="$parent.multi[field]"
|
|
ng-change="$parent.updateMulti(field)"
|
|
ng-blur="$parent.validateMulti(field)"
|
|
ng-disabled="$parent.selectedKeys.length<1 || kbdDisable">
|
|
<span ng-transclude></span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</script>
|
|
|
|
<script type="text/ng-template" id="multiNumbox.html">
|
|
<div class="form-group form-group-sm">
|
|
<input id="{{field}}-editor" class="form-control input-sm" size="{{size}}" type='number' min="{{min}}" max="{{max}}" step="{{step || 1}}"
|
|
ng-model="$parent.multi[field]"
|
|
ng-change="$parent.updateMulti(field)"
|
|
ng-blur="$parent.validateMulti(field)"
|
|
ng-disabled="$parent.selectedKeys.length<1 || kbdDisable"
|
|
style="max-width:80px">
|
|
</div>
|
|
</script>
|
|
|
|
<!-- Label Editor Template -->
|
|
<script type="text/ng-template" id="labelEditor.html">
|
|
<div class="form-group form-group-sm">
|
|
<div class="input-group input-group-sm hint--top hint--rounded" ng-attr-data-hint="{{hintText}}"
|
|
ui-on-Drop="$parent.dropSwatch($data,$event,true,labelIndex)" drop-channel="dragColor">
|
|
<input id="labeleditor{{labelIndex}}" class="form-control" size="6" type='text'
|
|
ng-model="$parent.multi.labels[labelIndex]"
|
|
ng-change="$parent.updateMulti('labels',labelIndex)"
|
|
ng-blur="$parent.validateMulti('labels',labelIndex)"
|
|
ng-disabled="$parent.selectedKeys.length<1"
|
|
ui-on-Drop="$parent.dropGlyph($data,$event,labelIndex)" drop-channel="dragGlyph">
|
|
<span class="input-group-btn">
|
|
<button class="btn btn-default"
|
|
ng-style="{'background': $parent.selectedKeys.length<1 ? '#eee' : (!$parent.multi.textColor[labelIndex] ? '#fff' : $parent.multi.textColor[labelIndex])}"
|
|
ng-model="$parent.multi.textColor[labelIndex]"
|
|
ng-change="$parent.updateMulti('textColor',labelIndex)"
|
|
colorpicker="hex"
|
|
colorpicker-close-on-select="true"
|
|
colorpicker-with-input="true"
|
|
ng-class="{'use-default':!$parent.multi.textColor[labelIndex]}"
|
|
ng-disabled="$parent.selectedKeys.length<1"> </button>
|
|
</span>
|
|
<input id="textsizeeditor{{labelIndex}}" class="form-control input-sm" size="4" type='number' min="1" max="9"
|
|
ng-model="$parent.multi.textSize[labelIndex]"
|
|
ng-change="$parent.updateMulti('textSize',labelIndex)"
|
|
ng-blur="$parent.validateMulti('textSize',labelIndex)"
|
|
ng-disabled="$parent.selectedKeys.length<1"
|
|
ng-style="{visibility:labelIndex<9 ? 'inherit' : 'hidden'}"
|
|
style="max-width:32px;">
|
|
</div>
|
|
</div>
|
|
</script>
|
|
|
|
<!--***********************************************
|
|
DOT.js Templates
|
|
************************************************-->
|
|
|
|
<!-- Keycap Template -->
|
|
<script type="text/ng-template" id="keycap_html">
|
|
<div class='{{=key.ghost ? "ghosted" : ""}} {{=key.decal ? "decal" : ""}} keycap'
|
|
{{? key.rotation_angle }}
|
|
style='transform:rotate({{=key.rotation_angle}}deg); transform-origin:{{=parms.origin_x}}px {{=parms.origin_y}}px;'
|
|
{{?}}>
|
|
|
|
<div style="left: {{=parms.capx}}px; top: {{=parms.capy}}px;
|
|
width: {{=parms.capwidth}}px; height: {{=parms.capheight}}px;
|
|
border-style: solid; border-width: {{=sizes.strokeWidth}}px; border-color: black; border-radius: {{=sizes.roundOuter}}px;
|
|
background-color: {{=parms.darkColor}};"
|
|
class="keyborder"></div>
|
|
{{? parms.jShaped}}
|
|
<div style="left: {{=parms.capx2}}px; top: {{=parms.capy2}}px;
|
|
width: {{=parms.capwidth2}}px; height: {{=parms.capheight2}}px;
|
|
border-style: solid; border-width: {{=sizes.strokeWidth}}px; border-color: black; border-radius: {{=sizes.roundOuter}}px;
|
|
background-color: {{=parms.darkColor}};"
|
|
class="keyborder"></div>
|
|
<div style="left: {{=parms.capx + sizes.strokeWidth}}px; top: {{=parms.capy + sizes.strokeWidth}}px;
|
|
width: {{=parms.capwidth - sizes.strokeWidth*2}}px;
|
|
height: {{=parms.capheight - sizes.strokeWidth*2}}px;
|
|
background-color: {{=parms.darkColor}};
|
|
border-radius: {{=sizes.roundOuter}}px;"></div>
|
|
{{?}}
|
|
|
|
{{? !key.ghost }}
|
|
{{? !key.decal}}
|
|
<div style="left: {{=parms.innercapx}}px; top: {{=parms.innercapy}}px;
|
|
width: {{=parms.innercapwidth}}px; height: {{=parms.innercapheight}}px;
|
|
border-style: solid; border-width: {{=sizes.strokeWidth}}px; border-color: rgba(0,0,0,0.1);
|
|
background-color: {{=parms.lightColor}};
|
|
border-radius: {{=sizes.roundInner}}px;"
|
|
class="keytop"></div>
|
|
{{? parms.jShaped && !key.stepped }}
|
|
<div style="left: {{=parms.innercapx2}}px; top: {{=parms.innercapy2}}px;
|
|
width: {{=parms.innercapwidth2}}px; height: {{=parms.innercapheight2}}px;
|
|
border-style: solid; border-width: {{=sizes.strokeWidth}}px; border-color: rgba(0,0,0,0.1); border-radius: {{=sizes.roundInner}}px;
|
|
background-color: {{=parms.lightColor}};
|
|
background-position: {{=Math.min(parms.innercapx-parms.innercapx2,0)}}px {{=Math.min(parms.innercapy-parms.innercapy2,0)}}px;
|
|
background-size: {{=Math.max(parms.innercapwidth,parms.innercapwidth2)}}px {{=Math.max(parms.innercapheight,parms.innercapheight2)}}px;"
|
|
class="keytop"></div>
|
|
<div style="left: {{=parms.innercapx + sizes.strokeWidth}}px; top: {{=parms.innercapy + sizes.strokeWidth}}px;
|
|
width: {{=parms.innercapwidth - sizes.strokeWidth*2}}px; height: {{=parms.innercapheight - sizes.strokeWidth*2}}px;
|
|
border-radius: {{=sizes.roundInner}}px;
|
|
background-color: {{=parms.lightColor}};
|
|
background-position: {{=Math.min(parms.innercapx2-parms.innercapx,0)}}px {{=Math.min(parms.innercapy2-parms.innercapy,0)}}px;
|
|
background-size: {{=Math.max(parms.innercapwidth,parms.innercapwidth2)}}px {{=Math.max(parms.innercapheight,parms.innercapheight2)}}px;"
|
|
class="keytop"></div>
|
|
{{?}}
|
|
{{?}} {{ /*decal*/ }}
|
|
|
|
<div style='left: {{=parms.innercapx}}px; top: {{=parms.innercapy}}px; width: {{=parms.innercapwidth}}px; height: {{=parms.innercapheight}}px; padding: {{=sizes.padding}}px;' class='keylabels'>
|
|
{{~key.labels :label:i}}
|
|
{{? label && label != "" }}
|
|
{{ var sanitizedLabel = ""; try { sanitizedLabel = $sanitize(label.replace(/<([^a-zA-Z\/]|$)/,"<$1")); } catch(e) {console.log(e);} }}
|
|
{{? sanitizedLabel !== "" }}
|
|
{{ var textSize = key.textSize[i] || key.default.textSize; }}
|
|
{{ var textColor = key.textColor[i] || key.default.textColor; }}
|
|
{{ if(i<9) textColor = lightenColor($color.hex(textColor), 1.2).hex(); }}
|
|
<div class='keylabel keylabel{{=i}} textsize{{=textSize}}' style='color:{{=textColor}}; width:{{=parms.textcapwidth}}px; height:{{=parms.textcapheight}}px;'>
|
|
<div style='width:{{=parms.textcapwidth}}px; max-width:{{=parms.textcapwidth}}px; height:{{=parms.textcapheight}}px;'>{{=sanitizedLabel}}</div>
|
|
</div>
|
|
{{??}}
|
|
<div class="hint--top hint--rounded" data-hint="Error: Invalid HTML in legend field."><i class="fa fa-times-circle"></i></div>
|
|
{{?}}
|
|
{{?}}
|
|
{{~}}
|
|
</div>
|
|
{{?}} {{ /*ghost*/ }}
|
|
|
|
</div>
|
|
</script>
|
|
|
|
<!-- Keycap Template for SVG-->
|
|
<script type="text/ng-template" id="keycap_svg">
|
|
<g class='{{=key.ghost ? "ghosted" : ""}} {{=key.decal ? "decal" : ""}} keycap'
|
|
{{? key.rotation_angle }}
|
|
transform="rotate({{=key.rotation_angle}} {{=parms.origin_x}} {{=parms.origin_y}})"
|
|
{{?}}>
|
|
|
|
{{? !key.decal }}
|
|
<!-- Outer Border -->
|
|
<rect x="{{=parms.capx+sizes.strokeWidth}}" y="{{=parms.capy+sizes.strokeWidth}}"
|
|
width="{{=parms.capwidth-sizes.strokeWidth*2}}" height="{{=parms.capheight-sizes.strokeWidth*2}}"
|
|
rx="{{=sizes.roundOuter}}" fill="{{=parms.darkColor}}" class="outer border"/>
|
|
{{? parms.jShaped }}
|
|
<rect x="{{=parms.capx2+sizes.strokeWidth}}" y="{{=parms.capy2+sizes.strokeWidth}}"
|
|
width="{{=parms.capwidth2-sizes.strokeWidth*2}}" height="{{=parms.capheight2-sizes.strokeWidth*2}}"
|
|
rx="{{=sizes.roundOuter}}" fill="{{=parms.darkColor}}" class="outer border"/>
|
|
{{?}}
|
|
<!-- Outer Fill -->
|
|
<rect x="{{=parms.capx+sizes.strokeWidth}}" y="{{=parms.capy+sizes.strokeWidth}}"
|
|
width="{{=parms.capwidth-sizes.strokeWidth*2}}" height="{{=parms.capheight-sizes.strokeWidth*2}}"
|
|
rx="{{=sizes.roundOuter}}" fill="{{=parms.darkColor}}"/>
|
|
{{? parms.jShaped }}
|
|
<rect x="{{=parms.capx2+sizes.strokeWidth}}" y="{{=parms.capy2+sizes.strokeWidth}}"
|
|
width="{{=parms.capwidth2-sizes.strokeWidth*2}}" height="{{=parms.capheight2-sizes.strokeWidth*2}}"
|
|
rx="{{=sizes.roundOuter}}" fill="{{=parms.darkColor}}"/>
|
|
{{?}}
|
|
|
|
{{? !key.ghost }}
|
|
<!-- Inner Border -->
|
|
<rect x="{{=parms.innercapx+sizes.strokeWidth}}" y="{{=parms.innercapy+sizes.strokeWidth}}"
|
|
width="{{=parms.innercapwidth-sizes.strokeWidth*2}}" height="{{=parms.innercapheight-sizes.strokeWidth*2}}"
|
|
rx="{{=sizes.roundOuter}}" fill="{{=parms.lightColor}}" class="inner border"/>
|
|
{{? parms.jShaped && !key.stepped }}
|
|
<rect x="{{=parms.innercapx2+sizes.strokeWidth}}" y="{{=parms.innercapy2+sizes.strokeWidth}}"
|
|
width="{{=parms.innercapwidth2-sizes.strokeWidth*2}}" height="{{=parms.innercapheight2-sizes.strokeWidth*2}}"
|
|
rx="{{=sizes.roundOuter}}" fill="{{=parms.lightColor}}" class="inner border"/>
|
|
{{?}}
|
|
<!-- Inner Fill -->
|
|
<rect x="{{=parms.innercapx+sizes.strokeWidth}}" y="{{=parms.innercapy+sizes.strokeWidth}}"
|
|
width="{{=parms.innercapwidth-sizes.strokeWidth*2}}" height="{{=parms.innercapheight-sizes.strokeWidth*2}}"
|
|
rx="{{=sizes.roundOuter}}" fill="{{=parms.lightColor}}"/>
|
|
{{? parms.jShaped && !key.stepped }}
|
|
<rect x="{{=parms.innercapx2+sizes.strokeWidth}}" y="{{=parms.innercapy2+sizes.strokeWidth}}"
|
|
width="{{=parms.innercapwidth2-sizes.strokeWidth*2}}" height="{{=parms.innercapheight2-sizes.strokeWidth*2}}"
|
|
rx="{{=sizes.roundOuter}}" fill="{{=parms.lightColor}}"/>
|
|
{{?}}
|
|
{{? sizes.profile !== "" }}
|
|
{{var theProfile = sizes.profile; if(/\b(SPACE)\b/.exec(key.profile)) theProfile = "SPACE";}}
|
|
{{? parms.jShaped && !key.stepped }}
|
|
{{
|
|
/*much harder to do j-shaped keys in SVG*/
|
|
theProfile = '_fill'+parms.index;
|
|
var rect = {
|
|
left: Math.min(parms.innercapx, parms.innercapx2),
|
|
top: Math.min(parms.innercapy, parms.innercapy2),
|
|
right: Math.min(parms.innercapx+parms.innercapwidth, parms.innercapx2+parms.innercapwidth2),
|
|
bottom: Math.min(parms.innercapy+parms.innercapheight, parms.innercapy2+parms.innercapheight2)
|
|
};
|
|
}}
|
|
{{? sizes.profile==="SA" || sizes.profile==="DSA" }}
|
|
<radialGradient id="{{=theProfile}}" xlink:href="#{{=sizes.profile}}" gradientUnits="userSpaceOnUse"
|
|
cx="{{=(rect.left+rect.right)/2}}" cy="{{=(rect.top+rect.bottom)/2}}"
|
|
r="{{=Math.min(rect.right-rect.left, rect.bottom-rect.top)}}"/>
|
|
{{??}}
|
|
<linearGradient id="{{=theProfile}}" xlink:href="#{{=sizes.profile}}" gradientUnits="userSpaceOnUse"
|
|
x1="{{=rect.left}}" y1="{{=rect.top}}" x2="{{=rect.right}}" y2="{{=rect.top}}"/>
|
|
{{?}}
|
|
<rect x="{{=parms.innercapx2+sizes.strokeWidth}}" y="{{=parms.innercapy2+sizes.strokeWidth}}"
|
|
width="{{=parms.innercapwidth2-sizes.strokeWidth*2}}" height="{{=parms.innercapheight2-sizes.strokeWidth*2}}"
|
|
rx="{{=sizes.roundOuter}}" fill="{{=parms.lightColor}}"/>
|
|
<rect x="{{=parms.innercapx2+sizes.strokeWidth}}" y="{{=parms.innercapy2+sizes.strokeWidth}}"
|
|
width="{{=parms.innercapwidth2-sizes.strokeWidth*2}}" height="{{=parms.innercapheight2-sizes.strokeWidth*2}}"
|
|
rx="{{=sizes.roundOuter}}" fill="url(#{{=theProfile}})"/>
|
|
<rect x="{{=parms.innercapx+sizes.strokeWidth}}" y="{{=parms.innercapy+sizes.strokeWidth}}"
|
|
width="{{=parms.innercapwidth-sizes.strokeWidth*2}}" height="{{=parms.innercapheight-sizes.strokeWidth*2}}"
|
|
rx="{{=sizes.roundOuter}}" fill="{{=parms.lightColor}}"/>
|
|
{{?}}
|
|
<rect x="{{=parms.innercapx+sizes.strokeWidth}}" y="{{=parms.innercapy+sizes.strokeWidth}}"
|
|
width="{{=parms.innercapwidth-sizes.strokeWidth*2}}" height="{{=parms.innercapheight-sizes.strokeWidth*2}}"
|
|
rx="{{=sizes.roundOuter}}" fill="url(#{{=theProfile}})"/>
|
|
{{?}}
|
|
|
|
{{?}} {{ /*ghost*/ }}
|
|
{{?}} {{ /*decal*/ }}
|
|
</g>
|
|
</script>
|
|
|
|
<script type="text/ng-template" id="keyboard_svg">
|
|
<svg width='{{=parms.width+parms.margin*2+parms.padding*2}}{{=parms.units}}'
|
|
height='{{=parms.height+parms.margin*2+parms.padding*2}}{{=parms.units}}'
|
|
viewBox='0 0 {{=parms.width+parms.margin*2+parms.padding*2}} {{=parms.height+parms.margin*2+parms.padding*2}}'
|
|
xmlns='http://www.w3.org/2000/svg'
|
|
xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
|
|
<style type='text/css'>
|
|
.keycap .border { stroke: black; stroke-width: {{=parms.strokeWidth*2}}; }
|
|
.keycap .inner.border { stroke: rgba(0,0,0,.1); }
|
|
</style>
|
|
<defs>
|
|
<linearGradient id="DCS">
|
|
<stop offset="0%" stop-color="black" stop-opacity="0"/>
|
|
<stop offset="40%" stop-color="black" stop-opacity="0.1"/>
|
|
<stop offset="60%" stop-color="black" stop-opacity="0.1"/>
|
|
<stop offset="100%" stop-color="black" stop-opacity="0"/>
|
|
</linearGradient>
|
|
<linearGradient id="SPACE" x1="0%" x2="0%" y1="0%" y2="100%">
|
|
<stop offset="0%" stop-color="black" stop-opacity="0.1"/>
|
|
<stop offset="20%" stop-color="black" stop-opacity="0.0"/>
|
|
<stop offset="40%" stop-color="black" stop-opacity="0.0"/>
|
|
<stop offset="100%" stop-color="black" stop-opacity="0.1"/>
|
|
</linearGradient>
|
|
<radialGradient id="DSA">
|
|
<stop offset="0%" stop-color="black" stop-opacity="0.1"/>
|
|
<stop offset="10%" stop-color="black" stop-opacity="0.1"/>
|
|
<stop offset="100%" stop-color="black" stop-opacity="0"/>
|
|
</radialGradient>
|
|
<radialGradient id="SA" xlink:href="#DSA" />
|
|
</defs>
|
|
|
|
<g transform='translate({{=parms.margin}},{{=parms.margin}})'>
|
|
<rect width="{{=parms.width+parms.padding*2}}" height="{{=parms.height+parms.padding*2}}"
|
|
stroke="#ddd" stroke-width="1" fill="{{=parms.backcolor}}" rx="6"/>
|
|
<g transform='translate({{=parms.padding}},{{=parms.padding}})'>
|
|
{{=parms.keys}}
|
|
</g>
|
|
</g>
|
|
</svg>
|
|
</script>
|
|
</div>
|
|
<div id='summary_print'></div><!-- just a div to make the summary print work -->
|
|
</body>
|
|
</html>
|