%3 ::xowiki::MenuItem ::xowiki::MenuItem init render ::xowiki::MenuComponent ::xowiki::MenuComponent html_id js_name ::xowiki::MenuItem->::xowiki::MenuComponent ::xowiki::Menu ::xowiki::Menu render ::xowiki::Menu->::xowiki::MenuComponent ::xowiki::BootstrapNavbarDropzone ::xowiki::BootstrapNavbarDropzone js render ::xowiki::BootstrapNavbarDropzone->::xowiki::MenuComponent ::xo::tdom::Object ::xo::tdom::Object render ::xowiki::MenuComponent->::xo::tdom::Object ::xo::tdom::AttributeManager ::xo::tdom::AttributeManager ::xo::tdom::Object->::xo::tdom::AttributeManager ::xo::OrderedComposite ::xo::OrderedComposite ::xo::tdom::Object->::xo::OrderedComposite

Class ::xowiki::BootstrapNavbarDropzone

::xowiki::BootstrapNavbarDropzone[i] create ... \
           [ -disposition (default "File") ] \
           [ -file_name_prefix (default "") ] \
           [ -href (default "#") ] \
           [ -label (default "DropZone") ] \
           [ -text (default "") ]

Defined in

Class Relations

  • class: ::xo::tdom::Class[i]
  • superclass: ::xowiki::MenuComponent[i]
::xo::tdom::Class create ::xowiki::BootstrapNavbarDropzone \
     -superclass ::xowiki::MenuComponent

Methods (to be applied on instances)

  • disposition (setter)

  • file_name_prefix (setter)

  • href (setter)

  • js (scripted)

    html::script -type "text/javascript" -nonce [security::csp::nonce] {
      html::t {
        + function($) {
          'use strict';
    
          var dropZone = document.getElementById('drop-zone');
          var uploadForm = document.getElementById('js-upload-form');
          var progressBar = document.getElementById('dropzone-progress-bar');
          var dropZoneResponse = document.getElementById('thumbnail-files-wrapper');
          var uploadFileRunning = 0;
          var uploadFilesStatus = [];
          var uploadFilesResponse = [];
    
          var startUpload = function(files, disposition, url, prefix, csrf) {
            //console.log("files " + files + " dispo '"+ disposition + "' url " + url + " prefix " + prefix);
            if (typeof files !== "undefined") {
              for (var i=0, l=files.length; i<l; i++) {
                // Send the file as multiple single requests and
                // not as a single post containing all entries. This
                // gives users with older NaviServers or AOLserver the chance
                // drop multiple files.
                uploadFile(files[i], disposition, url, prefix, csrf);
             }
    
            } else {
              alert("No support for the File API in this web browser");
            }
          }
    
          var uploadFile = function(file, disposition, url, prefix, csrf) {
            var xhr;
            var formData = new FormData();
            var fullName = (prefix == "" ? file.name : prefix + '/' + file.name);
            var fullUrl = url
            + "&disposition=" + encodeURIComponent(disposition)
            + "&name=" + encodeURIComponent(fullName);
    
            xhr = new XMLHttpRequest();
            xhr.upload.addEventListener("progress", function (evt) {
              if (evt.lengthComputable) {
    
                // For multiple drop files, we should probably we
                // should sum up the sizes.  However, since the
                // uploads are in parallel, this is already useful.
    
                progressBar.style.width = (evt.loaded / evt.total) * 100 + "%";
              } else {
                // No data to calculate on
              }
            }, false);
            xhr.addEventListener("load", function (event) {
              uploadFileRunning--;
              uploadFilesStatus.push(event.currentTarget.status);
              uploadFilesResponse.push(event.currentTarget.response);
              //console.log("ended with status " + event.currentTarget.status);
              //console.log("running: " + uploadFileRunning);
              if (dropZoneResponse) {
    
                // We have a dropzone response and update this in the
                // web page.
    
                dropZoneResponse.innerHTML = uploadFilesResponse[uploadFilesResponse.length-1];
                dropZoneResponse.querySelectorAll('.thumbnail-file').forEach(el => thumbnail_files_setup(el));
              }
              if (uploadFileRunning < 1) {
                if (dropZoneResponse) {
    
                  // We are done with all uploads. When the response is
                  // provided, it was updated above already in the web
                  // page, but we have still to reset the progress bar
                  // to indicate that we are done.
    
                  progressBar.style.width = '0%';
    
                } else {
                  // Reload the page to trigger a refresh
                  location.reload(true);
                }
              }
            }, false);
            xhr.open("post", fullUrl, true);
            formData.append("upload", file);
            formData.append("__csrf_token", csrf);
            uploadFileRunning++;
            xhr.send(formData);
          }
    
          uploadForm.addEventListener('submit', function(e) {
            //
            // Input handler for classical form submit
            //
            var input = document.getElementById('js-upload-files');
            var uploadFiles = input.files;
            var csrf = input.form.elements["__csrf_token"].value;
            e.preventDefault();
            //console.log("Submit handler");
            startUpload(input.files,
                        input.dataset.disposition ?? 'File',
                        input.dataset.url,
                        input.dataset.file_name_prefix ?? '',
                        csrf);
          })
    
          dropZone.ondrop = function(e) {
            //
            // Input handler for drag & drop
            //
            e.preventDefault();
            this.className = 'upload-drop-zone';
            var form = document.getElementById('js-upload-files').form;
            var csrf = form.elements["__csrf_token"].value;
            var input = document.getElementById('js-upload-files');
            //console.log("Drop handler");
            startUpload(e.dataTransfer.files,
                        input.dataset.disposition ?? 'File',
                        input.dataset.url,
                        input.dataset.file_name_prefix ?? '',
                        csrf);
          }
    
          dropZone.ondragover = function() {
            this.className = 'upload-drop-zone drop';
            return false;
          }
    
          dropZone.ondragleave = function() {
            this.className = 'upload-drop-zone';
            return false;
          }
        } (jQuery);
      }
    }
  • label (setter)

  • render (scripted, public)

     <instance of xowiki::BootstrapNavbarDropzone[i]> render

    doku

    Testcases:
    create_folder_with_page, create_workflow_with_instance
    if {${:href} ni {"" "#"}} {
      html::li {
        html::form -method "post" -enctype "multipart/form-data"  -style "display: none;"  -id "js-upload-form" {
              html::div -class "form-inline" {
                html::div -class "form-group" {
                  html::input  -type "file"  -name {files[]}  -id "js-upload-files"  -data-file_name_prefix ${:file_name_prefix}  -data-url ${:href}  -data-disposition ${:disposition}  -multiple multiple
                }
                html::button -type "submit" -class "btn btn-sm btn-primary" -id "js-upload-submit" {
                  html::t ${:text}
                }
                ::html::CSRFToken
              }
            }
        html::div -class "upload-drop-zone" -id "drop-zone" {
          html::span {html::t ${:label}}
          html::div -class "progress" {
            html::div -style "width: 0%;" -class "progress-bar" -id dropzone-progress-bar {
              html::span -class "sr-only" {html::t ""}
            }
          }
        }
      }
      :js
    }
  • text (setter)