Add save as button

This commit is contained in:
jdescottes 2015-04-23 23:59:05 +02:00
parent c570d8fd75
commit 473bd4705c
6 changed files with 120 additions and 59 deletions

3
.gitignore vendored
View File

@ -5,6 +5,9 @@
node_modules
npm-debug.log
# node webkit cache
cache
# sublime text stuff (the -project should actually be shared, but then we'd have to share the same disk location)
*.sublime-project
*.sublime-workspace

View File

@ -14,64 +14,69 @@
// timestamp used to generate unique name when saving as .piskel
this.timestamp = new Date();
this.insertPartials_();
// Only available in app-engine mode
this.piskelName = document.querySelector('.piskel-name');
this.saveOnlineStatus = document.querySelector('#save-online-status');
this.saveFileStatus = document.querySelector('#save-file-status');
this.descriptionInput = document.querySelector('#save-description');
this.nameInput = document.querySelector('#save-name');
this.saveOnlineButton = document.querySelector('#save-online-button');
this.isPublicCheckbox = document.querySelector('input[name=save-public-checkbox]');
var descriptor = this.piskelController.getPiskel().getDescriptor();
this.descriptionInput = document.querySelector('#save-description');
this.descriptionInput.value = descriptor.description;
this.isPublicCheckbox = document.querySelector('input[name=save-public-checkbox]');
this.nameInput.value = descriptor.name;
if (descriptor.isPublic) {
this.isPublicCheckbox.setAttribute('checked', true);
}
if (pskl.utils.Environment.detectNodeWebkit()) {
// hide 'save in browser'
var saveInBrowserSection = document.querySelector('#save-in-browser');
saveInBrowserSection.style.display = 'none';
this.addEventListener('#save-as-button', 'click', this.saveAs_);
}
this.addEventListener('#save-file-button', 'click', this.saveFile_);
this.addEventListener('#save-browser-button', 'click', this.saveLocal_);
this.saveOnlineButton = document.querySelector('#save-online-button');
this.addEventListener(this.saveOnlineButton, 'click', this.saveOnline_);
this.addEventListener('form[name=save-form]', 'submit', this.onSaveFormSubmit_);
this.nameInput = document.querySelector('#save-name');
this.nameInput.value = descriptor.name;
this.addEventListener(this.nameInput, 'keyup', this.updateLocalStatusFilename_);
if (pskl.app.isLoggedIn()) {
this.saveOnlineStatus.innerHTML = pskl.utils.Template.get('save-online-status-partial');
pskl.utils.Template.insert(this.saveOnlineStatus, 'beforeend', 'save-online-status-partial');
} else {
this.saveOnlineStatus.innerHTML = pskl.utils.Template.get('save-please-login-partial');
pskl.utils.Template.insert(this.saveOnlineStatus, 'beforeend', 'save-please-login-partial');
var container = document.querySelector('.setting-save-section');
container.classList.add('anonymous');
}
this.updateLocalStatusFilename_();
};
ns.SaveController.prototype.updateLocalStatusFilename_ = function () {
ns.SaveController.prototype.insertPartials_ = function () {
var partials = [];
if (pskl.utils.Environment.detectNodeWebkit()) {
var fileName = this.piskelController.getSavePath();
if (fileName !== null) {
this.saveFileStatus.innerHTML = pskl.utils.Template.getAndReplace('save-file-status-desktop-template', {
name : this.piskelController.getSavePath()
});
}
partials = [
'save-file-nw-partial',
'save-localstorage-partial',
'save-online-partial'
];
} else if (pskl.app.isLoggedIn()) {
partials = [
'save-online-partial',
'save-localstorage-partial',
'save-file-partial'
];
} else {
this.saveFileStatus.innerHTML = pskl.utils.Template.getAndReplace('save-file-status-template', {
name : this.getLocalFilename_()
});
partials = [
'save-file-partial',
'save-localstorage-partial',
'save-online-partial'
];
}
var container = document.querySelector('.save-form');
partials.forEach(function (partial) {
pskl.utils.Template.insert(container, 'beforeend', partial);
});
};
ns.SaveController.prototype.getLocalFilename_ = function () {
@ -141,12 +146,16 @@
ns.SaveController.prototype.saveFile_ = function () {
// detect if this is running in NodeWebkit
if (pskl.utils.Environment.detectNodeWebkit()) {
this.saveFileDesktop_();
pskl.app.desktopStorageService.save();
} else {
this.saveFileBrowser_();
}
};
ns.SaveController.prototype.saveAs_ = function () {
pskl.app.desktopStorageService.savePiskelAs();
};
ns.SaveController.prototype.saveFileBrowser_ = function () {
this.beforeSaving_();
pskl.utils.BlobUtils.stringToBlob(pskl.app.piskelController.serialize(), function(blob) {
@ -156,10 +165,6 @@
}.bind(this), 'application/piskel+json');
};
ns.SaveController.prototype.saveFileDesktop_ = function () {
pskl.app.desktopStorageService.save();
};
ns.SaveController.prototype.getName = function () {
return this.nameInput.value;
};

View File

@ -21,7 +21,7 @@
if (savePath) {
this.savePiskel(savePath);
} else {
this.savePiskelAs(savePath);
this.savePiskelAs();
}
};
@ -47,16 +47,32 @@
});
};
ns.DesktopStorageService.prototype.savePiskelAs = function (savePath) {
ns.DesktopStorageService.prototype.savePiskelAs = function () {
var serialized = this.piskelController.serialize();
var name = this.piskelController.getPiskel().getDescriptor().name;
// TODO: if there is already a file path, use it for the dialog's
// working directory and filename
pskl.utils.FileUtilsDesktop.saveAs(serialized, null, 'piskel', function (selectedSavePath) {
pskl.utils.FileUtilsDesktop.saveAs(serialized, name, 'piskel', function (selectedSavePath) {
this.piskelController.setSavePath(selectedSavePath);
var filename = this.extractFilename_(selectedSavePath);
if (filename) {
var descriptor = this.piskelController.getPiskel().getDescriptor();
descriptor.name = filename;
this.piskelController.getPiskel().setDescriptor(descriptor);
}
this.onSaveSuccess_();
}.bind(this));
};
ns.DesktopStorageService.prototype.extractFilename_ = function (savePath) {
var matches = (/[\/\\]([^\/\\]*)\.piskel$/gi).exec(savePath);
if (matches && matches[1]) {
return matches[1];
}
};
ns.DesktopStorageService.prototype.onSaveSuccess_ = function () {
var savePath = this.piskelController.getSavePath();
$.publish(Events.CLOSE_SETTINGS_DRAWER);

View File

@ -5,6 +5,8 @@
e.stopPropagation();
};
var CONFIRM_OVERRIDE = 'File already exists, do you want to override it ?';
ns.FileUtilsDesktop = {
chooseFileDialog: function (callback) {
@ -17,37 +19,44 @@
$chooser.trigger('click');
},
addExtensionIfNeeded : function (filename, extension) {
if (typeof extension == 'string') {
if (extension[0] !== '.') {
extension = '.' + extension;
}
var hasExtension = (filename.substring(filename.length - extension.length) === extension);
if (!hasExtension) {
filename += extension;
}
}
return filename;
},
/**
*
* @param content
* @param defaultFileName - file name to pre-populate the dialog
* @param defaultFilename - file name to pre-populate the dialog
* @param extension - if supplied, the selected extension will guaranteed to be on the filename -
* NOTE: there is a possible danger here... If the extension is added to a fileName, but there
* is already another file of the same name *with* the extension, it will get overwritten.
* @param callback
*/
saveAs: function (content, defaultFileName, extension, callback) {
saveAs: function (content, defaultFilename, extension, callback) {
// NodeWebkit has no js api for opening the save dialog.
// Instead, it adds two new attributes to the anchor tag: nwdirectory and nwsaveas
// (see: https://github.com/nwjs/nw.js/wiki/File-dialogs )
defaultFileName = defaultFileName || '';
var tagString = '<input type="file" nwsaveas="' + defaultFileName + '" nwworkingdir=""/>';
defaultFilename = defaultFilename || 'New Piskel';
defaultFilename = pskl.utils.FileUtilsDesktop.addExtensionIfNeeded(defaultFilename, extension);
var tagString = '<input type="file" accept=".piskel" nwsaveas="' + defaultFilename + '" nwworkingdir=""/>';
var $chooser = $(tagString);
$chooser.change(function (e) {
var filename = $(this).val();
if (typeof extension == 'string') {
if (extension[0] !== '.') {
extension = '.' + extension;
}
var hasExtension = (filename.substring(filename.length - extension.length) === extension);
if (!hasExtension) {
filename += extension;
}
}
filename = pskl.utils.FileUtilsDesktop.addExtensionIfNeeded(filename, extension);
pskl.utils.FileUtilsDesktop.saveToFile(content, filename, function () {
callback(filename);
});
});
$chooser.trigger('click');
},

View File

@ -21,6 +21,11 @@
return dummyEl.children[0];
},
insert : function (parent, position, templateId, dict) {
var html = pskl.utils.Template.getAndReplace(templateId, dict);
parent.insertAdjacentHTML(position, html);
},
getAndReplace : function (templateId, dict) {
var result = '';
var tpl = pskl.utils.Template.get(templateId);

View File

@ -1,5 +1,5 @@
<div class="settings-section setting-save-section">
<form action="" method="POST" name="save-form">
<form action="" method="POST" class="save-form" name="save-form">
<div class="settings-title">Describe your piskel</div>
<div class="settings-item">
<div class="settings-form-section" style="overflow:hidden">
@ -16,24 +16,47 @@
</label>
</div>
</div>
</form>
<!-- PARTIALS -->
<!-- save-online-partial -->
<script type="text/template" id="save-online-partial">
<div class="settings-title">Save online</div>
<div class="settings-item">
<input type="button" class="button button-primary" id="save-online-button" value="Save to your gallery" />
<div id="save-online-status" class="save-status"></div>
</div>
</script>
<!-- save-localstorage-partial -->
<script type="text/template" id="save-localstorage-partial">
<div id="save-in-browser">
<div class="settings-title">Save offline in Browser</div>
<div class="settings-item">
<input type="button" class="button button-primary" id="save-browser-button" value="Save in Browser" />
<div id="save-browser-status" class="save-status">Your piskel will be saved locally and will only be accessible from this browser.</div>
</div>
<div class="settings-title">Save offline in Browser</div>
<div class="settings-item">
<input type="button" class="button button-primary" id="save-browser-button" value="Save in Browser" />
<div id="save-browser-status" class="save-status">Your piskel will be saved locally and will only be accessible from this browser.</div>
</div>
</div>
</script>
<!-- save-file-partial -->
<script type="text/template" id="save-file-nw-partial">
<div class="settings-title">Save as File</div>
<div class="settings-item">
<input type="button" class="button button-primary" id="save-file-button" value="Save" />
<input type="button" class="button button-primary" id="save-as-button" value="Save as ..." />
<div id="save-file-status" class="save-status">Your sprite will be saved as a .piskel file.</div>
</div>
</script>
<script type="text/template" id="save-file-partial">
<div class="settings-title">Save offline as File</div>
<div class="settings-item">
<input type="button" class="button button-primary" id="save-file-button" value="Save as File" />
<div id="save-file-status" class="save-status"></div>
<input type="button" class="button button-primary" id="save-file-button" value="Save as ..." />
<div id="save-file-status" class="save-status">Your sprite will be downloaded as a .piskel file.</div>
</div>
</form>
</script>
<script type="text/template" id="save-please-login-partial">
<span>Login to <a href="http://piskelapp.com" target="_blank">piskelapp.com</a> to save and share your sprites online !</span>