alchemy-media 0.5.2 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +11 -4
  2. package/assets/fonts/fontawesome6/fa-brands-400.ttf +0 -0
  3. package/assets/fonts/fontawesome6/fa-brands-400.woff2 +0 -0
  4. package/assets/fonts/fontawesome6/fa-regular-400.ttf +0 -0
  5. package/assets/fonts/fontawesome6/fa-regular-400.woff2 +0 -0
  6. package/assets/fonts/fontawesome6/fa-solid-900.ttf +0 -0
  7. package/assets/fonts/fontawesome6/fa-solid-900.woff2 +0 -0
  8. package/assets/fonts/fontawesome6/fa-v4compatibility.ttf +0 -0
  9. package/assets/fonts/fontawesome6/fa-v4compatibility.woff2 +0 -0
  10. package/assets/stylesheets/alchemy_icons.scss +68 -0
  11. package/assets/stylesheets/alchemy_svg.scss +9 -0
  12. package/assets/stylesheets/chimera/mediafield.less +1 -2
  13. package/assets/stylesheets/element/alchemy_file.scss +95 -0
  14. package/assets/stylesheets/fontawesome6/_animated.scss +153 -0
  15. package/assets/stylesheets/fontawesome6/_bordered-pulled.scss +20 -0
  16. package/assets/stylesheets/fontawesome6/_core.scss +33 -0
  17. package/assets/stylesheets/fontawesome6/_fixed-width.scss +7 -0
  18. package/assets/stylesheets/fontawesome6/_functions.scss +57 -0
  19. package/assets/stylesheets/fontawesome6/_icons.scss +9 -0
  20. package/assets/stylesheets/fontawesome6/_list.scss +18 -0
  21. package/assets/stylesheets/fontawesome6/_mixins.scss +73 -0
  22. package/assets/stylesheets/fontawesome6/_rotated-flipped.scss +31 -0
  23. package/assets/stylesheets/fontawesome6/_screen-reader.scss +14 -0
  24. package/assets/stylesheets/fontawesome6/_shims.scss +2027 -0
  25. package/assets/stylesheets/fontawesome6/_sizing.scss +16 -0
  26. package/assets/stylesheets/fontawesome6/_stacked.scss +32 -0
  27. package/assets/stylesheets/fontawesome6/_variables.scss +4885 -0
  28. package/assets/stylesheets/fontawesome6/brands.scss +30 -0
  29. package/assets/stylesheets/fontawesome6/fontawesome.scss +21 -0
  30. package/assets/stylesheets/fontawesome6/regular.scss +26 -0
  31. package/assets/stylesheets/fontawesome6/solid.scss +26 -0
  32. package/assets/stylesheets/fontawesome6/v4-shims.scss +11 -0
  33. package/bootstrap.js +1 -0
  34. package/controller/media_files_controller.js +20 -0
  35. package/controller/media_gallery_chimera_controller.js +1 -0
  36. package/element/al_file.js +275 -0
  37. package/element/al_ico_element.js +17 -0
  38. package/element/al_svg.js +81 -0
  39. package/helper/media_helper.js +56 -10
  40. package/helper/widgets/image_widget.js +46 -0
  41. package/{lib/field_type → helper_field}/file_field_type.js +5 -3
  42. package/lib/media_types/image_media_type.js +34 -9
  43. package/model/media_file_model.js +9 -3
  44. package/model/media_raw_model.js +529 -529
  45. package/package.json +6 -6
  46. package/view/element/al_file.hwk +18 -0
  47. package/view/form/inputs/edit/file.hwk +8 -0
  48. package/assets/scripts/chimera/mediafield.js +0 -451
