From f1d531bf1e830c03a48a2e1ea70f4834b6a65c49 Mon Sep 17 00:00:00 2001 From: fdelencl42 Date: Mon, 3 Oct 2016 18:30:11 +0200 Subject: [PATCH 1/8] edit getmri/json route so it just gets info in DB and add POSTmri/json route to replace the previous get route --- controller/mri/index.js | 5 ++- controller/mri/mri.controller.js | 70 ++++++++++++++++++++++++-------- views/project.mustache | 2 +- 3 files changed, 57 insertions(+), 20 deletions(-) diff --git a/controller/mri/index.js b/controller/mri/index.js index 3d86ab1..6d0566f 100644 --- a/controller/mri/index.js +++ b/controller/mri/index.js @@ -6,7 +6,10 @@ var multer = require('multer'); var router = express.Router(); router.get('', controller.validator, controller.mri); -router.get('/json', controller.validator, controller.api_mri); +router.post('/json', controller.validator_post, controller.api_mri_post); +router.get('/json', controller.validator, controller.api_mri_get); +//TODO get->post +//todo new get route without download router.get('/upload', upload_controller.token); diff --git a/controller/mri/mri.controller.js b/controller/mri/mri.controller.js index 95802ec..eae4fab 100644 --- a/controller/mri/mri.controller.js +++ b/controller/mri/mri.controller.js @@ -8,6 +8,7 @@ var atlasMakerServer = require('../../js/atlasMakerServer'); //expressValidator = require('express-validator') var validator = function (req, res, next) { + console.log("post query, ", req.body); req.checkQuery('url', 'please enter a valid URL') .isURL(); @@ -23,6 +24,22 @@ var validator = function (req, res, next) { } }; +var validator_post = function (req, res, next) { + req.checkBody('url', 'please enter a valid URL') + .isURL(); + + // req.checkQuery('var', 'please enter one of the variables that are indicated') + // .optional() + // .matches("localpath|filename|source|url|dim|pixdim"); // todo: decent regexp + var errors = req.validationErrors(); + console.log(errors); + if (errors) { + res.send(errors).status(403).end(); + } else { + return next(); + } +}; + /* Download MRI file ---------------------*/ function downloadMRI(myurl, req, res, callback) { @@ -54,7 +71,6 @@ function downloadMRI(myurl, req, res, callback) { req.connection.socket.remoteAddress, username = (req.isAuthenticated()) ? req.user.username : ip, json = { - localpath: dest, filename: filename, success: true, source: myurl, @@ -138,8 +154,10 @@ var mri = function (req, res) { }); }; -var api_mri = function (req, res) { - var myurl = req.query.url, +var api_mri_post = function (req, res) { + console.log("post query, ", req.params); + + var myurl = req.body.url, hash = crypto.createHash('md5').update(myurl).digest('hex'); // shell equivalent: req.db.mri.find({source:"http://braincatalogue.org/data/Pineal/P001/t1wreq.db.nii.gz"}).limit(1).sort({$natural:-1}) @@ -147,28 +165,26 @@ var api_mri = function (req, res) { .then(function (json) { json = json[0]; if (json) { - if (req.query.var) { - var i, arr = req.query.var.split("/"); + if (req.body.var) { + var i, arr = req.body.var.split("/"); for (i in arr) { json = json[arr[i]]; } } res.json(json); } else { - if (req.query.var) { + if (req.body.var) { res.json({}); } else { - (function (my, rq, rs) { - downloadMRI(my, rq, rs, function (obj) { - if(obj) { - rq.db.get('mri').insert(obj); - rs.json(obj); - } else { - console.log("ERROR: Cannot read file"); - rs.json({}); - } - }); - }(myurl, req, res)); + downloadMRI(myurl, req, res, function (obj) { + if(obj) { + req.db.get('mri').insert(obj); + res.json(obj); + } else { + console.log("ERROR: Cannot read file"); + res.json({}); + } + }); } } }, function (err) { @@ -176,9 +192,27 @@ var api_mri = function (req, res) { }); }; +var api_mri_get = function (req, res) { + var myurl = req.query.url, + hash = crypto.createHash('md5').update(myurl).digest('hex'); + // shell equivalent: req.db.mri.find({source:"http://braincatalogue.org/data/Pineal/P001/t1wreq.db.nii.gz"}).limit(1).sort({$natural:-1}) + + req.db.get('mri').find({url: "/data/" + hash + "/", backup: {$exists: false}}, "-_id", {sort: {$natural: -1}, limit: 1}) + .then(function (json) { + res.status(200); + res.json(json); + }) + .catch(function(err) { + res.status(500); + res.json(err); + }); +}; + var mriController = function () { this.validator = validator; - this.api_mri = api_mri; + this.validator_post = validator_post; + this.api_mri_get = api_mri_get; + this.api_mri_post = api_mri_post; this.mri = mri; }; diff --git a/views/project.mustache b/views/project.mustache index 0307be2..1ad25c5 100644 --- a/views/project.mustache +++ b/views/project.mustache @@ -174,7 +174,7 @@ var str; function loadProjectFile(url) { var params={url:url,view:"cor",slice:180,fullscreen:false}; - $.get("/mri/json",{url:url}) + $.post("/mri/json",{url:url}) .done(function from_loadProjectFile(data) { if($.isEmptyObject(data) === false) { params.info=data; -- GitLab From 493367da3de09d9318d506e7295421c0fa6933b5 Mon Sep 17 00:00:00 2001 From: fdelencl42 Date: Tue, 4 Oct 2016 14:32:50 +0200 Subject: [PATCH 2/8] add placeholder to select tags --- views/project.mustache | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/views/project.mustache b/views/project.mustache index c6d6be6..61b3143 100644 --- a/views/project.mustache +++ b/views/project.mustache @@ -9,6 +9,10 @@ - - - - - - - - - - - diff --git a/public/js/atlasMaker-draw.js b/public/js/atlasMaker-draw.js index 41e9dfa..3af3f3c 100644 --- a/public/js/atlasMaker-draw.js +++ b/public/js/atlasMaker-draw.js @@ -1,11 +1,4 @@ -/** - * @page AtlasMaker: Image Drawing - */ - var AtlasMakerDraw = { - /** - * @function resizeWindow - */ resizeWindow: function resizeWindow() { var me=AtlasMakerWidget; var l=me.traceLog(resizeWindow,1);if(l)console.log(l); @@ -36,9 +29,6 @@ var AtlasMakerDraw = { } }, - /** - * @function configureBrainImage - */ configureBrainImage: function configureBrainImage() { var me=AtlasMakerWidget; var l=me.traceLog(configureBrainImage);if(l)console.log(l); @@ -72,9 +62,6 @@ var AtlasMakerDraw = { me.initCursor(); }, - /** - * @function configureAtlasImage - */ configureAtlasImage: function configureAtlasImage() { var me=AtlasMakerWidget; var l=me.traceLog(configureAtlasImage);if(l)console.log(l); @@ -84,9 +71,6 @@ var AtlasMakerDraw = { me.atlas_offcn.height=me.brain_H; me.atlas_px=me.atlas_offtx.getImageData(0,0,me.atlas_offcn.width,me.atlas_offcn.height); }, - /** - * @function nearestNeighbour - */ nearestNeighbour: function nearestNeighbour(ctx) { var me=AtlasMakerWidget; var l=me.traceLog(nearestNeighbour,1);if(l)console.log(l); @@ -94,9 +78,6 @@ var AtlasMakerDraw = { ctx.imageSmoothingEnabled = false; ctx.mozImageSmoothingEnabled = false; }, - /** - * @function computeSegmentedVolume - */ computeSegmentedVolume: function computeSegmentedVolume() { var me=AtlasMakerWidget; var l=me.traceLog(computeSegmentedVolume,1);if(l)console.log(l); @@ -111,9 +92,6 @@ var AtlasMakerDraw = { } return sum*me.User.pixdim[0]*me.User.pixdim[1]*me.User.pixdim[2]; }, - /** - * @function displayInformation - */ displayInformation: function displayInformation() { var me=AtlasMakerWidget; var l=me.traceLog(displayInformation,1);if(l)console.log(l); @@ -145,9 +123,6 @@ var AtlasMakerDraw = { } vector.html(str); }, - /** - * @function drawImages - */ drawImages: function drawImages() { var me=AtlasMakerWidget; var l=me.traceLog(drawImages,1);if(l)console.log(l); @@ -166,9 +141,6 @@ var AtlasMakerDraw = { me.sendRequestSliceMessage(); } }, - /** - * @function drawAtlasImage - */ drawAtlasImage: function drawAtlasImage(view,slice) { var me=AtlasMakerWidget; var l=me.traceLog(drawAtlasImage,1);if(l)console.log(l); diff --git a/public/js/atlasMaker-interaction.js b/public/js/atlasMaker-interaction.js index 3c22b80..935dea3 100644 --- a/public/js/atlasMaker-interaction.js +++ b/public/js/atlasMaker-interaction.js @@ -1,13 +1,7 @@ -/** - * @page AtlasMaker: Interaction - */ var AtlasMakerInteraction = { //======================================================================================== // Local user interaction //======================================================================================== - /** - * @function changeToolbarDisplay - */ changeToolbarDisplay: function changeToolbarDisplay(display) { var me=AtlasMakerWidget; var l=me.traceLog(changeToolbarDisplay);if(l)console.log(l); @@ -29,9 +23,6 @@ var AtlasMakerInteraction = { break; } }, - /** - * @function changeView - */ changeView: function changeView(theView) { var me=AtlasMakerWidget; var l=me.traceLog(changeView);if(l)console.log(l); @@ -59,9 +50,6 @@ var AtlasMakerInteraction = { me.initCursor(); }, - /** - * @function changeTool - */ changeTool: function changeTool(theTool) { var me=AtlasMakerWidget; var l=me.traceLog(changeTool);if(l)console.log(l); @@ -91,9 +79,6 @@ var AtlasMakerInteraction = { me.sendUserDataMessage(JSON.stringify({'tool':me.User.tool})); me.User.measureLength=null; }, - /** - * @function changePenSize - */ changePenSize: function changePenSize(theSize) { var me=AtlasMakerWidget; var l=me.traceLog(changePenSize);if(l)console.log(l); @@ -101,9 +86,6 @@ var AtlasMakerInteraction = { me.User.penSize=parseInt(theSize); me.sendUserDataMessage(JSON.stringify({'penSize':me.User.penSize})); }, - /** - * @function changePenColor - */ changePenColor: function changePenColor(index) { var me=AtlasMakerWidget; var l=me.traceLog(changePenColor);if(l)console.log(l); @@ -113,9 +95,6 @@ var AtlasMakerInteraction = { me.User.penValue=me.ontology.labels[index].value; me.sendUserDataMessage(JSON.stringify({'penValue':me.User.penValue})); }, - /** - * @function changeSlice - */ changeSlice: function changeSlice(x) { var me=AtlasMakerWidget; var l=me.traceLog(changeSlice,1);if(l)console.log(l); @@ -129,9 +108,6 @@ var AtlasMakerInteraction = { me.drawImages(); }, - /** - * @function prevSlice - */ prevSlice: function prevSlice() { var me=AtlasMakerWidget; var l=me.traceLog(prevSlice,1);if(l)console.log(l); @@ -144,9 +120,6 @@ var AtlasMakerInteraction = { me.changeSlice(x); } }, - /** - * @function nextSlice - */ nextSlice: function nextSlice() { var me=AtlasMakerWidget; var l=me.traceLog(nextSlice,1);if(l)console.log(l); @@ -160,9 +133,6 @@ var AtlasMakerInteraction = { me.changeSlice(x); } }, - /** - * @function toggleFill - */ toggleFill: function toggleFill(x) { var me=AtlasMakerWidget; var l=me.traceLog(toggleFill);if(l)console.log(l); @@ -170,18 +140,12 @@ var AtlasMakerInteraction = { me.User.doFill=x; me.sendUserDataMessage(JSON.stringify({'doFill':me.User.doFill})); }, - /** - * @function toggleChat - */ toggleChat: function toggleChat() { var me=AtlasMakerWidget; var l=me.traceLog(toggleChat);if(l)console.log(l); $("#chatBlock").toggle(); }, - /** - * @function toggleFullscreen - */ toggleFullscreen: function toggleFullscreen() { var me=AtlasMakerWidget; var l=me.traceLog(toggleFullscreen);if(l)console.log(l); @@ -224,9 +188,6 @@ var AtlasMakerInteraction = { me.fullscreen=false; } }, - /** - * @function render3D - */ render3D: function render3D() { var me=AtlasMakerWidget; var l=me.traceLog(render3D);if(l)console.log(l); @@ -237,17 +198,11 @@ var AtlasMakerInteraction = { // opens 3d render window window.open("/templates/surface.html?path="+me.User.dirname+me.User.atlasFilename,"_blank"); }, - /** - * @function link - */ link: function link() { var me=AtlasMakerWidget; var l=me.traceLog(link);if(l)console.log(l); window.prompt("Copy to clipboard:", location.href+"&view="+AtlasMakerWidget.User.view+"&slice="+AtlasMakerWidget.User.slice); }, - /** - * @function upload - */ upload: function upload() { var me=AtlasMakerWidget; var l=me.traceLog(upload);if(l)console.log(l); @@ -297,9 +252,6 @@ var AtlasMakerInteraction = { } input.click(); }, - /** - * @function download - */ download: function download() { var me=AtlasMakerWidget; var l=me.traceLog(download);if(l)console.log(l); @@ -312,9 +264,6 @@ var AtlasMakerInteraction = { document.body.appendChild(a); a.click(); }, - /** - * @function color - */ color: function color() { var me=AtlasMakerWidget; var l=me.traceLog(color);if(l)console.log(l); @@ -339,9 +288,6 @@ var AtlasMakerInteraction = { la.show(); } }, - /** - * @function ontologyValueToColor - */ ontologyValueToColor: function ontologyValueToColor(val) { var me=AtlasMakerWidget; var l=me.traceLog(ontologyValueToColor,3);if(l)console.log(l); @@ -357,9 +303,6 @@ var AtlasMakerInteraction = { } return c; }, - /** - * @function togglePreciseCursor - */ togglePreciseCursor: function togglePreciseCursor() { var me=AtlasMakerWidget; var l=me.traceLog(togglePreciseCursor);if(l)console.log(l); @@ -367,9 +310,6 @@ var AtlasMakerInteraction = { me.flagUsePreciseCursor=!me.flagUsePreciseCursor; me.initCursor(); }, - /** - * @function initCursor - */ initCursor: function initCursor() { var me=AtlasMakerWidget; var l=me.traceLog(initCursor,1);if(l)console.log(l); @@ -414,9 +354,6 @@ var AtlasMakerInteraction = { me.canvas.ontouchend=me.touchend; } }, - /** - * @function updateCursor - */ updateCursor: function updateCursor() { var me=AtlasMakerWidget; var l=me.traceLog(updateCursor,1);if(l)console.log(l); @@ -430,9 +367,6 @@ var AtlasMakerInteraction = { //$("#msg").html(C.state); //console.log(Crsr.state); }, - /** - * @function mousedown - */ mousedown: function mousedown(e) { var me=AtlasMakerWidget; var l=me.traceLog(mousedown);if(l)console.log(l); @@ -449,9 +383,6 @@ var AtlasMakerInteraction = { var y=parseInt((e.pageY-o.top)*(h/H)); me.down(x,Math.round(y*me.brain_Wdim/me.brain_Hdim)); }, - /** - * @function mousemove - */ mousemove: function mousemove(e) { var me=AtlasMakerWidget; var l=me.traceLog(mousemove,2);if(l)console.log(l); @@ -473,18 +404,12 @@ var AtlasMakerInteraction = { }); me.move(x,Math.round(y*me.brain_Wdim/me.brain_Hdim)); }, - /** - * @function mouseup - */ mouseup: function mouseup(e) { var me=AtlasMakerWidget; var l=me.traceLog(mouseup);if(l)console.log(l); me.up(e); }, - /** - * @function touchstart - */ touchstart: function touchstart(e) { var me=AtlasMakerWidget; var l=me.traceLog(touchstart);if(l)console.log(l); @@ -532,9 +457,6 @@ var AtlasMakerInteraction = { } else me.down(x,Math.round(y*me.brain_Wdim/me.brain_Hdim)); }, - /** - * @function touchmove - */ touchmove: function touchmove(e) { var me=AtlasMakerWidget; var l=me.traceLog(touchmove,2);if(l)console.log(l); @@ -585,9 +507,6 @@ var AtlasMakerInteraction = { me.move(x,Math.round(y*me.brain_Wdim/me.brain_Hdim)); } }, - /** - * @function touchend - */ touchend: function touchend(e) { var me=AtlasMakerWidget; var l=me.traceLog(touchend);if(l)console.log(l); @@ -604,9 +523,6 @@ var AtlasMakerInteraction = { } me.up(e); }, - /** - * @function down - */ down: function down(x,y) { var me=AtlasMakerWidget; var l=me.traceLog(down,2);if(l)console.log(l); @@ -654,9 +570,6 @@ var AtlasMakerInteraction = { // init annotation length counter me.annotationLength=0; }, - /** - * @function move - */ move: function move(x,y) { var me=AtlasMakerWidget; var l=me.traceLog(move,2);if(l)console.log(l); @@ -694,9 +607,6 @@ var AtlasMakerInteraction = { */ }, - /** - * @function up - */ up: function up(e) { var me=AtlasMakerWidget; var l=me.traceLog(up,2);if(l)console.log(l); @@ -722,9 +632,6 @@ var AtlasMakerInteraction = { var vol=me.computeSegmentedVolume(); me.info.volume=parseInt(vol)+" mm3"; }, - /** - * @function keyDown - */ keyDown: function keyDown(e) { var me=AtlasMakerWidget; var l=me.traceLog(keyDown,2);if(l)console.log(l); @@ -762,9 +669,6 @@ var AtlasMakerInteraction = { break; } }, - /** - * @function onkey - */ onkey: function onkey(e) { var me=AtlasMakerWidget; var l=me.traceLog(onkey,2);if(l)console.log(l); diff --git a/public/js/atlasMaker-io.js b/public/js/atlasMaker-io.js index 4f5175e..838929d 100644 --- a/public/js/atlasMaker-io.js +++ b/public/js/atlasMaker-io.js @@ -1,10 +1,4 @@ -/** - * @page AtlasMaker: Input/Output - */ var AtlasMakerIO = { - /** - * @function encodeNifti - */ encodeNifti: function encodeNifti() { var me=AtlasMakerWidget; var l=me.traceLog(encodeNifti);if(l)console.log(l); @@ -47,9 +41,6 @@ var AtlasMakerIO = { return niigz.result; }, - /** - * @function saveNifti - */ saveNifti: function saveNifti() { var me=AtlasMakerWidget; var l=me.traceLog(saveNifti);if(l)console.log(l); @@ -60,9 +51,6 @@ var AtlasMakerIO = { $("a#download_atlas").attr("href",window.URL.createObjectURL(niigzBlob)); $("a#download_atlas").attr("download",me.User.atlasFilename); }, - /** - * @function loadNifti - */ loadNifti: function loadNifti(nii) { var me=AtlasMakerWidget; var l=me.traceLog(loadNifti,1);if(l)console.log(l); @@ -108,9 +96,6 @@ var AtlasMakerIO = { /* {Linear algebra */ - /** - * @function computeS2VTransformation - */ computeS2VTransformation: function computeS2VTransformation() { var me=AtlasMakerWidget; var l=me.traceLog(computeS2VTransformation);if(l)console.log(l); @@ -125,7 +110,7 @@ var AtlasMakerIO = { var w2s=[[1/Math.abs(wpixdim[0]),0,0],[0,1/Math.abs(wpixdim[1]),0],[0,0,1/Math.abs(wpixdim[2])]]; var s2w=me.invMat(w2s); - // console.log(["v2w",v2w, "wori",wori, "wpixdim",wpixdim, "wvmax",wvmax, "wvmin",wvmin, "wmin",wmin, "wmax",wmax, "w2s",w2s]); + console.log(["v2w",v2w, "wori",wori, "wpixdim",wpixdim, "wvmax",wvmax, "wvmin",wvmin, "wmin",wmin, "wmax",wmax, "w2s",w2s]); me.User.s2v = { sdim: [(wmax[0]-wmin[0])/Math.abs(wpixdim[0])+1,(wmax[1]-wmin[1])/Math.abs(wpixdim[1])+1,(wmax[2]-wmin[2])/Math.abs(wpixdim[2])+1], @@ -136,9 +121,6 @@ var AtlasMakerIO = { wori: wori }; }, - /** - * @function testS2VTransformation - */ testS2VTransformation: function testS2VTransformation() { var me=AtlasMakerWidget; var l=me.traceLog(testS2VTransformation);if(l)console.log(l); @@ -150,51 +132,44 @@ var AtlasMakerIO = { var mri=me.User; // this line is different from server var doReset=false; - // console.log("Transformation TEST:"); - // console.log(" 1. transformation volume"); - + console.log("Transformation TEST:"); + + console.log(" 1. transformation volume"); var vv=mri.dim[0]*mri.dim[1]*mri.dim[2]; var vs=mri.s2v.sdim[0]*mri.s2v.sdim[1]*mri.s2v.sdim[2]; var diff=(vs-vv)/vv; if(Math.abs(diff)>0.001) { - /* console.log(" ERROR: Difference is too large"); console.log(" original volume:",vv); console.log(" rotated volume:",vs); console.log(" % difference:",diff*100); - */ doReset=true; } else { - // console.log(" ok."); + console.log(" ok."); } - // console.log(" 2. transformation origin"); + console.log(" 2. transformation origin"); if( mri.s2v.sori[0]<0||mri.s2v.sori[0]>mri.s2v.sdim[0] || mri.s2v.sori[1]<0||mri.s2v.sori[1]>mri.s2v.sdim[1] || mri.s2v.sori[2]<0||mri.s2v.sori[2]>mri.s2v.sdim[2]) { - // console.log(" Origin point is outside the dimensions of the data"); + console.log(" Origin point is outside the dimensions of the data"); doReset=true; } else { - // console.log(" ok."); + console.log(" ok."); } if(doReset) { - // console.log("THE TRANSFORMATION WILL BE RESET"); + console.log("THE TRANSFORMATION WILL BE RESET"); mri.v2w=[[mri.pixdim[0],0,0],[0,-mri.pixdim[1],0],[0,0,-mri.pixdim[2]]]; mri.wori=[0,mri.dim[1]-1,mri.dim[2]-1]; // re-compute the transformation from voxel space to screen space me.computeS2VTransformation(); // this line is different from server - /* console.log(mri.dir); console.log(mri.ori); console.log(mri.s2v); - */ } }, - /** - * @function S2I - */ S2I: function S2I(s,mri) { var me=AtlasMakerWidget; var l=me.traceLog(S2I,3);if(l)console.log(l); @@ -208,9 +183,6 @@ var AtlasMakerIO = { i= v[2]*mri.dim[1]*mri.dim[0]+ v[1]*mri.dim[0] +v[0]; return i; }, - /** - * @function mulMatVec - */ mulMatVec: function mulMatVec(m,v) { return [ m[0][0]*v[0]+m[0][1]*v[1]+m[0][2]*v[2], @@ -218,9 +190,6 @@ var AtlasMakerIO = { m[2][0]*v[0]+m[2][1]*v[1]+m[2][2]*v[2] ]; }, - /** - * @function invMat - */ invMat: function invMat(m) { var det; var w=[[],[],[]]; @@ -241,15 +210,9 @@ var AtlasMakerIO = { return w; }, - /** - * @function subVecVec - */ subVecVec: function subVecVec(a,b) { return [a[0]-b[0],a[1]-b[1],a[2]-b[2]]; }, - /** - * @function addVecVec - */ addVecVec: function addVecVec(a,b) { return [a[0]+b[0],a[1]+b[1],a[2]+b[2]]; }, diff --git a/public/js/atlasMaker-paint.js b/public/js/atlasMaker-paint.js index 7801e31..e456361 100644 --- a/public/js/atlasMaker-paint.js +++ b/public/js/atlasMaker-paint.js @@ -1,13 +1,7 @@ -/** - * @page AtlasMaker: Painting commands - */ var AtlasMakerPaint = { //==================================================================================== // Paint functions common to all users //==================================================================================== - /** - * @function paintxy - */ paintxy: function paintxy(u,c,x,y,usr) { var me=AtlasMakerWidget; var l=me.traceLog(paintxy,1);if(l)console.log(l); @@ -48,9 +42,6 @@ var AtlasMakerPaint = { usr.x0=coord.x; usr.y0=coord.y; }, - /** - * @function paintvol - */ paintvol: function paintvol(voxels) { /* this function is exclusively used for undoing */ var me=AtlasMakerWidget; @@ -68,9 +59,6 @@ var AtlasMakerPaint = { me.drawImages(); }, - /** - * @function fill - */ fill: function fill(x,y,z,val,myView) { var me=AtlasMakerWidget; var l=me.traceLog(fill);if(l)console.log(l); @@ -103,9 +91,6 @@ var AtlasMakerPaint = { } me.drawImages(); }, - /** - * @function line - */ line: function line(x,y,val,usr) { var me=AtlasMakerWidget; var l=me.traceLog(line,1);if(l)console.log(l); @@ -161,9 +146,6 @@ var AtlasMakerPaint = { } me.drawImages(); }, - /** - * @function slice2index - */ slice2index: function slice2index(mx,my,mz,myView) { var me=AtlasMakerWidget; var l=me.traceLog(slice2index,3);if(l)console.log(l); @@ -185,9 +167,6 @@ var AtlasMakerPaint = { */ return i; }, - /** - * @function slice2xyzi - */ slice2xyzi: function slice2xyzi(mx,my,mz,myView) { var me=AtlasMakerWidget; var l=me.traceLog(slice2xyzi,1);if(l)console.log(l); diff --git a/public/js/atlasMaker-ui.js b/public/js/atlasMaker-ui.js index 66e2c77..e0fce2c 100644 --- a/public/js/atlasMaker-ui.js +++ b/public/js/atlasMaker-ui.js @@ -1,10 +1,4 @@ -/** - * @page AtlasMaker: User Interface Elements - */ var AtlasMakerUI = { - /** - * @function slider - */ slider: function slider(elem,callback) { var me=AtlasMakerWidget; var l=me.traceLog(slider,2);if(l)console.log(l); @@ -34,9 +28,6 @@ var AtlasMakerUI = { $(document).on("mouseup touchend",function from_slider(){$(elem).data({drag:false})}); $(elem).on('mousedown touchstart',function from_slider(){$(elem).data({drag:true})}); }, - /** - * @function chose - */ chose: function chose(elem,callback) { // Initialise a 'chose' control var ch=$(elem).find(".a"); @@ -53,9 +44,6 @@ var AtlasMakerUI = { }); }); }, - /** - * @function toggle - */ toggle: function toggle(elem,callback) { // Initialise a 'toggle' control $(elem).click(function(){ @@ -64,9 +52,6 @@ var AtlasMakerUI = { callback($(this).hasClass("pressed")); }); }, - /** - * @function push - */ push: function push(elem,callback) { // Initialise a 'push' control $(elem).click(function(){ diff --git a/public/js/atlasMaker-ws.js b/public/js/atlasMaker-ws.js index 357c8d5..6a89994 100644 --- a/public/js/atlasMaker-ws.js +++ b/public/js/atlasMaker-ws.js @@ -1,13 +1,7 @@ -/** - * @page AtlasMaker: WebSockets - */ var AtlasMakerWS = { //==================================================================================== // Web sockets //==================================================================================== - /** - * @function createSocket - */ createSocket: function createSocket(host) { var me=AtlasMakerWidget; var l=me.traceLog(createSocket);if(l)console.log(l); @@ -22,9 +16,6 @@ var AtlasMakerWS = { return ws; }, - /** - * @function initSocketConnection - */ initSocketConnection: function initSocketConnection() { var me=AtlasMakerWidget; var l=me.traceLog(initSocketConnection);if(l)console.log(l); @@ -69,9 +60,6 @@ var AtlasMakerWS = { return def.promise(); }, - /** - * @function receiveSocketMessage - */ receiveSocketMessage: function receiveSocketMessage(msg) { var me=AtlasMakerWidget; var l=me.traceLog(receiveSocketMessage,1);if(l)console.log(l); @@ -97,9 +85,6 @@ var AtlasMakerWS = { */ switch(data.type) { - case "saveMetadata" : - me.receiveMetaData(data); - break; case "userData": me.receiveUserDataMessage(data); break; @@ -120,9 +105,6 @@ var AtlasMakerWS = { break; } }, - /** - * @function sendUserDataMessage - */ sendUserDataMessage: function sendUserDataMessage(description) { var me=AtlasMakerWidget; var l=me.traceLog(sendUserDataMessage,1);if(l)console.log(l); @@ -142,9 +124,6 @@ var AtlasMakerWS = { console.log("ERROR: Unable to sendUserDataMessage",ex); } }, - /** - * @function receiveBinaryMessage - */ receiveBinaryMessage: function receiveBinaryMessage(msgData) { var me=AtlasMakerWidget; var l=me.traceLog(receiveBinaryMessage,1);if(l)console.log(l); @@ -216,9 +195,6 @@ var AtlasMakerWS = { }; fileReader.readAsArrayBuffer(msgData); }, - /** - * @function receiveUserDataMessage - */ receiveUserDataMessage: function receiveUserDataMessage(data) { var me=AtlasMakerWidget; var l=me.traceLog(receiveUserDataMessage);if(l)console.log(l); @@ -255,9 +231,6 @@ var AtlasMakerWS = { var v,nusers=1; for(v in me.Collab) nusers++; $("#chat").text("Chat ("+nusers+" connected)"); }, - /** - * @function sendChatMessage - */ sendChatMessage: function sendChatMessage() { var me=AtlasMakerWidget; var l=me.traceLog(sendChatMessage);if(l)console.log(l); @@ -275,9 +248,6 @@ var AtlasMakerWS = { console.log("ERROR: Unable to sendChatMessage",ex); } }, - /** - * @function receiveChatMessage - */ receiveChatMessage: function receiveChatMessage(data) { var me=AtlasMakerWidget; var l=me.traceLog(receiveChatMessage);if(l)console.log(l); @@ -290,9 +260,6 @@ var AtlasMakerWS = { $("#log").append(msg); $("#log").scrollTop($("#log")[0].scrollHeight); }, - /** - * @function sendPaintMessage - */ sendPaintMessage: function sendPaintMessage(msg) { var me=AtlasMakerWidget; var l=me.traceLog(sendPaintMessage,1);if(l)console.log(l); @@ -305,9 +272,6 @@ var AtlasMakerWS = { console.log("ERROR: Unable to sendPaintMessage",ex); } }, - /** - * @function receivePaintMessage - */ receivePaintMessage: function receivePaintMessage(data) { var me=AtlasMakerWidget; var l=me.traceLog(receivePaintMessage,3);if(l)console.log(l); @@ -320,9 +284,6 @@ var AtlasMakerWS = { me.paintxy(u,c,x,y,me.Collab[u]); }, - /** - * @function receivePaintVolumeMessage - */ receivePaintVolumeMessage: function receivePaintVolumeMessage(data) { var me=AtlasMakerWidget; var l=me.traceLog(receivePaintVolumeMessage);if(l)console.log(l); @@ -332,9 +293,6 @@ var AtlasMakerWS = { voxels=data.data; me.paintvol(voxels.data); }, - /** - * @function sendUndoMessage - */ sendUndoMessage: function sendUndoMessage() { var me=AtlasMakerWidget; var l=me.traceLog(sendUndoMessage);if(l)console.log(l); @@ -347,9 +305,6 @@ var AtlasMakerWS = { console.log("ERROR: Unable to sendUndoMessage",ex); } }, - /** - * @function sendRequestSliceMessage - */ sendRequestSliceMessage: function sendRequestSliceMessage() { var me=AtlasMakerWidget; var l=me.traceLog(sendRequestSliceMessage,1);if(l)console.log(l); @@ -372,23 +327,6 @@ var AtlasMakerWS = { console.log("ERROR: Unable to sendRequestSliceMessage",ex); } }, - receiveMetaData: function receiveMetaData(data) { -// console.log(info_proxy); -// console.log(info_proxy.files); - for (var i in projectInfo.files.list) { - if (projectInfo.files.list[i].source == data.metadata.source) { - for (var key in projectInfo.files.list[i].mri.annotations) { - info_proxy["files.list." + i + ".mri.annotations." + key] = data.metadata.mri.annotations[key]; - } - info_proxy["files.list." + i + ".name"] = data.metadata.name; - break; - } - } - console.log("JUST RECIEVED SOME MORE DATA", data.metadata); - }, - /** - * @function sendSaveMetadataMessage - */ sendSaveMetadataMessage: function sendSaveMetadataMessage(info) { var me=AtlasMakerWidget; var l=me.traceLog(sendSaveMetadataMessage,1);if(l)console.log(l); @@ -401,9 +339,6 @@ var AtlasMakerWS = { console.log("ERROR: Unable to sendSaveMetadataMessage",ex); } }, - /** - * @function receiveDisconnectMessage - */ receiveDisconnectMessage: function receiveDisconnectMessage(data) { var me=AtlasMakerWidget; var l=me.traceLog(receiveDisconnectMessage);if(l)console.log(l); diff --git a/public/js/atlasMaker.js b/public/js/atlasMaker.js index 8b07128..6249ef5 100755 --- a/public/js/atlasMaker.js +++ b/public/js/atlasMaker.js @@ -1,11 +1,8 @@ -/** - * @page AtlasMaker - */ var AtlasMakerWidget = { //======================================================================================== // Globals //======================================================================================== - debug: 0, + debug: 2, container: null, // Element where atlasMaker lives brain_offcn: null, brain_offtx: null, @@ -80,17 +77,11 @@ var AtlasMakerWidget = { /* DEPRECATED Undo:[], */ version: 1, // version of the configuration file (slice number, plane, etc). Default=1 - /** - * @function traceLog - */ traceLog: function traceLog(f,l) { var me=AtlasMakerWidget; - if(me.debug && (l==undefined || me.debug>l)) + if(l==undefined || me.debug>l) return "am> "+(f.name)+" "+(f.caller?(f.caller.name||"annonymous"):"root"); }, - /** - * @function quit - */ quit: function quit() { var me=AtlasMakerWidget; var l=me.traceLog(quit);if(l)console.log(l); @@ -102,9 +93,6 @@ var AtlasMakerWidget = { //========== // Database //========== - /** - * @function logToDatabase - */ logToDatabase: function logToDatabase(key,value) { var def=$.Deferred(); var me=AtlasMakerWidget; @@ -130,9 +118,6 @@ var AtlasMakerWidget = { //==================================================================================== // Configuration //==================================================================================== - /** - * @function initAtlasMaker - */ initAtlasMaker: function initAtlasMaker(elem) { var me=AtlasMakerWidget; var l=me.traceLog(initAtlasMaker);if(l)console.log(l); @@ -243,9 +228,6 @@ var AtlasMakerWidget = { return def.promise(); }, - /** - * @function configureAtlasMaker - */ configureAtlasMaker: function configureAtlasMaker(info,index) { var me=AtlasMakerWidget; var l=me.traceLog(configureAtlasMaker);if(l)console.log(l); @@ -279,9 +261,6 @@ var AtlasMakerWidget = { return def.promise(); }); }, - /** - * @function configureOntology - */ configureOntology: function configureOntology(json) { var me=AtlasMakerWidget; var l=me.traceLog(configureOntology);if(l)console.log(l); @@ -290,9 +269,6 @@ var AtlasMakerWidget = { me.ontology.valueToIndex=[]; me.ontology.labels.forEach(function(o,i){me.ontology.valueToIndex[o.value]=i}); }, - /** - * @function configureMRI - */ configureMRI: function configureMRI(info,index) { var me=AtlasMakerWidget; var l=me.traceLog(configureMRI);if(l)console.log(l); diff --git a/public/js/brainbox.js b/public/js/brainbox.js index 0f85838..e63f9ec 100644 --- a/public/js/brainbox.js +++ b/public/js/brainbox.js @@ -1,26 +1,13 @@ -/** - * @library BrainBox - * @version 0.0.1 - * @brief Real-time collaboration in neuroimaging - */ - -/** - * @page BrainBox - */ - var BrainBox={ version: 1, - debug: 0, + debug: 1, info:{}, labelSets:null, access:["Read/Write","Read"], annotationType:["volume","text"], - /** - * @function traceLog - */ traceLog: function traceLog(f,l) { - if(BrainBox.debug && (l==undefined || BrainBox.debug>l)) + if(l==undefined || BrainBox.debug>l) return "bb> "+(f.name)+" "+(f.caller?(f.caller.name||"annonymous"):"root"); }, @@ -28,9 +15,6 @@ var BrainBox={ JavaScript implementation of Java's hashCode method from http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/ */ - /** - * @function hash - */ hash: function hash(str) { console.log(BrainBox.traceLog(hash)); @@ -49,9 +33,6 @@ var BrainBox={ } return res; }, - /** - * @function loadScript - */ loadScript: function loadScript(path) { var def = new $.Deferred(); var s = document.createElement("script"); @@ -62,9 +43,6 @@ var BrainBox={ document.body.appendChild(s); return def.promise(); }, - /** - * @function initBrainBox - */ initBrainBox: function initBrainBox() { console.log(BrainBox.traceLog(initBrainBox)); @@ -100,9 +78,6 @@ var BrainBox={ return def.promise(); }, - /** - * @function configureBrainBox - */ configureBrainBox: function configureBrainBox(param) { console.log(BrainBox.traceLog(configureBrainBox)); @@ -168,9 +143,6 @@ var BrainBox={ return def.promise(); }, - /** - * @function unload - */ unload: function unload() { console.log(BrainBox.traceLog(unload)); var foundStored=false; @@ -200,9 +172,6 @@ var BrainBox={ /* Annotation related functions */ - /** - * @function selectAnnotationTableRow - */ selectAnnotationTableRow: function selectAnnotationTableRow() { console.log(BrainBox.traceLog(selectAnnotationTableRow)); @@ -218,9 +187,6 @@ var BrainBox={ AtlasMakerWidget.configureAtlasMaker(BrainBox.info,index); } }, - /** - * @function appendAnnotationTableRow - */ appendAnnotationTableRow: function appendAnnotationTableRow(irow,param) { console.log(BrainBox.traceLog(appendAnnotationTableRow)); @@ -250,9 +216,6 @@ var BrainBox={ } } }, - /** - * @function addAnnotation - */ addAnnotation: function addAnnotation(param) { console.log(BrainBox.traceLog(addAnnotation)); @@ -277,9 +240,6 @@ var BrainBox={ // update in server BrainBox.saveAnnotations(param); }, - /** - * @function removeAnnotation - */ removeAnnotation: function removeAnnotation(param) { console.log(BrainBox.traceLog(removeAnnotation)); @@ -300,9 +260,6 @@ var BrainBox={ // update in server BrainBox.saveAnnotations(param); }, - /** - * @function saveAnnotations - */ saveAnnotations: function saveAnnotations(param) { console.log(BrainBox.traceLog(saveAnnotations)); @@ -311,9 +268,6 @@ var BrainBox={ hash_old=BrainBox.hash(JSON.stringify(BrainBox.info)); $(param.saveWarning).hide(); }, - /** - * @function loadLabelsets - */ loadLabelsets: function loadLabelsets() { console.log(BrainBox.traceLog(loadLabelsets)); diff --git a/public/js/twoWayBinding.js b/public/js/twoWayBinding.js index 051b793..903fef0 100644 --- a/public/js/twoWayBinding.js +++ b/public/js/twoWayBinding.js @@ -1,5 +1,5 @@ /** - * @page Two-Way Binding + * @namespace Two-Way Binding */ var date_format=function(e,d){$(e).text(new Date(d).toLocaleDateString())}; @@ -17,8 +17,7 @@ var date_format=function(e,d){$(e).text(new Date(d).toLocaleDateString())}; */ /** - * @function bind2 - * @desc Bind a javascript object with a DOM element and viceversa + * Bind a javascript object with a DOM element and viceversa * @param {object} proxy The object that will bind the source object and the DOM element * @param {object} original The source object to bind * @param {string} path Path to the property in the original object to bind @@ -53,8 +52,7 @@ function bind2(proxy,original,path,el,format,parse) { } /** - * @function bind1 - * @desc Bind the content of a DOM element to javascript object, but not the other way around + * Bind the content of a DOM element to javascript object, but not the other way around * @param {object} proxy The object that will bind the source object and the DOM element * @param {object} original The source object to bind * @param {string} path Path to the property in the original object to bind @@ -84,8 +82,7 @@ function bind2(proxy,original,path,el,format,parse) { } /** - * @function unbind2 - * @desc Unbind a javascript object and a DOM element + * Unbind a javascript object and a DOM element * @param {object} proxy The object that will bind the source object and the DOM element * @param {string} path Path to the property in the original object to bind */ diff --git a/views/project.mustache b/views/project.mustache index c6d6be6..1ad25c5 100644 --- a/views/project.mustache +++ b/views/project.mustache @@ -64,6 +64,8 @@ Name File + QC + QC Comment @@ -177,10 +179,6 @@ function loadProjectFile(url) { if($.isEmptyObject(data) === false) { params.info=data; BrainBox.configureBrainBox(params) - .then(function from_project(){ - AtlasMakerWidget.User.projectPage = projectInfo.shortname; - AtlasMakerWidget.sendUserDataMessage(JSON.stringify({projectPage:projectInfo.shortname})) - }); } else { var info=AtlasMakerWidget.container.find("#info"); info.html("ERROR: File is unreadable"); @@ -245,34 +243,44 @@ $("#projectFilesNumber").text(projectInfo.files.list.length+" Files"); $("#projectCollaboratorsNumber").text(projectInfo.collaborators.length+" Collaborators"); /* - The list of all files included in the project + The list of all collaborators participating in the project + (should be recovered from the database) */ +str=[ "", + "Name", + "Last visited", + ""].join(); +for(var i=0;i", + " ", + " "+projectInfo.collaborators[i]+"", + " ", + " 14 July 2016", + ""].join(""); +} +$("#collaborators").append(str); - //setup the names of the columns - var k, txtAnnotations = []; - for(k in projectInfo.annotations.list) { - if (projectInfo.annotations.list[k].type === "text") { - $("#projectFiles thead tr").append("" + projectInfo.annotations.list[k].name + ""); - txtAnnotations.push(projectInfo.annotations.list[k]); - } - } - - // Add the 'annotations' object to mri if it does not exist - var k; - for(k in projectInfo.files.list) { - if (!(projectInfo.files.list[k].mri)) - projectInfo.files.list[k].mri = {}; - if (!(projectInfo.files.list[k].mri.annotations)) - projectInfo.files.list[k].mri.annotations = {}; - /** - * @todo delete: undefined properties are created on assignment as far as the object exists - */ -// if (!(projectInfo.files.list[f].mri.annotations[projectInfo.annotations.list[k].name])) -// projectInfo.files.list[f].mri.annotations[projectInfo.annotations.list[k].name] = ""; - } +/* + The list of all files included in the project +*/ +str=[]; +for(var i=0;i", + " ", + " "+filename+"", + " ", + " ", + ""].join(""); +} +$("#projectFiles tbody").append(str); +for(var i=0;i", - " ", - " " - ]; - for(var g in txtAnnotations) { - if(txtAnnotations[g].values) { - trTemplate.push(""); - - /** - * @todo Why the closures if there's nothing asynchronous?? - */ - objTemplate.push({ - typeOfBinding:2, - path:"files.list.#.mri.annotations." + txtAnnotations[g].name, - format: function(e, d){$(e).find("select").get(0).value=d}, - parse: function(e){return $(e).find("select").val()} - }); - - } else { - trTemplate.push(""); - objTemplate.push({ - typeOfBinding:2, - path:"files.list.#.mri.annotations." + txtAnnotations[g].name - }); - } - } - trTemplate.push(""); - var aParam = { - table: $("#projectFiles table"), - info_proxy: info_proxy, - info: projectInfo, - trTemplate: trTemplate.join("\n"), - objTemplate: objTemplate - }; - - for(var i=0;i changes value to trigger data sending - $("#projectFiles table tbody").on('change', "select", function(e) { - $(e.target).blur(); - }); - -// listen to changes in file selection by clicking on the file table +// listen to changes in file selection by clicking of the file table $(document).on('click', "#projectFiles tbody tr",function() { + console.log(">> selectProjectFilesTableRow()"); var table=$(this).closest("table"); var currentIndex=$(table).find("tr.selected").index(); -- GitLab From 215bbc2d5f858eba7fa9faaff007805088788eaf Mon Sep 17 00:00:00 2001 From: fdelencl42 Date: Tue, 4 Oct 2016 15:30:42 +0200 Subject: [PATCH 5/8] Revert "Revert "conflicts fixed"" This reverts commit 2691e1808cc17cab2bf2f49ddf01e3c0360044a1. --- controller/mri/mri.controller.js | 11 +- controller/project/project.controller.js | 11 +- js/atlasMakerServer.js | 53 +++++--- public/doc/brainbox.md | 10 ++ public/doc/code.html | 30 +++++ public/js/atlasMaker-draw.js | 28 +++++ public/js/atlasMaker-interaction.js | 96 +++++++++++++++ public/js/atlasMaker-io.js | 55 +++++++-- public/js/atlasMaker-paint.js | 21 ++++ public/js/atlasMaker-ui.js | 15 +++ public/js/atlasMaker-ws.js | 65 ++++++++++ public/js/atlasMaker.js | 28 ++++- public/js/brainbox.js | 50 +++++++- public/js/twoWayBinding.js | 11 +- views/project.mustache | 146 +++++++++++++++++------ 15 files changed, 552 insertions(+), 78 deletions(-) create mode 100644 public/doc/code.html diff --git a/controller/mri/mri.controller.js b/controller/mri/mri.controller.js index eae4fab..7e471b3 100644 --- a/controller/mri/mri.controller.js +++ b/controller/mri/mri.controller.js @@ -114,11 +114,13 @@ var mri = function (req, res) { : ("Log in with GitHub"); var myurl = req.query.url, hash = crypto.createHash('md5').update(myurl).digest('hex'); - req.db.get('mri').find({url: "/data/" + hash + "/"}, {fields: {_id: 0}, sort: {$natural: -1}, limit: 1}) + console.log("query",myurl,hash); + req.db.get('mri').find({url: "/data/" + hash + "/", backup:{$exists:0}}, {fields: {_id: 0}, sort: {$natural: -1}, limit: 1}) .then(function (json) { - console.log(json); + console.log("json",json); json = json[0]; if (json) { + console.log("render with json"); res.render('mri', { title: json.name || 'Untitled MRI', params: JSON.stringify(req.query), @@ -126,6 +128,7 @@ var mri = function (req, res) { login: login }); } else { + console.log("download anew, calling downloadMRI"); (function (my, rq, rs) { downloadMRI(my, rq, rs, function (obj) { if(obj) { @@ -161,8 +164,12 @@ var api_mri_post = function (req, res) { hash = crypto.createHash('md5').update(myurl).digest('hex'); // shell equivalent: req.db.mri.find({source:"http://braincatalogue.org/data/Pineal/P001/t1wreq.db.nii.gz"}).limit(1).sort({$natural:-1}) + console.log("myurl from api_mri",myurl); + console.log("hash from api_mri",hash); + req.db.get('mri').find({url: "/data/" + hash + "/", backup: {$exists: false}}, "-_id", {sort: {$natural: -1}, limit: 1}) .then(function (json) { + console.log("json from api_mri",json); json = json[0]; if (json) { if (req.body.var) { diff --git a/controller/project/project.controller.js b/controller/project/project.controller.js index 77dd4d2..b87387b 100644 --- a/controller/project/project.controller.js +++ b/controller/project/project.controller.js @@ -31,10 +31,13 @@ var project = function(req, res) { req.db.get('mri').find({source:item,backup:{$exists:0}},{name:1,_id:0}) .then(function(obj) { if(obj[0]) { - json.files.list[json.files.list.indexOf(item)]={ - source: item, - name: obj[0].name - } + /* + json.files.list[json.files.list.indexOf(item)]={ + source: item, + name: obj[0].name + } + */ + json.files.list[json.files.list.indexOf(item)]=obj[0]; } else { json.files.list[json.files.list.indexOf(item)]={ source: item, diff --git a/js/atlasMakerServer.js b/js/atlasMakerServer.js index 392cf2b..a827d3b 100644 --- a/js/atlasMakerServer.js +++ b/js/atlasMakerServer.js @@ -15,6 +15,7 @@ var dateFormat = require('dateformat'); var async = require('async'); var Struct = require('struct'); var child_process = require('child_process'); +var merge = require('merge'); var mongo = require('mongodb'); var monk = require('monk'); @@ -426,25 +427,27 @@ var initSocketConnection = function initSocketConnection() { continue; } - // do not broadcast to unknown users + // do not broadcast to undefined users if( sourceUS.User===undefined || targetUS.User===undefined) { if(debug) console.log(" User "+sourceUS.uid+": "+(sourceUS.User===undefined)?"undefined":"defined"); if(debug) console.log(" User "+targetUS.uid+": "+(targetUS.User===undefined)?"undefined":"defined"); continue; } - - if( targetUS.User.iAtlas!==sourceUS.User.iAtlas && data.type!=="chat" && data.type!=="userData" ) { + + if (( targetUS.User.projectPage && targetUS.User.projectPage === sourceUS.User.projectPage) + || (targetUS.User.iAtlas === sourceUS.User.iAtlas) + || (data.type === "userData") + || (data.type === "chat") + ) { + if(data.type==="atlas") { + sendAtlasToUser(data.data,websocket.clients[i],false); + } else { + // sanitise data + const cleanData=DOMPurify.sanitize(JSON.stringify(data)); + websocket.clients[i].send(cleanData); + } + } else { if(debug>1) console.log(" no broadcast to user "+targetUS.User.username+" [uid: "+targetUS.uid+"] of atlas "+targetUS.User.specimenName+"/"+targetUS.User.atlasFilename); - continue; - } - - if(data.type==="atlas") { - sendAtlasToUser(data.data,websocket.clients[i],false); - } - else { - // sanitise data - const cleanData=DOMPurify.sanitize(JSON.stringify(data)); - websocket.clients[i].send(cleanData); } n++; } @@ -599,13 +602,27 @@ var receiveSaveMetadataMessage = function receiveSaveMetadataMessage(data,user_s var sourceUS=getUserFromUserId(data.uid); var json=data.metadata; json.modified=(new Date()).toJSON(); - json.modifiedBy=sourceUS.User.username||"unknown"; + json.modifiedBy = (sourceUS.User && sourceUS.User.username) ? sourceUS.User.username : "unknown"; + // sanitise json json=JSON.parse(DOMPurify.sanitize(JSON.stringify(json))); // sanitize works on strings, not objects + // mark previous one as backup - db.get('mri').update({url:json.url,backup:{$exists:false}},{$set:{backup:true}},{multi:true}); - // insert new one - db.get('mri').insert(json); + console.log("source:",json.source); + + db.get('mri').find({source:json.source, backup:{$exists:false}}) + .then(function (ret) { + console.log("original ret:", JSON.stringify(ret)); + console.log("original json:", json); + json = merge.recursive(ret[0], json); + delete json["_id"]; + console.log("merged json:", json); + db.get('mri').update({source:json.source},{$set:{backup:true}},{multi:true}) + .then(function () { + console.log("new version:",json); + db.get('mri').insert(json); + }); + }); }; var receiveAtlasFromUserMessage = function receiveAtlasFromUserMessage(data,user_socket) { traceLog(receiveAtlasFromUserMessage); @@ -1566,7 +1583,7 @@ var line = function line(x, y, val, User, undoLayer) { var y2=y; var i; - if(Math.pow(x1-x2,2)+Math.pow(y1-y2,2)>10*10) { + if(Math.pow(x1-x2,2)+Math.pow(y1-y2,2)>20*20) { console.log("WARNING: long line from",x1,y1,"to",x2,y2); console.log("User.uid:",User.uid); displayUsers(); diff --git a/public/doc/brainbox.md b/public/doc/brainbox.md index 4c0b33f..2e39ff7 100644 --- a/public/doc/brainbox.md +++ b/public/doc/brainbox.md @@ -139,6 +139,16 @@ Supported data formats: For the moment, BrainBox supports nifti file format. Fre * Project settings * Search * Documentation + + ###2.1 Home page + +BrainBox wants to facilitate data discovery. On the home page, you will find the option to either enter a link to a new MRI file ((that you would like to view)) or to choose from a list of previously visited links. Each will open an MRI page with the viewer and annotation tools. When visiting BrainBox for the first time, this list will hold example links to proposed brain data and, once you start working, will update to a list of links to your recently visited brains. In the URL field, you can point BrainBox to any MRI data available online, as for instance on FigShare, Zenodo, Dropbox, GitHub or your own website. If you upload your data to Dropbox, you need to modify the share link by replacing www by dl and deleting everything after .nii.gz + +In the top menu, the **[+]** icon is used to add a new project. Projects are collections of MRIs and annotations, and are discussed more deeply in section 2.3. Next to the **[+]** icon, the **[cog]** icon allows you to configure your existing projects, for example, to restrict access to a list of collaborators. In addition to that, BrainBox allows you to search for MRIs via their filename using the **[magnifying lens]** icon, for a user or a project, and to access the documentation. + +To be able to use full BrainBox functionalities, you need to login. BrainBox asks you to login with your GitHub account so that annotations can profit from GitHub’s versioning system and be saved to your user account as well as easily be shared with the BrainBox GitHub repository. Once logged in, a click on your username will take you to your user page. + +You can always come back to the home page by clicking on the BrainBox logo. ###MRI Page * Viewer diff --git a/public/doc/code.html b/public/doc/code.html new file mode 100644 index 0000000..966b3fd --- /dev/null +++ b/public/doc/code.html @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + diff --git a/public/js/atlasMaker-draw.js b/public/js/atlasMaker-draw.js index 3af3f3c..41e9dfa 100644 --- a/public/js/atlasMaker-draw.js +++ b/public/js/atlasMaker-draw.js @@ -1,4 +1,11 @@ +/** + * @page AtlasMaker: Image Drawing + */ + var AtlasMakerDraw = { + /** + * @function resizeWindow + */ resizeWindow: function resizeWindow() { var me=AtlasMakerWidget; var l=me.traceLog(resizeWindow,1);if(l)console.log(l); @@ -29,6 +36,9 @@ var AtlasMakerDraw = { } }, + /** + * @function configureBrainImage + */ configureBrainImage: function configureBrainImage() { var me=AtlasMakerWidget; var l=me.traceLog(configureBrainImage);if(l)console.log(l); @@ -62,6 +72,9 @@ var AtlasMakerDraw = { me.initCursor(); }, + /** + * @function configureAtlasImage + */ configureAtlasImage: function configureAtlasImage() { var me=AtlasMakerWidget; var l=me.traceLog(configureAtlasImage);if(l)console.log(l); @@ -71,6 +84,9 @@ var AtlasMakerDraw = { me.atlas_offcn.height=me.brain_H; me.atlas_px=me.atlas_offtx.getImageData(0,0,me.atlas_offcn.width,me.atlas_offcn.height); }, + /** + * @function nearestNeighbour + */ nearestNeighbour: function nearestNeighbour(ctx) { var me=AtlasMakerWidget; var l=me.traceLog(nearestNeighbour,1);if(l)console.log(l); @@ -78,6 +94,9 @@ var AtlasMakerDraw = { ctx.imageSmoothingEnabled = false; ctx.mozImageSmoothingEnabled = false; }, + /** + * @function computeSegmentedVolume + */ computeSegmentedVolume: function computeSegmentedVolume() { var me=AtlasMakerWidget; var l=me.traceLog(computeSegmentedVolume,1);if(l)console.log(l); @@ -92,6 +111,9 @@ var AtlasMakerDraw = { } return sum*me.User.pixdim[0]*me.User.pixdim[1]*me.User.pixdim[2]; }, + /** + * @function displayInformation + */ displayInformation: function displayInformation() { var me=AtlasMakerWidget; var l=me.traceLog(displayInformation,1);if(l)console.log(l); @@ -123,6 +145,9 @@ var AtlasMakerDraw = { } vector.html(str); }, + /** + * @function drawImages + */ drawImages: function drawImages() { var me=AtlasMakerWidget; var l=me.traceLog(drawImages,1);if(l)console.log(l); @@ -141,6 +166,9 @@ var AtlasMakerDraw = { me.sendRequestSliceMessage(); } }, + /** + * @function drawAtlasImage + */ drawAtlasImage: function drawAtlasImage(view,slice) { var me=AtlasMakerWidget; var l=me.traceLog(drawAtlasImage,1);if(l)console.log(l); diff --git a/public/js/atlasMaker-interaction.js b/public/js/atlasMaker-interaction.js index 935dea3..3c22b80 100644 --- a/public/js/atlasMaker-interaction.js +++ b/public/js/atlasMaker-interaction.js @@ -1,7 +1,13 @@ +/** + * @page AtlasMaker: Interaction + */ var AtlasMakerInteraction = { //======================================================================================== // Local user interaction //======================================================================================== + /** + * @function changeToolbarDisplay + */ changeToolbarDisplay: function changeToolbarDisplay(display) { var me=AtlasMakerWidget; var l=me.traceLog(changeToolbarDisplay);if(l)console.log(l); @@ -23,6 +29,9 @@ var AtlasMakerInteraction = { break; } }, + /** + * @function changeView + */ changeView: function changeView(theView) { var me=AtlasMakerWidget; var l=me.traceLog(changeView);if(l)console.log(l); @@ -50,6 +59,9 @@ var AtlasMakerInteraction = { me.initCursor(); }, + /** + * @function changeTool + */ changeTool: function changeTool(theTool) { var me=AtlasMakerWidget; var l=me.traceLog(changeTool);if(l)console.log(l); @@ -79,6 +91,9 @@ var AtlasMakerInteraction = { me.sendUserDataMessage(JSON.stringify({'tool':me.User.tool})); me.User.measureLength=null; }, + /** + * @function changePenSize + */ changePenSize: function changePenSize(theSize) { var me=AtlasMakerWidget; var l=me.traceLog(changePenSize);if(l)console.log(l); @@ -86,6 +101,9 @@ var AtlasMakerInteraction = { me.User.penSize=parseInt(theSize); me.sendUserDataMessage(JSON.stringify({'penSize':me.User.penSize})); }, + /** + * @function changePenColor + */ changePenColor: function changePenColor(index) { var me=AtlasMakerWidget; var l=me.traceLog(changePenColor);if(l)console.log(l); @@ -95,6 +113,9 @@ var AtlasMakerInteraction = { me.User.penValue=me.ontology.labels[index].value; me.sendUserDataMessage(JSON.stringify({'penValue':me.User.penValue})); }, + /** + * @function changeSlice + */ changeSlice: function changeSlice(x) { var me=AtlasMakerWidget; var l=me.traceLog(changeSlice,1);if(l)console.log(l); @@ -108,6 +129,9 @@ var AtlasMakerInteraction = { me.drawImages(); }, + /** + * @function prevSlice + */ prevSlice: function prevSlice() { var me=AtlasMakerWidget; var l=me.traceLog(prevSlice,1);if(l)console.log(l); @@ -120,6 +144,9 @@ var AtlasMakerInteraction = { me.changeSlice(x); } }, + /** + * @function nextSlice + */ nextSlice: function nextSlice() { var me=AtlasMakerWidget; var l=me.traceLog(nextSlice,1);if(l)console.log(l); @@ -133,6 +160,9 @@ var AtlasMakerInteraction = { me.changeSlice(x); } }, + /** + * @function toggleFill + */ toggleFill: function toggleFill(x) { var me=AtlasMakerWidget; var l=me.traceLog(toggleFill);if(l)console.log(l); @@ -140,12 +170,18 @@ var AtlasMakerInteraction = { me.User.doFill=x; me.sendUserDataMessage(JSON.stringify({'doFill':me.User.doFill})); }, + /** + * @function toggleChat + */ toggleChat: function toggleChat() { var me=AtlasMakerWidget; var l=me.traceLog(toggleChat);if(l)console.log(l); $("#chatBlock").toggle(); }, + /** + * @function toggleFullscreen + */ toggleFullscreen: function toggleFullscreen() { var me=AtlasMakerWidget; var l=me.traceLog(toggleFullscreen);if(l)console.log(l); @@ -188,6 +224,9 @@ var AtlasMakerInteraction = { me.fullscreen=false; } }, + /** + * @function render3D + */ render3D: function render3D() { var me=AtlasMakerWidget; var l=me.traceLog(render3D);if(l)console.log(l); @@ -198,11 +237,17 @@ var AtlasMakerInteraction = { // opens 3d render window window.open("/templates/surface.html?path="+me.User.dirname+me.User.atlasFilename,"_blank"); }, + /** + * @function link + */ link: function link() { var me=AtlasMakerWidget; var l=me.traceLog(link);if(l)console.log(l); window.prompt("Copy to clipboard:", location.href+"&view="+AtlasMakerWidget.User.view+"&slice="+AtlasMakerWidget.User.slice); }, + /** + * @function upload + */ upload: function upload() { var me=AtlasMakerWidget; var l=me.traceLog(upload);if(l)console.log(l); @@ -252,6 +297,9 @@ var AtlasMakerInteraction = { } input.click(); }, + /** + * @function download + */ download: function download() { var me=AtlasMakerWidget; var l=me.traceLog(download);if(l)console.log(l); @@ -264,6 +312,9 @@ var AtlasMakerInteraction = { document.body.appendChild(a); a.click(); }, + /** + * @function color + */ color: function color() { var me=AtlasMakerWidget; var l=me.traceLog(color);if(l)console.log(l); @@ -288,6 +339,9 @@ var AtlasMakerInteraction = { la.show(); } }, + /** + * @function ontologyValueToColor + */ ontologyValueToColor: function ontologyValueToColor(val) { var me=AtlasMakerWidget; var l=me.traceLog(ontologyValueToColor,3);if(l)console.log(l); @@ -303,6 +357,9 @@ var AtlasMakerInteraction = { } return c; }, + /** + * @function togglePreciseCursor + */ togglePreciseCursor: function togglePreciseCursor() { var me=AtlasMakerWidget; var l=me.traceLog(togglePreciseCursor);if(l)console.log(l); @@ -310,6 +367,9 @@ var AtlasMakerInteraction = { me.flagUsePreciseCursor=!me.flagUsePreciseCursor; me.initCursor(); }, + /** + * @function initCursor + */ initCursor: function initCursor() { var me=AtlasMakerWidget; var l=me.traceLog(initCursor,1);if(l)console.log(l); @@ -354,6 +414,9 @@ var AtlasMakerInteraction = { me.canvas.ontouchend=me.touchend; } }, + /** + * @function updateCursor + */ updateCursor: function updateCursor() { var me=AtlasMakerWidget; var l=me.traceLog(updateCursor,1);if(l)console.log(l); @@ -367,6 +430,9 @@ var AtlasMakerInteraction = { //$("#msg").html(C.state); //console.log(Crsr.state); }, + /** + * @function mousedown + */ mousedown: function mousedown(e) { var me=AtlasMakerWidget; var l=me.traceLog(mousedown);if(l)console.log(l); @@ -383,6 +449,9 @@ var AtlasMakerInteraction = { var y=parseInt((e.pageY-o.top)*(h/H)); me.down(x,Math.round(y*me.brain_Wdim/me.brain_Hdim)); }, + /** + * @function mousemove + */ mousemove: function mousemove(e) { var me=AtlasMakerWidget; var l=me.traceLog(mousemove,2);if(l)console.log(l); @@ -404,12 +473,18 @@ var AtlasMakerInteraction = { }); me.move(x,Math.round(y*me.brain_Wdim/me.brain_Hdim)); }, + /** + * @function mouseup + */ mouseup: function mouseup(e) { var me=AtlasMakerWidget; var l=me.traceLog(mouseup);if(l)console.log(l); me.up(e); }, + /** + * @function touchstart + */ touchstart: function touchstart(e) { var me=AtlasMakerWidget; var l=me.traceLog(touchstart);if(l)console.log(l); @@ -457,6 +532,9 @@ var AtlasMakerInteraction = { } else me.down(x,Math.round(y*me.brain_Wdim/me.brain_Hdim)); }, + /** + * @function touchmove + */ touchmove: function touchmove(e) { var me=AtlasMakerWidget; var l=me.traceLog(touchmove,2);if(l)console.log(l); @@ -507,6 +585,9 @@ var AtlasMakerInteraction = { me.move(x,Math.round(y*me.brain_Wdim/me.brain_Hdim)); } }, + /** + * @function touchend + */ touchend: function touchend(e) { var me=AtlasMakerWidget; var l=me.traceLog(touchend);if(l)console.log(l); @@ -523,6 +604,9 @@ var AtlasMakerInteraction = { } me.up(e); }, + /** + * @function down + */ down: function down(x,y) { var me=AtlasMakerWidget; var l=me.traceLog(down,2);if(l)console.log(l); @@ -570,6 +654,9 @@ var AtlasMakerInteraction = { // init annotation length counter me.annotationLength=0; }, + /** + * @function move + */ move: function move(x,y) { var me=AtlasMakerWidget; var l=me.traceLog(move,2);if(l)console.log(l); @@ -607,6 +694,9 @@ var AtlasMakerInteraction = { */ }, + /** + * @function up + */ up: function up(e) { var me=AtlasMakerWidget; var l=me.traceLog(up,2);if(l)console.log(l); @@ -632,6 +722,9 @@ var AtlasMakerInteraction = { var vol=me.computeSegmentedVolume(); me.info.volume=parseInt(vol)+" mm3"; }, + /** + * @function keyDown + */ keyDown: function keyDown(e) { var me=AtlasMakerWidget; var l=me.traceLog(keyDown,2);if(l)console.log(l); @@ -669,6 +762,9 @@ var AtlasMakerInteraction = { break; } }, + /** + * @function onkey + */ onkey: function onkey(e) { var me=AtlasMakerWidget; var l=me.traceLog(onkey,2);if(l)console.log(l); diff --git a/public/js/atlasMaker-io.js b/public/js/atlasMaker-io.js index 838929d..4f5175e 100644 --- a/public/js/atlasMaker-io.js +++ b/public/js/atlasMaker-io.js @@ -1,4 +1,10 @@ +/** + * @page AtlasMaker: Input/Output + */ var AtlasMakerIO = { + /** + * @function encodeNifti + */ encodeNifti: function encodeNifti() { var me=AtlasMakerWidget; var l=me.traceLog(encodeNifti);if(l)console.log(l); @@ -41,6 +47,9 @@ var AtlasMakerIO = { return niigz.result; }, + /** + * @function saveNifti + */ saveNifti: function saveNifti() { var me=AtlasMakerWidget; var l=me.traceLog(saveNifti);if(l)console.log(l); @@ -51,6 +60,9 @@ var AtlasMakerIO = { $("a#download_atlas").attr("href",window.URL.createObjectURL(niigzBlob)); $("a#download_atlas").attr("download",me.User.atlasFilename); }, + /** + * @function loadNifti + */ loadNifti: function loadNifti(nii) { var me=AtlasMakerWidget; var l=me.traceLog(loadNifti,1);if(l)console.log(l); @@ -96,6 +108,9 @@ var AtlasMakerIO = { /* {Linear algebra */ + /** + * @function computeS2VTransformation + */ computeS2VTransformation: function computeS2VTransformation() { var me=AtlasMakerWidget; var l=me.traceLog(computeS2VTransformation);if(l)console.log(l); @@ -110,7 +125,7 @@ var AtlasMakerIO = { var w2s=[[1/Math.abs(wpixdim[0]),0,0],[0,1/Math.abs(wpixdim[1]),0],[0,0,1/Math.abs(wpixdim[2])]]; var s2w=me.invMat(w2s); - console.log(["v2w",v2w, "wori",wori, "wpixdim",wpixdim, "wvmax",wvmax, "wvmin",wvmin, "wmin",wmin, "wmax",wmax, "w2s",w2s]); + // console.log(["v2w",v2w, "wori",wori, "wpixdim",wpixdim, "wvmax",wvmax, "wvmin",wvmin, "wmin",wmin, "wmax",wmax, "w2s",w2s]); me.User.s2v = { sdim: [(wmax[0]-wmin[0])/Math.abs(wpixdim[0])+1,(wmax[1]-wmin[1])/Math.abs(wpixdim[1])+1,(wmax[2]-wmin[2])/Math.abs(wpixdim[2])+1], @@ -121,6 +136,9 @@ var AtlasMakerIO = { wori: wori }; }, + /** + * @function testS2VTransformation + */ testS2VTransformation: function testS2VTransformation() { var me=AtlasMakerWidget; var l=me.traceLog(testS2VTransformation);if(l)console.log(l); @@ -132,44 +150,51 @@ var AtlasMakerIO = { var mri=me.User; // this line is different from server var doReset=false; - console.log("Transformation TEST:"); - - console.log(" 1. transformation volume"); + // console.log("Transformation TEST:"); + // console.log(" 1. transformation volume"); + var vv=mri.dim[0]*mri.dim[1]*mri.dim[2]; var vs=mri.s2v.sdim[0]*mri.s2v.sdim[1]*mri.s2v.sdim[2]; var diff=(vs-vv)/vv; if(Math.abs(diff)>0.001) { + /* console.log(" ERROR: Difference is too large"); console.log(" original volume:",vv); console.log(" rotated volume:",vs); console.log(" % difference:",diff*100); + */ doReset=true; } else { - console.log(" ok."); + // console.log(" ok."); } - console.log(" 2. transformation origin"); + // console.log(" 2. transformation origin"); if( mri.s2v.sori[0]<0||mri.s2v.sori[0]>mri.s2v.sdim[0] || mri.s2v.sori[1]<0||mri.s2v.sori[1]>mri.s2v.sdim[1] || mri.s2v.sori[2]<0||mri.s2v.sori[2]>mri.s2v.sdim[2]) { - console.log(" Origin point is outside the dimensions of the data"); + // console.log(" Origin point is outside the dimensions of the data"); doReset=true; } else { - console.log(" ok."); + // console.log(" ok."); } if(doReset) { - console.log("THE TRANSFORMATION WILL BE RESET"); + // console.log("THE TRANSFORMATION WILL BE RESET"); mri.v2w=[[mri.pixdim[0],0,0],[0,-mri.pixdim[1],0],[0,0,-mri.pixdim[2]]]; mri.wori=[0,mri.dim[1]-1,mri.dim[2]-1]; // re-compute the transformation from voxel space to screen space me.computeS2VTransformation(); // this line is different from server + /* console.log(mri.dir); console.log(mri.ori); console.log(mri.s2v); + */ } }, + /** + * @function S2I + */ S2I: function S2I(s,mri) { var me=AtlasMakerWidget; var l=me.traceLog(S2I,3);if(l)console.log(l); @@ -183,6 +208,9 @@ var AtlasMakerIO = { i= v[2]*mri.dim[1]*mri.dim[0]+ v[1]*mri.dim[0] +v[0]; return i; }, + /** + * @function mulMatVec + */ mulMatVec: function mulMatVec(m,v) { return [ m[0][0]*v[0]+m[0][1]*v[1]+m[0][2]*v[2], @@ -190,6 +218,9 @@ var AtlasMakerIO = { m[2][0]*v[0]+m[2][1]*v[1]+m[2][2]*v[2] ]; }, + /** + * @function invMat + */ invMat: function invMat(m) { var det; var w=[[],[],[]]; @@ -210,9 +241,15 @@ var AtlasMakerIO = { return w; }, + /** + * @function subVecVec + */ subVecVec: function subVecVec(a,b) { return [a[0]-b[0],a[1]-b[1],a[2]-b[2]]; }, + /** + * @function addVecVec + */ addVecVec: function addVecVec(a,b) { return [a[0]+b[0],a[1]+b[1],a[2]+b[2]]; }, diff --git a/public/js/atlasMaker-paint.js b/public/js/atlasMaker-paint.js index e456361..7801e31 100644 --- a/public/js/atlasMaker-paint.js +++ b/public/js/atlasMaker-paint.js @@ -1,7 +1,13 @@ +/** + * @page AtlasMaker: Painting commands + */ var AtlasMakerPaint = { //==================================================================================== // Paint functions common to all users //==================================================================================== + /** + * @function paintxy + */ paintxy: function paintxy(u,c,x,y,usr) { var me=AtlasMakerWidget; var l=me.traceLog(paintxy,1);if(l)console.log(l); @@ -42,6 +48,9 @@ var AtlasMakerPaint = { usr.x0=coord.x; usr.y0=coord.y; }, + /** + * @function paintvol + */ paintvol: function paintvol(voxels) { /* this function is exclusively used for undoing */ var me=AtlasMakerWidget; @@ -59,6 +68,9 @@ var AtlasMakerPaint = { me.drawImages(); }, + /** + * @function fill + */ fill: function fill(x,y,z,val,myView) { var me=AtlasMakerWidget; var l=me.traceLog(fill);if(l)console.log(l); @@ -91,6 +103,9 @@ var AtlasMakerPaint = { } me.drawImages(); }, + /** + * @function line + */ line: function line(x,y,val,usr) { var me=AtlasMakerWidget; var l=me.traceLog(line,1);if(l)console.log(l); @@ -146,6 +161,9 @@ var AtlasMakerPaint = { } me.drawImages(); }, + /** + * @function slice2index + */ slice2index: function slice2index(mx,my,mz,myView) { var me=AtlasMakerWidget; var l=me.traceLog(slice2index,3);if(l)console.log(l); @@ -167,6 +185,9 @@ var AtlasMakerPaint = { */ return i; }, + /** + * @function slice2xyzi + */ slice2xyzi: function slice2xyzi(mx,my,mz,myView) { var me=AtlasMakerWidget; var l=me.traceLog(slice2xyzi,1);if(l)console.log(l); diff --git a/public/js/atlasMaker-ui.js b/public/js/atlasMaker-ui.js index e0fce2c..66e2c77 100644 --- a/public/js/atlasMaker-ui.js +++ b/public/js/atlasMaker-ui.js @@ -1,4 +1,10 @@ +/** + * @page AtlasMaker: User Interface Elements + */ var AtlasMakerUI = { + /** + * @function slider + */ slider: function slider(elem,callback) { var me=AtlasMakerWidget; var l=me.traceLog(slider,2);if(l)console.log(l); @@ -28,6 +34,9 @@ var AtlasMakerUI = { $(document).on("mouseup touchend",function from_slider(){$(elem).data({drag:false})}); $(elem).on('mousedown touchstart',function from_slider(){$(elem).data({drag:true})}); }, + /** + * @function chose + */ chose: function chose(elem,callback) { // Initialise a 'chose' control var ch=$(elem).find(".a"); @@ -44,6 +53,9 @@ var AtlasMakerUI = { }); }); }, + /** + * @function toggle + */ toggle: function toggle(elem,callback) { // Initialise a 'toggle' control $(elem).click(function(){ @@ -52,6 +64,9 @@ var AtlasMakerUI = { callback($(this).hasClass("pressed")); }); }, + /** + * @function push + */ push: function push(elem,callback) { // Initialise a 'push' control $(elem).click(function(){ diff --git a/public/js/atlasMaker-ws.js b/public/js/atlasMaker-ws.js index 6a89994..357c8d5 100644 --- a/public/js/atlasMaker-ws.js +++ b/public/js/atlasMaker-ws.js @@ -1,7 +1,13 @@ +/** + * @page AtlasMaker: WebSockets + */ var AtlasMakerWS = { //==================================================================================== // Web sockets //==================================================================================== + /** + * @function createSocket + */ createSocket: function createSocket(host) { var me=AtlasMakerWidget; var l=me.traceLog(createSocket);if(l)console.log(l); @@ -16,6 +22,9 @@ var AtlasMakerWS = { return ws; }, + /** + * @function initSocketConnection + */ initSocketConnection: function initSocketConnection() { var me=AtlasMakerWidget; var l=me.traceLog(initSocketConnection);if(l)console.log(l); @@ -60,6 +69,9 @@ var AtlasMakerWS = { return def.promise(); }, + /** + * @function receiveSocketMessage + */ receiveSocketMessage: function receiveSocketMessage(msg) { var me=AtlasMakerWidget; var l=me.traceLog(receiveSocketMessage,1);if(l)console.log(l); @@ -85,6 +97,9 @@ var AtlasMakerWS = { */ switch(data.type) { + case "saveMetadata" : + me.receiveMetaData(data); + break; case "userData": me.receiveUserDataMessage(data); break; @@ -105,6 +120,9 @@ var AtlasMakerWS = { break; } }, + /** + * @function sendUserDataMessage + */ sendUserDataMessage: function sendUserDataMessage(description) { var me=AtlasMakerWidget; var l=me.traceLog(sendUserDataMessage,1);if(l)console.log(l); @@ -124,6 +142,9 @@ var AtlasMakerWS = { console.log("ERROR: Unable to sendUserDataMessage",ex); } }, + /** + * @function receiveBinaryMessage + */ receiveBinaryMessage: function receiveBinaryMessage(msgData) { var me=AtlasMakerWidget; var l=me.traceLog(receiveBinaryMessage,1);if(l)console.log(l); @@ -195,6 +216,9 @@ var AtlasMakerWS = { }; fileReader.readAsArrayBuffer(msgData); }, + /** + * @function receiveUserDataMessage + */ receiveUserDataMessage: function receiveUserDataMessage(data) { var me=AtlasMakerWidget; var l=me.traceLog(receiveUserDataMessage);if(l)console.log(l); @@ -231,6 +255,9 @@ var AtlasMakerWS = { var v,nusers=1; for(v in me.Collab) nusers++; $("#chat").text("Chat ("+nusers+" connected)"); }, + /** + * @function sendChatMessage + */ sendChatMessage: function sendChatMessage() { var me=AtlasMakerWidget; var l=me.traceLog(sendChatMessage);if(l)console.log(l); @@ -248,6 +275,9 @@ var AtlasMakerWS = { console.log("ERROR: Unable to sendChatMessage",ex); } }, + /** + * @function receiveChatMessage + */ receiveChatMessage: function receiveChatMessage(data) { var me=AtlasMakerWidget; var l=me.traceLog(receiveChatMessage);if(l)console.log(l); @@ -260,6 +290,9 @@ var AtlasMakerWS = { $("#log").append(msg); $("#log").scrollTop($("#log")[0].scrollHeight); }, + /** + * @function sendPaintMessage + */ sendPaintMessage: function sendPaintMessage(msg) { var me=AtlasMakerWidget; var l=me.traceLog(sendPaintMessage,1);if(l)console.log(l); @@ -272,6 +305,9 @@ var AtlasMakerWS = { console.log("ERROR: Unable to sendPaintMessage",ex); } }, + /** + * @function receivePaintMessage + */ receivePaintMessage: function receivePaintMessage(data) { var me=AtlasMakerWidget; var l=me.traceLog(receivePaintMessage,3);if(l)console.log(l); @@ -284,6 +320,9 @@ var AtlasMakerWS = { me.paintxy(u,c,x,y,me.Collab[u]); }, + /** + * @function receivePaintVolumeMessage + */ receivePaintVolumeMessage: function receivePaintVolumeMessage(data) { var me=AtlasMakerWidget; var l=me.traceLog(receivePaintVolumeMessage);if(l)console.log(l); @@ -293,6 +332,9 @@ var AtlasMakerWS = { voxels=data.data; me.paintvol(voxels.data); }, + /** + * @function sendUndoMessage + */ sendUndoMessage: function sendUndoMessage() { var me=AtlasMakerWidget; var l=me.traceLog(sendUndoMessage);if(l)console.log(l); @@ -305,6 +347,9 @@ var AtlasMakerWS = { console.log("ERROR: Unable to sendUndoMessage",ex); } }, + /** + * @function sendRequestSliceMessage + */ sendRequestSliceMessage: function sendRequestSliceMessage() { var me=AtlasMakerWidget; var l=me.traceLog(sendRequestSliceMessage,1);if(l)console.log(l); @@ -327,6 +372,23 @@ var AtlasMakerWS = { console.log("ERROR: Unable to sendRequestSliceMessage",ex); } }, + receiveMetaData: function receiveMetaData(data) { +// console.log(info_proxy); +// console.log(info_proxy.files); + for (var i in projectInfo.files.list) { + if (projectInfo.files.list[i].source == data.metadata.source) { + for (var key in projectInfo.files.list[i].mri.annotations) { + info_proxy["files.list." + i + ".mri.annotations." + key] = data.metadata.mri.annotations[key]; + } + info_proxy["files.list." + i + ".name"] = data.metadata.name; + break; + } + } + console.log("JUST RECIEVED SOME MORE DATA", data.metadata); + }, + /** + * @function sendSaveMetadataMessage + */ sendSaveMetadataMessage: function sendSaveMetadataMessage(info) { var me=AtlasMakerWidget; var l=me.traceLog(sendSaveMetadataMessage,1);if(l)console.log(l); @@ -339,6 +401,9 @@ var AtlasMakerWS = { console.log("ERROR: Unable to sendSaveMetadataMessage",ex); } }, + /** + * @function receiveDisconnectMessage + */ receiveDisconnectMessage: function receiveDisconnectMessage(data) { var me=AtlasMakerWidget; var l=me.traceLog(receiveDisconnectMessage);if(l)console.log(l); diff --git a/public/js/atlasMaker.js b/public/js/atlasMaker.js index 6249ef5..8b07128 100755 --- a/public/js/atlasMaker.js +++ b/public/js/atlasMaker.js @@ -1,8 +1,11 @@ +/** + * @page AtlasMaker + */ var AtlasMakerWidget = { //======================================================================================== // Globals //======================================================================================== - debug: 2, + debug: 0, container: null, // Element where atlasMaker lives brain_offcn: null, brain_offtx: null, @@ -77,11 +80,17 @@ var AtlasMakerWidget = { /* DEPRECATED Undo:[], */ version: 1, // version of the configuration file (slice number, plane, etc). Default=1 + /** + * @function traceLog + */ traceLog: function traceLog(f,l) { var me=AtlasMakerWidget; - if(l==undefined || me.debug>l) + if(me.debug && (l==undefined || me.debug>l)) return "am> "+(f.name)+" "+(f.caller?(f.caller.name||"annonymous"):"root"); }, + /** + * @function quit + */ quit: function quit() { var me=AtlasMakerWidget; var l=me.traceLog(quit);if(l)console.log(l); @@ -93,6 +102,9 @@ var AtlasMakerWidget = { //========== // Database //========== + /** + * @function logToDatabase + */ logToDatabase: function logToDatabase(key,value) { var def=$.Deferred(); var me=AtlasMakerWidget; @@ -118,6 +130,9 @@ var AtlasMakerWidget = { //==================================================================================== // Configuration //==================================================================================== + /** + * @function initAtlasMaker + */ initAtlasMaker: function initAtlasMaker(elem) { var me=AtlasMakerWidget; var l=me.traceLog(initAtlasMaker);if(l)console.log(l); @@ -228,6 +243,9 @@ var AtlasMakerWidget = { return def.promise(); }, + /** + * @function configureAtlasMaker + */ configureAtlasMaker: function configureAtlasMaker(info,index) { var me=AtlasMakerWidget; var l=me.traceLog(configureAtlasMaker);if(l)console.log(l); @@ -261,6 +279,9 @@ var AtlasMakerWidget = { return def.promise(); }); }, + /** + * @function configureOntology + */ configureOntology: function configureOntology(json) { var me=AtlasMakerWidget; var l=me.traceLog(configureOntology);if(l)console.log(l); @@ -269,6 +290,9 @@ var AtlasMakerWidget = { me.ontology.valueToIndex=[]; me.ontology.labels.forEach(function(o,i){me.ontology.valueToIndex[o.value]=i}); }, + /** + * @function configureMRI + */ configureMRI: function configureMRI(info,index) { var me=AtlasMakerWidget; var l=me.traceLog(configureMRI);if(l)console.log(l); diff --git a/public/js/brainbox.js b/public/js/brainbox.js index e63f9ec..0f85838 100644 --- a/public/js/brainbox.js +++ b/public/js/brainbox.js @@ -1,13 +1,26 @@ +/** + * @library BrainBox + * @version 0.0.1 + * @brief Real-time collaboration in neuroimaging + */ + +/** + * @page BrainBox + */ + var BrainBox={ version: 1, - debug: 1, + debug: 0, info:{}, labelSets:null, access:["Read/Write","Read"], annotationType:["volume","text"], + /** + * @function traceLog + */ traceLog: function traceLog(f,l) { - if(l==undefined || BrainBox.debug>l) + if(BrainBox.debug && (l==undefined || BrainBox.debug>l)) return "bb> "+(f.name)+" "+(f.caller?(f.caller.name||"annonymous"):"root"); }, @@ -15,6 +28,9 @@ var BrainBox={ JavaScript implementation of Java's hashCode method from http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/ */ + /** + * @function hash + */ hash: function hash(str) { console.log(BrainBox.traceLog(hash)); @@ -33,6 +49,9 @@ var BrainBox={ } return res; }, + /** + * @function loadScript + */ loadScript: function loadScript(path) { var def = new $.Deferred(); var s = document.createElement("script"); @@ -43,6 +62,9 @@ var BrainBox={ document.body.appendChild(s); return def.promise(); }, + /** + * @function initBrainBox + */ initBrainBox: function initBrainBox() { console.log(BrainBox.traceLog(initBrainBox)); @@ -78,6 +100,9 @@ var BrainBox={ return def.promise(); }, + /** + * @function configureBrainBox + */ configureBrainBox: function configureBrainBox(param) { console.log(BrainBox.traceLog(configureBrainBox)); @@ -143,6 +168,9 @@ var BrainBox={ return def.promise(); }, + /** + * @function unload + */ unload: function unload() { console.log(BrainBox.traceLog(unload)); var foundStored=false; @@ -172,6 +200,9 @@ var BrainBox={ /* Annotation related functions */ + /** + * @function selectAnnotationTableRow + */ selectAnnotationTableRow: function selectAnnotationTableRow() { console.log(BrainBox.traceLog(selectAnnotationTableRow)); @@ -187,6 +218,9 @@ var BrainBox={ AtlasMakerWidget.configureAtlasMaker(BrainBox.info,index); } }, + /** + * @function appendAnnotationTableRow + */ appendAnnotationTableRow: function appendAnnotationTableRow(irow,param) { console.log(BrainBox.traceLog(appendAnnotationTableRow)); @@ -216,6 +250,9 @@ var BrainBox={ } } }, + /** + * @function addAnnotation + */ addAnnotation: function addAnnotation(param) { console.log(BrainBox.traceLog(addAnnotation)); @@ -240,6 +277,9 @@ var BrainBox={ // update in server BrainBox.saveAnnotations(param); }, + /** + * @function removeAnnotation + */ removeAnnotation: function removeAnnotation(param) { console.log(BrainBox.traceLog(removeAnnotation)); @@ -260,6 +300,9 @@ var BrainBox={ // update in server BrainBox.saveAnnotations(param); }, + /** + * @function saveAnnotations + */ saveAnnotations: function saveAnnotations(param) { console.log(BrainBox.traceLog(saveAnnotations)); @@ -268,6 +311,9 @@ var BrainBox={ hash_old=BrainBox.hash(JSON.stringify(BrainBox.info)); $(param.saveWarning).hide(); }, + /** + * @function loadLabelsets + */ loadLabelsets: function loadLabelsets() { console.log(BrainBox.traceLog(loadLabelsets)); diff --git a/public/js/twoWayBinding.js b/public/js/twoWayBinding.js index 903fef0..051b793 100644 --- a/public/js/twoWayBinding.js +++ b/public/js/twoWayBinding.js @@ -1,5 +1,5 @@ /** - * @namespace Two-Way Binding + * @page Two-Way Binding */ var date_format=function(e,d){$(e).text(new Date(d).toLocaleDateString())}; @@ -17,7 +17,8 @@ var date_format=function(e,d){$(e).text(new Date(d).toLocaleDateString())}; */ /** - * Bind a javascript object with a DOM element and viceversa + * @function bind2 + * @desc Bind a javascript object with a DOM element and viceversa * @param {object} proxy The object that will bind the source object and the DOM element * @param {object} original The source object to bind * @param {string} path Path to the property in the original object to bind @@ -52,7 +53,8 @@ function bind2(proxy,original,path,el,format,parse) { } /** - * Bind the content of a DOM element to javascript object, but not the other way around + * @function bind1 + * @desc Bind the content of a DOM element to javascript object, but not the other way around * @param {object} proxy The object that will bind the source object and the DOM element * @param {object} original The source object to bind * @param {string} path Path to the property in the original object to bind @@ -82,7 +84,8 @@ function bind2(proxy,original,path,el,format,parse) { } /** - * Unbind a javascript object and a DOM element + * @function unbind2 + * @desc Unbind a javascript object and a DOM element * @param {object} proxy The object that will bind the source object and the DOM element * @param {string} path Path to the property in the original object to bind */ diff --git a/views/project.mustache b/views/project.mustache index 1ad25c5..c6d6be6 100644 --- a/views/project.mustache +++ b/views/project.mustache @@ -64,8 +64,6 @@ Name File - QC - QC Comment @@ -179,6 +177,10 @@ function loadProjectFile(url) { if($.isEmptyObject(data) === false) { params.info=data; BrainBox.configureBrainBox(params) + .then(function from_project(){ + AtlasMakerWidget.User.projectPage = projectInfo.shortname; + AtlasMakerWidget.sendUserDataMessage(JSON.stringify({projectPage:projectInfo.shortname})) + }); } else { var info=AtlasMakerWidget.container.find("#info"); info.html("ERROR: File is unreadable"); @@ -242,45 +244,35 @@ $("#projectCreated").text("Created on "+creation.toLocaleString()); $("#projectFilesNumber").text(projectInfo.files.list.length+" Files"); $("#projectCollaboratorsNumber").text(projectInfo.collaborators.length+" Collaborators"); -/* - The list of all collaborators participating in the project - (should be recovered from the database) -*/ -str=[ "", - "Name", - "Last visited", - ""].join(); -for(var i=0;i", - " ", - " "+projectInfo.collaborators[i]+"", - " ", - " 14 July 2016", - ""].join(""); -} -$("#collaborators").append(str); - /* The list of all files included in the project */ -str=[]; -for(var i=0;i", - " ", - " "+filename+"", - " ", - " ", - ""].join(""); -} -$("#projectFiles tbody").append(str); -for(var i=0;i" + projectInfo.annotations.list[k].name + ""); + txtAnnotations.push(projectInfo.annotations.list[k]); + } + } + + // Add the 'annotations' object to mri if it does not exist + var k; + for(k in projectInfo.files.list) { + if (!(projectInfo.files.list[k].mri)) + projectInfo.files.list[k].mri = {}; + if (!(projectInfo.files.list[k].mri.annotations)) + projectInfo.files.list[k].mri.annotations = {}; + /** + * @todo delete: undefined properties are created on assignment as far as the object exists + */ +// if (!(projectInfo.files.list[f].mri.annotations[projectInfo.annotations.list[k].name])) +// projectInfo.files.list[f].mri.annotations[projectInfo.annotations.list[k].name] = ""; + } // select first file by default (should come from localStorage) var url=projectInfo.files.list[0].source; -$("#projectFiles tbody tr:eq(0)").addClass("selected"); BrainBox.initBrainBox() .then(function from_project(){return BrainBox.loadLabelsets()}) @@ -291,9 +283,89 @@ BrainBox.initBrainBox() $(document).on('click', "#labels-close", function(){$("#labelset").hide()}); }); -// listen to changes in file selection by clicking of the file table + var info_proxy = {}; + var trTemplate; + var objTemplate = [ + { typeOfBinding:2, + path:"files.list.#.name" + }, + { + typeOfBinding:1, + path:"files.list.#.source", + format:function(e, d){ + $(e).find("a").prop("href", location.origin+"/mri?url=" + d); + $(e).find("a").html(d.split("/").pop()); + } + } + ]; + trTemplate=[ + "", + " ", + " " + ]; + for(var g in txtAnnotations) { + if(txtAnnotations[g].values) { + trTemplate.push(""); + + /** + * @todo Why the closures if there's nothing asynchronous?? + */ + objTemplate.push({ + typeOfBinding:2, + path:"files.list.#.mri.annotations." + txtAnnotations[g].name, + format: function(e, d){$(e).find("select").get(0).value=d}, + parse: function(e){return $(e).find("select").val()} + }); + + } else { + trTemplate.push(""); + objTemplate.push({ + typeOfBinding:2, + path:"files.list.#.mri.annotations." + txtAnnotations[g].name + }); + } + } + trTemplate.push(""); + var aParam = { + table: $("#projectFiles table"), + info_proxy: info_proxy, + info: projectInfo, + trTemplate: trTemplate.join("\n"), + objTemplate: objTemplate + }; + + for(var i=0;i changes value to trigger data sending + $("#projectFiles table tbody").on('change', "select", function(e) { + $(e.target).blur(); + }); + +// listen to changes in file selection by clicking on the file table $(document).on('click', "#projectFiles tbody tr",function() { - console.log(">> selectProjectFilesTableRow()"); var table=$(this).closest("table"); var currentIndex=$(table).find("tr.selected").index(); -- GitLab From a3225bcdfe2c59aa03417f22f971eae63847cb1e Mon Sep 17 00:00:00 2001 From: fdelencl42 Date: Tue, 4 Oct 2016 15:35:03 +0200 Subject: [PATCH 6/8] Revert "Revert "add placeholder to select tags"" This reverts commit 1c9da907ae24fb7afaf510680a903ab445193703. --- views/project.mustache | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/views/project.mustache b/views/project.mustache index c6d6be6..61b3143 100644 --- a/views/project.mustache +++ b/views/project.mustache @@ -9,6 +9,10 @@ ").appendTo(o)),a.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",a.opacity)),a.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",a.zIndex)),this.scrollParent[0]!==this.document[0]&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",e,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!s)for(n=this.containers.length-1;n>=0;n--)this.containers[n]._trigger("activate",e,this._uiHash(this));return t.ui.ddmanager&&(t.ui.ddmanager.current=this),t.ui.ddmanager&&!a.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this.dragging=!0,this._addClass(this.helper,"ui-sortable-helper"),this._mouseDrag(e),!0},_mouseDrag:function(e){var i,s,n,o,a=this.options,r=!1;for(this.position=this._generatePosition(e),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==this.document[0]&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-e.pageY=0;i--)if(s=this.items[i],n=s.item[0],o=this._intersectsWithPointer(s),o&&s.instance===this.currentContainer&&n!==this.currentItem[0]&&this.placeholder[1===o?"next":"prev"]()[0]!==n&&!t.contains(this.placeholder[0],n)&&("semi-dynamic"===this.options.type?!t.contains(this.element[0],n):!0)){if(this.direction=1===o?"down":"up","pointer"!==this.options.tolerance&&!this._intersectsWithSides(s))break;this._rearrange(e,s),this._trigger("change",e,this._uiHash());break}return this._contactContainers(e),t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),this._trigger("sort",e,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(e,i){if(e){if(t.ui.ddmanager&&!this.options.dropBehaviour&&t.ui.ddmanager.drop(this,e),this.options.revert){var s=this,n=this.placeholder.offset(),o=this.options.axis,a={};o&&"x"!==o||(a.left=n.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===this.document[0].body?0:this.offsetParent[0].scrollLeft)),o&&"y"!==o||(a.top=n.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===this.document[0].body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,t(this.helper).animate(a,parseInt(this.options.revert,10)||500,function(){s._clear(e)})}else this._clear(e,i);return!1}},cancel:function(){if(this.dragging){this._mouseUp(new t.Event("mouseup",{target:null})),"original"===this.options.helper?(this.currentItem.css(this._storedCSS),this._removeClass(this.currentItem,"ui-sortable-helper")):this.currentItem.show();for(var e=this.containers.length-1;e>=0;e--)this.containers[e]._trigger("deactivate",null,this._uiHash(this)),this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",null,this._uiHash(this)),this.containers[e].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),t.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?t(this.domPosition.prev).after(this.currentItem):t(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},t(i).each(function(){var i=(t(e.item||this).attr(e.attribute||"id")||"").match(e.expression||/(.+)[\-=_](.+)/);i&&s.push((e.key||i[1]+"[]")+"="+(e.key&&e.expression?i[1]:i[2]))}),!s.length&&e.key&&s.push(e.key+"="),s.join("&")},toArray:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},i.each(function(){s.push(t(e.item||this).attr(e.attribute||"id")||"")}),s},_intersectsWith:function(t){var e=this.positionAbs.left,i=e+this.helperProportions.width,s=this.positionAbs.top,n=s+this.helperProportions.height,o=t.left,a=o+t.width,r=t.top,h=r+t.height,l=this.offset.click.top,c=this.offset.click.left,u="x"===this.options.axis||s+l>r&&h>s+l,d="y"===this.options.axis||e+c>o&&a>e+c,p=u&&d;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>t[this.floating?"width":"height"]?p:e+this.helperProportions.width/2>o&&a>i-this.helperProportions.width/2&&s+this.helperProportions.height/2>r&&h>n-this.helperProportions.height/2},_intersectsWithPointer:function(t){var e,i,s="x"===this.options.axis||this._isOverAxis(this.positionAbs.top+this.offset.click.top,t.top,t.height),n="y"===this.options.axis||this._isOverAxis(this.positionAbs.left+this.offset.click.left,t.left,t.width),o=s&&n;return o?(e=this._getDragVerticalDirection(),i=this._getDragHorizontalDirection(),this.floating?"right"===i||"down"===e?2:1:e&&("down"===e?2:1)):!1},_intersectsWithSides:function(t){var e=this._isOverAxis(this.positionAbs.top+this.offset.click.top,t.top+t.height/2,t.height),i=this._isOverAxis(this.positionAbs.left+this.offset.click.left,t.left+t.width/2,t.width),s=this._getDragVerticalDirection(),n=this._getDragHorizontalDirection();return this.floating&&n?"right"===n&&i||"left"===n&&!i:s&&("down"===s&&e||"up"===s&&!e)},_getDragVerticalDirection:function(){var t=this.positionAbs.top-this.lastPositionAbs.top;return 0!==t&&(t>0?"down":"up")},_getDragHorizontalDirection:function(){var t=this.positionAbs.left-this.lastPositionAbs.left;return 0!==t&&(t>0?"right":"left")},refresh:function(t){return this._refreshItems(t),this._setHandleClassName(),this.refreshPositions(),this},_connectWith:function(){var t=this.options;return t.connectWith.constructor===String?[t.connectWith]:t.connectWith},_getItemsAsjQuery:function(e){function i(){r.push(this)}var s,n,o,a,r=[],h=[],l=this._connectWith();if(l&&e)for(s=l.length-1;s>=0;s--)for(o=t(l[s],this.document[0]),n=o.length-1;n>=0;n--)a=t.data(o[n],this.widgetFullName),a&&a!==this&&!a.options.disabled&&h.push([t.isFunction(a.options.items)?a.options.items.call(a.element):t(a.options.items,a.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),a]);for(h.push([t.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):t(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]),s=h.length-1;s>=0;s--)h[s][0].each(i);return t(r)},_removeCurrentsFromItems:function(){var e=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=t.grep(this.items,function(t){for(var i=0;e.length>i;i++)if(e[i]===t.item[0])return!1;return!0})},_refreshItems:function(e){this.items=[],this.containers=[this];var i,s,n,o,a,r,h,l,c=this.items,u=[[t.isFunction(this.options.items)?this.options.items.call(this.element[0],e,{item:this.currentItem}):t(this.options.items,this.element),this]],d=this._connectWith();if(d&&this.ready)for(i=d.length-1;i>=0;i--)for(n=t(d[i],this.document[0]),s=n.length-1;s>=0;s--)o=t.data(n[s],this.widgetFullName),o&&o!==this&&!o.options.disabled&&(u.push([t.isFunction(o.options.items)?o.options.items.call(o.element[0],e,{item:this.currentItem}):t(o.options.items,o.element),o]),this.containers.push(o));for(i=u.length-1;i>=0;i--)for(a=u[i][1],r=u[i][0],s=0,l=r.length;l>s;s++)h=t(r[s]),h.data(this.widgetName+"-item",a),c.push({item:h,instance:a,width:0,height:0,left:0,top:0})},refreshPositions:function(e){this.floating=this.items.length?"x"===this.options.axis||this._isFloating(this.items[0].item):!1,this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var i,s,n,o;for(i=this.items.length-1;i>=0;i--)s=this.items[i],s.instance!==this.currentContainer&&this.currentContainer&&s.item[0]!==this.currentItem[0]||(n=this.options.toleranceElement?t(this.options.toleranceElement,s.item):s.item,e||(s.width=n.outerWidth(),s.height=n.outerHeight()),o=n.offset(),s.left=o.left,s.top=o.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(i=this.containers.length-1;i>=0;i--)o=this.containers[i].element.offset(),this.containers[i].containerCache.left=o.left,this.containers[i].containerCache.top=o.top,this.containers[i].containerCache.width=this.containers[i].element.outerWidth(),this.containers[i].containerCache.height=this.containers[i].element.outerHeight();return this},_createPlaceholder:function(e){e=e||this;var i,s=e.options;s.placeholder&&s.placeholder.constructor!==String||(i=s.placeholder,s.placeholder={element:function(){var s=e.currentItem[0].nodeName.toLowerCase(),n=t("<"+s+">",e.document[0]);return e._addClass(n,"ui-sortable-placeholder",i||e.currentItem[0].className)._removeClass(n,"ui-sortable-helper"),"tbody"===s?e._createTrPlaceholder(e.currentItem.find("tr").eq(0),t("",e.document[0]).appendTo(n)):"tr"===s?e._createTrPlaceholder(e.currentItem,n):"img"===s&&n.attr("src",e.currentItem.attr("src")),i||n.css("visibility","hidden"),n},update:function(t,n){(!i||s.forcePlaceholderSize)&&(n.height()||n.height(e.currentItem.innerHeight()-parseInt(e.currentItem.css("paddingTop")||0,10)-parseInt(e.currentItem.css("paddingBottom")||0,10)),n.width()||n.width(e.currentItem.innerWidth()-parseInt(e.currentItem.css("paddingLeft")||0,10)-parseInt(e.currentItem.css("paddingRight")||0,10)))}}),e.placeholder=t(s.placeholder.element.call(e.element,e.currentItem)),e.currentItem.after(e.placeholder),s.placeholder.update(e,e.placeholder)},_createTrPlaceholder:function(e,i){var s=this;e.children().each(function(){t(" ",s.document[0]).attr("colspan",t(this).attr("colspan")||1).appendTo(i)})},_contactContainers:function(e){var i,s,n,o,a,r,h,l,c,u,d=null,p=null;for(i=this.containers.length-1;i>=0;i--)if(!t.contains(this.currentItem[0],this.containers[i].element[0]))if(this._intersectsWith(this.containers[i].containerCache)){if(d&&t.contains(this.containers[i].element[0],d.element[0]))continue;d=this.containers[i],p=i}else this.containers[i].containerCache.over&&(this.containers[i]._trigger("out",e,this._uiHash(this)),this.containers[i].containerCache.over=0);if(d)if(1===this.containers.length)this.containers[p].containerCache.over||(this.containers[p]._trigger("over",e,this._uiHash(this)),this.containers[p].containerCache.over=1);else{for(n=1e4,o=null,c=d.floating||this._isFloating(this.currentItem),a=c?"left":"top",r=c?"width":"height",u=c?"pageX":"pageY",s=this.items.length-1;s>=0;s--)t.contains(this.containers[p].element[0],this.items[s].item[0])&&this.items[s].item[0]!==this.currentItem[0]&&(h=this.items[s].item.offset()[a],l=!1,e[u]-h>this.items[s][r]/2&&(l=!0),n>Math.abs(e[u]-h)&&(n=Math.abs(e[u]-h),o=this.items[s],this.direction=l?"up":"down"));if(!o&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[p])return this.currentContainer.containerCache.over||(this.containers[p]._trigger("over",e,this._uiHash()),this.currentContainer.containerCache.over=1),void 0;o?this._rearrange(e,o,null,!0):this._rearrange(e,null,this.containers[p].element,!0),this._trigger("change",e,this._uiHash()),this.containers[p]._trigger("change",e,this._uiHash(this)),this.currentContainer=this.containers[p],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[p]._trigger("over",e,this._uiHash(this)),this.containers[p].containerCache.over=1}},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper)?t(i.helper.apply(this.element[0],[e,this.currentItem])):"clone"===i.helper?this.currentItem.clone():this.currentItem;return s.parents("body").length||t("parent"!==i.appendTo?i.appendTo:this.currentItem[0].parentNode)[0].appendChild(s[0]),s[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(!s[0].style.width||i.forceHelperSize)&&s.width(this.currentItem.width()),(!s[0].style.height||i.forceHelperSize)&&s.height(this.currentItem.height()),s},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var e=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===this.document[0].body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&t.ui.ie)&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var t=this.currentItem.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options;"parent"===n.containment&&(n.containment=this.helper[0].parentNode),("document"===n.containment||"window"===n.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,"document"===n.containment?this.document.width():this.window.width()-this.helperProportions.width-this.margins.left,("document"===n.containment?this.document.height()||document.body.parentNode.scrollHeight:this.window.height()||this.document[0].body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(n.containment)||(e=t(n.containment)[0],i=t(n.containment).offset(),s="hidden"!==t(e).css("overflow"),this.containment=[i.left+(parseInt(t(e).css("borderLeftWidth"),10)||0)+(parseInt(t(e).css("paddingLeft"),10)||0)-this.margins.left,i.top+(parseInt(t(e).css("borderTopWidth"),10)||0)+(parseInt(t(e).css("paddingTop"),10)||0)-this.margins.top,i.left+(s?Math.max(e.scrollWidth,e.offsetWidth):e.offsetWidth)-(parseInt(t(e).css("borderLeftWidth"),10)||0)-(parseInt(t(e).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,i.top+(s?Math.max(e.scrollHeight,e.offsetHeight):e.offsetHeight)-(parseInt(t(e).css("borderTopWidth"),10)||0)-(parseInt(t(e).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(e,i){i||(i=this.position);var s="absolute"===e?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(n[0].tagName);return{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():o?0:n.scrollTop())*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():o?0:n.scrollLeft())*s}},_generatePosition:function(e){var i,s,n=this.options,o=e.pageX,a=e.pageY,r="absolute"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=/(html|body)/i.test(r[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(e.pageX-this.offset.click.leftthis.containment[2]&&(o=this.containment[2]+this.offset.click.left),e.pageY-this.offset.click.top>this.containment[3]&&(a=this.containment[3]+this.offset.click.top)),n.grid&&(i=this.originalPageY+Math.round((a-this.originalPageY)/n.grid[1])*n.grid[1],a=this.containment?i-this.offset.click.top>=this.containment[1]&&i-this.offset.click.top<=this.containment[3]?i:i-this.offset.click.top>=this.containment[1]?i-n.grid[1]:i+n.grid[1]:i,s=this.originalPageX+Math.round((o-this.originalPageX)/n.grid[0])*n.grid[0],o=this.containment?s-this.offset.click.left>=this.containment[0]&&s-this.offset.click.left<=this.containment[2]?s:s-this.offset.click.left>=this.containment[0]?s-n.grid[0]:s+n.grid[0]:s)),{top:a-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():h?0:r.scrollTop()),left:o-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():h?0:r.scrollLeft())}},_rearrange:function(t,e,i,s){i?i[0].appendChild(this.placeholder[0]):e.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?e.item[0]:e.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var n=this.counter; +this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(t,e){function i(t,e,i){return function(s){i._trigger(t,s,e._uiHash(e))}}this.reverting=!1;var s,n=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(s in this._storedCSS)("auto"===this._storedCSS[s]||"static"===this._storedCSS[s])&&(this._storedCSS[s]="");this.currentItem.css(this._storedCSS),this._removeClass(this.currentItem,"ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!e&&n.push(function(t){this._trigger("receive",t,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||e||n.push(function(t){this._trigger("update",t,this._uiHash())}),this!==this.currentContainer&&(e||(n.push(function(t){this._trigger("remove",t,this._uiHash())}),n.push(function(t){return function(e){t._trigger("receive",e,this._uiHash(this))}}.call(this,this.currentContainer)),n.push(function(t){return function(e){t._trigger("update",e,this._uiHash(this))}}.call(this,this.currentContainer)))),s=this.containers.length-1;s>=0;s--)e||n.push(i("deactivate",this,this.containers[s])),this.containers[s].containerCache.over&&(n.push(i("out",this,this.containers[s])),this.containers[s].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,e||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.cancelHelperRemoval||(this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null),!e){for(s=0;n.length>s;s++)n[s].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!this.cancelHelperRemoval},_trigger:function(){t.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(e){var i=e||this;return{helper:i.helper,placeholder:i.placeholder||t([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:e?e.element:null}}}),t.widget("ui.spinner",{version:"1.12.1",defaultElement:"",widgetEventPrefix:"spin",options:{classes:{"ui-spinner":"ui-corner-all","ui-spinner-down":"ui-corner-br","ui-spinner-up":"ui-corner-tr"},culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),""!==this.value()&&this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var e=this._super(),i=this.element;return t.each(["min","max","step"],function(t,s){var n=i.attr(s);null!=n&&n.length&&(e[s]=n)}),e},_events:{keydown:function(t){this._start(t)&&this._keydown(t)&&t.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(t){return this.cancelBlur?(delete this.cancelBlur,void 0):(this._stop(),this._refresh(),this.previous!==this.element.val()&&this._trigger("change",t),void 0)},mousewheel:function(t,e){if(e){if(!this.spinning&&!this._start(t))return!1;this._spin((e>0?1:-1)*this.options.step,t),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(t)},100),t.preventDefault()}},"mousedown .ui-spinner-button":function(e){function i(){var e=this.element[0]===t.ui.safeActiveElement(this.document[0]);e||(this.element.trigger("focus"),this.previous=s,this._delay(function(){this.previous=s}))}var s;s=this.element[0]===t.ui.safeActiveElement(this.document[0])?this.previous:this.element.val(),e.preventDefault(),i.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,i.call(this)}),this._start(e)!==!1&&this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(e){return t(e.currentTarget).hasClass("ui-state-active")?this._start(e)===!1?!1:(this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e),void 0):void 0},"mouseleave .ui-spinner-button":"_stop"},_enhance:function(){this.uiSpinner=this.element.attr("autocomplete","off").wrap("").parent().append("")},_draw:function(){this._enhance(),this._addClass(this.uiSpinner,"ui-spinner","ui-widget ui-widget-content"),this._addClass("ui-spinner-input"),this.element.attr("role","spinbutton"),this.buttons=this.uiSpinner.children("a").attr("tabIndex",-1).attr("aria-hidden",!0).button({classes:{"ui-button":""}}),this._removeClass(this.buttons,"ui-corner-all"),this._addClass(this.buttons.first(),"ui-spinner-button ui-spinner-up"),this._addClass(this.buttons.last(),"ui-spinner-button ui-spinner-down"),this.buttons.first().button({icon:this.options.icons.up,showLabel:!1}),this.buttons.last().button({icon:this.options.icons.down,showLabel:!1}),this.buttons.height()>Math.ceil(.5*this.uiSpinner.height())&&this.uiSpinner.height()>0&&this.uiSpinner.height(this.uiSpinner.height())},_keydown:function(e){var i=this.options,s=t.ui.keyCode;switch(e.keyCode){case s.UP:return this._repeat(null,1,e),!0;case s.DOWN:return this._repeat(null,-1,e),!0;case s.PAGE_UP:return this._repeat(null,i.page,e),!0;case s.PAGE_DOWN:return this._repeat(null,-i.page,e),!0}return!1},_start:function(t){return this.spinning||this._trigger("start",t)!==!1?(this.counter||(this.counter=1),this.spinning=!0,!0):!1},_repeat:function(t,e,i){t=t||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,e,i)},t),this._spin(e*this.options.step,i)},_spin:function(t,e){var i=this.value()||0;this.counter||(this.counter=1),i=this._adjustValue(i+t*this._increment(this.counter)),this.spinning&&this._trigger("spin",e,{value:i})===!1||(this._value(i),this.counter++)},_increment:function(e){var i=this.options.incremental;return i?t.isFunction(i)?i(e):Math.floor(e*e*e/5e4-e*e/500+17*e/200+1):1},_precision:function(){var t=this._precisionOf(this.options.step);return null!==this.options.min&&(t=Math.max(t,this._precisionOf(this.options.min))),t},_precisionOf:function(t){var e=""+t,i=e.indexOf(".");return-1===i?0:e.length-i-1},_adjustValue:function(t){var e,i,s=this.options;return e=null!==s.min?s.min:0,i=t-e,i=Math.round(i/s.step)*s.step,t=e+i,t=parseFloat(t.toFixed(this._precision())),null!==s.max&&t>s.max?s.max:null!==s.min&&s.min>t?s.min:t},_stop:function(t){this.spinning&&(clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger("stop",t))},_setOption:function(t,e){var i,s,n;return"culture"===t||"numberFormat"===t?(i=this._parse(this.element.val()),this.options[t]=e,this.element.val(this._format(i)),void 0):(("max"===t||"min"===t||"step"===t)&&"string"==typeof e&&(e=this._parse(e)),"icons"===t&&(s=this.buttons.first().find(".ui-icon"),this._removeClass(s,null,this.options.icons.up),this._addClass(s,null,e.up),n=this.buttons.last().find(".ui-icon"),this._removeClass(n,null,this.options.icons.down),this._addClass(n,null,e.down)),this._super(t,e),void 0)},_setOptionDisabled:function(t){this._super(t),this._toggleClass(this.uiSpinner,null,"ui-state-disabled",!!t),this.element.prop("disabled",!!t),this.buttons.button(t?"disable":"enable")},_setOptions:r(function(t){this._super(t)}),_parse:function(t){return"string"==typeof t&&""!==t&&(t=window.Globalize&&this.options.numberFormat?Globalize.parseFloat(t,10,this.options.culture):+t),""===t||isNaN(t)?null:t},_format:function(t){return""===t?"":window.Globalize&&this.options.numberFormat?Globalize.format(t,this.options.numberFormat,this.options.culture):t},_refresh:function(){this.element.attr({"aria-valuemin":this.options.min,"aria-valuemax":this.options.max,"aria-valuenow":this._parse(this.element.val())})},isValid:function(){var t=this.value();return null===t?!1:t===this._adjustValue(t)},_value:function(t,e){var i;""!==t&&(i=this._parse(t),null!==i&&(e||(i=this._adjustValue(i)),t=this._format(i))),this.element.val(t),this._refresh()},_destroy:function(){this.element.prop("disabled",!1).removeAttr("autocomplete role aria-valuemin aria-valuemax aria-valuenow"),this.uiSpinner.replaceWith(this.element)},stepUp:r(function(t){this._stepUp(t)}),_stepUp:function(t){this._start()&&(this._spin((t||1)*this.options.step),this._stop())},stepDown:r(function(t){this._stepDown(t)}),_stepDown:function(t){this._start()&&(this._spin((t||1)*-this.options.step),this._stop())},pageUp:r(function(t){this._stepUp((t||1)*this.options.page)}),pageDown:r(function(t){this._stepDown((t||1)*this.options.page)}),value:function(t){return arguments.length?(r(this._value).call(this,t),void 0):this._parse(this.element.val())},widget:function(){return this.uiSpinner}}),t.uiBackCompat!==!1&&t.widget("ui.spinner",t.ui.spinner,{_enhance:function(){this.uiSpinner=this.element.attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml())},_uiSpinnerHtml:function(){return""},_buttonHtml:function(){return""}}),t.ui.spinner,t.widget("ui.tabs",{version:"1.12.1",delay:300,options:{active:null,classes:{"ui-tabs":"ui-corner-all","ui-tabs-nav":"ui-corner-all","ui-tabs-panel":"ui-corner-bottom","ui-tabs-tab":"ui-corner-top"},collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_isLocal:function(){var t=/#.*$/;return function(e){var i,s;i=e.href.replace(t,""),s=location.href.replace(t,"");try{i=decodeURIComponent(i)}catch(n){}try{s=decodeURIComponent(s)}catch(n){}return e.hash.length>1&&i===s}}(),_create:function(){var e=this,i=this.options;this.running=!1,this._addClass("ui-tabs","ui-widget ui-widget-content"),this._toggleClass("ui-tabs-collapsible",null,i.collapsible),this._processTabs(),i.active=this._initialActive(),t.isArray(i.disabled)&&(i.disabled=t.unique(i.disabled.concat(t.map(this.tabs.filter(".ui-state-disabled"),function(t){return e.tabs.index(t)}))).sort()),this.active=this.options.active!==!1&&this.anchors.length?this._findActive(i.active):t(),this._refresh(),this.active.length&&this.load(i.active)},_initialActive:function(){var e=this.options.active,i=this.options.collapsible,s=location.hash.substring(1);return null===e&&(s&&this.tabs.each(function(i,n){return t(n).attr("aria-controls")===s?(e=i,!1):void 0}),null===e&&(e=this.tabs.index(this.tabs.filter(".ui-tabs-active"))),(null===e||-1===e)&&(e=this.tabs.length?0:!1)),e!==!1&&(e=this.tabs.index(this.tabs.eq(e)),-1===e&&(e=i?!1:0)),!i&&e===!1&&this.anchors.length&&(e=0),e},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):t()}},_tabKeydown:function(e){var i=t(t.ui.safeActiveElement(this.document[0])).closest("li"),s=this.tabs.index(i),n=!0;if(!this._handlePageNav(e)){switch(e.keyCode){case t.ui.keyCode.RIGHT:case t.ui.keyCode.DOWN:s++;break;case t.ui.keyCode.UP:case t.ui.keyCode.LEFT:n=!1,s--;break;case t.ui.keyCode.END:s=this.anchors.length-1;break;case t.ui.keyCode.HOME:s=0;break;case t.ui.keyCode.SPACE:return e.preventDefault(),clearTimeout(this.activating),this._activate(s),void 0;case t.ui.keyCode.ENTER:return e.preventDefault(),clearTimeout(this.activating),this._activate(s===this.options.active?!1:s),void 0;default:return}e.preventDefault(),clearTimeout(this.activating),s=this._focusNextTab(s,n),e.ctrlKey||e.metaKey||(i.attr("aria-selected","false"),this.tabs.eq(s).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",s)},this.delay))}},_panelKeydown:function(e){this._handlePageNav(e)||e.ctrlKey&&e.keyCode===t.ui.keyCode.UP&&(e.preventDefault(),this.active.trigger("focus"))},_handlePageNav:function(e){return e.altKey&&e.keyCode===t.ui.keyCode.PAGE_UP?(this._activate(this._focusNextTab(this.options.active-1,!1)),!0):e.altKey&&e.keyCode===t.ui.keyCode.PAGE_DOWN?(this._activate(this._focusNextTab(this.options.active+1,!0)),!0):void 0},_findNextTab:function(e,i){function s(){return e>n&&(e=0),0>e&&(e=n),e}for(var n=this.tabs.length-1;-1!==t.inArray(s(),this.options.disabled);)e=i?e+1:e-1;return e},_focusNextTab:function(t,e){return t=this._findNextTab(t,e),this.tabs.eq(t).trigger("focus"),t},_setOption:function(t,e){return"active"===t?(this._activate(e),void 0):(this._super(t,e),"collapsible"===t&&(this._toggleClass("ui-tabs-collapsible",null,e),e||this.options.active!==!1||this._activate(0)),"event"===t&&this._setupEvents(e),"heightStyle"===t&&this._setupHeightStyle(e),void 0)},_sanitizeSelector:function(t){return t?t.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var e=this.options,i=this.tablist.children(":has(a[href])");e.disabled=t.map(i.filter(".ui-state-disabled"),function(t){return i.index(t)}),this._processTabs(),e.active!==!1&&this.anchors.length?this.active.length&&!t.contains(this.tablist[0],this.active[0])?this.tabs.length===e.disabled.length?(e.active=!1,this.active=t()):this._activate(this._findNextTab(Math.max(0,e.active-1),!1)):e.active=this.tabs.index(this.active):(e.active=!1,this.active=t()),this._refresh()},_refresh:function(){this._setOptionDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-hidden":"true"}),this.active.length?(this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}),this._addClass(this.active,"ui-tabs-active","ui-state-active"),this._getPanelForTab(this.active).show().attr({"aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var e=this,i=this.tabs,s=this.anchors,n=this.panels;this.tablist=this._getList().attr("role","tablist"),this._addClass(this.tablist,"ui-tabs-nav","ui-helper-reset ui-helper-clearfix ui-widget-header"),this.tablist.on("mousedown"+this.eventNamespace,"> li",function(e){t(this).is(".ui-state-disabled")&&e.preventDefault()}).on("focus"+this.eventNamespace,".ui-tabs-anchor",function(){t(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this.tabs=this.tablist.find("> li:has(a[href])").attr({role:"tab",tabIndex:-1}),this._addClass(this.tabs,"ui-tabs-tab","ui-state-default"),this.anchors=this.tabs.map(function(){return t("a",this)[0]}).attr({role:"presentation",tabIndex:-1}),this._addClass(this.anchors,"ui-tabs-anchor"),this.panels=t(),this.anchors.each(function(i,s){var n,o,a,r=t(s).uniqueId().attr("id"),h=t(s).closest("li"),l=h.attr("aria-controls");e._isLocal(s)?(n=s.hash,a=n.substring(1),o=e.element.find(e._sanitizeSelector(n))):(a=h.attr("aria-controls")||t({}).uniqueId()[0].id,n="#"+a,o=e.element.find(n),o.length||(o=e._createPanel(a),o.insertAfter(e.panels[i-1]||e.tablist)),o.attr("aria-live","polite")),o.length&&(e.panels=e.panels.add(o)),l&&h.data("ui-tabs-aria-controls",l),h.attr({"aria-controls":a,"aria-labelledby":r}),o.attr("aria-labelledby",r)}),this.panels.attr("role","tabpanel"),this._addClass(this.panels,"ui-tabs-panel","ui-widget-content"),i&&(this._off(i.not(this.tabs)),this._off(s.not(this.anchors)),this._off(n.not(this.panels)))},_getList:function(){return this.tablist||this.element.find("ol, ul").eq(0)},_createPanel:function(e){return t("
").attr("id",e).data("ui-tabs-destroy",!0)},_setOptionDisabled:function(e){var i,s,n;for(t.isArray(e)&&(e.length?e.length===this.anchors.length&&(e=!0):e=!1),n=0;s=this.tabs[n];n++)i=t(s),e===!0||-1!==t.inArray(n,e)?(i.attr("aria-disabled","true"),this._addClass(i,null,"ui-state-disabled")):(i.removeAttr("aria-disabled"),this._removeClass(i,null,"ui-state-disabled"));this.options.disabled=e,this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,e===!0)},_setupEvents:function(e){var i={};e&&t.each(e.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(!0,this.anchors,{click:function(t){t.preventDefault()}}),this._on(this.anchors,i),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(e){var i,s=this.element.parent();"fill"===e?(i=s.height(),i-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var e=t(this),s=e.css("position");"absolute"!==s&&"fixed"!==s&&(i-=e.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){i-=t(this).outerHeight(!0)}),this.panels.each(function(){t(this).height(Math.max(0,i-t(this).innerHeight()+t(this).height()))}).css("overflow","auto")):"auto"===e&&(i=0,this.panels.each(function(){i=Math.max(i,t(this).height("").height())}).height(i))},_eventHandler:function(e){var i=this.options,s=this.active,n=t(e.currentTarget),o=n.closest("li"),a=o[0]===s[0],r=a&&i.collapsible,h=r?t():this._getPanelForTab(o),l=s.length?this._getPanelForTab(s):t(),c={oldTab:s,oldPanel:l,newTab:r?t():o,newPanel:h};e.preventDefault(),o.hasClass("ui-state-disabled")||o.hasClass("ui-tabs-loading")||this.running||a&&!i.collapsible||this._trigger("beforeActivate",e,c)===!1||(i.active=r?!1:this.tabs.index(o),this.active=a?t():o,this.xhr&&this.xhr.abort(),l.length||h.length||t.error("jQuery UI Tabs: Mismatching fragment identifier."),h.length&&this.load(this.tabs.index(o),e),this._toggle(e,c))},_toggle:function(e,i){function s(){o.running=!1,o._trigger("activate",e,i)}function n(){o._addClass(i.newTab.closest("li"),"ui-tabs-active","ui-state-active"),a.length&&o.options.show?o._show(a,o.options.show,s):(a.show(),s())}var o=this,a=i.newPanel,r=i.oldPanel;this.running=!0,r.length&&this.options.hide?this._hide(r,this.options.hide,function(){o._removeClass(i.oldTab.closest("li"),"ui-tabs-active","ui-state-active"),n()}):(this._removeClass(i.oldTab.closest("li"),"ui-tabs-active","ui-state-active"),r.hide(),n()),r.attr("aria-hidden","true"),i.oldTab.attr({"aria-selected":"false","aria-expanded":"false"}),a.length&&r.length?i.oldTab.attr("tabIndex",-1):a.length&&this.tabs.filter(function(){return 0===t(this).attr("tabIndex")}).attr("tabIndex",-1),a.attr("aria-hidden","false"),i.newTab.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_activate:function(e){var i,s=this._findActive(e);s[0]!==this.active[0]&&(s.length||(s=this.active),i=s.find(".ui-tabs-anchor")[0],this._eventHandler({target:i,currentTarget:i,preventDefault:t.noop}))},_findActive:function(e){return e===!1?t():this.tabs.eq(e)},_getIndex:function(e){return"string"==typeof e&&(e=this.anchors.index(this.anchors.filter("[href$='"+t.ui.escapeSelector(e)+"']"))),e},_destroy:function(){this.xhr&&this.xhr.abort(),this.tablist.removeAttr("role").off(this.eventNamespace),this.anchors.removeAttr("role tabIndex").removeUniqueId(),this.tabs.add(this.panels).each(function(){t.data(this,"ui-tabs-destroy")?t(this).remove():t(this).removeAttr("role tabIndex aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded")}),this.tabs.each(function(){var e=t(this),i=e.data("ui-tabs-aria-controls");i?e.attr("aria-controls",i).removeData("ui-tabs-aria-controls"):e.removeAttr("aria-controls")}),this.panels.show(),"content"!==this.options.heightStyle&&this.panels.css("height","")},enable:function(e){var i=this.options.disabled;i!==!1&&(void 0===e?i=!1:(e=this._getIndex(e),i=t.isArray(i)?t.map(i,function(t){return t!==e?t:null}):t.map(this.tabs,function(t,i){return i!==e?i:null})),this._setOptionDisabled(i))},disable:function(e){var i=this.options.disabled;if(i!==!0){if(void 0===e)i=!0;else{if(e=this._getIndex(e),-1!==t.inArray(e,i))return;i=t.isArray(i)?t.merge([e],i).sort():[e]}this._setOptionDisabled(i)}},load:function(e,i){e=this._getIndex(e);var s=this,n=this.tabs.eq(e),o=n.find(".ui-tabs-anchor"),a=this._getPanelForTab(n),r={tab:n,panel:a},h=function(t,e){"abort"===e&&s.panels.stop(!1,!0),s._removeClass(n,"ui-tabs-loading"),a.removeAttr("aria-busy"),t===s.xhr&&delete s.xhr};this._isLocal(o[0])||(this.xhr=t.ajax(this._ajaxSettings(o,i,r)),this.xhr&&"canceled"!==this.xhr.statusText&&(this._addClass(n,"ui-tabs-loading"),a.attr("aria-busy","true"),this.xhr.done(function(t,e,n){setTimeout(function(){a.html(t),s._trigger("load",i,r),h(n,e)},1)}).fail(function(t,e){setTimeout(function(){h(t,e)},1)})))},_ajaxSettings:function(e,i,s){var n=this;return{url:e.attr("href").replace(/#.*$/,""),beforeSend:function(e,o){return n._trigger("beforeLoad",i,t.extend({jqXHR:e,ajaxSettings:o},s))}}},_getPanelForTab:function(e){var i=t(e).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+i))}}),t.uiBackCompat!==!1&&t.widget("ui.tabs",t.ui.tabs,{_processTabs:function(){this._superApply(arguments),this._addClass(this.tabs,"ui-tab")}}),t.ui.tabs,t.widget("ui.tooltip",{version:"1.12.1",options:{classes:{"ui-tooltip":"ui-corner-all ui-widget-shadow"},content:function(){var e=t(this).attr("title")||"";return t("").text(e).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,track:!1,close:null,open:null},_addDescribedBy:function(e,i){var s=(e.attr("aria-describedby")||"").split(/\s+/);s.push(i),e.data("ui-tooltip-id",i).attr("aria-describedby",t.trim(s.join(" ")))},_removeDescribedBy:function(e){var i=e.data("ui-tooltip-id"),s=(e.attr("aria-describedby")||"").split(/\s+/),n=t.inArray(i,s);-1!==n&&s.splice(n,1),e.removeData("ui-tooltip-id"),s=t.trim(s.join(" ")),s?e.attr("aria-describedby",s):e.removeAttr("aria-describedby")},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.liveRegion=t("
").attr({role:"log","aria-live":"assertive","aria-relevant":"additions"}).appendTo(this.document[0].body),this._addClass(this.liveRegion,null,"ui-helper-hidden-accessible"),this.disabledTitles=t([])},_setOption:function(e,i){var s=this;this._super(e,i),"content"===e&&t.each(this.tooltips,function(t,e){s._updateContent(e.element)})},_setOptionDisabled:function(t){this[t?"_disable":"_enable"]()},_disable:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur");n.target=n.currentTarget=s.element[0],e.close(n,!0)}),this.disabledTitles=this.disabledTitles.add(this.element.find(this.options.items).addBack().filter(function(){var e=t(this);return e.is("[title]")?e.data("ui-tooltip-title",e.attr("title")).removeAttr("title"):void 0}))},_enable:function(){this.disabledTitles.each(function(){var e=t(this);e.data("ui-tooltip-title")&&e.attr("title",e.data("ui-tooltip-title"))}),this.disabledTitles=t([])},open:function(e){var i=this,s=t(e?e.target:this.element).closest(this.options.items);s.length&&!s.data("ui-tooltip-id")&&(s.attr("title")&&s.data("ui-tooltip-title",s.attr("title")),s.data("ui-tooltip-open",!0),e&&"mouseover"===e.type&&s.parents().each(function(){var e,s=t(this);s.data("ui-tooltip-open")&&(e=t.Event("blur"),e.target=e.currentTarget=this,i.close(e,!0)),s.attr("title")&&(s.uniqueId(),i.parents[this.id]={element:this,title:s.attr("title")},s.attr("title",""))}),this._registerCloseHandlers(e,s),this._updateContent(s,e))},_updateContent:function(t,e){var i,s=this.options.content,n=this,o=e?e.type:null;return"string"==typeof s||s.nodeType||s.jquery?this._open(e,t,s):(i=s.call(t[0],function(i){n._delay(function(){t.data("ui-tooltip-open")&&(e&&(e.type=o),this._open(e,t,i))})}),i&&this._open(e,t,i),void 0)},_open:function(e,i,s){function n(t){l.of=t,a.is(":hidden")||a.position(l)}var o,a,r,h,l=t.extend({},this.options.position);if(s){if(o=this._find(i))return o.tooltip.find(".ui-tooltip-content").html(s),void 0;i.is("[title]")&&(e&&"mouseover"===e.type?i.attr("title",""):i.removeAttr("title")),o=this._tooltip(i),a=o.tooltip,this._addDescribedBy(i,a.attr("id")),a.find(".ui-tooltip-content").html(s),this.liveRegion.children().hide(),h=t("
").html(a.find(".ui-tooltip-content").html()),h.removeAttr("name").find("[name]").removeAttr("name"),h.removeAttr("id").find("[id]").removeAttr("id"),h.appendTo(this.liveRegion),this.options.track&&e&&/^mouse/.test(e.type)?(this._on(this.document,{mousemove:n}),n(e)):a.position(t.extend({of:i},this.options.position)),a.hide(),this._show(a,this.options.show),this.options.track&&this.options.show&&this.options.show.delay&&(r=this.delayedShow=setInterval(function(){a.is(":visible")&&(n(l.of),clearInterval(r))},t.fx.interval)),this._trigger("open",e,{tooltip:a})}},_registerCloseHandlers:function(e,i){var s={keyup:function(e){if(e.keyCode===t.ui.keyCode.ESCAPE){var s=t.Event(e);s.currentTarget=i[0],this.close(s,!0)}}};i[0]!==this.element[0]&&(s.remove=function(){this._removeTooltip(this._find(i).tooltip)}),e&&"mouseover"!==e.type||(s.mouseleave="close"),e&&"focusin"!==e.type||(s.focusout="close"),this._on(!0,i,s)},close:function(e){var i,s=this,n=t(e?e.currentTarget:this.element),o=this._find(n);return o?(i=o.tooltip,o.closing||(clearInterval(this.delayedShow),n.data("ui-tooltip-title")&&!n.attr("title")&&n.attr("title",n.data("ui-tooltip-title")),this._removeDescribedBy(n),o.hiding=!0,i.stop(!0),this._hide(i,this.options.hide,function(){s._removeTooltip(t(this))}),n.removeData("ui-tooltip-open"),this._off(n,"mouseleave focusout keyup"),n[0]!==this.element[0]&&this._off(n,"remove"),this._off(this.document,"mousemove"),e&&"mouseleave"===e.type&&t.each(this.parents,function(e,i){t(i.element).attr("title",i.title),delete s.parents[e]}),o.closing=!0,this._trigger("close",e,{tooltip:i}),o.hiding||(o.closing=!1)),void 0):(n.removeData("ui-tooltip-open"),void 0)},_tooltip:function(e){var i=t("
").attr("role","tooltip"),s=t("
").appendTo(i),n=i.uniqueId().attr("id");return this._addClass(s,"ui-tooltip-content"),this._addClass(i,"ui-tooltip","ui-widget ui-widget-content"),i.appendTo(this._appendTo(e)),this.tooltips[n]={element:e,tooltip:i}},_find:function(t){var e=t.data("ui-tooltip-id");return e?this.tooltips[e]:null},_removeTooltip:function(t){t.remove(),delete this.tooltips[t.attr("id")]},_appendTo:function(t){var e=t.closest(".ui-front, dialog");return e.length||(e=this.document[0].body),e},_destroy:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur"),o=s.element;n.target=n.currentTarget=o[0],e.close(n,!0),t("#"+i).remove(),o.data("ui-tooltip-title")&&(o.attr("title")||o.attr("title",o.data("ui-tooltip-title")),o.removeData("ui-tooltip-title"))}),this.liveRegion.remove()}}),t.uiBackCompat!==!1&&t.widget("ui.tooltip",t.ui.tooltip,{options:{tooltipClass:null},_tooltip:function(){var t=this._superApply(arguments);return this.options.tooltipClass&&t.tooltip.addClass(this.options.tooltipClass),t}}),t.ui.tooltip}); \ No newline at end of file diff --git a/public/lib/md5.min.js b/public/lib/md5.min.js new file mode 100644 index 0000000..05bab20 --- /dev/null +++ b/public/lib/md5.min.js @@ -0,0 +1,22 @@ +/* + * js-md5 v0.3.0 + * https://github.com/emn178/js-md5 + * + * Copyright 2014-2015, emn178@gmail.com + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ +(function(q,F){var u="undefined"!=typeof module;u&&(q=global,q.JS_MD5_TEST&&(q.navigator={userAgent:"Firefox"}));var C=(q.JS_MD5_TEST||!u)&&-1!=navigator.userAgent.indexOf("Firefox"),y=!q.JS_MD5_TEST&&"undefined"!=typeof ArrayBuffer,f="0123456789abcdef".split(""),D=[128,32768,8388608,-2147483648],t=[0,8,16,24],e=[],r;if(y){var A=new ArrayBuffer(68);r=new Uint8Array(A);e=new Uint32Array(A)}var x=function(g){var q="string"!=typeof g;q&&g.constructor==ArrayBuffer&&(g=new Uint8Array(g));var k,l,m,n,b, +a,d,c,h,u=!0,x=!1,p=0,v=0,z=0,w=g.length;e[16]=0;do{e[0]=e[16];e[16]=e[1]=e[2]=e[3]=e[4]=e[5]=e[6]=e[7]=e[8]=e[9]=e[10]=e[11]=e[12]=e[13]=e[14]=e[15]=0;if(q)if(y)for(a=v;pa;++p)r[a++]=g[p];else for(a=v;pa;++p)e[a>>2]|=g[p]<a;++p)b=g.charCodeAt(p),128>b?r[a++]=b:(2048>b?r[a++]=192|b>>6:(55296>b||57344<=b?r[a++]=224|b>>12:(b=65536+((b&1023)<<10|g.charCodeAt(++p)&1023),r[a++]=240|b>>18,r[a++]=128|b>>12&63),r[a++]=128|b>>6&63),r[a++]=128|b&63);else for(a= +v;pa;++p)b=g.charCodeAt(p),128>b?e[a>>2]|=b<b?e[a>>2]|=(192|b>>6)<b||57344<=b?e[a>>2]|=(224|b>>12)<>2]|=(240|b>>18)<>2]|=(128|b>>12&63)<>2]|=(128|b>>6&63)<>2]|=(128|b&63)<>2]|=D[a&3],++p);p>w&&56>a&&(e[14]=z<<3,x=!0);u?(b=e[0]-680876937,b=(b<<7|b>>>25)-271733879<<0,c=(-1732584194^b&2004318071)+e[1]-117830708,c=(c<<12|c>>> +20)+b<<0,d=(-271733879^c&(b^-271733879))+e[2]-1126478375,d=(d<<17|d>>>15)+c<<0,a=(b^d&(c^b))+e[3]-1316259209):(b=k,a=l,d=m,c=n,b+=(c^a&(d^c))+e[0]-680876936,b=(b<<7|b>>>25)+a<<0,c+=(d^b&(a^d))+e[1]-389564586,c=(c<<12|c>>>20)+b<<0,d+=(a^c&(b^a))+e[2]+606105819,d=(d<<17|d>>>15)+c<<0,a+=(b^d&(c^b))+e[3]-1044525330);a=(a<<22|a>>>10)+d<<0;b+=(c^a&(d^c))+e[4]-176418897;b=(b<<7|b>>>25)+a<<0;c+=(d^b&(a^d))+e[5]+1200080426;c=(c<<12|c>>>20)+b<<0;d+=(a^c&(b^a))+e[6]-1473231341;d=(d<<17|d>>>15)+c<<0;a+=(b^d& +(c^b))+e[7]-45705983;a=(a<<22|a>>>10)+d<<0;b+=(c^a&(d^c))+e[8]+1770035416;b=(b<<7|b>>>25)+a<<0;c+=(d^b&(a^d))+e[9]-1958414417;c=(c<<12|c>>>20)+b<<0;d+=(a^c&(b^a))+e[10]-42063;d=(d<<17|d>>>15)+c<<0;a+=(b^d&(c^b))+e[11]-1990404162;a=(a<<22|a>>>10)+d<<0;b+=(c^a&(d^c))+e[12]+1804603682;b=(b<<7|b>>>25)+a<<0;c+=(d^b&(a^d))+e[13]-40341101;c=(c<<12|c>>>20)+b<<0;d+=(a^c&(b^a))+e[14]-1502002290;d=(d<<17|d>>>15)+c<<0;a+=(b^d&(c^b))+e[15]+1236535329;a=(a<<22|a>>>10)+d<<0;b+=(d^c&(a^d))+e[1]-165796510;b=(b<<5| +b>>>27)+a<<0;c+=(a^d&(b^a))+e[6]-1069501632;c=(c<<9|c>>>23)+b<<0;d+=(b^a&(c^b))+e[11]+643717713;d=(d<<14|d>>>18)+c<<0;a+=(c^b&(d^c))+e[0]-373897302;a=(a<<20|a>>>12)+d<<0;b+=(d^c&(a^d))+e[5]-701558691;b=(b<<5|b>>>27)+a<<0;c+=(a^d&(b^a))+e[10]+38016083;c=(c<<9|c>>>23)+b<<0;d+=(b^a&(c^b))+e[15]-660478335;d=(d<<14|d>>>18)+c<<0;a+=(c^b&(d^c))+e[4]-405537848;a=(a<<20|a>>>12)+d<<0;b+=(d^c&(a^d))+e[9]+568446438;b=(b<<5|b>>>27)+a<<0;c+=(a^d&(b^a))+e[14]-1019803690;c=(c<<9|c>>>23)+b<<0;d+=(b^a&(c^b))+e[3]- +187363961;d=(d<<14|d>>>18)+c<<0;a+=(c^b&(d^c))+e[8]+1163531501;a=(a<<20|a>>>12)+d<<0;b+=(d^c&(a^d))+e[13]-1444681467;b=(b<<5|b>>>27)+a<<0;c+=(a^d&(b^a))+e[2]-51403784;c=(c<<9|c>>>23)+b<<0;d+=(b^a&(c^b))+e[7]+1735328473;d=(d<<14|d>>>18)+c<<0;a+=(c^b&(d^c))+e[12]-1926607734;a=(a<<20|a>>>12)+d<<0;h=a^d;b+=(h^c)+e[5]-378558;b=(b<<4|b>>>28)+a<<0;c+=(h^b)+e[8]-2022574463;c=(c<<11|c>>>21)+b<<0;h=c^b;d+=(h^a)+e[11]+1839030562;d=(d<<16|d>>>16)+c<<0;a+=(h^d)+e[14]-35309556;a=(a<<23|a>>>9)+d<<0;h=a^d;b+=(h^ +c)+e[1]-1530992060;b=(b<<4|b>>>28)+a<<0;c+=(h^b)+e[4]+1272893353;c=(c<<11|c>>>21)+b<<0;h=c^b;d+=(h^a)+e[7]-155497632;d=(d<<16|d>>>16)+c<<0;a+=(h^d)+e[10]-1094730640;a=(a<<23|a>>>9)+d<<0;h=a^d;b+=(h^c)+e[13]+681279174;b=(b<<4|b>>>28)+a<<0;c+=(h^b)+e[0]-358537222;c=(c<<11|c>>>21)+b<<0;h=c^b;d+=(h^a)+e[3]-722521979;d=(d<<16|d>>>16)+c<<0;a+=(h^d)+e[6]+76029189;a=(a<<23|a>>>9)+d<<0;h=a^d;b+=(h^c)+e[9]-640364487;b=(b<<4|b>>>28)+a<<0;c+=(h^b)+e[12]-421815835;c=(c<<11|c>>>21)+b<<0;h=c^b;d+=(h^a)+e[15]+530742520; +d=(d<<16|d>>>16)+c<<0;a+=(h^d)+e[2]-995338651;a=(a<<23|a>>>9)+d<<0;b+=(d^(a|~c))+e[0]-198630844;b=(b<<6|b>>>26)+a<<0;c+=(a^(b|~d))+e[7]+1126891415;c=(c<<10|c>>>22)+b<<0;d+=(b^(c|~a))+e[14]-1416354905;d=(d<<15|d>>>17)+c<<0;a+=(c^(d|~b))+e[5]-57434055;a=(a<<21|a>>>11)+d<<0;b+=(d^(a|~c))+e[12]+1700485571;b=(b<<6|b>>>26)+a<<0;c+=(a^(b|~d))+e[3]-1894986606;c=(c<<10|c>>>22)+b<<0;d+=(b^(c|~a))+e[10]-1051523;d=(d<<15|d>>>17)+c<<0;a+=(c^(d|~b))+e[1]-2054922799;a=(a<<21|a>>>11)+d<<0;b+=(d^(a|~c))+e[8]+1873313359; +b=(b<<6|b>>>26)+a<<0;c+=(a^(b|~d))+e[15]-30611744;c=(c<<10|c>>>22)+b<<0;d+=(b^(c|~a))+e[6]-1560198380;d=(d<<15|d>>>17)+c<<0;a+=(c^(d|~b))+e[13]+1309151649;a=(a<<21|a>>>11)+d<<0;b+=(d^(a|~c))+e[4]-145523070;b=(b<<6|b>>>26)+a<<0;c+=(a^(b|~d))+e[11]-1120210379;c=(c<<10|c>>>22)+b<<0;d+=(b^(c|~a))+e[2]+718787259;d=(d<<15|d>>>17)+c<<0;a+=(c^(d|~b))+e[9]-343485551;a=(a<<21|a>>>11)+d<<0;u?(k=b+1732584193<<0,l=a-271733879<<0,m=d-1732584194<<0,n=c+271733878<<0,u=!1):(k=k+b<<0,l=l+a<<0,m=m+d<<0,n=n+c<<0)}while(!x); +return C?(g=f[k>>4&15]+f[k&15],g+=f[k>>12&15]+f[k>>8&15],g+=f[k>>20&15]+f[k>>16&15],g+=f[k>>28&15]+f[k>>24&15],g+=f[l>>4&15]+f[l&15],g+=f[l>>12&15]+f[l>>8&15],g+=f[l>>20&15]+f[l>>16&15],g+=f[l>>28&15]+f[l>>24&15],g+=f[m>>4&15]+f[m&15],g+=f[m>>12&15]+f[m>>8&15],g+=f[m>>20&15]+f[m>>16&15],g+=f[m>>28&15]+f[m>>24&15],g+=f[n>>4&15]+f[n&15],g+=f[n>>12&15]+f[n>>8&15],g+=f[n>>20&15]+f[n>>16&15],g+=f[n>>28&15]+f[n>>24&15]):f[k>>4&15]+f[k&15]+f[k>>12&15]+f[k>>8&15]+f[k>>20&15]+f[k>>16&15]+f[k>>28&15]+f[k>> +24&15]+f[l>>4&15]+f[l&15]+f[l>>12&15]+f[l>>8&15]+f[l>>20&15]+f[l>>16&15]+f[l>>28&15]+f[l>>24&15]+f[m>>4&15]+f[m&15]+f[m>>12&15]+f[m>>8&15]+f[m>>20&15]+f[m>>16&15]+f[m>>28&15]+f[m>>24&15]+f[n>>4&15]+f[n&15]+f[n>>12&15]+f[n>>8&15]+f[n>>20&15]+f[n>>16&15]+f[n>>28&15]+f[n>>24&15]};if(!q.JS_MD5_TEST&&u){var B=require("crypto"),E=require("buffer").Buffer;module.exports=function(e){if("string"==typeof e)return 80>=e.length||183>=e.length&&!/[^\x00-\x7F]/.test(e)?x(e):B.createHash("md5").update(e,"utf8").digest("hex"); +e.constructor==ArrayBuffer&&(e=new Uint8Array(e));return 370>=e.length?x(e):B.createHash("md5").update(new E(e)).digest("hex")}}else q&&(q.md5=x)})(this); -- GitLab From ef158e153124f28b664c0515ee127e1e46eb970c Mon Sep 17 00:00:00 2001 From: roberto Date: Wed, 5 Oct 2016 18:09:02 +0200 Subject: [PATCH 8/8] import files dialog --- views/projectSettings.mustache | 102 +++++++++++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 5 deletions(-) diff --git a/views/projectSettings.mustache b/views/projectSettings.mustache index a71dac1..da0c633 100644 --- a/views/projectSettings.mustache +++ b/views/projectSettings.mustache @@ -8,7 +8,7 @@ - +