initial design lib tab. adding and removing svgs works.

This commit is contained in:
Teja 2015-01-31 01:34:49 +01:00
parent 16b721ede3
commit 7aa59e5763
2 changed files with 254 additions and 87 deletions

View file

@ -92,11 +92,60 @@ $(function(){
});
self.placedDesigns = ko.observableArray([]);
self.working_area_empty = ko.computed(function(){
return self.placedDesigns().length === 0;
});
self.clear = function(){
snap.selectAll('#userContent>*').remove();
self.placedDesigns([]);
};
// initialize list helper
self.listHelper = new ItemListHelper(
"gcodeFiles",
{
"name": function(a, b) {
// sorts ascending
if (a["name"].toLocaleLowerCase() < b["name"].toLocaleLowerCase()) return -1;
if (a["name"].toLocaleLowerCase() > b["name"].toLocaleLowerCase()) return 1;
return 0;
},
"upload": function(a, b) {
// sorts descending
if (b["date"] === undefined || a["date"] > b["date"]) return -1;
if (a["date"] < b["date"]) return 1;
return 0;
},
"size": function(a, b) {
// sorts descending
if (b["bytes"] === undefined || a["bytes"] > b["bytes"]) return -1;
if (a["bytes"] < b["bytes"]) return 1;
return 0;
}
},
{
"printed": function(file) {
return !(file["prints"] && file["prints"]["success"] && file["prints"]["success"] > 0);
},
"sd": function(file) {
return file["origin"] && file["origin"] == "sdcard";
},
"local": function(file) {
return !(file["origin"] && file["origin"] == "sdcard");
},
"machinecode": function(file) {
return file["type"] && file["type"] == "machinecode";
},
"model": function(file) {
return file["type"] && file["type"] == "model";
}
},
"name",
[],
[["sd", "local"], ["machinecode", "model"]],
0
);
self.trigger_resize = function(){
self.availableHeight(document.documentElement.clientHeight - $('body>nav').outerHeight() - $('footer>*').outerHeight() - 39); // magic number
@ -143,17 +192,10 @@ $(function(){
return val * self.svgDPI()/25.4;
};
//self.getDivDimensions(); // init
self.placeSVG = function(file) {
if (file && file["refs"] && file["refs"]["download"]) {
var url = file.refs.download.replace("downloads", "serve");
self.loadSVG(url);
}
};
self.loadSVG = function(url){
Snap.load(url, function (f) {
var url = self._getSVGserveUrl(file);
callback = function (f) {
var namespaces = {};
var root = f.select('svg').node.attributes;
for(var i = 0; i < root.length; i++){
@ -165,17 +207,67 @@ $(function(){
var newSvg = f.select("g");
newSvg.attr(namespaces);
var id = self.generateId(url);
// var id = self.generateId(url);
var id = self.getEntryId(file); // works better on multiple instances.
newSvg.attr({id: id});
snap.select("#userContent").append(newSvg);
newSvg.drag();// Making croc draggable. Go ahead drag it around!
// Obviously drag could take event handlers too
var ref = {
id : id,
url : url
};
self.placedDesigns.push(ref);
});
newSvg.drag();// TODO debug drag. should not be affected by scale matrix
file.id = id;
file.url = url;
self.placedDesigns.push(file);
};
self.loadSVG(url, callback);
};
self.loadSVG = function(url, callback){
Snap.load(url, callback);
};
self.removeSVG = function(file){
var url = self._getSVGserveUrl(file);
for (var idx = 0; idx < self.placedDesigns().length; idx++) {
var svg = self.placedDesigns()[idx];
if(svg.url === url){
console.log("#ää", svg.id);
snap.select('#'+svg.id).remove();
self.placedDesigns().splice(idx,1);
break;
}
}
};
self._getSVGserveUrl = function(file){
if (file && file["refs"] && file["refs"]["download"]) {
var url = file.refs.download.replace("downloads", "serve");
return url;
}
};
self.templateFor = function(data) {
var extension = data.name.split('.').pop().toLowerCase();
if (extension == "svg") {
return "wa_template_" + data.type + "_svg";
} else {
return "wa_template_" + data.type;
}
};
self.getEntryId = function(data) {
return "wa_" + md5(data["origin"] + ":" + data["name"]);
};
self.getEntryElement = function(data) {
var entryId = self.getEntryId(data);
var entryElements = $("#" + entryId);
if (entryElements && entryElements[0]) {
return entryElements[0];
} else {
return undefined;
}
};
self.init = function(){
@ -220,7 +312,7 @@ $(function(){
};
self.generateId = function(url){
var idBase = '_'+url.substring(url.lastIndexOf('/')+1).replace(/[^a-zA-Z0-9_.]/ig, '-'); // _ at first place if filename starts with a digit
var idBase = '_'+url.substring(url.lastIndexOf('/')+1).replace(/[^a-zA-Z0-9]/ig, '-'); // _ at first place if filename starts with a digit
idBase = idBase.replace('')
var suffix = 0;
var id = idBase + "-" + suffix;
@ -274,6 +366,6 @@ $(function(){
// view model class, parameters for constructor, container to bind to
ADDITIONAL_VIEWMODELS.push([WorkingAreaViewModel, "workingAreaViewModel",
["loginStateViewModel", "settingsViewModel", "printerStateViewModel", "gcodeFilesViewModel", "vectorConversionViewModel"],
document.getElementById("area_preview")]);
[document.getElementById("area_preview"), document.getElementById("working_area_files")]]);
});

View file

@ -21,7 +21,7 @@
</div>
<ul class="nav nav-pills">
<li class="active"><a href="#workingarea" data-toggle="tab">working area</a></li>
<!--<li><a href="#designlib" data-toggle="tab">design library</a></li>-->
<li><a href="#designlib" data-toggle="tab">design library</a></li>
<!--<li><a href="#gcode" data-toggle="tab">gcode</a></li>-->
<li><a href="#focus" data-toggle="tab">focus</a></li>
<li><a href="#term" data-toggle="tab">terminal</a></li>
@ -164,8 +164,10 @@
<div data-bind="visible: !isLocked()">
<!--
{{ _('File') }}: <strong data-bind="text: filename"></strong>&nbsp;<strong data-bind="visible: sd">(SD)</strong><br>
<!-- {{ _('Timelapse') }}: <strong data-bind="text: timelapseString"></strong><br>-->
{{ _('Timelapse') }}: <strong data-bind="text: timelapseString"></strong><br>
-->
{{ _('Approx. Total Job Time') }}: <strong data-bind="text: estimatedPrintTimeString"></strong><br>
<div class="progress" data-bind="visible: isPrinting()">
<div class="bar" id="job_progressBar" data-bind="style: { width: progressString() + '%' }">{{ _('Processed') }} : <strong data-bind="text: byteString"></strong></div>
@ -190,91 +192,52 @@
<div data-bind="visible: loginState.isUser" id="connection_accordion"></div>
<div class="accordion-group" id="files_accordion">
<div class="accordion-group" id="working_area_files">
<div class="">
<div class="accordion-heading">
<a class="accordion-toggle" data-toggle="collapse" href="#files"><i class="icon-list"></i> {{ _('Files') }}</a>
<a class="pull-right btn btn-small" data-bind="click: workingArea.clear" style="margin-right: 1em; margin-top: 4px;" ><i class="icon-remove-sign"></i> {{ _('Clear') }}</a>
</div>
<div class="settings-trigger accordion-heading-button btn-group" style="display: none;">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<span class="icon-wrench"></span>
</a>
<ul class="dropdown-menu">
<li><a href="#" data-bind="click: function() { $root.listHelper.changeSorting('name'); }"><i class="icon-ok" data-bind="style: {visibility: listHelper.currentSorting() == 'name' ? 'visible' : 'hidden'}"></i> {{ _('Sort by name') }} ({{ _('ascending') }})</a></li>
<li><a href="#" data-bind="click: function() { $root.listHelper.changeSorting('upload'); }"><i class="icon-ok" data-bind="style: {visibility: listHelper.currentSorting() == 'upload' ? 'visible' : 'hidden'}"></i> {{ _('Sort by upload date') }} ({{ _('descending') }})</a></li>
<li><a href="#" data-bind="click: function() { $root.listHelper.changeSorting('size'); }"><i class="icon-ok" data-bind="style: {visibility: listHelper.currentSorting() == 'size' ? 'visible' : 'hidden'}"></i> {{ _('Sort by file size') }} ({{ _('descending') }})</a></li>
<li class="divider"></li>
<li><a href="#" data-bind="click: function() { $root.listHelper.toggleFilter('machinecode'); }"><i class="icon-ok" data-bind="style: {visibility: _.contains(listHelper.currentFilters(), 'machinecode') ? 'visible' : 'hidden'}"></i> {{ _('Only show GCode files') }}</a></li>
<li><a href="#" data-bind="click: function() { $root.listHelper.toggleFilter('model'); }"><i class="icon-ok" data-bind="style: {visibility: _.contains(listHelper.currentFilters(), 'model') ? 'visible' : 'hidden'}"></i> {{ _('Only show STL files') }}</a></li>
<li class="divider"></li>
</ul>
<a class="accordion-toggle" data-toggle="collapse" href="#wa_filelist"><i class="icon-list"></i> {{ _('Files') }}</a>
<a class="pull-right btn btn-small" data-bind="click: clear" style="margin-right: 1em; margin-top: 4px;" ><i class="icon-remove-sign"></i> {{ _('Clear') }}</a>
</div>
</div>
<div class="accordion-body collapse in overflow_visible" id="files">
<div class="accordion-body collapse in overflow_visible" id="wa_filelist">
<div class="accordion-inner">
<form class="form-search">
<input type="text" class="input-block search-query" data-bind="value: searchQuery, valueUpdate: 'input'" placeholder="{{ _('Search...') }}">
</form>
<div class="gcode_files" data-bind="slimScrolledForeach: listHelper.paginatedItems">
<div class="gcode_files" data-bind="slimScrolledForeach: placedDesigns">
<div class="entry" data-bind="attr: { id: $root.getEntryId($data) }, template: { name: $root.templateFor($data), data: $data }"></div>
<script type="text/html" id="files_template_machinecode">
<script type="text/html" id="wa_template_machinecode">
<div class="file_list_entry">
<div class="title" data-bind="css: $root.getSuccessClass($data), style: { 'font-weight': $root.listHelper.isSelected($data) ? 'bold' : 'normal' }, text: name"></div>
<div class="uploaded">{{ _('Uploaded') }}: <span data-bind="text: formatTimeAgo(date)"></span></div>
<div class="size">{{ _('Size') }}: <span data-bind="text: formatSize(size)"></span></div>
<div class="additionalInfo hide" data-bind="html: $root.getAdditionalData($data)"></div>
<div class="btn-group action-buttons">
<a class="btn btn-mini" data-bind="attr: {href: $root.downloadLink($data), css: {disabled: !$root.downloadLink($data)}}"><i class="icon-download-alt" title="{{ _('Download') }}"></i></a>
<div class="btn btn-mini" data-bind="click: function() { if ($root.enableRemove($data)) { $root.removeFile($data); } else { return; } }, css: {disabled: !$root.enableRemove($data)}"><i class="icon-trash" title="{{ _('Remove') }}"></i></div>
<div class="btn btn-mini" data-bind="click: function() { if ($root.enableSelect($data)) { $root.startGcodeWithSafetyWarning($data); } else { return; } }, css: {disabled: !$root.enableSelect($data)}"><i class="icon-fire" title="{{ _('Load and Laser') }}"></i></div>
<div class="btn btn-mini" data-bind="click: function() { if ($root.enableRemove($data)) { $root.removeFile($data); } else { return; } }"><i class="icon-remove" title="{{ _('Remove') }}"></i></div>
</div>
</div>
</script>
<script type="text/html" id="files_template_model_svg">
<script type="text/html" id="wa_template_model_svg">
<div class="file_list_entry">
<div class="title muted" data-bind="text: name"></div>
<div class="uploaded">{{ _('Uploaded') }}: <span data-bind="text: formatTimeAgo(date)"></span></div>
<div class="size">{{ _('Size') }}: <span data-bind="text: formatSize(size)"></span></div>
<div class="btn-group action-buttons">
<div class="btn btn-mini" data-bind="click: function() { if ($root.enableRemove($data)) { $root.removeFile($data); } else { return; } }, css: {disabled: !$root.enableRemove($data)}"><i class="icon-trash" title="{{ _('Remove') }}"></i></div>
<div class="btn btn-mini" data-bind="click: function() { $root.workingArea.placeSVG($data); }, css: {disabled: !$root.enableSVGConversion($data)}"><i class="icon-arrow-right" title="{{ _('Use') }}"></i></div>
<div class="btn btn-mini" data-bind="click: function() { $root.removeSVG($data); }"><i class="icon-remove" title="{{ _('Remove') }}"></i></div>
</div>
</div>
</script>
<script type="text/html" id="files_template_folder">
<div class="title" data-bind="text: name"></div>
</script>
</div>
<div class="muted text-right">
<small>{{ _('Free') }}: <span data-bind="text: freeSpaceString"></span></small>
</div>
<div style="display: none;" data-bind="visible: loginState.isUser">
<div class="row-fluid upload-buttons">
<span class="btn btn-primary fileinput-button span12" data-bind="css: {disabled: !$root.loginState.isUser()}" style="margin-bottom: 10px">
<i class="icon-upload-alt icon-white"></i>
<span>{{ _('Upload') }}</span>
<input id="gcode_upload" type="file" name="file" class="fileinput-button" data-bind="enable: loginState.isUser()">
</span>
</div>
<div id="gcode_upload_progress" class="progress" style="width: 100%;">
<div class="bar" style="width: 0%"></div>
</div>
<div>
<small>{{ _('Hint: You can also drag and drop files on this page to upload them.') }}</small>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- end sidebar -->
<div class="span8">
<svg id="area_preview" class="workingarea"
data-bind="style: {
@ -287,6 +250,30 @@
<rect data-bind="click: move_laser"
id="coordGrid" x="0" y="0" width="0" height="0"
stroke="none" fill="none"></rect>
<text
xml:space="preserve"
data-bind="visible: working_area_empty"
style="font-size:64px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#DDDDDD;fill-opacity:1;stroke:none;font-family:DIN-BoldAlternate;-inkscape-font-specification:DIN-BoldAlternate Bold"
x="396.81018"
y="592.36218"
id="add_designs_hint"
><tspan
id="tspan2987"
x="368.571426"
y="532.36218"
style="text-anchor:middle;text-align:center">add designs via </tspan><tspan
x="368.571426"
y="592.36218"
id="tspan2989"
style="text-anchor:middle;text-align:center">the design library </tspan><tspan
x="368.571426"
y="652.36218"
id="tspan2993"
style="text-anchor:middle;text-align:center">or drag 'n' drop </tspan><tspan
x="368.571426"
y="712.36218"
id="tspan2991"
style="text-anchor:middle;text-align:center" /></text>
<g id="userContent"></g>
<g id="gCodePreview" data-bind="attr: { transform: scaleMatrixMMtoDisplay() }"></g>
</g>
@ -326,18 +313,106 @@
<div class="tab-pane" id="designlib">
<div class="container-fluid">
<div class="row-fluid">
<div class="span2">
<div class="row-fluid" id="files_accordion">
<div class="span4">
<ul>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
<li>Local</li>
<li>Online Library</li>
</ul>
<button>Use design</button>
<div class="">
<div class="accordion-heading">
<a class="accordion-toggle" data-toggle="collapse" href="#files"><i class="icon-list"></i> {{ _('Files') }}</a>
<a class="accordion-toggle" data-toggle="collapse" href="#files_search" style="text-decoration: none;"><i class="icon-search dropdown-toggle"></i><span class="caret" style="margin: .5em;"></span></a>
<a class="pull-right btn btn-small" data-bind="click: workingArea.clear" style="margin-right: 1em; margin-top: 4px;" ><i class="icon-remove-sign"></i> {{ _('Clear') }}</a>
</div>
<div class="settings-trigger accordion-heading-button btn-group" style="display: none;">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<span class="icon-wrench"></span>
</a>
<ul class="dropdown-menu">
<li><a href="#" data-bind="click: function() { $root.listHelper.changeSorting('name'); }"><i class="icon-ok" data-bind="style: {visibility: listHelper.currentSorting() == 'name' ? 'visible' : 'hidden'}"></i> {{ _('Sort by name') }} ({{ _('ascending') }})</a></li>
<li><a href="#" data-bind="click: function() { $root.listHelper.changeSorting('upload'); }"><i class="icon-ok" data-bind="style: {visibility: listHelper.currentSorting() == 'upload' ? 'visible' : 'hidden'}"></i> {{ _('Sort by upload date') }} ({{ _('descending') }})</a></li>
<li><a href="#" data-bind="click: function() { $root.listHelper.changeSorting('size'); }"><i class="icon-ok" data-bind="style: {visibility: listHelper.currentSorting() == 'size' ? 'visible' : 'hidden'}"></i> {{ _('Sort by file size') }} ({{ _('descending') }})</a></li>
<li class="divider"></li>
<li><a href="#" data-bind="click: function() { $root.listHelper.toggleFilter('machinecode'); }"><i class="icon-ok" data-bind="style: {visibility: _.contains(listHelper.currentFilters(), 'machinecode') ? 'visible' : 'hidden'}"></i> {{ _('Only show GCode files') }}</a></li>
<li><a href="#" data-bind="click: function() { $root.listHelper.toggleFilter('model'); }"><i class="icon-ok" data-bind="style: {visibility: _.contains(listHelper.currentFilters(), 'model') ? 'visible' : 'hidden'}"></i> {{ _('Only show STL files') }}</a></li>
<li class="divider"></li>
</ul>
</div>
<div id="files_search" class="collapse">
<form class="form-search">
<input type="text" class="input-block search-query" data-bind="value: searchQuery, valueUpdate: 'input'" placeholder="{{ _('Search...') }}">
</form>
</div>
<div class="muted text-right">
<small>{{ _('Free') }}: <span data-bind="text: freeSpaceString"></span></small>
</div>
<div style="display: none;" data-bind="visible: loginState.isUser">
<div class="row-fluid upload-buttons">
<span class="btn btn-primary fileinput-button span12" data-bind="css: {disabled: !$root.loginState.isUser()}" style="margin-bottom: 10px">
<i class="icon-upload-alt icon-white"></i>
<span>{{ _('Upload') }}</span>
<input id="gcode_upload" type="file" name="file" class="fileinput-button" data-bind="enable: loginState.isUser()">
</span>
</div>
<div id="gcode_upload_progress" class="progress" style="width: 100%;">
<div class="bar" style="width: 0%"></div>
</div>
<div>
<small>{{ _('Hint: You can also drag and drop files on this page to upload them.') }}</small>
</div>
</div>
</div>
</div>
<div class="span10">
<div class="designlib" > preview </div>
<div class="span8">
<div class="designlib" >
<div class="" >
<div id="files">
<div class="accordion-inner">
<div class="gcode_files" data-bind="slimScrolledForeach: listHelper.paginatedItems">
<div class="entry" data-bind="attr: { id: $root.getEntryId($data) }, template: { name: $root.templateFor($data), data: $data }"></div>
<script type="text/html" id="files_template_machinecode">
<div class="file_list_entry">
<div class="title" data-bind="css: $root.getSuccessClass($data), style: { 'font-weight': $root.listHelper.isSelected($data) ? 'bold' : 'normal' }, text: name"></div>
<div class="uploaded">{{ _('Uploaded') }}: <span data-bind="text: formatTimeAgo(date)"></span></div>
<div class="size">{{ _('Size') }}: <span data-bind="text: formatSize(size)"></span></div>
<div class="additionalInfo hide" data-bind="html: $root.getAdditionalData($data)"></div>
<div class="btn-group action-buttons">
<a class="btn btn-mini" data-bind="attr: {href: $root.downloadLink($data), css: {disabled: !$root.downloadLink($data)}}"><i class="icon-download-alt" title="{{ _('Download') }}"></i></a>
<div class="btn btn-mini" data-bind="click: function() { if ($root.enableRemove($data)) { $root.removeFile($data); } else { return; } }, css: {disabled: !$root.enableRemove($data)}"><i class="icon-trash" title="{{ _('Remove') }}"></i></div>
<div class="btn btn-mini" data-bind="click: function() { if ($root.enableSelect($data)) { $root.startGcodeWithSafetyWarning($data); } else { return; } }, css: {disabled: !$root.enableSelect($data)}"><i class="icon-fire" title="{{ _('Load and Laser') }}"></i></div>
</div>
</div>
</script>
<script type="text/html" id="files_template_model_svg">
<div class="file_list_entry">
<div class="title muted" data-bind="text: name"></div>
<div class="uploaded">{{ _('Uploaded') }}: <span data-bind="text: formatTimeAgo(date)"></span></div>
<div class="size">{{ _('Size') }}: <span data-bind="text: formatSize(size)"></span></div>
<div class="btn-group action-buttons">
<div class="btn btn-mini" data-bind="click: function() { if ($root.enableRemove($data)) { $root.removeFile($data); } else { return; } }, css: {disabled: !$root.enableRemove($data)}"><i class="icon-trash" title="{{ _('Remove') }}"></i></div>
<div class="btn btn-mini" data-bind="click: function() { $root.workingArea.removeSVG($data); }, css: {disabled: !$root.enableSVGConversion($data)}"><i class="icon-remove" title="{{ _('remove') }}"></i></div>
<div class="btn btn-mini" data-bind="click: function() { $root.workingArea.placeSVG($data); }, css: {disabled: !$root.enableSVGConversion($data)}"><i class="icon-ok" title="{{ _('Use') }}"></i></div>
</div>
</div>
</script>
<script type="text/html" id="files_template_folder">
<div class="title" data-bind="text: name"></div>
</script>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>