summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--content/fireflix-panel.xul57
-rw-r--r--content/fireflix.js53
-rw-r--r--locale/en-US/fireflix.dtd3
3 files changed, 72 insertions, 41 deletions
diff --git a/content/fireflix-panel.xul b/content/fireflix-panel.xul
index aa3dbd6..405804c 100644
--- a/content/fireflix-panel.xul
+++ b/content/fireflix-panel.xul
@@ -69,240 +69,247 @@
69 <popup id="sets_menu"> 69 <popup id="sets_menu">
70 <menuitem command="cmd_set_props"/> 70 <menuitem command="cmd_set_props"/>
71 <menuitem command="cmd_refresh_sets"/> 71 <menuitem command="cmd_refresh_sets"/>
72 <menuseparator/> 72 <menuseparator/>
73 <menu label="&panel.sets.generate_html;" id="sets_html_menu"/> 73 <menu label="&panel.sets.generate_html;" id="sets_html_menu"/>
74 </popup> 74 </popup>
75 </popupset> 75 </popupset>
76 76
77 <commandset id="cmdset_setphotos"> 77 <commandset id="cmdset_setphotos">
78 </commandset> 78 </commandset>
79 79
80 <popupset> 80 <popupset>
81 <popup id="setphotos_menu"> 81 <popup id="setphotos_menu">
82 <menu label="&panel.setphotos.generate_html;" id="setphotos_html_menu"/> 82 <menu label="&panel.setphotos.generate_html;" id="setphotos_html_menu"/>
83 </popup> 83 </popup>
84 </popupset> 84 </popupset>
85 85
86 <commandset id="cmdset_uploads"> 86 <commandset id="cmdset_uploads">
87 <command id="cmd_uploads_clear" label="&panel.uploads.clear.label;" 87 <command id="cmd_uploads_clear" label="&panel.uploads.clear.label;"
88 oncommand="fireflix.uploads.on_clear()" /> 88 oncommand="fireflix.uploads.on_clear()" />
89 <command id="cmd_uploads_upload" label="&panel.uploads.upload.label;" 89 <command id="cmd_uploads_upload" label="&panel.uploads.upload.label;"
90 oncommand="fireflix.uploads.on_upload()" /> 90 oncommand="fireflix.uploads.on_upload()" />
91 <command id="cmd_uploads_remove" label="&panel.uploads.remove.label;" 91 <command id="cmd_uploads_remove" label="&panel.uploads.remove.label;"
92 oncommand="fireflix.uploads.on_remove()" /> 92 oncommand="fireflix.uploads.on_remove()" />
93 <command id="cmd_uploads_add" label="&panel.uploads.add.label;" 93 <command id="cmd_uploads_add" label="&panel.uploads.add.label;"
94 oncommand="fireflix.uploads.on_add()" /> 94 oncommand="fireflix.uploads.on_add()" />
95 </commandset> 95 </commandset>
96 96
97 <popupset> 97 <popupset>
98 <popup id="uploads_menu"> 98 <popup id="uploads_menu">
99 <menuitem command="cmd_uploads_add"/> 99 <menuitem command="cmd_uploads_add"/>
100 <menuitem command="cmd_uploads_clear"/> 100 <menuitem command="cmd_uploads_clear"/>
101 <menuitem command="cmd_uploads_remove"/> 101 <menuitem command="cmd_uploads_remove"/>
102 <menuseparator/> 102 <menuseparator/>
103 <menuitem command="cmd_uploads_upload"/> 103 <menuitem command="cmd_uploads_upload"/>
104 <menuseparator/> 104 <menuseparator/>
105 <menu label="&panel.uploads.generate_html;" id="uploads_html_menu"/> 105 <menu label="&panel.uploads.generate_html;" id="uploads_html_menu"/>
106 </popup> 106 </popup>
107 </popupset> 107 </popupset>
108 108
109 <vbox class="wholething" flex="1"> 109 <vbox class="wholething" flex="1">
110 110
111 <groupbox context="auth_menu"> 111 <groupbox context="auth_menu">
112 <caption label="&panel.auth_info;"/> 112 <caption label="&panel.auth_info;"/>
113 <hbox> 113 <hbox>
114 <vbox pack="center" flex="1"> 114 <vbox pack="center" flex="1">
115 <label id="auth_info" value="&panel.no_auth_info;" disabled="true" crop="end"/> 115 <label id="auth_info" value="&panel.no_auth_info;" disabled="true" crop="end"/>
116 </vbox> 116 </vbox>
117 <button class="lean" id="b_auth" command="cmd_auth_auth"/> 117 <button class="lean" id="b_auth" command="cmd_auth_auth"/>
118 <button class="lean" id="b_auth_done" command="cmd_auth_done" hidden="true"/> 118 <button class="lean" id="b_auth_done" command="cmd_auth_done" hidden="true"/>
119 <button class="lean" command="cmd_auth_open_flickr" 119 <button class="lean" command="cmd_auth_open_flickr"
120 tooltiptext="&panel.auth.flickr.tip;"/> 120 tooltiptext="&panel.auth.flickr.tip;"/>
121 <button class="lean" command="cmd_help"/> 121 <button class="lean" command="cmd_help"/>
122 </hbox> 122 </hbox>
123 </groupbox> 123 </groupbox>
124 124
125 <tabbox flex="1" id="fireflix_tabs"> 125 <tabbox flex="1" id="fireflix_tabs">
126 126
127 <tabs> 127 <tabs>
128 <tab label="&panel.tabs.search;"/> 128 <tab label="&panel.tabs.search;"/>
129 <tab label="&panel.tabs.sets;"/> 129 <tab label="&panel.tabs.sets;"/>
130 <tab label="&panel.tabs.tags;" hidden="true"/> <!-- TODO: --> 130 <tab label="&panel.tabs.tags;" hidden="true"/> <!-- TODO: -->
131 <tab id="tab_upload" label="&panel.tabs.upload;"/> 131 <tab id="tab_upload" label="&panel.tabs.upload;"/>
132 </tabs> 132 </tabs>
133 133
134 <tabpanels flex="1"> 134 <tabpanels flex="1">
135 135
136 <tabpanel id="tabpanel_search" flex="1"> 136 <tabpanel id="tabpanel_search" flex="1">
137 <vbox flex="1"> 137 <vbox flex="1">
138 <groupbox class="search_params" orient="vertical" onkeypress="if(event.keyCode==event.DOM_VK_RETURN) fireflix.foundphotos.search_photos()"> 138 <groupbox class="search_params" orient="vertical" onkeypress="if(event.keyCode==event.DOM_VK_RETURN) fireflix.foundphotos.search_photos()">
139 <hbox> 139 <hbox>
140 <vbox pack="center"> 140 <vbox pack="center">
141 <label control="search_for" value="&panel.search.search_for.label;" accesskey="s"/> 141 <label control="search_for" value="&panel.search.search_for.label;" accesskey="s"/>
142 </vbox> 142 </vbox>
143 <textbox id="search_for" flex="1"/> 143 <textbox id="search_for" flex="1"/>
144 </hbox> 144 </hbox>
145 <hbox> 145 <hbox>
146 <checkbox id="search_tags" label="&panel.search.mode.tagsonly.label;" 146 <checkbox id="search_tags" label="&panel.search.mode.tagsonly.label;"
147 tooltiptext="&panel.search.mode.tagsonly.tip;" checked="false" 147 tooltiptext="&panel.search.mode.tagsonly.tip;" checked="false"
148 accesskey="t" /> 148 accesskey="t" />
149 <checkbox id="search_mine" label="&panel.search.mode.mine.label;" checked="true" accesskey="m"/> 149 <checkbox id="search_mine" label="&panel.search.mode.mine.label;" checked="true" accesskey="m"/>
150 <spacer flex="1"/> 150 <spacer flex="1"/>
151 <button class="lean" command="cmd_search"/> 151 <button class="lean" command="cmd_search"/>
152 </hbox> 152 </hbox>
153 </groupbox> 153 </groupbox>
154 <hbox> 154 <hbox>
155 <button class="lean" command="cmd_search_prev_page"/> 155 <button class="lean" command="cmd_search_prev_page"/>
156 <spacer flex="1"/> 156 <spacer flex="1"/>
157 <label id="search_page" hidden="true"/> 157 <label id="search_page" hidden="true"/>
158 <spacer flex="1"/> 158 <spacer flex="1"/>
159 <button class="lean" command="cmd_search_next_page"/> 159 <button class="lean" command="cmd_search_next_page"/>
160 </hbox> 160 </hbox>
161 <tree id="searchresults" rows="2" flex="1" 161 <tree id="searchresults" rows="2" flex="1"
162 onselect="fireflix.foundphotos.on_select()" 162 onselect="fireflix.foundphotos.on_select()"
163 ondblclick="fireflix.foundphotos.on_cmd_open(event)" 163 ondblclick="fireflix.foundphotos.on_cmd_open(event)"
164 onkeypress="if(event.keyCode==event.DOM_VK_RETURN) fireflix.foundphotos.on_cmd_open(event)"> 164 onkeypress="if(event.keyCode==event.DOM_VK_RETURN) fireflix.foundphotos.on_cmd_open(event)">
165 <treecols> 165 <treecols>
166 <treecol id="sr_title" label="&panel.search.col.title.label;" flex="2" crop="end" align="start" /> 166 <treecol id="sr_title" label="&panel.search.col.title.label;" flex="2" crop="end" align="start" />
167 </treecols> 167 </treecols>
168 <treechildren/> 168 <treechildren/>
169 </tree> 169 </tree>
170 <groupbox id="searchresult_props" orient="horizontal" hidden="true"> 170 <groupbox id="searchresult_props" orient="horizontal" hidden="true">
171 <vbox width="100" pack="center"> 171 <vbox width="100" pack="center">
172 <hbox pack="center"> 172 <hbox pack="center">
173 <image id="search_photo" 173 <image id="search_photo"
174 ondblclick="fireflix.foundphotos.on_cmd_open(event)"/> 174 ondblclick="fireflix.foundphotos.on_cmd_open(event)"/>
175 </hbox> 175 </hbox>
176 </vbox> 176 </vbox>
177 <vbox flex="1"> 177 <vbox flex="1">
178 <label id="searchresult_title" crop="end"/> 178 <label id="searchresult_title" crop="end"/>
179 <hbox flex="1" pack="center"> 179 <hbox flex="1" pack="center">
180 <div flex="1" id="searchresult_description" xmlns="http://www.w3.org/1999/xhtml"/> 180 <div flex="1" id="searchresult_description" xmlns="http://www.w3.org/1999/xhtml"/>
181 </hbox> 181 </hbox>
182 <hbox pack="end"> 182 <hbox pack="end">
183 <button command="cmd_search_open"/> 183 <button command="cmd_search_open"/>
184 </hbox> 184 </hbox>
185 </vbox> 185 </vbox>
186 </groupbox> 186 </groupbox>
187 </vbox> 187 </vbox>
188 </tabpanel> 188 </tabpanel>
189 189
190 <tabpanel id="tabpanel_sets" flex="1" 190 <tabpanel id="tabpanel_sets" flex="1"
191 onkeypress="if(event.keyCode==event.DOM_VK_RETURN) 191 onkeypress="if(event.keyCode==event.DOM_VK_RETURN)
192 document.getElementById('setphotos').focus()"> 192 document.getElementById('setphotos').focus()">
193 <vbox flex="1"> 193 <vbox flex="1">
194 <tree id="setslist" rows="2" onselect="fireflix.photosets.on_select()" 194 <tree id="setslist" rows="2" onselect="fireflix.photosets.on_select()"
195 flex="1" context="sets_menu" 195 flex="1" context="sets_menu"
196 ondblclick="fireflix.photosets.on_cmd_open_in_flickr(event)" 196 ondblclick="fireflix.photosets.on_cmd_open_in_flickr(event)"
197 > 197 >
198 <treecols> 198 <treecols>
199 <treecol id="sl_name" label="&panel.sets.name.label;" flex="4" crop="end" align="start" tooltiptext="&panel.sets.name.tip;"/> 199 <treecol id="sl_name" label="&panel.sets.name.label;" flex="4" crop="end" align="start" tooltiptext="&panel.sets.name.tip;"/>
200 <splitter class="tree-splitter" /> 200 <splitter class="tree-splitter" />
201 <treecol id="sl_photos" label="&panel.sets.photos.label;" flex="1" align="end" tooltiptext="&panel.sets.photos.tip;" /> 201 <treecol id="sl_photos" label="&panel.sets.photos.label;" flex="1" align="end" tooltiptext="&panel.sets.photos.tip;" />
202 </treecols> 202 </treecols>
203 <treechildren/> 203 <treechildren/>
204 </tree> 204 </tree>
205 <hbox> 205 <hbox>
206 <button command="cmd_refresh_sets" /> 206 <button command="cmd_refresh_sets" />
207 <button command="cmd_set_props" /> 207 <button command="cmd_set_props" />
208 </hbox> 208 </hbox>
209 <tree id="setphotos" rows="2" onselect="fireflix.photoset.on_select()" 209 <tree id="setphotos" rows="2" onselect="fireflix.photoset.on_select()"
210 flex="1" ondblclick="fireflix.photoset.on_cmd_open(event)" 210 flex="1" ondblclick="fireflix.photoset.on_cmd_open(event)"
211 onkeypress="if(event.keyCode==event.DOM_VK_RETURN) fireflix.photoset.on_cmd_open(event)" context="setphotos_menu"> 211 onkeypress="if(event.keyCode==event.DOM_VK_RETURN) fireflix.photoset.on_cmd_open(event)" context="setphotos_menu">
212 <treecols> 212 <treecols>
213 <treecol id="sp_title" label="&panel.setphotos.title.label;" flex="1" crop="end" align="start" tooltiptext="&panel.setphotos.title.tip;" /> 213 <treecol id="sp_title" label="&panel.setphotos.title.label;" flex="1" crop="end" align="start" tooltiptext="&panel.setphotos.title.tip;" />
214 <splitter class="tree-splitter" /> 214 <splitter class="tree-splitter" />
215 <treecol id="sp_taken" label="&panel.setphotos.taken.label;" crop="end" align="start" tooltiptext="&panel.setphotos.taken.tip;" hidden="true" /> 215 <treecol id="sp_taken" label="&panel.setphotos.taken.label;" crop="end" align="start" tooltiptext="&panel.setphotos.taken.tip;" hidden="true" />
216 <treecol id="sp_upload" label="&panel.setphotos.upload.label;" crop="end" align="start" tooltiptext="&panel.setphotos.upload.tip;" hidden="true" /> 216 <treecol id="sp_upload" label="&panel.setphotos.upload.label;" crop="end" align="start" tooltiptext="&panel.setphotos.upload.tip;" hidden="true" />
217 </treecols> 217 </treecols>
218 <treechildren/> 218 <treechildren/>
219 </tree> 219 </tree>
220 <groupbox id="set_photo_props" orient="horizontal" hidden="true"> 220 <groupbox id="set_photo_props" orient="horizontal" hidden="true">
221 <vbox width="100" pack="center"> 221 <vbox width="100" pack="center">
222 <hbox pack="center"> 222 <hbox pack="center">
223 <image id="set_photo" 223 <image id="set_photo"
224 ondblclick="fireflix.photoset.on_cmd_open(event)" /> 224 ondblclick="fireflix.photoset.on_cmd_open(event)" />
225 </hbox> 225 </hbox>
226 </vbox> 226 </vbox>
227 <spacer flex="1"/> 227 <spacer flex="1"/>
228 </groupbox> 228 </groupbox>
229 </vbox> 229 </vbox>
230 </tabpanel> 230 </tabpanel>
231 231
232 <tabpanel id="tabpanel_tags"> 232 <tabpanel id="tabpanel_tags">
233 <listbox id="tagslist" rows="8" flex="1"> 233 <listbox id="tagslist" rows="8" flex="1">
234 <listhead> 234 <listhead>
235 <listheader label="&panel.tagslist.tag.label;"/> 235 <listheader label="&panel.tagslist.tag.label;"/>
236 </listhead> 236 </listhead>
237 <listcols> 237 <listcols>
238 <listcol flex="1"/> 238 <listcol flex="1"/>
239 </listcols> 239 </listcols>
240 </listbox> 240 </listbox>
241 </tabpanel> 241 </tabpanel>
242 242
243 <tabpanel id="tabpanel_upload"> 243 <tabpanel id="tabpanel_upload">
244 <vbox flex="1"> 244 <vbox flex="1">
245 <tree id="uploadlist" rows="2" flex="1" 245 <tree id="uploadlist" rows="2" flex="1"
246 onselect="fireflix.uploads.selectionChanged()" 246 onselect="fireflix.uploads.selectionChanged()"
247 context="uploads_menu"> 247 context="uploads_menu">
248 <treecols> 248 <treecols>
249 <treecol id="up_file" label="&panel.uploadlist.file.label;" flex="4" crop="start" align="start"/> 249 <treecol id="up_file" label="&panel.uploadlist.file.label;" flex="4" crop="start" align="start"/>
250 <splitter class="tree-splitter" /> 250 <splitter class="tree-splitter" />
251 <treecol id="up_title" label="&panel.uploadlist.title.label;" flex="5" crop="end" align="start" /> 251 <treecol id="up_title" label="&panel.uploadlist.title.label;" flex="5" crop="end" align="start" />
252 <splitter class="tree-splitter" /> 252 <splitter class="tree-splitter" />
253 <treecol id="up_status" label="&panel.uploadlist.status.label;" flex="1" crop="end" align="start" /> 253 <treecol id="up_status" label="&panel.uploadlist.status.label;" flex="1" crop="end" align="start" />
254 </treecols> 254 </treecols>
255 <treechildren/> 255 <treechildren/>
256 </tree> 256 </tree>
257 <progressmeter id="upload_progress" mode="undetermined" hidden="true" /> 257 <progressmeter id="upload_progress" mode="undetermined" hidden="true" />
258 <groupbox id="upload_file_props" orient="vertical" hidden="true"> 258 <groupbox id="upload_file_props" orient="vertical" hidden="true">
259 <hbox> 259 <hbox>
260 <image id="upload_file_preview" width="100" height="100" /> 260 <image id="upload_file_preview" width="100" height="100" />
261 <grid flex="1"> 261 <vbox flex="1">
262 <columns> 262 <grid>
263 <column/> 263 <columns>
264 <column flex="1"/> 264 <column/>
265 </columns> 265 <column flex="1"/>
266 <rows> 266 </columns>
267 <row> 267 <rows>
268 <label control="upload_filename" 268 <row>
269 value="&panel.upload_props.filename.label;" /> 269 <label control="upload_filename"
270 <textbox id="upload_filename" 270 value="&panel.upload_props.filename.label;" />
271 oninput="fireflix.uploads.propsToSel('filename')"/> 271 <textbox id="upload_filename"
272 </row> 272 oninput="fireflix.uploads.propsToSel('filename')"/>
273 <row> 273 </row>
274 <label control="upload_title" value="&panel.upload_props.title.label;" /> 274 <row>
275 <textbox id="upload_title" 275 <label control="upload_title" value="&panel.upload_props.title.label;" />
276 oninput="fireflix.uploads.propsToSel('title')"/> 276 <textbox id="upload_title"
277 </row> 277 oninput="fireflix.uploads.propsToSel('title')"/>
278 <row> 278 </row>
279 <label control="upload_tags" value="&panel.upload_props.tags.label;" /> 279 <row>
280 <textbox id="upload_tags" 280 <label control="upload_tags" value="&panel.upload_props.tags.label;" />
281 oninput="fireflix.uploads.propsToSel('tags')"/> 281 <textbox id="upload_tags"
282 </row> 282 oninput="fireflix.uploads.propsToSel('tags')"/>
283 <!-- TODO: description, public, friend, family --> 283 </row>
284 </rows> 284 <!-- TODO: description, public, friend, family -->
285 </grid> 285 </rows>
286 </grid>
287 <hbox>
288 <checkbox id="upload_is_public" label="&panel.upload_props.is_public;"/>
289 <checkbox id="upload_is_friends" label="&panel.upload_props.is_friend;"/>
290 <checkbox id="upload_is_family" label="&panel.upload_props.is_family;"/>
291 </hbox>
292 </vbox>
286 </hbox> 293 </hbox>
287 <description id="upload_failure" hidden="true"/> 294 <description id="upload_failure" hidden="true"/>
288 </groupbox> 295 </groupbox>
289 <hbox> 296 <hbox>
290 <button class="lean" command="cmd_uploads_add" /> 297 <button class="lean" command="cmd_uploads_add" />
291 <spacer flex="1"/> 298 <spacer flex="1"/>
292 <button class="lean" command="cmd_uploads_remove" /> 299 <button class="lean" command="cmd_uploads_remove" />
293 <spacer flex="1"/> 300 <spacer flex="1"/>
294 <button class="lean" command="cmd_uploads_clear" /> 301 <button class="lean" command="cmd_uploads_clear" />
295 </hbox> 302 </hbox>
296 <hbox pack="center"> 303 <hbox pack="center">
297 <button command="cmd_uploads_upload" flex="1"/> 304 <button command="cmd_uploads_upload" flex="1"/>
298 </hbox> 305 </hbox>
299 </vbox> 306 </vbox>
300 </tabpanel> 307 </tabpanel>
301 308
302 </tabpanels> 309 </tabpanels>
303 310
304 </tabbox> 311 </tabbox>
305 312
306 </vbox> 313 </vbox>
307 314
308</page> 315</page>
diff --git a/content/fireflix.js b/content/fireflix.js
index 7291b68..78e56c2 100644
--- a/content/fireflix.js
+++ b/content/fireflix.js
@@ -143,617 +143,638 @@ var fireflix = {
143 photoset_id: psid, 143 photoset_id: psid,
144 extras: 'license,date_upload,date_taken,owner_name,icon_server,original_format,last_update' 144 extras: 'license,date_upload,date_taken,owner_name,icon_server,original_format,last_update'
145 }, function(xr) { 145 }, function(xr) {
146 var x = xr.responseXML; 146 var x = xr.responseXML;
147 var xp = x.evaluate( 147 var xp = x.evaluate(
148 '/rsp/photoset/photo', x, null, 148 '/rsp/photoset/photo', x, null,
149 XPathResult.ORDERED_NODE_ITERATOR_TYPE, null ); 149 XPathResult.ORDERED_NODE_ITERATOR_TYPE, null );
150 _this.importXPR(xp); 150 _this.importXPR(xp);
151 }, function(x,s,c,m) { 151 }, function(x,s,c,m) {
152 _this.fireflix.flickr_failure(x,s,c,m); 152 _this.fireflix.flickr_failure(x,s,c,m);
153 } 153 }
154 ); 154 );
155 }, 155 },
156 on_select: function() { 156 on_select: function() {
157 if(this.selection.count==1) { 157 if(this.selection.count==1) {
158 var p = this.photos[this.selection.currentIndex]; 158 var p = this.photos[this.selection.currentIndex];
159 this.set_photo.src = 159 this.set_photo.src =
160 this.fireflix.flickr.get_photo_url(p.server,p.id,p.secret,'t'); 160 this.fireflix.flickr.get_photo_url(p.server,p.id,p.secret,'t');
161 this.set_photo_props.hidden = false; 161 this.set_photo_props.hidden = false;
162 }else{ 162 }else{
163 this.set_photo_props.hidden = true; 163 this.set_photo_props.hidden = true;
164 } 164 }
165 }, 165 },
166 on_cmd_open: function(ev) { 166 on_cmd_open: function(ev) {
167 if(this.selection.currentIndex<0) return; 167 if(this.selection.currentIndex<0) return;
168 var p = this.photos[this.selection.currentIndex]; 168 var p = this.photos[this.selection.currentIndex];
169 if(!p.id) return; 169 if(!p.id) return;
170 this.fireflix.openTab(this.fireflix.flickr.make_photo_url(p,'p')); 170 this.fireflix.openTab(this.fireflix.flickr.make_photo_url(p,'p'));
171 } 171 }
172 }, 172 },
173 173
174 /* photosets treeview */ 174 /* photosets treeview */
175 photosets: { 175 photosets: {
176 sets: new Array(), 176 sets: new Array(),
177 fireflix: null, 177 fireflix: null,
178 init: function(f) { 178 init: function(f) {
179 this.fireflix = f; 179 this.fireflix = f;
180 document.getElementById('setslist').view = this; 180 document.getElementById('setslist').view = this;
181 }, 181 },
182 rowCount: 0, 182 rowCount: 0,
183 getCellText: function(r,c) { 183 getCellText: function(r,c) {
184 var s = this.sets[r]; 184 var s = this.sets[r];
185 if(c.id=='sl_name') return s.title; 185 if(c.id=='sl_name') return s.title;
186 if(c.id=='sl_photos') return s.photos; 186 if(c.id=='sl_photos') return s.photos;
187 return c.id; 187 return c.id;
188 }, 188 },
189 setTree: function(t) { this.tree = t }, 189 setTree: function(t) { this.tree = t },
190 isContainer: function(r) { return false; }, 190 isContainer: function(r) { return false; },
191 isSeparator: function(r) { return false; }, 191 isSeparator: function(r) { return false; },
192 isSorted: function() { return false; }, 192 isSorted: function() { return false; },
193 getLevel: function(r) { return 0; }, 193 getLevel: function(r) { return 0; },
194 getImageSrc: function(r,c) { return null }, 194 getImageSrc: function(r,c) { return null },
195 getRowProperties: function(r,p) {}, 195 getRowProperties: function(r,p) {},
196 getCellProperties: function(cid,cel,p) { }, 196 getCellProperties: function(cid,cel,p) { },
197 getColumnProperties: function(cid,cel,p) { }, 197 getColumnProperties: function(cid,cel,p) { },
198 cycleHeader: function(cid,e) { }, 198 cycleHeader: function(cid,e) { },
199 getParentIndex: function(r) { return -1; }, 199 getParentIndex: function(r) { return -1; },
200 drop: function(r,o) { }, 200 drop: function(r,o) { },
201 canDropBeforeAfter: function(r,b) { return false }, 201 canDropBeforeAfter: function(r,b) { return false },
202 202
203 importXPR: function(xp) { 203 importXPR: function(xp) {
204 this.tree.beginUpdateBatch(); 204 this.tree.beginUpdateBatch();
205 this.sets = new Array(); 205 this.sets = new Array();
206 var n; while(n=xp.iterateNext()) { 206 var n; while(n=xp.iterateNext()) {
207 this.sets.push(new Photoset(n)); 207 this.sets.push(new Photoset(n));
208 } 208 }
209 this.rowCount = this.sets.length; 209 this.rowCount = this.sets.length;
210 this.tree.endUpdateBatch(); 210 this.tree.endUpdateBatch();
211 }, 211 },
212 refresh_sets: function() { 212 refresh_sets: function() {
213 var _this = this; 213 var _this = this;
214 this.fireflix.flickr.api_call( 214 this.fireflix.flickr.api_call(
215 { 215 {
216 method: 'flickr.photosets.getList', 216 method: 'flickr.photosets.getList',
217 auth_token: 'default' 217 auth_token: 'default'
218 }, function(xr) { 218 }, function(xr) {
219 var x = xr.responseXML; 219 var x = xr.responseXML;
220 var xp = x.evaluate( 220 var xp = x.evaluate(
221 '/rsp/photosets/photoset', x, null, 221 '/rsp/photosets/photoset', x, null,
222 XPathResult.ORDERED_NODE_ITERATOR_TYPE, null ); 222 XPathResult.ORDERED_NODE_ITERATOR_TYPE, null );
223 _this.importXPR(xp); 223 _this.importXPR(xp);
224 }, function(x,s,c,m) { 224 }, function(x,s,c,m) {
225 _this.fireflix.flickr_failure(x,s,c,m); 225 _this.fireflix.flickr_failure(x,s,c,m);
226 } 226 }
227 ); 227 );
228 }, 228 },
229 on_select: function() { 229 on_select: function() {
230 if(this.selection.count==1) { 230 if(this.selection.count==1) {
231 this.fireflix.cmd_set_props.setAttribute('disabled','false'); 231 this.fireflix.cmd_set_props.setAttribute('disabled','false');
232 var s = this.sets[this.selection.currentIndex]; 232 var s = this.sets[this.selection.currentIndex];
233 this.fireflix.photoset.load_photos(s.id); 233 this.fireflix.photoset.load_photos(s.id);
234 }else{ 234 }else{
235 this.fireflix.cmd_set_props.setAttribute('disabled','true'); 235 this.fireflix.cmd_set_props.setAttribute('disabled','true');
236 } 236 }
237 }, 237 },
238 on_cmd_open_in_flickr: function(ev) { 238 on_cmd_open_in_flickr: function(ev) {
239 if(this.selection.currentIndex<0) return; 239 if(this.selection.currentIndex<0) return;
240 var p = this.sets[this.selection.currentIndex]; 240 var p = this.sets[this.selection.currentIndex];
241 if(!p.id) return; 241 if(!p.id) return;
242 this.fireflix.openTab(this.fireflix.flickr.make_photoset_url(p)); 242 this.fireflix.openTab(this.fireflix.flickr.make_photoset_url(p));
243 } 243 }
244 }, 244 },
245 245
246 refresh_user_tags: function() { 246 refresh_user_tags: function() {
247 var lb = document.getElementById('tagslist'); 247 var lb = document.getElementById('tagslist');
248 var _this = this; 248 var _this = this;
249 this.flickr.api_call( 249 this.flickr.api_call(
250 { 250 {
251 method: 'flickr.tags.getListUser', 251 method: 'flickr.tags.getListUser',
252 auth_token: 'default', 252 auth_token: 'default',
253 }, function(xr) { 253 }, function(xr) {
254 var x = xr.responseXML; 254 var x = xr.responseXML;
255 var xp = x.evaluate( 255 var xp = x.evaluate(
256 '/rsp/who/tags/tag', x, null, 256 '/rsp/who/tags/tag', x, null,
257 XPathResult.ORDERED_NODE_ITERATOR_TYPE, null ); 257 XPathResult.ORDERED_NODE_ITERATOR_TYPE, null );
258 // TODO: clear list 258 // TODO: clear list
259 var n; while(n=xp.iterateNext()) { 259 var n; while(n=xp.iterateNext()) {
260 lb.appendItem(n.firstChild.nodeValue); 260 lb.appendItem(n.firstChild.nodeValue);
261 } 261 }
262 }, function(x,s,c,m) { 262 }, function(x,s,c,m) {
263 _this.flickr_failure(x,s,c,m); 263 _this.flickr_failure(x,s,c,m);
264 } 264 }
265 ); 265 );
266 }, 266 },
267 267
268 uploadObserver: { 268 uploadObserver: {
269 fireflix: null, 269 fireflix: null,
270 init: function(f) { 270 init: function(f) {
271 this.fireflix = f; 271 this.fireflix = f;
272 }, 272 },
273 getSupportedFlavours: function() { 273 getSupportedFlavours: function() {
274 var rv = new FlavourSet(); 274 var rv = new FlavourSet();
275 rv.appendFlavour('application/x-moz-file','nsIFile'); 275 rv.appendFlavour('application/x-moz-file','nsIFile');
276 rv.appendFlavour('application/x-moz-url'); 276 rv.appendFlavour('application/x-moz-url');
277 rv.appendFlavour('text/uri-list'); 277 rv.appendFlavour('text/uri-list');
278 rv.appendFlavour('text/unicode'); 278 rv.appendFlavour('text/unicode');
279 return rv; 279 return rv;
280 }, 280 },
281 canHandleMultipleItems: true, 281 canHandleMultipleItems: true,
282 onDragOver: function(ev,fl,sess) { 282 onDragOver: function(ev,fl,sess) {
283 return true; 283 return true;
284 }, 284 },
285 onDrop: function(ev,dd,s) { 285 onDrop: function(ev,dd,s) {
286 var ldf = null; 286 var ldf = null;
287 for(var i in dd.dataList) { 287 for(var i in dd.dataList) {
288 var di = dd.dataList[i]; 288 var di = dd.dataList[i];
289 var dif = di.first; 289 var dif = di.first;
290 if( 290 if(
291 ldf==null 291 ldf==null
292 || ldf.flavour.contentType!=dif.flavour.contentType 292 || ldf.flavour.contentType!=dif.flavour.contentType
293 || ldf.contentLength!=dif.contentLength 293 || ldf.contentLength!=dif.contentLength
294 || ldf.data!=dif.data ) 294 || ldf.data!=dif.data )
295 this.drop_item(ev,di,s); 295 this.drop_item(ev,di,s);
296 ldf = dif; 296 ldf = dif;
297 } 297 }
298 }, 298 },
299 drop_item: function(ev,di,s) { 299 drop_item: function(ev,di,s) {
300 var d = di.first; 300 var d = di.first;
301 switch(d.flavour.contentType) { 301 switch(d.flavour.contentType) {
302 case 'text/unicode': 302 case 'text/unicode':
303 this.drop_urilist(ev,d.data,s); 303 this.drop_urilist(ev,d.data,s);
304 break; 304 break;
305 case 'application/x-moz-file': 305 case 'application/x-moz-file':
306 this.fireflix.uploads.add(d.data.path); 306 this.fireflix.uploads.add(d.data.path);
307 document.getElementById('fireflix_tabs').selectedTab 307 document.getElementById('fireflix_tabs').selectedTab
308 = document.getElementById('tab_upload'); 308 = document.getElementById('tab_upload');
309 break; 309 break;
310 case 'text/uri-list': 310 case 'text/uri-list':
311 // is it ascii or could it be utf8? 311 // is it ascii or could it be utf8?
312 this.drop_urilist(ev,splitascii(d.data),s); 312 this.drop_urilist(ev,splitascii(d.data),s);
313 break; 313 break;
314 default: alert(d.flavour.contentType+':'+d.data); break; 314 default: alert(d.flavour.contentType+':'+d.data); break;
315 }; 315 };
316 }, 316 },
317 drop_urilist: function(ev,ul,s) { 317 drop_urilist: function(ev,ul,s) {
318 // TODO: check for being a file? 318 // TODO: check for being a file?
319 var us = decodeURIComponent(ul).split(/[\r\n]/); 319 var us = decodeURIComponent(ul).split(/[\r\n]/);
320 for(var ui in us) 320 for(var ui in us)
321 if(/\S/.test(us[ui])) 321 if(/\S/.test(us[ui]))
322 this.fireflix.uploads.add(us[ui]); 322 this.fireflix.uploads.add(us[ui]);
323 document.getElementById('fireflix_tabs').selectedTab 323 document.getElementById('fireflix_tabs').selectedTab
324 = document.getElementById('tab_upload'); 324 = document.getElementById('tab_upload');
325 } 325 }
326 }, 326 },
327 327
328 uploads: { 328 uploads: {
329 fireflix: null, 329 fireflix: null,
330 init: function(f) { 330 init: function(f) {
331 this.fireflix=f; 331 this.fireflix=f;
332 pull_elements(this,document,[ 332 pull_elements(this,document,[
333 'upload_filename','upload_title','upload_file_preview', 333 'upload_filename','upload_title','upload_file_preview',
334 'upload_file_props','upload_progress','upload_tags', 334 'upload_file_props','upload_progress','upload_tags',
335 'cmd_uploads_upload', 'upload_failure' 335 'cmd_uploads_upload', 'upload_failure', 'upload_is_public',
336 'upload_is_friends', 'upload_is_family'
336 ]); 337 ]);
337 document.getElementById('uploadlist').view = this; 338 document.getElementById('uploadlist').view = this;
339 this.upload_is_public.addEventListener(
340 'CheckboxStateChange', { that: this,
341 handleEvent: function(ev) { this.that.propsToSel('is_public'); }
342 }, false );
343 this.upload_is_friends.addEventListener(
344 'CheckboxStateChange', { that: this,
345 handleEvent: function(ev) { this.that.propsToSel('is_friends'); }
346 }, false );
347 this.upload_is_family.addEventListener(
348 'CheckboxStateChange', { that: this,
349 handleEvent: function(ev) { this.that.propsToSel('is_family'); }
350 }, false );
338 }, 351 },
339 files: new Array(), 352 files: new Array(),
340 rowCount: 0, 353 rowCount: 0,
341 getCellText: function(r,c) { 354 getCellText: function(r,c) {
342 var f = this.files[r]; 355 var f = this.files[r];
343 if(c.id=='up_file') return f.file; 356 if(c.id=='up_file') return f.file;
344 if(c.id=='up_title') return f.title; 357 if(c.id=='up_title') return f.title;
345 if(c.id=='up_status') return f.state; 358 if(c.id=='up_status') return f.state;
346 return c.id; 359 return c.id;
347 }, 360 },
348 setTree: function(t) { this.tree = t }, 361 setTree: function(t) { this.tree = t },
349 isContainer: function(r) { return false; }, 362 isContainer: function(r) { return false; },
350 isSeparator: function(r) { return false; }, 363 isSeparator: function(r) { return false; },
351 isSorted: function(r) { return false; }, 364 isSorted: function(r) { return false; },
352 getLevel: function(r) { return 0; }, 365 getLevel: function(r) { return 0; },
353 getImageSrc: function(r,c) { return null }, 366 getImageSrc: function(r,c) { return null },
354 getRowProperties: function(r,p) { 367 getRowProperties: function(r,p) {
355 try { 368 try {
356 if(!Components) return; 369 if(!Components) return;
357 }catch(e) { return } 370 }catch(e) { return }
358 var f = this.files[r]; 371 var f = this.files[r];
359 var as = Components.classes['@mozilla.org/atom-service;1']. 372 var as = Components.classes['@mozilla.org/atom-service;1'].
360 getService(Components.interfaces.nsIAtomService); 373 getService(Components.interfaces.nsIAtomService);
361 p.AppendElement(as.getAtom(f.state)); 374 p.AppendElement(as.getAtom(f.state));
362 }, 375 },
363 getCellProperties: function(r,c,p) { this.getRowProperties(r,p); }, 376 getCellProperties: function(r,c,p) { this.getRowProperties(r,p); },
364 getColumnProperties: function(c,p) { }, 377 getColumnProperties: function(c,p) { },
365 cycleHeader: function(cid,e) { }, 378 cycleHeader: function(cid,e) { },
366 getParentIndex: function(r) { return -1; }, 379 getParentIndex: function(r) { return -1; },
367 drop: function(r,o) { }, 380 drop: function(r,o) { },
368 canDropBeforeAfter: function(r,b) { return false }, 381 canDropBeforeAfter: function(r,b) { return false },
369 382
370 add: function(f) { 383 add: function(f) {
371 if(f.indexOf('file:/')==0) { 384 if(f.indexOf('file:/')==0) {
372 f = f.substr(5); 385 f = f.substr(5);
373 while(f.substr(0,2)=='//') { // XXX: not very performant, is it? ;-) 386 while(f.substr(0,2)=='//') { // XXX: not very performant, is it? ;-)
374 f = f.substr(1); 387 f = f.substr(1);
375 } 388 }
376 } 389 }
377 var t = f; 390 var t = f;
378 var ls = t.lastIndexOf('/'); 391 var ls = t.lastIndexOf('/');
379 if(ls>0) t = t.substr(ls+1); 392 if(ls>0) t = t.substr(ls+1);
380 ls = t.lastIndexOf('\\'); 393 ls = t.lastIndexOf('\\');
381 if(ls>0) t = t.substr(ls+1); 394 if(ls>0) t = t.substr(ls+1);
382 var ld = t.lastIndexOf('.'); 395 var ld = t.lastIndexOf('.');
383 if(ld>0) t = t.substr(0,ld); 396 if(ld>0) t = t.substr(0,ld);
384 this.files.push( { 397 this.files.push( {
385 file: f, 398 file: f,
386 title: t, 399 title: t,
387 tags: '', 400 tags: '',
401 is_public: true, is_friend: false, is_family: false,
388 state: 'pending' 402 state: 'pending'
389 } ); 403 } );
390 this.rowCount = this.files.length; 404 this.rowCount = this.files.length;
391 this.tree.rowCountChanged(this.rowCount-1,1); 405 this.tree.rowCountChanged(this.rowCount-1,1);
392 }, 406 },
393 407
394 upload_worker: function() { 408 upload_worker: function() {
395 for(var f in this.files) { 409 for(var f in this.files) {
396 if(this.files[f].state=='pending') { 410 if(this.files[f].state=='pending') {
397 var ff = this.files[f]; 411 var ff = this.files[f];
398 this.on_file_upload(ff); 412 this.on_file_upload(ff);
399 ff.state='uploading'; 413 ff.state='uploading';
400 this.tree.invalidate(); 414 this.tree.invalidate();
401 var _this = this; 415 var _this = this;
402 this.fireflix.flickr.upload_file( 416 this.fireflix.flickr.upload_file(
403 ff.file, { title: ff.title, tags: ff.tags }, 417 ff.file, {
404 function(x,p) { 418 title: ff.title, tags: ff.tags,
419 is_public: ff.is_public?'1':'0',
420 is_friend: ff.is_friend?'1':'0',
421 is_family: ff.is_family?'1':'0'
422 }, function(x,p) {
405 ff.photoid = p; 423 ff.photoid = p;
406 _this.batch_ids.push(p); 424 _this.batch_ids.push(p);
407 ff.state='completed'; 425 ff.state='completed';
408 _this.tree.invalidate(); 426 _this.tree.invalidate();
409 window.setTimeout(_this.upload_to,0,_this); 427 window.setTimeout(_this.upload_to,0,_this);
410 }, function(x,s,c,m) { 428 }, function(x,s,c,m) {
411 ff.state='failed'; 429 ff.state='failed';
412 ff.flickr_errcode = c; 430 ff.flickr_errcode = c;
413 ff.flickr_errmsg = m; 431 ff.flickr_errmsg = m;
414 _this.tree.invalidate(); 432 _this.tree.invalidate();
415 window.setTimeout(_this.upload_to,0,_this); 433 window.setTimeout(_this.upload_to,0,_this);
416 } 434 }
417 ); 435 );
418 return; 436 return;
419 } 437 }
420 } 438 }
421 this.on_finish_upload(); 439 this.on_finish_upload();
422 }, 440 },
423 upload_to: function(_this) { _this.upload_worker(); }, 441 upload_to: function(_this) { _this.upload_worker(); },
424 on_file_upload: function(f) { 442 on_file_upload: function(f) {
425 this.cmd_uploads_upload.setAttribute('disabled','true'); 443 this.cmd_uploads_upload.setAttribute('disabled','true');
426 for(var fi in this.files) { 444 for(var fi in this.files) {
427 if(this.files[fi].file==f.file) { 445 if(this.files[fi].file==f.file) {
428 this.tree.ensureRowIsVisible(fi); 446 this.tree.ensureRowIsVisible(fi);
429 this.selection.rangedSelect(fi,fi,false); 447 this.selection.rangedSelect(fi,fi,false);
430 this.selection.currentIndex = fi; 448 this.selection.currentIndex = fi;
431 this.selToProps(); 449 this.selToProps();
432 break; 450 break;
433 } 451 }
434 } 452 }
435 }, 453 },
436 on_finish_upload: function() { 454 on_finish_upload: function() {
437 if(this.batch_ids.length) { 455 if(this.batch_ids.length) {
438 var psn = prompt(this.fireflix.loc_strings.getString('postUploadPhotoset')); 456 var psn = prompt(this.fireflix.loc_strings.getString('postUploadPhotoset'));
439 if(psn!=null) { 457 if(psn!=null) {
440 var pids = this.batch_ids.join(','); 458 var pids = this.batch_ids.join(',');
441 var ppid = this.batch_ids[0]; 459 var ppid = this.batch_ids[0];
442 var _this = this; 460 var _this = this;
443 this.fireflix.flickr.api_call( 461 this.fireflix.flickr.api_call(
444 { 462 {
445 method: 'flickr.photosets.create', 463 method: 'flickr.photosets.create',
446 auth_token: 'default', 464 auth_token: 'default',
447 title: psn, 465 title: psn,
448 primary_photo_id: ppid 466 primary_photo_id: ppid
449 }, function(x) { 467 }, function(x) {
450 var npid = 468 var npid =
451 x.responseXML.getElementsByTagName('photoset').item(0).getAttribute('id'); 469 x.responseXML.getElementsByTagName('photoset').item(0).getAttribute('id');
452 _this.fireflix.flickr.api_call( 470 _this.fireflix.flickr.api_call(
453 { 471 {
454 method: 'flickr.photosets.editPhotos', 472 method: 'flickr.photosets.editPhotos',
455 auth_token: 'default', 473 auth_token: 'default',
456 photoset_id: npid, 474 photoset_id: npid,
457 primary_photo_id: ppid, 475 primary_photo_id: ppid,
458 photo_ids: pids 476 photo_ids: pids
459 }, function(x) { 477 }, function(x) {
460 _this.fireflix.refresh_sets(); 478 _this.fireflix.refresh_sets();
461 }, function(x,s,c,m) { 479 }, function(x,s,c,m) {
462 _this.fireflix.flickr_failure(x,s,c,m); 480 _this.fireflix.flickr_failure(x,s,c,m);
463 } 481 }
464 ); 482 );
465 }, function(x,s,c,m) { 483 }, function(x,s,c,m) {
466 _this.fireflix.flickr_failure(x,s,c,m); 484 _this.fireflix.flickr_failure(x,s,c,m);
467 } 485 }
468 ); 486 );
469 } 487 }
470 } 488 }
471 this.selection.clearSelection(); 489 this.selection.clearSelection();
472 this.cmd_uploads_upload.setAttribute('disabled','false'); 490 this.cmd_uploads_upload.setAttribute('disabled','false');
473 this.upload_progress.setAttribute('hidden','true'); 491 this.upload_progress.setAttribute('hidden','true');
474 }, 492 },
475 493
476 clear_list: function() { 494 clear_list: function() {
477 this.tree.beginUpdateBatch(); 495 this.tree.beginUpdateBatch();
478 this.rowCount = 0; 496 this.rowCount = 0;
479 this.files = new Array(); 497 this.files = new Array();
480 this.tree.endUpdateBatch(); 498 this.tree.endUpdateBatch();
481 this.selToProps(); 499 this.selToProps();
482 }, 500 },
483 selectionChanged: function() { 501 selectionChanged: function() {
484 this.selToProps(); 502 this.selToProps();
485 }, 503 },
486 disableProps: function() { 504 disableProps: function() {
487 this.upload_filename.value=''; 505 this.upload_filename.value='';
488 this.upload_filename.disabled = true; 506 this.upload_filename.disabled = true;
489 this.upload_title.value=''; 507 this.upload_title.value='';
490 this.upload_title.disabled = true; 508 this.upload_title.disabled = true;
491 this.upload_file_preview.src = null; 509 this.upload_file_preview.src = null;
492 this.upload_tags.value=''; 510 this.upload_tags.value='';
493 this.upload_tags.disabled = true; 511 this.upload_tags.disabled = true;
512 this.upload_is_public.disabled = true;
513 this.upload_is_friends.disabled = true;
514 this.upload_is_family.disabled = true;
494 /* this.upload_file_props.hidden = true; */ 515 /* this.upload_file_props.hidden = true; */
495 }, 516 },
496 selToProps: function() { 517 selToProps: function() {
497 if(!this.selection.count) { 518 if(!this.selection.count) {
498 this.disableProps(); 519 this.disableProps();
499 this.upload_file_props.hidden = true; 520 this.upload_file_props.hidden = true;
500 }else if(this.selection.count==1) { 521 }else if(this.selection.count==1) {
501 var f=this.files[this.selection.currentIndex]; 522 var f=this.files[this.selection.currentIndex];
502 if(f==null) { 523 if(f==null) {
503 this.disableProps(); 524 this.disableProps();
504 this.upload_file_props.hidden = true; 525 this.upload_file_props.hidden = true;
505 }else{ 526 }else{
506 var inactives = f.state!='pending'; 527 var inactives = f.state!='pending';
507 this.upload_filename.value = f.file; 528 this.upload_filename.value = f.file; this.upload_filename.disabled = inactives;
508 this.upload_filename.disabled = inactives; 529 this.upload_title.value = f.title; this.upload_title.disabled = inactives;
509 this.upload_title.value = f.title;
510 this.upload_title.disabled = inactives;
511 this.upload_file_preview.src = 'file:///'+f.file; 530 this.upload_file_preview.src = 'file:///'+f.file;
512 this.upload_tags.value = f.tags; 531 this.upload_tags.value = f.tags; this.upload_tags.disabled = inactives;
513 this.upload_tags.disabled = inactives; 532 this.upload_is_public.checked = f.is_public; this.upload_is_public.disabled = inactives;
533 this.upload_is_friends.checked = f.is_friend; this.upload_is_friends.disabled = inactives;
534 this.upload_is_family.checked = f.is_family; this.upload_is_family.disabled = inactives;
514 if(f.state=='failed') { 535 if(f.state=='failed') {
515 this.upload_failure.textContent=f.flickr_errcode+': '+f.flickr_errmsg; 536 this.upload_failure.textContent=((f.flickr_errcode<0)?'':f.flickr_errcode+': ')+f.flickr_errmsg;
516 this.upload_failure.hidden = false; 537 this.upload_failure.hidden = false;
517 }else{ 538 }else{
518 this.upload_failure.hidden = true; 539 this.upload_failure.hidden = true;
519 } 540 }
520 this.upload_file_props.hidden = false; 541 this.upload_file_props.hidden = false;
521 } 542 }
522 }else{ 543 }else{
523 var ftitle = null; var onetitle = true; 544 var ftitle = null; var onetitle = true;
524 var ftags = null; var onetag = true; 545 var ftags = null; var onetag = true;
525 var fs = 0; 546 var fs = 0;
526 for(var ff in this.files) { 547 for(var ff in this.files) {
527 if(this.selection.isSelected(ff) && this.files[ff].state=='pending' ) { 548 if(this.selection.isSelected(ff) && this.files[ff].state=='pending' ) {
528 ++fs; 549 ++fs;
529 if(ftitle==null) { 550 if(ftitle==null) {
530 ftitle = this.files[ff].title; 551 ftitle = this.files[ff].title;
531 }else if(ftitle!=this.files[ff].title) { 552 }else if(ftitle!=this.files[ff].title) {
532 onetitle = false; 553 onetitle = false;
533 } 554 }
534 if(ftags==null) { 555 if(ftags==null) {
535 ftags = this.files[ff].tags; 556 ftags = this.files[ff].tags;
536 }else if(ftags!=this.files[ff].tags) { 557 }else if(ftags!=this.files[ff].tags) {
537 onetag = false; 558 onetag = false;
538 } 559 }
539 } 560 }
540 } 561 }
541 if(fs) { 562 if(fs) {
542 this.upload_filename.value=''; 563 this.upload_filename.value='';
543 this.upload_filename.disabled = true; 564 this.upload_filename.disabled = true;
544 if(onetitle) 565 if(onetitle)
545 this.upload_title.value = ftitle; 566 this.upload_title.value = ftitle;
546 this.upload_title.disabled = false; 567 this.upload_title.disabled = false;
547 if(onetag) 568 if(onetag)
548 this.upload_tags.value = ftags; 569 this.upload_tags.value = ftags;
549 this.upload_tags.disabled = false; 570 this.upload_tags.disabled = false;
550 this.upload_file_preview.src = null; 571 this.upload_file_preview.src = null;
551 this.upload_failure.hidden = true; 572 this.upload_failure.hidden = true;
552 this.upload_file_props.hidden = false; 573 this.upload_file_props.hidden = false;
553 }else 574 }else
554 this.disableProps(); 575 this.disableProps();
555 this.upload_file_props.hidden = true; 576 this.upload_file_props.hidden = true;
556 } 577 }
557 }, 578 },
558 propsToSel: function(prop) { 579 propsToSel: function(prop) {
559 if(this.selection.count<=0) return; 580 if(this.selection.count<=0) return;
560 for(var ff in this.files) { 581 for(var ff in this.files) {
561 if(this.selection.isSelected(ff) && this.files[ff].state=='pending') { 582 if(this.selection.isSelected(ff) && this.files[ff].state=='pending') {
562 if(prop=='filename') 583 if(prop=='filename') this.files[ff].file = this.upload_filename.value;
563 this.files[ff].file = this.upload_filename.value; 584 if(prop=='title') this.files[ff].title = this.upload_title.value;
564 if(prop=='title') 585 if(prop=='tags') this.files[ff].tags = this.upload_tags.value;
565 this.files[ff].title = this.upload_title.value; 586 if(prop=='is_public') this.files[ff].is_public = this.upload_is_public.checked;
566 if(prop=='tags') 587 if(prop=='is_friends') this.files[ff].is_friend = this.upload_is_friends.checked;
567 this.files[ff].tags = this.upload_tags.value; 588 if(prop=='is_family') this.files[ff].is_family = this.upload_is_family.checked;
568 this.tree.invalidateRow(ff); 589 this.tree.invalidateRow(ff);
569 } 590 }
570 } 591 }
571 }, 592 },
572 593
573 on_upload: function() { 594 on_upload: function() {
574 this.selToProps(); 595 this.selToProps();
575 this.batch_ids = new Array(); 596 this.batch_ids = new Array();
576 this.upload_progress.value=0; 597 this.upload_progress.value=0;
577 this.upload_progress.setAttribute('hidden','false'); 598 this.upload_progress.setAttribute('hidden','false');
578 this.upload_worker(); 599 this.upload_worker();
579 }, 600 },
580 on_clear: function() { 601 on_clear: function() {
581 this.clear_list(); 602 this.clear_list();
582 }, 603 },
583 on_remove: function() { 604 on_remove: function() {
584 if(this.selection.count) { 605 if(this.selection.count) {
585 this.tree.beginUpdateBatch(); 606 this.tree.beginUpdateBatch();
586 for(var i=this.files.length-1;i>=0;--i) { 607 for(var i=this.files.length-1;i>=0;--i) {
587 if(this.selection.isSelected(i)) { 608 if(this.selection.isSelected(i)) {
588 this.files.splice(i,1); 609 this.files.splice(i,1);
589 this.rowCount--; 610 this.rowCount--;
590 } 611 }
591 } 612 }
592 this.tree.endUpdateBatch(); 613 this.tree.endUpdateBatch();
593 this.selection.clearSelection(); 614 this.selection.clearSelection();
594 } 615 }
595 }, 616 },
596 on_add: function() { 617 on_add: function() {
597 var ifp = Components.interfaces.nsIFilePicker; 618 var ifp = Components.interfaces.nsIFilePicker;
598 var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(ifp); 619 var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(ifp);
599 fp.init(window, "Select a File", ifp.modeOpenMultiple); 620 fp.init(window, "Select a File", ifp.modeOpenMultiple);
600 fp.appendFilters(ifp.filterImages); 621 fp.appendFilters(ifp.filterImages);
601 var rv = fp.show(); 622 var rv = fp.show();
602 if(rv==ifp.returnOK) { 623 if(rv==ifp.returnOK) {
603 var ff = fp.files; 624 var ff = fp.files;
604 while(ff.hasMoreElements()) { 625 while(ff.hasMoreElements()) {
605 var f = ff.getNext(); 626 var f = ff.getNext();
606 f.QueryInterface(Components.interfaces.nsIFile); 627 f.QueryInterface(Components.interfaces.nsIFile);
607 this.add(f.path); 628 this.add(f.path);
608 } 629 }
609 } 630 }
610 } 631 }
611 }, 632 },
612 633
613 on_set_props: function() { 634 on_set_props: function() {
614 var pset = this.photosets.sets[this.photosets.selection.currentIndex]; 635 var pset = this.photosets.sets[this.photosets.selection.currentIndex];
615 window.openDialog( 636 window.openDialog(
616 "chrome://fireflix/content/photoset-props.xul", 637 "chrome://fireflix/content/photoset-props.xul",
617 null, "dependent,modal,dialog,chrome", this, 638 null, "dependent,modal,dialog,chrome", this,
618 pset ); 639 pset );
619 if(pset.dirty) { 640 if(pset.dirty) {
620 var _this = this; 641 var _this = this;
621 this.flickr.api_call( 642 this.flickr.api_call(
622 { 643 {
623 method: 'flickr.photosets.editMeta', 644 method: 'flickr.photosets.editMeta',
624 auth_token: 'default', 645 auth_token: 'default',
625 photoset_id: pset.id, 646 photoset_id: pset.id,
626 title: pset.title, 647 title: pset.title,
627 description: pset.description 648 description: pset.description
628 }, function(xr) { 649 }, function(xr) {
629 pset.dirty = false; 650 pset.dirty = false;
630 _this.flickr.api_call( 651 _this.flickr.api_call(
631 { 652 {
632 method: 'flickr.photosets.getPhotos', 653 method: 'flickr.photosets.getPhotos',
633 auth_token: 'default', 654 auth_token: 'default',
634 photoset_id: pset.id 655 photoset_id: pset.id
635 }, function(xr) { 656 }, function(xr) {
636 var x = xr.responseXML; 657 var x = xr.responseXML;
637 var xp = x.evaluate( 658 var xp = x.evaluate(
638 '/rsp/photoset/photo', x, null, 659 '/rsp/photoset/photo', x, null,
639 XPathResult.ORDERED_NODE_ITERATOR_TYPE, null ); 660 XPathResult.ORDERED_NODE_ITERATOR_TYPE, null );
640 var phids = new Array(); 661 var phids = new Array();
641 var priph = null; 662 var priph = null;
642 var n; while(n=xp.iterateNext()) { 663 var n; while(n=xp.iterateNext()) {
643 var pid = n.getAttribute('id'); 664 var pid = n.getAttribute('id');
644 phids.push( pid ); 665 phids.push( pid );
645 if(pid==pset.primary && n.getAttribute('isprimary')!='1') 666 if(pid==pset.primary && n.getAttribute('isprimary')!='1')
646 priph = pid; 667 priph = pid;
647 } 668 }
648 if(priph) { 669 if(priph) {
649 _this.flickr.api_call( 670 _this.flickr.api_call(
650 { 671 {
651 method: 'flickr.photosets.editPhotos', 672 method: 'flickr.photosets.editPhotos',
652 auth_token: 'default', 673 auth_token: 'default',
653 photoset_id: pset.id, 674 photoset_id: pset.id,
654 primary_photo_id: priph, 675 primary_photo_id: priph,
655 photo_ids: phids.join(',') 676 photo_ids: phids.join(',')
656 }, function() { }, function(x,s,c,m) { /* flickr.photosets.editPhotos */ 677 }, function() { }, function(x,s,c,m) { /* flickr.photosets.editPhotos */
657 _this.flickr_failure(x,s,c,m); 678 _this.flickr_failure(x,s,c,m);
658 } 679 }
659 ); 680 );
660 } 681 }
661 }, function(x,s,c,m) { /* flickr.photosets.getPhotos */ 682 }, function(x,s,c,m) { /* flickr.photosets.getPhotos */
662 _this.flickr_failure(x,s,c,m); 683 _this.flickr_failure(x,s,c,m);
663 } 684 }
664 ); 685 );
665 }, function(x,s,c,m) { /* flickr.photosets.editMeta */ 686 }, function(x,s,c,m) { /* flickr.photosets.editMeta */
666 _this.flickr_failure(x,s,c,m); 687 _this.flickr_failure(x,s,c,m);
667 } 688 }
668 ); 689 );
669 } 690 }
670 }, 691 },
671 on_refresh_sets: function() { 692 on_refresh_sets: function() {
672 this.refresh_sets(); 693 this.refresh_sets();
673 }, 694 },
674 on_cmd_sets_html: function(csfx,ev) { 695 on_cmd_sets_html: function(csfx,ev) {
675 var uti = csfx.charAt(0); var utl = csfx.charAt(1); 696 var uti = csfx.charAt(0); var utl = csfx.charAt(1);
676 var rv = this.build_html(this.photoset.photos,uti,utl); 697 var rv = this.build_html(this.photoset.photos,uti,utl);
677 this.popup_content(rv); 698 this.popup_content(rv);
678 }, 699 },
679 on_cmd_setphotos_html: function(csfx,ev) { 700 on_cmd_setphotos_html: function(csfx,ev) {
680 var uti = csfx.charAt(0); var utl = csfx.charAt(1); 701 var uti = csfx.charAt(0); var utl = csfx.charAt(1);
681 var rv = ''; 702 var rv = '';
682 for(var p in this.photoset.photos) { 703 for(var p in this.photoset.photos) {
683 if(this.photoset.selection.isSelected(p)) 704 if(this.photoset.selection.isSelected(p))
684 rv += this.photo_html(this.photoset.photos[p],uti,utl)+'\n'; 705 rv += this.photo_html(this.photoset.photos[p],uti,utl)+'\n';
685 } 706 }
686 this.popup_content(rv); 707 this.popup_content(rv);
687 }, 708 },
688 709
689 on_cmd_uploads_html: function(csfx,ev) { 710 on_cmd_uploads_html: function(csfx,ev) {
690 var uti = csfx.charAt(0); var utl = csfx.charAt(1); 711 var uti = csfx.charAt(0); var utl = csfx.charAt(1);
691 var pids = new Array(); 712 var pids = new Array();
692 for(var f in this.uploads.files) { 713 for(var f in this.uploads.files) {
693 if(this.uploads.selection.isSelected(f)) 714 if(this.uploads.selection.isSelected(f))
694 if(this.uploads.files[f].photoid) 715 if(this.uploads.files[f].photoid)
695 pids.push(this.uploads.files[f].photoid); 716 pids.push(this.uploads.files[f].photoid);
696 } 717 }
697 var pp = this.uploads.rowCount*2; if(pp>500) pp = 500; 718 var pp = this.uploads.rowCount*2; if(pp>500) pp = 500;
698 var _this = this; 719 var _this = this;
699 this.flickr.api_call( 720 this.flickr.api_call(
700 { 721 {
701 method: 'flickr.photos.search', 722 method: 'flickr.photos.search',
702 auth_token: 'default', 723 auth_token: 'default',
703 extras: 'original_format', 724 extras: 'original_format',
704 user_id: 'me', 725 user_id: 'me',
705 per_page: pp 726 per_page: pp
706 }, 727 },
707 function(xr) { 728 function(xr) {
708 var x = xr.responseXML; 729 var x = xr.responseXML;
709 var rv = ''; 730 var rv = '';
710 for(var pn in pids) { 731 for(var pn in pids) {
711 var p = pids[pn]; 732 var p = pids[pn];
712 var pp = new Photo(xp_node('/rsp/photos/photo[@id='+p+']',x)); 733 var pp = new Photo(xp_node('/rsp/photos/photo[@id='+p+']',x));
713 rv += _this.photo_html(pp,uti,utl)+'\n'; 734 rv += _this.photo_html(pp,uti,utl)+'\n';
714 } 735 }
715 _this.popup_content(rv); 736 _this.popup_content(rv);
716 }, function(x,s,c,m) { 737 }, function(x,s,c,m) {
717 _this.flickr_failure(x,s,c,m); 738 _this.flickr_failure(x,s,c,m);
718 } 739 }
719 ); 740 );
720 }, 741 },
721 742
722 /* 743 /*
723 * 744 *
724 */ 745 */
725 foundphotos: { 746 foundphotos: {
726 fireflix: null, 747 fireflix: null,
727 init: function(f) { 748 init: function(f) {
728 this.fireflix = f; 749 this.fireflix = f;
729 pull_elements(this,document,[ 750 pull_elements(this,document,[
730 'search_for','search_tags','search_mine', 751 'search_for','search_tags','search_mine',
731 'searchresult_props','search_photo', 752 'searchresult_props','search_photo',
732 'searchresult_title','searchresult_description', 753 'searchresult_title','searchresult_description',
733 'search_page','cmd_search_prev_page','cmd_search_next_page' 754 'search_page','cmd_search_prev_page','cmd_search_next_page'
734 ]); 755 ]);
735 document.getElementById('searchresults').view = this; 756 document.getElementById('searchresults').view = this;
736 }, 757 },
737 photos: new Array(), 758 photos: new Array(),
738 rowCount: 0, 759 rowCount: 0,
739 getCellText: function(r,c) { 760 getCellText: function(r,c) {
740 var p = this.photos[r]; 761 var p = this.photos[r];
741 if(c.id=='sr_title') return p.title; 762 if(c.id=='sr_title') return p.title;
742 return c.id; 763 return c.id;
743 }, 764 },
744 setTree: function(t) { this.tree = t }, 765 setTree: function(t) { this.tree = t },
745 isContainer: function(r) { return false }, 766 isContainer: function(r) { return false },
746 isSeparator: function(r) { return false }, 767 isSeparator: function(r) { return false },
747 isSorted: function(r) { return false }, 768 isSorted: function(r) { return false },
748 getLevel: function(r) { return 0 }, 769 getLevel: function(r) { return 0 },
749 getImageSrc: function(r,c) { return null }, 770 getImageSrc: function(r,c) { return null },
750 getRowProperties: function(r,p) { }, 771 getRowProperties: function(r,p) { },
751 getCellProperties: function(cid,cel,p) { }, 772 getCellProperties: function(cid,cel,p) { },
752 getColumnProperties: function(cid,cel,p) { }, 773 getColumnProperties: function(cid,cel,p) { },
753 cycleHeader: function(cid,e) { }, 774 cycleHeader: function(cid,e) { },
754 getParentIndex: function(r) { return -1 }, 775 getParentIndex: function(r) { return -1 },
755 drop: function(r,o) { }, 776 drop: function(r,o) { },
756 canDropBeforeAfter: function(r,b) { return false }, 777 canDropBeforeAfter: function(r,b) { return false },
757 778
758 importXPR: function(xp) { 779 importXPR: function(xp) {
759 this.selection.clearSelection(); 780 this.selection.clearSelection();
diff --git a/locale/en-US/fireflix.dtd b/locale/en-US/fireflix.dtd
index 3380078..d975031 100644
--- a/locale/en-US/fireflix.dtd
+++ b/locale/en-US/fireflix.dtd
@@ -1,90 +1,93 @@
1<!ENTITY % autoconf SYSTEM "chrome://fireflix/content/autoconf.dtd"> 1<!ENTITY % autoconf SYSTEM "chrome://fireflix/content/autoconf.dtd">
2%autoconf; 2%autoconf;
3 3
4<!-- About Box --> 4<!-- About Box -->
5 5
6<!ENTITY aboutFireflix "About Fireflix" > 6<!ENTITY aboutFireflix "About Fireflix" >
7<!ENTITY about.ok.label "OK"> 7<!ENTITY about.ok.label "OK">
8<!ENTITY about.license.label "License"> 8<!ENTITY about.license.label "License">
9<!ENTITY about.license.tip "Show copying policy"> 9<!ENTITY about.license.tip "Show copying policy">
10 10
11<!-- COPYING --> 11<!-- COPYING -->
12 12
13<!ENTITY copying.title "Filreflix: copying policy"> 13<!ENTITY copying.title "Filreflix: copying policy">
14 14
15<!-- Sidebar --> 15<!-- Sidebar -->
16 16
17<!ENTITY sidekey.key "X"> 17<!ENTITY sidekey.key "X">
18<!ENTITY sidekey.modifiers "control shift"> 18<!ENTITY sidekey.modifiers "control shift">
19 19
20<!ENTITY panel.auth_info "Authorization info"> 20<!ENTITY panel.auth_info "Authorization info">
21<!ENTITY panel.no_auth_info "No auth info available"> 21<!ENTITY panel.no_auth_info "No auth info available">
22 22
23<!ENTITY panel.auth.auth.label "Authorize"> 23<!ENTITY panel.auth.auth.label "Authorize">
24<!ENTITY panel.auth.done.label "Authorization complete"> 24<!ENTITY panel.auth.done.label "Authorization complete">
25<!ENTITY panel.auth.flickr.label "Flickr"> 25<!ENTITY panel.auth.flickr.label "Flickr">
26<!ENTITY panel.auth.flickr.tip "Open Flickr in new tab"> 26<!ENTITY panel.auth.flickr.tip "Open Flickr in new tab">
27<!ENTITY panel.auth.unauth.label "Sign off"> 27<!ENTITY panel.auth.unauth.label "Sign off">
28 28
29<!ENTITY panel.tabs.search "Search" > 29<!ENTITY panel.tabs.search "Search" >
30<!ENTITY panel.tabs.sets "Sets" > 30<!ENTITY panel.tabs.sets "Sets" >
31<!ENTITY panel.tabs.tags "Tags" > 31<!ENTITY panel.tabs.tags "Tags" >
32<!ENTITY panel.tabs.upload "Upload" > 32<!ENTITY panel.tabs.upload "Upload" >
33 33
34<!ENTITY panel.search.cmd_search.label "Search" > 34<!ENTITY panel.search.cmd_search.label "Search" >
35<!ENTITY panel.search.search_for.label "Search for:" > 35<!ENTITY panel.search.search_for.label "Search for:" >
36<!ENTITY panel.search.mode.tagsonly.label "tags"> 36<!ENTITY panel.search.mode.tagsonly.label "tags">
37<!ENTITY panel.search.mode.tagsonly.tip "Search tags only"> 37<!ENTITY panel.search.mode.tagsonly.tip "Search tags only">
38<!ENTITY panel.search.mode.mine.label "mine"> 38<!ENTITY panel.search.mode.mine.label "mine">
39<!ENTITY panel.search.col.title.label "Title"> 39<!ENTITY panel.search.col.title.label "Title">
40<!ENTITY panel.search.cmd_search_open.label "Open"> 40<!ENTITY panel.search.cmd_search_open.label "Open">
41<!ENTITY panel.search.cmd_search_prev_page.label " « "> 41<!ENTITY panel.search.cmd_search_prev_page.label " « ">
42<!ENTITY panel.search.cmd_search_next_page.label " » "> 42<!ENTITY panel.search.cmd_search_next_page.label " » ">
43 43
44<!ENTITY panel.sets.name.label "Set"> 44<!ENTITY panel.sets.name.label "Set">
45<!ENTITY panel.sets.name.tip "Photoset name"> 45<!ENTITY panel.sets.name.tip "Photoset name">
46<!ENTITY panel.sets.photos.label "Photos"> 46<!ENTITY panel.sets.photos.label "Photos">
47<!ENTITY panel.sets.photos.tip "Number of photos in set"> 47<!ENTITY panel.sets.photos.tip "Number of photos in set">
48 48
49<!ENTITY panel.sets.cmd_refresh_sets "Refresh"> 49<!ENTITY panel.sets.cmd_refresh_sets "Refresh">
50<!ENTITY panel.sets.cmd_properties "Properties"> 50<!ENTITY panel.sets.cmd_properties "Properties">
51 51
52<!ENTITY panel.sets.generate_html "Generate HTML"> 52<!ENTITY panel.sets.generate_html "Generate HTML">
53 53
54<!ENTITY panel.setphotos.title.label "Title"> 54<!ENTITY panel.setphotos.title.label "Title">
55<!ENTITY panel.setphotos.title.tip "Picture title"> 55<!ENTITY panel.setphotos.title.tip "Picture title">
56<!ENTITY panel.setphotos.taken.label "Taken"> 56<!ENTITY panel.setphotos.taken.label "Taken">
57<!ENTITY panel.setphotos.taken.tip "When the picture was taken"> 57<!ENTITY panel.setphotos.taken.tip "When the picture was taken">
58<!ENTITY panel.setphotos.upload.label "Uploaded"> 58<!ENTITY panel.setphotos.upload.label "Uploaded">
59<!ENTITY panel.setphotos.upload.tip "When the picure was uploaded"> 59<!ENTITY panel.setphotos.upload.tip "When the picure was uploaded">
60 60
61<!ENTITY panel.setphotos.generate_html "Generate HTML"> 61<!ENTITY panel.setphotos.generate_html "Generate HTML">
62 62
63<!ENTITY panel.tagslist.tag.label "Tag"> 63<!ENTITY panel.tagslist.tag.label "Tag">
64 64
65<!ENTITY panel.uploadlist.file.label "File name"> 65<!ENTITY panel.uploadlist.file.label "File name">
66<!ENTITY panel.uploadlist.title.label "Title"> 66<!ENTITY panel.uploadlist.title.label "Title">
67<!ENTITY panel.uploadlist.status.label "Status"> 67<!ENTITY panel.uploadlist.status.label "Status">
68 68
69<!ENTITY panel.upload_props.filename.label "File:"> 69<!ENTITY panel.upload_props.filename.label "File:">
70<!ENTITY panel.upload_props.title.label "Title:"> 70<!ENTITY panel.upload_props.title.label "Title:">
71<!ENTITY panel.upload_props.tags.label "Tags:"> 71<!ENTITY panel.upload_props.tags.label "Tags:">
72<!ENTITY panel.upload_props.is_public "Public">
73<!ENTITY panel.upload_props.is_friend "Friends">
74<!ENTITY panel.upload_props.is_family "Family">
72 75
73<!ENTITY panel.uploads.upload.label "Upload"> 76<!ENTITY panel.uploads.upload.label "Upload">
74<!ENTITY panel.uploads.clear.label "Clear"> 77<!ENTITY panel.uploads.clear.label "Clear">
75<!ENTITY panel.uploads.remove.label "Remove"> 78<!ENTITY panel.uploads.remove.label "Remove">
76<!ENTITY panel.uploads.add.label "Add"> 79<!ENTITY panel.uploads.add.label "Add">
77<!ENTITY panel.uploads.generate_html "Generate HTML"> 80<!ENTITY panel.uploads.generate_html "Generate HTML">
78 81
79<!ENTITY generated.title "Fireflix: Generated content"> 82<!ENTITY generated.title "Fireflix: Generated content">
80<!ENTITY generated.copy "copy"> 83<!ENTITY generated.copy "copy">
81<!ENTITY generated.nolf "remove linebreaks"> 84<!ENTITY generated.nolf "remove linebreaks">
82 85
83<!ENTITY browser.sidebar.label "Fireflix"> 86<!ENTITY browser.sidebar.label "Fireflix">
84<!ENTITY browser.sidebar.title "Fireflix"> 87<!ENTITY browser.sidebar.title "Fireflix">
85<!ENTITY browser.sidebar.tooltip "Fireflix"> 88<!ENTITY browser.sidebar.tooltip "Fireflix">
86 89
87<!ENTITY photosetprops.title "Photoset properties"> 90<!ENTITY photosetprops.title "Photoset properties">
88<!ENTITY photosetprops.set_title.label "Photoset title:"> 91<!ENTITY photosetprops.set_title.label "Photoset title:">
89<!ENTITY photosetprops.set_desc.label "Photoset description:"> 92<!ENTITY photosetprops.set_desc.label "Photoset description:">
90 93