oxjs/source/Ox.UI/js/Form/FileInput.js

311 lines
9.8 KiB
JavaScript
Raw Normal View History

2012-03-23 16:55:55 +00:00
'use strict';
2012-05-21 10:38:18 +00:00
/*@
2012-05-31 10:32:54 +00:00
Ox.FileInput <f> File Input
2012-05-21 10:38:18 +00:00
options <o> Options
2012-06-27 10:56:17 +00:00
disabled <b|false> If true, the element is disabled
maxFiles <n|-1> Maximum number of files (or -1 for unlimited)
maxLines <n|-1> Maximum number of lines to display (or -1 for unlimited)
maxSize <n|-1> Maximum total file size in bytes (or -1 for unlimited)
value <a|[]> Value (array of file objects)
width <w|256> Width in px
2012-05-21 10:38:18 +00:00
self <o> Shared private variable
2012-06-27 10:56:17 +00:00
([options[, self]]) -> <o:Ox.Element> File Input
change <!> change
2012-05-21 10:38:18 +00:00
@*/
2012-03-23 16:55:55 +00:00
Ox.FileInput = function(options, self) {
self = self || {};
var that = Ox.Element({}, self)
.defaults({
2012-06-27 10:56:17 +00:00
disabled: false,
2012-03-23 16:55:55 +00:00
maxFiles: -1,
maxLines: -1,
maxSize: -1,
2012-03-23 17:20:36 +00:00
value: [],
2012-03-23 16:55:55 +00:00
width: 256
})
.options(options || {})
2012-06-27 10:56:17 +00:00
.update({
disabled: function() {
that[self.options.disabled ? 'addClass' : 'removeClass']('OxDisabled');
self.$button.options({disabled: self.options.disabled});
self.$input && self.$input[self.options.disabled ? 'hide' : 'show']();
}
})
.addClass('OxFileInput' + (self.options.disabled ? ' OxDisabled' : ''))
2012-03-23 16:55:55 +00:00
.css({width: self.options.width + 'px'});
self.multiple = self.options.maxFiles != 1;
2012-03-23 17:57:12 +00:00
self.size = getSize();
2012-03-23 16:55:55 +00:00
self.$bar = Ox.Bar({size: 14})
2012-03-23 17:57:12 +00:00
.css(
Ox.extend({
width: self.options.width - 2 + 'px'
}, self.multiple && self.options.value.length ? {
borderBottomLeftRadius: 0,
borderBottomRightRadius: 0
} : {})
)
2012-03-23 16:55:55 +00:00
.appendTo(that);
2012-03-23 17:57:12 +00:00
self.$title = $('<div>')
2012-03-23 16:55:55 +00:00
.css({
float: 'left',
width: self.options.width - 102 + 'px',
paddingLeft: '4px',
overflow: 'hidden',
textOverflow: 'ellipsis'
})
2012-03-23 17:57:12 +00:00
.html(getTitleText())
2012-03-23 16:55:55 +00:00
.appendTo(self.$bar);
self.$size = $('<div>')
.css({
float: 'left',
width: '64px',
height: '14px',
paddingRight: '16px',
textAlign: 'right'
})
2012-03-23 17:57:12 +00:00
.html(getSizeText())
2012-03-23 16:55:55 +00:00
.appendTo(self.$bar);
self.$button = Ox.Button({
2012-06-27 10:56:17 +00:00
disabled: self.options.disabled,
2012-03-23 16:55:55 +00:00
style: 'symbol',
title: self.multiple || self.options.value.length == 0
? 'add' : 'close',
2012-03-23 16:55:55 +00:00
type: 'image'
})
.attr({
title: self.multiple || self.options.value.length == 0
? '' : 'Clear'
})
2012-03-23 16:55:55 +00:00
.css({
float: 'left',
marginTop: '-1px'
})
.bindEvent({
click: clearFile
})
.appendTo(self.$bar);
if (self.multiple || self.options.value.length == 0) {
self.$input = renderInput();
2012-06-27 10:56:17 +00:00
self.options.disabled && self.$input.hide();
}
2012-03-23 16:55:55 +00:00
if (self.multiple) {
self.$files = $('<div>')
.addClass('OxFiles')
.css({
width: self.options.width - 2 + 'px',
height: getHeight()
})
.appendTo(that);
2012-03-23 17:57:12 +00:00
self.options.value.length == 0 && self.$files.hide();
2012-06-27 07:41:10 +00:00
self.$list = Ox.TableList({
2012-03-23 16:55:55 +00:00
columns: [
{
id: 'name',
visible: true,
width: self.options.width - 94
},
{
align: 'right',
format: function(value) {
return Ox.formatValue(value, 'B');
},
id: 'size',
visible: true,
width: 64
},
{
align: 'right',
format: function(value, data) {
return Ox.Button({
style: 'symbol',
title: 'close',
type: 'image'
})
.attr({title: 'Remove File'})
.css({margin: '-1px -4px 0 0'})
.bindEvent({
click: function() {
self.$list.options({selected: [value]});
removeFiles([value]);
}
});
},
id: 'id',
visible: true,
width: 28
}
],
2012-03-23 17:57:12 +00:00
items: getItems(),
sort: [{key: 'name', operator: '+'}],
unique: 'id'
2012-03-23 16:55:55 +00:00
})
.css({
left: 0,
top: 0,
width: self.options.width - 2 + 'px',
2012-05-26 15:48:19 +00:00
height: '64px'
2012-03-23 16:55:55 +00:00
})
.bindEvent({
'delete': function(data) {
removeFiles(data.ids);
}
})
.appendTo(self.$files);
}
function addFiles(e) {
var filelist = e.target.files,
files = [];
Ox.loop(filelist.length, function(i) {
files.push(filelist.item(i));
});
files.sort(self.options.maxSize == -1 ? function(a, b) {
2012-03-23 17:20:36 +00:00
a = a.name.toLowerCase();
b = b.name.toLowerCase();
return a < b ? -1 : a > b ? 1 : 0;
2012-03-23 16:55:55 +00:00
} : function(a, b) {
2012-06-27 10:56:17 +00:00
// if there is a max size,
2012-03-23 17:20:36 +00:00
// try to add small files first
2012-03-23 16:55:55 +00:00
return a.size - b.size;
}).forEach(function(file) {
if (!exists(file) && (
self.options.maxFiles == -1
2012-03-23 17:20:36 +00:00
|| self.options.value.length < self.options.maxFiles
2012-03-23 17:57:12 +00:00
) && (
self.options.maxSize == -1
|| self.size + file.size < self.options.maxSize
2012-03-23 16:55:55 +00:00
)) {
2012-03-23 17:57:12 +00:00
self.options.value.push(file);
self.size += file.size;
2012-03-23 16:55:55 +00:00
}
});
2012-03-23 17:57:12 +00:00
self.$title.html(getTitleText());
self.$size.html(getSizeText());
2012-03-23 16:55:55 +00:00
if (self.multiple) {
self.$bar.css({
borderBottomLeftRadius: 0,
borderBottomRightRadius: 1
});
self.$files.css({height: getHeight()}).show();
self.$list.options({items: getItems()});
if (
2012-03-23 17:20:36 +00:00
self.options.value.length == self.options.maxFiles
2012-03-23 16:55:55 +00:00
|| self.size == self.options.maxSize
) {
self.$button.options({disabled: true});
}
self.$input = renderInput();
2012-03-23 16:55:55 +00:00
} else {
self.$button.options({title: 'close'}).attr({title: 'Clear'});
self.$input.remove();
2012-03-23 16:55:55 +00:00
}
2012-03-23 17:20:36 +00:00
that.triggerEvent('change', {value: self.options.value});
2012-03-23 16:55:55 +00:00
}
function clearFile() {
2012-03-23 17:20:36 +00:00
self.options.value = [];
2012-03-23 16:55:55 +00:00
self.size = 0;
2012-03-23 17:57:12 +00:00
self.$title.html(getTitleText());
self.$size.html(getSizeText());
2012-03-23 16:55:55 +00:00
self.$button.options({title: 'add'}).attr({title: ''});
self.$input = renderInput();
2012-03-23 17:20:36 +00:00
that.triggerEvent('change', {value: self.options.value});
2012-03-23 16:55:55 +00:00
}
function exists(file) {
2012-03-23 17:20:36 +00:00
return self.options.value.some(function(f) {
2012-03-23 16:55:55 +00:00
return f.name == file.name
&& f.size == file.size
&& Ox.isEqual(f.lastModifiedDate, file.lastModifiedDate);
});
}
function getHeight() {
return (
self.options.maxLines == -1
2012-03-23 17:20:36 +00:00
? self.options.value.length
: Math.min(self.options.value.length, self.options.maxLines)
2012-03-23 16:55:55 +00:00
) * 16 + 'px';
}
function getItems() {
2012-03-23 17:20:36 +00:00
return self.options.value.map(function(file, i) {
2012-03-23 16:55:55 +00:00
return {name: file.name, size: file.size, id: i};
});
}
function getSize() {
2012-03-23 17:57:12 +00:00
return self.options.value.reduce(function(prev, curr) {
return prev + curr.size;
}, 0);
}
function getSizeText() {
2012-03-23 16:55:55 +00:00
return self.size ? Ox.formatValue(self.size, 'B') : '';
}
2012-03-23 17:57:12 +00:00
function getTitleText() {
2012-03-23 17:20:36 +00:00
var length = self.options.value.length
2012-03-23 16:55:55 +00:00
return length == 0
? 'No file' + (self.multiple ? 's' : '') + ' selected'
: self.multiple
2012-03-23 17:57:12 +00:00
? length + ' file' + (length == 1 ? '' : 's')
2012-03-23 17:20:36 +00:00
: self.options.value[0].name;
2012-03-23 16:55:55 +00:00
}
function removeFiles(ids) {
2012-03-23 17:20:36 +00:00
self.options.value = self.options.value.filter(function(v, i) {
2012-03-23 16:55:55 +00:00
return ids.indexOf(i) == -1;
});
2012-03-23 17:57:12 +00:00
self.size = getSize();
2012-03-23 17:20:36 +00:00
if (self.options.value.length == 0) {
2012-03-23 16:55:55 +00:00
self.$bar.css({
borderBottomLeftRadius: '8px',
borderBottomRightRadius: '8px'
});
self.$files.hide();
}
2012-03-23 17:57:12 +00:00
self.$title.html(getTitleText());
self.$size.html(getSizeText());
2012-03-23 16:55:55 +00:00
self.$list.options({items: getItems(), selected: []});
self.$files.css({height: getHeight()});
2012-03-23 17:20:36 +00:00
that.triggerEvent('change', {value: self.options.value});
2012-03-23 16:55:55 +00:00
}
function renderInput() {
self.$input && self.$input.remove();
return $('<input>')
.attr(
Ox.extend({
title: self.multiple ? 'Add Files' : 'Select File',
type: 'file'
}, self.multiple ? {
multiple: true
} : {})
)
.css({
float: 'left',
width: '16px',
height: '14px',
margin: '-1px -7px 0 -16px',
opacity: 0
})
2012-05-28 14:06:22 +00:00
.on({
change: addFiles
})
.appendTo(self.$bar);
}
2012-03-23 16:55:55 +00:00
return that;
};