Attachment 'AttachmentDialog.patch'
Download 1 # HG changeset patch
2 # User Josef Meier <jo.meier@gmx.de>
3 # Date 1258914915 -3600
4 # Node ID 2e2bce28e785279f554a9188070f627193d8644e
5 # Parent af42eec12f386db44f3d104327c16fbec67a486d
6 Improved attachment dialog for GUI editor.
7
8 New features:
9 - available attachments are listed in a drop down list
10 - also attachments for a different page can be fetched and listed in the drop down list.
11 - new attachments can be created.
12 - error messages like 'Page doesn't exist', ...
13 - i18n support
14
15 --- a/MoinMoin/action/fckdialog.py Sat Nov 21 16:31:36 2009 +0100
16 +++ b/MoinMoin/action/fckdialog.py Sun Nov 22 19:35:15 2009 +0100
17 @@ -7,6 +7,8 @@
18 """
19
20 from MoinMoin import config, wikiutil
21 +from MoinMoin.action.AttachFile import _get_files
22 +from MoinMoin.Page import Page
23 import re
24
25 ##############################################################################
26 @@ -357,38 +359,87 @@
27 </html>
28 ''' % locals())
29
30 -##############################################################################
31 -### Attachment dialog
32 -##############################################################################
33
34 def attachment_dialog(request):
35 - # list of wiki pages
36 - name = request.values.get("pagename", "")
37 - if name:
38 - from MoinMoin import search
39 - # XXX error handling!
40 - searchresult = search.searchPages(request, 't:"%s"' % name)
41 -
42 - pages = [p.page_name for p in searchresult.hits]
43 - pages.sort()
44 - pages[0:0] = [name]
45 - page_list = '''
46 - <tr>
47 - <td colspan=2>
48 - <select id="sctPagename" size="1" onchange="OnChangePagename(this.value);">
49 - %s
50 - </select>
51 - <td>
52 - </tr>
53 -''' % "\n".join(['<option value="%s">%s</option>' % (page, page)
54 - for page in pages])
55 - else:
56 - page_list = ""
57 + """ Attachment dialog for GUI editor. """
58 + """ Features: This dialog can... """
59 + """ - list attachments in a drop down list """
60 + """ - list attachments also for a different page than the current one """
61 + """ - create new attachment """
62 + _ = request.getText
63 + url_prefix_static = request.cfg.url_prefix_static
64
65 # wiki url
66 - url_prefix_static = request.cfg.url_prefix_static
67 - scriptname = request.script_root + '/'
68 + scriptname = request.getScriptname()
69 + if not scriptname or not scriptname.endswith('/'):
70 + scriptname += "/"
71 action = scriptname
72 +
73 + # The following code lines implement the feature "list attachments for a different page".
74 + # Meaning of the variables:
75 + # - requestedPagename : Name of the page where attachments shall be listed from.
76 + # - attachmentsPagename : Name of the page where the attachments where retrieved from.
77 + # - destinationPagename : Name of the page where attachment will be placed on.
78 +
79 + requestedPagename = request.values.get("requestedPagename", "")
80 + destinationPagename = wikiutil.escape(request.values.get("destinationPagename", request.page.page_name))
81 +
82 + if requestedPagename == "":
83 + attachmentsPagename = request.page.page_name
84 + else:
85 + attachmentsPagename = requestedPagename
86 +
87 + attachments = []
88 + page = Page(request, attachmentsPagename)
89 + if page.exists():
90 + attachments = _get_files(request, attachmentsPagename)
91 +
92 + if not attachments:
93 + status = 1 # No attachments on this page.
94 + firstDropDownEntry = "<%s>" % _("No attachments found")
95 + else:
96 + status = 2 # Attachments found.
97 + firstDropDownEntry = "<%s>" % _("Select")
98 + attachments.sort()
99 + else:
100 + status = 0 # Page not found.
101 + firstDropDownEntry = "<%s>" % _("Page not found")
102 +
103 + attachments.insert(0, wikiutil.escape(firstDropDownEntry))
104 + attachmentList = '''
105 + <select id="sctAttachments" size="1" style="width:100%%">
106 + %s
107 + </select>
108 +''' % "\n".join(['<option value="%s">%s</option>' % (attachment, attachment)
109 + for attachment in attachments])
110 +
111 + # Translation of dialog texts.
112 + langRadioSelectAttachment = _("Select existing attachment")
113 + langRadioCreateNewAttachment = _("Create new attachment")
114 + langListAttachmentsButton = _("List attachments")
115 + langListAttachmentsForPage = _("List attachments for page:")
116 + langAttachmentList = _("Attachments")
117 + langNameNewAttachment = _("Name of the attachment")
118 + langNewAttachmentFormat = wikiutil.escape("%s: <%s></><%s>" % (_("Format"), _("Pagename"), _("Attachment name")))
119 + langExamples = _("Examples:")
120 + langExample1 = _("('test.pdf' is on current page)")
121 + langExample2 = _("('test.pdf' is on page 'test')")
122 + langExample3 = _("('test.pdf' is on page 'test1/test2')")
123 + langFurtherInfo = _("After you saved the page, an attachment symbol will be visible.")
124 +
125 + # Translation for the javascript part of this dialog.
126 + langPageAttachmentNotFound = _("Page '%s' (and attachment '%s') not found!")
127 + langPageNotFound = _("Page '%s' not found!")
128 + langAttachmentNotFound = _("Attachment '%s' couldn't be found on page '%s'!\n\nAdd this attachment before using it.")
129 + langAttachmentNotFoundMarker = _("Not found: %s")
130 + langAlertMissingPageName = _("Please enter a page name!")
131 + langAlertMissingAttachment = _("Please select an attachment from the drop down list!")
132 + langAlertInvalidDropDownList = _(""
133 +"You entered a different page's name.\nTherefore the content of the current "
134 +"drop down list is invalid now.\n\nPlease press the button 'List attachments' "
135 +"to get attachments for the remote page!")
136 + langAlertMissingNewAttachmentName = _("Please enter a name for the new attachment!")
137 +
138 request.write('''
139 <!--
140 * FCKeditor - The text editor for internet
141 @@ -422,31 +473,101 @@
142 <script src="%(url_prefix_static)s/applets/moinFCKplugins/moinurllib.js" type="text/javascript"></script>
143 </head>
144 <body scroll="no" style="OVERFLOW: hidden">
145 - <div id="divInfo">
146 - <div id="divLinkTypeAttachment">
147 - <table height="100%%" cellSpacing="0" cellPadding="0" width="100%%" border="0">
148 - <tr>
149 - <td>
150 - <form action=%(action)s method="GET">
151 - <input type="hidden" name="action" value="fckdialog">
152 - <input type="hidden" name="dialog" value="attachment">
153 - <table cellSpacing="0" cellPadding="0" align="center" border="0">
154 + <form id="DlgAttachmentForm" name="DlgAttachmentForm" action=%(action)s method="GET">
155 + <input type="hidden" name="action" value="fckdialog">
156 + <input type="hidden" name="dialog" value="attachment">
157 + <input type="hidden" id="requestedPagename" name="requestedPagename" value="%(requestedPagename)s">
158 + <input type="hidden" id="attachmentsPagename" name="attachmentsPagename" value="%(attachmentsPagename)s">
159 + <input type="hidden" id="destinationPagename" name="destinationPagename" value="%(destinationPagename)s">
160 + <input type="hidden" id="status" name="status" value="%(status)s">
161 + <input type="hidden" id="langPageAttachmentNotFound" value="%(langPageAttachmentNotFound)s">
162 + <input type="hidden" id="langPageNotFound" value="%(langPageNotFound)s">
163 + <input type="hidden" id="langAttachmentNotFound" value="%(langAttachmentNotFound)s">
164 + <input type="hidden" id="langAttachmentNotFoundMarker" value="%(langAttachmentNotFoundMarker)s">
165 + <input type="hidden" id="langAlertMissingPageName" value="%(langAlertMissingPageName)s">
166 + <input type="hidden" id="langAlertMissingAttachment" value="%(langAlertMissingAttachment)s">
167 + <input type="hidden" id="langAlertInvalidDropDownList" value="%(langAlertInvalidDropDownList)s">
168 + <input type="hidden" id="langAlertMissingNewAttachmentName" value="%(langAlertMissingNewAttachmentName)s">
169 +
170 + <div id="divInfo" style="valign=top;">
171 + <div id="divLinkTypeAttachment">
172 + <table cellSpacing="0" cellPadding="0" width="100%%" border="0">
173 <tr>
174 - <td>
175 - <span fckLang="AttachmentDlgName">Attachment Name</span><br>
176 - <input id="txtAttachmentname" name="pagename" size="30" value="%(name)s">
177 - </td>
178 + <td>
179 + <input type="radio" name="radioCreateSelectAttachment" id="radioSelectAttachment" value="1" onchange="OnCreateSelectChange();">
180 + </td>
181 + <td>
182 + <span id="DlgRadioSelectAttachment">%(langRadioSelectAttachment)s</span><br>
183 + </td>
184 </tr>
185 - </table>
186 - </form>
187 - </td>
188 - </tr>
189 + <tr>
190 + <td>
191 +
192 + </td>
193 + <td>
194 + <fieldset>
195 + <table cellSpacing="0" cellPadding="0" width="100%%" border="0">
196 + <tr width="100%%">
197 + <td valign="bottom" style="width:100%%" style="padding-top:10px">
198 + <span id="DlgAttachmentPage">%(langListAttachmentsForPage)s</span><br>
199 + <input id="txtAttachmentPagename" type="text" onkeyup="OnAttachmentPagenameChange();" onchange="OnAttachmentPagenameChange();" style="width:100%%">
200 + </td>
201 + <td valign="bottom" style="padding-left:10px">
202 + <input id=btnListAttachments type="submit" value="%(langListAttachmentsButton)s">
203 + </td>
204 + </tr>
205 + <tr>
206 + <td valign="top" style="padding-top:10px">
207 + <span id="DlgAttachmentList">%(langAttachmentList)s</span><br>
208 + %(attachmentList)s
209 + </td>
210 + <td>
211 +
212 + </td>
213 + </tr>
214 + </table>
215 + </fieldset>
216 + </td>
217 + </tr>
218 + <tr>
219 + <td>
220 + <input type="radio" name="radioCreateSelectAttachment" id="radioCreateAttachment" value="2" onchange="OnCreateSelectChange();">
221 + </td>
222 + <td>
223 + <span id="DlgRadioCreateAttachment">%(langRadioCreateNewAttachment)s</span><br>
224 + </td>
225 + </tr>
226 + <tr>
227 + <td>
228 +
229 + </td>
230 + <td>
231 + <fieldset>
232 + <table cellSpacing="0" cellPadding="0" width="100%%" border="0">
233 + <tr>
234 + <td>
235 + <span id="DlgNewAttachmentName">%(langNameNewAttachment)s</span><br>
236 + <input id="txtNewAttachmentName" size="30" type="text"><br>
237 + <span id="DlgNewAttachmentInfo">%(langNewAttachmentFormat)s<br>
238 + %(langExamples)s<br>
239 + <span><ul><li><b><i>test.pdf</i></b> %(langExample1)s</li>
240 + <li><b><i>test/test.pdf</i></b> %(langExample2)s</li>
241 + <li><b><i>test1/test2/test.pdf</i></b> %(langExample3)s</li></ul></span>
242 + %(langFurtherInfo)s</span>
243 + </td>
244 + </tr>
245 + </table>
246 + </fieldset>
247 + </td>
248 + </tr>
249 </table>
250 </div>
251 </div>
252 + </form>
253 </body>
254 </html>
255 ''' % locals())
256 +
257
258 ##############################################################################
259 ### Image dialog
260 --- a/MoinMoin/web/static/htdocs/applets/moinFCKplugins/moinattachment/fck_attachment.js Sat Nov 21 16:31:36 2009 +0100
261 +++ b/MoinMoin/web/static/htdocs/applets/moinFCKplugins/moinattachment/fck_attachment.js Sun Nov 22 19:35:15 2009 +0100
262 @@ -18,22 +18,12 @@
263 * Frederico Caldeira Knabben (fredck@fckeditor.net)
264 */
265
266 -var dialog = window.parent ;
267 -var oEditor = dialog.InnerDialogLoaded() ;
268 +var dialog = window.parent;
269 +var oEditor = dialog.InnerDialogLoaded();
270 var FCK = oEditor.FCK;
271 var FCKLang = oEditor.FCKLang;
272 var FCKConfig = oEditor.FCKConfig;
273 -
274 -//#### Dialog Tabs
275 -
276 -// Set the dialog tabs.
277 -window.parent.AddTab('Info', FCKLang.DlgLnkInfoTab);
278 -
279 -// Function called when a dialog tag is selected.
280 -function OnDialogTabChange(tabCode)
281 -{
282 - ShowE('divInfo' , (tabCode == 'Info'));
283 -}
284 +var invalidAttachmentList = false;
285
286 //#### Regular Expressions library.
287 var oRegex = new Object();
288 @@ -57,105 +47,378 @@
289 //#### Initialization Code
290
291 // oLink: The actual selected link in the editor.
292 -var oLink = dialog.Selection.GetSelection().MoveToAncestorNode( 'A' ) ;
293 -if ( oLink )
294 - FCK.Selection.SelectNode( oLink ) ;
295 +var oLink = dialog.Selection.GetSelection().MoveToAncestorNode('A');
296 +if (oLink)
297 + FCK.Selection.SelectNode(oLink);
298
299 window.onload = function()
300 {
301 - // Translate the dialog box texts.
302 - oEditor.FCKLanguageManager.TranslatePage(document);
303 + // Translate the dialog box texts.
304 + oEditor.FCKLanguageManager.TranslatePage(document);
305
306 - // Load the selected link information (if any).
307 - LoadSelection();
308 + // Load the selected link information (if any).
309 + LoadSelection();
310
311 - // Show the initial dialog content.
312 - GetE('divInfo').style.display = '';
313 + // Initialize the user interface.
314 + var attachmentsPagename = GetE('attachmentsPagename').value;
315 + GetE('requestedPagename').value = attachmentsPagename;
316 + GetE('txtAttachmentPagename').value = attachmentsPagename;
317
318 - // Activate the "OK" button.
319 - window.parent.SetOkButton(true);
320 + GetE('radioSelectAttachment').checked = true;
321 + OnCreateSelectChange();
322
323 - // select first text input element of dialog for usability
324 - SelectField('txtAttachmentname');
325 + // Activate the "OK" button.
326 + window.parent.SetOkButton(true);
327 }
328 +
329
330 function LoadSelection()
331 {
332 - if (!oLink) return;
333 + if (!oLink)
334 + return;
335
336 if (oLink.getAttribute('title') && oLink.getAttribute('title').StartsWith('attachment:'))
337 {
338 - GetE('txtAttachmentname').value = decodeUrl(oLink.getAttribute('title').Remove(0, 'attachment:'.length));
339 + SetBasePageAttachName(oLink.getAttribute('title').Remove(0, 'attachment:'.length));
340 }
341 }
342
343 -//#### Link type selection.
344 -function SetLinkType(linkType)
345 +
346 +// Escape '<', '>', '&' and '"' to avoid XSS issues.
347 +function escapeHTML(text)
348 {
349 - ShowE('divLinkTypeAttachment' , (linkType == 'attachment'));
350 + return text.replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
351 }
352
353 -//#### Called when user selects Wikipage.
354 -function OnChangePagename(pagename)
355 +
356 +function OnClickListAttachments()
357 {
358 - GetE("txtPagename").value = pagename;
359 + var requested = GetE('requestedPagename').value;
360 + GetE('requestedPagename').value = escapeHTML(requested);
361 }
362
363 -//#### Called while the user types the URL.
364 -function OnUrlChange()
365 +
366 +// Try to set selected attachment's name and source page name into the dialog.
367 +function SetBasePageAttachName(path)
368 {
369 - var sUrl = GetE('txtUrl').value;
370 - var sProtocol = oRegex.UrlOnChangeProtocol.exec(sUrl);
371 + path = decodeUrl(path);
372
373 - if (sProtocol)
374 + var idx = path.lastIndexOf('/'); // Image points to a different page ?
375 + var requestedPagename = GetE('requestedPagename').value;
376 + var attachmentsPagename = GetE('attachmentsPagename').value;
377 + var status = GetE('status').value;
378 + var currPicPagename = path.substring(0, idx);
379 + var currPicName = path.substring(idx+1, path.length);
380 +
381 + // If there is a request for an attachment located on a different page
382 + // then we request a list of attachments for that page.
383 + if ((currPicPagename != "") && (currPicPagename != attachmentsPagename))
384 {
385 - sUrl = sUrl.substr(sProtocol[0].length);
386 - GetE('txtUrl').value = sUrl;
387 + if (requestedPagename == "")
388 + {
389 + GetE('requestedPagename').value = currPicPagename;
390 + document.DlgAttachmentForm.submit(); // Transmit the form data and reload image dialog.
391 + return;
392 + }
393 }
394 - else if (oRegex.UrlOnChangeTestOther.test(sUrl))
395 + else
396 {
397 - GetE('cmbLinkProtocol').value = '';
398 + if (idx != -1)
399 + {
400 + GetE('txtAttachmentPagename').value = currPicPagename;
401 + GetE('sctAttachments').value = currPicName;
402 + }
403 + else
404 + {
405 + currPicName = path;
406 + GetE('txtAttachmentPagename').value = attachmentsPagename;
407 + GetE('sctAttachments').value = currPicName;
408 + }
409 + }
410 +
411 + // Check if the page and the attachment exist.
412 + if (status == 0)
413 + {
414 + if (currPicPagename == requestedPagename)
415 + {
416 + alert(LanguageString("langPageAttachmentNotFound", requestedPagename, currPicName));
417 + AppendDropDownList(LanguageString("langAttachmentNotFoundMarker", currPicName), currPicName);
418 + }
419 + else
420 + alert(LanguageString("langPageNotFound", attachmentsPagename));
421 + }
422 + else if (GetE('sctAttachments').value != currPicName && (currPicPagename == requestedPagename || requestedPagename == ""))
423 + {
424 + alert(LanguageString("langAttachmentNotFound", currPicName, attachmentsPagename));
425 + AppendDropDownList("Not found: " + currPicName, currPicName);
426 }
427 }
428 +
429 +
430 +// Append option to drop down list.
431 +function AppendDropDownList(text, value)
432 +{
433 + // Add missing attachment to drop down list.
434 + var optn = document.createElement("OPTION");
435 + optn.text = text;
436 + optn.value = value;
437 + GetE('sctAttachments').options.add(optn);
438 + GetE('sctAttachments').value = value;
439 +}
440 +
441 +
442 +// If the user changes the radio button's states, all unneeded dialog elements
443 +// will be grayed out here. Also all needed dialog elements will be ungrayed.
444 +function OnCreateSelectChange()
445 +{
446 + if (!GetE('radioCreateAttachment').checked)
447 + {
448 + GetE('txtNewAttachmentName').disabled = true;
449 + GetE('DlgNewAttachmentName').style.color = "gray";
450 + GetE('DlgNewAttachmentInfo').style.color = "gray";
451 +
452 + GetE('DlgAttachmentPage').style.color = "black";
453 + GetE('DlgAttachmentList').style.color = "black";
454 + GetE('txtAttachmentPagename').disabled = false;
455 + GetE('btnListAttachments').disabled = true;
456 + GetE('sctAttachments').disabled = false;
457 + }
458 + else
459 + {
460 + GetE('txtNewAttachmentName').disabled = false;
461 + GetE('DlgNewAttachmentName').style.color = "black";
462 + GetE('DlgNewAttachmentInfo').style.color = "black";
463 +
464 + GetE('DlgAttachmentPage').style.color = "gray";
465 + GetE('DlgAttachmentList').style.color = "gray";
466 + GetE('txtAttachmentPagename').disabled = true;
467 + GetE('btnListAttachments').disabled = true;
468 + GetE('sctAttachments').disabled = true;
469 + }
470 +}
471 +
472 +
473 +//#### Called while the user types the remote page name.
474 +function OnAttachmentPagenameChange()
475 +{
476 + GetE('requestedPagename').value = StripWhitespace(escapeHTML(GetE('txtAttachmentPagename').value));
477 +
478 + // If the remote page name was changed by the user, we gray out the drop
479 + // down listbox cause the attachments inside don't match with the page name
480 + // until the user presses the button.
481 + // The button will be ungrayed here so the user can press it to load all
482 + // attachments on the remote page.
483 + if (GetE('txtAttachmentPagename').value != "")
484 + {
485 + GetE('DlgAttachmentList').style.color = "gray";
486 + GetE('sctAttachments').disabled = true;
487 + GetE('btnListAttachments').disabled = false;
488 + invalidAttachmentList = true;
489 + }
490 + else
491 + {
492 + GetE('DlgAttachmentList').style.color = "gray";
493 + GetE('sctAttachments').disabled = true;
494 + GetE('btnListAttachments').disabled = true;
495 + invalidAttachmentList = true;
496 + }
497 +}
498 +
499 +
500 +// Does the user want to create a new attachment or does he want to select
501 +// from the drop down list.
502 +function RadioCreateSelectAttachmentState()
503 +{
504 + if (GetE('radioCreateAttachment').checked)
505 + return true;
506 + else
507 + return false;
508 +}
509 +
510 +
511 +function StripWhitespace(text)
512 +{
513 + text = text.replace(/^\s*|\s*$/g,'');
514 + return text;
515 +}
516 +
517
518 //#### The OK button was hit.
519 function Ok()
520 {
521 - var sUri;
522 - var sText = '';
523 + var createAttachment = RadioCreateSelectAttachmentState();
524 + var newAttachmentName = StripWhitespace(escapeHTML(GetE('txtNewAttachmentName').value));
525 + var attachmentPagename = StripWhitespace(escapeHTML(GetE('txtAttachmentPagename').value));
526 + var src = StripWhitespace(escapeHTML(GetE('txtAttachmentPagename').value)); // Image Source page/URL.
527 + var destinationPagename = StripWhitespace(escapeHTML(GetE('destinationPagename').value));
528 + var attachmentName = StripWhitespace(escapeHTML(GetE('sctAttachments').value)); // Image name.
529 + var indexOfAttachmentList = GetE('sctAttachments').selectedIndex;
530 + var title = '';
531
532 - sUri = GetE('txtAttachmentname').value;
533 - if (sUri.length == 0)
534 + // Check if the required gui elements are filled or selected.
535 + if (!createAttachment)
536 {
537 - alert(FCKLang.DlnLnkMsgNoUrl);
538 - return false;
539 + if (attachmentPagename.length == 0)
540 + {
541 + GetE('txtAttachmentPagename').focus();
542 + alert(LanguageString("langAlertMissingPageName"));
543 + return false;
544 + }
545 +
546 + if (invalidAttachmentList)
547 + {
548 + alert(LanguageString("langAlertInvalidDropDownList"));
549 + return false;
550 + }
551 +
552 + if (indexOfAttachmentList == 0)
553 + {
554 + alert(LanguageString("langAlertMissingAttachment"));
555 + return false;
556 + }
557 }
558 - sText = sUri;
559 - sUri = encodeUrl(sUri);
560 + else
561 + {
562 + if (newAttachmentName.length == 0)
563 + {
564 + GetE('txtNewAttachmentName').focus();
565 + alert(LanguageString("langAlertMissingNewAttachmentName"));
566 + return false;
567 + }
568 + }
569
570 - if (oLink) // Modifying an existent link.
571 + if (!createAttachment)
572 {
573 - oLink.href = sUri;
574 + // If attachment is on a different page, than we add a reference to it before
575 + // the attachment name (e.g.: remotepagename/attachment.pdf).
576 + // But: If you rename the destination's page name, this link won't be
577 + // processed by moin and will result in a broken link!
578 + if (destinationPagename != src)
579 + src += "/" + attachmentName;
580 + else
581 + src = attachmentName;
582 }
583 - else // Creating a new link.
584 + else
585 + src = newAttachmentName;
586 +
587 + linkText = src;
588 + src = encodeUrl(src);
589 +
590 + if (oLink)
591 {
592 - oLink = oEditor.FCK.CreateLink(sUri)[0];
593 - if (! oLink)
594 + // Modifying an existent link.
595 + oLink.href = src;
596 + }
597 + else
598 + {
599 + // Creating a new link.
600 + oLink = oEditor.FCK.CreateLink(src)[0];
601 + if (!oLink)
602 {
603 oLink = oEditor.FCK.CreateElement('A');
604 - oLink.href = sUri;
605 - oLink.appendChild(oEditor.FCK.EditorDocument.createTextNode(sText));
606 + oLink.href = src;
607 + oLink.appendChild(oEditor.FCK.EditorDocument.createTextNode(linkText));
608 }
609 }
610 -
611 - SetAttribute(oLink, 'title', 'attachment:' + sUri);
612
613 + SetAttribute(oLink, 'title', 'attachment:' + src);
614 return true;
615 }
616
617 -function SetUrl(url)
618 +
619 +// Create translation string from HTML variable. This variable was created in MoinMoin.
620 +// string LanguageString(<translationTemplate>, <variable1>, <variable2>, ...)
621 +// - translationTemplate : sprintf like string (e.g.: "error in %s")
622 +// - variable1 : this variable replaces the first '%s' in translationTemplate
623 +// - variable2 : this variable replaces the second '%s' in translationTemplate
624 +// ...
625 +// Return value: translated string
626 +function LanguageString(translationId)
627 {
628 - document.getElementById('txtUrl').value = url;
629 - OnUrlChange();
630 + var translationTemplate = GetE(translationId).value;
631 +
632 + switch(arguments.length)
633 + {
634 + case 1:
635 + translatedString = translationTemplate;
636 + break;
637 + case 2:
638 + translatedString = sprintf(translationTemplate, arguments[1]);
639 + break;
640 + case 3:
641 + translatedString = sprintf(translationTemplate, arguments[1], arguments[2]);
642 + break;
643 + case 4:
644 + translatedString = sprintf(translationTemplate, arguments[1], arguments[2], arguments[3]);
645 + break;
646 + case 5:
647 + translatedString = sprintf(translationTemplate, arguments[1], arguments[2], arguments[3], arguments[4]);
648 + break;
649 + case 6:
650 + translatedString = sprintf(translationTemplate, arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
651 + break;
652 + default:
653 + alert("Too much parameters in 'LanguageString'!");
654 + translatedString = "Error during translation!";
655 + break;
656 + }
657 +
658 + return translatedString;
659 }
660
661 +
662 +/**
663 + * sprintf() for JavaScript v.0.4
664 + *
665 + * Copyright (c) 2007 Alexandru Marasteanu <http://alexei.417.ro/>
666 + * Thanks to David Baird (unit test and patch).
667 + *
668 + * This program is free software; you can redistribute it and/or modify it under
669 + * the terms of the GNU General Public License as published by the Free Software
670 + * Foundation; either version 2 of the License, or (at your option) any later
671 + * version.
672 + *
673 + * This program is distributed in the hope that it will be useful, but WITHOUT
674 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
675 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
676 + * details.
677 + *
678 + * You should have received a copy of the GNU General Public License along with
679 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
680 + * Place, Suite 330, Boston, MA 02111-1307 USA
681 + */
682 +
683 +function str_repeat(i, m) { for (var o = []; m > 0; o[--m] = i); return(o.join('')); }
684 +
685 +function sprintf () {
686 + var i = 0, a, f = arguments[i++], o = [], m, p, c, x;
687 + while (f) {
688 + if (m = /^[^\x25]+/.exec(f)) o.push(m[0]);
689 + else if (m = /^\x25{2}/.exec(f)) o.push('%');
690 + else if (m = /^\x25(?:(\d+)\$)?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(f)) {
691 + if (((a = arguments[m[1] || i++]) == null) || (a == undefined)) throw("Too few arguments.");
692 + if (/[^s]/.test(m[7]) && (typeof(a) != 'number'))
693 + throw("Expecting number but found " + typeof(a));
694 + switch (m[7]) {
695 + case 'b': a = a.toString(2); break;
696 + case 'c': a = String.fromCharCode(a); break;
697 + case 'd': a = parseInt(a); break;
698 + case 'e': a = m[6] ? a.toExponential(m[6]) : a.toExponential(); break;
699 + case 'f': a = m[6] ? parseFloat(a).toFixed(m[6]) : parseFloat(a); break;
700 + case 'o': a = a.toString(8); break;
701 + case 's': a = ((a = String(a)) && m[6] ? a.substring(0, m[6]) : a); break;
702 + case 'u': a = Math.abs(a); break;
703 + case 'x': a = a.toString(16); break;
704 + case 'X': a = a.toString(16).toUpperCase(); break;
705 + }
706 + a = (/[def]/.test(m[7]) && m[2] && a > 0 ? '+' + a : a);
707 + c = m[3] ? m[3] == '0' ? '0' : m[3].charAt(1) : ' ';
708 + x = m[5] - String(a).length;
709 + p = m[5] ? str_repeat(c, x) : '';
710 + o.push(m[4] ? a + p : p + a);
711 + }
712 + else throw ("Huh ?!");
713 + f = f.substring(m[0].length);
714 + }
715 + return o.join('');
716 +}
717 --- a/MoinMoin/web/static/htdocs/applets/moinFCKplugins/moinattachment/fckplugin.js Sat Nov 21 16:31:36 2009 +0100
718 +++ b/MoinMoin/web/static/htdocs/applets/moinFCKplugins/moinattachment/fckplugin.js Sun Nov 22 19:35:15 2009 +0100
719 @@ -15,13 +15,13 @@
720 }
721
722 // Register the related command.
723 -FCKCommands.RegisterCommand('Attachment', new FCKDialogCommand( 'Attachment', FCKLang.DlgLnkWindowTitle, FCKConfig.WikiBasePath + FCKConfig.WikiPage + '?action=fckdialog&dialog=attachment', 400, 330, LinkState, 'CreateAttachment')) ;
724 +FCKCommands.RegisterCommand('Attachment', new FCKDialogCommand( 'Attachment', "Attachment", FCKConfig.WikiBasePath + FCKConfig.WikiPage + '?action=fckdialog&dialog=attachment', 600, 500, LinkState, 'CreateAttachment')) ;
725
726 oAttachmentItem = new FCKToolbarButton('Attachment', FCKLang.AttachmentBtn, null, null, false, true);
727 }
728 else
729 {
730 -FCKCommands.RegisterCommand('Attachment', new FCKDialogCommand( 'Attachment', FCKLang.DlgLnkWindowTitle, FCKConfig.WikiBasePath + FCKConfig.WikiPage + '?action=fckdialog&dialog=attachment', 400, 330, FCK.GetNamedCommandState, 'CreateAttachment')) ;
731 +FCKCommands.RegisterCommand('Attachment', new FCKDialogCommand( 'Attachment', "Attachment", FCKConfig.WikiBasePath + FCKConfig.WikiPage + '?action=fckdialog&dialog=attachment', 600, 500, FCK.GetNamedCommandState, 'CreateAttachment')) ;
732
733 oAttachmentItem = new FCKToolbarButton('Attachment', FCKLang.AttachmentBtn, null, null, false, false);
734 }
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.