Palette creator can save palettes to local storage

This commit is contained in:
jdescottes 2014-09-06 12:37:11 +02:00
parent e8db80a0ec
commit 8441f28ac1
25 changed files with 603 additions and 846 deletions

View File

@ -33,7 +33,7 @@
"karma": "0.12.17", "karma": "0.12.17",
"karma-chrome-launcher": "^0.1.4", "karma-chrome-launcher": "^0.1.4",
"karma-phantomjs-launcher": "^0.1.4", "karma-phantomjs-launcher": "^0.1.4",
"karma-jasmine": "^0.1.5", "karma-jasmine": "^0.2.0",
"nodewebkit": "~0.10.1" "nodewebkit": "~0.10.1"
}, },
"window": { "window": {

View File

@ -1,21 +0,0 @@
#dialog-container.create-palette-method {
width: 500px;
height: 200px;
top : 50%;
left : 50%;
position : absolute;
margin-left: -250px;
}
.show #dialog-container.create-palette-method {
margin-top: -100px;
}
.create-palette-method-item {
line-height : 24px;
}
.create-palette-method-item label{
margin-top: 3px;
margin-left: 5px;
}

View File

@ -51,6 +51,84 @@
margin: 11px; margin: 11px;
} }
.colors-list {
overflow : hidden;
width : 280px;
}
.create-palette-color, .create-palette-new-color, .colors-list-drop-proxy{
position:relative;
float : left;
width : 44px;
height : 44px;
margin : 10px 0 0 10px;
box-sizing : border-box;
cursor : pointer;
}
.create-palette-color {
border:1px solid #2c2c2c;
transition : border-color 0.2s;
}
.create-palette-color:hover {
border:1px solid gold;
}
.colors-list-drop-proxy {
border:2px dotted #eee;
}
.create-palette-new-color {
border:2px dotted gold;
border-radius: 2px;
line-height: 40px;
text-align: center;
font-size: 20px;
color: gold;
}
.create-palette-color.selected {
border:2px solid gold;
}
.create-palette-remove-color {
position: absolute;
top: 0;
right: 0;
padding: 2px 4px;
opacity : 0.2;
font-weight: bold;
color: rgb(255,255,255);
text-shadow : 0 0 1px rgb(0,0,0);
transition : opacity 0.3s, color 0.1s;
}
.light-color .create-palette-remove-color {
color: rgb(0,0,0);
text-shadow : 0 0 1px rgb(255,255,255);
}
.selected .create-palette-remove-color {
top: -1px;
right: -1px;
}
.create-palette-color:hover .create-palette-remove-color {
opacity: 0.6;
}
.create-palette-color .create-palette-remove-color:hover {
opacity: 1;
color: rgb(240,80,80);
text-shadow : 0 0 1px rgb(0,0,0);
}
/*SPECTRUM OVERRIDES*/ /*SPECTRUM OVERRIDES*/
.create-palette .sp-container{ .create-palette .sp-container{

View File

@ -1,212 +0,0 @@
.palette-manager-wrapper {
height: 100%;
position: relative;
}
.palette-manager-body {
position: absolute;
top: 45px;
bottom: 0;
right: 0;
left: 0;
}
.palette-manager-head {
position: absolute;
width: 100%;
background: gold;
margin: 0;
padding: 10px;
color: black;
font-size: 1.8em;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
.palette-manager-drawer {
width: 200px;
position: absolute;
top: 0;
bottom: 0;
}
.palette-manager-list {
position: absolute;
top:40px;
right: 0;
bottom: 0;
left: 0;
overflow: auto;
}
.palette-manager-actions {
position: absolute;
height:40px;
line-height:40px;
width: 100%;
text-align: center;
}
.palette-manager-actions-button {
width: 80px;
margin: 5px;
}
.palette-manager-palette-button,
.palette-manager-actions-button {
line-height: 20px;
}
.palette-manager-list li {
height: 48px;
line-height: 48px;
padding-left:10px;
font-size: 1.4em;
box-sizing: border-box;
-moz-box-sizing: border-box;
border-bottom: 1px solid #666;
cursor:pointer;
}
.palette-manager-list li:hover {
background : #222;
}
.palette-manager-list li.selected {
color : gold;
font-weight: bold;
}
.palette-manager-list li:nth-child(1) {
border-top: 1px solid #666;
}
.palette-manager-details {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 200px;
box-sizing: border-box;
-moz-box-sizing: border-box;
border-left:1px solid #666;
}
.palette-manager-details-head {
position: absolute;
height:40px;
line-height:40px;
width: 100%;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
.palette-manager-details-head-name {
padding: 0 10px 0 20px;
font-size: 1.5em;
font-weight: bold;
}
.palette-manager-details-head .edit-icon {
width: 24px;
display: inline-block;
background-size: 16px;
}
.palette-manager-details-head-actions {
float: right;
line-height: 40px;
padding-right: 10px;
}
.palette-manager-details-body {
position: absolute;
top:40px;
right: 0;
bottom: 0;
left: 0;
overflow: auto;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
.palette-manager-color-card {
width: 120px;
height: 180px;
display: inline-block;
position: relative;
margin: 20px 0 20px 20px;
box-shadow: 0 0 0px 0px gold;
transition: box-shadow 0.3s;
}
.palette-manager-color-card:hover {
box-shadow: 0 0 4px 1px gold;
}
.palette-manager-delete-card {
position: absolute;
top: 0;
right: 0;
width: 20px;
text-align: center;
font-size: 1.6em;
font-weight: bold;
color: rgb(255,255,255);
text-shadow : 0 0 2px rgb(0,0,0);
cursor: pointer;
opacity : 0.2;
transition : opacity 0.3s, color 0.1s;
}
.palette-manager-color-card:hover .palette-manager-delete-card {
opacity : 0.6;
}
.palette-manager-color-card .palette-manager-delete-card:hover {
opacity : 1;
color: rgb(240,80,80);
}
.palette-manager-new-color .palette-manager-color-square {
border: 3px dotted #888;
border-bottom-width: 0;
box-sizing: border-box;
-moz-box-sizing: border-box;
border-radius: 3px 3px 0 0;
cursor: pointer;
text-align: center;
font-size: 24px;
color: #888;
line-height: 120px;
}
.palette-manager-color-square {
width: 120px;
height: 120px;
cursor: pointer;
/*background-image:url(../img/tools/eyedropper.png);*/
}
.palette-manager-color-details {
color : #666;
background: #eee;
height: 60px;
padding-left: 5px;
}
.palette-manager-color-details li{
line-height: 20px;
font-weight: bold;
}

View File

@ -55,8 +55,28 @@
border-right-color: transparent; border-right-color: transparent;
} }
.palettes-list-secondary-color:before { .palettes-list-secondary-color:before {
right: 1px; right: 1px;
border-left-color: transparent; border-left-color: transparent;
}
.palette-action {
width : 18px;
height : 18px;
line-height : 16px;
text-align:center;
float : right;
font-size : 12px;
border: 1px solid gold;
border-radius : 2px;
box-sizing : border-box;
margin : 3px 3px 3px 0;
cursor : pointer;
transition : color 0.3s;
}
.palette-action:hover {
color : gold;
} }

View File

@ -68,7 +68,6 @@
<div id="dialog-container-wrapper"> <div id="dialog-container-wrapper">
<div id="dialog-container"> <div id="dialog-container">
<iframe src="templates/dialogs/create-palette.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe> <iframe src="templates/dialogs/create-palette.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
<iframe src="templates/dialogs/create-palette-method.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
<iframe src="templates/dialogs/import-image.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe> <iframe src="templates/dialogs/import-image.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
<iframe src="templates/dialogs/browse-local.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe> <iframe src="templates/dialogs/browse-local.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
</div> </div>

View File

@ -27,7 +27,6 @@ var Constants = {
NO_PALETTE_ID : '__no-palette', NO_PALETTE_ID : '__no-palette',
CURRENT_COLORS_PALETTE_ID : '__current-colors', CURRENT_COLORS_PALETTE_ID : '__current-colors',
MANAGE_PALETTE_ID : '__manage-palettes',
// Used for Spectrum input // Used for Spectrum input
PREFERRED_COLOR_FORMAT : 'rgb', PREFERRED_COLOR_FORMAT : 'rgb',

View File

@ -39,6 +39,9 @@
this.piskelController = new pskl.controller.piskel.PublicPiskelController(this.corePiskelController); this.piskelController = new pskl.controller.piskel.PublicPiskelController(this.corePiskelController);
this.piskelController.init(); this.piskelController.init();
this.paletteService = new pskl.service.PaletteService();
this.paletteService.init();
this.paletteController = new pskl.controller.PaletteController(); this.paletteController = new pskl.controller.PaletteController();
this.paletteController.init(); this.paletteController.init();
@ -129,9 +132,6 @@
if (pskl.devtools) { if (pskl.devtools) {
pskl.devtools.init(); pskl.devtools.init();
} }
// FIXME : remove
$.publish(Events.DIALOG_DISPLAY, 'create-palette');
}, },
loadPiskel_ : function (serializedPiskel, descriptor, fps) { loadPiskel_ : function (serializedPiskel, descriptor, fps) {

View File

@ -13,19 +13,26 @@
ns.PalettesListController = function (paletteController, usedColorService) { ns.PalettesListController = function (paletteController, usedColorService) {
this.usedColorService = usedColorService; this.usedColorService = usedColorService;
this.paletteService = pskl.app.paletteService;
this.paletteController = paletteController; this.paletteController = paletteController;
}; };
ns.PalettesListController.prototype.init = function () { ns.PalettesListController.prototype.init = function () {
this.paletteColorTemplate_ = pskl.utils.Template.get('palette-color-template'); this.paletteColorTemplate_ = pskl.utils.Template.get('palette-color-template');
this.colorListContainer_ = document.querySelector('.palettes-list-colors'); this.colorListContainer_ = document.querySelector('.palettes-list-colors');
this.colorPaletteSelect_ = document.querySelector('.palettes-list-select'); this.colorPaletteSelect_ = document.querySelector('.palettes-list-select');
this.createPaletteButton_ = document.querySelector('.create-palette-button');
var createPaletteButton_ = document.querySelector('.create-palette-button');
var paletteActions = document.querySelector('.palette-actions');
this.colorPaletteSelect_.addEventListener('change', this.onPaletteSelected_.bind(this)); this.colorPaletteSelect_.addEventListener('change', this.onPaletteSelected_.bind(this));
this.colorListContainer_.addEventListener('mouseup', this.onColorContainerMouseup.bind(this)); this.colorListContainer_.addEventListener('mouseup', this.onColorContainerMouseup.bind(this));
this.colorListContainer_.addEventListener('contextmenu', this.onColorContainerContextMenu.bind(this)); this.colorListContainer_.addEventListener('contextmenu', this.onColorContainerContextMenu.bind(this));
this.createPaletteButton_.addEventListener('click', this.onCreatePaletteClick_.bind(this));
createPaletteButton_.addEventListener('click', this.onCreatePaletteClick_.bind(this));
paletteActions.addEventListener('click', this.onPaletteActionsClick_.bind(this));
$.subscribe(Events.PALETTE_LIST_UPDATED, this.onPaletteListUpdated.bind(this)); $.subscribe(Events.PALETTE_LIST_UPDATED, this.onPaletteListUpdated.bind(this));
$.subscribe(Events.CURRENT_COLORS_UPDATED, this.fillColorListContainer.bind(this)); $.subscribe(Events.CURRENT_COLORS_UPDATED, this.fillColorListContainer.bind(this));
@ -42,7 +49,7 @@
id : Constants.CURRENT_COLORS_PALETTE_ID, id : Constants.CURRENT_COLORS_PALETTE_ID,
name : 'Current colors' name : 'Current colors'
}]; }];
palettes = palettes.concat(this.retrievePalettes()); palettes = palettes.concat(this.paletteService.getPalettes());
var html = palettes.map(function (palette) { var html = palettes.map(function (palette) {
return pskl.utils.Template.replace('<option value="{{id}}">{{name}}</option>', palette); return pskl.utils.Template.replace('<option value="{{id}}">{{name}}</option>', palette);
@ -74,7 +81,7 @@
if (paletteId === Constants.CURRENT_COLORS_PALETTE_ID) { if (paletteId === Constants.CURRENT_COLORS_PALETTE_ID) {
colors = this.usedColorService.getCurrentColors(); colors = this.usedColorService.getCurrentColors();
} else { } else {
var palette = this.getPaletteById(paletteId, this.retrievePalettes()); var palette = this.paletteService.getPaletteById(paletteId);
if (palette) { if (palette) {
colors = palette.colors; colors = palette.colors;
} }
@ -87,14 +94,14 @@
return colors; return colors;
}; };
ns.PalettesListController.prototype.selectPalette = function (paletteId) {
this.colorPaletteSelect_.value = paletteId;
};
ns.PalettesListController.prototype.selectPaletteFromUserSettings = function () { ns.PalettesListController.prototype.selectPaletteFromUserSettings = function () {
this.selectPalette(pskl.UserSettings.get(pskl.UserSettings.SELECTED_PALETTE)); this.selectPalette(pskl.UserSettings.get(pskl.UserSettings.SELECTED_PALETTE));
}; };
ns.PalettesListController.prototype.selectPalette = function (paletteId) {
this.colorPaletteSelect_.value = paletteId;
};
ns.PalettesListController.prototype.onPaletteSelected_ = function (evt) { ns.PalettesListController.prototype.onPaletteSelected_ = function (evt) {
var paletteId = this.colorPaletteSelect_.value; var paletteId = this.colorPaletteSelect_.value;
pskl.UserSettings.set(pskl.UserSettings.SELECTED_PALETTE, paletteId); pskl.UserSettings.set(pskl.UserSettings.SELECTED_PALETTE, paletteId);
@ -102,7 +109,39 @@
}; };
ns.PalettesListController.prototype.onCreatePaletteClick_ = function (evt) { ns.PalettesListController.prototype.onCreatePaletteClick_ = function (evt) {
$.publish(Events.DIALOG_DISPLAY, 'create-palette-method'); $.publish(Events.DIALOG_DISPLAY, 'create-palette');
};
ns.PalettesListController.prototype.onPaletteActionsClick_ = function (evt) {
var classList = evt.target.classList;
if (classList.contains('palette-action-edit')) {
this.editSelectedPalette_();
} else if (classList.contains('palette-action-delete')) {
this.deleteSelectedPalette_();
} else if (classList.contains('palette-action-download')) {
this.downloadSelectedPalette_();
}
};
ns.PalettesListController.prototype.editSelectedPalette_ = function () {
var paletteId = this.colorPaletteSelect_.value;
$.publish(Events.DIALOG_DISPLAY, {
dialogId : 'create-palette',
initArgs : paletteId
});
};
ns.PalettesListController.prototype.deleteSelectedPalette_ = function () {
var paletteId = this.colorPaletteSelect_.value;
var palette = this.paletteService.getPaletteById(paletteId);
if (window.confirm('Are you sure you want to delete palette ' + palette.name)) {
this.paletteService.deletePaletteById(palette.id);
this.selectPalette(Constants.CURRENT_COLORS_PALETTE_ID);
}
};
ns.PalettesListController.prototype.downloadSelectedPalette_ = function () {
window.alert('not implemented yet');
}; };
ns.PalettesListController.prototype.onColorContainerContextMenu = function (event) { ns.PalettesListController.prototype.onColorContainerContextMenu = function (event) {
@ -155,21 +194,4 @@
this.selectPaletteFromUserSettings(); this.selectPaletteFromUserSettings();
this.fillColorListContainer(); this.fillColorListContainer();
}; };
ns.PalettesListController.prototype.getPaletteById = function (paletteId, palettes) {
var match = null;
palettes.forEach(function (palette) {
if (palette.id === paletteId) {
match = palette;
}
});
return match;
};
ns.PalettesListController.prototype.retrievePalettes = function () {
var palettesString = window.localStorage.getItem('piskel.palettes');
return JSON.parse(palettesString) || [];
};
})(); })();

View File

@ -2,22 +2,34 @@
var ns = $.namespace('pskl.controller.dialogs'); var ns = $.namespace('pskl.controller.dialogs');
ns.CreatePaletteController = function (piskelController) { ns.CreatePaletteController = function (piskelController) {
this.tinyColor = null; this.paletteService = pskl.app.paletteService;
this.hsvColor = {h:0,s:0,v:0};
this.palette = [];
this.selectedIndex = -1; this.selectedIndex = -1;
}; };
pskl.utils.inherit(ns.CreatePaletteController, ns.AbstractDialogController); pskl.utils.inherit(ns.CreatePaletteController, ns.AbstractDialogController);
ns.CreatePaletteController.prototype.init = function () { ns.CreatePaletteController.prototype.init = function (paletteId) {
this.superclass.init.call(this); this.superclass.init.call(this);
console.log(paletteId);
if (paletteId) {
var palette = this.paletteService.getPaletteById(paletteId);
this.palette = pskl.model.Palette.fromObject(palette);
} else {
paletteId = pskl.utils.Uuid.generate();
this.palette = new pskl.model.Palette(paletteId, 'New palette', []);
}
this.colorsList = document.querySelector('.colors-list'); this.colorsList = document.querySelector('.colors-list');
this.colorPickerContainer = document.querySelector('.color-picker-container'); this.colorPickerContainer = document.querySelector('.color-picker-container');
this.colorPreviewEl = document.querySelector('.color-preview'); this.colorPreviewEl = document.querySelector('.color-preview');
this.submitButton = document.querySelector('.create-palette-submit');
this.nameInput = document.querySelector('input[name="palette-name"]');
this.nameInput.value = this.palette.name;
this.colorsList.addEventListener('click', this.onColorContainerClick_.bind(this)); this.colorsList.addEventListener('click', this.onColorContainerClick_.bind(this));
this.submitButton.addEventListener('click', this.onSubmitButtonClick_.bind(this));
this.nameInput.addEventListener('input', this.onNameInputChange_.bind(this));
this.hslRgbColorPicker = new pskl.controller.widgets.HslRgbColorPicker(this.colorPickerContainer, this.onColorUpdated_.bind(this)); this.hslRgbColorPicker = new pskl.controller.widgets.HslRgbColorPicker(this.colorPickerContainer, this.onColorUpdated_.bind(this));
this.hslRgbColorPicker.init(); this.hslRgbColorPicker.init();
@ -26,45 +38,114 @@
}; };
ns.CreatePaletteController.prototype.onColorUpdated_ = function (color) { ns.CreatePaletteController.prototype.onColorUpdated_ = function (color) {
this.colorPreviewEl.style.background = color.toRgbString(); var rgbColor = color.toRgbString();
this.palette[this.selectedIndex] = color.toRgbString(); this.colorPreviewEl.style.background = rgbColor;
this.refresh_(); this.palette.set(this.selectedIndex, rgbColor);
this.refreshColorElement_(this.selectedIndex);
};
/**
* Lightweight refresh only changing the color of one element of the palette color list
*/
ns.CreatePaletteController.prototype.refreshColorElement_ = function (index) {
var color = this.palette.get(this.selectedIndex);
var element = document.querySelector('[data-palette-index="'+index+'"]');
if (element) {
element.style.background = color;
element.classList.toggle('light-color', this.isLight_(color));
}
}; };
ns.CreatePaletteController.prototype.onColorContainerClick_ = function (evt) { ns.CreatePaletteController.prototype.onColorContainerClick_ = function (evt) {
var target = evt.target; var target = evt.target;
if (target.dataset.paletteIndex) { if (target.classList.contains('create-palette-color')) {
this.selectColor_(target.dataset.paletteIndex); this.onPaletteColorClick_(evt, target);
} else if (target.classList.contains('add-color-button')) { } else if (target.classList.contains('create-palette-new-color')) {
this.palette.push(this.palette[this.selectedIndex] || "#000000"); this.onNewColorClick_(evt, target);
this.refresh_(); } else if (target.classList.contains('create-palette-remove-color')) {
this.selectColor_(this.palette.length-1); this.onRemoveColorClick_(evt, target);
} }
this.refresh_();
};
ns.CreatePaletteController.prototype.onPaletteColorClick_ = function (evt, target) {
var index = parseInt(target.dataset.paletteIndex,10);
this.selectColor_(index);
};
ns.CreatePaletteController.prototype.onRemoveColorClick_ = function (evt, target) {
var colorElement = target.parentNode;
var index = parseInt(colorElement.dataset.paletteIndex,10);
this.removeColor_(index);
};
ns.CreatePaletteController.prototype.onNewColorClick_ = function (evt, target) {
var newColor = this.palette.get(this.selectedIndex) || '#000000';
this.palette.add(newColor);
this.selectColor_(this.palette.size()-1);
};
ns.CreatePaletteController.prototype.onSubmitButtonClick_ = function (evt) {
this.paletteService.savePalette(this.palette);
this.closeDialog();
};
ns.CreatePaletteController.prototype.onNameInputChange_ = function (evt) {
this.palette.name = this.nameInput.value;
}; };
ns.CreatePaletteController.prototype.selectColor_ = function (index) { ns.CreatePaletteController.prototype.selectColor_ = function (index) {
this.selectedIndex = index; this.selectedIndex = index;
this.hslRgbColorPicker.setColor(this.palette.get(index));
};
var previous = this.colorsList.querySelector('.selectedColor'); ns.CreatePaletteController.prototype.removeColor_ = function (index) {
if (previous) { this.palette.removeAt(index);
previous.classList.remove('selected'); this.refresh_();
}
var next = this.colorsList.querySelector('[data-palette-index="'+index+'"]');
next.classList.add('selected');
this.hslRgbColorPicker.setColor(this.palette[index]);
}; };
ns.CreatePaletteController.prototype.refresh_ = function () { ns.CreatePaletteController.prototype.refresh_ = function () {
var html = ""; var html = "";
var tpl = '<div data-palette-index="{{index}}" data-palette-color="{{color}}" style="height:40px;width:40px;float:left; margin:10px;background:{{color}}"></div>'; var tpl = pskl.utils.Template.get('create-palette-color-template');
this.palette.forEach(function (color, index) { var colors = this.palette.colors;
html += pskl.utils.Template.replace(tpl, {color:color, index:index});
});
html += '<div class=add-color-button style="height:40px;width:40px;margin:10px;float:left; background:gold">ADD</div>'; colors.forEach(function (color, index) {
var isSelected = (index === this.selectedIndex);
html += pskl.utils.Template.replace(tpl, {
color:color, index:index,
':selected':isSelected,
':light-color':this.isLight_(color)
});
}.bind(this));
html += '<li class="create-palette-new-color">+</li>';
this.colorsList.innerHTML = html; this.colorsList.innerHTML = html;
$('.colors-list').sortable({
placeholder: 'colors-list-drop-proxy',
update: this.onDrop_.bind(this),
items: '.create-palette-color'
});
};
ns.CreatePaletteController.prototype.isLight_ = function (color) {
var rgb = window.tinycolor(color).toRgb();
return rgb.r+rgb.b+rgb.g > 128*3;
};
ns.CreatePaletteController.prototype.onDrop_ = function (evt, drop) {
var colorElement = drop.item.get(0);
var oldIndex = parseInt(colorElement.dataset.paletteIndex, 10);
var newIndex = $('.create-palette-color').index(drop.item);
this.palette.move(oldIndex, newIndex);
this.selectedIndex = newIndex;
this.refresh_();
}; };
})(); })();

