Jump to content

Support for drag & drop, multiple file selects and instant uploads in file field


apeisa
 Share

Recommended Posts

Sounds like a right place. I think we need to test and play a little and decide how much validation we need here.

I'm thinking it should just go through the same exact validation as all the other uploaded files, if possible. This validation mainly consists of making sure it's the right file type (via extension) and renaming the file to be consistent with the characters PW allows for filenames. Though it also does some other stuff, like optionally unzipping zip files. The image Fieldtype also resizes the original image file if necessary (as you know). But don't worry too much about this stuff now– If you get a working example going, I'll be happy to place all the code where it needs to go. And of course, take your time… no rush. I just wanted to make sure I get you everything you need and all questions answered when you need it.

Link to comment
Share on other sites

Ok, here we go now. I didn't implement any validation (I let Ryan do that), so you are able to upload any files to image fields etc. Also it is possible to add more files than is allowed per image field.

I'm not sure if I remembered all the files needed, but should be. Just replace InputfieldFile folder from /wire/modules/inputfield and ProcessPageEdit goes to /wire/modules/process/processpageedit.

Will record little screencast soon (ready: http://screencast.com/t/IQk7U4Aewe). There are some things I would like to polish and rethink in the UI (bigger drop area and next to inputfield, not below), but overall it should be pretty usable. Please let me know what you think?

PS: There is image preview code commented out in the js-file - it did slow down the page very much if you added big images (even crashed my chrome dev inspector). You can try it if you want it.

PPS: Consider this "highly experimental" and try only on test environment :)

InputfieldFile.zip

ProcessPageEdit.module

Link to comment
Share on other sites

Just watched the screencast and it's great! Now I understand what all the excitement is about. :) I haven't yet installed it–only a few minutes left before I have to go, but planning to install first thing tomorrow morning (or later this evening, if possible). Love the way you did the progress bars. This all seems like quite a fantastic UI option for uploading images or files. Well done!

Link to comment
Share on other sites

Finally got a moment here to install and test it out. What can I say, it's awesome. :) Love it! This is how I'll be uploading files from now on. I'm thinking this must go in the first version of 2.1. One question is if there needs to be a 'drop area'? Is it possible to just have the entire field be a drop area?

Link to comment
Share on other sites

Thanks guys. I have been demoing this today at the office, and it has nice sales effect also. It does look & feel cool :) Also gives as possibility to brand pw as "HTML5 CMS" :D

One question is if there needs to be a 'drop area'? Is it possible to just have the entire field be a drop area?

Great idea, I will implement this. I will leave some text indicator to tell editors that you can drop files, but use the whole field as "drop area".

Link to comment
Share on other sites

Ok, few small improvements:

  • No more "drop area", just throw your files to the field and that's it (I did leave small "or drop your files here" notification, so that people will know the possibility)
  • Added 5-99% percentages to progressbar
  • Cleaned and credited the code. Not sure where I should thank the guys (Robert Nyman and Craig Buckler) who provided initial code examples and tutorials, so I putted in to the comments with links.

EDIT: Added ProcessPageEdit.module to attachment, since if someone tests this from zip only it won't save the files...

InputfieldFile.zip

ProcessPageEdit.module

Link to comment
Share on other sites

Awesome update! I just dragged in 6 files... beautiful! Even better now that I can just drag them anywhere in the field. Thank you for your fantastic work with this. I'm going to dig deeper into your code here soon so that I can figure out how to get this to be built-in to the WireUpload class.

Link to comment
Share on other sites

This has been causing issues on Soma's site and localhost. We did little debug session, and it seems that for some reason this:

$this->page->filesManager->path

returns nothing. So it tries to write the file to root and that gives (of course) permission issues:

<b>Warning</b>:  file_put_contents(/Koala.jpg) [<a href='function.file-put-contents'>function.file-put-contents</a>]: failed to open stream: Permission denied in <b>/path/to/pw/wire/modules/Process/ProcessPageEdit/ProcessPageEdit.module</b> on line <b>933</b>

We continue testing and report if $this->page->$fieldname->path works there.

But I am confused what might cause $this->page->filesManager->path to fail on Soma's server and localhost? He is using latest version of P21.

EDIT: This code works:

$this->page->$fieldname->path . "/" . $filename, 

One issue left: it saves files with the name it is saved (of course), like: Lighthouse.jpg, but on admin site it tries to get it with small first letter: getimagesize(/path/to/site/assets/files/1003/lighthouse.jpg) => this causes error. This seems to be something that will not be issue after ProcessPageEdit.module will use the wireupload class?

Link to comment
Share on other sites

