Changes for page Attachments
Last modified by superadmin on 2017/11/28 14:52
From empty
To version 1.1
edited by superadmin
on 2017/11/28 14:52
on 2017/11/28 14:52
Change comment: Install extension [org.xwiki.platform:xwiki-platform-attachment-ui/9.9]
Summary
-
Page properties (5 modified, 0 added, 0 removed)
-
Objects (0 modified, 19 added, 0 removed)
- XWiki.JavaScriptExtension[0]
- XWiki.JavaScriptExtension[1]
- XWiki.StyleSheetExtension[0]
- XWiki.WikiMacroClass[0]
- XWiki.WikiMacroParameterClass[0]
- XWiki.WikiMacroParameterClass[1]
- XWiki.WikiMacroParameterClass[2]
- XWiki.WikiMacroParameterClass[5]
- XWiki.WikiMacroParameterClass[6]
- XWiki.WikiMacroParameterClass[7]
- XWiki.WikiMacroParameterClass[10]
- XWiki.WikiMacroParameterClass[12]
- XWiki.WikiMacroParameterClass[13]
- XWiki.WikiMacroParameterClass[14]
- XWiki.WikiMacroParameterClass[15]
- XWiki.WikiMacroParameterClass[16]
- XWiki.WikiMacroParameterClass[17]
- XWiki.WikiMacroParameterClass[18]
- XWiki.WikiMacroParameterClass[19]
Details
- Page properties
-
- Title
-
... ... @@ -1,0 +1,1 @@ 1 +#if ($request.docname)$xwiki.getDocument($request.docname).plainTitle ($request.docname): #end$services.localization.render('xe.attachmentSelector.gallery.title') - Parent
-
... ... @@ -1,0 +1,1 @@ 1 +Main.WebHome - Author
-
... ... @@ -1,1 +1,1 @@ 1 - XWiki.XWikiGuest1 +xwiki:XWiki.superadmin - Hidden
-
... ... @@ -1,1 +1,1 @@ 1 - false1 +true - Content
-
... ... @@ -1,0 +1,302 @@ 1 +{{velocity output="false"}} 2 +#if ($request.xaction == 'postUpload') 3 + #set ($targetDocument = $xwiki.getDocument($request.get('docname'))) 4 + #set ($targetAttachDocument = $xwiki.getDocument($request.get('targetdocname'))) 5 + 6 + #set ($fieldname = $request.get('fieldname')) 7 + #set ($docAction = $request.get('docAction')) 8 + #set ($attachmentList = $targetAttachDocument.getAttachmentList()) 9 + #if ($attachmentList && $attachmentList.size() > 0) 10 + #set ($sortedAttachments = $sorttool.sort($attachmentList, 'date:desc')) 11 + #set ($lastAttachment = $sortedAttachments.get(0)) 12 + #end 13 + $response.sendRedirect($targetDocument.getURL($docAction, $escapetool.url({ 14 + $fieldname: $lastAttachment.filename, 15 + 'form_token': $request.form_token 16 + }))) 17 + #stop 18 +#end 19 +{{/velocity}} 20 + 21 +{{velocity output="false"}} 22 +## 23 +## Macros 24 +## 25 +#set ($translationPrefix = 'xe.attachmentSelector') 26 +#set ($attachmentPickerDocName = 'XWiki.AttachmentSelector') 27 + 28 +$xwiki.ssx.use($attachmentPickerDocName) 29 +$xwiki.jsx.use($attachmentPickerDocName) 30 + 31 +#** 32 + * Displays the attachment gallery as a list of attachment boxes, starting with special boxes for uploading a new attachment and for setting a default value. 33 + * 34 + * @param $targetDocument the document to recieve the field value being modified 35 + * @param $targetAttachDocument the document to list/save attachments to 36 + * @param $options generic picker options 37 + *# 38 +#macro (attachmentPicker_displayAttachmentGallery $targetDocument, $targetAttachDocument, $options) 39 + #set ($currentValue = $targetDocument.getValue($options.property)) 40 + #if ("$!{targetAttachDocument.getAttachment($currentValue)}" == '') 41 + #set ($currentValue = "$!{options.defaultValue}") 42 + #end 43 + (% class="gallery" %)((( 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_displayAttachmentGalleryEmptyValue($targetDocument, $targetAttachDocument, $options, $currentValue) 49 + #set ($sortedAttachments = $sorttool.sort($targetAttachDocument.getAttachmentList(), "${options.sortAttachmentsBy}") ) 50 + #foreach ($attachment in $sortedAttachments) 51 + #set ($extension = $attachment.getFilename()) 52 + #set ($extension = $extension.substring($mathtool.add($extension.lastIndexOf('.'), 1)).toLowerCase()) 53 + #if ($options.filter.size() == 0 || $options.filter.contains($extension)) 54 + #attachmentPicker_displayAttachmentBox($attachment $targetDocument $targetAttachDocument, $options $currentValue) 55 + #end 56 + #end 57 + ))) 58 +#end 59 + 60 +#** 61 + * Displays an attachment box. 62 + * 63 + * @param $attachment the target attachment to display 64 + * @param $targetDocument the document being modified 65 + * @param $options generic picker options 66 + * @param $currentValue the currently selected file, used for determining if the box should be highlighted as the current value 67 + *# 68 +#macro (attachmentPicker_displayAttachmentBox $attachment $targetDocument $targetAttachDocument, $options $currentValue) 69 + #if ($options.displayImage && $attachment.isImage()) 70 + #set ($cssClass = 'gallery_image') 71 + #else 72 + #set ($cssClass = '') 73 + #end 74 + #attachmentPicker_displayStartFrame({'value' : $attachment.filename, 'text' : $attachment.filename, 'cssClass' : "$!{cssClass}"} $currentValue) 75 + #attachmentPicker_displayAttachmentDetails($attachment $options) 76 + #set ($returnURL = $escapetool.url($doc.getURL('view', $request.queryString))) 77 + #set ($deleteURL = $targetAttachDocument.getAttachmentURL($attachment.filename, 'delattachment', "xredirect=${returnURL}&form_token=$!{services.csrf.getToken()}") ) 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}]) 81 +#end 82 + 83 +#** 84 + * Writes the wiki code used at the start of an attachment box. Outputs the attachment title bar, and opens the inner frame div. 85 + * 86 + * @param $boxOptions a map of parameters/options for the current attachment, holding, for example, the attachment name (boxOptions.value), 87 + * the title to display (boxOptions.text), optional extra CSS classnames to put on the box (boxOptions.cssClass) 88 + * @param $currentValue the currently selected file, used for determining if this attachment should be highlighted as the current value 89 + *# 90 +#macro (attachmentPicker_displayStartFrame $boxOptions $currentValue) 91 + (% class="gallery_attachmentbox $!{boxOptions.cssClass} #if ("$!{boxOptions.value}" == $currentValue) current#{end}" %)((( 92 + (% class="gallery_attachmenttitle" title="$!{boxOptions.value}" %)((($boxOptions.text))) 93 + (% class="gallery_attachmentframe" %)((( 94 +#end 95 + 96 +#** 97 + * Displays details about an attachment inside the attachment box. If the attachment is an image and the "displayImage" option is on, 98 + * then the image is displayed. Otherwise, some basic information is displayed: the version, the size, the date and the author. 99 + * 100 + * @param $attachment the target attachment to display 101 + * @param $options generic picker options 102 + *# 103 +#macro (attachmentPicker_displayAttachmentDetails $attachment $options) 104 + #if ($attachment) 105 + ## Compute the attachment reference because there's no getter. 106 + #set ($attachmentReference = $services.model.createAttachmentReference($attachment.document.documentReference, 107 + $attachment.filename)) 108 + #set ($attachmentStringReference = $services.model.serialize($attachmentReference, 'default')) 109 + #if ($attachment.isImage() && $options.displayImage) 110 + ## We add the version to the query string in order to invalidate the cache when an image attachment is replaced. 111 + #set ($queryString = $escapetool.url({'version': $attachment.version})) 112 + [[[[image:$attachmentStringReference||width=180 queryString="$queryString"]]>>attach:$attachmentStringReference]] 113 + #else 114 + * (% class="mime" %){{html wiki=false clean=false}}#mimetypeimg($attachment.getMimeType().toLowerCase() $attachment.getFilename().toLowerCase()){{/html}}(%%) (% class="filename" %)$attachment.getFilename()(% %) 115 + * v$attachment.getVersion() (#dynamicsize($attachment.longSize)) 116 + * $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')}]) 117 + * (% class="buttonwrapper" %)[[${services.localization.render("${translationPrefix}.actions.download")}>>attach:$attachmentStringReference||title="$services.localization.render("${translationPrefix}.actions.download")" rel="__blank" class="button"]](%%) 118 + #end 119 + #end 120 +#end 121 + 122 +#** 123 + * Writes the wiki code used at the end of an attachment box. Closes the inner frame div, and outputs the attachment actions. 124 + * 125 + * @param $actions a list of maps defining action buttons, where each entry contains a subset of the following: 126 + * <dl> 127 + * <dt>name</dt> 128 + * <dd>identifies the action; the name is used as a CSS classname, and in the translation key for the display text, as "xe.attachmentSelector.actions.<name>"</dd> 129 + * <dt>url</dt> 130 + * <dd>the destination of the button</dd> 131 + * <dt>rel</dt> 132 + * <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> 133 + * </dl> 134 + *# 135 +#macro (attachmentPicker_displayEndFrame $actions) 136 + )))## attachmentframe 137 + (% class="gallery_actions" %)((( 138 + #foreach ($action in $actions) 139 + #set( $actionname = $services.localization.render("${translationPrefix}.actions.${action.name}") ) 140 + [[${actionname}>>path:${action.url}||class="tool ${action.name}" title="${actionname}" #if($action.rel) rel="${action.rel}"#end]]## 141 + #end 142 + )))## actions 143 + )))## attachmentbox 144 +#end 145 + 146 +#** 147 + * Displays the upload box used for adding and selecting a new attachment. 148 + * 149 + * @param $targetDocument the document with the property being modified 150 + * @param $targetAttachDocument the document to upload the attachment to 151 + * @param $options generic picker options 152 + *# 153 +#macro (attachmentPicker_displayUploadForm $targetDocument, $targetAttachDocument, $options) 154 +#attachmentPicker_displayStartFrame({ 155 + 'value' : $services.localization.render("${translationPrefix}.upload.title"), 156 + 'text' : $services.localization.render("${translationPrefix}.upload.title"), 157 + 'cssClass' : 'gallery_upload' 158 + } $NULL) 159 +{{html clean="false"}} 160 +<form action="$targetAttachDocument.getURL('upload')" enctype="multipart/form-data" method="post" id="uploadAttachment" class="uploadAttachment xform"> 161 + <div class="gallery_upload_input"> 162 + #if (${options.rawfilter} != '') 163 + <span class="xHint">$escapetool.xml($services.localization.render("${translationPrefix}.upload.hint", [${options.rawfilter}]))</span> 164 + #end 165 + <input type="file" name="filepath" id="attachfile" class="noitems" title="$!{escapetool.xml($options.rawfilter)}"/> 166 + <input type="hidden" name="xredirect" value="$xwiki.getDocument($attachmentPickerDocName).getURL('get', "xaction=postUpload&docAction=$!{escapetool.url($options.get('docAction'))}&targetdocname=$!{escapetool.url($targetAttachDocument.fullName)}&docname=$!{escapetool.url($targetDocument.fullName)}&fieldname=$!{escapetool.url($options.get('classname'))}_$!{escapetool.url($options.get('object'))}_$!{escapetool.url($options.get('property'))}&form_token=$!{services.csrf.getToken()}")" /> 167 + <input type="hidden" name="docname" value="$!{escapetool.xml($targetDocument.fullName)}" /> 168 + <input type="hidden" name="classname" value="$!{escapetool.xml($options.get('classname'))}" /> 169 + <input type="hidden" name="object" value="$!{escapetool.xml($options.get('object'))}" /> 170 + <input type="hidden" name="property" value="$!{escapetool.xml($options.get('property'))}" /> 171 + <input type="hidden" name="form_token" value="$!{services.csrf.getToken()}" /> 172 + </div> 173 + #if ("$!currentValue" != '' && $currentValue != $options.defaultValue) 174 + <div> 175 + <label> 176 + <input type="checkbox" name="filename" value="$!escapetool.xml($currentValue)" 177 + />$services.localization.render('attachmentSelector.replace', 178 + ["<strong>$!escapetool.xml($currentValue)</strong>"]) 179 + </label> 180 + <span class="xHint">$escapetool.xml($services.localization.render('attachmentSelector.replace.hint'))</span> 181 + </div> 182 + #end 183 + #if ($xwiki.hasEditComment() && $options.versionSummary) 184 + <div> 185 + #if ($xwiki.isEditCommentFieldHidden()) 186 + <input type="hidden" name="comment" value="$!escapetool.xml($request.comment)" /> 187 + #else 188 + <label for="commentinput">$services.localization.render('core.comment')</label> 189 + <input type="text" name="comment" id="commentinput" value="$!escapetool.xml($request.comment)" 190 + title="$services.localization.render('core.comment.tooltip')" /> 191 + #end 192 + </div> 193 + #end 194 + <div class="buttons"> 195 + <span class="buttonwrapper"> 196 + <input type="submit" name="action_upload" class="button " value='$services.localization.render("${translationPrefix}.upload.submit")' title='$services.localization.render("${translationPrefix}.upload.submit")'/> 197 + </span> 198 + </div> 199 +</form> 200 +{{/html}} 201 +#attachmentPicker_displayEndFrame ([]) 202 +#end 203 + 204 +#** 205 + * Displays the "empty value" box, used for unsetting the field value. 206 + * 207 + * @param $targetDocument the document being modified 208 + * @param $targetAttachDocument the document that the attachments will the loaded from/saved to 209 + * @param $options generic picker options 210 + * @param $currentValue the currently selected file, used for determining if the empty box should be highlighted as the current value 211 + *# 212 +#macro (attachmentPicker_displayAttachmentGalleryEmptyValue $targetDocument, $targetAttachDocument, $options, $currentValue) 213 + #if ("$!{options.get('defaultValue')}" != '') 214 + #set ($reference = ${options.get('defaultValue')}) 215 + #set ($docNameLimit = $reference.indexOf('@')) 216 + #if ($docNameLimit > 0) 217 + #set ($docName = $reference.substring(0, $docNameLimit)) 218 + #else 219 + #set ($docName = $targetAttachDocument.fullName) 220 + #end 221 + #set ($attachmentName = $reference.substring($mathtool.add($docNameLimit, 1))) 222 + #set ($defaultAttachment = $xwiki.getDocument($docName).getAttachment($attachmentName)) 223 + #if ($defaultAttachment.isImage()) 224 + #set($dcssClass = 'gallery_image') 225 + #end 226 + #end 227 + #attachmentPicker_displayStartFrame({'cssClass' : "gallery_emptyChoice $!{dcssClass}", 'text' : $services.localization.render("${translationPrefix}.default"), 'value' : "${options.defaultValue}"} $currentValue) 228 + #attachmentPicker_displayAttachmentDetails($defaultAttachment $options) 229 + #set ($returnURL = $escapetool.url($doc.getURL('view', $request.queryString))) 230 + #set ($selectURL = $targetDocument.getURL(${options.get('docAction')}, "${options.get('classname')}_${options.get('object')}_${options.get('property')}=&form_token=$!{services.csrf.getToken()}")) 231 + #attachmentPicker_displayEndFrame ([{'name' : 'select', 'url' : $selectURL}]) 232 +#end 233 +{{/velocity}} 234 + 235 +{{velocity}} 236 +#if ($request.docname) 237 + #set ($targetDocument = $xwiki.getDocument($request.docname)) 238 + #if ($request.targetdocname) 239 + ## Use the target document if it exists. 240 + #set ($targetAttachDocument = $xwiki.getDocument($request.targetdocname)) 241 + #else 242 + ## Otherwise, just use the current document as the target to save/load attachments 243 + #set ($targetAttachDocument = $targetDocument) 244 + #end 245 + #if ("$!{request.savemode}" == 'direct') 246 + #set($docAction = 'save') 247 + #else 248 + #set($docAction = $targetAttachDocument.getDefaultEditMode()) 249 + #end 250 + #set ($filter = []) 251 + #set ($rawfilter = '') 252 + #if ("$!{request.filter}" != '') 253 + #foreach ($value in $request.filter.trim().split('\s*+[,|; ]\s*+')) 254 + #if ("$!value" != '') 255 + #set ($discard = $filter.add($value.toLowerCase())) 256 + #set ($rawfilter = "${rawfilter}, ${value}") 257 + #end 258 + #end 259 + #if ($rawfilter != '') 260 + #set ($rawfilter = $rawfilter.substring(2)) 261 + #end 262 + #end 263 + #if ("$!{request.displayImage}" == 'true') 264 + #set ($displayImage = true) 265 + #else 266 + #set ($displayImage = false) 267 + #end 268 + ### Determine attachment sorting 269 + #set($sortAttachmentsBy = "$!{request.sortAttachmentsBy}") 270 + #set ($validAttachmentProperties = ['filename', 'date', 'filesize', 'author', 'version', 'mimeType']) 271 + #if($sortAttachmentsBy == '' || $validAttachmentProperties.indexOf($sortAttachmentsBy) == -1) 272 + ### Default to sorting by filename, sort not requested. 273 + #set($sortAttachmentsBy = "filename") 274 + #end 275 + ### Set attachment sorting direction 276 + #if($sortAttachmentsBy == 'date') 277 + ### Sort the date descending 278 + #set($sortAttachmentsBy = "date:desc") 279 + #else 280 + ### Sort everything else ascending 281 + #set($sortAttachmentsBy = "${sortAttachmentsBy}:asc") 282 + #end 283 + #set ($options = { 284 + 'classname' : ${request.get('classname')}, 285 + 'object' : $!{mathtool.toInteger($request.object)}, 286 + 'property' : ${request.property}, 287 + 'displayImage' : ${displayImage}, 288 + 'docAction' : ${docAction}, 289 + 'defaultValue' : "$!{request.defaultValue}", 290 + 'rawfilter': "$!{rawfilter}", 291 + 'filter': ${filter}, 292 + 'sortAttachmentsBy': ${sortAttachmentsBy}, 293 + 'versionSummary': $request.versionSummary.equals('true') 294 + }) 295 + $!targetDocument.use($targetDocument.getObject($options.classname, $options.object))## 296 + #attachmentPicker_displayAttachmentGallery($targetDocument, $targetAttachDocument, $options) 297 + 298 + (% class="gallery_buttons buttons" %)((( 299 + (% class="buttonwrapper secondary" %)[[$services.localization.render("${translationPrefix}.cancel")>>$targetDocument||class="button secondary" id="attachment-picker-close"]] 300 + ))) 301 +#end 302 +{{/velocity}}
- XWiki.JavaScriptExtension[0]
-
- Caching policy
-
... ... @@ -1,0 +1,1 @@ 1 +long - Code
-
... ... @@ -1,0 +1,301 @@ 1 +var XWiki = (function(XWiki) { 2 + /** Handles the gallery buttons directly in the current page without reloading the window. */ 3 + XWiki.AttachmentPicker = Class.create({ 4 + /** 5 + * Constructor. 6 + * 7 + * @param property the property being edited, as the containing div with class="attachment-picker" 8 + * @param dialog the modal dialog where the gallery was loaded 9 + */ 10 + initialize : function(property, dialog) { 11 + this.property = property; 12 + this.dialog = dialog; 13 + this.gallery = dialog.dialogBox; 14 + if (!this.property.down('input')) { 15 + this.directSave = true; 16 + } 17 + this.defaultValue = ''; 18 + var defaultValueElement = this.gallery.down('.gallery_emptyChoice .gallery_attachmenttitle'); 19 + if (defaultValueElement) { 20 + this.defaultValue = defaultValueElement.title; 21 + } 22 + this.defaultImageSource = ''; 23 + var defaultImage = this.gallery.down('.gallery_emptyChoice.gallery_image img'); 24 + if (defaultImage) { 25 + this.defaultImageSource = defaultImage.src.replace(/\?.*$/, ''); 26 + } 27 + this.filterFormUpload(); 28 + this.addDeleteListeners(); 29 + this.addSelectListeners(); 30 + this.updateCurrentSelection(); 31 + this.addCloseListener(); 32 + var img = this.property.down('img'); 33 + if (img) { 34 + img.observe('load', function() {img.up('div').removeClassName('hidden');}); 35 + img.observe('error', function() {img.up('div').addClassName('hidden');}); 36 + } 37 + }, 38 + /** 39 + * Catches the upload form submission and stops it if the selected file is not of the accepted types (or not selected at all), 40 + * and saves the underlying form (if any) so that any unsaved changes won't be lost. 41 + */ 42 + filterFormUpload : function() { 43 + this.gallery.select('.uploadAttachment input[type="file"]').each(function(fileInput) { 44 + fileInput.__allowedExtensions = fileInput.title.toLowerCase().replace(/\s*[,|; ]\s*/g, " ").strip(); 45 + if (fileInput.__allowedExtensions != '') { 46 + fileInput.__allowedExtensions = fileInput.__allowedExtensions.split(" "); 47 + } else { 48 + fileInput.__allowedExtensions = false; 49 + } 50 + }); 51 + this.gallery.select(".uploadAttachment").invoke('observe', 'submit', function(event) { 52 + event.stop(); 53 + var uploadForm = event.element(); 54 + var hasErrors = false; 55 + uploadForm.select('input[type="file"]').each(function(fileInput) { 56 + if (fileInput.value == '') { 57 + new XWiki.widgets.Notification("$services.localization.render('xe.attachmentSelector.upload.error.noFile')", 'error'); 58 + hasErrors = true; 59 + } else if (fileInput.__allowedExtensions && fileInput.__allowedExtensions.indexOf(this.getFileExtension(fileInput.value)) == -1) { 60 + new XWiki.widgets.Notification("$services.localization.render('xe.attachmentSelector.upload.error.badExtension')", 'error'); 61 + hasErrors = true; 62 + } 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 + if (!hasErrors) { 67 + if (this.directSave) { 68 + uploadForm.submit(); 69 + } else { 70 + // FIXME This fails in HTML5, will deal with it later: 71 + // this.property.down('input').value = uploadForm.down('input[type="file"]').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')}); 78 + } 79 + } 80 + }.bindAsEventListener(this)); 81 + }, 82 + getFileExtension : function(filename) { 83 + var fpath = filename.replace('\\', '/'); 84 + var pieces = fpath.split('/'); 85 + if (pieces.length == 0) { 86 + return null; 87 + } 88 + var basename = pieces[pieces.length-1]; 89 + pieces = basename.split('.'); 90 + return pieces[pieces.length-1].toLowerCase(); 91 + }, 92 + 93 + /** Catch attachment delete requests. */ 94 + addDeleteListeners : function() { 95 + this.gallery.select('.gallery_actions .tool.delete').invoke('observe', 'click', this.onDelete.bindAsEventListener(this)); 96 + }, 97 + 98 + /** Catch attachment selection requests. */ 99 + addSelectListeners : function() { 100 + this.gallery.select('.gallery_actions .tool.select').invoke('observe', 'click', this.onSelect.bindAsEventListener(this)); 101 + }, 102 + 103 + /** AJAX deletion of attachments. */ 104 + onDelete : function(event) { 105 + event.stop(); 106 + deleteTool = event.element(); 107 + if (!deleteTool.disabled) { 108 + new XWiki.widgets.ConfirmedAjaxRequest( 109 + deleteTool.readAttribute('href'), 110 + { 111 + onCreate : function() { deleteTool.disabled = true }, 112 + onSuccess : function() { 113 + var attachmentBox = deleteTool.up('.gallery_attachmentbox'); 114 + if (attachmentBox) { 115 + if (attachmentBox.hasClassName('current')) { 116 + this.updateAttachment(this.defaultValue, this.defaultImageSource); 117 + if (this.gallery.down('.gallery_emptyChoice')) { 118 + this.gallery.down('.gallery_emptyChoice').addClassName('current'); 119 + } 120 + // Disable the replace feature because there's no selection. 121 + var fileNameInput = this.gallery.down('input[type="checkbox"][name="filename"]'); 122 + fileNameInput.disabled = true; 123 + // Empty the displayed selected file name. 124 + fileNameInput.up('label').down('strong').update(''); 125 + if (!this.directSave) { 126 + this.property.down('input').value = this.defaultValue; 127 + } 128 + } 129 + attachmentBox.remove(); 130 + } 131 + }.bind(this), 132 + onComplete : function() { 133 + deleteTool.disabled = false; 134 + } 135 + }, 136 + { 137 + confirmationText: "$services.localization.render('core.viewers.attachments.delete.confirm')", 138 + progressMessageText : "$services.localization.render('core.viewers.attachments.delete.inProgress')", 139 + successMessageText : "$services.localization.render('core.viewers.attachments.delete.done')", 140 + failureMessageText : "$services.localization.render('core.viewers.attachments.delete.failed')" 141 + } 142 + ); 143 + } 144 + }, 145 + 146 + /** Update the property with the selected value without reloading the page. */ 147 + onSelect : function(event) { 148 + event.stop(); 149 + var targetElement = event.element(); 150 + var attachmentName = targetElement.up('.gallery_attachmentbox').down('.gallery_attachmenttitle').title; 151 + var imageSource = targetElement.up('.gallery_attachmentbox.gallery_image'); 152 + if (imageSource) { 153 + imageSource = imageSource.down('.gallery_attachmentframe img'); 154 + if (imageSource) { 155 + imageSource = imageSource.src.replace(/\?.*$/, ''); 156 + } 157 + } 158 + if (!imageSource) { 159 + imageSource = ''; 160 + } 161 + if (this.directSave) { 162 + // save via ajax 163 + if (!targetElement.disabled) { 164 + new Ajax.Request(event.element().href, { 165 + onCreate : function() { 166 + targetElement.disabled = true; 167 + targetElement._x_notif = new XWiki.widgets.Notification("$services.localization.render('core.widgets.confirmationBox.notification.inProgress')", 'inprogress'); 168 + }, 169 + onSuccess : function () { 170 + targetElement._x_notif.hide(); 171 + // on success, update image 172 + this.updateAttachment(attachmentName, imageSource); 173 + this.dialog.closeDialog(); 174 + }.bindAsEventListener(this), 175 + onFailure : function(response) { 176 + var failureReason = response.statusText; 177 + if (response.statusText == '' /* No response */ || response.status == 12031 /* In IE */) { 178 + failureReason = 'Server not responding'; 179 + } 180 + if (targetElement._x_notif) { 181 + targetElement._x_notif.replace(new XWiki.widgets.Notification("$services.localization.render('core.widgets.confirmationBox.notification.failed')" + failureReason, "error")); 182 + } else { 183 + new XWiki.widgets.Notification(this.interactionParameters.failureMessageText + failureReason, "error"); 184 + } 185 + }, 186 + on1223 : function(response) { 187 + response.request.options.onSuccess(response); 188 + }, 189 + on0 : function(response) { 190 + response.request.options.onFailure(response); 191 + }, 192 + onComplete : function() { 193 + targetElement.disabled = false; 194 + } 195 + }); 196 + } 197 + } else { 198 + this.updateAttachment(attachmentName, imageSource); 199 + this.property.down('input').value = attachmentName; 200 + this.dialog.closeDialog(); 201 + } 202 + }, 203 + 204 + /** Update the property display. */ 205 + updateAttachment : function(attachmentName, imageSource) { 206 + var img = this.property.down('img'); 207 + if (img) { 208 + img.src = img.src.replace(/^[^\?]+($|\?)/, imageSource + "$1"); 209 + var link = img.up('a'); 210 + if (link) { 211 + link.href = link.href.replace(/^[^\?]+($|\?)/, imageSource + "$1"); 212 + } 213 + } else { 214 + var displayed = this.property.down('.displayed'); 215 + if (displayed) { 216 + displayed.update(attachmentName); 217 + var link = displayed.up('a'); 218 + if (link) { 219 + link.href = link.href.replace(/^[^\?]+($|\?)/, attachmentName + "$1"); 220 + } 221 + } 222 + } 223 + }, 224 + 225 + /** Update the gallery to reflect the currently selected value. */ 226 + updateCurrentSelection : function() { 227 + if (!this.directSave) { 228 + var selectedName = this.property.down('input').value; 229 + var selectedElement = this.gallery.down('.gallery_attachmenttitle[title="' + selectedName.replace('"', '\\22 ') + '"]'); 230 + if (selectedElement) { 231 + selectedElement = selectedElement.up('.gallery_attachmentbox'); 232 + } else { 233 + selectedElement = this.gallery.down('.gallery_emptyChoice'); 234 + } 235 + if (!selectedElement.hasClassName('current')) { 236 + this.gallery.select('.gallery_attachmentbox.current .tool.select').invoke('removeClassName', 'hidden'); 237 + this.gallery.select('.gallery_attachmentbox.current').invoke('removeClassName', 'current'); 238 + selectedElement.addClassName('current'); 239 + } 240 + selectedElement.down('.tool.select').addClassName('hidden'); 241 + } else { 242 + this.gallery.down('.current .tool.select').addClassName('hidden'); 243 + } 244 + }, 245 + addCloseListener : function () { 246 + var closeButton = $('attachment-picker-close'); 247 + if (closeButton) { 248 + closeButton.observe('click', function(event) { 249 + event.stop(); 250 + this.dialog.closeDialog(); 251 + }.bindAsEventListener(this)); 252 + } 253 + } 254 + }); 255 + 256 + var loading = new Element('div', {'class' : 'imgcenter'}).update("<img src=\"$xwiki.getSkinFile('icons/xwiki/ajax-loader-large.gif')\"/>"); 257 + var dialog; 258 + 259 + /* Hook onto the picker buttons so that the gallery is loaded via AJAX in a modal dialog. */ 260 + document.observe('xwiki:dom:loaded', function() { 261 + $$('.attachment-picker-start').invoke('observe', 'click', function(event) { 262 + event.stop(); 263 + var targetElement = event.element(); 264 + var url = targetElement.href; 265 + if (url.indexOf('?') < 0) { 266 + url += '?'; 267 + } 268 + url += "&xpage=plain"; 269 + dialog = new XWiki.widgets.ModalPopup( 270 + loading, {}, { 271 + 'verticalPosition' : 'top', 272 + 'removeOnClose' : true, 273 + 'title' : "$services.localization.render('xe.attachmentSelector.gallery.title')" 274 + } 275 + ); 276 + dialog.shortcuts.close.keys = []; 277 + dialog.showDialog(); 278 + dialog.dialog.down().setStyle({position: "fixed"}); 279 + dialog.dialog.setStyle({top: document.viewport.getScrollOffsets().top + "px", position: "absolute"}); 280 + dialog.dialogBox.setStyle({overflow: "hidden", width: "80%", margin: "0 10%"}); 281 + new Ajax.Updater(loading.up(), url, { 282 + onComplete : function() { 283 + // Play nice with the Lightbox widget 284 + if (window.gallery_lb) { 285 + window.gallery_lb.updateImageList(); 286 + } 287 + // Manually convert the special rel values into target attributes for the newly inserted content (rel="_something" => target="something") 288 + if (typeof (XWiki.fixLinksTargetAttribute) == 'function') { 289 + // Trick the function into updating link targets in edit mode; normally the conversion only takes place in view mode 290 + var __tmp = XWiki.contextaction; 291 + XWiki.contextaction = 'view'; 292 + XWiki.fixLinksTargetAttribute(dialog.dialog); 293 + XWiki.contextaction = __tmp; 294 + } 295 + new XWiki.AttachmentPicker(targetElement.up('.attachment-picker'), dialog); 296 + } 297 + }); 298 + }); 299 + }); 300 + return XWiki; 301 +}(XWiki || {})); - Name
-
... ... @@ -1,0 +1,1 @@ 1 +Loads the image picker in a modal dialog - Parse content
-
... ... @@ -1,0 +1,1 @@ 1 +Yes - Use this extension
-
... ... @@ -1,0 +1,1 @@ 1 +currentPage
- XWiki.JavaScriptExtension[1]
-
- Caching policy
-
... ... @@ -1,0 +1,1 @@ 1 +long - Code
-
... ... @@ -1,0 +1,33 @@ 1 +XWiki.widgets.ModalPopup.prototype.showDialog = function(event) { 2 + if (event) { 3 + Event.stop(event); 4 + } 5 + // Only do this if the dialog is not already active. 6 + if (!this.active) { 7 + this.active = true; 8 + if (!this.dialog) { 9 + // The dialog wasn't loaded, create it. 10 + this.createDialog(); 11 + } 12 + // Start listening to keyboard events 13 + this.attachKeyListeners(); 14 + // Display the dialog 15 + this.dialog.show(); 16 + } 17 +}; 18 +XWiki.widgets.ModalPopup.prototype.closeDialog = function(event) { 19 + if (event) { 20 + Event.stop(event); 21 + } 22 + // Call optional callback 23 + this.options.onClose.call(this); 24 + // Hide the dialog, without removing it from the DOM. 25 + this.dialog.hide(); 26 + if (this.options.removeOnClose) { 27 + this.dialog.remove(); 28 + } 29 + // Stop the UI shortcuts (except the initial Show Dialog one). 30 + this.detachKeyListeners(); 31 + // Re-enable the 'show' behavior. 32 + this.active = false; 33 +} - Name
-
... ... @@ -1,0 +1,1 @@ 1 +Patch for modalPopup.js, allowing to display several widgets on the same screen and removing position:fixed in IE - Parse content
-
... ... @@ -1,0 +1,1 @@ 1 +No - Use this extension
-
... ... @@ -1,0 +1,1 @@ 1 +currentPage
- XWiki.StyleSheetExtension[0]
-
- Caching policy
-
... ... @@ -1,0 +1,1 @@ 1 +long - Code
-
... ... @@ -1,0 +1,195 @@ 1 +#template("colorThemeInit.vm") 2 +#set ($boxSize = 170) 3 +#set ($boxPadding = 5) 4 +#set ($boxMargin = 5) 5 +## Make the upload box two times as wide, so that the input fits nicely. 6 +## | | 7 +## | | | | 8 +## | 1 width + 1 border + 2 margins + 1 border + 1 width | 9 +#set ($uploadBoxSize = $mathtool.add(2, $mathtool.add($mathtool.mul($boxSize, 2), $mathtool.mul($boxMargin, 2)))) 10 +#set ($imgSize = $mathtool.sub($boxSize, $mathtool.mul($boxPadding, 2))) 11 +#set ($actionsHeight = 20) 12 +#set ($actionsWidth = 16) 13 +/*--------------------------------------------------------*/ 14 +/* Attachment picker layout fixes */ 15 +.attachment-picker p { 16 + margin: 0; 17 + padding : 0; 18 +} 19 +.attachment-picker picture { 20 + max-width: 100%; 21 +} 22 +/*--------------------------------------------------------*/ 23 +/* Gallery attachmentboxes */ 24 +.gallery p { 25 + margin: 0; 26 +} 27 +.gallery_attachmentbox { 28 + background: $theme.pageContentBackgroundColor; 29 + border: 1px solid $theme.borderColor; 30 + border-radius: 5px; 31 + float: left; 32 + margin: ${boxMargin}px; 33 + overflow: hidden; 34 + position: relative; 35 + width: ${boxSize}px; 36 +} 37 +.gallery .current { 38 + background-color: $theme.highlightColor; 39 + border-width: 3px; 40 + margin: 3px; 41 +} 42 +.gallery .current .gallery_attachmenttitle { 43 + font-weight: bold; 44 +} 45 +.gallery_attachmentbox:hover { 46 + background-color: $theme.highlightColor; 47 +} 48 + 49 +.gallery_attachmenttitle { 50 + background: $theme.backgroundSecondaryColor; 51 + border-bottom: 1px dotted $theme.borderColor; 52 + border-radius: 5px 5px 0px 0px; 53 + font-size: 85%; 54 + padding: 3px ${boxPadding}px; 55 + overflow: hidden; 56 + text-overflow: ellipsis; 57 + white-space: nowrap; 58 +} 59 +.gallery_attachmenttitle p { 60 + text-align: center; 61 + overflow: hidden; 62 +} 63 + 64 +.gallery_attachmentframe { 65 + padding: ${boxPadding}px; 66 + height: ${imgSize}px; 67 + overflow: hidden; 68 + position: relative; 69 +} 70 + 71 +.gallery_attachmentframe a { 72 + display: block; 73 + text-align: center; 74 +} 75 + 76 +.gallery_attachmentbox img { 77 + max-height: ${imgSize}px; 78 + max-width: ${imgSize}px; 79 + width: auto; 80 +} 81 +.gallery_attachmentframe ul { 82 + list-style-type: none; 83 + margin: 0; 84 + padding: 0; 85 +} 86 +.gallery_attachmentframe li { 87 + margin: 0.5em 0 0.5em 20px; 88 + font-size: 0.8em; 89 +} 90 +.gallery_attachmentframe .mime { 91 + margin: 0 2px 0 -20px; 92 +} 93 +.gallery_attachmentframe .mime img { 94 + vertical-align: top; 95 +} 96 +.gallery_attachmentframe li .filename { 97 + display: inline-block; 98 + font-weight: bold; 99 + width: $mathtool.sub($imgSize, 22)px; 100 + word-wrap: break-word; 101 +} 102 + 103 +/* Actions */ 104 +.gallery_actions { 105 + width: auto; 106 + position: absolute; 107 + bottom: 0px; 108 + right: ${boxPadding}px; 109 +} 110 +.gallery_actions .tool { 111 + background: none no-repeat 50% transparent; 112 + cursor: pointer; 113 + display: block; 114 + float: left; 115 + height: ${actionsHeight}px; 116 + padding: 0 !important; 117 + overflow: hidden; 118 + text-indent: -1000em; 119 + opacity: 0.6; 120 + width: ${actionsWidth}px; 121 +} 122 +.gallery_actions .tool:hover { 123 + opacity: 1; 124 +} 125 +.gallery_actions .select { 126 + background-image: url("$xwiki.getSkinFile('icons/silk/tick.png')"); 127 +} 128 +.gallery_actions .delete { 129 + background-image: url("$xwiki.getSkinFile('icons/silk/cross.png')"); 130 +} 131 +.gallery_actions .view { 132 + background-image: url("$xwiki.getSkinFile('icons/silk/link.png')"); 133 +} 134 +.gallery_actions .download { 135 + background-image: url("$xwiki.getSkinFile('icons/silk/arrow_down.png')"); 136 +} 137 +/*--------------------------------------------------*/ 138 +/* Upload form */ 139 +.gallery_upload { 140 + ## Make this box twice as large as the others 141 + width: ${uploadBoxSize}px; 142 +} 143 +* html .gallery_upload { 144 + width: ${mathtool.add($uploadBoxSize, 2)}px; 145 +} 146 +.gallery_upload, .gallery_upload:hover { 147 + background-color: $theme.backgroundSecondaryColor; 148 +} 149 + 150 +.gallery_upload .gallery_attachmenttitle { 151 + background-position: 1px center; 152 + background-image: url("$xwiki.getSkinFile('icons/silk/bullet_add.png')"); 153 + background-repeat: no-repeat; 154 + padding-left: 16px; 155 +} 156 +.gallery_upload .gallery_attachmentframe { 157 + height: auto; 158 +} 159 +.gallery_upload_input { 160 + margin-bottom: 10px; 161 +} 162 +.gallery_upload input[type="file"] { 163 + font-size: 86%; 164 + width: ${mathtool.sub($uploadBoxSize, $mathtool.mul($boxPadding, 2))}px; 165 +} 166 +.gallery_upload .buttonwrapper { 167 + margin: 0; 168 +} 169 +.gallery_upload .button, 170 +.gallery_upload label { 171 + font-size: 86%; 172 +} 173 +.gallery_upload input[type="checkbox"] { 174 + vertical-align: text-bottom; 175 +} 176 +.gallery_upload label[for="commentinput"] { 177 + margin-top: 10px; 178 +} 179 + 180 +/* ------------------------------------ */ 181 +/* Buttons on top: */ 182 +.gallery_actions { 183 + top: 1px; 184 + right: 3px; 185 +} 186 +.gallery_attachmenttitle p { 187 + text-align: left; 188 + margin-right: ${mathtool.add($mathtool.mul(2, $actionsWidth), $boxPadding)}px; 189 +} 190 +/* ------------------------------------ */ 191 +/* Cancel button */ 192 +.gallery_buttons { 193 + clear: both; 194 + margin: ${boxMargin}px; 195 +} - Name
-
... ... @@ -1,0 +1,1 @@ 1 +Attachment galery styling - Parse content
-
... ... @@ -1,0 +1,1 @@ 1 +Yes - Use this extension
-
... ... @@ -1,0 +1,1 @@ 1 +onDemand
- XWiki.WikiMacroClass[0]
-
- Macro code
-
... ... @@ -1,0 +1,158 @@ 1 +{{velocity output="false"}} 2 +$xwiki.jsfx.use('js/xwiki/widgets/modalPopup.js', true)## 3 +$xwiki.ssfx.use('js/xwiki/widgets/modalPopup.css', true)## 4 +$xwiki.jsx.use($xcontext.macro.doc.fullName)## 5 +$xwiki.ssx.use($xcontext.macro.doc.fullName)## 6 +$xwiki.jsfx.use('js/scriptaculous/builder.js')## 7 +## Integrates the optional Lightbox widget (from http://extensions.xwiki.org/xwiki/bin/view/Extension/Lightbox+Application ) 8 +#if ($xwiki.exists('XWiki.Lightbox')) 9 + $xwiki.jsx.use('XWiki.Lightbox') 10 + $xwiki.ssx.use('XWiki.Lightbox') 11 +#end 12 + 13 +## 14 +## Prepare parameters 15 +## 16 +## Keep track for when we have a target document 17 +#set ($hasTargetDoc = false) 18 +#set ($targetdoc = "$!{xcontext.macro.params.targetdocname}") 19 +### 20 +## Set the targetdoc we want to save to (default to current doc if not set) 21 +#if ("$!{targetdoc}" != '') 22 + ## Check access on targetdocname 23 + #set ($targetPermView = $xwiki.hasAccessLevel('view',$xcontext.user,${targetdoc})) 24 + #set ($targetPermEdit = $xwiki.hasAccessLevel('edit',$xcontext.user,${targetdoc})) 25 + #set ($targetdoc = $xwiki.getDocument($targetdoc) ) 26 + #set ($hasTargetDoc = true) 27 +#else 28 + ## The user should have edit and view permissions for the current doc 29 + #set ($targetPermView = true) 30 + #set ($targetPermEdit = true) 31 + #set($targetdoc = $doc) 32 +#end 33 +#set ($classname = "$!{xcontext.macro.params.classname}") 34 +#set ($property = "$!{xcontext.macro.params.property}") 35 +#set ($object = $mathtool.toInteger("$!{xcontext.macro.params.object}")) 36 +#if ("$!{object}" != $!{xcontext.macro.params.object}) 37 + #set ($object = ${doc.getObject($classname).number}) 38 + #if ("$!{object}" == '') 39 + #set ($object = 0) 40 + #end 41 +#end 42 + 43 +#if ("$!{xcontext.macro.params.displayImage}" == 'true' && $targetPermView) 44 + #set ($displayImage = true) 45 +#else 46 + #set ($displayImage = false) 47 +#end 48 +#if ($displayImage) 49 + #set ($alt = "$!{xcontext.macro.params.alternateText}") 50 + #set ($width = "$!{xcontext.macro.params.width}") 51 + #set ($height = "$!{xcontext.macro.params.height}") 52 + #set ($imageParams = '') 53 + #if ("${width}" != '') 54 + #set($imageParams = "$!{imageParams} width=${width}") 55 + #end 56 + #if ("${height}" != '') 57 + #set ($imageParams = "$!{imageParams} height=${height}") 58 + #end 59 + #set ($imageParams = "$!{imageParams} alt='${alt}'") 60 + #if ("$!{imageParams}" != '') 61 + #set ($imageParams = "||${imageParams.trim()}") 62 + #end 63 +#end 64 +#if ("$!{xcontext.macro.params.link}" == 'true') 65 + #set ($link = true) 66 +#else 67 + #set ($link = false) 68 +#end 69 + 70 +#set ($cssClass = "displayed x-attachment $!{xcontext.macro.params.cssClass}") 71 +#set ($defaultValue = "$!{xcontext.macro.params.defaultValue}") 72 +#if ($defaultValue != '') 73 + #set ($defaultReference = $services.model.resolveAttachment($defaultValue)) 74 +#else 75 + #set ($defaultReference = false) 76 +#end 77 +#set ($filter = ${xcontext.macro.params.filter}) 78 + 79 +#set ($buttontext = "$!{xcontext.macro.params.buttontext}") 80 +#if ($buttontext == '') 81 + #set ($buttontext = $services.localization.render('xe.attachmentSelector.selectFile')) 82 +#end 83 + 84 +#set ($savemode = "$!{xcontext.macro.params.savemode}") 85 +#if ($savemode != 'direct') 86 + #set ($savemode = 'form') 87 +#end 88 + 89 +#set ($propValue = "$!{doc.getObject($classname, $object).getProperty($property).value}") 90 +## 91 + 92 +#macro (attachmentPicker_displayAttachment $name $displayImage $withLink $forceElement) 93 + #set ($attachment = $targetdoc.getAttachment("$!{name}")) 94 + #if ("$!{name}" != '' && "$!{attachment}" != '') 95 + #set ($attachmentRef = $services.model.createAttachmentReference(${targetdoc.documentReference}, ${name})) 96 + #set ($attachmentName = $name) 97 + #else 98 + #set ($attachmentRef = $defaultReference) 99 + #if ($attachmentRef) 100 + #set ($docReference = $attachmentRef.documentReference) 101 + #else 102 + #set ($docReference = $targetdoc.documentReference) 103 + #end 104 + #set ($attachmentName = $attachmentRef.name) 105 + #set ($attachment = $xwiki.getDocument($docReference).getAttachment($attachmentName)) 106 + #if (!$attachment) 107 + #set ($withLink = false) 108 + #end 109 + #end 110 + #if ($attachmentRef) 111 + #set ($attachmentResource = $services.model.serialize($attachmentRef, 'local')) 112 + #else 113 + #set ($attachmentResource = '') 114 + #end 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)))## 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(%%)## 119 + #end 120 +#end 121 + 122 +## Display the "Choose an attachment" button if they can: 123 +## 1. Edit the current page 124 +## 2. View the target attachment page. (can be the same page) 125 +#macro (attachmentPicker_displayButton) 126 + #if ($hasEdit && $targetPermView) 127 + #set ($queryString = { 128 + 'docname': $doc.fullName, 129 + 'classname': $classname, 130 + 'property': $property, 131 + 'object': $object, 132 + 'savemode': $savemode, 133 + 'defaultValue': $defaultValue, 134 + 'filter': $filter, 135 + 'displayImage': $displayImage, 136 + 'versionSummary': $xcontext.macro.params.versionSummary.equals('true') 137 + }) 138 + #if ($hasTargetDoc) 139 + #set ($queryString.targetdocname = $targetdoc.fullName) 140 + #end 141 + (% class="buttonwrapper" %)[[$buttontext>>$xcontext.macro.doc.fullName||queryString="$escapetool.url($queryString)" 142 + class="attachment-picker-start button" title="$buttontext"]](%%)## 143 + #end 144 +#end 145 +{{/velocity}} 146 + 147 +{{velocity}} 148 +#if ("${savemode}" == 'direct') 149 + (% class="attachment-picker" %)(((#attachmentPicker_displayAttachment($propValue $displayImage $link true) #attachmentPicker_displayButton()))) 150 +#elseif ($xcontext.action == 'inline' || $xcontext.action == 'edit') 151 + (% class="attachment-picker" %)(((## 152 + #attachmentPicker_displayAttachment($propValue $displayImage false true) #attachmentPicker_displayButton()## 153 + {{html}}<input type="hidden" name="${classname}_${object}_${property}" value="${propValue}"/>{{/html}}## 154 + ))) 155 +#else 156 + #attachmentPicker_displayAttachment($propValue $displayImage $link false) 157 +#end 158 +{{/velocity}} - Macro content type
-
... ... @@ -1,0 +1,1 @@ 1 +No content - Default category
-
... ... @@ -1,0 +1,1 @@ 1 +Development - Macro description
-
... ... @@ -1,0 +1,1 @@ 1 +A control to be used for object properties of the current document that are supposed to contain the name of an attachment from the current (or target) document. Allows uploading new attachments, and deleting attachments from the target document. If no target document is specified, the current document will be used. Object properties are only saved to the current document. - Macro id
-
... ... @@ -1,0 +1,1 @@ 1 +attachmentSelector - Macro name
-
... ... @@ -1,0 +1,1 @@ 1 +Attachment Selector - Supports inline mode
-
... ... @@ -1,0 +1,1 @@ 1 +Yes - Macro visibility
-
... ... @@ -1,0 +1,1 @@ 1 +Current Wiki
- XWiki.WikiMacroParameterClass[0]
-
- Parameter description
-
... ... @@ -1,0 +1,1 @@ 1 +The full name of the document holding the XClass that contains the property associated with this picker. - Parameter mandatory
-
... ... @@ -1,0 +1,1 @@ 1 +Yes - Parameter name
-
... ... @@ -1,0 +1,1 @@ 1 +classname
- XWiki.WikiMacroParameterClass[1]
-
- Parameter description
-
... ... @@ -1,0 +1,1 @@ 1 +The name of the property associated with the picker. - Parameter mandatory
-
... ... @@ -1,0 +1,1 @@ 1 +Yes - Parameter name
-
... ... @@ -1,0 +1,1 @@ 1 +property
- XWiki.WikiMacroParameterClass[2]
-
- Parameter description
-
... ... @@ -1,0 +1,1 @@ 1 +The identifier (number) of the object for which the property is displayed by this picker. If missing, the first instance of the class given by the parameter classname found in the document will be considered. - Parameter mandatory
-
... ... @@ -1,0 +1,1 @@ 1 +No - Parameter name
-
... ... @@ -1,0 +1,1 @@ 1 +object
- XWiki.WikiMacroParameterClass[5]
-
- Parameter description
-
... ... @@ -1,0 +1,1 @@ 1 +A CSS class for the element surrounding the property value. - Parameter mandatory
-
... ... @@ -1,0 +1,1 @@ 1 +No - Parameter name
-
... ... @@ -1,0 +1,1 @@ 1 +cssClass
- XWiki.WikiMacroParameterClass[6]
-
- Parameter default value
-
... ... @@ -1,0 +1,1 @@ 1 +form - Parameter description
-
... ... @@ -1,0 +1,1 @@ 1 +States how the property is updated. Accepted values: "form" (default) meaning that the selected value is stored in an input that will be saved via an external form; "direct" meas that the picker is responsible with updating the property value. - Parameter mandatory
-
... ... @@ -1,0 +1,1 @@ 1 +No - Parameter name
-
... ... @@ -1,0 +1,1 @@ 1 +savemode
- XWiki.WikiMacroParameterClass[7]
-
- Parameter description
-
... ... @@ -1,0 +1,1 @@ 1 +Text of the button that triggers the picker. Defaults to $services.localization.render('xe.attachmentSelector.selectFile'). - Parameter mandatory
-
... ... @@ -1,0 +1,1 @@ 1 +No - Parameter name
-
... ... @@ -1,0 +1,1 @@ 1 +buttontext
- XWiki.WikiMacroParameterClass[10]
-
- Parameter description
-
... ... @@ -1,0 +1,1 @@ 1 +What attachment is displayed in view mode if the property is empty. Should either be empty or in the form of a wiki attachment reference (e.g. "attachment.txt", "Another.Document@attachment.txt"). - Parameter mandatory
-
... ... @@ -1,0 +1,1 @@ 1 +No - Parameter name
-
... ... @@ -1,0 +1,1 @@ 1 +defaultValue
- XWiki.WikiMacroParameterClass[12]
-
- Parameter description
-
... ... @@ -1,0 +1,1 @@ 1 +Comma separated list of file extensions accepted by the property (to become a comma separated list of mimetypes when XWiki will use HTML5). All files are accepted if this parameter is empty. - Parameter mandatory
-
... ... @@ -1,0 +1,1 @@ 1 +No - Parameter name
-
... ... @@ -1,0 +1,1 @@ 1 +filter
- XWiki.WikiMacroParameterClass[13]
-
- Parameter default value
-
... ... @@ -1,0 +1,1 @@ 1 +false - Parameter description
-
... ... @@ -1,0 +1,1 @@ 1 +States whether images are displayed or just their name is printed like for other attachments. Possible values: true, false (default). - Parameter mandatory
-
... ... @@ -1,0 +1,1 @@ 1 +No - Parameter name
-
... ... @@ -1,0 +1,1 @@ 1 +displayImage
- XWiki.WikiMacroParameterClass[14]
-
- Parameter description
-
... ... @@ -1,0 +1,1 @@ 1 +The width of the displayed image, only taken into account if displayImage=true. - Parameter mandatory
-
... ... @@ -1,0 +1,1 @@ 1 +No - Parameter name
-
... ... @@ -1,0 +1,1 @@ 1 +width
- XWiki.WikiMacroParameterClass[15]
-
- Parameter description
-
... ... @@ -1,0 +1,1 @@ 1 +The height of the displayed image, only taken into account if displayImage=true - Parameter mandatory
-
... ... @@ -1,0 +1,1 @@ 1 +No - Parameter name
-
... ... @@ -1,0 +1,1 @@ 1 +height
- XWiki.WikiMacroParameterClass[16]
-
- Parameter description
-
... ... @@ -1,0 +1,1 @@ 1 +The alternate text of the displayed image, only taken into account if displayImage=true - Parameter mandatory
-
... ... @@ -1,0 +1,1 @@ 1 +No - Parameter name
-
... ... @@ -1,0 +1,1 @@ 1 +alternateText
- XWiki.WikiMacroParameterClass[17]
-
- Parameter default value
-
... ... @@ -1,0 +1,1 @@ 1 +false - Parameter description
-
... ... @@ -1,0 +1,1 @@ 1 +States whether a link to the attachment is associated in view mode with the displayed attachment name/image. Possible values: true, false (default). - Parameter mandatory
-
... ... @@ -1,0 +1,1 @@ 1 +No - Parameter name
-
... ... @@ -1,0 +1,1 @@ 1 +link
- XWiki.WikiMacroParameterClass[18]
-
- Parameter description
-
... ... @@ -1,0 +1,1 @@ 1 +The target document name to save/list attachments from - Parameter mandatory
-
... ... @@ -1,0 +1,1 @@ 1 +No - Parameter name
-
... ... @@ -1,0 +1,1 @@ 1 +targetdocname
- XWiki.WikiMacroParameterClass[19]
-
- Parameter default value
-
... ... @@ -1,0 +1,1 @@ 1 +false - 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 - Parameter name
-
... ... @@ -1,0 +1,1 @@ 1 +versionSummary