View File

@ -1,63 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs');
ns.CreatePaletteMethodController = function (piskelController) {
};
pskl.utils.inherit(ns.CreatePaletteMethodController, ns.AbstractDialogController);
ns.CreatePaletteMethodController.prototype.init = function () {
this.superclass.init.call(this);
this.createButton = document.querySelector('.create-palette-method-continue');
this.cancelButton = document.querySelector('.create-palette-method-cancel');
this.createButton.addEventListener('click', this.onCreateButtonClick_.bind(this));
this.cancelButton.addEventListener('click', function () {
$.publish(Events.DIALOG_HIDE);
});
};
ns.CreatePaletteMethodController.prototype.onCreateButtonClick_ = function (evt) {
var method = this.getSelectedMethod_();
var initArgs = {
method : method
};
if (method === 'palette') {
initArgs.paletteId = this.getSelectedPaletteId_();
}
this.closeDialog();
window.setTimeout(function () {
$.publish(Events.DIALOG_DISPLAY, {
dialogId : 'create-palette',
initArgs : initArgs
});
},500);
};
ns.CreatePaletteMethodController.prototype.getSelectedMethod_ = function (evt) {
var options = document.querySelectorAll('.create-palette-method-list input[type="radio"]');
var method;
for (var i = 0 ; i < options.length ; i++) {
console.log(options[i]);
if (options[i].checked) {
method = options[i].value;
}
}
return method;
};
ns.CreatePaletteMethodController.prototype.getSelectedPaletteId_ = function (evt) {
var select = document.querySelector('.palettes-list-select');
return select.value;
};
})();

View File

@ -2,14 +2,6 @@
var ns = $.namespace('pskl.controller.dialogs'); var ns = $.namespace('pskl.controller.dialogs');
var dialogs = { var dialogs = {
'manage-palettes' : {
template : 'templates/dialogs/manage-palettes.html',
controller : ns.PaletteManagerController
},
'create-palette-method' : {
template : 'templates/dialogs/create-palette-method.html',
controller : ns.CreatePaletteMethodController
},
'create-palette' : { 'create-palette' : {
template : 'templates/dialogs/create-palette.html', template : 'templates/dialogs/create-palette.html',
controller : ns.CreatePaletteController controller : ns.CreatePaletteController
@ -35,7 +27,7 @@
$.subscribe(Events.DIALOG_DISPLAY, this.onDialogDisplayEvent_.bind(this)); $.subscribe(Events.DIALOG_DISPLAY, this.onDialogDisplayEvent_.bind(this));
$.subscribe(Events.DIALOG_HIDE, this.onDialogHideEvent_.bind(this)); $.subscribe(Events.DIALOG_HIDE, this.onDialogHideEvent_.bind(this));
pskl.app.shortcutService.addShortcut('alt+P', this.onDialogDisplayEvent_.bind(this, null, 'manage-palettes')); pskl.app.shortcutService.addShortcut('alt+P', this.onDialogDisplayEvent_.bind(this, null, 'create-palettes'));
this.dialogWrapper_.classList.add('animated'); this.dialogWrapper_.classList.add('animated');
}; };

View File

@ -1,382 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs');
var tinycolor = window.tinycolor;
var SELECTED_CLASSNAME = 'selected';
var NEW_COLOR_CLASS = 'palette-manager-new-color';
var CLOSE_ICON_CLASS = 'palette-manager-delete-card';
var EDIT_NAME_CLASS = 'edit-icon';
ns.PaletteManagerController = function (piskelController) {
this.piskelController = piskelController;
this.palettes = this.retrieveUserPalettes();
this.originalPalettes = this.retrieveUserPalettes();
this.selectedPaletteId = null;
// Keep track of all spectrum instances created, to dispose them when closing the popup
this.spectrumContainers = [];
};
pskl.utils.inherit(ns.PaletteManagerController, ns.AbstractDialogController);
ns.PaletteManagerController.prototype.init = function () {
this.superclass.init.call(this);
this.palettesList = document.querySelector('.palette-manager-list');
this.paletteBody = document.querySelector('.palette-manager-details-body');
this.paletteHead = document.querySelector('.palette-manager-details-head');
this.createButton = document.querySelector('.palette-manager-actions-button[data-action="create"]');
this.saveAllButton = document.querySelector('.palette-manager-actions-button[data-action="save-all"]');
this.colorCardTemplate = pskl.utils.Template.get('palette-color-card-template');
this.newColorTemplate = pskl.utils.Template.get('palette-new-color-template');
this.paletteHeadTemplate = pskl.utils.Template.get('palette-details-head-template');
// Events
this.palettesList.addEventListener('click', this.onPaletteListClick.bind(this));
// Delegated event listener for events repeated on all cards
this.paletteBody.addEventListener('click', this.delegatedPaletteBodyClick.bind(this));
this.paletteHead.addEventListener('click', this.delegatedPaletteHeadClick.bind(this));
this.createButton.addEventListener('click', this.onCreateClick_.bind(this));
this.saveAllButton.addEventListener('click', this.saveAll.bind(this));
// Init markup
this.createPaletteListMarkup();
if (this.palettes.length > 0) {
this.selectPalette(this.palettes[0].id);
} else {
this.createPalette('New palette');
}
};
ns.PaletteManagerController.prototype.destroy = function () {
this.destroySpectrumPickers();
};
ns.PaletteManagerController.prototype.onCreateClick_ = function (evt) {
this.createPalette();
};
ns.PaletteManagerController.prototype.createPalette = function (name) {
if (!name) {
name = window.prompt('Please enter a name for your palette', 'New palette');
}
if (name) {
var palette = this.createPaletteObject(name);
this.palettes.push(palette);
this.createPaletteListMarkup();
this.selectPalette(palette.id);
}
};
ns.PaletteManagerController.prototype.createPaletteObject = function (name) {
return {
id : 'palette-' + Date.now() + '-' + Math.floor(Math.random()*1000),
name : name,
colors : []
};
};
ns.PaletteManagerController.prototype.redraw = function () {
this.createPaletteListMarkup();
this.selectPalette(this.selectedPaletteId);
};
ns.PaletteManagerController.prototype.selectPalette = function (paletteId) {
this.deselectCurrentPalette();
var paletteListItem = this.palettesList.querySelector('[data-palette-id='+paletteId+']');
if (paletteListItem) {
this.selectedPaletteId = paletteId;
paletteListItem.classList.add(SELECTED_CLASSNAME);
this.refreshPaletteDetails();
}
};
ns.PaletteManagerController.prototype.refreshPaletteDetails = function () {
this.createPaletteHeadMarkup();
this.createPaletteBodyMarkup();
this.initPaletteDetailsEvents();
this.initPaletteCardsSpectrum();
};
ns.PaletteManagerController.prototype.createPaletteListMarkup = function () {
var html = this.palettes.map(function (palette) {
var paletteCopy = {
id : palette.id,
name : this.isPaletteModified(palette) ? palette.name + " *" : palette.name
};
return pskl.utils.Template.replace('<li data-palette-id="{{id}}">{{name}}</li>', paletteCopy);
}.bind(this)).join('');
this.palettesList.innerHTML = html;
};
/**
* Fill the palette body container with color cards for the selected palette
*/
ns.PaletteManagerController.prototype.createPaletteHeadMarkup = function () {
var palette = this.getSelectedPalette();
var dict = {
'name' : palette.name,
'save:disabled' : !this.isPaletteModified(palette),
'revert:disabled' : !this.isPaletteModified(palette),
'delete:disabled' : this.palettes.length < 2
};
var html = pskl.utils.Template.replace(this.paletteHeadTemplate, dict);
this.paletteHead.innerHTML = html;
};
ns.PaletteManagerController.prototype.isPaletteModified = function (palette) {
var isModified = false;
var originalPalette = this.getPaletteById(palette.id, this.originalPalettes);
if (originalPalette) {
var differentName = originalPalette.name !== palette.name;
var differentColors = palette.colors.join('') !== originalPalette.colors.join('');
isModified = differentName || differentColors;
} else {
isModified = true;
}
return isModified;
};
/**
* Fill the palette body container with color cards for the selected palette
*/
ns.PaletteManagerController.prototype.createPaletteBodyMarkup = function () {
var palette = this.getSelectedPalette();
var html = this.getColorCardsMarkup(palette.colors);
html += pskl.utils.Template.replace(this.newColorTemplate, {classname : NEW_COLOR_CLASS});
this.paletteBody.innerHTML = html;
};
ns.PaletteManagerController.prototype.initPaletteDetailsEvents = function () {
// New Card click event
var newCard = this.paletteBody.querySelector('.' + NEW_COLOR_CLASS);
newCard.addEventListener('click', this.onNewCardClick.bind(this));
if (this.palettes.length < 2) {
var deleteButton = this.paletteHead.querySelector('.palette-manager-palette-button[data-action="delete"]');
deleteButton.setAttribute("disabled", "disabled");
}
};
ns.PaletteManagerController.prototype.onNewCardClick = function () {
var color;
var palette = this.getSelectedPalette();
if (palette && palette.colors.length > 0) {
color = palette.colors[palette.colors.length-1];
} else {
color = '#FFFFFF';
}
this.addColorInSelectedPalette(color);
};
ns.PaletteManagerController.prototype.delegatedPaletteBodyClick = function (event) {
var target = event.target;
if (target.classList.contains(CLOSE_ICON_CLASS)) {
var colorId = parseInt(target.parentNode.dataset.colorId, 10);
this.removeColorInSelectedPalette(colorId);
}
};
ns.PaletteManagerController.prototype.delegatedPaletteHeadClick = function (event) {
var target = event.target;
if (target.classList.contains(EDIT_NAME_CLASS)) {
this.renameSelectedPalette();
} else if (target.classList.contains('palette-manager-palette-button')) {
var action = target.dataset.action;
if (action === 'save') {
this.savePalette(this.getSelectedPalette().id);
this.redraw();
} else if (action === 'revert') {
this.revertChanges();
} else if (action === 'delete') {
this.deleteSelectedPalette();
}
}
};
ns.PaletteManagerController.prototype.getSpectrumSelector_ = function () {
return ':not(.' + NEW_COLOR_CLASS + ')>.palette-manager-color-square';
};
ns.PaletteManagerController.prototype.initPaletteCardsSpectrum = function () {
var oSelf = this;
var container = $(this.getSpectrumSelector_());
container.spectrum({
clickoutFiresChange : true,
showInput: true,
showButtons: false,
change : function (color) {
var target = this;
var colorId = parseInt(target.parentNode.dataset.colorId, 10);
oSelf.updateColorInSelectedPalette(colorId, color);
},
beforeShow : function() {
var target = this;
var colorId = parseInt(target.parentNode.dataset.colorId, 10);
var palette = oSelf.getSelectedPalette();
var color = palette.colors[colorId];
container.spectrum("set", color);
}
});
this.spectrumContainers.push(container);
};
/**
* Destroy all spectrum instances generated by the palette manager
*/
ns.PaletteManagerController.prototype.destroySpectrumPickers = function () {
this.spectrumContainers.forEach(function (container) {
container.spectrum("destroy");
});
this.spectrumContainers = [];
};
ns.PaletteManagerController.prototype.updateColorInSelectedPalette = function (colorId, color) {
var palette = this.getSelectedPalette();
var hexColor = '#' + (color.toHex().toUpperCase());
palette.colors.splice(colorId, 1, hexColor);
this.redraw();
};
ns.PaletteManagerController.prototype.addColorInSelectedPalette = function (color) {
var selectedPalette = this.getSelectedPalette();
selectedPalette.colors.push(color);
this.redraw();
};
ns.PaletteManagerController.prototype.removeColorInSelectedPalette = function (colorId) {
var palette = this.getSelectedPalette();
palette.colors.splice(colorId, 1);
this.redraw();
};
ns.PaletteManagerController.prototype.renameSelectedPalette = function () {
var palette = this.getSelectedPalette();
var name = window.prompt('Please enter a new name for palette "' + palette.name + '"', palette.name);
if (name) {
palette.name = name;
this.redraw();
}
};
ns.PaletteManagerController.prototype.getSelectedPalette = function () {
return this.getPaletteById(this.selectedPaletteId, this.palettes);
};
ns.PaletteManagerController.prototype.getColorCardsMarkup = function (colors) {
var html = colors.map(function (color, index) {
var dict = {
colorId : index,
hex : color,
rgb : tinycolor(color).toRgbString(),
hsl : tinycolor(color).toHslString()
};
return pskl.utils.Template.replace(this.colorCardTemplate, dict);
}.bind(this)).join('');
return html;
};
ns.PaletteManagerController.prototype.getPaletteById = function (paletteId, palettes) {
var match = null;
palettes.forEach(function (palette) {
if (palette.id === paletteId) {
match = palette;
}
});
return match;
};
ns.PaletteManagerController.prototype.removePaletteById = function (paletteId, palettes) {
var palette = this.getPaletteById(paletteId, palettes);
if (palette) {
var index = palettes.indexOf(palette);
palettes.splice(index, 1);
}
};
ns.PaletteManagerController.prototype.deselectCurrentPalette = function () {
var selectedItem = this.palettesList.querySelector('.' + SELECTED_CLASSNAME);
if (selectedItem) {
this.selectedPaletteId = null;
selectedItem.classList.remove(SELECTED_CLASSNAME);
}
};
ns.PaletteManagerController.prototype.revertChanges = function () {
var palette = this.getSelectedPalette();
var originalPalette = this.getPaletteById(palette.id, this.originalPalettes);
palette.name = originalPalette.name;
palette.colors = originalPalette.colors.slice(0);
this.redraw();
};
ns.PaletteManagerController.prototype.deleteSelectedPalette = function () {
var palette = this.getSelectedPalette();
if (this.palettes.length > 1) {
if (window.confirm('Are you sure you want to delete "' + palette.name + '" ?')) {
this.removePaletteById(palette.id, this.palettes);
this.removePaletteById(palette.id, this.originalPalettes);
this.persistToLocalStorage();
this.createPaletteListMarkup();
this.selectPalette(this.palettes[0].id);
}
}
};
ns.PaletteManagerController.prototype.onPaletteListClick = function (event) {
var target = event.target;
if (target.dataset.paletteId) {
this.selectPalette(target.dataset.paletteId);
}
};
ns.PaletteManagerController.prototype.saveAll = function () {
this.palettes.forEach(function (palette) {
this.savePalette(palette.id);
}.bind(this));
this.redraw();
};
ns.PaletteManagerController.prototype.savePalette = function (paletteId) {
var palette = this.getPaletteById(paletteId, this.palettes);
var originalPalette = this.getPaletteById(paletteId, this.originalPalettes);
if (originalPalette) {
originalPalette.name = palette.name;
originalPalette.colors = palette.colors;
} else {
this.originalPalettes.push(palette);
}
this.persistToLocalStorage();
$.publish(Events.SHOW_NOTIFICATION, [{"content": "Palette " + palette.name + " successfully saved !"}]);
window.setTimeout($.publish.bind($, Events.HIDE_NOTIFICATION), 2000);
};
ns.PaletteManagerController.prototype.persistToLocalStorage = function () {
window.localStorage.setItem('piskel.palettes', JSON.stringify(this.originalPalettes));
this.originalPalettes = this.retrieveUserPalettes();
$.publish(Events.PALETTE_LIST_UPDATED);
};
ns.PaletteManagerController.prototype.retrieveUserPalettes = function () {
var palettesString = window.localStorage.getItem('piskel.palettes');
return JSON.parse(palettesString) || [];
};
})();