@@ -0,0 +1,30 @@
1
+ /*!
2
+ * Font Awesome Free 6.1.1 by @fontawesome - https://fontawesome.com
3
+ * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4
+ * Copyright 2022 Fonticons, Inc.
5
+ */
6
+ @import 'functions';
7
+ @import 'variables';
8
+
9
+ :root, :host {
10
+ --#{$fa-css-prefix}-font-brands: normal 400 1em/1 "Font Awesome 6 Brands";
11
+ }
12
+
13
+ @font-face {
14
+ font-family: 'Font Awesome 6 Brands';
15
+ font-style: normal;
16
+ font-weight: 400;
17
+ font-display: $fa-font-display;
18
+ src: url('#{$fa-font-path}/fa-brands-400.woff2') format('woff2'),
19
+ url('#{$fa-font-path}/fa-brands-400.ttf') format('truetype');
20
+ }
21
+
22
+ .fab,
23
+ .#{$fa-css-prefix}-brands {
24
+ font-family: 'Font Awesome 6 Brands';
25
+ font-weight: 400;
26
+ }
27
+
28
+ @each $name, $icon in $fa-brand-icons {
29
+ .#{$fa-css-prefix}-#{$name}:before { content: unquote("\"#{ $icon }\""); }
30
+ }
@@ -0,0 +1,21 @@
1
+ /*!
2
+ * Font Awesome Free 6.1.1 by @fontawesome - https://fontawesome.com
3
+ * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4
+ * Copyright 2022 Fonticons, Inc.
5
+ */
6
+ // Font Awesome core compile (Web Fonts-based)
7
+ // -------------------------
8
+
9
+ @import 'functions';
10
+ @import 'variables';
11
+ @import 'mixins';
12
+ @import 'core';
13
+ @import 'sizing';
14
+ @import 'fixed-width';
15
+ @import 'list';
16
+ @import 'bordered-pulled';
17
+ @import 'animated';
18
+ @import 'rotated-flipped';
19
+ @import 'stacked';
20
+ @import 'icons';
21
+ @import 'screen-reader';
@@ -0,0 +1,26 @@
1
+ /*!
2
+ * Font Awesome Free 6.1.1 by @fontawesome - https://fontawesome.com
3
+ * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4
+ * Copyright 2022 Fonticons, Inc.
5
+ */
6
+ @import 'functions';
7
+ @import 'variables';
8
+
9
+ :root, :host {
10
+ --#{$fa-css-prefix}-font-regular: normal 400 1em/1 "#{ $fa-style-family }";
11
+ }
12
+
13
+ @font-face {
14
+ font-family: 'Font Awesome 6 Free';
15
+ font-style: normal;
16
+ font-weight: 400;
17
+ font-display: $fa-font-display;
18
+ src: url('#{$fa-font-path}/fa-regular-400.woff2') format('woff2'),
19
+ url('#{$fa-font-path}/fa-regular-400.ttf') format('truetype');
20
+ }
21
+
22
+ .far,
23
+ .#{$fa-css-prefix}-regular {
24
+ font-family: 'Font Awesome 6 Free';
25
+ font-weight: 400;
26
+ }
@@ -0,0 +1,26 @@
1
+ /*!
2
+ * Font Awesome Free 6.1.1 by @fontawesome - https://fontawesome.com
3
+ * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4
+ * Copyright 2022 Fonticons, Inc.
5
+ */
6
+ @import 'functions';
7
+ @import 'variables';
8
+
9
+ :root, :host {
10
+ --#{$fa-css-prefix}-font-solid: normal 900 1em/1 "#{ $fa-style-family }";
11
+ }
12
+
13
+ @font-face {
14
+ font-family: 'Font Awesome 6 Free';
15
+ font-style: normal;
16
+ font-weight: 900;
17
+ font-display: $fa-font-display;
18
+ src: url('#{$fa-font-path}/fa-solid-900.woff2') format('woff2'),
19
+ url('#{$fa-font-path}/fa-solid-900.ttf') format('truetype');
20
+ }
21
+
22
+ .fas,
23
+ .#{$fa-css-prefix}-solid {
24
+ font-family: 'Font Awesome 6 Free';
25
+ font-weight: 900;
26
+ }
@@ -0,0 +1,11 @@
1
+ /*!
2
+ * Font Awesome Free 6.1.1 by @fontawesome - https://fontawesome.com
3
+ * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
4
+ * Copyright 2022 Fonticons, Inc.
5
+ */
6
+ // V4 shims compile (Web Fonts-based)
7
+ // -------------------------
8
+
9
+ @import 'functions';
10
+ @import 'variables';
11
+ @import 'shims';
package/bootstrap.js CHANGED
@@ -40,6 +40,7 @@ alchemy.createDir(options.cache);
40
40
  Router.get('Media::static', /\/media\/static\/(.*)*/, 'MediaFile#serveStatic');