Found the issue:

$page->filesManager->path - doesn't return anything, it should be:

$page->filesManager->path() - this works

I changed this in ProcessPageEdit.module to be $this->page->filesManager->path()

and now upload works.

Link to comment
Share on other sites

Just a quick one, I was having a read of things you can do with HTML5 and one of them suggests you can resize images before they're uploaded: http://hacks.mozilla.org/2010/02/an-html5-offline-image-editor-and-uploader-application/

Is this really possible? If so, it's awesome and I would like to know if it's possible to include this in your code Antti if an image field has width and/or height dimensions set?

One of my biggest gripes is that often you'll hand a website over to the webmaster and they won;t know about resizing images before they're uploaded so, especially as digital cameras are getting better and better, you'll frequently get images of 5mb at something silly like 3000 pixels wide being uploaded :rolleyes:

If it's possible to do this, it would be amazing. It would also solve my issue with Windows not wanting to play nice and resize images in PW as this would happen before uploading, but that's just a nice side-effect ;)

EDIT: Potentially more useful reference for this: http://webreflection.blogspot.com/2010/12/100-client-side-image-resizing.html

EDIT2: The possibilities here seem limitless - you can even perform cropping on the client side before uploading, but I'd settle for resizing before upload for now purely because of the speed benefits - especially when uploading multiple images :)

Link to comment
Share on other sites

Only problem (well, maybe not only ;)) is that you're then putting resizing code into the more generic fileupload js, and also when you resize an image this way it seems to be a PNG and so would need processing further on the server to get it into the correct format (thinking the PHP code for that pretty much already exists in PW though if you can force a resize to the same size and just a different file extension).

