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 +                &nbsp;
 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 +                                &nbsp;
 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 +                &nbsp;
 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, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
 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.
  • [get | view] (2009-11-22 19:59:21, 27.6 KB) [[attachment:AttachmentDialog.patch]]
  • [get | view] (2009-11-22 22:01:28, 15.2 KB) [[attachment:betterui.svg]]
  • [get | view] (2009-11-24 11:27:48, 8.0 KB) [[attachment:dialog_elements.png]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.