From 3dee85226f1fa6a29a03d598c8c11be1c5dba4ca Mon Sep 17 00:00:00 2001 From: John Martin Date: Tue, 15 Oct 2013 15:10:09 +0100 Subject: [PATCH] [#1262] First working version of the JS module for image uploading --- .../base/javascript/modules/image-upload.js | 147 ++++++++++++++++++ ckan/public/base/javascript/resource.config | 1 + ckan/public/base/less/forms.less | 34 ++++ ckan/templates/group/snippets/group_form.html | 10 +- ckan/templates/macros/form.html | 27 ++++ .../snippets/organization_form.html | 9 +- 6 files changed, 211 insertions(+), 17 deletions(-) create mode 100644 ckan/public/base/javascript/modules/image-upload.js diff --git a/ckan/public/base/javascript/modules/image-upload.js b/ckan/public/base/javascript/modules/image-upload.js new file mode 100644 index 00000000000..69ca8f93c05 --- /dev/null +++ b/ckan/public/base/javascript/modules/image-upload.js @@ -0,0 +1,147 @@ +/* Image Upload + * + * + * Options + * - id: what's the id of the context? + */ +this.ckan.module('image-upload', function($, _) { + return { + /* options object can be extended using data-module-* attributes */ + options: { + is_url: true, + has_image: false, + i18n: { + upload: _('From computer'), + url: _('From web'), + remove: _('Remove'), + label: _('Upload image'), + label_url: _('Image URL'), + remove_tooltip: _('Reset this') + }, + template: [ + '' + ].join("\n") + }, + + state: { + attached: 1, + blank: 2, + web: 3 + }, + + /* Initialises the module setting up elements and event listeners. + * + * Returns nothing. + */ + initialize: function () { + $.proxyAll(this, /_on/); + var options = this.options; + + // firstly setup the fields + this.input = $('input[name="image_upload"]', this.el); + this.field_url = $('input[name="image_url"]', this.el).parents('.control-group'); + this.field_image = this.input.parents('.control-group'); + + var checkbox = $('input[name="clear_upload"]', this.el); + if (checkbox.length > 0) { + options.has_image = true; + checkbox.parents('.control-group').remove(); + } + + this.field_clear = $('') + .appendTo(this.el); + + this.button_url = $(' '+this.i18n('url')+'') + .on('click', this._onFromWeb) + .insertAfter(this.input); + + this.button_upload = $(''+this.i18n('upload')+'') + .insertAfter(this.input); + + this.button_remove = $('') + .text(this.i18n('remove')) + .on('click', this._onRemove) + .insertAfter(this.button_upload); + + $('') + .prop('title', this.i18n('remove_tooltip')) + .on('click', this._onRemove) + .insertBefore($('input', this.field_url)); + + $('label[for="field-image-upload"]').text(this.i18n('label')); + + this.input + .on('mouseover', this._onInputMouseOver) + .on('mouseout', this._onInputMouseOut) + .on('change', this._onInputChange) + .css('width', this.button_upload.outerWidth()) + .hide(); + + this.fields = $('') + .add(this.button_remove) + .add(this.button_upload) + .add(this.button_url) + .add(this.input) + .add(this.field_url) + .add(this.field_image); + + if (options.is_url) { + this.changeState(this.state.web); + } else if (options.has_image) { + this.changeState(this.state.attached); + } else { + this.changeState(this.state.blank); + } + + }, + + changeState: function(state) { + this.fields.hide(); + if (state == this.state.blank) { + this.button_upload + .add(this.field_image) + .add(this.button_url) + .add(this.input) + .show(); + } else if (state == this.state.attached) { + this.button_remove + .add(this.field_image) + .show(); + } else if (state == this.state.web) { + this.field_url + .show(); + } + }, + + _onFromWeb: function() { + this.changeState(this.state.web); + $('input', this.field_url).focus(); + if (this.options.has_image) { + this.field_clear.val('true'); + } + }, + + _onRemove: function() { + this.changeState(this.state.blank); + $('input', this.field_url).val(''); + if (this.options.has_image) { + this.field_clear.val('true'); + } + }, + + _onInputChange: function() { + this.file_name = this.input.val(); + this.field_clear.val(''); + this.changeState(this.state.attached); + }, + + _onInputMouseOver: function() { + this.button_upload.addClass('hover'); + }, + + _onInputMouseOut: function() { + this.button_upload.removeClass('hover'); + } + + } +}); diff --git a/ckan/public/base/javascript/resource.config b/ckan/public/base/javascript/resource.config index b1a7302d9e8..564da811a6e 100644 --- a/ckan/public/base/javascript/resource.config +++ b/ckan/public/base/javascript/resource.config @@ -38,6 +38,7 @@ ckan = modules/table-toggle-more.js modules/dataset-visibility.js modules/media-grid.js + modules/image-upload.js main = apply_html_class diff --git a/ckan/public/base/less/forms.less b/ckan/public/base/less/forms.less index 289439c291a..2bfc1a2d492 100644 --- a/ckan/public/base/less/forms.less +++ b/ckan/public/base/less/forms.less @@ -670,3 +670,37 @@ textarea { .box-shadow(none); } } + +.js .image-upload { + #field-image-upload { + cursor: pointer; + position: absolute; + z-index: 1; + .opacity(0); + } + .controls { + position: relative; + } + .btn { + position: relative; + top: 0; + margin-right: 10px; + &.hover { + color: @grayDark; + text-decoration: none; + background-position: 0 -15px; + .transition(background-position .1s linear); + } + } + .btn-remove-url { + position: absolute; + margin-right: 0; + top: 4px; + right: 5px; + padding: 0 4px; + .border-radius(100px); + .icon-remove { + margin-right: 0; + } + } +} diff --git a/ckan/templates/group/snippets/group_form.html b/ckan/templates/group/snippets/group_form.html index 322f9ebff8a..cd19912d66b 100644 --- a/ckan/templates/group/snippets/group_form.html +++ b/ckan/templates/group/snippets/group_form.html @@ -19,15 +19,7 @@ {{ form.markdown('description', label=_('Description'), id='field-description', placeholder=_('A little information about my group...'), value=data.description, error=errors.description) }} - {{ form.input('image_url', label=_('Image URL'), id='field-image-url', placeholder=_('http://example.com/my-image.jpg'), value=data.image_url, error=errors.image_url, classes=['control-full']) }} - - - {% if h.uploads_enabled() %} - {{ form.input('image_upload', label=_('Image Upload'), id='field-image-upload', type='file', placeholder='', value=data.image_url, error='', classes=['control-full']) }} - {% if data.image_url and not data.image_url.startswith('http') %} - {{ form.checkbox('clear_upload', label=_('Clear Upload'), id='field-clear-upload', value='true', error='', classes=['control-full']) }} - {% endif %} - {% endif %} + {{ form.image_upload(data, errors, image_url=c.group_dict.image_display_url, is_upload_enabled=h.uploads_enabled()) }} {% endblock %} diff --git a/ckan/templates/macros/form.html b/ckan/templates/macros/form.html index 497dea6bf02..7dc044ccca2 100644 --- a/ckan/templates/macros/form.html +++ b/ckan/templates/macros/form.html @@ -395,3 +395,30 @@

{% endmacro %} +{# +Builds a file upload for input + +Example + {% import 'macros/form.html' as form %} + {{ form.image_upload(data, errors, is_upload_enabled=true) }} + +#} +{% macro image_upload(data, errors, image_url=false, is_upload_enabled=false, placeholder=false) %} + {% set placeholder = placeholder if placeholder else _('http://example.com/my-image.jpg') %} + {% set has_uploaded_data = data.image_url and not data.image_url.startswith('http') %} + {% set is_url = data.image_url and data.image_url.startswith('http') %} + + {% if is_upload_enabled %}
{% endif %} + + {{ input('image_url', label=_('Image URL'), id='field-image-url', placeholder=placeholder, value=data.image_url, error=errors.image_url, classes=['control-full']) }} + + {% if is_upload_enabled %} + {{ input('image_upload', label=_('Image Upload'), id='field-image-upload', type='file', placeholder='', value='', error='', classes=['control-full']) }} + {% if has_uploaded_data %} + {{ checkbox('clear_upload', label=_('Clear Upload'), id='field-clear-upload', value='true', error='', classes=['control-full']) }} + {% endif %} + {% endif %} + + {% if is_upload_enabled %}
{% endif %} + +{% endmacro %} diff --git a/ckan/templates/organization/snippets/organization_form.html b/ckan/templates/organization/snippets/organization_form.html index 0a2134e89f7..0b97b958d38 100644 --- a/ckan/templates/organization/snippets/organization_form.html +++ b/ckan/templates/organization/snippets/organization_form.html @@ -19,14 +19,7 @@ {{ form.markdown('description', label=_('Description'), id='field-description', placeholder=_('A little information about my organization...'), value=data.description, error=errors.description) }} - {{ form.input('image_url', label=_('Image URL'), id='field-image-url', placeholder=_('http://example.com/my-image.jpg'), value=data.image_url, error=errors.image_url, classes=['control-full']) }} - - {% if h.uploads_enabled() %} - {{ form.input('image_upload', label=_('Image Upload'), id='field-image-upload', type='file', placeholder='', value=data.image_url, error='', classes=['control-full']) }} - {% if data.image_url and not data.image_url.startswith('http') %} - {{ form.checkbox('clear_upload', label=_('Clear Upload'), id='field-clear-upload', value='true', error='', classes=['control-full']) }} - {% endif %} - {% endif %} + {{ form.image_upload(data, errors, image_url=c.group_dict.image_display_url, is_upload_enabled=h.uploads_enabled()) }} {% endblock %}