38
src/js/model/Palette.js Normal file
View File

@ -0,0 +1,38 @@
(function () {
var ns = $.namespace('pskl.model');
ns.Palette = function (id, name, colors) {
this.id = id;
this.name = name;
this.colors = colors;
};
ns.Palette.fromObject = function (paletteObj) {
var colors = paletteObj.colors.slice(0 , paletteObj.colors.length);
return new ns.Palette(paletteObj.id, paletteObj.name, colors);
};
ns.Palette.prototype.get = function (index) {
return this.colors[index];
};
ns.Palette.prototype.set = function (index, color) {
this.colors[index] = color;
};
ns.Palette.prototype.add = function (color) {
this.colors.push(color);
};
ns.Palette.prototype.size = function () {
return this.colors.length;
};
ns.Palette.prototype.removeAt = function (index) {
this.colors.splice(index, 1);
};
ns.Palette.prototype.move = function (oldIndex, newIndex) {
this.colors.splice(newIndex, 0, this.colors.splice(oldIndex, 1)[0]);
};
})();

View File

@ -0,0 +1,61 @@
(function () {
var ns = $.namespace('pskl.service');
ns.PaletteService = function () {
this.palettes = [];
this.localStorageService = window.localStorage;
};
ns.PaletteService.prototype.init = function () {};
ns.PaletteService.prototype.getPalettes = function () {
var palettesString = this.localStorageService.getItem('piskel.palettes');
return JSON.parse(palettesString) || [];
};
ns.PaletteService.prototype.getPaletteById = function (paletteId) {
var palettes = this.getPalettes();
return this.findPaletteInArray_(paletteId, palettes);
};
ns.PaletteService.prototype.savePalette = function (palette) {
var palettes = this.getPalettes();
var existingPalette = this.findPaletteInArray_(palette.id, palettes);
if (existingPalette) {
var currentIndex = palettes.indexOf(existingPalette);
palettes.splice(currentIndex, 1, palette);
} else {
palettes.push(palette);
}
this.savePalettes_(palettes);
$.publish(Events.SHOW_NOTIFICATION, [{"content": "Palette " + palette.name + " successfully saved !"}]);
window.setTimeout($.publish.bind($, Events.HIDE_NOTIFICATION), 2000);
};
ns.PaletteService.prototype.deletePaletteById = function (id) {
var palettes = this.getPalettes();
var filteredPalettes = palettes.filter(function (palette) {
return palette.id !== id;
});
this.savePalettes_(filteredPalettes);
};
ns.PaletteService.prototype.savePalettes_ = function (palettes) {
this.localStorageService.setItem('piskel.palettes', JSON.stringify(palettes));
$.publish(Events.PALETTE_LIST_UPDATED);
};
ns.PaletteService.prototype.findPaletteInArray_ = function (paletteId, palettes) {
var match = null;
palettes.forEach(function (palette) {
if (palette.id === paletteId) {
match = palette;
}
});
return match;
};
})();

