Changes for page Attachments

Last modified by Ludovic Dubost on 2024/07/22 15:50

From version 2.1
edited by Thomas Mortagne
on 2014/09/29 12:35
Change comment: Install extension [org.xwiki.platform:xwiki-platform-attachment-ui-6.2]
To version 17.1
edited by Ludovic Dubost
on 2024/07/22 15:50
Change comment: Install extension [org.xwiki.platform:xwiki-platform-attachment-ui/16.5.0]

Summary

Details

Page properties
Author
... ... @@ -1,1 +1,1 @@
1 -xwiki:XWiki.ThomasMortagne
1 +xwiki:XWiki.ludovic
Content
... ... @@ -1,16 +1,23 @@
1 1  {{velocity output="false"}}
2 +#set ($translationPrefix = 'xe.attachmentSelector')
3 +
2 2  #if ($request.xaction == 'postUpload')
3 3   #set ($targetDocument = $xwiki.getDocument($request.get('docname')))
4 4   #set ($targetAttachDocument = $xwiki.getDocument($request.get('targetdocname')))
5 5  
6 6   #set ($fieldname = $request.get('fieldname'))
9 + #set ($comment = $services.localization.render("${translationPrefix}.postUpload.comment", [$fieldname]))
7 7   #set ($docAction = $request.get('docAction'))
8 8   #set ($attachmentList = $targetAttachDocument.getAttachmentList())
9 9   #if ($attachmentList && $attachmentList.size() > 0)
10 - #set ($sortedAttachments = $sorttool.sort($attachmentList, 'date:desc'))
13 + #set ($sortedAttachments = $collectiontool.sort($attachmentList, 'date:desc'))
11 11   #set ($lastAttachment = $sortedAttachments.get(0))
12 12   #end
13 - $response.sendRedirect($targetDocument.getURL($docAction, "$!{fieldname}=$!{lastAttachment.filename}&form_token=$!{escapetool.url($request.get('form_token'))}"))
16 + $response.sendRedirect($targetDocument.getURL($docAction, $escapetool.url({
17 + $fieldname: $lastAttachment.filename,
18 + 'comment': $comment,
19 + 'form_token': $request.form_token
20 + })))
14 14   #stop
15 15  #end
16 16  {{/velocity}}
... ... @@ -19,7 +19,6 @@
19 19  ##
20 20  ## Macros
21 21  ##
22 -#set ($translationPrefix = 'xe.attachmentSelector')
23 23  #set ($attachmentPickerDocName = 'XWiki.AttachmentSelector')
24 24  
25 25  $xwiki.ssx.use($attachmentPickerDocName)
... ... @@ -39,11 +39,14 @@
39 39   #end
40 40   (% class="gallery" %)(((
41 41   ## Only display the upload form if they have edit permission on targetAttachDocument
42 - #if ($xwiki.hasAccessLevel('edit',$xcontext.user,${targetAttachDocument.fullName}))
43 - #attachmentPicker_displayUploadForm($targetDocument, $targetAttachDocument, $options)
44 - #end
48 + #attachmentPicker_displayUploadForm($targetDocument, $targetAttachDocument, $options)
45 45   #attachmentPicker_displayAttachmentGalleryEmptyValue($targetDocument, $targetAttachDocument, $options, $currentValue)
46 - #set ($sortedAttachments = $sorttool.sort($targetAttachDocument.getAttachmentList(), "${options.sortAttachmentsBy}") )
50 + #if ("$!services.temporaryAttachments" != '')
51 + #set ($unsortedAttachments = $services.temporaryAttachments.listAllAttachments($targetAttachDocument))
52 + #set ($sortedAttachments = $collectiontool.sort($unsortedAttachments, "${options.sortAttachmentsBy}"))
53 + #else
54 + #set ($sortedAttachments = $collectiontool.sort($targetAttachDocument.getAttachmentList(), "${options.sortAttachmentsBy}") )
55 + #end
47 47   #foreach ($attachment in $sortedAttachments)
48 48   #set ($extension = $attachment.getFilename())
49 49   #set ($extension = $extension.substring($mathtool.add($extension.lastIndexOf('.'), 1)).toLowerCase())
... ... @@ -63,18 +63,46 @@
63 63   * @param $currentValue the currently selected file, used for determining if the box should be highlighted as the current value
64 64   *#
65 65  #macro (attachmentPicker_displayAttachmentBox $attachment $targetDocument $targetAttachDocument, $options $currentValue)
66 - #if ($options.displayImage && $attachment.isImage())
67 - #set ($cssClass = 'gallery_image')
75 + #set ($hasTemporaryAttachment = "$!services.temporaryAttachments" != '')
76 + #set ($canEdit = $xwiki.hasAccessLevel('edit', $xcontext.user, ${targetAttachDocument.fullName}))
77 + #set ($isTemporaryAttachment = false)
78 + #if(!$hasTemporaryAttachment)
79 + #set ($canDeleteAttachment = $canEdit)
68 68   #else
69 - #set ($cssClass = '')
81 + #set ($isTemporaryAttachment = $services.temporaryAttachments.temporaryAttachmentExists($attachment))
82 + ## TODO: Update once it is made possible to delete temporary attachments (see XWIKI-20225).
83 + #set ($canDeleteAttachment = !$isTemporaryAttachment && $canEdit)
70 70   #end
71 - #attachmentPicker_displayStartFrame({'value' : $attachment.filename, 'text' : $attachment.filename, 'cssClass' : "$!{cssClass}"} $currentValue)
85 + #set ($cssClasses = [])
86 + #if ($options.displayImage && $attachment.isImage())
87 + #set ($discard = $cssClasses.add('gallery_image'))
88 + #end
89 + #if ($isTemporaryAttachment)
90 + #set ($discard = $cssClasses.add('temporary_attachment'))
91 + #end
92 + #attachmentPicker_displayStartFrame({'value' : $attachment.filename, 'text' : $attachment.filename, 'cssClass' : "${stringtool.join($cssClasses, ' ')}"} $currentValue)
72 72   #attachmentPicker_displayAttachmentDetails($attachment $options)
73 73   #set ($returnURL = $escapetool.url($doc.getURL('view', $request.queryString)))
74 74   #set ($deleteURL = $targetAttachDocument.getAttachmentURL($attachment.filename, 'delattachment', "xredirect=${returnURL}&form_token=$!{services.csrf.getToken()}") )
75 75   #set ($viewURL = $targetAttachDocument.getAttachmentURL($attachment.filename) )##{'name' : 'download', 'url' : $viewURL, 'rel' : '__blank'}
76 - #set ($selectURL = $targetDocument.getURL(${options.get('docAction')}, "${options.get('classname')}_${options.get('object')}_${options.get('property')}=${attachment.filename}&form_token=$!{services.csrf.getToken()}"))
77 - #attachmentPicker_displayEndFrame ([{'name' : 'select', 'url' : $selectURL}, {'name' : 'delete', 'url' : $deleteURL}])
97 + #set ($selectURL = $targetDocument.getURL(${options.get('docAction')}, $escapetool.url({
98 + "${options.get('classname')}_${options.get('object')}_${options.get('property')}": ${attachment.filename},
99 + 'form_token': $!{services.csrf.getToken()}
100 + })))
101 + ## Delete action is only proposed for users with the edit right on the document.
102 + ## If the temporary attachment is available, the delete action is only allowed for non-temporary attachments.
103 + #set ($attachmentActions = [{'name' : 'select', 'url' : $selectURL}])
104 + #if($canDeleteAttachment)
105 + #set ($discard = $attachmentActions.add({'name' : 'delete', 'url' : $deleteURL}))
106 + #end
107 + #define($additionalContent)
108 + #if ($isTemporaryAttachment)
109 + #set ($titleMessage = $services.localization.render('attachment.attachmentSelector.attachmentBox.temporaryAttachmentTitle'))
110 + #set ($titleMessage = $services.rendering.escape($titleMessage, 'xwiki/2.1'))
111 + (% title="$titleMessage" %)$services.icon.render('clock')(%%)
112 + #end
113 + #end
114 + #attachmentPicker_displayEndFrame ($attachmentActions $additionalContent)
78 78  #end
79 79  
80 80  #**
... ... @@ -86,7 +86,9 @@
86 86   *#
87 87  #macro (attachmentPicker_displayStartFrame $boxOptions $currentValue)
88 88   (% class="gallery_attachmentbox $!{boxOptions.cssClass} #if ("$!{boxOptions.value}" == $currentValue) current#{end}" %)(((
89 - (% class="gallery_attachmenttitle" title="$!{boxOptions.value}" %)((($boxOptions.text)))
126 + (% class="gallery_attachmenttitle" title="$services.rendering.escape($!{boxOptions.value}, 'xwiki/2.1')" %)(((
127 + $services.rendering.escape($boxOptions.text, 'xwiki/2.1')
128 + )))
90 90   (% class="gallery_attachmentframe" %)(((
91 91  #end
92 92  
... ... @@ -99,14 +99,19 @@
99 99   *#
100 100  #macro (attachmentPicker_displayAttachmentDetails $attachment $options)
101 101   #if ($attachment)
141 + ## Compute the attachment reference because there's no getter.
142 + #set ($attachmentReference = $services.model.createAttachmentReference($attachment.document.documentReference,
143 + $attachment.filename))
144 + #set ($attachmentStringReference = $services.rendering.escape($services.model.serialize($attachmentReference, 'default'), 'xwiki/2.1'))
102 102   #if ($attachment.isImage() && $options.displayImage)
103 - #set ($attachmentDocument = $attachment.getDocument())
104 -[[[[image:${attachmentDocument.fullName}@${attachment.filename}||width=160]]>>attach:${attachmentDocument.fullName}@${attachment.filename}||rel="lightbox[attachments]"]]
146 + ## We add the version to the query string in order to invalidate the cache when an image attachment is replaced.
147 + #set ($queryString = $escapetool.url({'version': $attachment.version}))
148 + [[[[image:${attachmentStringReference}||width=180 queryString="$queryString"]]>>attach:$attachmentStringReference]]
105 105   #else
106 - * (% class="mime" %){{html wiki=false clean=false}}#mimetypeimg($attachment.getMimeType().toLowerCase() $attachment.getFilename().toLowerCase()){{/html}}(%%) (% class="filename" %)$attachment.getFilename()(% %)
107 - * v$attachment.getVersion() (#dynamicsize($attachment.filesize))
150 + * (% class="mime" %){{html wiki=false clean=false}}#mimetypeimg($attachment.getMimeType().toLowerCase() $attachment.getFilename().toLowerCase()){{/html}}(%%) (% class="filename" %)$services.rendering.escape($attachment.getFilename(), 'xwiki/2.1')(% %)
151 + * v$attachment.getVersion() (#dynamicsize($attachment.longSize))
108 108   * $services.localization.render('core.viewers.attachments.author', [$!{xwiki.getUserName($attachment.author, false)}]) $services.localization.render('core.viewers.attachments.date', [$!{xwiki.formatDate($attachment.date, 'dd/MM/yyyy hh:mm')}])
109 - * (% class="buttonwrapper" %)[[${services.localization.render("${translationPrefix}.actions.download")}>>attach:${attachment.getDocument()}@${attachment.filename}||title="$services.localization.render("${translationPrefix}.actions.download")" rel="__blank" class="button"]](%%)
153 + * (% class="buttonwrapper" %)[[${services.localization.render("${translationPrefix}.actions.download")}>>attach:${attachmentStringReference}||title="$services.localization.render("${translationPrefix}.actions.download")" rel="__blank" class="button"]](%%)
110 110   #end
111 111   #end
112 112  #end
... ... @@ -123,8 +123,9 @@
123 123   * <dt>rel</dt>
124 124   * <dd>an optional parameter to be used in the "rel" HTML attribute; for example "__blank" can be used to open the link in a new tab/window</dd>
125 125   * </dl>
170 + * @param $additionalContent optional additional content that does not follow the structure of the actions
126 126   *#
127 -#macro (attachmentPicker_displayEndFrame $actions)
172 +#macro (attachmentPicker_displayEndFrame $actions $additionalContent)
128 128   )))## attachmentframe
129 129   (% class="gallery_actions" %)(((
130 130   #foreach ($action in $actions)
... ... @@ -131,6 +131,7 @@
131 131   #set( $actionname = $services.localization.render("${translationPrefix}.actions.${action.name}") )
132 132   [[${actionname}>>path:${action.url}||class="tool ${action.name}" title="${actionname}" #if($action.rel) rel="${action.rel}"#end]]##
133 133   #end
179 + $!additionalContent
134 134   )))## actions
135 135   )))## attachmentbox
136 136  #end
... ... @@ -154,7 +154,7 @@
154 154   #if (${options.rawfilter} != '')
155 155   <span class="xHint">$escapetool.xml($services.localization.render("${translationPrefix}.upload.hint", [${options.rawfilter}]))</span>
156 156   #end
157 - <input type="file" name="filepath" id="attachfile" class="attachment" size="30" title="$!{escapetool.xml($options.rawfilter)}"/>
203 + <input type="file" name="filepath" id="attachfile" class="noitems" title="$!{escapetool.xml($options.rawfilter)}"/>
158 158   <input type="hidden" name="xredirect" value="$xwiki.getDocument($attachmentPickerDocName).getURL('get', "xaction=postUpload&amp;docAction=$!{escapetool.url($options.get('docAction'))}&amp;targetdocname=$!{escapetool.url($targetAttachDocument.fullName)}&amp;docname=$!{escapetool.url($targetDocument.fullName)}&amp;fieldname=$!{escapetool.url($options.get('classname'))}_$!{escapetool.url($options.get('object'))}_$!{escapetool.url($options.get('property'))}&amp;form_token=$!{services.csrf.getToken()}")" />
159 159   <input type="hidden" name="docname" value="$!{escapetool.xml($targetDocument.fullName)}" />
160 160   <input type="hidden" name="classname" value="$!{escapetool.xml($options.get('classname'))}" />
... ... @@ -162,6 +162,27 @@
162 162   <input type="hidden" name="property" value="$!{escapetool.xml($options.get('property'))}" />
163 163   <input type="hidden" name="form_token" value="$!{services.csrf.getToken()}" />
164 164   </div>
211 + #if ("$!currentValue" != '' && $currentValue != $options.defaultValue)
212 + <div>
213 + <label>
214 + <input type="checkbox" name="filename" value="$!escapetool.xml($currentValue)"
215 + />$services.localization.render('attachmentSelector.replace',
216 + ["<strong>$!escapetool.xml($currentValue)</strong>"])
217 + </label>
218 + <span class="xHint">$escapetool.xml($services.localization.render('attachmentSelector.replace.hint'))</span>
219 + </div>
220 + #end
221 + #if ($xwiki.hasEditComment() && $options.versionSummary)
222 + <div>
223 + #if ($xwiki.isEditCommentFieldHidden())
224 + <input type="hidden" name="comment" value="$!escapetool.xml($request.comment)" />
225 + #else
226 + <label for="commentinput">$services.localization.render('core.comment')</label>
227 + <input type="text" name="comment" id="commentinput" value="$!escapetool.xml($request.comment)"
228 + title="$services.localization.render('core.comment.tooltip')" />
229 + #end
230 + </div>
231 + #end
165 165   <div class="buttons">
166 166   <span class="buttonwrapper">
167 167   <input type="submit" name="action_upload" class="button " value='$services.localization.render("${translationPrefix}.upload.submit")' title='$services.localization.render("${translationPrefix}.upload.submit")'/>
... ... @@ -205,11 +205,6 @@
205 205  
206 206  {{velocity}}
207 207  #if ($request.docname)
208 - ###if ($request.xpage == 'plain')
209 - ## ## IE6 + XHR + gzip compression = BOOM!
210 - ## ## This disables the automatic gzip compression
211 - ## $response.setContentType('multipart/formdata')
212 - ###end
213 213   #set ($targetDocument = $xwiki.getDocument($request.docname))
214 214   #if ($request.targetdocname)
215 215   ## Use the target document if it exists.
... ... @@ -258,7 +258,7 @@
258 258   #end
259 259   #set ($options = {
260 260   'classname' : ${request.get('classname')},
261 - 'object' : $!{mathtool.toInteger($request.object)},
323 + 'object' : $!{numbertool.toNumber($request.object).intValue()},
262 262   'property' : ${request.property},
263 263   'displayImage' : ${displayImage},
264 264   'docAction' : ${docAction},
... ... @@ -265,13 +265,16 @@
265 265   'defaultValue' : "$!{request.defaultValue}",
266 266   'rawfilter': "$!{rawfilter}",
267 267   'filter': ${filter},
268 - 'sortAttachmentsBy': ${sortAttachmentsBy}
330 + 'sortAttachmentsBy': ${sortAttachmentsBy},
331 + 'versionSummary': $request.versionSummary.equals('true')
269 269   })
270 270   $!targetDocument.use($targetDocument.getObject($options.classname, $options.object))##
271 271   #attachmentPicker_displayAttachmentGallery($targetDocument, $targetAttachDocument, $options)
272 272  
336 + #set ($cancelLinkName = $services.rendering.escape($services.rendering.escape($services.localization.render("${translationPrefix}.cancel"), 'xwiki/2.1'), 'xwiki/2.1'))
337 + #set ($cancelLinkTarget = $services.rendering.escape($services.model.serialize($targetDocument), 'xwiki/2.1'))
273 273   (% class="gallery_buttons buttons" %)(((
274 - (% class="buttonwrapper secondary" %)[[$services.localization.render("${translationPrefix}.cancel")>>$targetDocument||class="button secondary" id="attachment-picker-close"]]
339 + (% class="buttonwrapper secondary" %)[[$cancelLinkName>>$cancelLinkTarget||class="button secondary" id="attachment-picker-close"]]
275 275   )))
276 276  #end
277 277  {{/velocity}}
XWiki.JavaScriptExtension[0]
Code
... ... @@ -1,4 +1,66 @@
1 1  var XWiki = (function(XWiki) {
2 + function uploadTemporaryAttachment() {
3 + // Require jquery locally until we are able to fully migrate this code away from prototype.
4 + const form = this.property.up('form');
5 + require(['jquery'], function ($) {
6 + const data = new FormData();
7 + const uploadedFile = $('#attachfile')[0].files[0];
8 + const filenameCheckbox = $("#uploadAttachment input[name='filename']");
9 +
10 + // TODO: Fix replace currently selected checkbox (see XWIKI-20181).
11 + data.append('upload', uploadedFile);
12 + const notification = new XWiki.widgets.Notification(
13 + "$services.localization.render('xe.attachmentSelector.upload.inProgress')", 'inprogress');
14 + const params = {
15 + 'form_token': $(form).find('[name="form_token"]').val(),
16 + 'sheet': 'CKEditor.FileUploader',
17 + 'outputSyntax': 'plain'
18 + };
19 +
20 + // Update the name of the file with the name of the currently selected attachment if required.
21 + if (filenameCheckbox.prop('checked')) {
22 + params['filename'] = filenameCheckbox.val()
23 + }
24 +
25 + $.ajax({
26 + 'url': XWiki.currentDocument.getURL('get', new URLSearchParams(params).toString()),
27 + method: 'POST',
28 + data: data,
29 + processData: false,
30 + contentType: false, // Sets the 'multipart/form-data' automatically
31 + headers: {
32 + 'X-XWiki-Temporary-Attachment-Support': true
33 + }
34 + }).done(function (response) {
35 + #set ($successMessage = $escapetool.javascript($services.localization.render('attachment.attachmentSelector.temporaryUpload.success')))
36 + notification.replace(new XWiki.widgets.Notification("$successMessage", 'done'));
37 + // Add a field with the name of the uploaded file so that it is moved from the temporary
38 + // attachments to the persisded ones on save.
39 + $(form).append($('<input/>')
40 + .prop('type', 'hidden')
41 + .prop('name', 'uploadedFiles')
42 + .prop('value', response.fileName))
43 + $(form).find('input[type="hidden"].property-reference').prop('value', response.fileName);
44 + this.updateAttachment(response.fileName, response.url);
45 + this.dialog.closeDialog();
46 + }.bind(this)).fail(function () {
47 + #set ($errorMessage = $escapetool.javascript($services.localization.render('attachment.attachmentSelector.temporaryUpload.failure')))notification.replace(new XWiki.widgets.Notification("$errorMessage", 'error'));
48 + });
49 + }.bind(this));
50 + }
51 +
52 + function directUploadAttachment(uploadForm) {
53 + // FIXME This fails in HTML5, will deal with it later:
54 + // this.property.down('input').value = uploadForm.down('input[type="file"]').value;
55 + // uploadForm.xredirect.value = window.location.pathname;
56 + document.observe('xwiki:document:saved', function () {
57 + new XWiki.widgets.Notification("$services.localization.render('xe.attachmentSelector.upload.inProgress')",
58 + 'inprogress');
59 + uploadForm.submit();
60 + })
61 + document.fire('xwiki:actions:save', {'continue': true, form: this.property.up('form')});
62 + }
63 +
2 2   /** Handles the gallery buttons directly in the current page without reloading the window. */
3 3   XWiki.AttachmentPicker = Class.create({
4 4   /**
... ... @@ -40,7 +40,7 @@
40 40   * and saves the underlying form (if any) so that any unsaved changes won't be lost.
41 41   */
42 42   filterFormUpload : function() {
43 - this.gallery.select('.uploadAttachment input.attachment').each(function(fileInput) {
105 + this.gallery.select('.uploadAttachment input[type="file"]').each(function(fileInput) {
44 44   fileInput.__allowedExtensions = fileInput.title.toLowerCase().replace(/\s*[,|; ]\s*/g, " ").strip();
45 45   if (fileInput.__allowedExtensions != '') {
46 46   fileInput.__allowedExtensions = fileInput.__allowedExtensions.split(" ");
... ... @@ -52,7 +52,7 @@
52 52   event.stop();
53 53   var uploadForm = event.element();
54 54   var hasErrors = false;
55 - uploadForm.select('input.attachment').each(function(fileInput) {
117 + uploadForm.select('input[type="file"]').each(function(fileInput) {
56 56   if (fileInput.value == '') {
57 57   new XWiki.widgets.Notification("$services.localization.render('xe.attachmentSelector.upload.error.noFile')", 'error');
58 58   hasErrors = true;
... ... @@ -60,21 +60,23 @@
60 60   new XWiki.widgets.Notification("$services.localization.render('xe.attachmentSelector.upload.error.badExtension')", 'error');
61 61   hasErrors = true;
62 62   }
125 + const beforeUploadEvent = Event.fire(document, 'xwiki:actions:beforeUpload', {
126 + file: fileInput.files[0]
127 + });
128 +
129 + if (beforeUploadEvent.defaultPrevented) {
130 + hasErrors = true;
131 + }
63 63   }.bind(this));
64 - // No form submission by AJAX right now, because file uploads can't be done this way without HTML5, this is future work
65 - // Save the document before submitting, since the current form data will be lost otherwise
66 66   if (!hasErrors) {
67 67   if (this.directSave) {
68 68   uploadForm.submit();
69 69   } else {
70 - // FIXME This fails in HTML5, will deal with it later:
71 - // this.property.down('input').value = uploadForm.down('.attachment').value;
72 - // uploadForm.xredirect.value = window.location.pathname;
73 - document.observe('xwiki:document:saved', function() {
74 - new XWiki.widgets.Notification("$services.localization.render('xe.attachmentSelector.upload.inProgress')", 'inprogress');
75 - uploadForm.submit();
76 - })
77 - document.fire('xwiki:actions:save', {'continue': true, form: this.property.up('form')});
137 + if ("$!services.temporaryAttachments" != '') {
138 + uploadTemporaryAttachment.call(this);
139 + } else {
140 + directUploadAttachment.call(this, uploadForm);
141 + }
78 78   }
79 79   }
80 80   }.bindAsEventListener(this));
... ... @@ -117,6 +117,11 @@
117 117   if (this.gallery.down('.gallery_emptyChoice')) {
118 118   this.gallery.down('.gallery_emptyChoice').addClassName('current');
119 119   }
184 + // Disable the replace feature because there's no selection.
185 + var fileNameInput = this.gallery.down('input[type="checkbox"][name="filename"]');
186 + fileNameInput.disabled = true;
187 + // Empty the displayed selected file name.
188 + fileNameInput.up('label').down('strong').update('');
120 120   if (!this.directSave) {
121 121   this.property.down('input').value = this.defaultValue;
122 122   }
... ... @@ -168,10 +168,7 @@
168 168   this.dialog.closeDialog();
169 169   }.bindAsEventListener(this),
170 170   onFailure : function(response) {
171 - var failureReason = response.statusText;
172 - if (response.statusText == '' /* No response */ || response.status == 12031 /* In IE */) {
173 - failureReason = 'Server not responding';
174 - }
240 + var failureReason = response.statusText || 'Server not responding';
175 175   if (targetElement._x_notif) {
176 176   targetElement._x_notif.replace(new XWiki.widgets.Notification("$services.localization.render('core.widgets.confirmationBox.notification.failed')" + failureReason, "error"));
177 177   } else {
... ... @@ -178,9 +178,6 @@
178 178   new XWiki.widgets.Notification(this.interactionParameters.failureMessageText + failureReason, "error");
179 179   }
180 180   },
181 - on1223 : function(response) {
182 - response.request.options.onSuccess(response);
183 - },
184 184   on0 : function(response) {
185 185   response.request.options.onFailure(response);
186 186   },
... ... @@ -270,11 +270,7 @@
270 270   );
271 271   dialog.shortcuts.close.keys = [];
272 272   dialog.showDialog();
273 - if (window.browser.isIE6x) {
274 - dialog.dialog.down().setStyle({position: "absolute"});
275 - } else {
276 - dialog.dialog.down().setStyle({position: "fixed"});
277 - }
336 + dialog.dialog.down().setStyle({position: "fixed"});
278 278   dialog.dialog.setStyle({top: document.viewport.getScrollOffsets().top + "px", position: "absolute"});
279 279   dialog.dialogBox.setStyle({overflow: "hidden", width: "80%", margin: "0 10%"});
280 280   new Ajax.Updater(loading.up(), url, {
XWiki.StyleSheetExtension[0]
Code
... ... @@ -27,7 +27,7 @@
27 27  .gallery_attachmentbox {
28 28   background: $theme.pageContentBackgroundColor;
29 29   border: 1px solid $theme.borderColor;
30 - border-radius: 5px;
30 + border-radius: 8px;
31 31   float: left;
32 32   margin: ${boxMargin}px;
33 33   overflow: hidden;
... ... @@ -34,19 +34,11 @@
34 34   position: relative;
35 35   width: ${boxSize}px;
36 36  }
37 -/* Broken IE6 box model, add the border width to the total width. */
38 -* html .gallery_attachmentbox {
39 - width: ${mathtool.add($boxSize, 2)}px;
40 -}
41 41  .gallery .current {
42 42   background-color: $theme.highlightColor;
43 43   border-width: 3px;
44 44   margin: 3px;
45 45  }
46 -/* Broken IE6 box model, add the border width to the total width. */
47 -* html .gallery .current {
48 - width: ${mathtool.add($boxSize, 6)}px;
49 -}
50 50  .gallery .current .gallery_attachmenttitle {
51 51   font-weight: bold;
52 52  }
... ... @@ -57,7 +57,7 @@
57 57  .gallery_attachmenttitle {
58 58   background: $theme.backgroundSecondaryColor;
59 59   border-bottom: 1px dotted $theme.borderColor;
60 - border-radius: 5px 5px 0px 0px;
52 + border-radius: 8px 8px 0px 0px;
61 61   font-size: 85%;
62 62   padding: 3px ${boxPadding}px;
63 63   overflow: hidden;
... ... @@ -148,9 +148,6 @@
148 148   ## Make this box twice as large as the others
149 149   width: ${uploadBoxSize}px;
150 150  }
151 -* html .gallery_upload {
152 - width: ${mathtool.add($uploadBoxSize, 2)}px;
153 -}
154 154  .gallery_upload, .gallery_upload:hover {
155 155   background-color: $theme.backgroundSecondaryColor;
156 156  }
... ... @@ -161,24 +161,29 @@
161 161   background-repeat: no-repeat;
162 162   padding-left: 16px;
163 163  }
164 -.gallery_upload form {
165 - height: ${imgSize}px;
153 +.gallery_upload .gallery_attachmentframe {
154 + height: auto;
166 166  }
167 -.gallery_upload .xHint {
168 - text-transform: none !important;
156 +.gallery_upload_input {
157 + margin-bottom: 10px;
169 169  }
170 -.gallery_upload input.attachment {
171 - font-size: 83.3%;
172 - margin: 0; /* Overrides viewers/attachments.css */
173 - padding: 0; /* Overrides viewers/attachments.css */
159 +.gallery_upload input[type="file"] {
160 + font-size: 86%;
174 174   width: ${mathtool.sub($uploadBoxSize, $mathtool.mul($boxPadding, 2))}px;
175 175  }
176 176  .gallery_upload .buttonwrapper {
177 177   margin: 0;
178 178  }
179 -.gallery_upload .button {
180 - font-size: .65em;
166 +.gallery_upload .button,
167 +.gallery_upload label {
168 + font-size: 86%;
181 181  }
170 +.gallery_upload input[type="checkbox"] {
171 + vertical-align: text-bottom;
172 +}
173 +.gallery_upload label[for="commentinput"] {
174 + margin-top: 10px;
175 +}
182 182  
183 183  /* ------------------------------------ */
184 184  /* Buttons on top: */
XWiki.WikiMacroClass[0]
Macro code
... ... @@ -3,7 +3,6 @@
3 3  $xwiki.ssfx.use('js/xwiki/widgets/modalPopup.css', true)##
4 4  $xwiki.jsx.use($xcontext.macro.doc.fullName)##
5 5  $xwiki.ssx.use($xcontext.macro.doc.fullName)##
6 -$xwiki.jsfx.use('js/scriptaculous/builder.js')##
7 7  ## Integrates the optional Lightbox widget (from http://extensions.xwiki.org/xwiki/bin/view/Extension/Lightbox+Application )
8 8  #if ($xwiki.exists('XWiki.Lightbox'))
9 9   $xwiki.jsx.use('XWiki.Lightbox')
... ... @@ -32,9 +32,9 @@
32 32  #end
33 33  #set ($classname = "$!{xcontext.macro.params.classname}")
34 34  #set ($property = "$!{xcontext.macro.params.property}")
35 -#set ($object = $mathtool.toInteger("$!{xcontext.macro.params.object}"))
34 +#set ($object = $numbertool.toNumber("$!{xcontext.macro.params.object}").intValue())
36 36  #if ("$!{object}" != $!{xcontext.macro.params.object})
37 - #set ($object = ${doc.getObject($classname).number})
36 + #set ($object = ${targetdoc.getObject($classname).number})
38 38   #if ("$!{object}" == '')
39 39   #set ($object = 0)
40 40   #end
... ... @@ -46,9 +46,18 @@
46 46   #set ($displayImage = false)
47 47  #end
48 48  #if ($displayImage)
49 - #set ($alt = "$!{xcontext.macro.params.alternateText}")
50 - #set ($width = "$!{xcontext.macro.params.width}")
51 - #set ($height = "$!{xcontext.macro.params.height}")
48 + #set ($alt = '')
49 + #set ($width = '')
50 + #set ($height = '')
51 + #if ($xcontext.macro.params.alternateText)
52 + #set ($alt = "$services.rendering.escape($!{xcontext.macro.params.alternateText}, 'xwiki/2.1')")
53 + #end
54 + #if ($xcontext.macro.params.width)
55 + #set ($width = "$services.rendering.escape($!{xcontext.macro.params.width}, 'xwiki/2.1')")
56 + #end
57 + #if ($xcontext.macro.params.height)
58 + #set ($height = "$services.rendering.escape($!{xcontext.macro.params.height}, 'xwiki/2.1')")
59 + #end
52 52   #set ($imageParams = '')
53 53   #if ("${width}" != '')
54 54   #set($imageParams = "$!{imageParams} width=${width}")
... ... @@ -86,7 +86,7 @@
86 86   #set ($savemode = 'form')
87 87  #end
88 88  
89 -#set ($propValue = "$!{doc.getObject($classname, $object).getProperty($property).value}")
97 +#set ($propValue = "$!{targetdoc.getObject($classname, $object).getProperty($property).value}")
90 90  ##
91 91  
92 92  #macro (attachmentPicker_displayAttachment $name $displayImage $withLink $forceElement)
... ... @@ -113,9 +113,9 @@
113 113   #set ($attachmentResource = '')
114 114   #end
115 115   #if ($displayImage)
116 - (% class="$!{cssClass}#if (!$attachment) hidden#end" %)(((#if ("$!{attachmentResource}" != '' || $forceElement)#if($withLink)[[#end[[image:${attachmentResource}$!{imageParams}]]#if($withLink)>>attach:${attachmentResource}||rel=lightbox]]#{end}#end)))##
124 + (% class="$!{cssClass}#if (!$attachment) hidden#end" %)(((#if ("$!{attachmentResource}" != '' || $forceElement)#if($withLink)[[#end[[image:$services.rendering.escape(${attachmentResource}, 'xwiki/2.1')$!{imageParams}]]#if($withLink)>>attach:$services.rendering.escape(${attachmentResource},'xwiki/2.1')||rel=lightbox]]#{end}#end)))##
117 117   #else
118 - (% class="$!{cssClass}" %)#if ("$!{attachmentResource}" != '' || $forceElement)#if ($withLink)[[attach:${attachmentResource}||rel=__blank]]#{else}(% class="displayed" %)#if($targetPermView)$!{attachmentName}#{else}Access Denied#{end}(% %)#{end}#end(%%)##
126 + (% class="$!{cssClass}" %)#if ("$!{attachmentResource}" != '' || $forceElement)#if ($withLink)[[attach:${attachmentResource}||rel=__blank]]#{else}(% class="displayed" %)#if($targetPermView)$!{services.rendering.escape($!{attachmentName}, 'xwiki/2.1')}#{else}Access Denied#{end}(% %)#{end}#end(%%)##
119 119   #end
120 120  #end
121 121  
... ... @@ -123,7 +123,25 @@
123 123  ## 1. Edit the current page
124 124  ## 2. View the target attachment page. (can be the same page)
125 125  #macro (attachmentPicker_displayButton)
126 - #if ($hasEdit && $targetPermView)(% class="buttonwrapper" %)[[${buttontext}>>${xcontext.macro.doc.fullName}||queryString="#if ($hasTargetDoc)targetdocname=${escapetool.url($targetdoc.fullName)}&#{end}docname=${escapetool.url($doc.fullName)}&classname=${classname}&property=${property}&object=${object}&savemode=${savemode}&defaultValue=$escapetool.url($defaultValue)&filter=$!{filter}&displayImage=${displayImage}" class="attachment-picker-start button" title="${buttontext}"]](%%)#end
134 + #if ($targetPermView)
135 + #set ($queryString = {
136 + 'docname': $doc.fullName,
137 + 'classname': $classname,
138 + 'property': $property,
139 + 'object': $object,
140 + 'savemode': $savemode,
141 + 'defaultValue': $defaultValue,
142 + 'filter': $filter,
143 + 'displayImage': $displayImage,
144 + 'versionSummary': $xcontext.macro.params.versionSummary.equals('true')
145 + })
146 + #if ($hasTargetDoc)
147 + #set ($queryString.targetdocname = $targetdoc.fullName)
148 + #end
149 + #set ($linkLabel = $services.rendering.escape($services.rendering.escape($buttontext, 'xwiki/2.1'), 'xwiki/2.1'))
150 + (% class="buttonwrapper" %)[[$linkLabel>>${xcontext.macro.doc.fullName}||queryString="$escapetool.url($queryString)"
151 + class="attachment-picker-start button" title="$services.rendering.escape($buttontext, 'xwiki/2.1')"]](%%)##
152 + #end
127 127  #end
128 128  {{/velocity}}
129 129  
... ... @@ -133,7 +133,7 @@
133 133  #elseif ($xcontext.action == 'inline' || $xcontext.action == 'edit')
134 134   (% class="attachment-picker" %)(((##
135 135   #attachmentPicker_displayAttachment($propValue $displayImage false true) #attachmentPicker_displayButton()##
136 - {{html}}<input type="hidden" name="${classname}_${object}_${property}" value="${propValue}"/>{{/html}}##
162 + {{html}}<input type="hidden" name="$escapetool.xml("${classname}_${object}_${property}")" value="$escapetool.xml("${propValue}")" class="property-reference"/>{{/html}}##
137 137   )))
138 138  #else
139 139   #attachmentPicker_displayAttachment($propValue $displayImage $link false)
Cached
... ... @@ -1,0 +1,1 @@
1 +No
Asynchronous rendering
... ... @@ -1,0 +1,1 @@
1 +No
Default categories
... ... @@ -1,0 +1,1 @@
1 +Development
XWiki.WikiMacroParameterClass[0]
Parameter type
... ... @@ -1,0 +1,1 @@
1 +org.xwiki.model.reference.DocumentReference
XWiki.WikiMacroParameterClass[10]
Parameter type
... ... @@ -1,0 +1,1 @@
1 +org.xwiki.model.reference.AttachmentReference
XWiki.WikiMacroParameterClass[18]
Parameter type
... ... @@ -1,0 +1,1 @@
1 +org.xwiki.model.reference.DocumentReference
XWiki.WikiMacroParameterClass[19]
Parameter default value
... ... @@ -1,0 +1,1 @@
1 +false
Parameter name
... ... @@ -1,0 +1,1 @@
1 +versionSummary
Parameter description
... ... @@ -1,0 +1,1 @@
1 +Whether to allow the user to enter a version summary that will be recorded in the history. An automatic message is used when no version summary is provided or if the version summary input is not displayed.
Parameter mandatory
... ... @@ -1,0 +1,1 @@
1 +No