/********************************************************************** * * Ribbon Crop API * * **********************************************************************/ var CROP_STACK = [] var CROP_MODES = [] /******************************************************* Crop Data ***/ function isViewCropped(){ return CROP_STACK.length != 0 } function getAllData(){ if(!isViewCropped()){ return DATA } else { return CROP_STACK[0] } } // NOTE: this will not update .current state... // NOTE: when keep_ribbons is set, this may generate empty ribbons... // // XXX should this set the .current to anything but null or the first elem??? function makeCroppedData(gids, keep_ribbons){ var res = { varsion: '2.0', current: null, ribbons: [], order: DATA.order.slice(), } // flat single ribbon crop... if(!keep_ribbons){ res.ribbons[0] = gids // keep the ribbon structure... } else { $.each(DATA.ribbons, function(_, e){ e = e.filter(function(ee){ return gids.indexOf(ee) >= 0 }) // skip empty ribbons... if(e.length != 0){ res.ribbons.push(e) } }) } return res } // NOTE: if keep_ribbons is not set this will ALWAYS build a single ribbon // data-set... function cropDataTo(gids, keep_ribbons){ var prev_state = DATA var cur = DATA.current var r = getRibbonIndex() var new_data = makeCroppedData(gids, keep_ribbons) // do nothing if there is no change... // XXX is there a better way to compare states??? if(JSON.stringify(DATA.ribbons) == JSON.stringify(new_data.ribbons)){ return DATA } CROP_STACK.push(prev_state) DATA = new_data cur = getGIDBefore(cur, keep_ribbons ? r : 0) cur = cur == null ? gids[0] : cur DATA.current = cur reloadViewer() updateImages() return prev_state } function uncropData(){ if(!isViewCropped()){ return DATA } var prev_state = DATA var cur = DATA.current DATA = CROP_STACK.pop() // check if cur exists in data being loaded... if($.map(DATA.ribbons, function(e, i){ return e.indexOf(cur) >= 0 }).indexOf(true) >= 0){ // keep the current position... DATA.current = cur } reloadViewer() updateImages() return prev_state } function showAllData(){ var prev_state = DATA var cur = DATA.current if(CROP_STACK.length != 0){ DATA = getAllData() CROP_STACK = [] // XXX do we need to check if this exists??? // ...in theory, as long as there are no global destructive // operations, no. // keep the current position... DATA.current = cur reloadViewer() updateImages() } return prev_state } // Helpers for making crop modes and using crop... // Make a generic crop mode toggler // // NOTE: This will add the toggler to CROP_MODES, for use by // uncropLastState(...) // NOTE: crop modes are exclusive -- it is not possible to enter one crop // mode from a different crop mode function makeCropModeToggler(cls, crop){ var res = createCSSClassToggler( '.viewer', //cls + ' cropped-mode', cls, function(action){ // prevent mixing marked-only and single-ribbon modes... if(action == 'on' && isViewCropped() && res('?') != 'on'){ return false } }, function(action){ if(action == 'on'){ showStatusQ('Cropping current ribbon...') crop() } else { showStatusQ('Uncropping to all data...') showAllData() } }) CROP_MODES.push(res) return res } // Uncrop to last state and there is no states to uncrop then exit // cropped mode. // // NOTE: this will exit all crop modes when uncropping the last step. function uncropLastState(){ // do nothing if we aren't in a crop mode... if(!isViewCropped()){ return } // exit cropped all modes... if(CROP_STACK.length == 1){ $.each(CROP_MODES, function(_, e){ e('off') }) // ucrop one state... } else { showStatusQ('Uncropping...') uncropData() } } /********************************************************************** * vim:set ts=4 sw=4 : */