17
src/js/utils/Uuid.js Normal file
View File

@ -0,0 +1,17 @@
(function(){
var ns = $.namespace('pskl.utils');
var s4 = function () {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
};
ns.Uuid = {
generate : function () {
return 'ss-s-s-s-sss'.replace(/s/g, function () {
return s4();
});
}
};
})();

View File

@ -25,6 +25,7 @@
"js/utils/PiskelFileUtils.js", "js/utils/PiskelFileUtils.js",
"js/utils/Template.js", "js/utils/Template.js",
"js/utils/UserSettings.js", "js/utils/UserSettings.js",
"js/utils/Uuid.js",
"js/utils/Xhr.js", "js/utils/Xhr.js",
"js/utils/serialization/Serializer.js", "js/utils/serialization/Serializer.js",
"js/utils/serialization/Deserializer.js", "js/utils/serialization/Deserializer.js",
@ -50,6 +51,7 @@
"js/model/Layer.js", "js/model/Layer.js",
"js/model/piskel/Descriptor.js", "js/model/piskel/Descriptor.js",
"js/model/frame/CachedFrameProcessor.js", "js/model/frame/CachedFrameProcessor.js",
"js/model/Palette.js",
"js/model/Piskel.js", "js/model/Piskel.js",
// Selection // Selection
@ -99,9 +101,7 @@
// Dialogs sub-controllers // Dialogs sub-controllers
"js/controller/dialogs/AbstractDialogController.js", "js/controller/dialogs/AbstractDialogController.js",
"js/controller/dialogs/PaletteManagerController.js",
"js/controller/dialogs/CreatePaletteController.js", "js/controller/dialogs/CreatePaletteController.js",
"js/controller/dialogs/CreatePaletteMethodController.js",
"js/controller/dialogs/ImportImageController.js", "js/controller/dialogs/ImportImageController.js",
"js/controller/dialogs/BrowseLocalController.js", "js/controller/dialogs/BrowseLocalController.js",
@ -119,6 +119,7 @@
"js/service/BackupService.js", "js/service/BackupService.js",
"js/service/BeforeUnloadService.js", "js/service/BeforeUnloadService.js",
"js/service/HistoryService.js", "js/service/HistoryService.js",
"js/service/PaletteService.js",
"js/service/SavedStatusService.js", "js/service/SavedStatusService.js",
"js/service/keyboard/ShortcutService.js", "js/service/keyboard/ShortcutService.js",
"js/service/keyboard/KeycodeTranslator.js", "js/service/keyboard/KeycodeTranslator.js",

