/********************************************************************** * * * **********************************************************************/ //var DEBUG = DEBUG != null ? DEBUG : true var SLIDESHOW_INTERVAL = 3000 var SLIDESHOW_LOOP = true var SLIDESHOW_DIRECTION = 'next' /********************************************************************** * Utils... */ // NOTE: this expects a certain structure, this it is not generic... //function makeDrawerToggler(contentRenderer, root, element_class, mode_class){ function makeDrawerToggler(contentRenderer, root){ var element_class = '.drawer-block' var toggler = createCSSClassToggler( root, 'drawer-mode overlay', function(action){ // XXX var body = $(document.body) var win = $(window) // on... if(action == 'on'){ // remove helo when we scroll to the top... var scroll_handler = function(){ if(body.scrollTop() <= 0){ toggler('off') } } // prepare and cleanup... $(element_class).remove() showInOverlay($(root)) // build the help... var doc = contentRenderer() .addClass(element_class.replace('.', ' ')) .on('click', function(){ event.stopImmediatePropagation() return false }) .css({ cursor: 'auto', }) // XXX depends on body... .appendTo(body) // add exit by click... // XXX depends on body... body .one('click', function(){ toggler('off') }) .css({ cursor: 'hand', }) // scroll to the help... // NOTE: need to set the scroll handler AFTER we // scroll down, or it will be more of a // tease than a help... var t = getRelativeVisualPosition($(root), doc).top body .animate({ scrollTop: Math.abs(t) - 40, }, function(){ // XXX depends on window... win .on('scroll', scroll_handler) }) // off... } else { // things to cleanup... var _cleanup = function(){ $(element_class).remove() hideOverlay($(root)) // XXX depends on body... body.click() win.off('scroll', scroll_handler) } // animate things if we are not at the top... if(body.scrollTop() > 0){ // XXX depends on body... body .css({ cursor: '', }) .animate({ scrollTop: 0, }, _cleanup) // if we are at the top do things fast... } else { _cleanup() } } }) return toggler } /********************************************************************** * Modes */ // XXX make this save and restore settings... var toggleSingleImageMode = createCSSClassToggler( '.viewer', 'single-image-mode', function(action){ // prevent reentering... if(action == toggleSingleImageMode('?')){ return false } }, function(action){ var w = getScreenWidthInImages() // single image mode... if(action == 'on'){ TRANSITION_MODE_DEFAULT = 'css' // save things... SETTINGS['ribbon-mode-screen-images'] = w SETTINGS['ribbon-mode-image-info'] = toggleImageInfo('?') // load things... w = SETTINGS['single-image-mode-screen-images'] w = w == null ? 1 : w var p = SETTINGS['single-image-mode-proportions'] p = p == null ? 'square' : p // set stuff... toggleImageProportions(p) fitNImages(w) toggleImageInfo('off') // ribbon mode... } else { TRANSITION_MODE_DEFAULT = 'animate' // save things... SETTINGS['single-image-mode-screen-images'] = w SETTINGS['single-image-mode-proportions'] = toggleImageProportions('?') // load things... w = SETTINGS['ribbon-mode-screen-images'] w = w == null ? DEFAULT_SCREEN_IMAGES : w toggleImageProportions('none') fitNImages(w) var i = SETTINGS['ribbon-mode-image-info'] == 'on' ? 'on' : 'off' toggleImageInfo(i) SETTINGS['ribbon-mode-image-info'] = i centerRibbons() } }) // XXX make this not conflict with marked-only-mode, better yet, make them // one single mode... // XXX is this a mode??? var toggleSingleRibbonMode = makeCropModeToggler( 'single-ribbon-mode', function(){ cropDataTo(DATA.ribbons[getRibbonIndex()].slice()) }) // TODO transitions... // TODO a real setup UI (instead of prompt) var toggleSlideShowMode = createCSSClassToggler( '.viewer', '.slideshow-mode', function(action){ if(action == 'on'){ updateStatus('Slideshow...').show() // interval from user... //var interval = prompt('Slideshow interval (sec):', SLIDESHOW_INTERVAL/1000) formDialog($('.viewer'), 'Slideshow', { 'Interval': (SLIDESHOW_INTERVAL/1000) + 'sec', 'Looping': SLIDESHOW_LOOP ? true : false, 'Reverse direction': SLIDESHOW_DIRECTION == 'prev' ? true : false }, 'Start') .done(function(data){ var looping = data['Looping'] var reverse = data['Reverse direction'] SLIDESHOW_LOOP = looping SLIDESHOW_DIRECTION = reverse == true ? 'prev' : 'next' // parse interval... var interval_raw = data['Interval'] // units... var M = 1000 if(/ms|msec|milsec|millisecond[s]/i.test(interval_raw)){ M = 1 } else if(/(s|sec|second[s])/i.test(interval_raw)){ M = 1000 } else if(/m|min|minute[s]/i.test(interval_raw)){ M = 1000*60 } // fractions... if(/[0-9]+\/[0-9]+/.test(interval_raw)){ var parts = interval_raw.split('/') var interval = parseFloat(parts[0]) / parseFloat(parts[1]) } else { var interval = parseFloat(interval_raw) } SLIDESHOW_INTERVAL = isNaN(interval) ? 3000 : interval*M console.log('>>>', data, interval) showStatus('Slideshow: starting:', SLIDESHOW_INTERVAL/1000 +'sec,', SLIDESHOW_LOOP ? 'looped...' : 'unlooped...') // XXX is this the correct way to go??? hideOverlay($('.viewer')) toggleSingleImageMode('on') _slideshow_timer = setInterval(function(){ var cur = getImage() // advance the image... var next = SLIDESHOW_DIRECTION == 'next' ? nextImage() : prevImage() // handle slideshow end... if(getImageGID(cur) == getImageGID(next)){ if(SLIDESHOW_LOOP){ SLIDESHOW_DIRECTION == 'next' ? firstImage() : lastImage() } else { toggleSlideShowMode('off') return } } // center and trigger load events... centerRibbon() }, SLIDESHOW_INTERVAL) }) // user cancelled... .fail(function(){ toggleSlideShowMode('off') }) } else { window._slideshow_timer != null && clearInterval(_slideshow_timer) showStatus('Slideshow: canceled.') hideOverlay($('.viewer')) } }) var toggleTheme = createCSSClassToggler( '.viewer', [ 'gray', 'dark', 'light' ], // XXX does this get called for default state (gray)??? function(action){ SETTINGS['global-theme'] = action }) var toggleImageInfo = createCSSClassToggler( '.viewer', '.image-info-visible', function(action){ if(toggleSingleImageMode('?') == 'off'){ SETTINGS['ribbon-mode-image-info'] = action } }) var toggleInlineImageInfo = createCSSClassToggler( '.viewer', '.image-info-inline-visible', function(action){ if(action == 'on'){ $(document) .on('mouseover', inlineImageInfoHoverHandler) } else { $(document) .off('mouseover', inlineImageInfoHoverHandler) $('.inline-image-info').remove() } }) var toggleImageProportions = createCSSClassToggler( '.viewer', [ 'none', 'fit-viewer' ], function(action){ // prevent reentering... if(action == toggleImageProportions('?')){ return false } }, function(action){ var image = $('.image') var h = image.outerHeight(true) var w = image.outerWidth(true) // viewer proportions... // XXX going into here twice for a rotated 90/270 image will // set it back to square... // ...can't even begin to imagine what can affect this! if(action == 'fit-viewer'){ var viewer = $('.viewer') var W = viewer.innerWidth() var H = viewer.innerHeight() if(W > H){ image.css('width', W * h/H) } else { image.css('height', H * w/W) } // account for rotation... correctImageProportionsForRotation(image) centerView(null, 'css') // square proportions... } else { var size = Math.min(w, h) image.css({ width: size, height: size }) // account for rotation... correctImageProportionsForRotation(image) centerView(null, 'css') } }) var toggleHelp = makeDrawerToggler( function(){ // XXX populate... // ...load from file. return $('