Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

HTML Settings

Here you can Sed posuere consectetur est at lobortis. Donec ullamcorper nulla non metus auctor fringilla. Maecenas sed diam eget risus varius blandit sit amet non magna. Donec id elit non mi porta gravida at eget metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.

            
              <form class="pure-form pure-form-aligned" method="post" action="#" name="competition-upload">
  <fieldset id="initial-fields">
    <div class="pure-g">
      <div class="pure-u-2-3">

        <div class="pure-control-group">
          <label for="name">Your Name</label>
          <input id="name" name="name" type="text" required value="Joe Submitter">
        </div>

        <div class="pure-control-group">
          <label for="email">Email Address</label>
          <input id="email" name="email" type="email" required value="joe@indiefilmmaker.co">
        </div>

        <div class="pure-control-group">
          <label for="title">Film Title</label>
          <input id="title" name="title" type="text" required value="The Pigeon Diaries">
        </div>

        <div class="pure-control-group">
          <label for="director">Director's name</label>
          <input id="director" name="director" type="text" required value="Jane Director">
        </div>

      </div>
      <div class="pure-u-1-3">
        <div>

          <label>Genre</label>

          <label for="doco" class="pure-radio">
            <input id="doco" type="radio" name="genre" value="Documentary" checked>
            Documentary
          </label>

          <label for="animation" class="pure-radio">
            <input id="animation" type="radio" name="Animation" value="option2">
            Animation
          </label>

          <label for="live-action" class="pure-radio">
            <input id="live-action" type="radio" name="genre" value="Live Action">
            Live Action
          </label>

          <label for="experimental" class="pure-radio">
            <input id="experimental" type="radio" name="genre" value="Experimental">
            Experimental
          </label>

          <label for="other" class="pure-radio">
            <input id="other" type="radio" name="genre" value="Other">
            Other
          </label>

        </div>
      </div>
      <div class="pure-controls" id="submit-controls">
        <button type="button" id="initial-field-submit" class="pure-button pure-button-primary" onclick="continueToUpload()">Continue</button>
      </div>
    </div>
  </fieldset>

  <fieldset id="uploader"><!-- Widget will get inserted here //--></fieldset>
  
  <!-- Adding some hidden fields to submit upload information //-->
  <input type="hidden" name="upload-id" id="upload-id">
  <input type="hidden" name="file-count" id="file-count">
  <input type="hidden" name="upload-size" id="upload-size">
</form>
            
          
!
            
              body {
  background-color: #eee;
}

form {
  margin: 10px;
}

#uploader:empty {
  display: none;
}

#uploader {
  background-color: #fcfafa;
  margin: 0px 10px;
  padding: 10px;
  border: 1px solid #ccc !important;
  box-shadow: inset 0 1px 3px #ddd;
  border-radius: 4px;
}

label:not(.pure-radio) {
  font-weight: bold;
}

input:disabled {
  background-color: #eee;
}
            
          
!
            
              //We've added a click trigger to the 'Continue' button
//  onclick="continueToUpload()"
//This function will: 
  //1. validate the form
  //2. Gather field values
  //3. Format additional information to a 'message' string
  //4. Define an oncomplete callback function to be called when the upload finishes
  //5. Initialise the widget with the form values and complete callback

