Changes for page Attachments

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

From version 3.1
edited by Ludovic Dubost
on 2015/09/01 11:46
Change comment: Install extension [org.xwiki.platform:xwiki-platform-attachment-ui-7.1]
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
Content
... ... @@ -1,17 +1,21 @@
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 13   $response.sendRedirect($targetDocument.getURL($docAction, $escapetool.url({
14 14   $fieldname: $lastAttachment.filename,
18 + 'comment': $comment,
15 15   'form_token': $request.form_token
16 16   })))
17 17   #stop
... ... @@ -22,7 +22,6 @@
22 22  ##
23 23  ## Macros
24 24  ##
25 -#set ($translationPrefix = 'xe.attachmentSelector')
26 26  #set ($attachmentPickerDocName = 'XWiki.AttachmentSelector')
27 27  
28 28  $xwiki.ssx.use($attachmentPickerDocName)
... ... @@ -42,11 +42,14 @@
42 42   #end
43 43   (% class="gallery" %)(((
44 44   ## Only display the upload form if they have edit permission on targetAttachDocument
45 - #if ($xwiki.hasAccessLevel('edit',$xcontext.user,${targetAttachDocument.fullName}))
46 - #attachmentPicker_displayUploadForm($targetDocument, $targetAttachDocument, $options)
47 - #end
48 + #attachmentPicker_displayUploadForm($targetDocument, $targetAttachDocument, $options)
48 48   #attachmentPicker_displayAttachmentGalleryEmptyValue($targetDocument, $targetAttachDocument, $options, $currentValue)
49 - #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
50 50   #foreach ($attachment in $sortedAttachments)
51 51   #set ($extension = $attachment.getFilename())
52 52   #set ($extension = $extension.substring($mathtool.add($extension.lastIndexOf('.'), 1)).toLowerCase())
... ... @@ -66,18 +66,46 @@
66 66   * @param $currentValue the currently selected file, used for determining if the box should be highlighted as the current value
67 67   *#
68 68  #macro (attachmentPicker_displayAttachmentBox $attachment $targetDocument $targetAttachDocument, $options $currentValue)
69 - #if ($options.displayImage && $attachment.isImage())
70 - #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)
71 71   #else
72 - #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)
73 73   #end
74 - #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)
75 75   #attachmentPicker_displayAttachmentDetails($attachment $options)
76 76   #set ($returnURL = $escapetool.url($doc.getURL('view', $request.queryString)))
77 77   #set ($deleteURL = $targetAttachDocument.getAttachmentURL($attachment.filename, 'delattachment', "xredirect=${returnURL}&form_token=$!{services.csrf.getToken()}") )
78 78   #set ($viewURL = $targetAttachDocument.getAttachmentURL($attachment.filename) )##{'name' : 'download', 'url' : $viewURL, 'rel' : '__blank'}
79 - #set ($selectURL = $targetDocument.getURL(${options.get('docAction')}, "${options.get('classname')}_${options.get('object')}_${options.get('property')}=${attachment.filename}&form_token=$!{services.csrf.getToken()}"))
80 - #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)
81 81  #end
82 82  
83 83  #**
... ... @@ -89,7 +89,9 @@
89 89   *#
90 90  #macro (attachmentPicker_displayStartFrame $boxOptions $currentValue)
91 91   (% class="gallery_attachmentbox $!{boxOptions.cssClass} #if ("$!{boxOptions.value}" == $currentValue) current#{end}" %)(((
92 - (% 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 + )))
93 93   (% class="gallery_attachmentframe" %)(((
94 94  #end
95 95  
... ... @@ -102,14 +102,19 @@
102 102   *#
103 103  #macro (attachmentPicker_displayAttachmentDetails $attachment $options)
104 104   #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'))
105 105   #if ($attachment.isImage() && $options.displayImage)
106 - #set ($attachmentDocument = $attachment.getDocument())
107 -[[[[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]]
108 108   #else
109 - * (% class="mime" %){{html wiki=false clean=false}}#mimetypeimg($attachment.getMimeType().toLowerCase() $attachment.getFilename().toLowerCase()){{/html}}(%%) (% class="filename" %)$attachment.getFilename()(% %)
110 - * 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))
111 111   * $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')}])
112 - * (% 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"]](%%)
113 113   #end
114 114   #end
115 115  #end
... ... @@ -126,8 +126,9 @@
126 126   * <dt>rel</dt>
127 127   * <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>
128 128   * </dl>
170 + * @param $additionalContent optional additional content that does not follow the structure of the actions
129 129   *#
130 -#macro (attachmentPicker_displayEndFrame $actions)
172 +#macro (attachmentPicker_displayEndFrame $actions $additionalContent)
131 131   )))## attachmentframe
132 132   (% class="gallery_actions" %)(((
133 133   #foreach ($action in $actions)
... ... @@ -134,6 +134,7 @@
134 134   #set( $actionname = $services.localization.render("${translationPrefix}.actions.${action.name}") )
135 135   [[${actionname}>>path:${action.url}||class="tool ${action.name}" title="${actionname}" #if($action.rel) rel="${action.rel}"#end]]##
136 136   #end
179 + $!additionalContent
137 137   )))## actions
138 138   )))## attachmentbox
139 139  #end
... ... @@ -157,7 +157,7 @@
157 157   #if (${options.rawfilter} != '')
158 158   <span class="xHint">$escapetool.xml($services.localization.render("${translationPrefix}.upload.hint", [${options.rawfilter}]))</span>
159 159   #end
160 - <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)}"/>
161 161   <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()}")" />
162 162   <input type="hidden" name="docname" value="$!{escapetool.xml($targetDocument.fullName)}" />
163 163   <input type="hidden" name="classname" value="$!{escapetool.xml($options.get('classname'))}" />
... ... @@ -165,6 +165,27 @@
165 165   <input type="hidden" name="property" value="$!{escapetool.xml($options.get('property'))}" />
166 166   <input type="hidden" name="form_token" value="$!{services.csrf.getToken()}" />
167 167   </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
168 168   <div class="buttons">
169 169   <span class="buttonwrapper">
170 170   <input type="submit" name="action_upload" class="button " value='$services.localization.render("${translationPrefix}.upload.submit")' title='$services.localization.render("${translationPrefix}.upload.submit")'/>
... ... @@ -208,11 +208,6 @@
208 208  
209 209  {{velocity}}
210 210  #if ($request.docname)
211 - ###if ($request.xpage == 'plain')
212 - ## ## IE6 + XHR + gzip compression = BOOM!
213 - ## ## This disables the automatic gzip compression
214 - ## $response.setContentType('multipart/formdata')
215 - ###end
216 216   #set ($targetDocument = $xwiki.getDocument($request.docname))
217 217   #if ($request.targetdocname)
218 218   ## Use the target document if it exists.
... ... @@ -261,7 +261,7 @@
261 261   #end
262 262   #set ($options = {
263 263   'classname' : ${request.get('classname')},
264 - 'object' : $!{mathtool.toInteger($request.object)},
323 + 'object' : $!{numbertool.toNumber($request.object).intValue()},
265 265   'property' : ${request.property},
266 266   'displayImage' : ${displayImage},
267 267   'docAction' : ${docAction},
... ... @@ -268,13 +268,16 @@
268 268   'defaultValue' : "$!{request.defaultValue}",
269 269   'rawfilter': "$!{rawfilter}",
270 270   'filter': ${filter},
271 - 'sortAttachmentsBy': ${sortAttachmentsBy}
330 + 'sortAttachmentsBy': ${sortAttachmentsBy},
331 + 'versionSummary': $request.versionSummary.equals('true')
272 272   })
273 273   $!targetDocument.use($targetDocument.getObject($options.classname, $options.object))##
274 274   #attachmentPicker_displayAttachmentGallery($targetDocument, $targetAttachDocument, $options)
275 275  
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'))
276 276   (% class="gallery_buttons buttons" %)(((
277 - (% 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"]]
278 278   )))
279 279  #end
280 280  {{/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