diff options
author | Fulup Ar Foll <fulup@iot.bzh> | 2015-12-20 21:04:34 +0100 |
---|---|---|
committer | Fulup Ar Foll <fulup@iot.bzh> | 2015-12-20 21:04:34 +0100 |
commit | 4136c1506e0c894e604ec069339313987a7e05e7 (patch) | |
tree | 1276966f93dce30949e78d4aef456223dea71b48 /afb-client/app/Frontend/widgets/FormInput | |
parent | 07eb8e102607da8d6a4c1cd9835e8465c9280161 (diff) |
Implemented client upload with rangeslider and zip open
Diffstat (limited to 'afb-client/app/Frontend/widgets/FormInput')
4 files changed, 388 insertions, 115 deletions
diff --git a/afb-client/app/Frontend/widgets/FormInput/FormInput.scss b/afb-client/app/Frontend/widgets/FormInput/FormInput.scss index 37519fd..77aed6e 100644 --- a/afb-client/app/Frontend/widgets/FormInput/FormInput.scss +++ b/afb-client/app/Frontend/widgets/FormInput/FormInput.scss @@ -7,11 +7,33 @@ @import "app/ibz-mixins"; -upload-file { - height: 5rem; +.upload-file { display: inline-block; float: right; + height : 5rem; + width : 5rem; + margin: 0.5rem; + img { height: inherit;} + + .ibz-range-slider { + height: 10% !important; + border-radius: 5px; + background-color: lightgrey !important; + + .range-slider-handle { + width: 10% !important; + height: 100% !important; + margin-top: .2rem; + background-color: purple !important; + } + + .range-slider-active-segment { + height: 80% !important; + background-color: lightgreen; + } + } + } input-text { diff --git a/afb-client/app/Frontend/widgets/FormInput/UploadFile.js b/afb-client/app/Frontend/widgets/FormInput/UploadFile.js deleted file mode 100644 index 9a2f031..0000000 --- a/afb-client/app/Frontend/widgets/FormInput/UploadFile.js +++ /dev/null @@ -1,113 +0,0 @@ - -/* - * Copyright (C) 2015 "IoT.bzh" - * Author "Fulup Ar Foll" - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details.. - * - * Reference: - * https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications#Using_hidden_file_input_elements_using_the_click%28%29_method - * https://uncorkedstudios.com/blog/multipartformdata-file-upload-with-angularjs - * https://www.terlici.com/2015/05/16/uploading-files-locally.html - * https://github.com/nervgh/angular-file-upload/blob/master/src/services/FileUploader.js - */ - - -function changeInput() { - console.log ('input imgClicked'); -} - -(function() { -'use strict'; - -// WARNING: Angular ng-change does not work on input/file. Let's hook our callback through standard JS function -var tmpl = '<form target="null" action="/api/afbs/file-upload" method="post" enctype="multipart/form-data" >'+ - '<input type="file" name="{{name}}" onchange="angular.element(this).scope().UpLoadFile(this.files)" accept="{{mime}}/*" style="display" >'+ - '<input type="submit" class="submit" style="display" > ' + - '</form>' + - '<img id="{{name}}-img" src="{{imagepath}}" ng-click="imgClicked()">' ; - -function basename(path) { - return path.split('/').reverse()[0]; -} - -angular.module('UploadFile',['ConfigApp']) - -.directive('uploadFile', function(ConfigApp, $http, JQemu) { - function mymethods(scope, elem, attrs) { - - // get widget image handle from template - scope.imgElem = elem.find('img'); - scope.inputElem = elem.find('input'); - scope.submitElem = JQemu.findByType (elem.children(), "submit"); - - - // Image was ckick let's simulate an input (file) click - scope.imgClicked = function () { - scope.inputElem[0].click(); // Warning Angular TriggerEvent does not work!!! - }; - - // upload file to server - scope.UpLoadFile= function(files) { - - - for (var i = 0; i < files.length; i++) { - var file = files[i]; - console.log ("Selected file=" + file.name + " size="+ file.size/1024); - var mimeType = /image.*/; // build regular expression from Mime - if (!file.type.match(mimeType)) { - continue; - } - - if (file.size > scope.sizemax*1024) { - scope.imagepath = scope.istoobig; // warning is path is wrong nothing happen - scope.$apply('imagepath'); // we short-circuit Angular resync Image - } else { - - scope.basename=basename(file.name); - scope.imgElem[0].file = file; - - var reader = new FileReader(); - reader.readAsDataURL(file); - reader.onload = function (upload) { - scope.imagepath = upload.target.result; - scope.$apply('imagepath'); // we short-circuit Angular resync image - scope.submitElem[0].click(); // Warning Angular TriggerEvent does not work!!! - }; - } - } - }; - - // Initiallize default values from attributes values - if (attrs.icon) scope.imagepath= ConfigApp.paths[attrs.category] + attrs.icon; - else scope.imagepath=ConfigApp.paths.avatars + 'tux-bzh.png'; - - if (attrs.istoobig) scope.istoobig= ConfigApp.paths[attrs.category] + attrs.istoobig; - else scope.istoobig=ConfigApp.paths.avatars + 'istoobig.jpg'; - - scope.name= attrs.name || 'avatar'; - scope.mime= attrs.mime || 'image'; - scope.sizemax= attrs.sizemax || 100; // default max size 100KB - - } - - return { - restrict: 'E', - template: tmpl, - link: mymethods, - scope: { - callback : '=' - } - }; -}); - -console.log ("UploadFile Loaded"); -})(); diff --git a/afb-client/app/Frontend/widgets/FormInput/UploadFiles.js b/afb-client/app/Frontend/widgets/FormInput/UploadFiles.js new file mode 100644 index 0000000..6c68960 --- /dev/null +++ b/afb-client/app/Frontend/widgets/FormInput/UploadFiles.js @@ -0,0 +1,309 @@ + +/* + * Copyright (C) 2015 "IoT.bzh" + * Author "Fulup Ar Foll" + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details.. + * + * Reference: + * https://developer.mozilla.org/en/docs/Web/API/FileReader + * https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications#Using_hidden_file_input_elements_using_the_click%28%29_method + * https://uncorkedstudios.com/blog/multipartformdata-file-upload-with-angularjs + * https://www.terlici.com/2015/05/16/uploading-files-locally.html + * https://github.com/nervgh/angular-file-upload/blob/master/src/services/FileUploader.js + * https://stuk.github.io/jszip/documentation/howto/read_zip.html + * http://onehungrymind.com/zip-parsing-jszip-angular/ + */ + + +function changeInput() { + console.log ('input imgClicked'); +} + +(function() { +'use strict'; + +// WARNING: Angular ng-change does not work on input/file. Let's hook our callback through standard JS function +var tmpl = '<input type="file" name="{{name}}-input" onchange="angular.element(this).scope().UpLoadFile(this.files)" accept="{{mimetype}}" style="display:none">'+ + '<div class="upload-file" ng-click="imgClicked()">' + + '<img id="{{name}}-img" src="{{thumbnail}}">' + + '<range-slider ng-show="!noslider" id="{{name}}-slider" automatic=true inithook="SliderInitCB"></range-slider>' + + '</div>'; + + +function Basename(path) { + return path.split('/').reverse()[0]; +} + +// Service Create xform insert files in and Post it to url +function LoadFileSvc (scope, elem, posturl, files, thumbnailCB) { + var xmlReq = new XMLHttpRequest(); + var xform = new FormData(); + + // Update slider during Upload + xmlReq.upload.onprogress = function (event) { + var progress = Math.round(event.lengthComputable ? event.loaded * 100 / event.total : 0); + if (scope.slider) scope.slider.setValue (progress); + }; + + // Upload is finish let's notify controler callback + xmlReq.onload = function () { + elem.addClass ("success"); + var response ={ + status : xmlReq.status, + headers: xmlReq.getAllResponseHeaders() + }; + scope.callback (response); + }; + + xmlReq.onerror = function () { + elem.addClass ("error fail"); + var response ={ + status : xmlReq.status, + headers: xmlReq.getAllResponseHeaders() + }; + scope.callback (response); + }; + + xmlReq.onabort = function () { + elem.addClass ("error abort"); + var response ={ + status : xmlReq.status, + headers: xmlReq.getAllResponseHeaders() + }; + scope.callback (response); + }; + + for (var i = 0; i < files.length; i++) { + var file = files[i]; + if (!file.type.match(scope.mimetype)) { + continue; + } + + console.log ("Selected file=" + file.name + " size="+ file.size/1024 + " Type="+ file.type); + + // File to upload is too big + if (file.size > scope.maxsize*1024) { + scope.thumbnail = scope.istoobig; // warning if image path is wrong nothing happen + scope.$apply('thumbnail'); // we short-circuit Angular resync Image + return; + } + + // This is not an uploadable file + if(isNaN(file.size)) { + scope.thumbnail = scope.isnotvalid; + scope.$apply('thumbnail'); + return; + } + + scope.Basename=Basename(file.name); + scope.imgElem[0].file = file; + + // If File is an image let display it now + if (thumbnailCB) { + var reader = new FileReader(); + reader.readAsArrayBuffer(file); + reader.onload = thumbnailCB; + } + + // if everything is OK let's add file to xform + xform.append(scope.name, file, file.name); + } + + + // everything looks OK let's Post it + xmlReq.open("POST", posturl , true); + xmlReq.send(xform); +}; + +angular.module('UploadFiles',['ConfigApp', 'ModalNotification', 'RangeSlider']) + +.directive('uploadImage', function(ConfigApp, JQemu, Notification) { + function mymethods(scope, elem, attrs) { + + // get widget image handle from template + scope.imgElem = elem.find('img'); + scope.inputElem = elem.find('input'); + + // Image was ckick let's simulate an input (file) click + scope.imgClicked = function () { + scope.inputElem[0].click(); // Warning Angular TriggerEvent does not work!!! + }; + + // Slider control handle registration after creation + scope.SliderInitCB=function (slider) { + scope.slider= slider; + }; + + // Upload is delegated to a shared function + scope.UpLoadFile=function (files) { + var readerCB = function (upload) { + // scope.thumbnail = upload.target.result; + scope.imgElem[0].src = window.URL.createObjectURL(new Blob([upload.target.result], {type: "image"})); + scope.$apply('thumbnail'); // we short-circuit Angular resync image + }; + var posturl = attrs.posturl + "?token=" + ConfigApp.session.token; + LoadFileSvc (scope, elem, posturl, files, readerCB); + }; + + // Initiallize default values from attributes values + scope.name= attrs.name || 'avatar'; + scope.category= attrs.category || 'image'; + scope.mimetype= (attrs.accept || 'image') + '/*'; + scope.maxsize= attrs.maxsize || 100; // default max size 100KB + scope.regexp = new RegExp (attrs.accept+ '.*','i'); + + if (attrs.thumbnail) scope.thumbnail= ConfigApp.paths[scope.category] + attrs.thumbnail; + else scope.thumbnail=ConfigApp.paths[scope.category] + 'tux-bzh.png'; + + if (attrs.thumbnail) scope.isnotvalid= ConfigApp.paths[scope.category] + attrs.isnotvalid; + else scope.isnotvalid=ConfigApp.paths[scope.category] + 'isnotvalid.png'; + + if (attrs.istoobig) scope.istoobig= ConfigApp.paths[scope.category] + attrs.istoobig; + else scope.istoobig=ConfigApp.paths[scope.category] + 'istoobig.png'; + scope.noslider = attrs.noslider || false; + + if (!attrs.posturl) throw new TypeError('file-upload %s posturl=/api/xxxx/xxxx required', scope.attrs); + } + return { + restrict: 'E', + template: tmpl, + link: mymethods, + scope: { + callback : '=' + } + }; +}) + +.directive('uploadAudio', function(ConfigApp, JQemu, Notification) { + function mymethods(scope, elem, attrs) { + + // get widget image handle from template + scope.imgElem = elem.find('img'); + scope.inputElem = elem.find('input'); + + // Image was ckick let's simulate an input (file) click + scope.imgClicked = function () { + scope.inputElem[0].click(); // Warning Angular TriggerEvent does not work!!! + }; + + // Slider control handle registration after creation + scope.SliderInitCB=function (slider) { + scope.slider= slider; + }; + + // Upload is delegated to a shared function + scope.UpLoadFile=function (files) { + var posturl = attrs.posturl + "?token=" + ConfigApp.session.token; + LoadFileSvc (scope, elem, posturl, files, false); + }; + + // Initiallize default values from attributes values + scope.name= attrs.name || 'audio'; + scope.category= attrs.category || 'audio'; + scope.mimetype= (attrs.accept || 'audio') + '/*'; + scope.maxsize= attrs.maxsize || 10000; // default max size 10MB + scope.regexp = new RegExp (attrs.accept+ '.*','i'); + + if (attrs.thumbnail) scope.thumbnail= ConfigApp.paths[scope.category] + attrs.thumbnail; + else scope.thumbnail=ConfigApp.paths[scope.category] + 'upload-music.png'; + + if (attrs.thumbnail) scope.isnotvalid= ConfigApp.paths[scope.category] + attrs.isnotvalid; + else scope.isnotvalid=ConfigApp.paths[scope.category] + 'isnotvalid.png'; + + if (attrs.istoobig) scope.istoobig= ConfigApp.paths[scope.category] + attrs.istoobig; + else scope.istoobig=ConfigApp.paths[scope.category] + 'istoobig.png'; + scope.noslider = attrs.noslider || false; + + if (!attrs.posturl) throw new TypeError('file-upload %s posturl=/api/xxxx/xxxx required', scope.attrs); + } + return { + restrict: 'E', + template: tmpl, + link: mymethods, + scope: { + callback : '=' + } + }; + +}) + +.directive('uploadAppli', function(ConfigApp, JQemu, Notification) { + function mymethods(scope, elem, attrs) { + + // get widget image handle from template + scope.imgElem = elem.find('img'); + scope.inputElem = elem.find('input'); + + // Image was ckick let's simulate an input (file) click + scope.imgClicked = function () { + scope.inputElem[0].click(); // Warning Angular TriggerEvent does not work!!! + }; + + // Slider control handle registration after creation + scope.SliderInitCB=function (slider) { + scope.slider= slider; + }; + + // Upload is delegated to a shared function + scope.UpLoadFile=function (files) { + + var readerCB = function (upload) { + var zipapp = new JSZip(upload.target.result); + var thumbnail = zipapp.file("afa-pkg/thumbnail.jpg"); + + // Check is we have a thumbnail within loaded Zipfile + if (!thumbnail) { + console.log ("This is not a valid Application Framework APP"); + scope.thumbnail=ConfigApp.paths[scope.category] + 'isnotvalid.png'; + scope.$apply('thumbnail'); // we short-circuit Angular resync image + return; + } + scope.imgElem[0].src = window.URL.createObjectURL(new Blob([thumbnail.asArrayBuffer()], {type: "image"})); + scope.$apply('thumbnail'); // we short-circuit Angular resync image + }; + + var posturl = attrs.posturl + "?token=" + ConfigApp.session.token; + LoadFileSvc (scope, elem, posturl, files, readerCB); + }; + + // Initiallize default values from attributes values + scope.name= attrs.name || 'appli'; + scope.category= attrs.category || 'appli'; + scope.mimetype= (attrs.accept || '.zip'); + scope.maxsize= attrs.maxsize || 100000; // default max size 100MB + scope.regexp = new RegExp (attrs.accept+ '.*','i'); + + if (attrs.thumbnail) scope.thumbnail= ConfigApp.paths[scope.category] + attrs.thumbnail; + else scope.thumbnail=ConfigApp.paths[scope.category] + 'upload-appli.png'; + + if (attrs.thumbnail) scope.isnotvalid= ConfigApp.paths[scope.category] + attrs.isnotvalid; + else scope.isnotvalid=ConfigApp.paths[scope.category] + 'isnotvalid.png'; + + if (attrs.istoobig) scope.istoobig= ConfigApp.paths[scope.category] + attrs.istoobig; + else scope.istoobig=ConfigApp.paths[scope.category] + 'istoobig.png'; + scope.noslider = attrs.noslider || false; + + if (!attrs.posturl) throw new TypeError('file-upload %s posturl=/api/xxxx/xxxx required', scope.attrs); + } + return { + restrict: 'E', + template: tmpl, + link: mymethods, + scope: { + callback : '=' + } + }; + +}); + +console.log ("UploadFile Loaded"); +})(); diff --git a/afb-client/app/Frontend/widgets/FormInput/newjavascript.js b/afb-client/app/Frontend/widgets/FormInput/newjavascript.js new file mode 100644 index 0000000..10280c7 --- /dev/null +++ b/afb-client/app/Frontend/widgets/FormInput/newjavascript.js @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2015 fulup + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + var reader = new FileReader(); + // Closure to capture the file information. + reader.onload = (function(theFile) { + return function(e) { + var $title = $("<h4>", { + text : theFile.name + }); + $result.append($title); + var $fileContent = $("<ul>"); + try { + + var dateBefore = new Date(); + // read the content of the file with JSZip + var zip = new JSZip(e.target.result); + var dateAfter = new Date(); + + $title.append($("<span>", { + text:" (parsed in " + (dateAfter - dateBefore) + "ms)" + })); + + // that, or a good ol' for(var entryName in zip.files) + $.each(zip.files, function (index, zipEntry) { + $fileContent.append($("<li>", { + text : zipEntry.name + })); + // the content is here : zipEntry.asText() + }); + // end of the magic ! + + } catch(e) { + $fileContent = $("<div>", { + "class" : "alert alert-danger", + text : "Error reading " + theFile.name + " : " + e.message + }); + } + $result.append($fileContent); + } + })(f);
\ No newline at end of file |