1
1
<!doctype html>
2
2
< html >
3
3
< head >
4
+ < title > Picky</ title >
5
+ < meta name ="author " content ="Textgain ">
4
6
< meta charset ="utf-8 ">
5
7
6
8
< style >
7
9
* {
8
- font : 12px Arial;
9
- line-height : 1em ;
10
10
color : # 555 ;
11
+ font : 12 px/1em Arial;
11
12
}
12
13
body {
13
14
margin : 25px ;
18
19
.var a {
19
20
text-decoration : none;
20
21
}
21
- label {
22
+ label { /* " LABEL " */
22
23
display : inline-block;
23
- margin-right : 5px ;
24
24
width : 40px ;
25
+ margin-right : 5px ;
26
+ font-size : 0.75em ;
25
27
text-align : right;
26
28
text-transform : uppercase;
27
- font-size : 0.75em ;
28
29
}
29
- input , select , textarea , button {
30
+ input , select , textarea , button , . button {
30
31
outline : none;
31
32
}
32
33
input [type = "text" ],
33
34
input [type = "number" ] {
35
+ padding : 2px 0 ;
34
36
border : 0 ;
35
37
border-bottom : 1px solid # ccc ;
36
- padding : 2px 0 ;
37
38
}
38
39
input [type = "text" ],
39
40
input [type = "number" ],
40
41
textarea {
42
+ box-sizing : border-box;
41
43
width : 180px ;
42
44
}
43
45
textarea {
44
46
height : 90px ;
45
- border : 1px solid # ccc ;
46
47
padding : 4px ;
48
+ border : 1px solid # ccc ;
47
49
}
48
50
.button {
49
51
display : inline-block;
50
- padding : 6px 8px ;
51
- background : dodgerblue;
52
- color : white;
52
+ padding : 8px ;
53
+ border : 1px solid # ccc ;
54
+ border-radius : 8px ;
55
+ color : inherit;
56
+ background : # fff ;
53
57
text-decoration : none;
54
58
}
59
+ .button : hover ,
60
+ .button .hot {
61
+ color : white;
62
+ background : rgb (0 , 150 , 255 );
63
+ border : 1px solid rgb (0 , 150 , 255 );
64
+ }
55
65
.view {
56
66
position : absolute;
57
67
top : 40px ;
58
68
left : 320px ;
59
69
width : 720px ;
60
70
height : 480px ;
61
71
text-align : center;
72
+ /* border: 1px dotted red; */
62
73
}
63
74
.view div {
64
75
position : relative;
74
85
.view a {
75
86
position : absolute;
76
87
display : block;
77
- min-width : 50 px ;
88
+ min-width : 45 px ;
78
89
min-height : 1em ;
79
90
padding : 8px ;
80
- border : 1px solid rgba (255 , 255 , 255 , 0.25 );
81
- background : rgba ( 0 , 0 , 0 , 0.75 ) ;
91
+ border : 1px solid rgba (255 , 255 , 255 , 0.6 );
92
+ border-radius : 8 px ;
82
93
color : white;
94
+ background : rgba (0 , 0 , 0 , 0.6 );
83
95
text-decoration : none;
84
96
}
85
97
.view a # T { top : 0% ; left : 50% ; transform : translate (-50% , -50% ); }
115
127
116
128
var images = [ ] ; // [File1, File2, ...]
117
129
var texts = { } ; // {image: text}
118
- var labels = { } ; // {image: [label1, label2 , ...]}
130
+ var tags = { } ; // {image: [tag1, tag2 , ...]}
119
131
var index = 0 ;
120
132
121
133
var controls = {
122
- 'T' : 'text+image ' ,
123
- 'L' : 'text ' ,
124
- 'R' : 'image ' ,
134
+ 'T' : '' ,
135
+ 'L' : 'bad ' ,
136
+ 'R' : 'good ' ,
125
137
'B' : ''
126
138
} ;
127
139
128
140
function $ ( id ) {
129
141
return document . getElementById ( id ) ;
130
142
}
131
143
132
- function readAsJSON ( file , v ) {
144
+ function readAsJSON ( file , o ) {
133
145
// Parse JSON-file & assign to object.
134
- var f ;
146
+ let f ;
135
147
f = new FileReader ( ) ;
136
148
f . onload = function ( ) {
137
- window [ v ] = JSON . parse ( f . result ) ;
149
+ window [ o ] = JSON . parse ( f . result ) ;
138
150
refresh ( ) ;
139
151
} ;
140
152
f . readAsText ( file ) ;
150
162
readAsJSON ( input . files [ 0 ] , 'texts' ) ;
151
163
}
152
164
153
- function loadLabels ( input ) {
154
- readAsJSON ( input . files [ 0 ] , 'labels ' ) ;
165
+ function loadTags ( input ) {
166
+ readAsJSON ( input . files [ 0 ] , 'tags ' ) ;
155
167
}
156
168
157
169
function refresh ( ) {
158
170
show ( index ) ;
159
171
}
160
172
161
173
function show ( i ) {
162
- // Show image with given index + labels .
163
- $ ( 'index' ) . value = '' ;
164
- $ ( 'name' ) . value = '' ;
165
- $ ( 'labels' ) . value = '' ;
166
- $ ( 'text' ) . innerHTML = '' ;
167
- $ ( 'image' ) . src = '#' ;
174
+ // Show image with given index + tags .
175
+ $ ( 'index' ) . value = '' ;
176
+ $ ( 'name' ) . value = '' ;
177
+ $ ( 'tags' ) . value = '' ;
178
+ $ ( 'text' ) . innerHTML = '' ;
179
+ $ ( 'image' ) . src = '#' ;
168
180
169
- var img = images [ i ] ;
181
+ let img = images [ i ] ;
170
182
if ( img ) {
171
- $ ( 'index' ) . value = i ;
172
- $ ( 'name' ) . value = img . name ;
173
- $ ( 'labels' ) . value = ( labels [ img . name ] || [ ] ) . join ( ', ' ) ;
174
- $ ( 'text' ) . innerHTML = ( texts [ img . name ] || '' ) ;
183
+ $ ( 'index' ) . value = i ;
184
+ $ ( 'name' ) . value = img . name ;
185
+ $ ( 'tags' ) . value = ( tags [ img . name ] || [ ] ) . join ( ', ' ) ;
186
+ $ ( 'text' ) . innerHTML = ( texts [ img . name ] || '' ) ;
175
187
f = new FileReader ( ) ;
176
188
f . onload = function ( ) {
177
189
try {
184
196
}
185
197
186
198
function customize ( k , v ) {
187
- // Assign label v to control k (T/L/R/B).
199
+ // Assign tag v to control k (T/L/R/B).
188
200
controls [ k ] = $ ( k ) . innerHTML = v ;
189
201
}
190
202
191
203
function bwd ( ) {
192
- // Show previous image (if any).
204
+ // Show prev image (if any).
193
205
index = Math . max ( index - 1 , - 1 ) ;
194
206
show ( index ) ;
195
207
}
202
214
203
215
function goto ( i ) {
204
216
// Show image with index i.
205
- index = Math . min ( Math . max ( parseInt ( i ) || 0 , 0 ) , images . length - 1 ) ;
217
+ index = Math . max ( parseInt ( i ) || 0 , 0 ) ;
218
+ index = Math . min ( index , images . length - 1 ) ;
206
219
show ( index ) ;
207
220
}
208
221
209
222
function tag ( v ) {
210
- // 1) Add label v to current image.
223
+ // 1) Add tag v to current image.
211
224
// 2) Show next image.
212
- var img = images [ index ] ;
225
+ let img = images [ index ] ;
213
226
if ( img && v ) {
214
- var k = img . name ;
215
- if ( labels [ k ] == undefined ) {
216
- labels [ k ] = [ ] ;
227
+ let k = img . name ;
228
+ if ( tags [ k ] == undefined ) {
229
+ tags [ k ] = [ ] ;
217
230
}
218
- if ( labels [ k ] . includes ( v ) == false ) {
219
- labels [ k ] . push ( v ) ;
231
+ if ( tags [ k ] . includes ( v ) == false ) {
232
+ tags [ k ] . push ( v ) ;
220
233
}
221
234
}
222
235
fwd ( ) ;
236
+
237
+ $ ( 'save' ) . classList . add ( 'hot' ) ; // (unsaved changes)
223
238
}
224
239
225
240
function edit ( s ) {
226
- // Replace labels on current image,
241
+ // Replace tags on current image,
227
242
// from comma-separated string.
228
- var img = images [ index ] ;
243
+ let img = images [ index ] ;
229
244
if ( img ) {
230
- var k = img . name ;
231
- var a = s . split ( ',' ) ;
232
- for ( var i = 0 ; i < a . length ; i ++ ) {
245
+ let k = img . name ;
246
+ let a = s . split ( ',' ) ;
247
+ for ( let i = 0 ; i < a . length ; i ++ ) {
233
248
a [ i ] = a [ i ] . trim ( ) ;
234
249
}
235
- labels [ k ] = a ;
250
+ tags [ k ] = a ;
236
251
}
252
+
253
+ $ ( 'save' ) . classList . add ( 'hot' ) ; // (unsaved changes)
237
254
}
238
255
239
256
function save ( a ) {
240
- // Generate JSON-file from labels at <a>.
241
- var f ;
242
- f = JSON . stringify ( labels ) ;
257
+ // Generate JSON-file from tags at <a>.
258
+ let f ;
259
+ f = JSON . stringify ( tags ) ;
243
260
f = new File ( [ f ] , { type : 'text/plain' } ) ;
244
261
f = URL . createObjectURL ( f ) ;
245
- a . download = 'labels .json' ;
262
+ a . download = 'tags .json' ;
246
263
a . href = f ;
264
+
265
+ $ ( 'save' ) . classList . remove ( 'hot' ) ;
247
266
}
248
267
249
268
window . onload = function ( ) {
250
269
251
270
// Controls:
252
271
// 1) Backspace & tab show previous/next image.
253
- // 2) Up, down, left, right add label to image.
272
+ // 2) Up, down, left, right add tasg to image.
254
273
// 3) As long as no field has the focus.
255
274
document . addEventListener ( 'keydown' , function ( e ) {
256
275
if ( [ 'a' , 'input' , 'textarea' ] . includes ( e . target . tagName . toLowerCase ( ) ) ) {
298
317
</ div >
299
318
300
319
< div class ="var ">
301
- < label > labels </ label >
302
- < input type ="file " onchange ="loadLabels (this); " />
320
+ < label > tags </ label >
321
+ < input type ="file " onchange ="loadTags (this); " />
303
322
</ div >
304
323
305
324
< div class ="var ">
306
325
< label > ▲</ label >
307
- < input type ="text " onchange ="customize('T', this.value); " value ="text+image " />
326
+ < input type ="text " onchange ="customize('T', this.value); " value ="" />
308
327
</ div >
309
328
< div class ="var ">
310
329
< label > ◀</ label >
311
- < input type ="text " onchange ="customize('L', this.value); " value ="text " />
330
+ < input type ="text " onchange ="customize('L', this.value); " value ="bad " />
312
331
</ div >
313
332
< div class ="var ">
314
333
< label > ▶</ label >
315
- < input type ="text " onchange ="customize('R', this.value); " value ="image " />
334
+ < input type ="text " onchange ="customize('R', this.value); " value ="good " />
316
335
</ div >
317
336
< div class ="var ">
318
337
< label > ▼</ label >
325
344
< a href ="# " onclick ="bwd(); return false; "> «</ a >
326
345
< a href ="# " onclick ="fwd(); return false; "> »</ a >
327
346
</ div >
328
-
347
+
329
348
< div class ="var ">
330
349
< label > name</ label >
331
350
< input type ="text " id ="name " disabled />
332
351
</ div >
333
-
352
+
334
353
< br />
335
354
< div class ="var ">
336
355
< label > </ label >
337
- < textarea id ="labels " onchange ="edit(this.value); "> </ textarea >
356
+ < textarea id ="tags " onchange ="edit(this.value); "> </ textarea >
338
357
</ div >
339
-
358
+
340
359
< div class ="var ">
341
360
< label > </ label >
342
361
< a class ="button " id ="save " href ="" onclick ="save(this); "> Save</ a >
343
362
< input type ="checkbox " id ="auto " /> auto
344
- < div >
363
+ </ div >
345
364
346
365
< div class ="view ">
347
366
< div >
348
367
< img id ="image " src ="" /> < br />
349
- < a id ="L " href ="# " onclick ="tag(this.innerHTML); return false; "> text </ a >
350
- < a id ="T " href ="# " onclick ="tag(this.innerHTML); return false; "> text+image </ a >
351
- < a id ="R " href ="# " onclick ="tag(this.innerHTML); return false; "> image </ a >
368
+ < a id ="L " href ="# " onclick ="tag(this.innerHTML); return false; "> bad </ a >
369
+ < a id ="T " href ="# " onclick ="tag(this.innerHTML); return false; "> </ a >
370
+ < a id ="R " href ="# " onclick ="tag(this.innerHTML); return false; "> good </ a >
352
371
< a id ="B " href ="# " onclick ="tag(this.innerHTML); return false; "> </ a >
353
372
</ div >
354
373
</ div >
355
374
356
375
< p id ="text "> </ p >
357
-
376
+
358
377
</ body >
359
378
360
379
</ html >
0 commit comments