View File

@ -14,10 +14,8 @@
"css/color-picker-slider.css", "css/color-picker-slider.css",
"css/dialogs.css", "css/dialogs.css",
"css/dialogs-import-image.css", "css/dialogs-import-image.css",
"css/dialogs-manage-palettes.css",
"css/dialogs-browse-local.css", "css/dialogs-browse-local.css",
"css/dialogs-create-palette.css", "css/dialogs-create-palette.css",
"css/dialogs-create-palette-method.css",
"css/toolbox.css", "css/toolbox.css",
"css/toolbox-layers-list.css", "css/toolbox-layers-list.css",
"css/toolbox-palettes-list.css", "css/toolbox-palettes-list.css",

View File

@ -1,28 +0,0 @@
<div class="dialog-wrapper">
<h3 class="dialog-head">
Create palette
<span class="palette-manager-close dialog-close">X</span>
</h3>
<div style="padding:10px 20px; font-size:1.3em">
Select your creation method :
<ul style="margin:10px 0" class="create-palette-method-list">
<li class="create-palette-method-item">
<input type="radio" name="palette-creation-mode" id="palette-creation-mode-manual" value="manual" checked="checked">
<label for="palette-creation-mode-manual">Manual</label>
</li>
<li class="create-palette-method-item">
<input type="radio" name="palette-creation-mode" id="palette-creation-mode-import" value="import">
<label for="palette-creation-mode-import">Import from existing file or image</label><br>
</li>
<li class="create-palette-method-item">
<input type="radio" name="palette-creation-mode" id="palette-creation-mode-palette" value="palette">
<label for="palette-creation-mode-palette">Clone existing palette</label>
<select class="palettes-list-select" style="margin:3px 0;">
<option value="current-colors">Current colors</option>
</select>
</li>
</ul>
<button class="button button-primary create-palette-method-continue" style="float:right">Continue</button>
<button class="button create-palette-method-cancel" style="float:right">Cancel</button>
</div>
</div>

