';
15 |
16 | // Folder in Dropbox for images to be scaled down
17 | const FOLDER_PATH = '/photos';
18 |
19 | // Number of results when listing files from Dropbox
20 | const PAGINATION_SIZE = 20;
21 |
22 | // Anything above this size limit will be resized according to options below
23 | const LIMIT_SIZE = 5000000; // in bytes
24 |
25 | // Parameters to configure the thumbnail download
26 | const FORMAT = 'jpeg';
27 | const SIZE = 'w2048h1536';
28 | const MODE = 'fitone_bestfit';
29 |
30 | // Initialization of Dropbox SDK
31 | const
32 | Dropbox = require('dropbox').Dropbox,
33 | fetch = require('isomorphic-fetch'),
34 | config = {
35 | fetch: fetch,
36 | accessToken: DROPBOX_ACCESS_TOKEN
37 | };
38 | var dbx = new Dropbox(config);
39 |
40 |
41 | // Entry point for the script
42 | module.exports.run = async () =>{
43 | try{
44 |
45 | let has_more = true;
46 | let cursor = null;
47 | let counter = 0; // keeps track of number of imgs resized
48 |
49 | while(has_more){
50 |
51 | let files_list;
52 |
53 | // Get the next page of files from Dropbox
54 | if(!cursor){
55 | let params = { path: FOLDER_PATH, limit: PAGINATION_SIZE };
56 | files_list = await dbx.filesListFolder(params);
57 |
58 | }else{
59 | files_list = await dbx.filesListFolderContinue({cursor:cursor});
60 | }
61 |
62 | cursor = files_list.cursor;
63 | has_more = files_list.has_more;
64 |
65 | let imgs_paths = filterOverSizedImgsInDropboxResult(files_list.entries);
66 |
67 | for(let i = 0; i < imgs_paths.length; i++){
68 |
69 | let path = imgs_paths[i];
70 |
71 | //1. download a lower resolution version of the file
72 | let thumbnail = await downloadThumbnailAsync(path);
73 |
74 | //2. upload the lowres file to Dropbox in the same folder
75 | let upload_response = await uploadFileAsync(path, thumbnail.fileBinary);
76 |
77 | //3. move original file to a /highres folder within the folder of origin
78 | await moveFileAsync(path);
79 |
80 | console.log('resized and moved ' + path);
81 |
82 | counter++;
83 | }
84 | }
85 |
86 | console.log("Finished! Resized " + counter + " images");
87 |
88 | }catch(error){
89 | console.log('!! Encountered error, aborting');
90 | console.log(error);
91 | }
92 | }
93 |
94 | // Filters an array of entries returning only the paths for the oversized images
95 | function filterOverSizedImgsInDropboxResult(entries){
96 |
97 | let imgs_paths = [];
98 | for(let i = 0; i < entries.length; i++) {
99 | entry = entries[i];
100 | if(entry.path_lower.search(/\.(gif|jpg|jpeg|tiff|png)$/i) == -1) continue;
101 | if(entry.size > LIMIT_SIZE ){
102 | imgs_paths.push(entry.path_lower);
103 | }
104 | }
105 |
106 | return imgs_paths;
107 | }
108 |
109 | // Downloads a thumbnail from Dropbox for a given path
110 | function downloadThumbnailAsync(path){
111 |
112 | let download_params = {
113 | path: path,
114 | format: FORMAT,
115 | size: SIZE,
116 | mode: MODE
117 | }
118 |
119 | return dbx.filesGetThumbnail(download_params);
120 | }
121 |
122 | // Uploads a file in Dropbox in a given path
123 | function uploadFileAsync(path,fileBinary){
124 |
125 | let upload_params = {
126 | //the picture will be added the _lowres suffix
127 | path : path.substr(0, path.lastIndexOf('.')) + '_lowres.jpg',
128 | contents : fileBinary,
129 | autorename: true,
130 | mute: true
131 | }
132 |
133 | return dbx.filesUpload(upload_params);
134 | }
135 |
136 | // Moves source images to a /highres folder within the original directory
137 | function moveFileAsync(path){
138 |
139 | let move_params = {
140 | from_path : path,
141 | //regex for the last / in the path
142 | to_path : path.replace(/\/(?!.*\/)/, "/highres/"),
143 | autorename : true
144 | };
145 |
146 | return dbx.filesMoveV2(move_params);
147 | }
148 |
--------------------------------------------------------------------------------
/azureservices.js:
--------------------------------------------------------------------------------
1 | require('dotenv').config({silent: true});
2 |
3 | const
4 | rp = require('request-promise'),
5 | config = require('./config'),
6 | store = require('./redismodel');
7 |
8 | //creates a new Person Group on Azure
9 | module.exports.createGroupAsync = ()=>{
10 | let options={
11 | method: 'PUT',
12 | url: 'https://'+config.AZURE_LOCATION+'.'+config.AZURE_FACE_ROUTE+'/persongroups/'+config.AZURE_PERSON_GROUP_ID,
13 | headers:{'Ocp-Apim-Subscription-Key':process.env.AZURE_COGNITIVE_KEY},
14 | json:true,
15 | body:{'name':config.AZURE_PERSON_GROUP_DESC}
16 | }
17 | return rp(options);
18 | }
19 |
20 | //Adds a person to the group and trains images
21 | module.exports.addPersonToPersonGroupAsync = async (displayName,facePaths) =>{
22 | //Construct a basic request options object used across calls with Face API
23 | let options = {};
24 | options.headers = {'Ocp-Apim-Subscription-Key':process.env.AZURE_COGNITIVE_KEY};
25 | options.json = true;
26 | options.method = 'POST';
27 |
28 | //First, try to create a person and add it to the Person Group.
29 | //this will give us back a personID
30 | let personId;
31 | let personGroupId = config.AZURE_PERSON_GROUP_ID;
32 |
33 | try{
34 |
35 | displayName = displayName.toLowerCase();
36 |
37 | options.url = 'https://'+config.AZURE_LOCATION+'.'+config.AZURE_FACE_ROUTE+'/persongroups/'+personGroupId+'/persons';
38 | options.body = {"name":displayName};
39 |
40 | let result = await rp(options);
41 |
42 | //If person added to the group a PersonID is created
43 | personId = result.personId;
44 |
45 | }catch(error){
46 | throw(new Error("Error adding "+displayName+" Message:"+error.message));
47 | }
48 |
49 | //Now try to add the faces for that person
50 | options.url = 'https://'+config.AZURE_LOCATION+'.'+config.AZURE_FACE_ROUTE+'/persongroups/'+personGroupId+'/persons/'+personId+'/persistedFaces';
51 | let addedFacesCount=0;
52 |
53 | for(let i = 0; i < facePaths.length; i++){
54 | try{
55 | options.body = {'url':facePaths[i]};
56 | await rp(options);
57 | addedFacesCount++;
58 | }catch(error){
59 | console.log("Error: Failed to add face for URL:"+facePaths[i]+"\n"+error.message);
60 | //ignore errors and continue with the other pictures
61 | }
62 | }
63 |
64 | if(addedFacesCount == 0) throw(new Error("Couldn't add any of the faces"));
65 |
66 | //Train the model
67 | try{
68 | options.url = 'https://'+config.AZURE_LOCATION+'.'+config.AZURE_FACE_ROUTE+'/persongroups/'+personGroupId+'/train';
69 | options.body = null;
70 | await rp(options);
71 | }catch(error){
72 | throw(new Error("Error training model after adding user "+displayName+" Message:"+error.message));
73 | }
74 |
75 | //store the displayName for that personId
76 | try{
77 | await store.setAsync(store.PREFIX_PERSONID + personId, displayName);
78 | }catch(error){
79 | throw(new Error("Couldn't add "+displayName+" to local store. Message:"+error.message));
80 | }
81 |
82 | //A person has successfully been added and model has been trained
83 | console.log(displayName + " added with personID=" + personId);
84 |
85 | }
86 |
87 | /*
88 | Resolves with all the people from a personGroup on a picture
89 | The returned value is an array of personIds
90 | */
91 | module.exports.detectPersonsInPhotoAsync = async (photoURL) =>{
92 | try{
93 |
94 | let options = {
95 | method: 'POST',
96 | url: 'https://'+config.AZURE_LOCATION+'.'+config.AZURE_FACE_ROUTE+'/detect',
97 | headers:{'Ocp-Apim-Subscription-Key':process.env.AZURE_COGNITIVE_KEY},
98 | json:true,
99 | body:{'url':photoURL}
100 | }
101 |
102 | //Detect all the faces in the url
103 | let response = await rp(options);
104 |
105 | //put only the faceIds into a single array
106 | let faceIds = response.map(function (entry) {
107 | return entry.faceId;
108 | });
109 |
110 | //if no faces found on the picture return with an empty array
111 | if(!faceIds || faceIds.length == 0) return [];
112 |
113 | //per detect method limitation
114 | if(faceIds.length > 10) throw (new Error("More than 10 people in picture"));
115 |
116 | //Check the people those faces belong to in the personGroup
117 | options.url = 'https://'+config.AZURE_LOCATION+'.'+config.AZURE_FACE_ROUTE+'/identify',
118 | options.body = {
119 | "personGroupId":config.AZURE_PERSON_GROUP_ID,
120 | "faceIds":faceIds,
121 | "maxNumOfCandidatesReturned":1, //only one candidate per face
122 | "confidenceThreshold": 0.5
123 | }
124 |
125 | response = await rp(options);
126 |
127 | //retrieve all the persons identified in the picture as an array of personIds
128 | let personIds = [];
129 | for (let i=0; i < response.length; i++){
130 | if(response[i].candidates.length > 0){
131 | personIds.push(response[i].candidates[0].personId);
132 | }
133 | }
134 |
135 | return personIds;
136 |
137 | }catch(error){
138 | throw(new Error("Error detecting people in photo. "+error.message));
139 | }
140 | }
--------------------------------------------------------------------------------
/public/galleria/themes/fullscreen/galleria.fullscreen.min.css:
--------------------------------------------------------------------------------
1 | #galleria-loader{height:1px!important}body,html{background:#000}.galleria-theme-fullscreen{height:100%;overflow:hidden;position:fixed;top:0;left:0;width:100%;background:#000;-webkit-font-smoothing:antialiased}.galleria-theme-fullscreen img{-moz-user-select:none;-webkit-user-select:none;-o-user-select:none}.galleria-theme-fullscreen .galleria-stage{width:100%;height:100%;position:absolute}.galleria-theme-fullscreen .galleria-thumbnails-container{position:absolute;bottom:0;z-index:2;padding-top:16px;width:100%}.galleria-theme-fullscreen.videoplay .galleria-thumbnails-container{display:none!important}.galleria-theme-fullscreen.videoplay .galleria-image-nav{top:80px;bottom:80px;height:auto}.galleria-theme-fullscreen .galleria-thumbnails-tab{opacity:.7;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)";filter:alpha(opacity=70);position:absolute;left:50%;margin-left:-50px;top:0;height:16px;width:100px;background:url(up.gif) 50% 5px no-repeat #000;cursor:pointer;-moz-border-radius-topleft:4px;-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;-webkit-border-top-left-radius:4px}.galleria-theme-fullscreen.light .galleria-thumbnails-tab{background:url(up-neg.gif) 50% 50% no-repeat #fff;opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";filter:alpha(opacity=100)}.galleria-theme-fullscreen .galleria-thumbnails-tab:hover{opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";filter:alpha(opacity=100)}.galleria-theme-fullscreen .galleria-thumbnails-tab.open,.galleria-theme-fullscreen .galleria-thumbnails-tab.open:hover{background-image:url(down.gif);opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";filter:alpha(opacity=100)}.galleria-theme-fullscreen.light .galleria-thumbnails-tab.open,.galleria-theme-fullscreen.light .galleria-thumbnails-tab.open:hover{background-image:url(down-neg.gif)}.galleria-theme-fullscreen .galleria-thumbnails{background:#000;overflow:hidden}.galleria-theme-fullscreen .galleria-thumbnails-list{background:#000;padding-top:5px;padding-bottom:5px;overflow:hidden}.galleria-theme-fullscreen.light .galleria-thumbnails,.galleria-theme-fullscreen.light .galleria-thumbnails-list{background:#fff}.galleria-theme-fullscreen .galleria-thumbnails .galleria-image{width:80px;height:50px;float:left;cursor:pointer;margin-right:5px}.galleria-theme-fullscreen .galleria-thumbnails .galleria-image img{background:#000}.galleria-theme-fullscreen .galleria-thumbnails .active{cursor:default}.galleria-theme-fullscreen .galleria-carousel .galleria-thumbnails-list{border-left:30px solid #000;border-right:30px solid #000}.galleria-theme-fullscreen.light .galleria-carousel .galleria-thumbnails-list{border-color:#fff}.galleria-theme-fullscreen .galleria-image-nav{width:100%;height:100%;position:absolute;top:0;left:0}.galleria-theme-fullscreen .galleria-image-nav-left,.galleria-theme-fullscreen .galleria-image-nav-right{width:100px;right:0;top:0;bottom:0;background:url(r.gif) 50% 50% no-repeat;position:absolute;cursor:pointer;z-index:2;display:none}.galleria-theme-fullscreen.smallarrows .galleria-image-nav-right{background-image:url(r-neg.png)}.galleria-theme-fullscreen .galleria-image-nav-left{left:0;right:auto;background-image:url(l.gif)}.galleria-theme-fullscreen.smallarrows .galleria-image-nav-left{background-image:url(l-neg.png)}.galleria-theme-fullscreen .galleria-loader{width:30px;height:30px;background:url(loader.gif) 50% 50% no-repeat #fff;position:absolute;top:50%;left:50%;margin-top:-15px;margin-left:-15px;z-index:3}.galleria-theme-fullscreen .galleria-info{z-index:4;font:13px/1.4 helvetica,arial,sans-serif;color:#fff;position:absolute;top:0;width:100%;border-top:2px solid #000;display:none;text-align:center;padding:10px 0;background:rgba(0,0,0,.5);border-bottom:1px solid rgba(0,0,0,.1)}.galleria-theme-fullscreen.light .galleria-info{background:rgba(255,255,255,.5);color:#000}.galleria-theme-fullscreen .galleria-info-text{width:50%;margin:0 auto}.galleria-theme-fullscreen .galleria-info-title{font-weight:700;display:inline-block;margin-right:10px}.galleria-theme-fullscreen .galleria-info-description{display:inline-block}.galleria-theme-fullscreen .galleria-thumb-nav-left,.galleria-theme-fullscreen .galleria-thumb-nav-right{cursor:pointer;display:none;background:url(p.gif) 50% 50% no-repeat;position:absolute;left:5px;top:21px;bottom:5px;width:20px;z-index:3;opacity:.8;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";filter:alpha(opacity=80)}.galleria-theme-fullscreen.light .galleria-thumb-nav-left{background-image:url(p-neg.png)}.galleria-theme-fullscreen .galleria-thumb-nav-right{background-image:url(n.gif);left:auto;right:5px}.galleria-theme-fullscreen.light .galleria-thumb-nav-right{background-image:url(n-neg.png)}.galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-left,.galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-right{display:block}.galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-left:hover,.galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-right:hover{background-color:#222}.galleria-theme-fullscreen .galleria-thumb-nav-left.disabled,.galleria-theme-fullscreen .galleria-thumb-nav-left.disabled:hover,.galleria-theme-fullscreen .galleria-thumb-nav-right.disabled,.galleria-theme-fullscreen .galleria-thumb-nav-right.disabled:hover{opacity:.2;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";filter:alpha(opacity=20);cursor:default}.galleria-theme-fullscreen.light .galleria-carousel .galleria-thumb-nav-left:hover,.galleria-theme-fullscreen.light .galleria-carousel .galleria-thumb-nav-right:hover{background-color:#ddd}
--------------------------------------------------------------------------------
/public/galleria/themes/fullscreen/galleria.fullscreen.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Galleria Classic Theme 2017-02-27
3 | * http://galleria.io
4 | *
5 | * Copyright (c) 2010 - 2017 worse is better UG
6 | * Licensed 2017-02-27 under the MIT license
7 | * https://raw.github.com/worseisbetter/galleria/master/LICENSE
8 | *
9 | */
10 |
11 | (function($) {
12 |
13 | /*global jQuery, Galleria, window */
14 |
15 | Galleria.addTheme({
16 | name: 'fullscreen',
17 | version: '1.5.4',
18 | author: 'Galleria',
19 | css: 'galleria.fullscreen.css',
20 | // begin site script
21 | defaults: {
22 | transition: 'none',
23 | imageCrop: true,
24 | thumbCrop: 'height',
25 | easing: 'galleriaOut',
26 | trueFullscreen: false,
27 |
28 | // set this to false if you want to keep the thumbnails:
29 | _hideDock: Galleria.TOUCH ? false : true,
30 |
31 | // set this to true if you want to shrink the carousel when clicking a thumbnail:
32 | _closeOnClick: false
33 | },
34 | init: function(options) {
35 |
36 | Galleria.requires( 1.5, 'This version of Fullscreen theme requires Galleria version 1.5 or later');
37 |
38 | this.addElement('thumbnails-tab');
39 | this.appendChild('thumbnails-container', 'thumbnails-tab');
40 |
41 | var tab = this.$('thumbnails-tab'),
42 | loader = this.$('loader'),
43 | thumbs = this.$('thumbnails-container'),
44 | list = this.$('thumbnails-list'),
45 | infotext = this.$('info-text'),
46 | info = this.$('info'),
47 | OPEN = !options._hideDock,
48 | POS = 0;
49 |
50 | if (Galleria.IE) {
51 | this.addElement('iefix');
52 | this.appendChild('container', 'iefix');
53 | this.$('iefix').css({
54 | zIndex: 3,
55 | position: 'absolute',
56 | backgroundColor: this.hasVariation('light') ? '#fff' : '#000',
57 | opacity: 0.4,
58 | top: 0
59 | });
60 | }
61 |
62 | if ( options.thumbnails === false ) {
63 | thumbs.hide();
64 | }
65 |
66 | var fixCaption = this.proxy(function(img) {
67 |
68 | var w = img.width || $(img).width();
69 |
70 | if (!(img || w)) {
71 | return;
72 | }
73 | w = Math.min(w, $(window).width());
74 | infotext.width(w - 40);
75 | if (Galleria.IE && this.getOptions('showInfo')) {
76 | this.$('iefix').width(info.outerWidth()).height(info.outerHeight());
77 | }
78 | });
79 |
80 | this.bind('rescale', function() {
81 | POS = this.getStageHeight() - tab.height() - 2;
82 | thumbs.css('top', OPEN ? POS - list.outerHeight() + 2 : POS);
83 | var img = this.getActiveImage();
84 | if (img) {
85 | fixCaption(img);
86 | }
87 | });
88 |
89 | this.bind('loadstart', function(e) {
90 | if (!e.cached) {
91 | loader.show().fadeTo(100, 1);
92 | }
93 | $(e.thumbTarget).css('opacity', 1).parent().siblings().children().css('opacity', 0.6);
94 | });
95 |
96 | this.bind('loadfinish', function(e) {
97 | loader.fadeOut(300);
98 | this.$('info, iefix').toggle(this.hasInfo());
99 | });
100 |
101 | this.bind('image', function(e) {
102 | e.imageTarget && fixCaption(e.imageTarget);
103 | });
104 |
105 | this.bind('thumbnail', function(e) {
106 | $(e.thumbTarget).parent(':not(.active)').children().css('opacity', 0.6);
107 | $(e.thumbTarget).on('click:fast', function() {
108 | if (OPEN && options._closeOnClick) {
109 | tab.trigger('click:fast');
110 | }
111 | });
112 | });
113 |
114 | this.trigger('rescale');
115 |
116 | if ( !Galleria.TOUCH ) {
117 |
118 | this.addIdleState(thumbs, { opacity: 0 });
119 | this.addIdleState(this.get('info'), { opacity: 0 });
120 |
121 | this.$('image-nav-left, image-nav-right').css('opacity', 0.01).hover(function() {
122 | $(this).animate({opacity: 1}, 100);
123 | }, function() {
124 | $(this).animate({opacity: 0});
125 | }).show();
126 |
127 | }
128 |
129 | if (Galleria.IE) {
130 | this.addIdleState(this.get('iefix'), { opacity: 0 });
131 | }
132 |
133 | if (options._hideDock) {
134 | tab.on('click:fast', this.proxy(function() {
135 | tab.toggleClass('open', !OPEN);
136 | if (!OPEN) {
137 | thumbs.animate({
138 | top: POS - list.outerHeight() + 2
139 | }, 400, options.easing);
140 | } else {
141 | thumbs.animate({
142 | top: POS
143 | }, 400, options.easing);
144 | }
145 | OPEN = !OPEN;
146 | }));
147 | } else {
148 | this.bind('thumbnail', function() {
149 | thumbs.css('top', POS - list.outerHeight() + 2);
150 | });
151 | tab.css('visibility', 'hidden');
152 | }
153 |
154 | this.$('thumbnails').children().hover(function() {
155 | $(this).not('.active').children().stop().fadeTo(100, 1);
156 | }, function() {
157 | $(this).not('.active').children().stop().fadeTo(400, 0.6);
158 | });
159 |
160 | this.enterFullscreen();
161 | this.attachKeyboard({
162 | escape: function(e) {
163 | return false;
164 | },
165 | up: function(e) {
166 | if (!OPEN) {
167 | tab.trigger('click:fast');
168 | }
169 | e.preventDefault();
170 | },
171 | down: function(e) {
172 | if (OPEN) {
173 | tab.trigger('click:fast');
174 | }
175 | e.preventDefault();
176 | }
177 | });
178 | }
179 | // end site script
180 | });
181 |
182 | }(jQuery));
183 |
--------------------------------------------------------------------------------
/public/galleria/themes/classic/galleria.classic.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Galleria Classic Theme 2017-02-13
3 | * http://galleria.io
4 | *
5 | * Copyright (c) 2010 - 2017 worse is better UG
6 | * Licensed under the MIT license
7 | * https://raw.github.com/worseisbetter/galleria/master/LICENSE
8 | *
9 | */
10 |
11 | #galleria-loader{height:1px!important}
12 |
13 | .galleria-theme-classic {
14 | position: relative;
15 | overflow: hidden;
16 | background: #000;
17 | }
18 | .galleria-theme-classic img {
19 | -moz-user-select: none;
20 | -webkit-user-select: none;
21 | -o-user-select: none;
22 | }
23 | .galleria-theme-classic .galleria-stage {
24 | position: absolute;
25 | top: 10px;
26 | bottom: 60px;
27 | left: 10px;
28 | right: 10px;
29 | overflow:hidden;
30 | }
31 | .galleria-theme-classic .galleria-thumbnails-container {
32 | height: 50px;
33 | bottom: 0;
34 | position: absolute;
35 | left: 10px;
36 | right: 10px;
37 | z-index: 2;
38 | }
39 | .galleria-theme-classic .galleria-carousel .galleria-thumbnails-list {
40 | margin-left: 30px;
41 | margin-right: 30px;
42 | }
43 | .galleria-theme-classic .galleria-thumbnails .galleria-image {
44 | height: 40px;
45 | width: 60px;
46 | background: #000;
47 | margin: 0 5px 0 0;
48 | border: 1px solid #000;
49 | float: left;
50 | cursor: pointer;
51 | }
52 | .galleria-theme-classic .galleria-counter {
53 | position: absolute;
54 | bottom: 10px;
55 | left: 10px;
56 | text-align: right;
57 | color: #fff;
58 | font: normal 11px/1 arial,sans-serif;
59 | z-index: 1;
60 | }
61 | .galleria-theme-classic .galleria-loader {
62 | background: #000;
63 | width: 20px;
64 | height: 20px;
65 | position: absolute;
66 | top: 10px;
67 | right: 10px;
68 | z-index: 2;
69 | display: none;
70 | background: url(classic-loader.gif) no-repeat 2px 2px;
71 | }
72 | .galleria-theme-classic .galleria-info {
73 | width: 50%;
74 | top: 15px;
75 | left: 15px;
76 | z-index: 2;
77 | position: absolute;
78 | }
79 | .galleria-theme-classic .galleria-info-text {
80 | background-color: #000;
81 | padding: 12px;
82 | display: none;
83 | /* IE7 */ zoom:1;
84 | }
85 | .galleria-theme-classic .galleria-info-title {
86 | font: bold 12px/1.1 arial,sans-serif;
87 | margin: 0;
88 | color: #fff;
89 | margin-bottom: 7px;
90 | }
91 | .galleria-theme-classic .galleria-info-description {
92 | font: italic 12px/1.4 georgia,serif;
93 | margin: 0;
94 | color: #bbb;
95 | }
96 | .galleria-theme-classic .galleria-info-close {
97 | width: 9px;
98 | height: 9px;
99 | position: absolute;
100 | top: 5px;
101 | right: 5px;
102 | background-position: -753px -11px;
103 | opacity: .5;
104 | filter: alpha(opacity=50);
105 | cursor: pointer;
106 | display: none;
107 | }
108 | .galleria-theme-classic .notouch .galleria-info-close:hover{
109 | opacity:1;
110 | filter: alpha(opacity=100);
111 | }
112 | .galleria-theme-classic .touch .galleria-info-close:active{
113 | opacity:1;
114 | filter: alpha(opacity=100);
115 | }
116 | .galleria-theme-classic .galleria-info-link {
117 | background-position: -669px -5px;
118 | opacity: .7;
119 | filter: alpha(opacity=70);
120 | position: absolute;
121 | width: 20px;
122 | height: 20px;
123 | cursor: pointer;
124 | background-color: #000;
125 | }
126 | .galleria-theme-classic.notouch .galleria-info-link:hover {
127 | opacity: 1;
128 | filter: alpha(opacity=100);
129 | }
130 | .galleria-theme-classic.touch .galleria-info-link:active {
131 | opacity: 1;
132 | filter: alpha(opacity=100);
133 | }
134 | .galleria-theme-classic .galleria-image-nav {
135 | position: absolute;
136 | top: 50%;
137 | margin-top: -62px;
138 | width: 100%;
139 | height: 62px;
140 | left: 0;
141 | }
142 | .galleria-theme-classic .galleria-image-nav-left,
143 | .galleria-theme-classic .galleria-image-nav-right {
144 | opacity: .3;
145 | filter: alpha(opacity=30);
146 | cursor: pointer;
147 | width: 62px;
148 | height: 124px;
149 | position: absolute;
150 | left: 10px;
151 | z-index: 2;
152 | background-position: 0 46px;
153 | }
154 | .galleria-theme-classic .galleria-image-nav-right {
155 | left: auto;
156 | right: 10px;
157 | background-position: -254px 46px;
158 | z-index: 2;
159 | }
160 | .galleria-theme-classic.notouch .galleria-image-nav-left:hover,
161 | .galleria-theme-classic.notouch .galleria-image-nav-right:hover {
162 | opacity: 1;
163 | filter: alpha(opacity=100);
164 | }
165 | .galleria-theme-classic.touch .galleria-image-nav-left:active,
166 | .galleria-theme-classic.touch .galleria-image-nav-right:active {
167 | opacity: 1;
168 | filter: alpha(opacity=100);
169 | }
170 | .galleria-theme-classic .galleria-thumb-nav-left,
171 | .galleria-theme-classic .galleria-thumb-nav-right {
172 | cursor: pointer;
173 | display: none;
174 | background-position: -495px 5px;
175 | position: absolute;
176 | left: 0;
177 | top: 0;
178 | height: 40px;
179 | width: 23px;
180 | z-index: 3;
181 | opacity: .8;
182 | filter: alpha(opacity=80);
183 | }
184 | .galleria-theme-classic .galleria-thumb-nav-right {
185 | background-position: -578px 5px;
186 | border-right: none;
187 | right: 0;
188 | left: auto;
189 | }
190 | .galleria-theme-classic .galleria-thumbnails-container .disabled {
191 | opacity: .2;
192 | filter: alpha(opacity=20);
193 | cursor: default;
194 | }
195 | .galleria-theme-classic.notouch .galleria-thumb-nav-left:hover,
196 | .galleria-theme-classic.notouch .galleria-thumb-nav-right:hover {
197 | opacity: 1;
198 | filter: alpha(opacity=100);
199 | background-color: #111;
200 | }
201 | .galleria-theme-classic.touch .galleria-thumb-nav-left:active,
202 | .galleria-theme-classic.touch .galleria-thumb-nav-right:active {
203 | opacity: 1;
204 | filter: alpha(opacity=100);
205 | background-color: #111;
206 | }
207 | .galleria-theme-classic.notouch .galleria-thumbnails-container .disabled:hover {
208 | opacity: .2;
209 | filter: alpha(opacity=20);
210 | background-color: transparent;
211 | }
212 |
213 | .galleria-theme-classic .galleria-carousel .galleria-thumb-nav-left,
214 | .galleria-theme-classic .galleria-carousel .galleria-thumb-nav-right {
215 | display: block;
216 | }
217 | .galleria-theme-classic .galleria-thumb-nav-left,
218 | .galleria-theme-classic .galleria-thumb-nav-right,
219 | .galleria-theme-classic .galleria-info-link,
220 | .galleria-theme-classic .galleria-info-close,
221 | .galleria-theme-classic .galleria-image-nav-left,
222 | .galleria-theme-classic .galleria-image-nav-right {
223 | background-image: url(classic-map.png);
224 | background-repeat: no-repeat;
225 | }
226 | .galleria-theme-classic.galleria-container.videoplay .galleria-info,
227 | .galleria-theme-classic.galleria-container.videoplay .galleria-counter{ display:none!important; }
228 |
--------------------------------------------------------------------------------
/public/galleria/plugins/history/history-demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Galleria History Plugin
6 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
Galleria History Plugin
35 |
Demonstrating a basic history example. Supports most browsers, including FF 3.0+ and IE 7+
36 |
37 |
38 |
39 |
86 |
87 |
Made by Galleria.
88 |
89 |
90 |
99 |
100 |
--------------------------------------------------------------------------------
/public/galleria/themes/fullscreen/fullscreen-demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Galleria Fullscreen Theme Demo
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
18 |
19 |
20 |
21 |
95 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/public/galleria/themes/fullscreen/fullscreen-demo-cdn.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Galleria Fullscreen Theme Demo
7 |
8 |
11 |
12 |
13 |
14 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/public/galleria/themes/fullscreen/galleria.fullscreen.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Galleria Classic Theme 2017-02-27
3 | * http://galleria.io
4 | *
5 | * Copyright (c) 2010 - 2017 worse is better UG
6 | * Licensed 2017-02-27 under the MIT license
7 | * https://raw.github.com/worseisbetter/galleria/master/LICENSE
8 | *
9 | */
10 |
11 | #galleria-loader{height:1px!important}
12 |
13 | html,
14 | body { background: #000 }
15 | .galleria-theme-fullscreen {
16 | height: 100%;
17 | overflow: hidden;
18 | position: fixed;
19 | top: 0;
20 | left: 0;
21 | width: 100%;
22 | background: #000;
23 | -webkit-font-smoothing: antialiased;
24 | }
25 | .galleria-theme-fullscreen img {
26 | -moz-user-select: none;
27 | -webkit-user-select: none;
28 | -o-user-select: none;
29 | }
30 | .galleria-theme-fullscreen .galleria-stage {
31 | width: 100%;
32 | height: 100%;
33 | position: absolute;
34 | }
35 | .galleria-theme-fullscreen .galleria-thumbnails-container {
36 | position: absolute;
37 | bottom: 0;
38 | z-index: 2;
39 | padding-top: 16px;
40 | width: 100%;
41 | }
42 | .galleria-theme-fullscreen.videoplay .galleria-thumbnails-container { display:none!important; }
43 | .galleria-theme-fullscreen.videoplay .galleria-image-nav { top:80px; bottom:80px; height:auto; }
44 |
45 | .galleria-theme-fullscreen .galleria-thumbnails-tab {
46 | opacity: .7;
47 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=70)";
48 | filter: alpha(opacity=70);
49 | position: absolute;
50 | left: 50%;
51 | margin-left: -50px;
52 | top: 0;
53 | height: 16px;
54 | width: 100px;
55 | background: #000 url(up.gif) no-repeat 50% 5px;
56 | cursor: pointer;
57 | -moz-border-radius-topleft: 4px;
58 | -moz-border-radius-topright: 4px;
59 | -webkit-border-top-right-radius: 4px;
60 | -webkit-border-top-left-radius: 4px;
61 | }
62 | .galleria-theme-fullscreen.light .galleria-thumbnails-tab {
63 | background:#fff url(up-neg.gif) no-repeat 50% 50%;
64 | opacity: 1;
65 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
66 | filter: alpha(opacity=100);
67 | }
68 | .galleria-theme-fullscreen .galleria-thumbnails-tab:hover {
69 | opacity: 1;
70 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
71 | filter: alpha(opacity=100);
72 | }
73 | .galleria-theme-fullscreen .galleria-thumbnails-tab.open,
74 | .galleria-theme-fullscreen .galleria-thumbnails-tab.open:hover {
75 | background-image: url(down.gif);
76 | opacity: 1;
77 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
78 | filter: alpha(opacity=100);
79 | }
80 | .galleria-theme-fullscreen.light .galleria-thumbnails-tab.open,
81 | .galleria-theme-fullscreen.light .galleria-thumbnails-tab.open:hover {
82 | background-image: url(down-neg.gif);
83 | }
84 | .galleria-theme-fullscreen .galleria-thumbnails {
85 | background: #000;
86 | overflow: hidden;
87 | }
88 | .galleria-theme-fullscreen .galleria-thumbnails-list {
89 | background: #000;
90 | padding-top: 5px;
91 | padding-bottom: 5px;
92 | overflow: hidden;
93 | }
94 | .galleria-theme-fullscreen.light .galleria-thumbnails,
95 | .galleria-theme-fullscreen.light .galleria-thumbnails-list {
96 | background:#fff;
97 | }
98 | .galleria-theme-fullscreen .galleria-thumbnails .galleria-image {
99 | width: 80px;
100 | height: 50px;
101 | float: left;
102 | cursor: pointer;
103 | margin-right: 5px;
104 | }
105 | .galleria-theme-fullscreen .galleria-thumbnails .galleria-image img { background: #000 }
106 | .galleria-theme-fullscreen .galleria-thumbnails .active { cursor: default }
107 | .galleria-theme-fullscreen .galleria-carousel .galleria-thumbnails-list {
108 | border-left: 30px solid #000;
109 | border-right: 30px solid #000;
110 | }
111 | .galleria-theme-fullscreen.light .galleria-carousel .galleria-thumbnails-list {
112 | border-color: #fff;
113 | }
114 | .galleria-theme-fullscreen .galleria-image-nav {
115 | width: 100%;
116 | height: 100%;
117 | position: absolute;
118 | top: 0;
119 | left: 0;
120 | }
121 | .galleria-theme-fullscreen .galleria-image-nav-right,
122 | .galleria-theme-fullscreen .galleria-image-nav-left {
123 | width: 100px;
124 | right: 0;
125 | top: 0;
126 | bottom: 0;
127 | background: url(r.gif) no-repeat 50% 50%;
128 | position: absolute;
129 | cursor: pointer;
130 | z-index: 2;
131 | display: none;
132 | }
133 | .galleria-theme-fullscreen.smallarrows .galleria-image-nav-right {
134 | background-image: url(r-neg.png);
135 | }
136 | .galleria-theme-fullscreen .galleria-image-nav-left {
137 | left: 0;
138 | right: auto;
139 | background-image: url(l.gif);
140 | }
141 | .galleria-theme-fullscreen.smallarrows .galleria-image-nav-left {
142 | background-image: url(l-neg.png);
143 | }
144 | .galleria-theme-fullscreen .galleria-loader {
145 | width: 30px;
146 | height: 30px;
147 | background: #fff url(loader.gif) no-repeat 50% 50%;
148 | position: absolute;
149 | top: 50%;
150 | left: 50%;
151 | margin-top: -15px;
152 | margin-left: -15px;
153 | z-index: 3;
154 | }
155 | .galleria-theme-fullscreen .galleria-info {
156 | z-index: 4;
157 | font: 13px/1.4 helvetica,arial,sans-serif;
158 | color: #fff;
159 | position: absolute;
160 | top: 0;
161 | width: 100%;
162 | border-top: 2px solid #000;
163 | display: none;
164 | text-align: center;
165 | padding: 10px 0;
166 | background: rgba(0,0,0,.5);
167 | border-bottom:1px solid rgba(0,0,0,.1);
168 | }
169 | .galleria-theme-fullscreen.light .galleria-info{background:rgba(255,255,255,.5);color:#000;}
170 | .galleria-theme-fullscreen .galleria-info-text {
171 | width: 50%;
172 | margin: 0 auto;
173 | }
174 | .galleria-theme-fullscreen .galleria-info-title { font-weight: bold; display: inline-block; margin-right:10px; }
175 | .galleria-theme-fullscreen .galleria-info-description { display:inline-block; }
176 | .galleria-theme-fullscreen .galleria-thumb-nav-left,
177 | .galleria-theme-fullscreen .galleria-thumb-nav-right {
178 | cursor: pointer;
179 | display: none;
180 | background: url(p.gif) no-repeat 50% 50%;
181 | position: absolute;
182 | left: 5px;
183 | top: 21px;
184 | bottom: 5px;
185 | width: 20px;
186 | z-index: 3;
187 | opacity: .8;
188 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";
189 | filter: alpha(opacity=80);
190 | }
191 | .galleria-theme-fullscreen.light .galleria-thumb-nav-left{
192 | background-image: url(p-neg.png);
193 | }
194 | .galleria-theme-fullscreen .galleria-thumb-nav-right {
195 | background-image: url(n.gif);
196 | left: auto;
197 | right: 5px;
198 | }
199 | .galleria-theme-fullscreen.light .galleria-thumb-nav-right{
200 | background-image: url(n-neg.png);
201 | }
202 | .galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-left,
203 | .galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-right { display: block }
204 | .galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-left:hover,
205 | .galleria-theme-fullscreen .galleria-carousel .galleria-thumb-nav-right:hover { background-color: #222 }
206 | .galleria-theme-fullscreen .galleria-thumb-nav-left.disabled,
207 | .galleria-theme-fullscreen .galleria-thumb-nav-right.disabled,
208 | .galleria-theme-fullscreen .galleria-thumb-nav-left.disabled:hover,
209 | .galleria-theme-fullscreen .galleria-thumb-nav-right.disabled:hover {
210 | opacity: .2;
211 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";
212 | filter: alpha(opacity=20);
213 | cursor: default;
214 | }
215 | .galleria-theme-fullscreen.light .galleria-carousel .galleria-thumb-nav-left:hover,
216 | .galleria-theme-fullscreen.light .galleria-carousel .galleria-thumb-nav-right:hover { background-color: #ddd }
217 |
218 |
--------------------------------------------------------------------------------
/public/galleria/themes/classic/classic-demo-cdn.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Galleria Classic Theme
6 |
21 |
22 |
23 |
24 |
Galleria Classic Theme
25 |
Demonstrating a basic gallery example.
26 |
27 |
28 |
29 |
110 |
Made by Galleria.
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
124 |
125 |
--------------------------------------------------------------------------------
/public/galleria/themes/classic/classic-demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Galleria Classic Theme
6 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
Galleria Classic Theme
33 |
Demonstrating a basic gallery example.
34 |
35 |
36 |
37 |
118 |
Made by Galleria.
119 |
120 |
121 |
130 |
131 |
--------------------------------------------------------------------------------
/public/galleria/themes/classic/classic-demo-cdn (SFConflict me@a1b0n.com 2017-02-12-23-35-56).html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Galleria Classic Theme
6 |
21 |
22 |
23 |
24 |
Galleria Classic Theme
25 |
Demonstrating a basic gallery example.
26 |
27 |
28 |
29 |
110 |
Made by Galleria.
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
124 |
125 |
--------------------------------------------------------------------------------
/dbxservices.js:
--------------------------------------------------------------------------------
1 | //load environment variables
2 | require('dotenv').config({silent: true});
3 | //Dropbox SDK requires this line
4 | require('isomorphic-fetch');
5 |
6 | const
7 | Dropbox = require('dropbox').Dropbox,
8 | template = require ('./property_group_template'),
9 | store = require('./redismodel');
10 |
11 | var dbx = new Dropbox({ accessToken: process.env.DBX_TOKEN});
12 |
13 | /*
14 | Returns an array with temporary links from a folder path
15 | Only links for image files are returned.
16 | Resolves with a esponse in the following format:
17 | {
18 | temporaryLinks: [link1,link2,link3],
19 | paths:[path1,path2,path3],
20 | cursor: cursor,
21 | has_more: True/False
22 | }
23 | */
24 | module.exports.getTemporaryLinksForFolderAsync = async (folder_path,limit,lastModified)=>{
25 | try{
26 |
27 | let params = {};
28 | params.path = folder_path;
29 | if(limit){params.limit = limit;}
30 |
31 | let result = await dbx.filesListFolder(params);
32 | let returnValue = await filterDropboxResultAsync(result,lastModified);
33 |
34 | return returnValue;
35 |
36 | }catch(error){
37 | throw(new Error("couldnt get temporary links. " + getDbxErrorMsg(error)));
38 | }
39 | }
40 |
41 | //Same as getTemporaryLinksForFolderAsync but takes a cursor instead of path
42 | //Resolves with the same values
43 | module.exports.getTemporaryLinksForCursorAsync = async (cursor,lastModified) =>{
44 | try{
45 |
46 | let result = await dbx.filesListFolderContinue({"cursor":cursor});
47 | let returnValue = await filterDropboxResultAsync(result,lastModified);
48 |
49 | return returnValue;
50 |
51 | }catch(error){
52 | throw(new Error("couldnt get temporary links. " + getDbxErrorMsg(error)));
53 | }
54 | }
55 |
56 | //Internal function that filters a Dropbox result
57 | async function filterDropboxResultAsync(result,lastModified){
58 | try{
59 |
60 | let returnValue = {};
61 |
62 | //Get cursor to fetch more pictures
63 | returnValue.cursor = result.cursor;
64 | returnValue.has_more = result.has_more;
65 |
66 | let imgPaths = [];
67 | for(let i = 0; i < result.entries.length; i++) {
68 | entry = result.entries[i];
69 | if(lastModified && entry.server_modified < lastModified) continue;
70 | if(entry.path_lower.search(/\.(gif|jpg|jpeg|tiff|png)$/i) == -1) continue;
71 |
72 | imgPaths.push(entry.path_lower);
73 | }
74 |
75 | //Get a temporary link for each of those paths returned
76 | let temporaryLinks= await getTemporaryLinksForPathsAsync(imgPaths);
77 |
78 | returnValue.temporaryLinks= temporaryLinks;
79 | returnValue.imgPaths = imgPaths;
80 |
81 | return returnValue;
82 |
83 | }catch(error){
84 | throw(new Error("couldnt filter result. " + getDbxErrorMsg(error)));
85 | }
86 | }
87 |
88 | //Internal function to get an array with temp links from an array with paths
89 | async function getTemporaryLinksForPathsAsync(imgPaths){
90 | try{
91 |
92 | let promises = [];
93 |
94 | //Create a promise for each path and push it to an array of promises
95 | imgPaths.forEach((path_lower)=>{
96 | promises.push(dbx.filesGetTemporaryLink({"path":path_lower}));
97 | });
98 |
99 | //when all promises are fulfilled a result is built in an ordered fashion
100 | let result = await Promise.all(promises);
101 |
102 | //Construct a new array only with the link field of the result
103 | let temporaryLinks = result.map(function (entry) {
104 | return entry.link;
105 | });
106 |
107 | return temporaryLinks;
108 |
109 | }catch(error){
110 | throw(new Error("couldnt create temporary links. " + getDbxErrorMsg(error)));
111 | }
112 | }
113 | //makes the above function available outside of this file with same name
114 | module.exports.getTemporaryLinksForPathsAsync = getTemporaryLinksForPathsAsync;
115 |
116 | //Gets an error message from an error potentially comming from Dropbox
117 | function getDbxErrorMsg(error){
118 | if(typeof error.message == 'string'){
119 | return error.message;
120 | }
121 | else if(typeof error.error == 'string'){
122 | return error.error;
123 | }
124 | else if (typeof error.error.error_summary == 'string'){
125 | return error.error.error_summary;
126 | }else{
127 | return null;
128 | }
129 | }
130 |
131 | //Returns a Template Id from local storage or gets a new one and stores it
132 | module.exports.getTemplateIDAsync = async ()=>{
133 | try{
134 |
135 | let template_id = await store.getAsync("property_group_template_id");
136 | if (!template_id){
137 | let result = await dbx.filePropertiesTemplatesAddForUser(template.property_group_template);
138 | template_id = result.template_id;
139 | await store.setAsync("property_group_template_id",template_id);
140 | }
141 | return template_id;
142 |
143 | }catch(error){
144 | throw(new Error("couldn't get templateID. " + getDbxErrorMsg(error)));
145 | }
146 | }
147 |
148 | //Adds a set of properties to a specific file, if it exists overwrites it
149 | module.exports.addPropertiesAsync = async (templateId,path,names)=>{
150 |
151 | let property_group_object = buildPropertyGroup(names,path,templateId);
152 |
153 | try{
154 |
155 | let result = await dbx.filePropertiesPropertiesAdd(property_group_object);
156 |
157 | }catch(error){
158 |
159 | let tag = null;
160 |
161 | //if error from Dropbox, get the .tag field
162 | if (typeof error.error.error['.tag'] !== 'undefined'){
163 | tag = error.error.error['.tag'];
164 | }
165 |
166 | //If the property exists, overwrite it
167 | if(tag == "property_group_already_exists"){
168 | try{
169 |
170 | console.log("property exist, overwriting");
171 | await dbx.filePropertiesPropertiesOverwrite(property_group_object);
172 |
173 | }catch(error){
174 | throw(new Error("Error overwriting properties. " + getDbxErrorMsg(error)))
175 | }
176 | }else{
177 | throw(new Error("Error adding properties to user. " + getDbxErrorMsg(error)));
178 | }
179 | }
180 | }
181 |
182 | //returns a property group as a json object
183 | function buildPropertyGroup(names,path,templateId){
184 | //construct array with persons found according to template
185 | let fields = [];
186 | for(let i = 0; i < names.length; i++){
187 | fields.push({'name': 'person' + (i), 'value':names[i]})
188 | }
189 |
190 | return {
191 | "path": path,
192 | "property_groups": [{
193 | "template_id": templateId,
194 | "fields": fields
195 | }]
196 | }
197 | }
198 |
199 | /*
200 | Searchs for a property using a name
201 | Resolves with an object with the following structure
202 | {
203 | paths: [path1,path2,path3],
204 | cursor: cursor
205 | }
206 | an empty cursor means there are no more results
207 | */
208 | module.exports.searchPropertiesAsync = async (name)=>{
209 | try{
210 |
211 | //build the query iterating on each personId and possible value
212 | //E.g. two personIs will create 10 queries
213 | let query= {};
214 | query.template_filter = 'filter_none';
215 | query.queries = [];
216 | let max = template.property_group_template.fields.length;
217 |
218 | for(let i = 0; i < max; i++){
219 | let single_query = {
220 | "query": name,
221 | "mode": {".tag": "field_name","field_name": "person" + i},
222 | "logical_operator": "or_operator"
223 | }
224 | query.queries.push(single_query);
225 | }
226 |
227 | let result = await dbx.filePropertiesPropertiesSearch(query);
228 | let returnValue = filterPropertySearchResult(result);
229 | return returnValue;
230 |
231 | }catch(error){
232 | throw(new Error("Error searching properties. " + getDbxErrorMsg(error)));
233 | }
234 | }
235 |
236 | //Same as searchPropertiesAsync but continues the search with a cursor
237 | module.exports.searchPropertiesFromCursorAsync = async (cursor) =>{
238 | try{
239 |
240 | let result = await dbx.filePropertiesPropertiesSearchContinue({"cursor":cursor});
241 | let returnValue = filterPropertySearchResult(result);
242 | return returnValue;
243 |
244 | }catch(error){
245 | throw(new Error("Error searching properties. " + getDbxErrorMsg(error)));
246 | }
247 | }
248 |
249 | // Fapi.tsilters results from a property search
250 | function filterPropertySearchResult(result){
251 |
252 | let returnValue = {};
253 | returnValue.cursor = (typeof result.cursor !== 'undefined')?result.cursor:'';
254 |
255 | //Construct a new array only with the path field if file is not deleted
256 | let paths = [];
257 |
258 | for(let i = 0; i < result.matches.length; i++){
259 | let entry = result.matches[i];
260 | if(!entry.is_deleted){
261 | paths.push(entry.path);
262 | }
263 | }
264 |
265 | returnValue.paths= paths;
266 | return returnValue;
267 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2018 Dropbox, Inc.
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
15 |
16 | Third party code used by A Dropbox image gallery with tags are:
17 |
18 | - Galleria 1.5.7, located at public/galleria, is licensed as follows:
19 |
20 | Copyright (c) 2010 - 2017 worse is better UG
21 | Licensed under the MIT License.
22 |
23 |
24 | Apache License
25 |
26 | Version 2.0, January 2004
27 |
28 | http://www.apache.org/licenses/
29 |
30 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
31 |
32 | 1. Definitions.
33 |
34 | "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
35 |
36 | "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
37 |
38 | "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
39 |
40 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
41 |
42 | "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
43 |
44 | "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
45 |
46 | "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
47 |
48 | "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
49 |
50 | "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
51 |
52 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
53 |
54 | 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
55 |
56 | 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
57 |
58 | 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
59 |
60 | You must give any other recipients of the Work or Derivative Works a copy of this License; and
61 | You must cause any modified files to carry prominent notices stating that You changed the files; and
62 | You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
63 | If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
64 |
65 | You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
66 | 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
67 |
68 | 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
69 |
70 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
71 |
72 | 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
73 |
74 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
75 |
76 | END OF TERMS AND CONDITIONS
--------------------------------------------------------------------------------
/public/galleria/plugins/picasa/galleria.picasa.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Galleria Picasa Plugin 2016-09-03
3 | * http://galleria.io
4 | *
5 | * Copyright (c) 2010 - 2017 worse is better UG
6 | * Licensed under the MIT license
7 | * https://raw.github.com/worseisbetter/galleria/master/LICENSE
8 | *
9 | */
10 |
11 | (function($) {
12 |
13 | /*global jQuery, Galleria, window */
14 |
15 | Galleria.requires(1.25, 'The Picasa Plugin requires Galleria version 1.2.5 or later.');
16 |
17 | // The script path
18 | var PATH = Galleria.utils.getScriptPath();
19 |
20 | /**
21 |
22 | @class
23 | @constructor
24 |
25 | @example var picasa = new Galleria.Picasa();
26 |
27 | @author http://wib.io
28 |
29 | @requires jQuery
30 | @requires Galleria
31 |
32 | @returns Instance
33 | */
34 |
35 | Galleria.Picasa = function() {
36 |
37 | this.options = {
38 | max: 30, // photos to return
39 | imageSize: 'medium', // photo size ( thumb,small,medium,big,original ) or a number
40 | thumbSize: 'thumb', // thumbnail size ( thumb,small,medium,big,original ) or a number
41 | complete: function(){} // callback to be called inside the Galleria.prototype.load
42 | };
43 |
44 | };
45 |
46 | Galleria.Picasa.prototype = {
47 |
48 | // bring back the constructor reference
49 |
50 | constructor: Galleria.Picasa,
51 |
52 | /**
53 | Search for anything at Picasa
54 |
55 | @param {String} phrase The string to search for
56 | @param {Function} [callback] The callback to be called when the data is ready
57 |
58 | @returns Instance
59 | */
60 |
61 | search: function( phrase, callback ) {
62 | return this._call( 'search', 'all', {
63 | q: phrase
64 | }, callback );
65 | },
66 |
67 | /**
68 | Get a user's public photos
69 |
70 | @param {String} username The username to fetch photos from
71 | @param {Function} [callback] The callback to be called when the data is ready
72 |
73 | @returns Instance
74 | */
75 |
76 | user: function( username, callback ) {
77 | return this._call( 'user', 'user/' + username, callback );
78 | },
79 |
80 | /**
81 | Get photos from an album
82 |
83 | @param {String} username The username that owns the album
84 | @param {String} album The album ID
85 | @param {Function} [callback] The callback to be called when the data is ready
86 |
87 | @returns Instance
88 | */
89 |
90 | useralbum: function( username, album, callback ) {
91 | return this._call( 'useralbum', 'user/' + username + '/album/' + album, callback );
92 | },
93 |
94 | /**
95 | Set picasa options
96 |
97 | @param {Object} options The options object to blend
98 |
99 | @returns Instance
100 | */
101 |
102 | setOptions: function( options ) {
103 | $.extend(this.options, options);
104 | return this;
105 | },
106 |
107 |
108 | // call Picasa
109 |
110 | _call: function( type, url, params, callback ) {
111 |
112 | url = 'https://picasaweb.google.com/data/feed/api/' + url + '?';
113 |
114 | if (typeof params == 'function') {
115 | callback = params;
116 | params = {};
117 | }
118 |
119 | var self = this;
120 |
121 | params = $.extend({
122 | 'kind': 'photo',
123 | 'access': 'public',
124 | 'max-results': this.options.max,
125 | 'thumbsize': this._getSizes().join(','),
126 | 'alt': 'json-in-script',
127 | 'callback': '?'
128 | }, params );
129 |
130 | $.each(params, function( key, value ) {
131 | url += '&' + key + '=' + value;
132 | });
133 |
134 | // since Picasa throws 404 when the call is malformed, we must set a timeout here:
135 |
136 | var data = false;
137 |
138 | Galleria.utils.wait({
139 | until: function() {
140 | return data;
141 | },
142 | success: function() {
143 | self._parse.call( self, data.feed.entry, callback );
144 | },
145 | error: function() {
146 | var msg = '';
147 | if ( type == 'user' ) {
148 | msg = 'user not found.';
149 | } else if ( type == 'useralbum' ) {
150 | msg = 'album or user not found.';
151 | }
152 | Galleria.raise('Picasa request failed' + (msg ? ': ' + msg : '.'));
153 | },
154 | timeout: 5000
155 | });
156 |
157 | $.getJSON( url, function( result ) {
158 | data = result;
159 | });
160 |
161 | return self;
162 | },
163 |
164 |
165 | // parse image sizes and return an array of three
166 |
167 | _getSizes: function() {
168 |
169 | var self = this,
170 | norm = {
171 | small: '72c',
172 | thumb: '104u',
173 | medium: '640u',
174 | big: '1024u',
175 | original: '1600u'
176 | },
177 | op = self.options,
178 | t = {},
179 | n,
180 | sz = [32,48,64,72,94,104,110,128,144,150,160,200,220,288,320,400,512,576,640,720,800,912,1024,1152,1280,1440,1600];
181 |
182 | $(['thumbSize', 'imageSize']).each(function() {
183 | if( op[this] in norm ) {
184 | t[this] = norm[ op[this] ];
185 | } else {
186 | n = Galleria.utils.parseValue( op[this] );
187 | if (n > 1600) {
188 | n = 1600;
189 | } else {
190 | $.each( sz, function(i) {
191 | if ( n < this ) {
192 | n = sz[i-1];
193 | return false;
194 | }
195 | });
196 | }
197 | t[this] = n;
198 | }
199 | });
200 |
201 | return [ t.thumbSize, t.imageSize, '1280u'];
202 |
203 | },
204 |
205 |
206 | // parse the result and call the callback with the galleria-ready data array
207 |
208 | _parse: function( data, callback ) {
209 |
210 | var self = this,
211 | gallery = [],
212 | img;
213 |
214 | $.each( data, function() {
215 |
216 | img = this.media$group.media$thumbnail;
217 |
218 | gallery.push({
219 | thumb: img[0].url,
220 | image: img[1].url,
221 | big: img[2].url,
222 | title: this.summary.$t
223 | });
224 | });
225 |
226 | callback.call( this, gallery );
227 | }
228 | };
229 |
230 |
231 | /**
232 | Galleria modifications
233 | We fake-extend the load prototype to make Picasa integration as simple as possible
234 | */
235 |
236 |
237 | // save the old prototype in a local variable
238 |
239 | var load = Galleria.prototype.load;
240 |
241 |
242 | // fake-extend the load prototype using the picasa data
243 |
244 | Galleria.prototype.load = function() {
245 |
246 | // pass if no data is provided or picasa option not found
247 | if ( arguments.length || typeof this._options.picasa !== 'string' ) {
248 | load.apply( this, Galleria.utils.array( arguments ) );
249 | return;
250 | }
251 |
252 | // define some local vars
253 | var self = this,
254 | args = Galleria.utils.array( arguments ),
255 | picasa = this._options.picasa.split(':'),
256 | p,
257 | opts = $.extend({}, self._options.picasaOptions),
258 | loader = typeof opts.loader !== 'undefined' ?
259 | opts.loader : $('').css({
260 | width: 48,
261 | height: 48,
262 | opacity: 0.7,
263 | background:'#000 url('+PATH+'loader.gif) no-repeat 50% 50%'
264 | });
265 |
266 | if ( picasa.length ) {
267 |
268 | // validate the method
269 | if ( typeof Galleria.Picasa.prototype[ picasa[0] ] !== 'function' ) {
270 | Galleria.raise( picasa[0] + ' method not found in Picasa plugin' );
271 | return load.apply( this, args );
272 | }
273 |
274 | // validate the argument
275 | if ( !picasa[1] ) {
276 | Galleria.raise( 'No picasa argument found' );
277 | return load.apply( this, args );
278 | }
279 |
280 | // apply the preloader
281 | window.setTimeout(function() {
282 | self.$( 'target' ).append( loader );
283 | },100);
284 |
285 | // create the instance
286 | p = new Galleria.Picasa();
287 |
288 | // apply Flickr options
289 | if ( typeof self._options.picasaOptions === 'object' ) {
290 | p.setOptions( self._options.picasaOptions );
291 | }
292 |
293 | // call the picasa method and trigger the DATA event
294 | var arg = [];
295 | if ( picasa[0] == 'useralbum' ) {
296 | arg = picasa[1].split('/');
297 | if (arg.length != 2) {
298 | Galleria.raise( 'Picasa useralbum not correctly formatted (should be [user]/[album])');
299 | return;
300 | }
301 | } else {
302 | arg.push( picasa[1] );
303 | }
304 |
305 | arg.push(function(data) {
306 | self._data = data;
307 | loader.remove();
308 | self.trigger( Galleria.DATA );
309 | p.options.complete.call(p, data);
310 | });
311 |
312 | p[ picasa[0] ].apply( p, arg );
313 |
314 | } else {
315 |
316 | // if flickr array not found, pass
317 | load.apply( this, args );
318 | }
319 | };
320 |
321 | }( jQuery ) );
--------------------------------------------------------------------------------
/public/galleria/plugins/flickr/galleria.flickr.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Galleria Flickr Plugin 2016-09-03
3 | * http://galleria.io
4 | *
5 | * Copyright (c) 2010 - 2017 worse is better UG
6 | * Licensed under the MIT license
7 | * https://raw.github.com/worseisbetter/galleria/master/LICENSE
8 | *
9 | */
10 |
11 | (function($) {
12 |
13 | /*global jQuery, Galleria, window */
14 |
15 | Galleria.requires(1.25, 'The Flickr Plugin requires Galleria version 1.2.5 or later.');
16 |
17 | // The script path
18 | var PATH = Galleria.utils.getScriptPath();
19 |
20 | /**
21 |
22 | @class
23 | @constructor
24 |
25 | @example var flickr = new Galleria.Flickr();
26 |
27 | @author http://galleria.io
28 |
29 | @requires jQuery
30 | @requires Galleria
31 |
32 | @param {String} [api_key] Flickr API key to be used, defaults to the Galleria key
33 |
34 | @returns Instance
35 | */
36 |
37 | Galleria.Flickr = function( api_key ) {
38 |
39 | this.api_key = api_key || '2a2ce06c15780ebeb0b706650fc890b2';
40 |
41 | this.options = {
42 | max: 30, // photos to return
43 | imageSize: 'medium', // photo size ( thumb,small,medium,big,original )
44 | thumbSize: 'thumb', // thumbnail size ( thumb,small,medium,big,original )
45 | sort: 'interestingness-desc', // sort option ( date-posted-asc, date-posted-desc, date-taken-asc, date-taken-desc, interestingness-desc, interestingness-asc, relevance )
46 | description: false, // set this to true to get description as caption
47 | complete: function(){}, // callback to be called inside the Galleria.prototype.load
48 | backlink: false // set this to true if you want to pass a link back to the original image
49 | };
50 | };
51 |
52 | Galleria.Flickr.prototype = {
53 |
54 | // bring back the constructor reference
55 |
56 | constructor: Galleria.Flickr,
57 |
58 | /**
59 | Search for anything at Flickr
60 |
61 | @param {String} phrase The string to search for
62 | @param {Function} [callback] The callback to be called when the data is ready
63 |
64 | @returns Instance
65 | */
66 |
67 | search: function( phrase, callback ) {
68 | return this._find({
69 | text: phrase
70 | }, callback );
71 | },
72 |
73 | /**
74 | Search for anything at Flickr by tag
75 |
76 | @param {String} tag The tag(s) to search for
77 | @param {Function} [callback] The callback to be called when the data is ready
78 |
79 | @returns Instance
80 | */
81 |
82 | tags: function( tag, callback ) {
83 | return this._find({
84 | tags: tag
85 | }, callback);
86 | },
87 |
88 | /**
89 | Get a user's public photos
90 |
91 | @param {String} username The username as shown in the URL to fetch
92 | @param {Function} [callback] The callback to be called when the data is ready
93 |
94 | @returns Instance
95 | */
96 |
97 | user: function( username, callback ) {
98 | return this._call({
99 | method: 'flickr.urls.lookupUser',
100 | url: 'flickr.com/photos/' + username
101 | }, function( data ) {
102 | this._find({
103 | user_id: data.user.id,
104 | method: 'flickr.people.getPublicPhotos'
105 | }, callback);
106 | });
107 | },
108 |
109 | /**
110 | Get photos from a photoset by ID
111 |
112 | @param {String|Number} photoset_id The photoset id to fetch
113 | @param {Function} [callback] The callback to be called when the data is ready
114 |
115 | @returns Instance
116 | */
117 |
118 | set: function( photoset_id, callback ) {
119 | return this._find({
120 | photoset_id: photoset_id,
121 | method: 'flickr.photosets.getPhotos'
122 | }, callback);
123 | },
124 |
125 | /**
126 | Get photos from a gallery by ID
127 |
128 | @param {String|Number} gallery_id The gallery id to fetch
129 | @param {Function} [callback] The callback to be called when the data is ready
130 |
131 | @returns Instance
132 | */
133 |
134 | gallery: function( gallery_id, callback ) {
135 | return this._find({
136 | gallery_id: gallery_id,
137 | method: 'flickr.galleries.getPhotos'
138 | }, callback);
139 | },
140 |
141 | /**
142 | Search groups and fetch photos from the first group found
143 | Useful if you know the exact name of a group and want to show the groups photos.
144 |
145 | @param {String} group The group name to search for
146 | @param {Function} [callback] The callback to be called when the data is ready
147 |
148 | @returns Instance
149 | */
150 |
151 | groupsearch: function( group, callback ) {
152 | return this._call({
153 | text: group,
154 | method: 'flickr.groups.search'
155 | }, function( data ) {
156 | this.group( data.groups.group[0].nsid, callback );
157 | });
158 | },
159 |
160 | /**
161 | Get photos from a group by ID
162 |
163 | @param {String} group_id The group id to fetch
164 | @param {Function} [callback] The callback to be called when the data is ready
165 |
166 | @returns Instance
167 | */
168 |
169 | group: function ( group_id, callback ) {
170 | return this._find({
171 | group_id: group_id,
172 | method: 'flickr.groups.pools.getPhotos'
173 | }, callback );
174 | },
175 |
176 | /**
177 | Set flickr options
178 |
179 | @param {Object} options The options object to blend
180 |
181 | @returns Instance
182 | */
183 |
184 | setOptions: function( options ) {
185 | $.extend(this.options, options);
186 | return this;
187 | },
188 |
189 |
190 | // call Flickr and raise errors
191 |
192 | _call: function( params, callback ) {
193 |
194 | var url = 'https://api.flickr.com/services/rest/?';
195 |
196 | var scope = this;
197 |
198 | params = $.extend({
199 | format : 'json',
200 | jsoncallback : '?',
201 | api_key: this.api_key
202 | }, params );
203 |
204 | $.each(params, function( key, value ) {
205 | url += '&' + key + '=' + value;
206 | });
207 |
208 | $.getJSON(url, function(data) {
209 | if ( data.stat === 'ok' ) {
210 | callback.call(scope, data);
211 | } else {
212 | Galleria.raise( data.code.toString() + ' ' + data.stat + ': ' + data.message, true );
213 | }
214 | });
215 | return scope;
216 | },
217 |
218 |
219 | // "hidden" way of getting a big image (~1024) from flickr
220 |
221 | _getBig: function( photo ) {
222 |
223 | if ( photo.url_l ) {
224 | return photo.url_l;
225 | } else if ( parseInt( photo.width_o, 10 ) > 1280 ) {
226 |
227 | return 'https://farm'+photo.farm + '.static.flickr.com/'+photo.server +
228 | '/' + photo.id + '_' + photo.secret + '_b.jpg';
229 | }
230 |
231 | return photo.url_o || photo.url_z || photo.url_m;
232 |
233 | },
234 |
235 |
236 | // get image size by option name
237 |
238 | _getSize: function( photo, size ) {
239 |
240 | var img;
241 |
242 | switch(size) {
243 |
244 | case 'thumb':
245 | img = photo.url_t;
246 | break;
247 |
248 | case 'small':
249 | img = photo.url_s;
250 | break;
251 |
252 | case 'big':
253 | img = this._getBig( photo );
254 | break;
255 |
256 | case 'original':
257 | img = photo.url_o ? photo.url_o : this._getBig( photo );
258 | break;
259 |
260 | default:
261 | img = photo.url_z || photo.url_m;
262 | break;
263 | }
264 | return img;
265 | },
266 |
267 |
268 | // ask flickr for photos, parse the result and call the callback with the galleria-ready data array
269 |
270 | _find: function( params, callback ) {
271 |
272 | params = $.extend({
273 | method: 'flickr.photos.search',
274 | extras: 'url_t,url_m,url_o,url_s,url_l,url_z,description',
275 | sort: this.options.sort,
276 | per_page: Math.min( this.options.max, 500 )
277 | }, params );
278 |
279 | return this._call( params, function(data) {
280 |
281 | var gallery = [],
282 | photos = data.photos ? data.photos.photo : data.photoset.photo,
283 | len = photos.length,
284 | photo,
285 | i;
286 |
287 | for ( i=0; i').css({
335 | width: 48,
336 | height: 48,
337 | opacity: 0.7,
338 | background:'#000 url('+PATH+'loader.gif) no-repeat 50% 50%'
339 | });
340 |
341 | if ( flickr.length ) {
342 |
343 | // validate the method
344 | if ( typeof Galleria.Flickr.prototype[ flickr[0] ] !== 'function' ) {
345 | Galleria.raise( flickr[0] + ' method not found in Flickr plugin' );
346 | return load.apply( this, args );
347 | }
348 |
349 | // validate the argument
350 | if ( !flickr[1] ) {
351 | Galleria.raise( 'No flickr argument found' );
352 | return load.apply( this, args );
353 | }
354 |
355 | // apply the preloader
356 | window.setTimeout(function() {
357 | self.$( 'target' ).append( loader );
358 | },100);
359 |
360 | // create the instance
361 | f = new Galleria.Flickr();
362 |
363 | // apply Flickr options
364 | if ( typeof self._options.flickrOptions === 'object' ) {
365 | f.setOptions( self._options.flickrOptions );
366 | }
367 |
368 | // call the flickr method and trigger the DATA event
369 | f[ flickr[0] ]( flickr[1], function( data ) {
370 |
371 | self._data = data;
372 | loader.remove();
373 | self.trigger( Galleria.DATA );
374 | f.options.complete.call(f, data);
375 |
376 | });
377 | } else {
378 |
379 | // if flickr array not found, pass
380 | load.apply( this, args );
381 | }
382 | };
383 |
384 | }( jQuery ) );
--------------------------------------------------------------------------------