allow menu item to trigger native file dialog (see demo, fixes #691)
This commit is contained in:
parent
1c3e257bc8
commit
df03bf1841
6 changed files with 246 additions and 97 deletions
|
@ -1,42 +1,155 @@
|
||||||
Ox.load('UI', function() {
|
Ox.load('UI', function() {
|
||||||
|
|
||||||
//Ox.Theme('modern');
|
var files,
|
||||||
|
|
||||||
Ox.FileInput({
|
$menu = Ox.MainMenu({
|
||||||
maxFiles: 1,
|
menus: [
|
||||||
width: 256
|
{
|
||||||
|
id: 'file', title: 'File', items: [
|
||||||
|
{id: 'mount', title: 'Mount Volume...', icon: Ox.UI.getImageURL('symbolMount'), checked: true, disabled: true, keyboard: 'control m'},
|
||||||
|
{id: 'select', title: 'Select Files...', icon: Ox.UI.getImageURL('symbolVolume'), file: {maxFiles: -1, maxSize: -1, width: 96}, keyboard: 'control f'},
|
||||||
|
{id: 'unmount', title: 'Unmount Volume', icon: Ox.UI.getImageURL('symbolUnmount'), keyboard: 'control u'}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.bindEvent({
|
||||||
|
click: function(data) {
|
||||||
|
if (data.id == 'select') {
|
||||||
|
files = data.files;
|
||||||
|
openDialog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
$main = Ox.Element()
|
||||||
|
.append(
|
||||||
|
Ox.Label({
|
||||||
|
textAlign: 'center',
|
||||||
|
title: 'File Button',
|
||||||
|
width: 128
|
||||||
})
|
})
|
||||||
.css({
|
.css({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
left: '16px',
|
left: '16px',
|
||||||
top: '16px'
|
top: '16px'
|
||||||
})
|
})
|
||||||
.appendTo(Ox.$body);
|
)
|
||||||
|
.append(
|
||||||
Ox.FileButton({
|
Ox.FileButton({
|
||||||
title: 'Select Files...',
|
maxFiles: 1,
|
||||||
width: 256
|
title: 'Select File...',
|
||||||
})
|
width: 128
|
||||||
.bindEvent({
|
|
||||||
click: function(data) {
|
|
||||||
this.options({disabled: true});
|
|
||||||
Ox.FileInput({
|
|
||||||
value: data.files,
|
|
||||||
width: 256
|
|
||||||
})
|
})
|
||||||
.css({
|
.css({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
left: '16px',
|
left: '160px',
|
||||||
top: '80px'
|
top: '16px'
|
||||||
})
|
})
|
||||||
.appendTo(Ox.$body);
|
)
|
||||||
}
|
.append(
|
||||||
|
Ox.Label({
|
||||||
|
textAlign: 'center',
|
||||||
|
title: 'File Input',
|
||||||
|
width: 128
|
||||||
})
|
})
|
||||||
.css({
|
.css({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
left: '16px',
|
left: '16px',
|
||||||
top: '48px'
|
top: '48px'
|
||||||
})
|
})
|
||||||
|
)
|
||||||
|
.append(
|
||||||
|
Ox.FileInput({
|
||||||
|
maxFiles: 1,
|
||||||
|
width: 256
|
||||||
|
})
|
||||||
|
.css({
|
||||||
|
position: 'absolute',
|
||||||
|
left: '160px',
|
||||||
|
top: '48px'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.append(
|
||||||
|
Ox.FileInput({
|
||||||
|
width: 256
|
||||||
|
})
|
||||||
|
.css({
|
||||||
|
position: 'absolute',
|
||||||
|
left: '160px',
|
||||||
|
top: '80px'
|
||||||
|
})
|
||||||
|
),
|
||||||
|
|
||||||
|
$panel = Ox.SplitPanel({
|
||||||
|
elements: [
|
||||||
|
{
|
||||||
|
element: $menu,
|
||||||
|
size: 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
element: $main
|
||||||
|
}
|
||||||
|
],
|
||||||
|
orientation: 'vertical'
|
||||||
|
})
|
||||||
.appendTo(Ox.$body);
|
.appendTo(Ox.$body);
|
||||||
|
|
||||||
|
function openDialog() {
|
||||||
|
|
||||||
|
var $content,
|
||||||
|
|
||||||
|
$dialog = Ox.Dialog({
|
||||||
|
buttons: [
|
||||||
|
Ox.Button({
|
||||||
|
id: 'cancel',
|
||||||
|
title: 'Cancel'
|
||||||
|
})
|
||||||
|
.bindEvent({
|
||||||
|
click: function() {
|
||||||
|
$dialog.close();
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
Ox.Button({
|
||||||
|
id: 'upload',
|
||||||
|
title: 'Upload'
|
||||||
|
})
|
||||||
|
.bindEvent({
|
||||||
|
click: function() {
|
||||||
|
$dialog.close();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
],
|
||||||
|
content: $content = Ox.Element()
|
||||||
|
.css(getContentCSS())
|
||||||
|
.append(
|
||||||
|
Ox.FileInput({
|
||||||
|
value: files,
|
||||||
|
width: 256
|
||||||
|
})
|
||||||
|
.css({
|
||||||
|
position: 'absolute',
|
||||||
|
left: '16px',
|
||||||
|
top: '16px',
|
||||||
|
marginBottom: '16px'
|
||||||
|
})
|
||||||
|
.bindEvent({
|
||||||
|
change: function(data) {
|
||||||
|
files = data.value;
|
||||||
|
$content.css(getContentCSS())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
),
|
||||||
|
title: 'Files',
|
||||||
|
width: 288 + Ox.UI.SCROLLBAR_SIZE,
|
||||||
|
height: 129
|
||||||
|
})
|
||||||
|
.open();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function getContentCSS() {
|
||||||
|
return {height: 49 + files.length * 16 + 'px'}
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
|
@ -733,6 +733,18 @@ input.OxCheckbox {
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
OxFileButton
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
.OxMenu .OxFileButton > .OxButton {
|
||||||
|
height: 16px;
|
||||||
|
margin: -1px 0 0 -6px;
|
||||||
|
border-width: 0;
|
||||||
|
background: transparent;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
OxFileInput
|
OxFileInput
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -32,26 +32,7 @@ Ox.FileButton = function(options, self) {
|
||||||
})
|
})
|
||||||
.appendTo(that);
|
.appendTo(that);
|
||||||
|
|
||||||
self.$input = $('<input>')
|
self.$input = renderInput();
|
||||||
.attr(
|
|
||||||
Ox.extend({
|
|
||||||
title: self.multiple ? 'Add Files' : 'Select File',
|
|
||||||
type: 'file'
|
|
||||||
}, self.multiple ? {
|
|
||||||
multiple: true
|
|
||||||
} : {})
|
|
||||||
)
|
|
||||||
.css({
|
|
||||||
float: 'left',
|
|
||||||
width: self.options.width + 'px',
|
|
||||||
height: '16px',
|
|
||||||
marginLeft: -self.options.width + 'px',
|
|
||||||
opacity: 0
|
|
||||||
})
|
|
||||||
.bind({
|
|
||||||
change: selectFiles
|
|
||||||
})
|
|
||||||
.appendTo(that);
|
|
||||||
self.options.disabled && self.$input.hide();
|
self.options.disabled && self.$input.hide();
|
||||||
|
|
||||||
function selectFiles(e) {
|
function selectFiles(e) {
|
||||||
|
@ -71,7 +52,7 @@ Ox.FileButton = function(options, self) {
|
||||||
}).forEach(function(file) {
|
}).forEach(function(file) {
|
||||||
if ((
|
if ((
|
||||||
self.options.maxFiles == -1
|
self.options.maxFiles == -1
|
||||||
|| self.options.value.length < self.options.maxFiles
|
|| self.files.length < self.options.maxFiles
|
||||||
) && (
|
) && (
|
||||||
self.options.maxSize == -1
|
self.options.maxSize == -1
|
||||||
|| self.size + file.size < self.options.maxSize
|
|| self.size + file.size < self.options.maxSize
|
||||||
|
@ -80,11 +61,36 @@ Ox.FileButton = function(options, self) {
|
||||||
self.size += file.size;
|
self.size += file.size;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
self.$input = renderInput();
|
||||||
if (self.files.length) {
|
if (self.files.length) {
|
||||||
that.triggerEvent('click', {files: self.files});
|
that.triggerEvent('click', {files: self.files});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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: self.options.width + 'px',
|
||||||
|
height: '16px',
|
||||||
|
marginLeft: -self.options.width + 'px',
|
||||||
|
opacity: 0
|
||||||
|
})
|
||||||
|
.bind({
|
||||||
|
change: selectFiles
|
||||||
|
})
|
||||||
|
.appendTo(that);
|
||||||
|
}
|
||||||
|
|
||||||
self.setOption = function(key, value) {
|
self.setOption = function(key, value) {
|
||||||
if (key == 'disabled') {
|
if (key == 'disabled') {
|
||||||
self.$button.options({disabled: value});
|
self.$button.options({disabled: value});
|
||||||
|
|
|
@ -65,29 +65,7 @@ Ox.FileInput = function(options, self) {
|
||||||
})
|
})
|
||||||
.appendTo(self.$bar);
|
.appendTo(self.$bar);
|
||||||
|
|
||||||
self.$input = Ox.Element({
|
self.$input = renderInput();
|
||||||
element: '<input>'
|
|
||||||
//tooltip: self.multiple ? 'Add Files' : 'Select File'
|
|
||||||
})
|
|
||||||
.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
|
|
||||||
})
|
|
||||||
.bind({
|
|
||||||
change: addFiles
|
|
||||||
})
|
|
||||||
.appendTo(self.$bar);
|
|
||||||
|
|
||||||
if (self.multiple) {
|
if (self.multiple) {
|
||||||
self.$files = $('<div>')
|
self.$files = $('<div>')
|
||||||
|
@ -128,11 +106,6 @@ Ox.FileInput = function(options, self) {
|
||||||
click: function() {
|
click: function() {
|
||||||
self.$list.options({selected: [value]});
|
self.$list.options({selected: [value]});
|
||||||
removeFiles([value]);
|
removeFiles([value]);
|
||||||
/*
|
|
||||||
setTimeout(function() {
|
|
||||||
self.$list.options({selected: []});
|
|
||||||
}, 25);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -174,6 +147,7 @@ Ox.FileInput = function(options, self) {
|
||||||
// try to add small files first
|
// try to add small files first
|
||||||
return a.size - b.size;
|
return a.size - b.size;
|
||||||
}).forEach(function(file) {
|
}).forEach(function(file) {
|
||||||
|
Ox.print('::', file, exists(file), self.options.value)
|
||||||
if (!exists(file) && (
|
if (!exists(file) && (
|
||||||
self.options.maxFiles == -1
|
self.options.maxFiles == -1
|
||||||
|| self.options.value.length < self.options.maxFiles
|
|| self.options.value.length < self.options.maxFiles
|
||||||
|
@ -200,9 +174,10 @@ Ox.FileInput = function(options, self) {
|
||||||
) {
|
) {
|
||||||
self.$button.options({disabled: true});
|
self.$button.options({disabled: true});
|
||||||
}
|
}
|
||||||
|
self.$input = renderInput();
|
||||||
} else {
|
} else {
|
||||||
self.$button.options({title: 'close'}).attr({title: 'Clear'});
|
self.$button.options({title: 'close'}).attr({title: 'Clear'});
|
||||||
self.$input.hide();
|
self.$input.remove();
|
||||||
}
|
}
|
||||||
that.triggerEvent('change', {value: self.options.value});
|
that.triggerEvent('change', {value: self.options.value});
|
||||||
}
|
}
|
||||||
|
@ -213,7 +188,7 @@ Ox.FileInput = function(options, self) {
|
||||||
self.$title.html(getTitleText());
|
self.$title.html(getTitleText());
|
||||||
self.$size.html(getSizeText());
|
self.$size.html(getSizeText());
|
||||||
self.$button.options({title: 'add'}).attr({title: ''});
|
self.$button.options({title: 'add'}).attr({title: ''});
|
||||||
self.$input.show();
|
self.$input = renderInput();
|
||||||
that.triggerEvent('change', {value: self.options.value});
|
that.triggerEvent('change', {value: self.options.value});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,5 +252,29 @@ Ox.FileInput = function(options, self) {
|
||||||
that.triggerEvent('change', {value: self.options.value});
|
that.triggerEvent('change', {value: self.options.value});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
})
|
||||||
|
.bind({
|
||||||
|
change: addFiles
|
||||||
|
})
|
||||||
|
.appendTo(self.$bar);
|
||||||
|
}
|
||||||
|
|
||||||
return that;
|
return that;
|
||||||
};
|
};
|
||||||
|
|
|
@ -116,7 +116,7 @@ Ox.Menu = function(options, self) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function clickItem(position) {
|
function clickItem(position, files) {
|
||||||
var item = that.items[position],
|
var item = that.items[position],
|
||||||
group = item.options('group'),
|
group = item.options('group'),
|
||||||
menu = self.options.mainmenu || self.options.parent || that,
|
menu = self.options.mainmenu || self.options.parent || that,
|
||||||
|
@ -156,10 +156,10 @@ Ox.Menu = function(options, self) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
menu.triggerEvent('click', {
|
menu.triggerEvent('click', Ox.extend({
|
||||||
id: item.options('id'),
|
id: item.options('id'),
|
||||||
title: Ox.stripTags(item.options('title')[0])
|
title: Ox.stripTags(item.options('title')[0])
|
||||||
});
|
}, files ? {files: files} : {}));
|
||||||
}
|
}
|
||||||
if (item.options('title').length == 2) {
|
if (item.options('title').length == 2) {
|
||||||
item.toggleTitle();
|
item.toggleTitle();
|
||||||
|
@ -236,10 +236,14 @@ Ox.Menu = function(options, self) {
|
||||||
var item,
|
var item,
|
||||||
position,
|
position,
|
||||||
$target = $(event.target),
|
$target = $(event.target),
|
||||||
$parent = $target.parent();
|
$parent = $target.parent(),
|
||||||
|
$grandparent = $parent.parent();
|
||||||
if ($parent.is('.OxCell')) {
|
if ($parent.is('.OxCell')) {
|
||||||
$target = $parent;
|
$target = $parent;
|
||||||
$parent = $target.parent();
|
$parent = $target.parent();
|
||||||
|
} else if ($grandparent.is('.OxCell')) {
|
||||||
|
$target = $grandparent;
|
||||||
|
$parent = $target.parent();
|
||||||
}
|
}
|
||||||
if ($target.is('.OxCell')) {
|
if ($target.is('.OxCell')) {
|
||||||
position = $parent.data('position');
|
position = $parent.data('position');
|
||||||
|
@ -617,6 +621,10 @@ Ox.Menu = function(options, self) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
that.clickItem = function(position, files) {
|
||||||
|
clickItem(position, files);
|
||||||
|
};
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
getItem <f>
|
getItem <f>
|
||||||
@*/
|
@*/
|
||||||
|
|
|
@ -28,7 +28,6 @@ Ox.MenuItem = function(options, self) {
|
||||||
bind: [], // fixme: what's this?
|
bind: [], // fixme: what's this?
|
||||||
checked: null,
|
checked: null,
|
||||||
disabled: false,
|
disabled: false,
|
||||||
file: false,
|
|
||||||
group: '',
|
group: '',
|
||||||
icon: '',
|
icon: '',
|
||||||
id: '',
|
id: '',
|
||||||
|
@ -38,6 +37,7 @@ Ox.MenuItem = function(options, self) {
|
||||||
menu: null, // fixme: is passing the menu to 100s of menu items really memory-neutral?
|
menu: null, // fixme: is passing the menu to 100s of menu items really memory-neutral?
|
||||||
position: 0,
|
position: 0,
|
||||||
title: [],
|
title: [],
|
||||||
|
type: ''
|
||||||
})
|
})
|
||||||
.options(Ox.extend(Ox.clone(options), {
|
.options(Ox.extend(Ox.clone(options), {
|
||||||
keyboard: parseKeyboard(options.keyboard || self.defaults.keyboard),
|
keyboard: parseKeyboard(options.keyboard || self.defaults.keyboard),
|
||||||
|
@ -55,7 +55,6 @@ Ox.MenuItem = function(options, self) {
|
||||||
self.options.checked = false;
|
self.options.checked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// construct
|
|
||||||
that.append(
|
that.append(
|
||||||
that.$status = $('<td>')
|
that.$status = $('<td>')
|
||||||
.addClass('OxCell OxStatus')
|
.addClass('OxCell OxStatus')
|
||||||
|
@ -79,13 +78,25 @@ Ox.MenuItem = function(options, self) {
|
||||||
: {}
|
: {}
|
||||||
)
|
)
|
||||||
.html(
|
.html(
|
||||||
|
self.options.file
|
||||||
|
?
|
||||||
|
Ox.FileButton(Ox.extend(Ox.clone(self.options.file), {
|
||||||
|
title: self.options.title[0],
|
||||||
|
width: self.options.file.width
|
||||||
|
})).bindEvent({
|
||||||
|
click: function(data) {
|
||||||
|
self.options.menu.clickItem(self.options.position, data.files);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
: (
|
||||||
Ox.isString(self.options.title[0])
|
Ox.isString(self.options.title[0])
|
||||||
? self.options.title[0]
|
? self.options.title[0]
|
||||||
: $('<div>').html(self.options.title[0]).html()
|
: $('<div>').html(self.options.title[0]).html()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
.append(
|
.append(
|
||||||
$('<td>')
|
that.$modifiers = $('<td>')
|
||||||
.addClass('OxCell OxModifiers')
|
.addClass('OxCell OxModifiers')
|
||||||
.html(
|
.html(
|
||||||
self.options.keyboard.modifiers.map(function(modifier) {
|
self.options.keyboard.modifiers.map(function(modifier) {
|
||||||
|
@ -94,7 +105,7 @@ Ox.MenuItem = function(options, self) {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.append(
|
.append(
|
||||||
$('<td>')
|
that.$key = $('<td>')
|
||||||
.addClass(
|
.addClass(
|
||||||
'OxCell Ox' + (self.options.items.length ? 'Submenu' : 'Key')
|
'OxCell Ox' + (self.options.items.length ? 'Submenu' : 'Key')
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue