mirror of
https://github.com/piskelapp/piskel.git
synced 2023-08-10 21:12:52 +03:00
Add save as button
This commit is contained in:
parent
c570d8fd75
commit
473bd4705c
3
.gitignore
vendored
3
.gitignore
vendored
@ -5,6 +5,9 @@
|
|||||||
node_modules
|
node_modules
|
||||||
npm-debug.log
|
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 text stuff (the -project should actually be shared, but then we'd have to share the same disk location)
|
||||||
*.sublime-project
|
*.sublime-project
|
||||||
*.sublime-workspace
|
*.sublime-workspace
|
||||||
|
@ -14,64 +14,69 @@
|
|||||||
// timestamp used to generate unique name when saving as .piskel
|
// timestamp used to generate unique name when saving as .piskel
|
||||||
this.timestamp = new Date();
|
this.timestamp = new Date();
|
||||||
|
|
||||||
|
this.insertPartials_();
|
||||||
|
|
||||||
// Only available in app-engine mode
|
// Only available in app-engine mode
|
||||||
this.piskelName = document.querySelector('.piskel-name');
|
this.piskelName = document.querySelector('.piskel-name');
|
||||||
|
|
||||||
this.saveOnlineStatus = document.querySelector('#save-online-status');
|
this.saveOnlineStatus = document.querySelector('#save-online-status');
|
||||||
this.saveFileStatus = document.querySelector('#save-file-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();
|
var descriptor = this.piskelController.getPiskel().getDescriptor();
|
||||||
this.descriptionInput = document.querySelector('#save-description');
|
|
||||||
this.descriptionInput.value = descriptor.description;
|
this.descriptionInput.value = descriptor.description;
|
||||||
|
this.nameInput.value = descriptor.name;
|
||||||
this.isPublicCheckbox = document.querySelector('input[name=save-public-checkbox]');
|
|
||||||
if (descriptor.isPublic) {
|
if (descriptor.isPublic) {
|
||||||
this.isPublicCheckbox.setAttribute('checked', true);
|
this.isPublicCheckbox.setAttribute('checked', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pskl.utils.Environment.detectNodeWebkit()) {
|
if (pskl.utils.Environment.detectNodeWebkit()) {
|
||||||
// hide 'save in browser'
|
this.addEventListener('#save-as-button', 'click', this.saveAs_);
|
||||||
var saveInBrowserSection = document.querySelector('#save-in-browser');
|
|
||||||
saveInBrowserSection.style.display = 'none';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.addEventListener('#save-file-button', 'click', this.saveFile_);
|
this.addEventListener('#save-file-button', 'click', this.saveFile_);
|
||||||
|
|
||||||
this.addEventListener('#save-browser-button', 'click', this.saveLocal_);
|
this.addEventListener('#save-browser-button', 'click', this.saveLocal_);
|
||||||
|
|
||||||
this.saveOnlineButton = document.querySelector('#save-online-button');
|
|
||||||
this.addEventListener(this.saveOnlineButton, 'click', this.saveOnline_);
|
this.addEventListener(this.saveOnlineButton, 'click', this.saveOnline_);
|
||||||
|
|
||||||
this.addEventListener('form[name=save-form]', 'submit', this.onSaveFormSubmit_);
|
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()) {
|
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 {
|
} 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');
|
var container = document.querySelector('.setting-save-section');
|
||||||
container.classList.add('anonymous');
|
container.classList.add('anonymous');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updateLocalStatusFilename_();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.SaveController.prototype.updateLocalStatusFilename_ = function () {
|
ns.SaveController.prototype.insertPartials_ = function () {
|
||||||
|
var partials = [];
|
||||||
if (pskl.utils.Environment.detectNodeWebkit()) {
|
if (pskl.utils.Environment.detectNodeWebkit()) {
|
||||||
var fileName = this.piskelController.getSavePath();
|
partials = [
|
||||||
if (fileName !== null) {
|
'save-file-nw-partial',
|
||||||
this.saveFileStatus.innerHTML = pskl.utils.Template.getAndReplace('save-file-status-desktop-template', {
|
'save-localstorage-partial',
|
||||||
name : this.piskelController.getSavePath()
|
'save-online-partial'
|
||||||
});
|
];
|
||||||
}
|
} else if (pskl.app.isLoggedIn()) {
|
||||||
|
partials = [
|
||||||
|
'save-online-partial',
|
||||||
|
'save-localstorage-partial',
|
||||||
|
'save-file-partial'
|
||||||
|
];
|
||||||
} else {
|
} else {
|
||||||
this.saveFileStatus.innerHTML = pskl.utils.Template.getAndReplace('save-file-status-template', {
|
partials = [
|
||||||
name : this.getLocalFilename_()
|
'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 () {
|
ns.SaveController.prototype.getLocalFilename_ = function () {
|
||||||
@ -141,12 +146,16 @@
|
|||||||
ns.SaveController.prototype.saveFile_ = function () {
|
ns.SaveController.prototype.saveFile_ = function () {
|
||||||
// detect if this is running in NodeWebkit
|
// detect if this is running in NodeWebkit
|
||||||
if (pskl.utils.Environment.detectNodeWebkit()) {
|
if (pskl.utils.Environment.detectNodeWebkit()) {
|
||||||
this.saveFileDesktop_();
|
pskl.app.desktopStorageService.save();
|
||||||
} else {
|
} else {
|
||||||
this.saveFileBrowser_();
|
this.saveFileBrowser_();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ns.SaveController.prototype.saveAs_ = function () {
|
||||||
|
pskl.app.desktopStorageService.savePiskelAs();
|
||||||
|
};
|
||||||
|
|
||||||
ns.SaveController.prototype.saveFileBrowser_ = function () {
|
ns.SaveController.prototype.saveFileBrowser_ = function () {
|
||||||
this.beforeSaving_();
|
this.beforeSaving_();
|
||||||
pskl.utils.BlobUtils.stringToBlob(pskl.app.piskelController.serialize(), function(blob) {
|
pskl.utils.BlobUtils.stringToBlob(pskl.app.piskelController.serialize(), function(blob) {
|
||||||
@ -156,10 +165,6 @@
|
|||||||
}.bind(this), 'application/piskel+json');
|
}.bind(this), 'application/piskel+json');
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.SaveController.prototype.saveFileDesktop_ = function () {
|
|
||||||
pskl.app.desktopStorageService.save();
|
|
||||||
};
|
|
||||||
|
|
||||||
ns.SaveController.prototype.getName = function () {
|
ns.SaveController.prototype.getName = function () {
|
||||||
return this.nameInput.value;
|
return this.nameInput.value;
|
||||||
};
|
};
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
if (savePath) {
|
if (savePath) {
|
||||||
this.savePiskel(savePath);
|
this.savePiskel(savePath);
|
||||||
} else {
|
} 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 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
|
// TODO: if there is already a file path, use it for the dialog's
|
||||||
// working directory and filename
|
// 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);
|
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_();
|
this.onSaveSuccess_();
|
||||||
}.bind(this));
|
}.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 () {
|
ns.DesktopStorageService.prototype.onSaveSuccess_ = function () {
|
||||||
var savePath = this.piskelController.getSavePath();
|
var savePath = this.piskelController.getSavePath();
|
||||||
$.publish(Events.CLOSE_SETTINGS_DRAWER);
|
$.publish(Events.CLOSE_SETTINGS_DRAWER);
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var CONFIRM_OVERRIDE = 'File already exists, do you want to override it ?';
|
||||||
|
|
||||||
ns.FileUtilsDesktop = {
|
ns.FileUtilsDesktop = {
|
||||||
|
|
||||||
chooseFileDialog: function (callback) {
|
chooseFileDialog: function (callback) {
|
||||||
@ -17,37 +19,44 @@
|
|||||||
$chooser.trigger('click');
|
$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 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 -
|
* @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
|
* 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.
|
* is already another file of the same name *with* the extension, it will get overwritten.
|
||||||
* @param callback
|
* @param callback
|
||||||
*/
|
*/
|
||||||
saveAs: function (content, defaultFileName, extension, callback) {
|
saveAs: function (content, defaultFilename, extension, callback) {
|
||||||
// NodeWebkit has no js api for opening the save dialog.
|
// NodeWebkit has no js api for opening the save dialog.
|
||||||
// Instead, it adds two new attributes to the anchor tag: nwdirectory and nwsaveas
|
// Instead, it adds two new attributes to the anchor tag: nwdirectory and nwsaveas
|
||||||
// (see: https://github.com/nwjs/nw.js/wiki/File-dialogs )
|
// (see: https://github.com/nwjs/nw.js/wiki/File-dialogs )
|
||||||
defaultFileName = defaultFileName || '';
|
defaultFilename = defaultFilename || 'New Piskel';
|
||||||
var tagString = '<input type="file" nwsaveas="' + defaultFileName + '" nwworkingdir=""/>';
|
defaultFilename = pskl.utils.FileUtilsDesktop.addExtensionIfNeeded(defaultFilename, extension);
|
||||||
|
var tagString = '<input type="file" accept=".piskel" nwsaveas="' + defaultFilename + '" nwworkingdir=""/>';
|
||||||
var $chooser = $(tagString);
|
var $chooser = $(tagString);
|
||||||
$chooser.change(function (e) {
|
$chooser.change(function (e) {
|
||||||
var filename = $(this).val();
|
var filename = $(this).val();
|
||||||
if (typeof extension == 'string') {
|
filename = pskl.utils.FileUtilsDesktop.addExtensionIfNeeded(filename, extension);
|
||||||
if (extension[0] !== '.') {
|
|
||||||
extension = '.' + extension;
|
|
||||||
}
|
|
||||||
var hasExtension = (filename.substring(filename.length - extension.length) === extension);
|
|
||||||
if (!hasExtension) {
|
|
||||||
filename += extension;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pskl.utils.FileUtilsDesktop.saveToFile(content, filename, function () {
|
pskl.utils.FileUtilsDesktop.saveToFile(content, filename, function () {
|
||||||
callback(filename);
|
callback(filename);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$chooser.trigger('click');
|
$chooser.trigger('click');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -21,6 +21,11 @@
|
|||||||
return dummyEl.children[0];
|
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) {
|
getAndReplace : function (templateId, dict) {
|
||||||
var result = '';
|
var result = '';
|
||||||
var tpl = pskl.utils.Template.get(templateId);
|
var tpl = pskl.utils.Template.get(templateId);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<div class="settings-section setting-save-section">
|
<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-title">Describe your piskel</div>
|
||||||
<div class="settings-item">
|
<div class="settings-item">
|
||||||
<div class="settings-form-section" style="overflow:hidden">
|
<div class="settings-form-section" style="overflow:hidden">
|
||||||
@ -16,24 +16,47 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</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-title">Save online</div>
|
||||||
<div class="settings-item">
|
<div class="settings-item">
|
||||||
<input type="button" class="button button-primary" id="save-online-button" value="Save to your gallery" />
|
<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 id="save-online-status" class="save-status"></div>
|
||||||
</div>
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- save-localstorage-partial -->
|
||||||
|
<script type="text/template" id="save-localstorage-partial">
|
||||||
<div id="save-in-browser">
|
<div id="save-in-browser">
|
||||||
<div class="settings-title">Save offline in Browser</div>
|
<div class="settings-title">Save offline in Browser</div>
|
||||||
<div class="settings-item">
|
<div class="settings-item">
|
||||||
<input type="button" class="button button-primary" id="save-browser-button" value="Save in Browser" />
|
<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 id="save-browser-status" class="save-status">Your piskel will be saved locally and will only be accessible from this browser.</div>
|
||||||
</div>
|
</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-title">Save offline as File</div>
|
||||||
<div class="settings-item">
|
<div class="settings-item">
|
||||||
<input type="button" class="button button-primary" id="save-file-button" value="Save as File" />
|
<input type="button" class="button button-primary" id="save-file-button" value="Save as ..." />
|
||||||
<div id="save-file-status" class="save-status"></div>
|
<div id="save-file-status" class="save-status">Your sprite will be downloaded as a .piskel file.</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</script>
|
||||||
|
|
||||||
<script type="text/template" id="save-please-login-partial">
|
<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>
|
<span>Login to <a href="http://piskelapp.com" target="_blank">piskelapp.com</a> to save and share your sprites online !</span>
|
||||||
|
Loading…
Reference in New Issue
Block a user