##// END OF EJS Templates
Non-image file icons are inverted on hover
neko259 -
r1673:8d6575ac default
parent child Browse files
Show More
@@ -1,149 +1,149 b''
1 from django.core.files.images import get_image_dimensions
1 from django.core.files.images import get_image_dimensions
2 from django.template.defaultfilters import filesizeformat
2 from django.template.defaultfilters import filesizeformat
3 from django.contrib.staticfiles.templatetags.staticfiles import static
3 from django.contrib.staticfiles.templatetags.staticfiles import static
4
4
5 FILE_STUB_IMAGE = 'images/file.png'
5 FILE_STUB_IMAGE = 'images/file.png'
6 FILE_STUB_URL = 'images/url.png'
6 FILE_STUB_URL = 'images/url.png'
7
7
8 FILE_TYPES_VIDEO = (
8 FILE_TYPES_VIDEO = (
9 'webm',
9 'webm',
10 'mp4',
10 'mp4',
11 'mpeg',
11 'mpeg',
12 'ogv',
12 'ogv',
13 )
13 )
14 FILE_TYPE_SVG = 'svg'
14 FILE_TYPE_SVG = 'svg'
15 FILE_TYPES_AUDIO = (
15 FILE_TYPES_AUDIO = (
16 'ogg',
16 'ogg',
17 'mp3',
17 'mp3',
18 'opus',
18 'opus',
19 )
19 )
20 FILE_TYPES_IMAGE = (
20 FILE_TYPES_IMAGE = (
21 'jpeg',
21 'jpeg',
22 'jpg',
22 'jpg',
23 'png',
23 'png',
24 'bmp',
24 'bmp',
25 'gif',
25 'gif',
26 )
26 )
27
27
28 PLAIN_FILE_FORMATS = {
28 PLAIN_FILE_FORMATS = {
29 'pdf': 'pdf',
29 'pdf': 'pdf',
30 'djvu': 'djvu',
30 'djvu': 'djvu',
31 'txt': 'txt',
31 'txt': 'txt',
32 'tex': 'tex',
32 'tex': 'tex',
33 'xcf': 'xcf',
33 'xcf': 'xcf',
34 }
34 }
35
35
36 CSS_CLASS_IMAGE = 'image'
36 CSS_CLASS_IMAGE = 'image'
37 CSS_CLASS_THUMB = 'thumb'
37 CSS_CLASS_THUMB = 'thumb'
38
38
39
39
40 def get_viewers():
40 def get_viewers():
41 return AbstractViewer.__subclasses__()
41 return AbstractViewer.__subclasses__()
42
42
43
43
44 class AbstractViewer:
44 class AbstractViewer:
45 def __init__(self, file, file_type, hash, url):
45 def __init__(self, file, file_type, hash, url):
46 self.file = file
46 self.file = file
47 self.file_type = file_type
47 self.file_type = file_type
48 self.hash = hash
48 self.hash = hash
49 self.url = url
49 self.url = url
50
50
51 @staticmethod
51 @staticmethod
52 def supports(file_type):
52 def supports(file_type):
53 return True
53 return True
54
54
55 def get_view(self):
55 def get_view(self):
56 return '<div class="image">'\
56 return '<div class="image">'\
57 '{}'\
57 '{}'\
58 '<div class="image-metadata"><a href="{}" download >{}, {}</a></div>'\
58 '<div class="image-metadata"><a href="{}" download >{}, {}</a></div>'\
59 '</div>'.format(self.get_format_view(), self.file.url,
59 '</div>'.format(self.get_format_view(), self.file.url,
60 self.file_type, filesizeformat(self.file.size))
60 self.file_type, filesizeformat(self.file.size))
61
61
62 def get_format_view(self):
62 def get_format_view(self):
63 if self.file_type in PLAIN_FILE_FORMATS:
63 if self.file_type in PLAIN_FILE_FORMATS:
64 image = 'images/fileformats/{}.png'.format(
64 image = 'images/fileformats/{}.png'.format(
65 PLAIN_FILE_FORMATS[self.file_type])
65 PLAIN_FILE_FORMATS[self.file_type])
66 else:
66 else:
67 image = FILE_STUB_IMAGE
67 image = FILE_STUB_IMAGE
68
68
69 return '<a href="{}">'\
69 return '<a href="{}">'\
70 '<img src="{}" width="200" height="150"/>'\
70 '<img class="url-image" src="{}" width="200" height="150"/>'\
71 '</a>'.format(self.file.url, static(image))
71 '</a>'.format(self.file.url, static(image))
72
72
73
73
74 class VideoViewer(AbstractViewer):
74 class VideoViewer(AbstractViewer):
75 @staticmethod
75 @staticmethod
76 def supports(file_type):
76 def supports(file_type):
77 return file_type in FILE_TYPES_VIDEO
77 return file_type in FILE_TYPES_VIDEO
78
78
79 def get_format_view(self):
79 def get_format_view(self):
80 return '<video width="200" height="150" controls src="{}"></video>'\
80 return '<video width="200" height="150" controls src="{}"></video>'\
81 .format(self.file.url)
81 .format(self.file.url)
82
82
83
83
84 class AudioViewer(AbstractViewer):
84 class AudioViewer(AbstractViewer):
85 @staticmethod
85 @staticmethod
86 def supports(file_type):
86 def supports(file_type):
87 return file_type in FILE_TYPES_AUDIO
87 return file_type in FILE_TYPES_AUDIO
88
88
89 def get_format_view(self):
89 def get_format_view(self):
90 return '<audio controls src="{}"></audio>'.format(self.file.url)
90 return '<audio controls src="{}"></audio>'.format(self.file.url)
91
91
92
92
93 class SvgViewer(AbstractViewer):
93 class SvgViewer(AbstractViewer):
94 @staticmethod
94 @staticmethod
95 def supports(file_type):
95 def supports(file_type):
96 return file_type == FILE_TYPE_SVG
96 return file_type == FILE_TYPE_SVG
97
97
98 def get_format_view(self):
98 def get_format_view(self):
99 return '<a class="thumb" href="{}">'\
99 return '<a class="thumb" href="{}">'\
100 '<img class="post-image-preview" width="200" height="150" src="{}" />'\
100 '<img class="post-image-preview" width="200" height="150" src="{}" />'\
101 '</a>'.format(self.file.url, self.file.url)
101 '</a>'.format(self.file.url, self.file.url)
102
102
103
103
104 class ImageViewer(AbstractViewer):
104 class ImageViewer(AbstractViewer):
105 @staticmethod
105 @staticmethod
106 def supports(file_type):
106 def supports(file_type):
107 return file_type in FILE_TYPES_IMAGE
107 return file_type in FILE_TYPES_IMAGE
108
108
109 def get_format_view(self):
109 def get_format_view(self):
110 metadata = '{}, {}'.format(self.file.name.split('.')[-1],
110 metadata = '{}, {}'.format(self.file.name.split('.')[-1],
111 filesizeformat(self.file.size))
111 filesizeformat(self.file.size))
112 width, height = get_image_dimensions(self.file.file)
112 width, height = get_image_dimensions(self.file.file)
113 preview_path = self.file.path.replace('.', '.200x150.')
113 preview_path = self.file.path.replace('.', '.200x150.')
114 pre_width, pre_height = get_image_dimensions(preview_path)
114 pre_width, pre_height = get_image_dimensions(preview_path)
115
115
116 split = self.file.url.rsplit('.', 1)
116 split = self.file.url.rsplit('.', 1)
117 w, h = 200, 150
117 w, h = 200, 150
118 thumb_url = '%s.%sx%s.%s' % (split[0], w, h, split[1])
118 thumb_url = '%s.%sx%s.%s' % (split[0], w, h, split[1])
119
119
120 return '<a class="{}" href="{full}">' \
120 return '<a class="{}" href="{full}">' \
121 '<img class="post-image-preview"' \
121 '<img class="post-image-preview"' \
122 ' src="{}"' \
122 ' src="{}"' \
123 ' alt="{}"' \
123 ' alt="{}"' \
124 ' width="{}"' \
124 ' width="{}"' \
125 ' height="{}"' \
125 ' height="{}"' \
126 ' data-width="{}"' \
126 ' data-width="{}"' \
127 ' data-height="{}" />' \
127 ' data-height="{}" />' \
128 '</a>' \
128 '</a>' \
129 .format(CSS_CLASS_THUMB,
129 .format(CSS_CLASS_THUMB,
130 thumb_url,
130 thumb_url,
131 self.hash,
131 self.hash,
132 str(pre_width),
132 str(pre_width),
133 str(pre_height), str(width), str(height),
133 str(pre_height), str(width), str(height),
134 full=self.file.url, image_meta=metadata)
134 full=self.file.url, image_meta=metadata)
135
135
136
136
137 class UrlViewer(AbstractViewer):
137 class UrlViewer(AbstractViewer):
138 @staticmethod
138 @staticmethod
139 def supports(file_type):
139 def supports(file_type):
140 return file_type is None
140 return file_type is None
141
141
142 def get_view(self):
142 def get_view(self):
143 return '<div class="image">' \
143 return '<div class="image">' \
144 '{}' \
144 '{}' \
145 '</div>'.format(self.get_format_view())
145 '</div>'.format(self.get_format_view())
146 def get_format_view(self):
146 def get_format_view(self):
147 return '<a href="{}">' \
147 return '<a href="{}">' \
148 '<img src="{}" width="200" height="150"/>' \
148 '<img class="url-image" src="{}" width="200" height="150"/>' \
149 '</a>'.format(self.url, static(FILE_STUB_URL))
149 '</a>'.format(self.url, static(FILE_STUB_URL))
@@ -1,171 +1,175 b''
1 .ui-button {
1 .ui-button {
2 display: none;
2 display: none;
3 }
3 }
4
4
5 .ui-dialog-content {
5 .ui-dialog-content {
6 padding: 0;
6 padding: 0;
7 min-height: 0;
7 min-height: 0;
8 }
8 }
9
9
10 .mark_btn {
10 .mark_btn {
11 cursor: pointer;
11 cursor: pointer;
12 }
12 }
13
13
14 .img-full {
14 .img-full {
15 position: fixed;
15 position: fixed;
16 background-color: #CCC;
16 background-color: #CCC;
17 border: 1px solid #000;
17 border: 1px solid #000;
18 cursor: pointer;
18 cursor: pointer;
19 }
19 }
20
20
21 .strikethrough {
21 .strikethrough {
22 text-decoration: line-through;
22 text-decoration: line-through;
23 }
23 }
24
24
25 .post_preview {
25 .post_preview {
26 z-index: 300;
26 z-index: 300;
27 position:absolute;
27 position:absolute;
28 }
28 }
29
29
30 .gallery_image {
30 .gallery_image {
31 display: inline-block;
31 display: inline-block;
32 }
32 }
33
33
34 @media print {
34 @media print {
35 .post-form-w {
35 .post-form-w {
36 display: none;
36 display: none;
37 }
37 }
38 }
38 }
39
39
40 input[name="image"] {
40 input[name="image"] {
41 display: block;
41 display: block;
42 width: 100px;
42 width: 100px;
43 height: 100px;
43 height: 100px;
44 cursor: pointer;
44 cursor: pointer;
45 position: absolute;
45 position: absolute;
46 opacity: 0;
46 opacity: 0;
47 z-index: 1;
47 z-index: 1;
48 }
48 }
49
49
50 .file_wrap {
50 .file_wrap {
51 width: 100px;
51 width: 100px;
52 height: 100px;
52 height: 100px;
53 border: solid 1px white;
53 border: solid 1px white;
54 display: inline-block;
54 display: inline-block;
55 }
55 }
56
56
57 form > .file_wrap {
57 form > .file_wrap {
58 float: left;
58 float: left;
59 }
59 }
60
60
61 .file-thumb {
61 .file-thumb {
62 width: 100px;
62 width: 100px;
63 height: 100px;
63 height: 100px;
64 background-size: cover;
64 background-size: cover;
65 background-position: center;
65 background-position: center;
66 }
66 }
67
67
68 .compact-form-text {
68 .compact-form-text {
69 margin-left:110px;
69 margin-left:110px;
70 }
70 }
71
71
72 textarea, input {
72 textarea, input {
73 -moz-box-sizing: border-box;
73 -moz-box-sizing: border-box;
74 -webkit-box-sizing: border-box;
74 -webkit-box-sizing: border-box;
75 box-sizing: border-box;
75 box-sizing: border-box;
76 }
76 }
77
77
78 .compact-form-text > textarea {
78 .compact-form-text > textarea {
79 height: 100px;
79 height: 100px;
80 width: 100%;
80 width: 100%;
81 }
81 }
82
82
83 .post-button-form {
83 .post-button-form {
84 display: inline;
84 display: inline;
85 }
85 }
86
86
87 .post-button-form > button, #autoupdate {
87 .post-button-form > button, #autoupdate {
88 border: none;
88 border: none;
89 margin: inherit;
89 margin: inherit;
90 padding: inherit;
90 padding: inherit;
91 background: none;
91 background: none;
92 font-size: inherit;
92 font-size: inherit;
93 cursor: pointer;
93 cursor: pointer;
94 }
94 }
95
95
96 #form-close-button {
96 #form-close-button {
97 display: none;
97 display: none;
98 }
98 }
99
99
100 .post-image-full {
100 .post-image-full {
101 width: 100%;
101 width: 100%;
102 height: auto;
102 height: auto;
103 }
103 }
104
104
105 #preview-text {
105 #preview-text {
106 display: none;
106 display: none;
107 }
107 }
108
108
109 .random-images-table {
109 .random-images-table {
110 text-align: center;
110 text-align: center;
111 width: 100%;
111 width: 100%;
112 }
112 }
113
113
114 .random-images-table > div {
114 .random-images-table > div {
115 margin-left: auto;
115 margin-left: auto;
116 margin-right: auto;
116 margin-right: auto;
117 }
117 }
118
118
119 .tag-image, .tag-text-data {
119 .tag-image, .tag-text-data {
120 display: inline-block;
120 display: inline-block;
121 }
121 }
122
122
123 .tag-text-data > h2 {
123 .tag-text-data > h2 {
124 margin: 0;
124 margin: 0;
125 }
125 }
126
126
127 .tag-image {
127 .tag-image {
128 margin-right: 5px;
128 margin-right: 5px;
129 }
129 }
130
130
131 .reply-to-message {
131 .reply-to-message {
132 display: none;
132 display: none;
133 }
133 }
134
134
135 .tripcode {
135 .tripcode {
136 padding: 2px;
136 padding: 2px;
137 }
137 }
138
138
139 #fav-panel {
139 #fav-panel {
140 display: none;
140 display: none;
141 margin: 1ex;
141 margin: 1ex;
142 }
142 }
143
143
144 .hidden_post {
144 .hidden_post {
145 opacity: 0.2;
145 opacity: 0.2;
146 }
146 }
147
147
148 .hidden_post:hover {
148 .hidden_post:hover {
149 opacity: 1;
149 opacity: 1;
150 }
150 }
151
151
152 .monochrome > .image > .thumb > img {
152 .monochrome > .image > .thumb > img {
153 filter: grayscale(100%);
153 filter: grayscale(100%);
154 -webkit-filter: grayscale(100%);
154 -webkit-filter: grayscale(100%);
155 }
155 }
156
156
157 #quote-button {
157 #quote-button {
158 position: absolute;
158 position: absolute;
159 display: none;
159 display: none;
160 cursor: pointer;
160 cursor: pointer;
161 z-index: 400;
161 z-index: 400;
162 }
162 }
163
163
164 .required-field:before {
164 .required-field:before {
165 content: '* ';
165 content: '* ';
166 }
166 }
167
167
168 .hint {
168 .hint {
169 border-bottom: dashed 1px;
169 border-bottom: dashed 1px;
170 cursor: help;
170 cursor: help;
171 }
171 }
172
173 .url-image:hover {
174 filter: invert(100%);
175 }
General Comments 0
You need to be logged in to leave comments. Login now