2
* plupload.browserplus.js
4
* Copyright 2009, Moxiecode Systems AB
5
* Released under GPL License.
7
* License: http://www.plupload.com/license
8
* Contributing: http://www.plupload.com/contributing
11
// JSLint defined globals
12
/*global plupload:false, BrowserPlus:false, window:false */
16
* Yahoo BrowserPlus implementation. This runtime supports these features: dragdrop, jpgresize, pngresize.
19
* @class plupload.runtimes.BrowserPlus
20
* @extends plupload.Runtime
22
plupload.runtimes.BrowserPlus = plupload.addRuntime("browserplus", {
24
* Returns a list of supported features for the runtime.
26
* @return {Object} Name/value object with supported features.
28
getFeatures : function() {
41
* Initializes the browserplus runtime.
44
* @param {plupload.Uploader} uploader Uploader instance that needs to be initialized.
45
* @param {function} callback Callback to execute when the runtime initializes or fails to initialize. If it succeeds an object with a parameter name success will be set to true.
47
init : function(uploader, callback) {
48
var browserPlus = window.BrowserPlus, browserPlusFiles = {}, settings = uploader.settings, resize = settings.resize;
50
function addSelectedFiles(native_files) {
51
var files, i, selectedFiles = [], file, id;
53
// Add the native files and setup plupload files
54
for (i = 0; i < native_files.length; i++) {
55
file = native_files[i];
57
browserPlusFiles[id] = file;
59
selectedFiles.push(new plupload.File(id, file.name, file.size));
62
// Any files selected fire event
64
uploader.trigger("FilesAdded", selectedFiles);
68
// Setup event listeners if browserplus was initialized
73
uploader.bind("PostInit", function() {
74
var dropTargetElm, dropElmId = settings.drop_element,
75
dropTargetId = uploader.id + '_droptarget',
76
dropElm = document.getElementById(dropElmId),
79
// Enable/disable drop support for the drop target
80
// this is needed to resolve IE bubbeling issues and make it possible to drag/drop
81
// files into gears runtimes on the same page
82
function addDropHandler(id, end_callback) {
83
// Add drop target and listener
84
browserPlus.DragAndDrop.AddDropTarget({id : id}, function(res) {
85
browserPlus.DragAndDrop.AttachCallbacks({
87
hover : function(res) {
88
if (!res && end_callback) {
92
drop : function(res) {
97
addSelectedFiles(res);
105
document.getElementById(dropTargetId).style.top = '-1000px';
109
// Since IE has issues with bubbeling when it comes to the drop of files
110
// we need to do this hack where we show a drop target div element while dropping
111
if (document.attachEvent && (/MSIE/gi).test(navigator.userAgent)) {
112
// Create drop target
113
dropTargetElm = document.createElement('div');
114
dropTargetElm.setAttribute('id', dropTargetId);
115
plupload.extend(dropTargetElm.style, {
116
position : 'absolute',
119
filter : 'alpha(opacity=0)',
123
document.body.appendChild(dropTargetElm);
125
plupload.addEvent(dropElm, 'dragenter', function(e) {
126
var dropElm, dropElmPos;
128
dropElm = document.getElementById(dropElmId);
129
dropElmPos = plupload.getPos(dropElm);
131
plupload.extend(document.getElementById(dropTargetId).style, {
132
top : dropElmPos.y + 'px',
133
left : dropElmPos.x + 'px',
134
width : dropElm.offsetWidth + 'px',
135
height : dropElm.offsetHeight + 'px'
139
addDropHandler(dropTargetId, hide);
141
addDropHandler(dropElmId);
145
plupload.addEvent(document.getElementById(settings.browse_button), 'click', function(e) {
146
var mimes = [], i, a, filters = settings.filters, ext, type;
154
// Convert extensions to mimetypes
156
for (i = 0; i < filters.length; i++) {
157
ext = filters[i].extensions.split(',');
159
for (a = 0; a < ext.length; a++) {
160
if (ext[a] === '*') {
162
break no_type_restriction;
164
type = plupload.mimeTypes[ext[a]];
166
if (type && plupload.inArray(type, mimes) === -1) {
167
mimes.push(plupload.mimeTypes[ext[a]]);
172
browserPlus.FileBrowse.OpenBrowseDialog({
176
addSelectedFiles(res.value);
182
dropElm = dropTargetElm = null;
185
uploader.bind("CancelUpload", function() {
186
browserPlus.Uploader.cancel({}, function(){});
189
uploader.bind("DisableBrowse", function(up, state) {
193
uploader.bind("UploadFile", function(up, file) {
194
var nativeFile = browserPlusFiles[file.id], reqParams = {},
195
chunkSize = up.settings.chunk_size, loadProgress, chunkStack = [];
197
function uploadFile(chunk, chunks) {
200
// Stop upload if file is maked as failed
201
if (file.status == plupload.FAILED) {
205
reqParams.name = file.target_name || file.name;
207
// Only send chunk parameters if chunk size is defined
209
reqParams.chunk = "" + chunk;
210
reqParams.chunks = "" + chunks;
213
chunkFile = chunkStack.shift();
215
browserPlus.Uploader.upload({
216
url : up.settings.url,
217
files : {file : chunkFile},
218
cookies : document.cookies,
219
postvars : plupload.extend(reqParams, up.settings.multipart_params),
220
progressCallback : function(res) {
223
// since more than 1 chunk can be sent at a time, keep track of how many bytes
224
// of each chunk was sent
225
loadProgress[chunk] = parseInt(res.filePercent * chunkFile.size / 100, 10);
226
for (i = 0; i < loadProgress.length; i++) {
227
loaded += loadProgress[i];
230
file.loaded = loaded;
231
up.trigger('UploadProgress', file);
234
var httpStatus, chunkArgs;
237
httpStatus = res.value.statusCode;
240
up.trigger('ChunkUploaded', file, {
243
response : res.value.body,
248
if (chunkStack.length > 0) {
249
// More chunks to be uploaded
250
uploadFile(++chunk, chunks);
252
file.status = plupload.DONE;
254
up.trigger('FileUploaded', file, {
255
response : res.value.body,
260
if (httpStatus >= 400) {
261
up.trigger('Error', {
262
code : plupload.HTTP_ERROR,
263
message : plupload.translate('HTTP Error.'),
270
up.trigger('Error', {
271
code : plupload.GENERIC_ERROR,
272
message : plupload.translate('Generic Error.'),
280
function chunkAndUploadFile(native_file) {
281
file.size = native_file.size;
283
browserPlus.FileAccess.chunk({file : native_file, chunkSize : chunkSize}, function(cr) {
285
var chunks = cr.value, len = chunks.length;
287
loadProgress = Array(len);
289
for (var i = 0; i < len; i++) {
291
chunkStack.push(chunks[i]);
298
loadProgress = Array(1);
299
chunkStack.push(native_file);
304
// Resize image if it's a supported format and resize is enabled
305
if (resize && /\.(png|jpg|jpeg)$/i.test(file.name)) {
306
BrowserPlus.ImageAlter.transform({
308
quality : resize.quality || 90,
311
maxwidth : resize.width,
312
maxheight : resize.height
317
chunkAndUploadFile(res.value.file);
321
chunkAndUploadFile(nativeFile);
325
callback({success : true});
328
// Check for browserplus object
330
browserPlus.init(function(res) {
332
{service: "Uploader", version: "3"},
333
{service: "DragAndDrop", version: "1"},
334
{service: "FileBrowse", version: "1"},
335
{service: "FileAccess", version: "2"}
339
services.push({service : 'ImageAlter', version : "4"});
343
browserPlus.require({