Anyway, not as easy as I first thought :(

Link to comment
Share on other sites

Pete, great idea and will def. implement that at some point. I also thought about cropping, but decided that it breaks the uploading flow badly. Might also use cropped images to show preview of the images (that might be the reason that preview slowed the site down because they were huge images just scaled down in css).

I think that cropping would be best handled after uploading, in modal view that opens when you click the filename.

Link to comment
Share on other sites

$page->filesManager->path - doesn't return anything, it should be:
$page->filesManager->path() - this works

Sorry about this, I think I posted an example using 'path' rather than 'path()' earlier by mistake. The function version was required here. I say 'was', because I just updated the class to also support the non-function version too, so will commit that soon.

Link to comment
Share on other sites

Antti, I've been going through the code line by line just to see how everything works so that I can be of more help here. The code looks beautiful, you did an awesome job with putting this together. I've only made it through the InputfieldFile part so far and here are some comments/questions for core integration:


In this line, I'm wondering about the css('color', 'white') because that may or may not be compatible with whatever UI theme is being used?

progressBarValue.addClass("ui-state-default").css('color','white').html("<span>100% complete</span>");

Also on the line above, what do you think about replacing the word "complete" with a ui-icon-check or a ui-icon-circle-check, just so there's one less thing to translate in languages?


Since this line is in the JS, it made me realize I probably need to make ProcessPageEdit so that you can post right to "./". Otherwise, the HTML5 upload will be harder to make use of outside of the PageEdit (for example, the new CSV import module has a file upload, and so having the JS post to /fields/ isn't portable). This is my fault of course, and I'm working on an alternative so that you can post to "./" rather than "./fields/" and will keep you up to date.

xhr.open("POST", "./fields/?id=" + page_id, true);


I was wondering about class names like "over" and "complete", and if it might be generic enough to conflict with some other future 3rd party module or customization that someone is using. If these are part of jQuery UI's built-in progress bar classes, then there's nothing we can do about it, so skip the next paragraph. :) Otherwise, here's a thought about class names created by modules:

When it comes to the core, it might seem overly verbose, but I mostly try to use really specific names so that there's no possibility it could ever conflict with someone else's stuff. I figure I'll leave the short/simple names for non-core stuff. For instance, lets say someone builds their own new Fieldtype and they use class names like "over", "on" and so forth. If they don't scope them down far enough in their stylesheet, the "over" one could potentially affect the HTML5 upload styles. Like, lets say they had this in their stylesheet:

.over {
    position: absolute; 
    top: 0;
    left: 0; 
}

Granted, that's their problem not ours, and you've properly scoped your styles in the CSS. But it's also one of those things that is easy enough to prevent with specificity. Examples might be: InputfieldFileHTML5Over and InputfieldFileHTML5Complete … verbose and ugly, I know. But I just wanted to mention this and you decide whether it's worth it.


I don't know my way around JS near as well as PHP, so had a question on this line:

if (typeof files !== "undefined") {

If I recall correctly, I usually see it like this (constant rather than string):

if (typeof files !== undefined) {

Does it work either way?


On the following lines in the stylesheet, I'm wondering about theme conflicts when someone swaps in a new jQuery UI theme. Specifically wondering if any might work better as jQuery UI interaction states or interaction cues classes (http://jqueryui.com/docs/Theming/API) rather than defining specific colors. Also should mention that I'm occasionally defining some specific colors in some of the module-specific code in PW as well, but am trying to move away from it for better compatibility with new admin themes.

.InputfieldFileUpload .dropHere  {  
    ...
    color: #777;
}

.complete {
    background: green !important;
}

.AjaxUpload .ui-progressbar-value {
    ...
    color: black;
}

.ui-widget-content.over { 
    border-color: rgb(135, 167, 27);
    background: rgba(90, 200, 27, 0.1);
}
Link to comment
Share on other sites

Ryan, thanks for your feedback and nice words.

I haven't really thought about css clashes (and classes) here at all - although it might feel so since it uses jQuery UI progressbar, but that was the last thing that got added there :) So most of the classes and css are just quick ones I added to test things out. Will definitely try to make those use as much as jQuery UI as possible.

I agree that it would be perfect to have zero colors coming from module & admin css - there are quite a bit currently around. It might be that some are needed because jQuery UI is not for everything (or is it? I don't know.), but I agree that we should keep that at minimum. Or at least use different shades of gray if some coloring is needed.


"undefined" or undefined - I think there are few ways of checking undefined in if clause:

(antti === undefined) or (typeof antti == "undefined") and I have read somewhere (can't even remember) that latter is the safest (works everywhere). Not on solid ground here, so please keep me corrected if I am wrong. It has never let me down though :)


On posting to ./ insted of ./fields - You might wanna check if  $_SERVER['HTTP_X_FIELDNAME'] returns something. Well, there are plenty of ways of course and you will know the best one.


I will take a look at the jQuery Theming API and look for the best UI classes here. It worked without too much problem in progressbars, so shouldn't be a problem here. Also agree with having "ugly but unique" classes, will def. help people who are building own admin themes (like myself).

Link to comment
Share on other sites

because jQuery UI is not for everything (or is it? I don't know.),

It's definitely not for everything. There are plenty of things we need to define custom styles for. I try to keep them all part of the admin theme for the most part, but of course those have to be general purpose, non-specific stuff. It gets tricky when you get down to modules with specific needs, especially with regards to color. One way I've been avoiding the issue lately is to use opacity. For instance, if I want something to be a little de-emphasized, I might add an "opacity: 0.5;" to the stylesheet, so that it'll continue to be de-emphasized (with the right colors) regardless of the admin theme. Not sure if this is the best approach or not... but it seems to work.

Ultimately we may want to add more styles to theme stylesheets to cover more needs. Or could standardize on some style framework that compliments jQuery UI and takes a broader role. I appreciate any suggestions you have in this area.

"undefined" or undefined - I think there are few ways of checking undefined in if clause:

Good to know. I rarely had to deal with "undefined" before jQuery 1.6, but now it seems 1.6 likes to return undefined for everything it didn't before, so I suppose I'm getting to know non-jQuery javascript a little better now. :)

On posting to ./ insted of ./fields - You might wanna check if  $_SERVER['HTTP_X_FIELDNAME'] returns something. Well, there are plenty of ways of course and you will know the best one.

Can you describe more or point me to a good link? I'm not sure I understand about the HTTP_X_FIELDNAME.

Also agree with having "ugly but unique" classes, will def. help people who are building own admin themes (like myself).

I use 'ugly but unique' mostly for selecting in javascript or styling things that are completely unique to the module. Everywhere else the jQuery UI styles are probably better, but of course they don't cover everything. Perhaps we can collaborate on PW's common CSS framework to cover all the stuff that jQuery UI doesn't.

Link to comment
Share on other sites

Ultimately we may want to add more styles to theme stylesheets to cover more needs. Or could standardize on some style framework that compliments jQuery UI and takes a broader role. I appreciate any suggestions you have in this area.

I think that latter might be better. I think that Themeroller and UI theme should be used as is - it should be vanilla and no reason to edit or add to those files ever. But to use more classes and styles that compliment jQuery UI sounds good to me.

What comes to this drag & drop upload, UI was pretty much all that needed. Ok, the default hover state (pink) is little wild on big field area, but at least you notice it :) New "UI compatible" version available below:

I tried this on my "clean admin" theme and it works nicely. Also this is 100% compatible with AdminBar (at least the latest version).

InputfieldFile.zip

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...