function continueToUpload() {
  //1. Let's make sure the form is valid before continuing
  if (!document.forms["competition-upload"].reportValidity()) return;

  //If the form is valid then let's disable the fields for the next step
  document
    .getElementById("initial-fields")
    .setAttribute("disabled", "disabled");
  //Hide the 'Continue' button
  document.getElementById("submit-controls").style.display = "none";

  //2. We'll collect all the field values
  var name = document.getElementById("name").value;
  var email = document.getElementById("email").value;
  var title = document.getElementById("title").value;
  var director = document.getElementById("director").value;
  var genre = document.querySelector('input[name="genre"]:checked').value;

  //3. We'll put the Director and Genre information together to go into the message field
  var message = "Director: " + director + "\n" + "Genre: " + genre;

  //4. Setup the upload complete callback function
  //This function will: 
    //a. Hide the widget for neatness
    //b. Enable the form fields so they can be POSTed to your server
    //c. Gather some information from the upload to include on your serve
    //d. Put the upload details in some hidden form fields
    //e. Submit the form to the server
  
  var onComplete = function(uploadInfo, fileInfo) {
    //4a. Hide the uploader now it's done
    document.getElementById("uploader").style.display = "none";
    //4b. Re-enable form inputs to submit them
    document.getElementById("initial-fields").removeAttribute("disabled");
    
    //4c. Gather some info from upload 
    var uploadId = uploadInfo.id; //Our upload id, useful to link from your own system
    var fileCount = uploadInfo.estimatedFileCount; //The number of files uploaded
    var uploadSize = uploadInfo.estimatedSize; //The total size of the upload in bytes
    
    //4d. Store the info in the hidden form fields
    document.getElementById("upload-id").value = uploadId;
    document.getElementById("file-count").value = fileCount;
    document.getElementById("upload-size").value = uploadSize;
    
    //4e. Submit the form to the server
    //document.forms["competition-upload"].submit();
    
    //There's no server in this demo so just show an alert with what would be submitted
    var formData = new FormData(document.forms["competition-upload"]);
    var formValues = "Form data to submit: \n\n";
    for (var pair of formData.entries()) {
      formValues += pair[0]+ ': ' + pair[1] + '\n'; 
    }
    alert(formValues);
    
  };
  
  //5. Now we can initialise the widget with the pre-populated fields
  //Since we have all the information we need it will show as a simple file chooser.
  //The code below is modified from the Avanced Snippet in the Widget Editor.
  DigitalPigeon.init(
    document.getElementById("uploader"), 
    {
      url:
        "https://digitalpigeon.com/rcv/widget?aid=313b08b0-4608-11e0-b23d-00163e4f5c0b&lid=387e1d50-34a8-11e9-b1f2-062d42c19b03",
      fields: {
        name: {
          value: name //pass in the name from the form
        },
        email: {
          value: email //pass in the email from the form
        },
        summary: {
          value: title //pass in the film title from the form
        },
        message: {
          value: message //pass in the message we formatted above
        }
      },
      customize: {
        "color-scheme": "light",
        "link-color": "#0078e7",
        "background-color": "#fcfafa"
      },
      oncomplete: onComplete
    }
  );
  
  

  return false;
}




;(function() {
    var DigitalPigeon = window.DigitalPigeon = {
        fields: ["name","email", "summary", "message", "files"],
        customisers: ["send-label", "color-scheme", "background-color", "label-color", "link-color", "height"],
        completeJSIndex: 0,
        completeJS: [],

        init: function(parentEl, options) {

            if (parentEl === undefined) { // this is always the case the first time the script is loaded
                this.initPopupElements();
                this.initInlineElements();
                this.listenForUploadComplete();
            } else { //optional manual init for dynamic/single page apps

                options.customize = options.customize || {};
                options.fields = options.fields || {};

                this.initWithOptions(parentEl, options);
            }

        },

        initWithOptions: function(parentEl, options) {
            var flatProps = {};
            var optionProp;
            var i;
            var propName;
            for (i in this.fields) {
                propName = this.fields[i];
                optionProp = options.fields[propName];
                if (optionProp !== undefined) {
                    if (optionProp.label !== undefined) {
                        flatProps[propName + "-label"] = optionProp.label;
                    }
                    if (optionProp.placeholder !== undefined) {
                        flatProps[propName + "-placeholder"] = optionProp.placeholder;
                    }
                    if (optionProp.value !== undefined) {
                        flatProps[propName] = optionProp.value;
                    }
                }
            }


            for (i in this.customisers) {
                propName = this.customisers[i];
                if (options.customize[propName] !== undefined) flatProps[propName] = options.customize[propName]
            }

            this.uploadDiv = document.createElement("DIV");

            parentEl.appendChild(this.uploadDiv);

            var queryStr = this.getPresetParams(flatProps, parentEl);

            if (options.oncomplete !== undefined) {
                queryStr += '&callback=' + this.completeJSIndex;
                this.completeJS.push(options.oncomplete);
                this.completeJSIndex++;
            }

            var iframeHeight = options.customize.height || this.height;

            var frameURL = this.formatUrl(options.url, queryStr, "inline");

            this.uploadDiv.style.position = "relative";
            this.uploadDiv.style.minWidth = this.minWidth + "px";
            this.uploadDiv.style.height = iframeHeight + "px";
            this.uploadDiv.innerHTML = this.embedHTML(i);
            var iframe = document.getElementById(this.iFrameId +"-embed-"+ i);
            iframe.src = frameURL;
        },

        initInlineElements: function() {
            var queryStr, i, completeJSAttr;
            var frameURL, iframe;
            var uploadDivs = this.getElementsWithClass("pigeon-upload-inline", ["div", "a"]);
            for (i = uploadDivs.length-1; i >=0 ; i--) {
                this.uploadDiv = document.createElement("DIV");

                queryStr = this.getPresetParams(uploadDivs[i], uploadDivs[i]);
                completeJSAttr = uploadDivs[i].getAttribute("data-oncomplete");
                if (completeJSAttr != null) { //let the receive page know it's handling a JS callback
                    queryStr += '&callback='+ this.completeJSIndex;
                    this.completeJS.push(completeJSAttr);
                    this.completeJSIndex++;
                }
                if (uploadDivs[i].tagName == "A") {
                   frameURL = this.formatUrl(uploadDivs[i].getAttribute("href"), queryStr, "inline");
                } else {
                   frameURL = this.formatUrl(uploadDivs[i].getAttribute("data-url"), queryStr, "inline");
                }

                var iframeHeight = uploadDivs[i].getAttribute("data-height");
                iframeHeight = iframeHeight || this.height;

                uploadDivs[i].parentNode.replaceChild(this.uploadDiv, uploadDivs[i]);
                this.uploadDiv.style.position = "relative";
                this.uploadDiv.style.minWidth = this.minWidth + "px";
                this.uploadDiv.style.height = iframeHeight + "px";
                this.uploadDiv.innerHTML = this.embedHTML(i);
                iframe = document.getElementById(this.iFrameId +"-embed-"+ i);
                iframe.src = frameURL;
            }
        },

        initPopupElements: function() {
            var uploadLinks = this.getElementsWithClass("pigeon-upload-popup", ["a"]);
            var queryStr, i, completeJSAttr;
            var windowIndex = Date.now() + (Math.random() * 1000); //seed a random number for referencing windows
            if (uploadLinks.length > 0) {

                window.pigeonPopupOffset = 0;
                window.pigeonPopup = function (url, title, w, h) {
                  if (window[title] != null && !window[title].closed) {
                      window[title].focus();
                      return;
                  }
                  var wLeft = window.screenLeft ? window.screenLeft : window.screenX;
                  var wTop = window.screenTop ? window.screenTop : window.screenY;
                  var left = wLeft + (window.innerWidth / 2) - (w / 2) + window.pigeonPopupOffset;
                  var top = wTop + (window.innerHeight / 2) - (h / 2) + window.pigeonPopupOffset;
                  window.pigeonPopupOffset += 30;
                  window[title] = window.open(url, title, 'directories=no, titlebar=no, toolbar=no, location=no, status=no, menubar=no, scrollbars=no, resizable=no, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);
                };

                for (i = uploadLinks.length-1; i >=0 ; i--) {
                    queryStr = this.getPresetParams(uploadLinks[i], null);
                    completeJSAttr = uploadLinks[i].getAttribute("data-oncomplete");
                    if (completeJSAttr != null) { //let the receive page know it's handling a JS callback
                        queryStr += '&callback='+ this.completeJSIndex;
                        this.completeJS.push(completeJSAttr);
                        this.completeJSIndex++;
                    }
                    var windowURL = this.formatUrl(uploadLinks[i].getAttribute("href"), queryStr, "popup");
                    var att = document.createAttribute("onclick");
                    att.value = "window.pigeonPopup('"+windowURL+"','pigeon-uploader-"+(windowIndex++)+"',800,570); return false";
                    uploadLinks[i].setAttributeNode(att);
                }
            }
        },

        listenForUploadComplete: function() {
            var that = this;
            var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
            var eventer = window[eventMethod];
            var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";

            // Listen to message from child window
            eventer(messageEvent,
                (function(plugin) {
                    return function(e) {
                        var key = e.message ? "message" : "data";
                        var msg = e[key];
                        if (msg.event != null && msg.event == "uploadComplete") {
                            var complete = plugin.completeJS[msg.eventIndex];
                          
                            if (typeof complete == 'string' && complete.toLowerCase().indexOf("http") == 0) {
                                window.location = complete;
                            } else {
                                try {
                                    var result = eval(complete);
                                    if (typeof result == 'function') {
                                      
                                        result(msg.data.bucket, msg.data.detail, e.source);
                                    }
                                } catch (e) {
                                    alert('There was an error while completing your upload, please contact us and quote ERROR CODE: 0\n\n' + e.message);
                                    throw e;
                                }
                            }
                        }
                    };
                })(that), false);
        },
        getPresetParams: function(paramSource, targetElement) {
            var attribGetter;

            if (paramSource instanceof HTMLElement) {
                attribGetter = function(name) {
                    return paramSource.getAttribute("data-" + name);
                }
            } else {
                attribGetter = function(name) {
                    return paramSource[name]
                }
            }

            var queryVals = [];
            var value;
            this.hiddenFields = 0;
            for (var i in this.fields) {
                value = attribGetter(this.fields[i]);
                if (value != null) {
                    queryVals.push(encodeURIComponent(this.fields[i]) + "=" + encodeURIComponent(value));
                    this.hiddenFields++
                }
                value = attribGetter(this.fields[i] + "-label");
                if (value != null) {
                    queryVals.push(encodeURIComponent(this.fields[i] + "-label") + "=" + encodeURIComponent(value));
                }
                value = attribGetter(this.fields[i] + "-placeholder");
                if (value != null) {
                    queryVals.push(encodeURIComponent(this.fields[i] + "-placeholder") + "=" + encodeURIComponent(value));
                }
            }

            if (this.hiddenFields >= 2) { //if 2 fields are hidden then layout vertically
                queryVals.push("vertical-layout=true");
            }

            var pageStyleDefaults = {};
            if (targetElement != null) {
                //Try to setup some defaults that match the page
                var parentEl = targetElement.parentNode;
                pageStyleDefaults["background-color"] = this.getBGColor(parentEl);
                pageStyleDefaults["label-color"] = this.getStyleProp(parentEl, "color");
                if (targetElement.tagName == "A") {
                    pageStyleDefaults["link-color"] = this.getStyleProp(targetElement, "color");
                }
            }

            for (i in this.customisers) {
                value = attribGetter(this.customisers[i]);
                if (value != null) {
                    queryVals.push(encodeURIComponent(this.customisers[i]) + "=" + encodeURIComponent(value));
                } else {
                    value = pageStyleDefaults[this.customisers[i]];
                    if (value != null) {
                        queryVals.push(encodeURIComponent(this.customisers[i]) + "=" + encodeURIComponent(value));
                    }
                }
            }
            return queryVals.join("&");
        },
        getStyleProp: function(elem, prop) {
            if (window.getComputedStyle) {
                return window.getComputedStyle(elem, null).getPropertyValue(prop);
            } else if (elem.currentStyle) {
                return elem.currentStyle[prop]; //IE
            }
        },
        getBGColor: function(elem) {
            var color = this.getStyleProp(elem, "background-color");
            if ((color !== 'rgba(0, 0, 0, 0)') && (color !== 'transparent')) {
                return color;
            }
            // if not: are we at the body element?
            if (elem.nodeName == "BODY") {
                return "#fff";
            } else {
                return this.getBGColor(elem.parentNode);
            }
        },
        formatUrl: function(url, params, widgetType) {
            if (url.indexOf("?") == -1) {
                url += "?"
            } else {
                url += "&"
            }
            return url + "widget="+widgetType+"&referrer=" + encodeURIComponent(window.location.href.split('?')[0])  + "&" + params;
        },
        getElementsWithClass: function(className, tags) {
            if (document.getElementsByClassName) {
                return document.getElementsByClassName(className);
            } else {
                var elArray = [];

                var regex = new RegExp("(^|\\s)" + className + "(\\s|$)");
                for (var t = 0; t < tags.length; t++) {
                    var tmp = document.getElementsByTagName(tags[t]);
                    for (var i = 0; i < tmp.length; i++) {
                        if (regex.test(tmp[i].className)) {
                            elArray.push(tmp[i]);
                        }
                    }
                }

                return elArray;
            }
        },
        iFrameId: "digi-dialog-iframe",
        loadedFrame: false,
        cdn: "https://d3d9fxd16gl89m.cloudfront.net/widgets/",
        width: 800,
        minWidth: 300,
        maxWidth: "100%",
        height: 485,
        embedHTML: function(index) {
            return "<iframe id='" + this.iFrameId +"-embed-" +index+"' frameborder='0' name='digi-iframe' style='display: block; background: #FAFBFC; border: none; -moz-border-radius: 3px; -webkit-border-radius: 3px; height: 100%; padding: none; position: absolute; top: 0; right: 0; bottom: 0; left: 0; width: 100%;'></iframe>";
        }
    };

    DigitalPigeon.init();

    var event = new CustomEvent('pigeonReady', { });
    document.dispatchEvent(event);

})();
            
          
!
999px
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.

Console