View File

@ -4,12 +4,11 @@
<span class="dialog-close">X</span> <span class="dialog-close">X</span>
</h3> </h3>
<div class="dialog-create-palette" style="font-size:1.3em"> <div class="dialog-create-palette" style="font-size:1.3em">
<form action="" method="POST" name="create-palette-form">
<div class="create-palette-section form-section"> <div class="create-palette-section form-section">
<span class="dialog-create-palette-name">Name :</span><input type="text" class="textfield" name="palette-name" placeholder="New palette"/> <span class="dialog-create-palette-name">Name :</span><input type="text" class="textfield" name="palette-name" placeholder="palette name ..."/>
</div> </div>
<div class="colors-container"> <div class="colors-container">
<div class="colors-list"></div> <ul class="colors-list"></ul>
<div class="color-picker-container"> <div class="color-picker-container">
<div class="color-picker-spectrum"></div> <div class="color-picker-spectrum"></div>
<div class="color-picker-slider"> <div class="color-picker-slider">
@ -46,8 +45,7 @@
<div class="color-preview"></div> <div class="color-preview"></div>
</div> </div>
</div> </div>
<input type="submit" name="create-palette-submit" class="button button-primary create-palette-submit" value="Save" /> <button type="button" name="create-palette-submit" class="button button-primary create-palette-submit">Save</button>
</form>
</div> </div>
<script type="text/template" id="color-picker-slider-template"> <script type="text/template" id="color-picker-slider-template">
@ -58,4 +56,14 @@
</div> </div>
</script> </script>
<script type="text/template" id="create-palette-color-template">
<li
class="create-palette-color {{:selected}} {{:light-color}}"
style="background:{{color}}"
data-palette-index="{{index}}"
data-palette-color="{{color}}">
<div class="create-palette-remove-color">X</div>
</li>
</script>
</div> </div>

View File

@ -1,57 +0,0 @@
<div class="palette-manager-wrapper">
<h3 class="palette-manager-head dialog-head">
Palette manager
<span class="dialog-close">X</span>
</h3>
<div class="palette-manager-body">
<div class="palette-manager-drawer">
<div class="palette-manager-actions">
<button type="button" class="palette-manager-actions-button button " data-action="create">Create</button>
<button type="button" class="palette-manager-actions-button button " data-action="save-all">Save all</button>
</div>
<ul class="palette-manager-list">
</ul>
</div>
<div class="palette-manager-details">
<div class="palette-manager-details-head"></div>
<div class="palette-manager-details-body"></div>
</div>
</div>
</div>
<script type="text/template" id="palette-details-head-template">
<span class="palette-manager-details-head-name">{{name}}</span>
<span class="action-icon edit-icon" title="edit name">&nbsp;</span>
<div class="palette-manager-details-head-actions">
<button class="palette-manager-palette-button button button-primary" {{save:disabled}} data-action="save" type="button">Save</button>
<button class="palette-manager-palette-button button " {{revert:disabled}} data-action="revert" type="button">Revert</button>
<button class="palette-manager-palette-button button " {{delete:disabled}} data-action="delete" type="button">Delete</button>
</div>
</script>
<script type="text/template" id="palette-color-card-template">
<div class="palette-manager-color-card" data-color-id="{{colorId}}">
<span class="palette-manager-delete-card" title="remove this color">X</span>
<div class="palette-manager-color-square" style="background-color:{{hex}}"></div>
<div class="palette-manager-color-details allow-user-select">
<ul>
<li>{{hex}}</li>
<li>{{rgb}}</li>
<li>{{hsl}}</li>
</ul>
</div>
</div>
</script>
<script type="text/template" id="palette-new-color-template">
<div class="palette-manager-color-card {{classname}}">
<div class="palette-manager-color-square">Add</div>
<div class="palette-manager-color-details">
<ul>
<li>Hex</li>
<li>RGB</li>
<li>HSL</li>
</ul>
</div>
</div>
</script>

