Drag & Drop using Dropzone and Seaside - javascript

I'm struggling a little with the dropzone implementation for dragging/dropping files. I am developing on a Smalltalk platform with Seaside on the front end. Currently, I am able to upload a file but unable to see the success icon as well as the progress bar appear at the time of upload. When I inspect elements on the web, I do see that the divs representing the success/progress are present. I do see the file size and file name appear just as the file gets dropped in. Can someone point out what I'm missing? My code is as follows:
| serverURL url |
serverURL := RepWebSettings portalSettingsWebServerURL ifNil: [self session requestContext request uri serverURL].
url := serverURL ,
html context actionUrl printString ,
'&' , (html callbacks store: (Seaside.WAValueCallback on: [self uploadFileDroppedFiles])).
html div class: 'layoutBorder'; with: [
html div id: 'draganddropupload'; class: 'dropzone';
with: [
html div class: 'dz-message'; with: [
html image url: RepWebFileLibrary / #draganddropPng]]].
html script: ('
$(document).ready(function () {
Dropzone.autoDiscover = false;
Dropzone.uploadMultiple = true;
Dropzone.createImageThumbnails = false;
$("#draganddropupload").dropzone({
url: "%1",
success: function (file, response) {
document.location.reload(true);
}
});
});' bindWith: url).

When you run your example with Chrome's Developer Tools opened to the 'Console' tab what javascript errors do you see? Seems like Dropzone manages the progress bar and checkmark.
From looking at their simple example:
https://github.com/enyo/dropzone/blob/gh-pages/examples/simple.html
The only difference between what you've got and what they've got is that they're using a 'form' tag with the 'dropzone' class and you're using a 'div' tag.
So, it may be that Dropzone expects to operate in a 'form' and without any other inputs in that form. So if it were me I'd change that div tag in your seaside code to a form, and make sure the new form wasn't nested inside another form on the page.

Related

How Can I Pass String Variable to Anonymous Adobe View SDK Script?

I have a very basic knowledge of javascript and I have been unable to find a solution for my specific use of the Adobe View SDK API, though it seems like there should be a way. I am working on a web page to show newsletters in the pdf viewer. I have created a w3.css modal element so that I can open the viewer with a button click, and then close it with an "x" in the corner. The button click and the "x" toggle between the display style being "none" or "block". I really like this solution as it lets me use small images of the newsletters as the buttons, and it can be observed here: Test News Page by clicking on the newsletter image below May 4, 2020.
The ultimate goal I have is to be able to change the name of the pdf document that is opened in the viewer by clicking the button, which would need to pass a string variable called "docName" to the url called by the View SDK script. Since the url is already specified in the script inside my modal element when the page loads, here is the thinking I have for the additional script I need to pass my string variables: The button-click invokes my script (function changeName(docName)) and passes the "docName" variable. Then my script needs to pass this variable to the url in the View script (this is the part I don't know how to do), then refresh the page to reload my modal, and then change the display style of the modal to "block". I will copy the code for the View SDK below, showing where I need to insert the string variable with my document name:
<script src="https://documentcloud.adobe.com/view-sdk/main.js"></script>
<script type="text/javascript">
document.addEventListener("adobe_dc_view_sdk.ready", function(){
var adobeDCView = new AdobeDC.View({clientId: "06179511ab964c9284f1b0887eca1b46", divId: "adobe-dc-view"});
adobeDCView.previewFile({
content:{location: {url: "https://www.shcsfarmington.org/" + docName + ".pdf"}},
metaData:{fileName: "Newsletter_050420.pdf"}
}, {embedMode: "FULL_WINDOW", defaultViewMode: "FIT_WIDTH"});
});
</script>
It seems like this should work, but with my limited knowledge of javascript I don't know how to pass this variable to the anonymous function in the View SDK code, and I would need as much detail and specifics in the syntax of the solution. I appreciate any help with this. Thanks.
EDIT: I thought maybe it would help to show the code for the function that I have come up with so far - then it could be examined and easier to debug and comment on:
<button id="CSS-050420" onclick="changeDoc('Newsletter_050420');"></button>
<script>
function changeDoc(docName) {
/* Need to pass docName to url=https://shcsfarmington.org/2020/news/Newsletter_" + newsDate + ".pdf"; */
window.location.reload(true);
document.getElementById('viewerModal').style.display='block';
}
</script>
I created a CodePen here for you to look at.
Basically, you'll load the first file when the SDK is ready but then you need to set the adobeDCView to null before recreating it.
function showPDF(url) {
adobeDCView = null;
fetch(url)
.then((res) => res.blob())
.then((blob) => {
adobeDCView = new AdobeDC.View({
// This clientId can be used for any CodePen example
clientId: "e800d12fc12c4d60960778b2bc4370af",
// The id of the container for the PDF Viewer
divId: "adobe-dc-view"
});
adobeDCView.previewFile(
{
content: { promise: Promise.resolve(blob.arrayBuffer()) },
metaData: { fileName: url.split("/").slice(-1)[0] }
},
{
embedMode: "FULL_WINDOW",
defaultViewMode: "FIT_PAGE",
showDownloadPDF: true,
showPrintPDF: true,
showLeftHandPanel: false,
showAnnotationTools: false
}
);
});
}
The link click even will pass the url to the PDF and then display it.

CKEditor - Upload URL is not called by plugin uploadimage

I tried to search, but no luck for now. I integrated CKEditor 4.5.10 with uploadimage plugin (using Builder). I set the filebrowserUploadUrl and filebrowserBrowseUrl options when using CKEDITOR.replace.
No error (except the one stating I can't use local images that should be fixed when to image is uploaded and changed by the plugin).
I put a breakpoint as my first line in my upload PHP file, but I never get there. Yes, my debuging stuff is working perfectly as I can break using the Uploading tab in the image dialog.
I'm trying to copy/paste from Word an image with text using CTRL-C + CTRL-V.
What could I've missed ?
Code of initialization (I justed forked the imageuploader plugin to ameliorate it, so I have control over it) :
var superAdminPlugins = 'sourcearea,elementspath,forms';
var autoUploadPlugins = ''; //',uploadimage,uploadwidget'; // I already put them in VIA Builder
var toRemovePlugin = ',resize';
var toTestPlugin = ',base64image,ckeditortablecellsselection,autoembed,bgimage,backgrounds,pbckcode,tabletoolstoolbar';
alert(CKEDITOR.getUrl('') + 'plugins/imageuploader/imgupload.php');
ckEditor = CKEDITOR.replace(textareaId, {
language: wee.currentLanguage,
extraPlugins: 'allmedias,imageuploader' + autoUploadPlugins,
removePlugins: superAdminPlugins + toTestPlugin + toRemovePlugin,
toolbarCanCollapse: true,
scayt_sLang: scaytLanguageToUse,
youtube_width: 300,
youtube_height: 300,
filebrowserUploadUrl: CKEDITOR.getUrl('') + 'plugins/imageuploader/imgupload.php',
filebrowserBrowseUrl: CKEDITOR.getUrl('') + 'plugins/imageuploader/imgbrowser.php'
});
I discovered why it doesn't work. And indeed, it's normal, well kind of.
Copying an image from a picture editor creates an image using base64 encoding. So the image is included directly in the content thus accessible by the plugin.
Weirdly, copying only the image from MS Word does exactly the same thing, so it works! Yeah! But unfortunately, copying an image with text, the image is included as a link to a local file in a temporary folder. So, the content not being contained in the clipboard, the plugin can't use it.
I'll then try to create a Java software that will catch a clipboard change and adjust its content with base64 images instead. Hope I'll be able to do so! If yes, I'll post it somewhere.
EDIT :
Here is the Java software I made to support this :
https://github.com/djon2003/ClipboardImageToBase64

filepicker-rails w/signup form: button to `remove` the file in Filepicker

In my Rails 3.2 app I am using Filepicker through the filepicker-rails gem to allow users to upload a profile photo on the signup form. In the f.filepicker_field I am using the onchange option to call an onImageUpload() function that gets information about the newly uploaded image from the automatically-generated event.fpfile and disables the Filepicker browse button:
function onImageUpload() {
file = event.fpfile
img = $("<img>").prop("src", file.url).css({
width: '160px',
height: '160px',
});
$("#profile_photo_preview").append(img);
$(".filepicker-button").toggleClass("disabled");
};
I read about the event.fpfile at the Filepicker docs section on Widgets. In the form I also have a link that, when clicked, removes the recently updated image from the DOM and re-enables the Filepicker button:
:javascript
$(document).ready(function() {
$("#picture-remover").click(function() {
$("#profile_photo_preview").html("");
if ( $(".filepicker-button").hasClass("disabled") ) {
$(".filepicker-button").toggleClass("disabled");
};
});
});
...
...
= link_to "Remove Picture", id: "picture-remover"
This all seems to work pretty well. The only problem is that if a user removes the first picture and then uses the Filepicker browser to upload another, the original picture is still being saved in my Filepicker account.
I'd like to have my "Remove Picture" link remove the picture not only from the DOM, but also from my Filepicker account altogether. The Filepicker docs have a section on removing/deleting files here but I don't really understand the example code or how to implement it for myself. I'm particularly confused about the relationship between the InkBlob that is mentioned for removing a file and the event.fpfile object that I'm using to display a thumbnail preview.
So far I've tried adding the following line to my "Remove Picture" link but nothing happens:
:javascript
$(document).ready(function() {
$("#picture-remover").click(function() {
$("#profile_photo_preview").html("");
if ( $(".filepicker-button").hasClass("disabled") ) {
$(".filepicker-button").toggleClass("disabled");
};
filepicker.remove(InkBlob); #added this line
});
});
Many thanks to anyone who can point me in the right direction!
InkBlob and event.fpfile objects have the same role and the same attributes.
In your example you can pass event.fpfile object to remove function.
var file = event.fpfile;
filepicker.remove(
file,
function(){
console.log("Removed");
}
);
Generally to remove filepicker file you only need it's url.
So this code also works fine:
var someObject = {url: 'https://www.filepicker.io/api/file/xaXphhT9R0GB1tPYUQAr'};
filepicker.remove(
someObject,
function(){
console.log("Removed");
}
);

Why won't my function get called up after my Ajax event OR on (document).ready?

I have a javaScript function called embedAmplienceModules() which is sat in an external js file that needs calling for certain promo banners on our site that have a class called ‘amplience-module’. This javaScript enables functionality to work on these banners that was created inside a 3rd party partner called Amplience, like slideshows, digital catalogues, hot spot links on lifestyle images that link directly through to products etc.
This script needs loading after either of the two events occur:
A click on a category option in the side nav which refreshes the page content via Ajax.
A click on a banner which links through to a category page which causes a page refresh.
ISSUE:
The problem is, my script gets loaded successfully via option 1 above but not option 2. It only loads the script once. So if I have three Amplience promo banners present the script only loads for the last one. I have tried wrapping the call to my embedAmplienceModules() function inside a (document).ready but this doesn't work.
In another external javaScript file which is used for all global site js, we have an Ajax event handler and within this is the call to my embedAmplienceModules() function, which works fine after the Ajax event/refresh.
Below is the content of the javaScript file. The call to this file is sat within the <head> tag of the site.
function embedAmplienceModules() {
$('.amplience-module').each(function() {
var divId = $(this).attr('id'); // div id eg.'amp-m1-area'
var ampId = $(this).data("ampid"); // Pulls amp id eg. 'eba2d785-f2c1-494f-8f92-b3d95dff80f8' from 'data-ampid' attribute in contentmodules.html template
var ampDimWidth = $(this).data("ampdimwidth"); // Pulls amp module width eg. '747' from 'data-ampdimwidth' attribute in contentmodules.html template
var ampDimHeight = $(this).data("ampdimheight"); // Pulls amp module height eg. '241' from 'data-ampdimheight' attribute in contentmodules.html template
var ampBaseDir = $(this).data("ampbasedir"); // Pulls player file path from 'data-ampbasedir' attribute in contentmodules.html template
var options = {
target: divId,
width: ampDimWidth,
height: ampDimHeight,
vars: {id: ampId, resolveJSPath:"true"},
params: {allowScriptAccess: "always", base: ampBaseDir, deepLinking:"false",wmode: "transparent"},
src: [
{type:"html5", src: ampBaseDir+"tcplayer.js", xd: [ampBaseDir+"xd.html"]},
{type:"swf", src: ampBaseDir+"tcplayer.swf",version:"9.0.0"}
]
};
options = $.extend(options);
interact.embedApp(options); // the actual Amplience library call
$(this).removeClass("amplience-module"); // remove the amplienceModule class so this does not get run again for this module later. Must have this.
});
}
This is the html which uses data-XXX attributes to store the appropriate information based on details entered in the back end for the particular Amplience banner. I have removed some conditional values here to make it easier to understand. These are pulled in based on values entered into the back end against the category.
<div id="amp-m1-area" class="amplience-module" data-ampid="eba2d785-f2c1-494f-8f92-b3d95dff80f8" data-ampdimwidth="241" data-ampdimheight="241" data-ampbasedir="path/to/amp/directory"></div>
The loading order is:
File containing my embedAmplienceModules() function
Content i.e. HTML containing data-XXX atts
Global js file containing call to embedAmplienceModules() function for Ajax event
Any ideas on why this function won't load on (document).ready?
** ANSWER**
I removed the 'options = $.extend(options);' line and it worked!
I removed the 'options = $.extend(options);' line and it worked!

How to modify drag and drop behavior from a browser?

Conventionally, if I click on a link on a browser and drag, the data that is 'fetched' is the URL and its name, and that can be used by the target application (MS Word or a Java Swing app).
I want to modify the default behavior of a browser on drag to include some more data.
One good application is dragging from a google search results page. For example, as shown in the diagram below, when I drag from anywhere in the first result area (marked in yellow), I want to capture not just the url of the page, but also all additional information (like the links for "Actions", "In Mac OS" links at the bottom of the first result).
I am not sure what I need to get this behavior. Javascript might be one solution I guess (maybe an extension that makes a javascript code run on all the pages that load?), but am not sure at all. Any pointers / tips / suggestions would be useful.
To enable drag and drop, simply add draggable="true" as an attribute on an element.
Example:
<div draggable="true">Little brother</div>
All drag events have a property called dataTransfer which is used to hold the drag data. dataTransfer contains two pieces of information, the data format(MIME) and the stored data. The information is set using event.dataTransfer.setData().
event.dataTransfer.setData("text/plain", "Text to drag");
Here's an example that changes the drag and drop behavior.
Setup:
Go to Google.com using Google Chrome.
Search for anything, like "dog".
Press F12 to open up the Dev console.
Copy and Paste the content of jQuery in the console.
Copy and Paste the content of Drag-N-Drop Script in the console.
Usage:
Drag and drop a search result section from the web browser to a text editor, like wordpad.
Result:
A collection of links should show up in your text editor. The links are markdown styled.
Drag-N-Drop Script
(function () {
// #author Larry Battle (http://bateru.com/news) 12.07.2012
var URLS = {
JQUERY : "http://code.jquery.com/jquery-1.8.3.min.js"
};
var SELECTORS = {
GOOGLE_LINK_SECTIONS : ".g"
};
var getNameAndURLFromLinks = function (el) {
var info = ["Links:\n"];
$(el).find("a").each(function () {
var url = $(this).attr("href");
if (/https?:\/\//.test(url)) {
info.push( "- [" + $(this).text() + "](" + url + ")");
}
});
return info.join("\n");
};
var storeDataInEvent = function (evt) {
var info = getNameAndURLFromLinks($(this));
event.dataTransfer.setData('text/plain', info);
};
var main = function () {
$(SELECTORS.GOOGLE_LINK_SECTIONS)
.attr("draggable", true)
.css("border", "3px orange solid")
.bind("dragstart", storeDataInEvent);
};
if(!window.jQuery){
window.alert("Paste the source of jQuery in the console and then run this script again. URL:" + URLS.JQUERY);
}else if(!/search/.test(document.location.href)){
window.alert("Google for something, then run this script in the console again.");
}
main();
}());
You should be able to create a Google Chrome extension that has this functionality for a set number of websites. Each site should have a different main() function. However, you might be able to create a general algorithm if you test against the top 100 sites.
Info on Drag and Drop: https://developer.mozilla.org/en-US/docs/DragDrop/Drag_Operations
dataTransfer Object: http://help.dottoro.com/ljvspfdo.php
List of MIME: http://en.wikipedia.org/wiki/Internet_media_type

Categories