2013-05-14 18:10:33 +04:00
|
|
|
/**********************************************************************
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
|
|
//var DEBUG = DEBUG != null ? DEBUG : true
|
|
|
|
|
|
2013-06-01 21:44:49 +04:00
|
|
|
var CURSOR_SHOW_THRESHOLD = 20
|
2013-06-01 21:33:59 +04:00
|
|
|
var CURSOR_HIDE_TIMEOUT = 1000
|
2013-06-01 18:26:06 +04:00
|
|
|
|
2013-06-08 01:48:22 +04:00
|
|
|
var STATUS_QUEUE = []
|
|
|
|
|
var STATUS_QUEUE_TIME = 200
|
|
|
|
|
|
|
|
|
|
|
2013-06-01 18:26:06 +04:00
|
|
|
|
|
|
|
|
|
2012-07-24 14:40:15 +04:00
|
|
|
/*********************************************************************/
|
|
|
|
|
|
2013-06-01 18:26:06 +04:00
|
|
|
// XXX revise...
|
2013-06-01 18:43:14 +04:00
|
|
|
// NOTE: to catch the click event correctly while the cursor is hidden
|
|
|
|
|
// this must be the first to get the event...
|
2013-06-08 20:04:27 +04:00
|
|
|
// NOTE: this uses element.data to store the timer and cursor position...
|
2013-06-01 18:26:06 +04:00
|
|
|
function autoHideCursor(elem){
|
|
|
|
|
elem = $(elem)
|
2013-06-08 20:04:27 +04:00
|
|
|
var data = elem.data()
|
2013-06-01 18:26:06 +04:00
|
|
|
elem
|
|
|
|
|
.on('mousemove', function(evt){
|
2013-06-01 21:33:59 +04:00
|
|
|
var cursor = elem.css('cursor')
|
|
|
|
|
|
2013-06-08 20:04:27 +04:00
|
|
|
data._cursor_pos = data._cursor_pos == null || cursor != 'none' ?
|
2013-06-01 18:26:06 +04:00
|
|
|
[evt.clientX, evt.clientY]
|
2013-06-08 20:04:27 +04:00
|
|
|
: data._cursor_pos
|
2013-06-01 18:26:06 +04:00
|
|
|
|
2013-06-01 21:33:59 +04:00
|
|
|
// cursor visible -- extend visibility...
|
|
|
|
|
if(cursor != 'none'){
|
2013-06-01 18:26:06 +04:00
|
|
|
|
2013-06-08 20:04:27 +04:00
|
|
|
if(data._cursor_timeout != null){
|
|
|
|
|
clearTimeout(data._cursor_timeout)
|
2013-06-01 18:26:06 +04:00
|
|
|
}
|
2013-06-08 20:04:27 +04:00
|
|
|
data._cursor_timeout = setTimeout(function(){
|
|
|
|
|
if(Math.abs(evt.clientX - data._cursor_pos[0]) < CURSOR_SHOW_THRESHOLD
|
|
|
|
|
|| Math.abs(evt.clientY - data._cursor_pos[1]) < CURSOR_SHOW_THRESHOLD){
|
2013-06-01 18:26:06 +04:00
|
|
|
|
2013-06-01 21:33:59 +04:00
|
|
|
elem.css('cursor', 'none')
|
|
|
|
|
}
|
|
|
|
|
}, CURSOR_HIDE_TIMEOUT)
|
2013-06-01 18:26:06 +04:00
|
|
|
|
2013-06-01 21:33:59 +04:00
|
|
|
|
|
|
|
|
// cursor hidden -- if outside the threshold, show...
|
2013-06-08 20:04:27 +04:00
|
|
|
} else if(Math.abs(evt.clientX - data._cursor_pos[0]) > CURSOR_SHOW_THRESHOLD
|
|
|
|
|
|| Math.abs(evt.clientY - data._cursor_pos[1]) > CURSOR_SHOW_THRESHOLD){
|
2013-06-01 21:33:59 +04:00
|
|
|
|
|
|
|
|
elem.css('cursor', '')
|
2013-06-01 18:26:06 +04:00
|
|
|
}
|
|
|
|
|
})
|
2013-06-01 18:43:14 +04:00
|
|
|
.click(function(evt){
|
|
|
|
|
if(elem.css('cursor') == 'none'){
|
|
|
|
|
//event.stopImmediatePropagation()
|
|
|
|
|
//event.preventDefault()
|
|
|
|
|
|
2013-06-08 20:04:27 +04:00
|
|
|
if(data._cursor_timeout != null){
|
|
|
|
|
clearTimeout(data._cursor_timeout)
|
|
|
|
|
data._cursor_timeout = null
|
2013-06-01 18:43:14 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
elem.css('cursor', '')
|
|
|
|
|
//return false
|
|
|
|
|
}
|
|
|
|
|
})
|
2013-06-01 18:26:06 +04:00
|
|
|
return elem
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-06-08 20:04:27 +04:00
|
|
|
/*
|
|
|
|
|
// XXX does not work...
|
|
|
|
|
// ...does not show the cursor without moving it...
|
|
|
|
|
function showCursor(elem){
|
|
|
|
|
elem = $(elem)
|
|
|
|
|
var data = elem.data()
|
|
|
|
|
if(data._cursor_timeout != null){
|
|
|
|
|
clearTimeout(data._cursor_timeout)
|
|
|
|
|
}
|
|
|
|
|
elem.css('cursor', '')
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
2013-06-04 09:29:38 +04:00
|
|
|
function flashIndicator(direction){
|
|
|
|
|
var cls = {
|
2013-06-08 02:29:14 +04:00
|
|
|
// shift up/down...
|
2013-06-04 09:29:38 +04:00
|
|
|
prev: '.up-indicator',
|
|
|
|
|
next: '.down-indicator',
|
2013-06-08 05:46:57 +04:00
|
|
|
// hit start/end/top/bottom of view...
|
2013-06-04 09:29:38 +04:00
|
|
|
start: '.start-indicator',
|
|
|
|
|
end: '.end-indicator',
|
2013-06-08 02:29:14 +04:00
|
|
|
top: '.top-indicator',
|
|
|
|
|
bottom: '.bottom-indicator',
|
2013-06-04 09:29:38 +04:00
|
|
|
}[direction]
|
|
|
|
|
|
|
|
|
|
var indicator = $(cls)
|
|
|
|
|
|
|
|
|
|
if(indicator.length == 0){
|
|
|
|
|
indicator = $('<div>')
|
|
|
|
|
.addClass(cls.replace('.', ''))
|
|
|
|
|
.appendTo($('.viewer'))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return indicator
|
|
|
|
|
// NOTE: this needs to be visible in all cases and key press
|
|
|
|
|
// rhythms...
|
|
|
|
|
.show()
|
|
|
|
|
.delay(100)
|
|
|
|
|
.fadeOut(300)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Update an info element
|
|
|
|
|
//
|
|
|
|
|
// align can be:
|
|
|
|
|
// - top
|
|
|
|
|
// - bottom
|
|
|
|
|
//
|
|
|
|
|
// If target is an existing info container (class: overlay-info) then
|
|
|
|
|
// just fill that.
|
|
|
|
|
function updateInfo(elem, data, target){
|
|
|
|
|
var viewer = $('.viewer')
|
|
|
|
|
target = target == null ? viewer : $(target)
|
|
|
|
|
elem = elem == null ? $('.overlay-info') : $(elem)
|
|
|
|
|
|
|
|
|
|
if(elem.length == 0){
|
|
|
|
|
elem = $('<div/>')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
elem
|
|
|
|
|
.addClass('overlay-info')
|
|
|
|
|
.html('')
|
|
|
|
|
.off()
|
|
|
|
|
|
|
|
|
|
if(typeof(data) == typeof('abc')){
|
|
|
|
|
elem.html(data)
|
|
|
|
|
} else {
|
|
|
|
|
elem.append(data)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return elem
|
|
|
|
|
.appendTo(target)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function showInfo(elem, data, target){
|
|
|
|
|
elem = elem == null ? $('.overlay-info') : elem
|
|
|
|
|
elem = data == null ? elem : updateInfo(elem, data, traget)
|
|
|
|
|
return elem.fadeIn()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function hideInfo(elem){
|
|
|
|
|
elem = elem == null ? $('.overlay-info') : elem
|
|
|
|
|
return elem.fadeOut()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Update status message
|
|
|
|
|
//
|
|
|
|
|
// NOTE: this will update message content and return it as-is, things
|
|
|
|
|
// like showing the message are to be done manually...
|
|
|
|
|
// see: showStatus(...) and showErrorStatus(...) for a higher level
|
|
|
|
|
// API...
|
|
|
|
|
// NOTE: in addition to showing user status, this will also log the
|
|
|
|
|
// satus to browser console...
|
|
|
|
|
// NOTE: the message will be logged to console via either console.log(...)
|
|
|
|
|
// or console.error(...), if the message starts with "Error".
|
|
|
|
|
// NOTE: if message is null, then just return the status element...
|
|
|
|
|
//
|
|
|
|
|
// XXX add abbility to append and clear status...
|
|
|
|
|
function updateStatus(message){
|
|
|
|
|
|
|
|
|
|
var elem = $('.global-status')
|
|
|
|
|
if(elem.length == 0){
|
|
|
|
|
elem = $('<div class="global-status"/>')
|
|
|
|
|
}
|
|
|
|
|
if(message == null){
|
|
|
|
|
return elem
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(typeof(message) == typeof('s') && /^error.*/i.test(message)){
|
|
|
|
|
console.error.apply(console, arguments)
|
|
|
|
|
} else {
|
|
|
|
|
console.log.apply(console, arguments)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(arguments.length > 1){
|
|
|
|
|
message = Array.apply(Array, arguments).join(' ')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return updateInfo(elem, message)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Same as updateInfo(...) but will aslo show and animate-close the message
|
2013-06-04 16:32:33 +04:00
|
|
|
//
|
|
|
|
|
// XXX the next call will not reset the animation of the previous, rather
|
|
|
|
|
// it will pause it and rezume...
|
|
|
|
|
// ...not sure if this is correct.
|
2013-06-04 09:29:38 +04:00
|
|
|
function showStatus(message){
|
|
|
|
|
return updateStatus.apply(null, arguments)
|
2013-06-04 16:32:33 +04:00
|
|
|
//.stop()
|
|
|
|
|
.stop(true, false)
|
|
|
|
|
//.finish()
|
2013-06-04 09:29:38 +04:00
|
|
|
.show()
|
|
|
|
|
.delay(500)
|
|
|
|
|
.fadeOut(800)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-06-08 01:48:22 +04:00
|
|
|
// Same as showStatus(...) but queue the message so as to display it for
|
|
|
|
|
// a meaningful amount of time...
|
|
|
|
|
//
|
|
|
|
|
// - This will print the first message right away.
|
|
|
|
|
// - Each consecutive message if STATUS_QUEUE_TIME has not passed yet
|
|
|
|
|
// will get queued.
|
|
|
|
|
// - Once the STATUS_QUEUE_TIME has passed the next message is reported
|
|
|
|
|
// and so on until the queue is empty.
|
|
|
|
|
//
|
|
|
|
|
// NOTE: for very a fast and large sequence of messages the reporting
|
|
|
|
|
// may (will) take longer (significantly) than the actual "job"...
|
|
|
|
|
// NOTE: this will delay the logging also...
|
|
|
|
|
function showStatusQ(message){
|
|
|
|
|
if(STATUS_QUEUE.length == 0){
|
|
|
|
|
|
|
|
|
|
// end marker...
|
|
|
|
|
STATUS_QUEUE.push(0)
|
|
|
|
|
|
|
|
|
|
showStatus.apply(null, arguments)
|
|
|
|
|
|
|
|
|
|
function _printer(){
|
|
|
|
|
// if queue is empty we have nothing to do...
|
|
|
|
|
if(STATUS_QUEUE.length == 1){
|
|
|
|
|
STATUS_QUEUE.pop()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
// if not empty show a status and repeat...
|
|
|
|
|
showStatus.apply(null, STATUS_QUEUE.pop())
|
|
|
|
|
setTimeout(_printer, STATUS_QUEUE_TIME)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setTimeout(_printer, STATUS_QUEUE_TIME)
|
|
|
|
|
|
|
|
|
|
// queue not empty...
|
|
|
|
|
} else {
|
|
|
|
|
STATUS_QUEUE.splice(1, 0, Array.apply(Array, arguments))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-06-04 09:29:38 +04:00
|
|
|
// Same as showStatus(...) but will always add 'Error: ' to the start
|
|
|
|
|
// of the message
|
|
|
|
|
//
|
|
|
|
|
// NOTE: this will show the message but will not hide it.
|
|
|
|
|
function showErrorStatus(message){
|
|
|
|
|
message = Array.apply(Array, arguments)
|
|
|
|
|
message.splice(0, 0, 'Error:')
|
|
|
|
|
return updateStatus.apply(null, message)
|
|
|
|
|
.one('click', function(){ $(this).fadeOut() })
|
2013-06-04 16:32:33 +04:00
|
|
|
//.stop()
|
|
|
|
|
.stop(true, false)
|
|
|
|
|
//.finish()
|
2013-06-04 09:29:38 +04:00
|
|
|
.show()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// shorthand methods...
|
|
|
|
|
function hideStatus(){
|
|
|
|
|
// yes, this indeed looks funny -- to hide a status you need to show
|
|
|
|
|
// it without any arguments... ;)
|
|
|
|
|
return showStatus()
|
|
|
|
|
}
|
|
|
|
|
function getStatus(){
|
|
|
|
|
return updateStatus()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// XXX move to ui.js?
|
|
|
|
|
function makeIndicator(text){
|
2013-06-08 02:29:14 +04:00
|
|
|
return $('<span class="indicator expanding-text">'+
|
2013-06-04 09:29:38 +04:00
|
|
|
'<span class="hidden">'+ text +'</span>'+
|
|
|
|
|
'<span class="shown">'+ text[0] +'</span>'+
|
|
|
|
|
'</span>')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function showGlobalIndicator(cls, text){
|
|
|
|
|
var c = $('.global-mode-indicators')
|
|
|
|
|
if(c.length == 0){
|
|
|
|
|
c = $('<div>')
|
|
|
|
|
.addClass('global-mode-indicators')
|
2013-06-08 02:29:14 +04:00
|
|
|
.append('<span class="mode-tip">Global status</span>')
|
2013-06-04 09:29:38 +04:00
|
|
|
.appendTo($('.viewer'))
|
|
|
|
|
}
|
|
|
|
|
return makeIndicator(text)
|
|
|
|
|
.addClass(cls)
|
|
|
|
|
.appendTo(c)
|
|
|
|
|
}
|
|
|
|
|
function showContextIndicator(cls, text){
|
|
|
|
|
var c = $('.context-mode-indicators')
|
|
|
|
|
if(c.length == 0){
|
|
|
|
|
c = $('<div>')
|
|
|
|
|
.addClass('context-mode-indicators')
|
2013-06-08 02:29:14 +04:00
|
|
|
.append('<span class="mode-tip">Context status</span>')
|
2013-06-04 09:29:38 +04:00
|
|
|
.appendTo($('.viewer'))
|
|
|
|
|
}
|
|
|
|
|
return makeIndicator(text)
|
|
|
|
|
.addClass(cls)
|
|
|
|
|
.appendTo(c)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-06-10 19:20:35 +04:00
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
|
* Modal dialogs...
|
|
|
|
|
*/
|
|
|
|
|
|
2013-06-10 17:28:32 +04:00
|
|
|
function getOverlay(root){
|
|
|
|
|
root = $(root)
|
|
|
|
|
var overlay = root.find('.overlay-block')
|
|
|
|
|
if(overlay.length == 0){
|
|
|
|
|
return $('<div class="overlay-block">'+
|
|
|
|
|
'<div class="background"/>'+
|
|
|
|
|
'<div class="content"/>'+
|
|
|
|
|
'</div>').appendTo(root)
|
|
|
|
|
}
|
|
|
|
|
return overlay
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function showInOverlay(root, data){
|
|
|
|
|
root = $(root)
|
|
|
|
|
|
|
|
|
|
var overlay = getOverlay(root)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(data != null){
|
|
|
|
|
var container = $('<table width="100%" height="100%"><tr><td align="center" valign="center">'+
|
|
|
|
|
'<div class="dialog"/>'+
|
|
|
|
|
'</td></tr></table>')
|
|
|
|
|
var dialog = container.find('.dialog')
|
|
|
|
|
|
|
|
|
|
//overlay.find('.background')
|
|
|
|
|
// .click(function(){ hideOverlay(root) })
|
|
|
|
|
|
|
|
|
|
dialog
|
|
|
|
|
.append(data)
|
2013-06-11 03:10:01 +04:00
|
|
|
.on('click', function(){
|
2013-06-10 19:20:35 +04:00
|
|
|
event.stopPropagation()
|
|
|
|
|
})
|
2013-06-10 17:28:32 +04:00
|
|
|
overlay.find('.content')
|
2013-06-10 19:20:35 +04:00
|
|
|
.on('click', function(){
|
|
|
|
|
overlay.trigger('close')
|
|
|
|
|
hideOverlay(root)
|
|
|
|
|
})
|
2013-06-11 03:10:01 +04:00
|
|
|
.on('close accept', function(){
|
|
|
|
|
//hideOverlay(root)
|
|
|
|
|
})
|
2013-06-10 17:28:32 +04:00
|
|
|
.append(container)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
root.addClass('overlay')
|
|
|
|
|
|
|
|
|
|
return overlay
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function hideOverlay(root){
|
|
|
|
|
root.removeClass('overlay')
|
2013-06-10 19:20:35 +04:00
|
|
|
root.find('.overlay-block')
|
|
|
|
|
.trigger('close')
|
|
|
|
|
.remove()
|
2013-06-10 17:28:32 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-06-12 14:45:48 +04:00
|
|
|
var FIELD_TYPES = {
|
2013-07-04 19:00:38 +04:00
|
|
|
// format:
|
|
|
|
|
// string
|
2013-07-07 03:19:41 +04:00
|
|
|
// XXX add datalist option...
|
2013-06-12 14:45:48 +04:00
|
|
|
text: {
|
|
|
|
|
type: 'text',
|
|
|
|
|
text: null,
|
|
|
|
|
default: '',
|
2013-06-13 02:02:24 +04:00
|
|
|
html: '<div class="field string">'+
|
2013-06-12 14:45:48 +04:00
|
|
|
'<span class="text"></span>'+
|
|
|
|
|
'<input type="text" class="value">'+
|
|
|
|
|
'</div>',
|
2013-06-12 16:11:19 +04:00
|
|
|
test: function(val){
|
|
|
|
|
return typeof(val) == typeof('abc')
|
|
|
|
|
},
|
2013-06-12 17:25:13 +04:00
|
|
|
set: function(field, value){
|
|
|
|
|
$(field).find('.value').attr('value', value)
|
2013-06-12 14:45:48 +04:00
|
|
|
},
|
2013-06-12 16:11:19 +04:00
|
|
|
get: function(field){
|
2013-06-12 14:45:48 +04:00
|
|
|
return $(field).find('.value').attr('value')
|
|
|
|
|
},
|
|
|
|
|
},
|
2013-07-04 19:00:38 +04:00
|
|
|
|
|
|
|
|
// format:
|
|
|
|
|
// true | false
|
2013-06-12 14:45:48 +04:00
|
|
|
bool: {
|
2013-06-12 16:11:19 +04:00
|
|
|
type: 'bool',
|
2013-06-12 14:45:48 +04:00
|
|
|
text: null,
|
|
|
|
|
default: false,
|
2013-06-13 02:02:24 +04:00
|
|
|
html: '<div class="field checkbox">'+
|
2013-06-22 19:30:56 +04:00
|
|
|
'<label><input type="checkbox" class="value">'+
|
|
|
|
|
'<span class="text"></span></label>'+
|
2013-06-12 14:45:48 +04:00
|
|
|
'</div>',
|
2013-06-12 16:11:19 +04:00
|
|
|
test: function(val){
|
|
|
|
|
return val === true || val === false
|
|
|
|
|
},
|
|
|
|
|
set: function(field, value){
|
|
|
|
|
if(value){
|
2013-06-12 14:45:48 +04:00
|
|
|
$(field).find('.value').attr('checked', '')
|
|
|
|
|
} else {
|
|
|
|
|
$(field).find('.value').removeAttr('checked')
|
|
|
|
|
}
|
|
|
|
|
},
|
2013-06-12 16:11:19 +04:00
|
|
|
get: function(field){
|
2013-06-12 17:25:13 +04:00
|
|
|
return $(field).find('.value').attr('checked') == 'checked'
|
2013-06-12 14:45:48 +04:00
|
|
|
},
|
|
|
|
|
},
|
2013-06-13 17:25:38 +04:00
|
|
|
|
2013-06-13 19:42:42 +04:00
|
|
|
// NOTE: this will not work without node-webkit...
|
2013-07-04 19:00:38 +04:00
|
|
|
// format:
|
|
|
|
|
// { dir: <default-path> }
|
2013-06-13 17:25:38 +04:00
|
|
|
dir: {
|
|
|
|
|
type: 'dir',
|
|
|
|
|
text: null,
|
|
|
|
|
default: false,
|
|
|
|
|
html: '<div class="field checkbox">'+
|
|
|
|
|
'<span class="text"></span>'+
|
|
|
|
|
'<input type="file" class="value" nwdirectory />'+
|
|
|
|
|
'</div>',
|
|
|
|
|
test: function(val){
|
|
|
|
|
return typeof(val) == typeof({}) && 'dir' in val
|
|
|
|
|
},
|
|
|
|
|
set: function(field, value){
|
|
|
|
|
field.find('.value').attr('nwworkingdir', value.dir)
|
|
|
|
|
},
|
|
|
|
|
get: function(field){
|
|
|
|
|
var f = $(field).find('.value')[0].files
|
|
|
|
|
if(f.length == 0){
|
|
|
|
|
return ''
|
|
|
|
|
}
|
|
|
|
|
return f[0].path
|
|
|
|
|
},
|
|
|
|
|
},
|
2013-07-04 19:00:38 +04:00
|
|
|
|
2013-06-13 19:42:42 +04:00
|
|
|
// NOTE: this will not work without node-webkit...
|
2013-07-04 19:00:38 +04:00
|
|
|
// format:
|
|
|
|
|
// { dir: <default-path> }
|
2013-07-07 03:19:41 +04:00
|
|
|
// XXX add datalist option...
|
2013-06-13 17:25:38 +04:00
|
|
|
ndir: {
|
|
|
|
|
type: 'ndir',
|
|
|
|
|
text: null,
|
|
|
|
|
default: false,
|
|
|
|
|
html: '<div class="field dir">'+
|
|
|
|
|
'<span class="text"></span>'+
|
|
|
|
|
'<input type="text" class="path"/>'+
|
|
|
|
|
'<button class="browse">Browse</button>'+
|
|
|
|
|
'</div>',
|
|
|
|
|
test: function(val){
|
|
|
|
|
return typeof(val) == typeof({}) && 'ndir' in val
|
|
|
|
|
},
|
|
|
|
|
set: function(field, value){
|
|
|
|
|
var that = this
|
|
|
|
|
|
|
|
|
|
// NOTE: we are attaching the file browser to body to avoid
|
|
|
|
|
// click events on it closing the dialog...
|
|
|
|
|
// ...for some reason stopPropagation(...) does not do
|
|
|
|
|
// the job...
|
|
|
|
|
var file = $('<input type="file" class="value" nwdirectory/>')
|
|
|
|
|
.attr('nwworkingdir', value.ndir)
|
|
|
|
|
.change(function(){
|
|
|
|
|
var p = file[0].files
|
|
|
|
|
if(p.length != 0){
|
|
|
|
|
field.find('.path').val(p[0].path)
|
|
|
|
|
}
|
|
|
|
|
file.detach()
|
2013-08-02 01:25:28 +04:00
|
|
|
// focus+select the path field...
|
2013-08-01 03:19:42 +04:00
|
|
|
// NOTE: this is here to enable fast select-open
|
|
|
|
|
// keyboard cycle (tab, enter, <select path>,
|
|
|
|
|
// enter, enter)...
|
2013-08-01 03:16:41 +04:00
|
|
|
field.find('.path')
|
|
|
|
|
.focus()
|
|
|
|
|
.select()
|
2013-06-13 17:25:38 +04:00
|
|
|
})
|
|
|
|
|
.hide()
|
|
|
|
|
field.find('.path').val(value.ndir)
|
|
|
|
|
|
|
|
|
|
field.find('.browse').click(function(){
|
|
|
|
|
file
|
2013-06-15 03:04:06 +04:00
|
|
|
// load user input path...
|
|
|
|
|
.attr('nwworkingdir', field.find('.path').val())
|
2013-06-13 17:25:38 +04:00
|
|
|
.appendTo($('body'))
|
|
|
|
|
.click()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
get: function(field){
|
|
|
|
|
return field.find('.path').val()
|
|
|
|
|
},
|
|
|
|
|
},
|
2013-06-22 17:54:15 +04:00
|
|
|
|
2013-07-04 19:00:38 +04:00
|
|
|
// format:
|
|
|
|
|
// ['a', 'b', 'c', ...]
|
2013-06-22 17:54:15 +04:00
|
|
|
choice: {
|
|
|
|
|
type: 'choice',
|
|
|
|
|
text: null,
|
|
|
|
|
default: false,
|
|
|
|
|
html: '<div class="field choice">'+
|
|
|
|
|
'<span class="text"></span>'+
|
2013-06-22 19:30:56 +04:00
|
|
|
'<div class="item"><label>'+
|
2013-06-22 17:54:15 +04:00
|
|
|
'<input type="radio" class="value"/>'+
|
|
|
|
|
'<span class="item-text"></span>'+
|
2013-06-22 19:30:56 +04:00
|
|
|
'</label></div>'+
|
2013-06-22 17:54:15 +04:00
|
|
|
'</div>',
|
|
|
|
|
test: function(val){
|
|
|
|
|
return typeof(val) == typeof([]) && val.constructor.name == 'Array'
|
|
|
|
|
},
|
|
|
|
|
set: function(field, value){
|
|
|
|
|
var t = field.find('.text').text()
|
2013-06-22 19:30:56 +04:00
|
|
|
t = t == '' ? Math.random()+'' : t
|
2013-06-22 17:54:15 +04:00
|
|
|
var item = field.find('.item').last()
|
|
|
|
|
for(var i=0; i < value.length; i++){
|
|
|
|
|
item.find('.value')
|
|
|
|
|
.val(value[i])
|
|
|
|
|
item.find('.item-text')
|
|
|
|
|
.text(value[i])
|
|
|
|
|
item.appendTo(field)
|
|
|
|
|
|
|
|
|
|
item = item.clone()
|
|
|
|
|
}
|
|
|
|
|
field.find('.value')
|
|
|
|
|
.attr('name', t)
|
|
|
|
|
.first()
|
|
|
|
|
.attr('checked', '')
|
|
|
|
|
},
|
|
|
|
|
get: function(field){
|
|
|
|
|
return $(field).find('.value:checked').val()
|
|
|
|
|
},
|
|
|
|
|
},
|
2013-07-04 19:00:38 +04:00
|
|
|
|
2013-07-08 07:07:26 +04:00
|
|
|
// format:
|
|
|
|
|
// {
|
|
|
|
|
// select: ['a', 'b', 'c', ...]
|
|
|
|
|
// // default option (optional)...
|
|
|
|
|
// default: <number> | <text>
|
|
|
|
|
// }
|
|
|
|
|
select: {
|
|
|
|
|
type: 'select',
|
|
|
|
|
text: null,
|
|
|
|
|
default: false,
|
|
|
|
|
html: '<div class="field choice">'+
|
|
|
|
|
'<span class="text"></span>'+
|
|
|
|
|
'<select>'+
|
|
|
|
|
'<option class="option"></option>'+
|
|
|
|
|
'</select>'+
|
|
|
|
|
'</div>',
|
|
|
|
|
test: function(val){
|
|
|
|
|
return 'select' in val
|
|
|
|
|
},
|
|
|
|
|
set: function(field, value){
|
|
|
|
|
var t = field.find('.text').text()
|
|
|
|
|
var item = field.find('.option').last()
|
|
|
|
|
var select = field.find('select')
|
|
|
|
|
for(var i=0; i < value.select.length; i++){
|
|
|
|
|
item
|
|
|
|
|
.text(value.select[i])
|
|
|
|
|
.val(value.select[i])
|
|
|
|
|
item.appendTo(select)
|
|
|
|
|
|
|
|
|
|
item = item.clone()
|
|
|
|
|
}
|
|
|
|
|
if(value.default != null){
|
|
|
|
|
if(typeof(value.default) == typeof(123)){
|
|
|
|
|
field.find('.option')
|
|
|
|
|
.eq(value.default)
|
|
|
|
|
.attr('selected', '')
|
|
|
|
|
} else {
|
|
|
|
|
field.find('.option[value="'+ value.default +'"]')
|
|
|
|
|
.attr('selected', '')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
get: function(field){
|
|
|
|
|
return $(field).find('.option:selected').val()
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
|
2013-07-04 19:00:38 +04:00
|
|
|
// NOTE: a button can have state...
|
|
|
|
|
// format:
|
|
|
|
|
// {
|
|
|
|
|
// // click event handler...
|
|
|
|
|
// button: <function>,
|
|
|
|
|
// // optional, button text (default 'OK')...
|
|
|
|
|
// text: <button-label>,
|
|
|
|
|
// // optional, initial state setup...
|
|
|
|
|
// default: <function>,
|
|
|
|
|
// }
|
|
|
|
|
button: {
|
|
|
|
|
type: 'button',
|
|
|
|
|
text: null,
|
|
|
|
|
default: false,
|
|
|
|
|
html: '<div class="field button">'+
|
|
|
|
|
'<span class="text"></span>'+
|
|
|
|
|
'<button class="button"></button>'+
|
|
|
|
|
'</div>',
|
|
|
|
|
test: function(val){
|
|
|
|
|
return 'button' in val
|
|
|
|
|
},
|
|
|
|
|
set: function(field, value){
|
|
|
|
|
var btn = $(field).find('button')
|
|
|
|
|
.click(value.button)
|
|
|
|
|
.html(value.text == null ? 'OK' : value.text)
|
|
|
|
|
if('default' in value){
|
|
|
|
|
value.default(btn)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
get: function(field){
|
|
|
|
|
return $(field).attr('state')
|
|
|
|
|
},
|
|
|
|
|
},
|
2013-06-12 14:45:48 +04:00
|
|
|
}
|
|
|
|
|
|
2013-06-13 19:42:42 +04:00
|
|
|
// Show a complex form dialog
|
|
|
|
|
//
|
|
|
|
|
// This will build a form and collect it's data on "accept" specified by
|
|
|
|
|
// the config object...
|
2013-06-12 14:45:48 +04:00
|
|
|
//
|
|
|
|
|
// config format:
|
|
|
|
|
// {
|
|
|
|
|
// // simple field...
|
|
|
|
|
// <field-description>: <default-value>,
|
|
|
|
|
//
|
|
|
|
|
// ...
|
|
|
|
|
// }
|
|
|
|
|
//
|
2013-07-01 17:16:12 +04:00
|
|
|
// <field-description> and split in two with a "|" the section before will
|
|
|
|
|
// show as the field text and the text after as the tooltip.
|
|
|
|
|
// Example:
|
|
|
|
|
// "field text | field tooltip..."
|
|
|
|
|
//
|
2013-06-12 14:45:48 +04:00
|
|
|
// field's default value determines it's type:
|
|
|
|
|
// bool - checkbox
|
|
|
|
|
// string - textarea
|
2013-06-13 19:42:42 +04:00
|
|
|
//
|
|
|
|
|
// see FIELD_TYPES for supported field types.
|
2013-06-12 14:45:48 +04:00
|
|
|
//
|
2013-06-20 02:41:29 +04:00
|
|
|
// NOTE: if btn is set to false explicitly then no button will be
|
|
|
|
|
// rendered in the form dialog.
|
2013-07-01 17:16:12 +04:00
|
|
|
// NOTE: to include a literal "|" in <field-description> just escape it
|
|
|
|
|
// like this: "\|"
|
2013-06-20 02:41:29 +04:00
|
|
|
//
|
2013-06-12 17:25:13 +04:00
|
|
|
// XXX add form testing...
|
|
|
|
|
// XXX add undefined field handling/reporting...
|
2013-06-13 01:37:30 +04:00
|
|
|
// XXX revise...
|
|
|
|
|
function formDialog(root, message, config, btn, cls){
|
2013-06-12 17:25:13 +04:00
|
|
|
cls = cls == null ? '' : cls
|
2013-06-13 17:25:38 +04:00
|
|
|
btn = btn == null ? 'OK' : btn
|
2013-06-13 01:37:30 +04:00
|
|
|
root = root == null ? $('.viewer') : root
|
|
|
|
|
|
2013-06-12 16:11:19 +04:00
|
|
|
var form = $('<div class="form"/>')
|
|
|
|
|
var data = {}
|
|
|
|
|
var res = $.Deferred()
|
|
|
|
|
|
2013-06-12 17:25:13 +04:00
|
|
|
// handle message and btn...
|
|
|
|
|
form.append($('<div class="text">'+message+'</div>'))
|
2013-06-12 16:11:19 +04:00
|
|
|
|
|
|
|
|
// build the form...
|
|
|
|
|
for(var t in config){
|
|
|
|
|
var did_handling = false
|
|
|
|
|
for(var f in FIELD_TYPES){
|
|
|
|
|
if(FIELD_TYPES[f].test(config[t])){
|
|
|
|
|
var field = FIELD_TYPES[f]
|
|
|
|
|
var html = $(field.html)
|
|
|
|
|
|
2013-07-01 17:16:12 +04:00
|
|
|
// get the tooltip...
|
|
|
|
|
if(/[^\\]\|/.test(t)){
|
2013-07-03 20:18:00 +04:00
|
|
|
// XXX do we need to cut the spaces off here???
|
2013-07-01 17:16:12 +04:00
|
|
|
var tip = t.split(/\s*\|\s*/)
|
|
|
|
|
text = tip[0]
|
|
|
|
|
tip = tip[1]
|
|
|
|
|
$('<span class="tooltip-icon tooltip-right">?</span>')
|
|
|
|
|
.attr('tooltip', tip)
|
|
|
|
|
.appendTo(html)
|
|
|
|
|
// cleanup...
|
|
|
|
|
} else {
|
|
|
|
|
text = t.replace(/\\\|/g, '|')
|
|
|
|
|
}
|
|
|
|
|
// setup text and data...
|
|
|
|
|
html.find('.text').text(text)
|
2013-06-12 16:11:19 +04:00
|
|
|
field.set(html, config[t])
|
|
|
|
|
|
2013-06-12 17:25:13 +04:00
|
|
|
// NOTE: this is here to isolate t and field.get values...
|
|
|
|
|
// ...is there a better way???
|
|
|
|
|
var _ = (function(title, getter){
|
|
|
|
|
html.on('resolve', function(evt, e){
|
|
|
|
|
data[title] = getter(e)
|
|
|
|
|
})
|
|
|
|
|
})(t, field.get)
|
2013-06-12 16:11:19 +04:00
|
|
|
|
|
|
|
|
form.append(html)
|
|
|
|
|
|
|
|
|
|
did_handling = true
|
2013-06-12 17:25:13 +04:00
|
|
|
break
|
2013-06-12 16:11:19 +04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// handle unresolved fields...
|
|
|
|
|
if(!did_handling){
|
2013-06-13 01:37:30 +04:00
|
|
|
console.warn('formDialog: not all fields understood.')
|
2013-06-12 16:11:19 +04:00
|
|
|
// XXX skipping field...
|
|
|
|
|
// XXX
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-12 17:25:13 +04:00
|
|
|
// add button...
|
2013-06-20 02:41:29 +04:00
|
|
|
if(btn !== false){
|
|
|
|
|
var button = $('<button class="accept">'+btn+'</button>')
|
|
|
|
|
form.append(button)
|
|
|
|
|
}
|
2013-06-12 17:25:13 +04:00
|
|
|
|
|
|
|
|
var overlay = showInOverlay(root, form)
|
|
|
|
|
.addClass('dialog ' + cls)
|
2013-06-12 16:11:19 +04:00
|
|
|
.on('accept', function(){
|
|
|
|
|
form.find('.field').each(function(_, e){
|
2013-06-12 17:25:13 +04:00
|
|
|
$(e).trigger('resolve', [$(e)])
|
2013-06-12 16:11:19 +04:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// XXX test if all required stuff is filled...
|
|
|
|
|
res.resolve(data)
|
|
|
|
|
|
|
|
|
|
hideOverlay(root)
|
|
|
|
|
})
|
|
|
|
|
.on('close', function(){
|
|
|
|
|
res.reject()
|
2013-06-12 17:25:13 +04:00
|
|
|
|
2013-06-12 16:11:19 +04:00
|
|
|
})
|
|
|
|
|
|
2013-06-12 17:25:13 +04:00
|
|
|
button.click(function(){
|
|
|
|
|
overlay.trigger('accept')
|
|
|
|
|
})
|
|
|
|
|
|
2013-06-13 01:37:30 +04:00
|
|
|
setTimeout(function(){
|
2013-06-13 02:02:24 +04:00
|
|
|
form.find('.field input').first()
|
2013-06-13 01:37:30 +04:00
|
|
|
.focus()
|
|
|
|
|
.select()
|
|
|
|
|
}, 100)
|
|
|
|
|
|
|
|
|
|
return res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-06-13 19:42:42 +04:00
|
|
|
|
2013-06-13 01:37:30 +04:00
|
|
|
/************************************************ Standard dialogs ***/
|
2013-07-03 20:18:00 +04:00
|
|
|
// NOTE: these return a deferred that will reflect the state of the
|
|
|
|
|
// dialog, and the progress of the operations that it riggers...
|
|
|
|
|
//
|
|
|
|
|
// XXX might be a good idea to be able to block the ui (overlay + progress
|
|
|
|
|
// bar?) until some long/critical operations finish, to prevent the
|
|
|
|
|
// user from breaking things while the ui is inconsistent...
|
2013-06-13 01:37:30 +04:00
|
|
|
|
|
|
|
|
var _alert = alert
|
|
|
|
|
function alert(){
|
|
|
|
|
var message = Array.apply(null, arguments).join(' ')
|
2013-06-20 02:41:29 +04:00
|
|
|
//return formDialog(null, String(message), {}, 'OK', 'alert')
|
|
|
|
|
return formDialog(null, String(message), {}, false, 'alert')
|
2013-06-13 01:37:30 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var _prompt = prompt
|
|
|
|
|
function prompt(message, dfl, btn){
|
|
|
|
|
btn = btn == null ? 'OK' : btn
|
|
|
|
|
var res = $.Deferred()
|
2013-06-13 17:25:38 +04:00
|
|
|
formDialog(null, message, {'': ''+(dfl == null ? '' : dfl)}, btn, 'prompt')
|
2013-06-13 01:37:30 +04:00
|
|
|
.done(function(data){ res.resolve(data['']) })
|
|
|
|
|
.fail(function(){ res.reject() })
|
2013-06-12 16:11:19 +04:00
|
|
|
return res
|
2013-06-12 14:45:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-06-13 01:37:30 +04:00
|
|
|
/*
|
|
|
|
|
function confirm(){
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
2013-06-13 19:42:42 +04:00
|
|
|
// NOTE: this will not work without node-webkit...
|
2013-06-13 17:25:38 +04:00
|
|
|
function getDir(message, dfl, btn){
|
|
|
|
|
btn = btn == null ? 'OK' : btn
|
|
|
|
|
dfl = dfl == null ? '' : dfl
|
|
|
|
|
var res = $.Deferred()
|
|
|
|
|
|
|
|
|
|
formDialog(null, message, {'': {ndir: dfl}}, btn, 'getDir')
|
|
|
|
|
.done(function(data){ res.resolve(data['']) })
|
|
|
|
|
.fail(function(){ res.reject() })
|
|
|
|
|
|
|
|
|
|
return res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-06-22 17:54:15 +04:00
|
|
|
|
|
|
|
|
/***************************************** Domain-specific dialogs ***/
|
|
|
|
|
|
2013-06-21 17:47:44 +04:00
|
|
|
// XXX do reporting...
|
2013-07-07 02:20:22 +04:00
|
|
|
// XXX would be nice to save settings...
|
2013-07-07 03:19:41 +04:00
|
|
|
// ...might be good to use datalist...
|
2013-06-27 17:29:53 +04:00
|
|
|
function exportPreviewsDialog(state, dfl){
|
2013-06-21 17:47:44 +04:00
|
|
|
dfl = dfl == null ? BASE_URL : dfl
|
2013-06-27 17:29:53 +04:00
|
|
|
|
|
|
|
|
// XXX make this more generic...
|
2013-07-03 07:03:46 +04:00
|
|
|
// tell the user what state are we exporting...
|
2013-06-27 17:29:53 +04:00
|
|
|
if(state == null){
|
|
|
|
|
state = toggleMarkedOnlyView('?') == 'on' ? 'marked images' : state
|
|
|
|
|
state = toggleSingleRibbonMode('?') == 'on' ? 'current ribbon' : state
|
|
|
|
|
state = state == null ? 'all images' : state
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-21 17:47:44 +04:00
|
|
|
var res = $.Deferred()
|
|
|
|
|
|
2013-06-21 20:02:54 +04:00
|
|
|
updateStatus('Export...').show()
|
|
|
|
|
|
2013-07-01 18:05:50 +04:00
|
|
|
// NOTE: we are not defining the object in-place here because some
|
|
|
|
|
// keys become unreadable with JS syntax preventing us from
|
|
|
|
|
// splitting the key into several lines...
|
|
|
|
|
var cfg = {}
|
|
|
|
|
cfg['Image name pattern | '+
|
|
|
|
|
'%f - full filename\n'+
|
|
|
|
|
'%n - filename\n'+
|
2013-07-07 02:20:22 +04:00
|
|
|
'%e - extension (with leading dot)\n'+
|
|
|
|
|
'%(abc)m - if marked insert "abc"\n'+
|
2013-07-01 18:05:50 +04:00
|
|
|
'%gid - log gid\n'+
|
|
|
|
|
'%g - short gid\n'+
|
2013-07-01 18:25:33 +04:00
|
|
|
'%I - global order\n'+
|
|
|
|
|
'%i - current selection order'] = '%f'
|
2013-07-01 18:05:50 +04:00
|
|
|
cfg['Fav directory name'] = 'fav'
|
2013-07-08 07:07:26 +04:00
|
|
|
cfg['Size | '+
|
|
|
|
|
'The selected size is aproximate, the actual\n'+
|
2013-07-08 07:18:43 +04:00
|
|
|
'preview will be copied from cache.\n\n'+
|
|
|
|
|
'NOTE: if not all previews are yet generated,\n'+
|
|
|
|
|
'this will save the available previews, not all\n'+
|
|
|
|
|
'of which may be of the right size, if this\n'+
|
|
|
|
|
'happens wait till all the previews are done\n'+
|
|
|
|
|
'and export again.'] = {
|
2013-07-08 07:07:26 +04:00
|
|
|
select: ['Original image'].concat(PREVIEW_SIZES.slice().sort()),
|
|
|
|
|
default: 1
|
|
|
|
|
}
|
2013-07-08 07:37:57 +04:00
|
|
|
cfg['Destination | '+
|
|
|
|
|
'Relative paths are supported.\n\n'+
|
|
|
|
|
'NOTE: All paths are relative to the curent\n'+
|
|
|
|
|
'directory.'] = {ndir: dfl}
|
2013-07-01 18:05:50 +04:00
|
|
|
|
|
|
|
|
var keys = Object.keys(cfg)
|
|
|
|
|
|
2013-07-03 07:03:46 +04:00
|
|
|
formDialog(null, '<b>Export:</b> '+ state +'.', cfg, 'OK', 'exportPreviewsDialog')
|
2013-06-21 17:47:44 +04:00
|
|
|
.done(function(data){
|
2013-07-08 07:07:26 +04:00
|
|
|
var s = data[keys[2]]
|
|
|
|
|
s = s == 'Original image' ? Math.max.apply(null, PREVIEW_SIZES)*2 : parseInt(s)-5
|
2013-06-21 19:10:12 +04:00
|
|
|
exportTo(
|
2013-07-08 07:07:26 +04:00
|
|
|
normalizePath(data[keys[3]]),
|
2013-07-01 18:05:50 +04:00
|
|
|
data[keys[0]],
|
2013-07-08 07:07:26 +04:00
|
|
|
data[keys[1]],
|
|
|
|
|
s)
|
2013-06-21 20:02:54 +04:00
|
|
|
// XXX do real reporting...
|
|
|
|
|
showStatusQ('Copying data...')
|
2013-06-21 17:47:44 +04:00
|
|
|
res.resolve(data[''])
|
|
|
|
|
})
|
2013-06-21 20:02:54 +04:00
|
|
|
.fail(function(){
|
|
|
|
|
showStatusQ('Export: canceled.')
|
|
|
|
|
res.reject()
|
|
|
|
|
})
|
2013-06-21 17:47:44 +04:00
|
|
|
|
|
|
|
|
return res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-06-22 17:54:15 +04:00
|
|
|
function loadDirectoryDialog(dfl){
|
2013-06-21 20:02:54 +04:00
|
|
|
dfl = dfl == null ? BASE_URL : dfl
|
|
|
|
|
|
|
|
|
|
updateStatus('Open...').show()
|
|
|
|
|
|
2013-07-03 06:42:14 +04:00
|
|
|
formDialog(null, 'Path to open', {
|
|
|
|
|
'': {ndir: dfl},
|
2013-07-05 05:33:54 +04:00
|
|
|
'Precess previews': true,
|
2013-07-03 06:58:28 +04:00
|
|
|
}, 'OK', 'loadDirectoryDialog')
|
2013-07-03 06:42:14 +04:00
|
|
|
.done(function(data){
|
2013-07-03 06:58:28 +04:00
|
|
|
var path = normalizePath(data[''].trim())
|
2013-07-03 06:42:14 +04:00
|
|
|
var process_previews = data['Precess previews']
|
2013-07-03 06:58:28 +04:00
|
|
|
|
2013-06-21 22:57:16 +04:00
|
|
|
// reset the modes...
|
|
|
|
|
toggleSingleImageMode('off')
|
|
|
|
|
toggleSingleRibbonMode('off')
|
2013-06-23 03:14:04 +04:00
|
|
|
toggleMarkedOnlyView('off')
|
2013-06-21 22:57:16 +04:00
|
|
|
|
2013-07-03 06:58:28 +04:00
|
|
|
// do the loading...
|
2013-07-08 04:11:04 +04:00
|
|
|
statusNotify(loadDir(path, !process_previews))
|
|
|
|
|
/*
|
2013-07-03 06:42:14 +04:00
|
|
|
.done(function(){
|
2013-07-05 05:33:54 +04:00
|
|
|
if(process_previews){
|
2013-07-03 06:42:14 +04:00
|
|
|
showStatusQ('Previews: processing started...')
|
2013-07-03 06:58:28 +04:00
|
|
|
// generate/attach previews...
|
2013-07-03 06:42:14 +04:00
|
|
|
makeImagesPreviewsQ(DATA.order)
|
|
|
|
|
.done(function(){
|
|
|
|
|
showStatusQ('Previews: processing done.')
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
2013-07-08 04:11:04 +04:00
|
|
|
*/
|
2013-06-21 20:02:54 +04:00
|
|
|
})
|
|
|
|
|
.fail(function(){
|
|
|
|
|
showStatusQ('Open: canceled.')
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-06-22 17:54:15 +04:00
|
|
|
function sortImagesDialog(message){
|
2013-06-22 19:30:56 +04:00
|
|
|
|
2013-06-22 17:54:15 +04:00
|
|
|
updateStatus('Sort...').show()
|
|
|
|
|
|
|
|
|
|
message = message == null ? 'Sort images by:' : message
|
2013-06-22 19:30:56 +04:00
|
|
|
|
2013-06-22 17:54:15 +04:00
|
|
|
cfg = {}
|
|
|
|
|
cfg[message] = [
|
|
|
|
|
'Date (ascending)',
|
|
|
|
|
'Name (ascending)',
|
|
|
|
|
'Date (decending)',
|
2013-06-22 19:30:56 +04:00
|
|
|
'Name (decending)'
|
2013-06-22 17:54:15 +04:00
|
|
|
]
|
|
|
|
|
|
|
|
|
|
formDialog(null, '',
|
|
|
|
|
cfg,
|
|
|
|
|
'OK',
|
|
|
|
|
'sortImagesDialog')
|
|
|
|
|
.done(function(res){
|
|
|
|
|
res = res[message]
|
|
|
|
|
|
|
|
|
|
if(/Date/.test(res)){
|
|
|
|
|
var method = sortImagesByDate
|
|
|
|
|
} else {
|
|
|
|
|
var method = sortImagesByName
|
|
|
|
|
}
|
|
|
|
|
if(/\(ascending\)/.test(res)){
|
|
|
|
|
var reverse = null
|
|
|
|
|
} else {
|
|
|
|
|
var reverse = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
showStatusQ('Sorting by: '+res+'...')
|
|
|
|
|
|
|
|
|
|
method(reverse)
|
|
|
|
|
})
|
|
|
|
|
.fail(function(){
|
|
|
|
|
showStatusQ('Sort: canceled.')
|
|
|
|
|
})
|
|
|
|
|
}
|
2013-06-13 01:37:30 +04:00
|
|
|
|
2013-06-11 03:10:01 +04:00
|
|
|
|
|
|
|
|
function showImageInfo(){
|
|
|
|
|
var gid = getImageGID(getImage())
|
|
|
|
|
var r = getRibbonIndex(getRibbon())
|
|
|
|
|
var data = IMAGES[gid]
|
|
|
|
|
var orientation = data.orientation
|
|
|
|
|
orientation = orientation == null ? 0 : orientation
|
|
|
|
|
var flipped = data.flipped
|
|
|
|
|
flipped = flipped == null ? '' : ', flipped '+flipped+'ly'
|
|
|
|
|
var order = DATA.order.indexOf(gid)
|
|
|
|
|
var name = data.path.split('/').pop()
|
|
|
|
|
|
|
|
|
|
alert('<div>'+
|
|
|
|
|
'<h2>"'+ name +'"</h2>'+
|
|
|
|
|
|
|
|
|
|
'<table>'+
|
|
|
|
|
'<tr><td>GID: </td><td>'+ gid +'</td></tr>'+
|
|
|
|
|
'<tr><td>Path: </td><td>"'+ data.path +'"</td></tr>'+
|
|
|
|
|
'<tr><td>Orientation: </td><td>'+ orientation +'°'+flipped+'</td></tr>'+
|
|
|
|
|
'<tr><td>Order: </td><td>'+ order +'</td></tr>'+
|
|
|
|
|
'<tr><td>Position (ribbon): </td><td>'+ (DATA.ribbons[r].indexOf(gid)+1) +
|
|
|
|
|
'/'+ DATA.ribbons[r].length +'</td></tr>'+
|
|
|
|
|
'<tr><td>Position (global): </td><td>'+ (order+1) +'/'+ DATA.order.length +'</td></tr>'+
|
|
|
|
|
'</table>'+
|
|
|
|
|
'</div>')
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-10 19:20:35 +04:00
|
|
|
|
2013-06-11 03:10:01 +04:00
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
|
* vim:set ts=4 sw=4 nowrap : */
|