View File

@ -1,18 +1,30 @@
<div class="toolbox-container palettes-list-container"> <div class="toolbox-container palettes-list-container">
<h3 class="toolbox-title palettes-title" <h3 class="toolbox-title palettes-title"
style="overflow: hidden;height: 36px;box-sizing: border-box;border-bottom: 1px solid #444;"> style="overflow: hidden;height: 36px;box-sizing: border-box;border-bottom: 1px solid #444;">
<span style="line-height:20px ">Palettes</span> <span style="line-height:20px ">Palettes</span>
<div <div
class="button button-primary create-palette-button" class="button button-primary create-palette-button"
title="Create new palette" title="Create new palette"
rel="tooltip" rel="tooltip"
data-placement="top" data-placement="top"
style="width:20px; height:20px; float:right; font-size:1.1em">+</div> style="width:20px; height:20px; float:right; font-size:1.1em">+</div>
</h3> </h3>
<div <div
class="palettes-actions" class="palette-actions"
style="background-color:#3f3f3f; border-bottom:#222; height:24px; padding:0 3px;"> style="background-color:#3f3f3f; border-bottom:#222; height:24px; padding:0 3px;">
<select class="palettes-list-select" style="margin:3px 0;"></select> <select class="palettes-list-select" style="margin:3px 0;"></select>
<div class="palette-action palette-action-download"
title="Download palette"
rel="tooltip"
data-placement="top">dl</div>
<div class="palette-action palette-action-delete"
title="Delete palette"
rel="tooltip"
data-placement="top">d</div>
<div class="palette-action palette-action-edit"
title="Edit palette"
rel="tooltip"
data-placement="top">e</div>
</div> </div>
<div class="palettes-list-colors"></div> <div class="palettes-list-colors"></div>
<script type="text/template" id="palette-color-template"> <script type="text/template" id="palette-color-template">

View File

@ -0,0 +1,23 @@
describe("Palette", function() {
beforeEach(function() {});
afterEach(function() {});
it("moves colors correctly", function() {
// when
var colors = [
'#000000',
'#111111',
'#222222'
];
var palette = new pskl.model.Palette('id', 'name', colors);
// then
palette.move(2,0);
// verify
expect(palette.get(0)).toBe('#222222');
expect(palette.get(1)).toBe('#000000');
expect(palette.get(2)).toBe('#111111');
});
});

View File

@ -0,0 +1,144 @@
describe("Palette Service", function() {
var paletteService = null;
var localStorage = {};
var localStorageService;
var addPalette = function (id, name, color) {
var palette = new pskl.model.Palette(id, name, [color]);
paletteService.savePalette(palette);
};
var verifyPaletteIsStored = function (paletteId) {
var palette = paletteService.getPaletteById(paletteId);
expect(palette).not.toBeNull();
return palette;
};
var verifyPaletteIsNotStored = function (paletteId) {
var palette = paletteService.getPaletteById(paletteId);
expect(palette).toBeNull();
};
beforeEach(function() {
localStorage = {};
localStorageService = {
getItem : function (key) {
if (localStorage.hasOwnProperty(key)) {
return localStorage[key];
} else {
return null;
}
},
setItem : function (key, item) {
localStorage[key] = item;
}
};
paletteService = new pskl.service.PaletteService();
paletteService.localStorageService = localStorageService;
});
it("returns an empty array when no palette is stored", function() {
spyOn(localStorageService, 'getItem').and.callThrough();
var palettes = paletteService.getPalettes();
expect(Array.isArray(palettes)).toBe(true);
expect(palettes.length).toBe(0);
expect(localStorageService.getItem).toHaveBeenCalled();
});
it("can store a palette", function() {
// when
spyOn(localStorageService, 'setItem').and.callThrough();
var paletteId = 'palette-id';
var paletteName = 'palette-name';
var paletteColor = '#001122';
// then
addPalette(paletteId, paletteName, paletteColor);
var palettes = paletteService.getPalettes();
// verify
expect(localStorageService.setItem).toHaveBeenCalled();
expect(Array.isArray(palettes)).toBe(true);
expect(palettes.length).toBe(1);
var retrievedPalette = paletteService.getPaletteById(paletteId);
expect(retrievedPalette).toBeDefined();
expect(retrievedPalette.id).toBe(paletteId);
expect(retrievedPalette.name).toBe(paletteName);
var colors = retrievedPalette.colors;
expect(Array.isArray(colors)).toBe(true);
expect(colors.length).toBe(1);
var color = colors[0];
expect(color).toBe(paletteColor);
});
it("updates a palette", function() {
// when
var paletteId = 'palette-id';
var paletteName = 'palette-name';
var paletteColor1 = '#001122';
var paletteColor2 = '#334455';
// then
addPalette(paletteId, paletteName, paletteColor1);
addPalette(paletteId, paletteName, paletteColor2);
// verify
var palettes = paletteService.getPalettes();
expect(palettes.length).toBe(1);
var retrievedPalette = paletteService.getPaletteById(paletteId);
var color = retrievedPalette.colors[0];
expect(color).toBe(paletteColor2);
});
it("can delete a palette", function() {
// when
addPalette('palette-id', 'palette-name', ['#001122']);
// then
paletteService.deletePaletteById('palette-id');
// verify
var palettes = paletteService.getPalettes();
expect(palettes.length).toBe(0);
});
it("attempts to delete unexisting palette without side effect", function() {
// when
addPalette('palette-id', 'palette-name', ['#001122']);
// then
var palettes = paletteService.getPalettes();
paletteService.deletePaletteById('some-other-palette-id');
// verify
expect(palettes.length).toBe(1);
});
it("deletes the correct palette when several palettes are stored", function() {
// when
addPalette('palette-id-0', 'palette-name-0', ['#000000']);
addPalette('palette-id-1', 'palette-name-1', ['#111111']);
addPalette('palette-id-2', 'palette-name-2', ['#222222']);
// then
paletteService.deletePaletteById('palette-id-1');
// verify
var palettes = paletteService.getPalettes();
expect(palettes.length).toBe(2);
verifyPaletteIsStored('palette-id-0');
verifyPaletteIsNotStored('palette-id-1');
verifyPaletteIsStored('palette-id-2');
});
});

27
test/js/utils/UuidTest.js Normal file
View File

@ -0,0 +1,27 @@
describe("UUID Generator", function() {
beforeEach(function() {});
afterEach(function() {});
it("returns valid uuids", function() {
// when
// then
var uuid1 = pskl.utils.Uuid.generate();
var uuid2 = pskl.utils.Uuid.generate();
// verify
expect(typeof uuid1).toBe("string");
expect(uuid1.length).toBe(36);
var splits = uuid1.split('-');
expect(splits.length).toBe(5);
expect(splits[0].length).toBe(8);
expect(splits[1].length).toBe(4);
expect(splits[2].length).toBe(4);
expect(splits[3].length).toBe(4);
expect(splits[4].length).toBe(12);
expect(uuid1).not.toBe(uuid2);
});
});