41
41
  Router.get('Media::image', options.url + '/{id}', 'MediaFile#image');
42
42
 
43
+ Router.get('MediaFile#data', '/media/data/{[MediaFile._id]id}', 'MediaFile#data');
43
44
  Router.get('MediaFile#info', '/media/info', 'MediaFile#info');
44
45
 
45
46
  // Allow dummy extensions
@@ -312,6 +312,26 @@ MediaFiles.setAction(function uploadsingle(conduit) {
312
312
  });
313
313
  });
314
314
 
315
+ /**
316
+ * Get the file data
317
+ *
318
+ * @author Jelle De Loecker <jelle@develry.be>
319
+ * @since 0.5.1
320
+ * @version 0.5.1
321
+ *
322
+ * @param {Conduit} conduit
323
+ * @param {Document.MediaFile} media_file
324
+ */
325
+ MediaFiles.setAction(function data(conduit, media_file) {
326
+ conduit.setHeader('cache-control', 'public, max-age=3600, must-revalidate');
327
+
328
+ conduit.end({
329
+ name : media_file.name,
330
+ alt : media_file.alt,
331
+ title : media_file.title
332
+ });
333
+ });
334
+
315
335
  /**
316
336
  * Get info on a file
317
337
  *
@@ -2,6 +2,7 @@
2
2
  if (!alchemy.plugins.chimera) {
3
3
  return;
4
4
  }
5
+ return;
5
6
 
6
7
  /**
7
8
  * The Media Gallery Gallery Controller class
@@ -0,0 +1,275 @@
1
+ /**
2
+ * The al-image custom element
3
+ *
4
+ * @author Jelle De Loecker <jelle@elevenways.be>
5
+ * @since 0.6.0
6
+ * @version 0.6.0
7
+ */
8
+ const AlFile = Function.inherits('Alchemy.Element.App', 'AlFile');
9
+
10
+ /**
11
+ * The template code
12
+ *
13
+ * @author Jelle De Loecker <jelle@elevenways.be>
14
+ * @since 0.6.0
15
+ * @version 0.6.0
16
+ */
17
+ AlFile.setTemplateFile('element/al_file');
18
+
19
+ /**
20
+ * The stylesheet to load for this element
21
+ *
22
+ * @author Jelle De Loecker <jelle@elevenways.be>
23
+ * @since 0.6.0
24
+ * @version 0.6.0
25
+ */
26
+ AlFile.setStylesheetFile('element/alchemy_file');
27
+
28
+ /**
29
+ * Getter for the drop target
30
+ *
31
+ * @author Jelle De Loecker <jelle@elevenways.be>
32
+ * @since 0.6.2
33
+ * @version 0.6.2
34
+ */
35
+ AlFile.addElementGetter('drop_target', '.al-file-drop-target');
36
+
37
+ /**
38
+ * Getter for the file input
39
+ *
40
+ * @author Jelle De Loecker <jelle@elevenways.be>
41
+ * @since 0.2.0
42
+ * @version 0.2.0
43
+ */
44
+ AlFile.addElementGetter('file_input', '.al-file-input');
45
+
46
+ /**
47
+ * Getter for the preview
48
+ *
49
+ * @author Jelle De Loecker <jelle@elevenways.be>
50
+ * @since 0.2.0
51
+ * @version 0.2.0
52
+ */
53
+ AlFile.addElementGetter('preview_element', '.al-file-preview');
54
+
55
+ /**
56
+ * Getter for the remove button
57
+ *
58
+ * @author Jelle De Loecker <jelle@elevenways.be>
59
+ * @since 0.6.2
60
+ * @version 0.6.2
61
+ */
62
+ AlFile.addElementGetter('remove_button', '.al-file-remove');
63
+
64
+ /**
65
+ * Getter for the uploading-icon
66
+ *
67
+ * @author Jelle De Loecker <jelle@elevenways.be>
68
+ * @since 0.6.2
69
+ * @version 0.6.2
70
+ */
71
+ AlFile.addElementGetter('icon_uploading', '.uploading-icon');
72
+
73
+ /**
74
+ * Getter for the empty-icon
75
+ *
76
+ * @author Jelle De Loecker <jelle@elevenways.be>
77
+ * @since 0.6.2
78
+ * @version 0.6.2
79
+ */
80
+ AlFile.addElementGetter('icon_empty', '.empty-icon');
81
+
82
+ /**
83
+ * Set the value
84
+ *
85
+ * @author Jelle De Loecker <jelle@elevenways.be>
86
+ * @since 0.6.0
87
+ * @version 0.6.2
88
+ */
89
+ AlFile.setAttribute('value', null, function setValue(value) {
90
+
91
+ if (value == null) {
92
+ value = '';
93
+ }
94
+
95
+ if (this.remove_button) {
96
+ this.remove_button.hidden = !value;
97
+ }
98
+
99
+ if (this.icon_empty) {
100
+ this.icon_empty.hidden = !!value;
101
+ }
102
+
103
+ this.updatePreview(value);
104
+ return value;
105
+ });
106
+
107
+ /**
108
+ * Update the preview image
109
+ *
110
+ * @author Jelle De Loecker <jelle@elevenways.be>
111
+ * @since 0.6.0
112
+ * @version 0.6.0
113
+ */
114
+ AlFile.setMethod(function updatePreview(value) {
115
+
116
+ if (arguments.length == 0) {
117
+ value = this.value;
118
+ }
119
+
120
+ if (this.preview_element) {
121
+ Hawkejs.removeChildren(this.preview_element);
122
+
123
+ if (value) {
124
+ let img = this.createElement('img');
125
+ img.setAttribute('src', '/media/thumbnail/' + value);
126
+ img.setAttribute('srcset', '/media/thumbnail/' + value + '?dpr=2 2x');
127
+
128
+ this.preview_element.append(img);
129
+ }
130
+ }
131
+ });
132
+
133
+ /**
134
+ * Upload the file
135
+ *
136
+ * @author Jelle De Loecker <jelle@elevenways.be>
137
+ * @since 0.6.0
138
+ * @version 0.6.2
139
+ */
140
+ AlFile.setMethod(async function uploadFile(config) {
141
+
142
+ let file = config.file,
143
+ filename = config.filename,
144
+ format = config.format;
145
+
146
+ this.classList.add('uploading');
147
+
148
+ let form_data = new FormData(),
149
+ url = this.dataset.uploadUrl;
150
+
151
+ if (!url) {
152
+ url = '/media/upload';
153
+ }
154
+
155
+ form_data.append('uploaded_file', file);
156
+ form_data.append('filename', filename);
157
+
158
+ if (format) {
159
+ form_data.append('format', format);
160
+ }
161
+
162
+ let response;
163
+
164
+ try {
165
+ response = await Blast.fetch({
166
+ url : url,
167
+ post : form_data,
168
+ });
169
+ } catch (err) {
170
+ console.error('Failed to upload file:', err);
171
+ }
172
+
173
+ this.classList.remove('uploading');
174
+
175
+ if (!response || !response.files || !response.files[0]) {
176
+ return;
177
+ }
178
+
179
+ let uploaded_file = response.files[0];
180
+
181
+ this.value = uploaded_file.id;
182
+
183
+ // uploaded_file.name
184
+ // uploaded_file.media_raw_id
185
+ });
186
+
187
+ /**
188
+ * Added to the DOM for the first time
189
+ *
190
+ * @author Jelle De Loecker <jelle@elevenways.be>
191
+ * @since 0.6.0
192
+ * @version 0.6.2
193
+ */
194
+ AlFile.setMethod(function introduced() {
195
+
196
+ const that = this;
197
+
198
+ this.addEventListener('dragenter', e => {
199
+ e.preventDefault();
200
+ });
201
+
202
+ this.addEventListener('dragover', e => {
203
+ this.classList.add('dropping');
204
+ e.preventDefault();
205
+ });
206
+
207
+ this.addEventListener('dragend', e => {
208
+ this.classList.remove('dropping');
209
+ });
210
+
211
+ this.addEventListener('dragleave', e => {
212
+ this.classList.remove('dropping');
213
+ });
214
+
215
+ this.addEventListener('drop', e => {
216
+ this.classList.remove('dropping');
217
+ this.classList.add('dropped');
218
+
219
+ e.preventDefault();
220
+
221
+ let file = e.dataTransfer.files[0];
222
+
223
+ this.uploadFile({
224
+ file : file,
225
+ filename : file.name,
226
+ format : null,
227
+ });
228
+ });
229
+
230
+ this.updatePreview();
231
+
232
+ this.file_input.addEventListener('change', e => {
233
+
234
+ this.classList.remove('dropping');
235
+ this.classList.add('dropped');
236
+
237
+ this.uploadFile({
238
+ file : this.file_input.files[0],
239
+ filename : this.file_input.files[0].name,
240
+ format : null,
241
+ });
242
+ });
243
+
244
+ this.remove_button.addEventListener('click', e => {
245
+ this.value = null;
246
+ });
247
+
248
+ });
249
+
250
+ /**
251
+ * Get the content for hawkejs
252
+ *
253
+ * @author Jelle De Loecker <jelle@elevenways.be>
254
+ * @since 0.6.0
255
+ * @version 0.6.0
256
+ */
257
+ AlFile.setMethod(function _getContent(callback) {
258
+
259
+ var that = this,
260
+ src = this.getAttribute('src');
261
+
262
+ this.viewRender.helpers.Alchemy.getResource({name: 'MediaFile#info', params: {path: src}}, function gotResult(err, info) {
263
+
264
+ if (err) {
265
+ return callback(err);
266
+ }
267
+
268
+ console.log('Size:', info);
269
+
270
+ that.innerHTML = '<img class="final" src="/media/static/' + src + '?width=50%25" width=' + info.width + ' height=' + info.height +' style="width:400px">'
271
+ + '<img class="placeholder" src="/media/static/' + src + '?width=20px">';
272
+
273
+ callback(null);
274
+ });
275
+ });
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The al-ico element
3
+ *
4
+ * @author Jelle De Loecker <jelle@elevenways.be>
5
+ * @since 0.6.0
6
+ * @version 0.6.0
7
+ */
8
+ const Icon = Function.inherits('Alchemy.Element', 'AlIco');
9
+
10
+ /**
11
+ * The stylesheet to load for this element
12
+ *
13
+ * @author Jelle De Loecker <jelle@elevenways.be>
14
+ * @since 0.6.0
15
+ * @version 0.6.0
16
+ */
17
+ Icon.setStylesheetFile('alchemy_icons');
@@ -0,0 +1,81 @@
1
+ /**
2
+ * The al-svg element
3
+ *
4
+ * @author Jelle De Loecker <jelle@elevenways.be>
5
+ * @since 0.5.1
6
+ * @version 0.5.1
7
+ */
8
+ const Svg = Function.inherits('Alchemy.Element', 'AlSvg');
9
+
10
+ /**
11
+ * The stylesheet to load for this element
12
+ *
13
+ * @author Jelle De Loecker <jelle@elevenways.be>
14
+ * @since 0.5.1
15
+ * @version 0.5.1
16
+ */
17
+ Svg.setStylesheetFile('alchemy_svg');
18
+
19
+ /**
20
+ * The location of the svg
21
+ *
22
+ * @author Jelle De Loecker <jelle@elevenways.be>
23
+ * @since 0.5.1
24
+ * @version 0.5.1
25
+ */
26
+ Svg.setAttribute('src');
27
+
28
+ /**
29
+ * Get the contents of this SVG
30
+ *
31
+ * @author Jelle De Loecker <jelle@elevenways.be>
32
+ * @since 0.5.1
33
+ * @version 0.5.1
34
+ */
35
+ Svg.setMethod(async function injectSvg() {
36
+
37
+ let contents,
38
+ src = this.src;
39
+
40
+ if (!src.endsWith('.svg')) {
41
+ src += '.svg';
42
+ }
43
+
44
+ // Remove all the content
45
+ Hawkejs.removeChildren(this);
46
+
47
+ if (Blast.isNode) {
48
+ let path = await alchemy.findImagePath(src);
49
+
50
+ if (path) {
51
+ let file = new Classes.Alchemy.Inode.File(path);
52
+ contents = await file.readString();
53
+ } else {
54
+ contents = '';
55
+ }
56
+ } else {
57
+ contents = await Blast.fetch('/media/static/' + src, {cache: 60 * 60 * 1000});
58
+ }
59
+
60
+ this.innerHTML = contents;
61
+
62
+ if (this._resolve_me_too) {
63
+ this._resolve_me_too.resolve();
64
+ }
65
+ });
66
+
67
+ /**
68
+ * Cached render method for Hawkejs
69
+ *
70
+ * @author Jelle De Loecker <jelle@elevenways.be>
71
+ * @since 0.5.1
72
+ * @version 0.5.1
73
+ */
74
+ Hawkejs.setCachedMethod(Svg, Hawkejs.RENDER_CONTENT, function doRender() {
75
+
76
+ if (!this.src) {
77
+ return;
78
+ }
79
+
80
+ return this.injectSvg();
81
+ });
@@ -93,7 +93,7 @@ Media.setStatic(function loadImagesBasedOnSize() {
93
93
  *
94
94
  * @author Jelle De Loecker <jelle@develry.be>
95
95
  * @since 0.5.0
96
- * @version 0.5.0
96
+ * @version 0.6.2
97
97
  *
98
98
  * @param {Element} element The element to apply to
99
99
  * @param {String} image The image identifier
@@ -103,13 +103,12 @@ Media.setStatic(function loadImagesBasedOnSize() {
103
103
  */
104
104
  Media.setMethod(function applyDirective(element, image, options) {
105
105
 
106
- var srcset,
106
+ let record,
107
107
  height = element.getAttribute('height'),
108
- clone,
109
- width = element.getAttribute('width'),
110
- url;
108
+ width = element.getAttribute('width');
111
109
 
112
110
  if (image && typeof image == 'object' && image._id) {
111
+ record = image;
113
112
  image = image._id;
114
113
  }
115
114
 
@@ -117,6 +116,12 @@ Media.setMethod(function applyDirective(element, image, options) {
117
116
  options = {};
118
117
  }
119
118
 
119
+ let variables = element[Hawkejs.VARIABLES];
120
+
121
+ if (!options.route) {
122
+ options.route = variables?.['media-route'];
123
+ }
124
+
120
125
  if (width) {
121
126
  if (width.indexOf('%') > -1) {
122
127
  element.removeAttribute('width');
@@ -133,16 +138,57 @@ Media.setMethod(function applyDirective(element, image, options) {
133
138
  options.height = height;
134
139
  }
135
140
 
136
- url = this.imageUrl(image, options);
137
- clone = url.clone();
141
+ let url = this.imageUrl(image, options),
142
+ clone = url.clone();
143
+
138
144
  clone.addQuery('dpr', 2);
139
145
 
140
- srcset = clone + ' 2x';
146
+ let srcset = clone + ' 2x';
141
147
 
142
148
  // Set the source attribute
143
149
  element.setAttribute('src', url);
144
150
 
145
151
  element.setAttribute('srcset', srcset);
152
+
153
+ if (element.hasAttribute('alt')) {
154
+ return;
155
+ }
156
+
157
+ if (record && record.alt) {
158
+ element.setAttribute('alt', record.alt);
159
+ return;
160
+ }
161
+
162
+ if (!String(image).isHex()) {
163
+ return;
164
+ }
165
+
166
+ let pledge = new Pledge();
167
+
168
+ this.view.helpers.Alchemy.getResource({
169
+ name: 'MediaFile#data',
170
+ params: {
171
+ id: image
172
+ }
173
+ }, function gotResult(err, data) {
174
+
175
+ if (!err && data) {
176
+ if (data.alt) {
177
+ element.setAttribute('alt', data.alt);
178
+ } else {
179
+ element.setAttribute('alt', '');
180
+ }
181
+
182
+ if (data.title && !element.hasAttribute('title')) {
183
+ element.setAttribute('title', data.title);
184
+ }
185
+
186
+ }
187
+
188
+ pledge.resolve();
189
+ });
190
+
191
+ return pledge;
146
192
  });
147
193
 
148
194
  /**
@@ -168,7 +214,7 @@ Media.setMethod(function fileAnchor(file_id, options) {
168
214
  *
169
215
  * @author Jelle De Loecker <jelle@develry.be>
170
216
  * @since 0.2.0
171
- * @version 0.2.0
217
+ * @version 0.5.1
172
218
  *
173
219
  * @param {String} image_id
174
220
  *
@@ -184,7 +230,7 @@ Media.setMethod(function imageUrl(image_id, options) {
184
230
  options = {};
185
231
  }
186
232
 
187
- if (String(image_id).isObjectId()) {
233
+ if (String(image_id).isHex()) {
188
234
 
189
235
  if (options.route) {
190
236
  routeName = options.route;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * The Widget Image class
3
+ *
4
+ * @constructor
5
+ *
6
+ * @author Jelle De Loecker <jelle@elevenways.be>
7
+ * @since 0.1.0
8
+ * @version 0.1.0
9
+ *
10
+ * @param {Object} data
11
+ */
12
+ const Image = Function.inherits('Alchemy.Widget', 'Image');
13
+
14
+ /**
15
+ * Prepare the schema
16
+ *
17
+ * @author Jelle De Loecker <jelle@elevenways.be>
18
+ * @since 0.1.0
19
+ * @version 0.1.0
20
+ */
21
+ Image.constitute(function prepareSchema() {
22
+
23
+ this.schema.addField('image', 'File', {
24
+ widget_config_editable: true,
25
+ });
26
+ });
27
+
28
+ /**
29
+ * Populate the widget
30
+ *
31
+ * @author Jelle De Loecker <jelle@elevenways.be>
32
+ * @since 0.1.0
33
+ * @version 0.1.0
34
+ *
35
+ * @param {HTMLElement} widget
36
+ */
37
+ Image.setMethod(function populateWidget() {
38
+
39
+ let img = this.createElement('img');
40
+
41
+ this.hawkejs_renderer.helpers.Media.applyDirective(img, this.config.image);
42
+
43
+ populateWidget.super.call(this);
44
+
45
+ this.widget.append(img);
46
+ });